Search
lxdream.org :: lxdream/src/xlat/disasm/i386-dis.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/disasm/i386-dis.c
changeset 1264:74ad81710528
prev1263:b3de98d19faf
next1298:d0eb2307b847
author nkeynes
date Tue Mar 06 12:42:33 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Merge ARM disassembler from binutils 2.22
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/xlat/disasm/i386-dis.c Tue Mar 06 12:42:33 2012 +1000
1.3 @@ -0,0 +1,4379 @@
1.4 +/* Print i386 instructions for GDB, the GNU debugger.
1.5 + Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
1.6 + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
1.7 +
1.8 + This file is part of GDB.
1.9 +
1.10 + This program is free software; you can redistribute it and/or modify
1.11 + it under the terms of the GNU General Public License as published by
1.12 + the Free Software Foundation; either version 2 of the License, or
1.13 + (at your option) any later version.
1.14 +
1.15 + This program is distributed in the hope that it will be useful,
1.16 + but WITHOUT ANY WARRANTY; without even the implied warranty of
1.17 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.18 + GNU General Public License for more details.
1.19 +
1.20 + You should have received a copy of the GNU General Public License
1.21 + along with this program; if not, write to the Free Software
1.22 + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
1.23 +
1.24 +/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
1.25 + July 1988
1.26 + modified by John Hassey (hassey@dg-rtp.dg.com)
1.27 + x86-64 support added by Jan Hubicka (jh@suse.cz)
1.28 + VIA PadLock support by Michal Ludvig (mludvig@suse.cz). */
1.29 +
1.30 +/* The main tables describing the instructions is essentially a copy
1.31 + of the "Opcode Map" chapter (Appendix A) of the Intel 80386
1.32 + Programmers Manual. Usually, there is a capital letter, followed
1.33 + by a small letter. The capital letter tell the addressing mode,
1.34 + and the small letter tells about the operand size. Refer to
1.35 + the Intel manual for details. */
1.36 +
1.37 +#include "xlat/disasm/dis-asm.h"
1.38 +#include "xlat/disasm/sysdep.h"
1.39 +#include "xlat/xlatdasm.h"
1.40 +#include "gettext.h"
1.41 +
1.42 +#define MAXLEN 20
1.43 +
1.44 +#include <setjmp.h>
1.45 +
1.46 +#ifndef UNIXWARE_COMPAT
1.47 +/* Set non-zero for broken, compatible instructions. Set to zero for
1.48 + non-broken opcodes. */
1.49 +#define UNIXWARE_COMPAT 1
1.50 +#endif
1.51 +
1.52 +static int fetch_data (struct disassemble_info *, bfd_byte *);
1.53 +static void ckprefix (void);
1.54 +static const char *prefix_name (int, int);
1.55 +static int print_insn (bfd_vma, disassemble_info *);
1.56 +static void dofloat (int);
1.57 +static void OP_ST (int, int);
1.58 +static void OP_STi (int, int);
1.59 +static int putop (const char *, int);
1.60 +static void oappend (const char *);
1.61 +static void append_seg (void);
1.62 +static void OP_indirE (int, int);
1.63 +static void OP_E (int, int);
1.64 +static void OP_G (int, int);
1.65 +static bfd_vma get64 (void);
1.66 +static bfd_signed_vma get32 (void);
1.67 +static bfd_signed_vma get32s (void);
1.68 +static int get16 (void);
1.69 +static void set_op (bfd_vma, int);
1.70 +static void OP_REG (int, int);
1.71 +static void OP_IMREG (int, int);
1.72 +static void OP_I (int, int);
1.73 +static void OP_I64 (int, int);
1.74 +static void OP_sI (int, int);
1.75 +static void OP_J (int, int);
1.76 +static void OP_SEG (int, int);
1.77 +static void OP_DIR (int, int);
1.78 +static void OP_OFF (int, int);
1.79 +static void OP_OFF64 (int, int);
1.80 +static void ptr_reg (int, int);
1.81 +static void OP_ESreg (int, int);
1.82 +static void OP_DSreg (int, int);
1.83 +static void OP_C (int, int);
1.84 +static void OP_D (int, int);
1.85 +static void OP_T (int, int);
1.86 +static void OP_Rd (int, int);
1.87 +static void OP_MMX (int, int);
1.88 +static void OP_XMM (int, int);
1.89 +static void OP_EM (int, int);
1.90 +static void OP_EX (int, int);
1.91 +static void OP_MS (int, int);
1.92 +static void OP_XS (int, int);
1.93 +static void OP_M (int, int);
1.94 +static void OP_0fae (int, int);
1.95 +static void OP_0f07 (int, int);
1.96 +static void NOP_Fixup (int, int);
1.97 +static void OP_3DNowSuffix (int, int);
1.98 +static void OP_SIMD_Suffix (int, int);
1.99 +static void SIMD_Fixup (int, int);
1.100 +static void PNI_Fixup (int, int);
1.101 +static void INVLPG_Fixup (int, int);
1.102 +static void BadOp (void);
1.103 +
1.104 +struct dis_private {
1.105 + /* Points to first byte not fetched. */
1.106 + bfd_byte *max_fetched;
1.107 + bfd_byte the_buffer[MAXLEN];
1.108 + bfd_vma insn_start;
1.109 + int orig_sizeflag;
1.110 + jmp_buf bailout;
1.111 +};
1.112 +
1.113 +/* The opcode for the fwait instruction, which we treat as a prefix
1.114 + when we can. */
1.115 +#define FWAIT_OPCODE (0x9b)
1.116 +
1.117 +/* Set to 1 for 64bit mode disassembly. */
1.118 +static int mode_64bit;
1.119 +
1.120 +/* Flags for the prefixes for the current instruction. See below. */
1.121 +static int prefixes;
1.122 +
1.123 +/* REX prefix the current instruction. See below. */
1.124 +static int rex;
1.125 +/* Bits of REX we've already used. */
1.126 +static int rex_used;
1.127 +#define REX_MODE64 8
1.128 +#define REX_EXTX 4
1.129 +#define REX_EXTY 2
1.130 +#define REX_EXTZ 1
1.131 +/* Mark parts used in the REX prefix. When we are testing for
1.132 + empty prefix (for 8bit register REX extension), just mask it
1.133 + out. Otherwise test for REX bit is excuse for existence of REX
1.134 + only in case value is nonzero. */
1.135 +#define USED_REX(value) \
1.136 + { \
1.137 + if (value) \
1.138 + rex_used |= (rex & value) ? (value) | 0x40 : 0; \
1.139 + else \
1.140 + rex_used |= 0x40; \
1.141 + }
1.142 +
1.143 +/* Flags for prefixes which we somehow handled when printing the
1.144 + current instruction. */
1.145 +static int used_prefixes;
1.146 +
1.147 +/* Flags stored in PREFIXES. */
1.148 +#define PREFIX_REPZ 1
1.149 +#define PREFIX_REPNZ 2
1.150 +#define PREFIX_LOCK 4
1.151 +#define PREFIX_CS 8
1.152 +#define PREFIX_SS 0x10
1.153 +#define PREFIX_DS 0x20
1.154 +#define PREFIX_ES 0x40
1.155 +#define PREFIX_FS 0x80
1.156 +#define PREFIX_GS 0x100
1.157 +#define PREFIX_DATA 0x200
1.158 +#define PREFIX_ADDR 0x400
1.159 +#define PREFIX_FWAIT 0x800
1.160 +
1.161 +/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
1.162 + to ADDR (exclusive) are valid. Returns 1 for success, longjmps
1.163 + on error. */
1.164 +#define FETCH_DATA(info, addr) \
1.165 + ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
1.166 + ? 1 : fetch_data ((info), (addr)))
1.167 +
1.168 +static int
1.169 +fetch_data (struct disassemble_info *info, bfd_byte *addr)
1.170 +{
1.171 + int status;
1.172 + struct dis_private *priv = (struct dis_private *) info->private_data;
1.173 + bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
1.174 +
1.175 + status = (*info->read_memory_func) (start,
1.176 + priv->max_fetched,
1.177 + addr - priv->max_fetched,
1.178 + info);
1.179 + if (status != 0)
1.180 + {
1.181 + /* If we did manage to read at least one byte, then
1.182 + print_insn_i386 will do something sensible. Otherwise, print
1.183 + an error. We do that here because this is where we know
1.184 + STATUS. */
1.185 + if (priv->max_fetched == priv->the_buffer)
1.186 + (*info->memory_error_func) (status, start, info);
1.187 + longjmp (priv->bailout, 1);
1.188 + }
1.189 + else
1.190 + priv->max_fetched = addr;
1.191 + return 1;
1.192 +}
1.193 +
1.194 +#define XX NULL, 0
1.195 +
1.196 +#define Eb OP_E, b_mode
1.197 +#define Ev OP_E, v_mode
1.198 +#define Ed OP_E, d_mode
1.199 +#define Eq OP_E, q_mode
1.200 +#define Edq OP_E, dq_mode
1.201 +#define Edqw OP_E, dqw_mode
1.202 +#define indirEv OP_indirE, v_mode
1.203 +#define indirEp OP_indirE, f_mode
1.204 +#define Ew OP_E, w_mode
1.205 +#define Ma OP_E, v_mode
1.206 +#define M OP_M, 0 /* lea, lgdt, etc. */
1.207 +#define Mp OP_M, f_mode /* 32 or 48 bit memory operand for LDS, LES etc */
1.208 +#define Gb OP_G, b_mode
1.209 +#define Gv OP_G, v_mode
1.210 +#define Gd OP_G, d_mode
1.211 +#define Gdq OP_G, dq_mode
1.212 +#define Gw OP_G, w_mode
1.213 +#define Rd OP_Rd, d_mode
1.214 +#define Rm OP_Rd, m_mode
1.215 +#define Ib OP_I, b_mode
1.216 +#define sIb OP_sI, b_mode /* sign extened byte */
1.217 +#define Iv OP_I, v_mode
1.218 +#define Iq OP_I, q_mode
1.219 +#define Iv64 OP_I64, v_mode
1.220 +#define Iw OP_I, w_mode
1.221 +#define I1 OP_I, const_1_mode
1.222 +#define Jb OP_J, b_mode
1.223 +#define Jv OP_J, v_mode
1.224 +#define Cm OP_C, m_mode
1.225 +#define Dm OP_D, m_mode
1.226 +#define Td OP_T, d_mode
1.227 +
1.228 +#define RMeAX OP_REG, eAX_reg
1.229 +#define RMeBX OP_REG, eBX_reg
1.230 +#define RMeCX OP_REG, eCX_reg
1.231 +#define RMeDX OP_REG, eDX_reg
1.232 +#define RMeSP OP_REG, eSP_reg
1.233 +#define RMeBP OP_REG, eBP_reg
1.234 +#define RMeSI OP_REG, eSI_reg
1.235 +#define RMeDI OP_REG, eDI_reg
1.236 +#define RMrAX OP_REG, rAX_reg
1.237 +#define RMrBX OP_REG, rBX_reg
1.238 +#define RMrCX OP_REG, rCX_reg
1.239 +#define RMrDX OP_REG, rDX_reg
1.240 +#define RMrSP OP_REG, rSP_reg
1.241 +#define RMrBP OP_REG, rBP_reg
1.242 +#define RMrSI OP_REG, rSI_reg
1.243 +#define RMrDI OP_REG, rDI_reg
1.244 +#define RMAL OP_REG, al_reg
1.245 +#define RMAL OP_REG, al_reg
1.246 +#define RMCL OP_REG, cl_reg
1.247 +#define RMDL OP_REG, dl_reg
1.248 +#define RMBL OP_REG, bl_reg
1.249 +#define RMAH OP_REG, ah_reg
1.250 +#define RMCH OP_REG, ch_reg
1.251 +#define RMDH OP_REG, dh_reg
1.252 +#define RMBH OP_REG, bh_reg
1.253 +#define RMAX OP_REG, ax_reg
1.254 +#define RMDX OP_REG, dx_reg
1.255 +
1.256 +#define eAX OP_IMREG, eAX_reg
1.257 +#define eBX OP_IMREG, eBX_reg
1.258 +#define eCX OP_IMREG, eCX_reg
1.259 +#define eDX OP_IMREG, eDX_reg
1.260 +#define eSP OP_IMREG, eSP_reg
1.261 +#define eBP OP_IMREG, eBP_reg
1.262 +#define eSI OP_IMREG, eSI_reg
1.263 +#define eDI OP_IMREG, eDI_reg
1.264 +#define AL OP_IMREG, al_reg
1.265 +#define AL OP_IMREG, al_reg
1.266 +#define CL OP_IMREG, cl_reg
1.267 +#define DL OP_IMREG, dl_reg
1.268 +#define BL OP_IMREG, bl_reg
1.269 +#define AH OP_IMREG, ah_reg
1.270 +#define CH OP_IMREG, ch_reg
1.271 +#define DH OP_IMREG, dh_reg
1.272 +#define BH OP_IMREG, bh_reg
1.273 +#define AX OP_IMREG, ax_reg
1.274 +#define DX OP_IMREG, dx_reg
1.275 +#define indirDX OP_IMREG, indir_dx_reg
1.276 +
1.277 +#define Sw OP_SEG, w_mode
1.278 +#define Ap OP_DIR, 0
1.279 +#define Ob OP_OFF, b_mode
1.280 +#define Ob64 OP_OFF64, b_mode
1.281 +#define Ov OP_OFF, v_mode
1.282 +#define Ov64 OP_OFF64, v_mode
1.283 +#define Xb OP_DSreg, eSI_reg
1.284 +#define Xv OP_DSreg, eSI_reg
1.285 +#define Yb OP_ESreg, eDI_reg
1.286 +#define Yv OP_ESreg, eDI_reg
1.287 +#define DSBX OP_DSreg, eBX_reg
1.288 +
1.289 +#define es OP_REG, es_reg
1.290 +#define ss OP_REG, ss_reg
1.291 +#define cs OP_REG, cs_reg
1.292 +#define ds OP_REG, ds_reg
1.293 +#define fs OP_REG, fs_reg
1.294 +#define gs OP_REG, gs_reg
1.295 +
1.296 +#define MX OP_MMX, 0
1.297 +#define XM OP_XMM, 0
1.298 +#define EM OP_EM, v_mode
1.299 +#define EX OP_EX, v_mode
1.300 +#define MS OP_MS, v_mode
1.301 +#define XS OP_XS, v_mode
1.302 +#define OPSUF OP_3DNowSuffix, 0
1.303 +#define OPSIMD OP_SIMD_Suffix, 0
1.304 +
1.305 +#define cond_jump_flag NULL, cond_jump_mode
1.306 +#define loop_jcxz_flag NULL, loop_jcxz_mode
1.307 +
1.308 +/* bits in sizeflag */
1.309 +#define SUFFIX_ALWAYS 4
1.310 +#define AFLAG 2
1.311 +#define DFLAG 1
1.312 +
1.313 +#define b_mode 1 /* byte operand */
1.314 +#define v_mode 2 /* operand size depends on prefixes */
1.315 +#define w_mode 3 /* word operand */
1.316 +#define d_mode 4 /* double word operand */
1.317 +#define q_mode 5 /* quad word operand */
1.318 +#define t_mode 6 /* ten-byte operand */
1.319 +#define x_mode 7 /* 16-byte XMM operand */
1.320 +#define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */
1.321 +#define cond_jump_mode 9
1.322 +#define loop_jcxz_mode 10
1.323 +#define dq_mode 11 /* operand size depends on REX prefixes. */
1.324 +#define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */
1.325 +#define f_mode 13 /* 4- or 6-byte pointer operand */
1.326 +#define const_1_mode 14
1.327 +
1.328 +#define es_reg 100
1.329 +#define cs_reg 101
1.330 +#define ss_reg 102
1.331 +#define ds_reg 103
1.332 +#define fs_reg 104
1.333 +#define gs_reg 105
1.334 +
1.335 +#define eAX_reg 108
1.336 +#define eCX_reg 109
1.337 +#define eDX_reg 110
1.338 +#define eBX_reg 111
1.339 +#define eSP_reg 112
1.340 +#define eBP_reg 113
1.341 +#define eSI_reg 114
1.342 +#define eDI_reg 115
1.343 +
1.344 +#define al_reg 116
1.345 +#define cl_reg 117
1.346 +#define dl_reg 118
1.347 +#define bl_reg 119
1.348 +#define ah_reg 120
1.349 +#define ch_reg 121
1.350 +#define dh_reg 122
1.351 +#define bh_reg 123
1.352 +
1.353 +#define ax_reg 124
1.354 +#define cx_reg 125
1.355 +#define dx_reg 126
1.356 +#define bx_reg 127
1.357 +#define sp_reg 128
1.358 +#define bp_reg 129
1.359 +#define si_reg 130
1.360 +#define di_reg 131
1.361 +
1.362 +#define rAX_reg 132
1.363 +#define rCX_reg 133
1.364 +#define rDX_reg 134
1.365 +#define rBX_reg 135
1.366 +#define rSP_reg 136
1.367 +#define rBP_reg 137
1.368 +#define rSI_reg 138
1.369 +#define rDI_reg 139
1.370 +
1.371 +#define indir_dx_reg 150
1.372 +
1.373 +#define FLOATCODE 1
1.374 +#define USE_GROUPS 2
1.375 +#define USE_PREFIX_USER_TABLE 3
1.376 +#define X86_64_SPECIAL 4
1.377 +
1.378 +#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0
1.379 +
1.380 +#define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0
1.381 +#define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0
1.382 +#define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0
1.383 +#define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0
1.384 +#define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0
1.385 +#define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0
1.386 +#define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0
1.387 +#define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0
1.388 +#define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0
1.389 +#define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0
1.390 +#define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0
1.391 +#define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0
1.392 +#define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0
1.393 +#define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0
1.394 +#define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0
1.395 +#define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0
1.396 +#define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0
1.397 +#define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0
1.398 +#define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0
1.399 +#define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0
1.400 +#define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0
1.401 +#define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0
1.402 +#define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0
1.403 +#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0
1.404 +#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0
1.405 +
1.406 +#define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0
1.407 +#define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0
1.408 +#define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0
1.409 +#define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0
1.410 +#define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0
1.411 +#define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0
1.412 +#define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0
1.413 +#define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0
1.414 +#define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0
1.415 +#define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0
1.416 +#define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0
1.417 +#define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0
1.418 +#define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0
1.419 +#define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0
1.420 +#define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0
1.421 +#define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0
1.422 +#define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0
1.423 +#define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0
1.424 +#define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0
1.425 +#define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0
1.426 +#define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0
1.427 +#define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0
1.428 +#define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0
1.429 +#define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0
1.430 +#define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0
1.431 +#define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0
1.432 +#define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0
1.433 +#define PREGRP27 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0
1.434 +#define PREGRP28 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0
1.435 +#define PREGRP29 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0
1.436 +#define PREGRP30 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0
1.437 +#define PREGRP31 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0
1.438 +#define PREGRP32 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0
1.439 +
1.440 +#define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0
1.441 +
1.442 +typedef void (*op_rtn) (int bytemode, int sizeflag);
1.443 +
1.444 +struct dis386 {
1.445 + const char *name;
1.446 + op_rtn op1;
1.447 + int bytemode1;
1.448 + op_rtn op2;
1.449 + int bytemode2;
1.450 + op_rtn op3;
1.451 + int bytemode3;
1.452 +};
1.453 +
1.454 +/* Upper case letters in the instruction names here are macros.
1.455 + 'A' => print 'b' if no register operands or suffix_always is true
1.456 + 'B' => print 'b' if suffix_always is true
1.457 + 'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand
1.458 + . size prefix
1.459 + 'E' => print 'e' if 32-bit form of jcxz
1.460 + 'F' => print 'w' or 'l' depending on address size prefix (loop insns)
1.461 + 'H' => print ",pt" or ",pn" branch hint
1.462 + 'I' => honor following macro letter even in Intel mode (implemented only
1.463 + . for some of the macro letters)
1.464 + 'J' => print 'l'
1.465 + 'L' => print 'l' if suffix_always is true
1.466 + 'N' => print 'n' if instruction has no wait "prefix"
1.467 + 'O' => print 'd', or 'o'
1.468 + 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix,
1.469 + . or suffix_always is true. print 'q' if rex prefix is present.
1.470 + 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always
1.471 + . is true
1.472 + 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode)
1.473 + 'S' => print 'w', 'l' or 'q' if suffix_always is true
1.474 + 'T' => print 'q' in 64bit mode and behave as 'P' otherwise
1.475 + 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise
1.476 + 'W' => print 'b' or 'w' ("w" or "de" in intel mode)
1.477 + 'X' => print 's', 'd' depending on data16 prefix (for XMM)
1.478 + 'Y' => 'q' if instruction has an REX 64bit overwrite prefix
1.479 +
1.480 + Many of the above letters print nothing in Intel mode. See "putop"
1.481 + for the details.
1.482 +
1.483 + Braces '{' and '}', and vertical bars '|', indicate alternative
1.484 + mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel
1.485 + modes. In cases where there are only two alternatives, the X86_64
1.486 + instruction is reserved, and "(bad)" is printed.
1.487 +*/
1.488 +
1.489 +static const struct dis386 dis386[] = {
1.490 + /* 00 */
1.491 + { "addB", Eb, Gb, XX },
1.492 + { "addS", Ev, Gv, XX },
1.493 + { "addB", Gb, Eb, XX },
1.494 + { "addS", Gv, Ev, XX },
1.495 + { "addB", AL, Ib, XX },
1.496 + { "addS", eAX, Iv, XX },
1.497 + { "push{T|}", es, XX, XX },
1.498 + { "pop{T|}", es, XX, XX },
1.499 + /* 08 */
1.500 + { "orB", Eb, Gb, XX },
1.501 + { "orS", Ev, Gv, XX },
1.502 + { "orB", Gb, Eb, XX },
1.503 + { "orS", Gv, Ev, XX },
1.504 + { "orB", AL, Ib, XX },
1.505 + { "orS", eAX, Iv, XX },
1.506 + { "push{T|}", cs, XX, XX },
1.507 + { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */
1.508 + /* 10 */
1.509 + { "adcB", Eb, Gb, XX },
1.510 + { "adcS", Ev, Gv, XX },
1.511 + { "adcB", Gb, Eb, XX },
1.512 + { "adcS", Gv, Ev, XX },
1.513 + { "adcB", AL, Ib, XX },
1.514 + { "adcS", eAX, Iv, XX },
1.515 + { "push{T|}", ss, XX, XX },
1.516 + { "popT|}", ss, XX, XX },
1.517 + /* 18 */
1.518 + { "sbbB", Eb, Gb, XX },
1.519 + { "sbbS", Ev, Gv, XX },
1.520 + { "sbbB", Gb, Eb, XX },
1.521 + { "sbbS", Gv, Ev, XX },
1.522 + { "sbbB", AL, Ib, XX },
1.523 + { "sbbS", eAX, Iv, XX },
1.524 + { "push{T|}", ds, XX, XX },
1.525 + { "pop{T|}", ds, XX, XX },
1.526 + /* 20 */
1.527 + { "andB", Eb, Gb, XX },
1.528 + { "andS", Ev, Gv, XX },
1.529 + { "andB", Gb, Eb, XX },
1.530 + { "andS", Gv, Ev, XX },
1.531 + { "andB", AL, Ib, XX },
1.532 + { "andS", eAX, Iv, XX },
1.533 + { "(bad)", XX, XX, XX }, /* SEG ES prefix */
1.534 + { "daa{|}", XX, XX, XX },
1.535 + /* 28 */
1.536 + { "subB", Eb, Gb, XX },
1.537 + { "subS", Ev, Gv, XX },
1.538 + { "subB", Gb, Eb, XX },
1.539 + { "subS", Gv, Ev, XX },
1.540 + { "subB", AL, Ib, XX },
1.541 + { "subS", eAX, Iv, XX },
1.542 + { "(bad)", XX, XX, XX }, /* SEG CS prefix */
1.543 + { "das{|}", XX, XX, XX },
1.544 + /* 30 */
1.545 + { "xorB", Eb, Gb, XX },
1.546 + { "xorS", Ev, Gv, XX },
1.547 + { "xorB", Gb, Eb, XX },
1.548 + { "xorS", Gv, Ev, XX },
1.549 + { "xorB", AL, Ib, XX },
1.550 + { "xorS", eAX, Iv, XX },
1.551 + { "(bad)", XX, XX, XX }, /* SEG SS prefix */
1.552 + { "aaa{|}", XX, XX, XX },
1.553 + /* 38 */
1.554 + { "cmpB", Eb, Gb, XX },
1.555 + { "cmpS", Ev, Gv, XX },
1.556 + { "cmpB", Gb, Eb, XX },
1.557 + { "cmpS", Gv, Ev, XX },
1.558 + { "cmpB", AL, Ib, XX },
1.559 + { "cmpS", eAX, Iv, XX },
1.560 + { "(bad)", XX, XX, XX }, /* SEG DS prefix */
1.561 + { "aas{|}", XX, XX, XX },
1.562 + /* 40 */
1.563 + { "inc{S|}", RMeAX, XX, XX },
1.564 + { "inc{S|}", RMeCX, XX, XX },
1.565 + { "inc{S|}", RMeDX, XX, XX },
1.566 + { "inc{S|}", RMeBX, XX, XX },
1.567 + { "inc{S|}", RMeSP, XX, XX },
1.568 + { "inc{S|}", RMeBP, XX, XX },
1.569 + { "inc{S|}", RMeSI, XX, XX },
1.570 + { "inc{S|}", RMeDI, XX, XX },
1.571 + /* 48 */
1.572 + { "dec{S|}", RMeAX, XX, XX },
1.573 + { "dec{S|}", RMeCX, XX, XX },
1.574 + { "dec{S|}", RMeDX, XX, XX },
1.575 + { "dec{S|}", RMeBX, XX, XX },
1.576 + { "dec{S|}", RMeSP, XX, XX },
1.577 + { "dec{S|}", RMeBP, XX, XX },
1.578 + { "dec{S|}", RMeSI, XX, XX },
1.579 + { "dec{S|}", RMeDI, XX, XX },
1.580 + /* 50 */
1.581 + { "pushS", RMrAX, XX, XX },
1.582 + { "pushS", RMrCX, XX, XX },
1.583 + { "pushS", RMrDX, XX, XX },
1.584 + { "pushS", RMrBX, XX, XX },
1.585 + { "pushS", RMrSP, XX, XX },
1.586 + { "pushS", RMrBP, XX, XX },
1.587 + { "pushS", RMrSI, XX, XX },
1.588 + { "pushS", RMrDI, XX, XX },
1.589 + /* 58 */
1.590 + { "popS", RMrAX, XX, XX },
1.591 + { "popS", RMrCX, XX, XX },
1.592 + { "popS", RMrDX, XX, XX },
1.593 + { "popS", RMrBX, XX, XX },
1.594 + { "popS", RMrSP, XX, XX },
1.595 + { "popS", RMrBP, XX, XX },
1.596 + { "popS", RMrSI, XX, XX },
1.597 + { "popS", RMrDI, XX, XX },
1.598 + /* 60 */
1.599 + { "pusha{P|}", XX, XX, XX },
1.600 + { "popa{P|}", XX, XX, XX },
1.601 + { "bound{S|}", Gv, Ma, XX },
1.602 + { X86_64_0 },
1.603 + { "(bad)", XX, XX, XX }, /* seg fs */
1.604 + { "(bad)", XX, XX, XX }, /* seg gs */
1.605 + { "(bad)", XX, XX, XX }, /* op size prefix */
1.606 + { "(bad)", XX, XX, XX }, /* adr size prefix */
1.607 + /* 68 */
1.608 + { "pushT", Iq, XX, XX },
1.609 + { "imulS", Gv, Ev, Iv },
1.610 + { "pushT", sIb, XX, XX },
1.611 + { "imulS", Gv, Ev, sIb },
1.612 + { "ins{b||b|}", Yb, indirDX, XX },
1.613 + { "ins{R||R|}", Yv, indirDX, XX },
1.614 + { "outs{b||b|}", indirDX, Xb, XX },
1.615 + { "outs{R||R|}", indirDX, Xv, XX },
1.616 + /* 70 */
1.617 + { "joH", Jb, XX, cond_jump_flag },
1.618 + { "jnoH", Jb, XX, cond_jump_flag },
1.619 + { "jbH", Jb, XX, cond_jump_flag },
1.620 + { "jaeH", Jb, XX, cond_jump_flag },
1.621 + { "jeH", Jb, XX, cond_jump_flag },
1.622 + { "jneH", Jb, XX, cond_jump_flag },
1.623 + { "jbeH", Jb, XX, cond_jump_flag },
1.624 + { "jaH", Jb, XX, cond_jump_flag },
1.625 + /* 78 */
1.626 + { "jsH", Jb, XX, cond_jump_flag },
1.627 + { "jnsH", Jb, XX, cond_jump_flag },
1.628 + { "jpH", Jb, XX, cond_jump_flag },
1.629 + { "jnpH", Jb, XX, cond_jump_flag },
1.630 + { "jlH", Jb, XX, cond_jump_flag },
1.631 + { "jgeH", Jb, XX, cond_jump_flag },
1.632 + { "jleH", Jb, XX, cond_jump_flag },
1.633 + { "jgH", Jb, XX, cond_jump_flag },
1.634 + /* 80 */
1.635 + { GRP1b },
1.636 + { GRP1S },
1.637 + { "(bad)", XX, XX, XX },
1.638 + { GRP1Ss },
1.639 + { "testB", Eb, Gb, XX },
1.640 + { "testS", Ev, Gv, XX },
1.641 + { "xchgB", Eb, Gb, XX },
1.642 + { "xchgS", Ev, Gv, XX },
1.643 + /* 88 */
1.644 + { "movB", Eb, Gb, XX },
1.645 + { "movS", Ev, Gv, XX },
1.646 + { "movB", Gb, Eb, XX },
1.647 + { "movS", Gv, Ev, XX },
1.648 + { "movQ", Ev, Sw, XX },
1.649 + { "leaS", Gv, M, XX },
1.650 + { "movQ", Sw, Ev, XX },
1.651 + { "popU", Ev, XX, XX },
1.652 + /* 90 */
1.653 + { "nop", NOP_Fixup, 0, XX, XX },
1.654 + { "xchgS", RMeCX, eAX, XX },
1.655 + { "xchgS", RMeDX, eAX, XX },
1.656 + { "xchgS", RMeBX, eAX, XX },
1.657 + { "xchgS", RMeSP, eAX, XX },
1.658 + { "xchgS", RMeBP, eAX, XX },
1.659 + { "xchgS", RMeSI, eAX, XX },
1.660 + { "xchgS", RMeDI, eAX, XX },
1.661 + /* 98 */
1.662 + { "cW{tR||tR|}", XX, XX, XX },
1.663 + { "cR{tO||tO|}", XX, XX, XX },
1.664 + { "Jcall{T|}", Ap, XX, XX },
1.665 + { "(bad)", XX, XX, XX }, /* fwait */
1.666 + { "pushfT", XX, XX, XX },
1.667 + { "popfT", XX, XX, XX },
1.668 + { "sahf{|}", XX, XX, XX },
1.669 + { "lahf{|}", XX, XX, XX },
1.670 + /* a0 */
1.671 + { "movB", AL, Ob64, XX },
1.672 + { "movS", eAX, Ov64, XX },
1.673 + { "movB", Ob64, AL, XX },
1.674 + { "movS", Ov64, eAX, XX },
1.675 + { "movs{b||b|}", Yb, Xb, XX },
1.676 + { "movs{R||R|}", Yv, Xv, XX },
1.677 + { "cmps{b||b|}", Xb, Yb, XX },
1.678 + { "cmps{R||R|}", Xv, Yv, XX },
1.679 + /* a8 */
1.680 + { "testB", AL, Ib, XX },
1.681 + { "testS", eAX, Iv, XX },
1.682 + { "stosB", Yb, AL, XX },
1.683 + { "stosS", Yv, eAX, XX },
1.684 + { "lodsB", AL, Xb, XX },
1.685 + { "lodsS", eAX, Xv, XX },
1.686 + { "scasB", AL, Yb, XX },
1.687 + { "scasS", eAX, Yv, XX },
1.688 + /* b0 */
1.689 + { "movB", RMAL, Ib, XX },
1.690 + { "movB", RMCL, Ib, XX },
1.691 + { "movB", RMDL, Ib, XX },
1.692 + { "movB", RMBL, Ib, XX },
1.693 + { "movB", RMAH, Ib, XX },
1.694 + { "movB", RMCH, Ib, XX },
1.695 + { "movB", RMDH, Ib, XX },
1.696 + { "movB", RMBH, Ib, XX },
1.697 + /* b8 */
1.698 + { "movS", RMeAX, Iv64, XX },
1.699 + { "movS", RMeCX, Iv64, XX },
1.700 + { "movS", RMeDX, Iv64, XX },
1.701 + { "movS", RMeBX, Iv64, XX },
1.702 + { "movS", RMeSP, Iv64, XX },
1.703 + { "movS", RMeBP, Iv64, XX },
1.704 + { "movS", RMeSI, Iv64, XX },
1.705 + { "movS", RMeDI, Iv64, XX },
1.706 + /* c0 */
1.707 + { GRP2b },
1.708 + { GRP2S },
1.709 + { "retT", Iw, XX, XX },
1.710 + { "retT", XX, XX, XX },
1.711 + { "les{S|}", Gv, Mp, XX },
1.712 + { "ldsS", Gv, Mp, XX },
1.713 + { "movA", Eb, Ib, XX },
1.714 + { "movQ", Ev, Iv, XX },
1.715 + /* c8 */
1.716 + { "enterT", Iw, Ib, XX },
1.717 + { "leaveT", XX, XX, XX },
1.718 + { "lretP", Iw, XX, XX },
1.719 + { "lretP", XX, XX, XX },
1.720 + { "int3", XX, XX, XX },
1.721 + { "int", Ib, XX, XX },
1.722 + { "into{|}", XX, XX, XX },
1.723 + { "iretP", XX, XX, XX },
1.724 + /* d0 */
1.725 + { GRP2b_one },
1.726 + { GRP2S_one },
1.727 + { GRP2b_cl },
1.728 + { GRP2S_cl },
1.729 + { "aam{|}", sIb, XX, XX },
1.730 + { "aad{|}", sIb, XX, XX },
1.731 + { "(bad)", XX, XX, XX },
1.732 + { "xlat", DSBX, XX, XX },
1.733 + /* d8 */
1.734 + { FLOAT },
1.735 + { FLOAT },
1.736 + { FLOAT },
1.737 + { FLOAT },
1.738 + { FLOAT },
1.739 + { FLOAT },
1.740 + { FLOAT },
1.741 + { FLOAT },
1.742 + /* e0 */
1.743 + { "loopneFH", Jb, XX, loop_jcxz_flag },
1.744 + { "loopeFH", Jb, XX, loop_jcxz_flag },
1.745 + { "loopFH", Jb, XX, loop_jcxz_flag },
1.746 + { "jEcxzH", Jb, XX, loop_jcxz_flag },
1.747 + { "inB", AL, Ib, XX },
1.748 + { "inS", eAX, Ib, XX },
1.749 + { "outB", Ib, AL, XX },
1.750 + { "outS", Ib, eAX, XX },
1.751 + /* e8 */
1.752 + { "callT", Jv, XX, XX },
1.753 + { "jmpT", Jv, XX, XX },
1.754 + { "Jjmp{T|}", Ap, XX, XX },
1.755 + { "jmp", Jb, XX, XX },
1.756 + { "inB", AL, indirDX, XX },
1.757 + { "inS", eAX, indirDX, XX },
1.758 + { "outB", indirDX, AL, XX },
1.759 + { "outS", indirDX, eAX, XX },
1.760 + /* f0 */
1.761 + { "(bad)", XX, XX, XX }, /* lock prefix */
1.762 + { "icebp", XX, XX, XX },
1.763 + { "(bad)", XX, XX, XX }, /* repne */
1.764 + { "(bad)", XX, XX, XX }, /* repz */
1.765 + { "hlt", XX, XX, XX },
1.766 + { "cmc", XX, XX, XX },
1.767 + { GRP3b },
1.768 + { GRP3S },
1.769 + /* f8 */
1.770 + { "clc", XX, XX, XX },
1.771 + { "stc", XX, XX, XX },
1.772 + { "cli", XX, XX, XX },
1.773 + { "sti", XX, XX, XX },
1.774 + { "cld", XX, XX, XX },
1.775 + { "std", XX, XX, XX },
1.776 + { GRP4 },
1.777 + { GRP5 },
1.778 +};
1.779 +
1.780 +static const struct dis386 dis386_twobyte[] = {
1.781 + /* 00 */
1.782 + { GRP6 },
1.783 + { GRP7 },
1.784 + { "larS", Gv, Ew, XX },
1.785 + { "lslS", Gv, Ew, XX },
1.786 + { "(bad)", XX, XX, XX },
1.787 + { "syscall", XX, XX, XX },
1.788 + { "clts", XX, XX, XX },
1.789 + { "sysretP", XX, XX, XX },
1.790 + /* 08 */
1.791 + { "invd", XX, XX, XX },
1.792 + { "wbinvd", XX, XX, XX },
1.793 + { "(bad)", XX, XX, XX },
1.794 + { "ud2a", XX, XX, XX },
1.795 + { "(bad)", XX, XX, XX },
1.796 + { GRPAMD },
1.797 + { "femms", XX, XX, XX },
1.798 + { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix. */
1.799 + /* 10 */
1.800 + { PREGRP8 },
1.801 + { PREGRP9 },
1.802 + { PREGRP30 },
1.803 + { "movlpX", EX, XM, SIMD_Fixup, 'h' },
1.804 + { "unpcklpX", XM, EX, XX },
1.805 + { "unpckhpX", XM, EX, XX },
1.806 + { PREGRP31 },
1.807 + { "movhpX", EX, XM, SIMD_Fixup, 'l' },
1.808 + /* 18 */
1.809 + { GRP14 },
1.810 + { "(bad)", XX, XX, XX },
1.811 + { "(bad)", XX, XX, XX },
1.812 + { "(bad)", XX, XX, XX },
1.813 + { "(bad)", XX, XX, XX },
1.814 + { "(bad)", XX, XX, XX },
1.815 + { "(bad)", XX, XX, XX },
1.816 + { "(bad)", XX, XX, XX },
1.817 + /* 20 */
1.818 + { "movL", Rm, Cm, XX },
1.819 + { "movL", Rm, Dm, XX },
1.820 + { "movL", Cm, Rm, XX },
1.821 + { "movL", Dm, Rm, XX },
1.822 + { "movL", Rd, Td, XX },
1.823 + { "(bad)", XX, XX, XX },
1.824 + { "movL", Td, Rd, XX },
1.825 + { "(bad)", XX, XX, XX },
1.826 + /* 28 */
1.827 + { "movapX", XM, EX, XX },
1.828 + { "movapX", EX, XM, XX },
1.829 + { PREGRP2 },
1.830 + { "movntpX", Ev, XM, XX },
1.831 + { PREGRP4 },
1.832 + { PREGRP3 },
1.833 + { "ucomisX", XM,EX, XX },
1.834 + { "comisX", XM,EX, XX },
1.835 + /* 30 */
1.836 + { "wrmsr", XX, XX, XX },
1.837 + { "rdtsc", XX, XX, XX },
1.838 + { "rdmsr", XX, XX, XX },
1.839 + { "rdpmc", XX, XX, XX },
1.840 + { "sysenter", XX, XX, XX },
1.841 + { "sysexit", XX, XX, XX },
1.842 + { "(bad)", XX, XX, XX },
1.843 + { "(bad)", XX, XX, XX },
1.844 + /* 38 */
1.845 + { "(bad)", XX, XX, XX },
1.846 + { "(bad)", XX, XX, XX },
1.847 + { "(bad)", XX, XX, XX },
1.848 + { "(bad)", XX, XX, XX },
1.849 + { "(bad)", XX, XX, XX },
1.850 + { "(bad)", XX, XX, XX },
1.851 + { "(bad)", XX, XX, XX },
1.852 + { "(bad)", XX, XX, XX },
1.853 + /* 40 */
1.854 + { "cmovo", Gv, Ev, XX },
1.855 + { "cmovno", Gv, Ev, XX },
1.856 + { "cmovb", Gv, Ev, XX },
1.857 + { "cmovae", Gv, Ev, XX },
1.858 + { "cmove", Gv, Ev, XX },
1.859 + { "cmovne", Gv, Ev, XX },
1.860 + { "cmovbe", Gv, Ev, XX },
1.861 + { "cmova", Gv, Ev, XX },
1.862 + /* 48 */
1.863 + { "cmovs", Gv, Ev, XX },
1.864 + { "cmovns", Gv, Ev, XX },
1.865 + { "cmovp", Gv, Ev, XX },
1.866 + { "cmovnp", Gv, Ev, XX },
1.867 + { "cmovl", Gv, Ev, XX },
1.868 + { "cmovge", Gv, Ev, XX },
1.869 + { "cmovle", Gv, Ev, XX },
1.870 + { "cmovg", Gv, Ev, XX },
1.871 + /* 50 */
1.872 + { "movmskpX", Gdq, XS, XX },
1.873 + { PREGRP13 },
1.874 + { PREGRP12 },
1.875 + { PREGRP11 },
1.876 + { "andpX", XM, EX, XX },
1.877 + { "andnpX", XM, EX, XX },
1.878 + { "orpX", XM, EX, XX },
1.879 + { "xorpX", XM, EX, XX },
1.880 + /* 58 */
1.881 + { PREGRP0 },
1.882 + { PREGRP10 },
1.883 + { PREGRP17 },
1.884 + { PREGRP16 },
1.885 + { PREGRP14 },
1.886 + { PREGRP7 },
1.887 + { PREGRP5 },
1.888 + { PREGRP6 },
1.889 + /* 60 */
1.890 + { "punpcklbw", MX, EM, XX },
1.891 + { "punpcklwd", MX, EM, XX },
1.892 + { "punpckldq", MX, EM, XX },
1.893 + { "packsswb", MX, EM, XX },
1.894 + { "pcmpgtb", MX, EM, XX },
1.895 + { "pcmpgtw", MX, EM, XX },
1.896 + { "pcmpgtd", MX, EM, XX },
1.897 + { "packuswb", MX, EM, XX },
1.898 + /* 68 */
1.899 + { "punpckhbw", MX, EM, XX },
1.900 + { "punpckhwd", MX, EM, XX },
1.901 + { "punpckhdq", MX, EM, XX },
1.902 + { "packssdw", MX, EM, XX },
1.903 + { PREGRP26 },
1.904 + { PREGRP24 },
1.905 + { "movd", MX, Edq, XX },
1.906 + { PREGRP19 },
1.907 + /* 70 */
1.908 + { PREGRP22 },
1.909 + { GRP10 },
1.910 + { GRP11 },
1.911 + { GRP12 },
1.912 + { "pcmpeqb", MX, EM, XX },
1.913 + { "pcmpeqw", MX, EM, XX },
1.914 + { "pcmpeqd", MX, EM, XX },
1.915 + { "emms", XX, XX, XX },
1.916 + /* 78 */
1.917 + { "(bad)", XX, XX, XX },
1.918 + { "(bad)", XX, XX, XX },
1.919 + { "(bad)", XX, XX, XX },
1.920 + { "(bad)", XX, XX, XX },
1.921 + { PREGRP28 },
1.922 + { PREGRP29 },
1.923 + { PREGRP23 },
1.924 + { PREGRP20 },
1.925 + /* 80 */
1.926 + { "joH", Jv, XX, cond_jump_flag },
1.927 + { "jnoH", Jv, XX, cond_jump_flag },
1.928 + { "jbH", Jv, XX, cond_jump_flag },
1.929 + { "jaeH", Jv, XX, cond_jump_flag },
1.930 + { "jeH", Jv, XX, cond_jump_flag },
1.931 + { "jneH", Jv, XX, cond_jump_flag },
1.932 + { "jbeH", Jv, XX, cond_jump_flag },
1.933 + { "jaH", Jv, XX, cond_jump_flag },
1.934 + /* 88 */
1.935 + { "jsH", Jv, XX, cond_jump_flag },
1.936 + { "jnsH", Jv, XX, cond_jump_flag },
1.937 + { "jpH", Jv, XX, cond_jump_flag },
1.938 + { "jnpH", Jv, XX, cond_jump_flag },
1.939 + { "jlH", Jv, XX, cond_jump_flag },
1.940 + { "jgeH", Jv, XX, cond_jump_flag },
1.941 + { "jleH", Jv, XX, cond_jump_flag },
1.942 + { "jgH", Jv, XX, cond_jump_flag },
1.943 + /* 90 */
1.944 + { "seto", Eb, XX, XX },
1.945 + { "setno", Eb, XX, XX },
1.946 + { "setb", Eb, XX, XX },
1.947 + { "setae", Eb, XX, XX },
1.948 + { "sete", Eb, XX, XX },
1.949 + { "setne", Eb, XX, XX },
1.950 + { "setbe", Eb, XX, XX },
1.951 + { "seta", Eb, XX, XX },
1.952 + /* 98 */
1.953 + { "sets", Eb, XX, XX },
1.954 + { "setns", Eb, XX, XX },
1.955 + { "setp", Eb, XX, XX },
1.956 + { "setnp", Eb, XX, XX },
1.957 + { "setl", Eb, XX, XX },
1.958 + { "setge", Eb, XX, XX },
1.959 + { "setle", Eb, XX, XX },
1.960 + { "setg", Eb, XX, XX },
1.961 + /* a0 */
1.962 + { "pushT", fs, XX, XX },
1.963 + { "popT", fs, XX, XX },
1.964 + { "cpuid", XX, XX, XX },
1.965 + { "btS", Ev, Gv, XX },
1.966 + { "shldS", Ev, Gv, Ib },
1.967 + { "shldS", Ev, Gv, CL },
1.968 + { GRPPADLCK2 },
1.969 + { GRPPADLCK1 },
1.970 + /* a8 */
1.971 + { "pushT", gs, XX, XX },
1.972 + { "popT", gs, XX, XX },
1.973 + { "rsm", XX, XX, XX },
1.974 + { "btsS", Ev, Gv, XX },
1.975 + { "shrdS", Ev, Gv, Ib },
1.976 + { "shrdS", Ev, Gv, CL },
1.977 + { GRP13 },
1.978 + { "imulS", Gv, Ev, XX },
1.979 + /* b0 */
1.980 + { "cmpxchgB", Eb, Gb, XX },
1.981 + { "cmpxchgS", Ev, Gv, XX },
1.982 + { "lssS", Gv, Mp, XX },
1.983 + { "btrS", Ev, Gv, XX },
1.984 + { "lfsS", Gv, Mp, XX },
1.985 + { "lgsS", Gv, Mp, XX },
1.986 + { "movz{bR|x|bR|x}", Gv, Eb, XX },
1.987 + { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */
1.988 + /* b8 */
1.989 + { "(bad)", XX, XX, XX },
1.990 + { "ud2b", XX, XX, XX },
1.991 + { GRP8 },
1.992 + { "btcS", Ev, Gv, XX },
1.993 + { "bsfS", Gv, Ev, XX },
1.994 + { "bsrS", Gv, Ev, XX },
1.995 + { "movs{bR|x|bR|x}", Gv, Eb, XX },
1.996 + { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */
1.997 + /* c0 */
1.998 + { "xaddB", Eb, Gb, XX },
1.999 + { "xaddS", Ev, Gv, XX },
1.1000 + { PREGRP1 },
1.1001 + { "movntiS", Ev, Gv, XX },
1.1002 + { "pinsrw", MX, Edqw, Ib },
1.1003 + { "pextrw", Gdq, MS, Ib },
1.1004 + { "shufpX", XM, EX, Ib },
1.1005 + { GRP9 },
1.1006 + /* c8 */
1.1007 + { "bswap", RMeAX, XX, XX },
1.1008 + { "bswap", RMeCX, XX, XX },
1.1009 + { "bswap", RMeDX, XX, XX },
1.1010 + { "bswap", RMeBX, XX, XX },
1.1011 + { "bswap", RMeSP, XX, XX },
1.1012 + { "bswap", RMeBP, XX, XX },
1.1013 + { "bswap", RMeSI, XX, XX },
1.1014 + { "bswap", RMeDI, XX, XX },
1.1015 + /* d0 */
1.1016 + { PREGRP27 },
1.1017 + { "psrlw", MX, EM, XX },
1.1018 + { "psrld", MX, EM, XX },
1.1019 + { "psrlq", MX, EM, XX },
1.1020 + { "paddq", MX, EM, XX },
1.1021 + { "pmullw", MX, EM, XX },
1.1022 + { PREGRP21 },
1.1023 + { "pmovmskb", Gdq, MS, XX },
1.1024 + /* d8 */
1.1025 + { "psubusb", MX, EM, XX },
1.1026 + { "psubusw", MX, EM, XX },
1.1027 + { "pminub", MX, EM, XX },
1.1028 + { "pand", MX, EM, XX },
1.1029 + { "paddusb", MX, EM, XX },
1.1030 + { "paddusw", MX, EM, XX },
1.1031 + { "pmaxub", MX, EM, XX },
1.1032 + { "pandn", MX, EM, XX },
1.1033 + /* e0 */
1.1034 + { "pavgb", MX, EM, XX },
1.1035 + { "psraw", MX, EM, XX },
1.1036 + { "psrad", MX, EM, XX },
1.1037 + { "pavgw", MX, EM, XX },
1.1038 + { "pmulhuw", MX, EM, XX },
1.1039 + { "pmulhw", MX, EM, XX },
1.1040 + { PREGRP15 },
1.1041 + { PREGRP25 },
1.1042 + /* e8 */
1.1043 + { "psubsb", MX, EM, XX },
1.1044 + { "psubsw", MX, EM, XX },
1.1045 + { "pminsw", MX, EM, XX },
1.1046 + { "por", MX, EM, XX },
1.1047 + { "paddsb", MX, EM, XX },
1.1048 + { "paddsw", MX, EM, XX },
1.1049 + { "pmaxsw", MX, EM, XX },
1.1050 + { "pxor", MX, EM, XX },
1.1051 + /* f0 */
1.1052 + { PREGRP32 },
1.1053 + { "psllw", MX, EM, XX },
1.1054 + { "pslld", MX, EM, XX },
1.1055 + { "psllq", MX, EM, XX },
1.1056 + { "pmuludq", MX, EM, XX },
1.1057 + { "pmaddwd", MX, EM, XX },
1.1058 + { "psadbw", MX, EM, XX },
1.1059 + { PREGRP18 },
1.1060 + /* f8 */
1.1061 + { "psubb", MX, EM, XX },
1.1062 + { "psubw", MX, EM, XX },
1.1063 + { "psubd", MX, EM, XX },
1.1064 + { "psubq", MX, EM, XX },
1.1065 + { "paddb", MX, EM, XX },
1.1066 + { "paddw", MX, EM, XX },
1.1067 + { "paddd", MX, EM, XX },
1.1068 + { "(bad)", XX, XX, XX }
1.1069 +};
1.1070 +
1.1071 +static const unsigned char onebyte_has_modrm[256] = {
1.1072 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1073 + /* ------------------------------- */
1.1074 + /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */
1.1075 + /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */
1.1076 + /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */
1.1077 + /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */
1.1078 + /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */
1.1079 + /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */
1.1080 + /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */
1.1081 + /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */
1.1082 + /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */
1.1083 + /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */
1.1084 + /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */
1.1085 + /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */
1.1086 + /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */
1.1087 + /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */
1.1088 + /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */
1.1089 + /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */
1.1090 + /* ------------------------------- */
1.1091 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1092 +};
1.1093 +
1.1094 +static const unsigned char twobyte_has_modrm[256] = {
1.1095 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1096 + /* ------------------------------- */
1.1097 + /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */
1.1098 + /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */
1.1099 + /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */
1.1100 + /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1.1101 + /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */
1.1102 + /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */
1.1103 + /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */
1.1104 + /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */
1.1105 + /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1.1106 + /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */
1.1107 + /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */
1.1108 + /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */
1.1109 + /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */
1.1110 + /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */
1.1111 + /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */
1.1112 + /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */
1.1113 + /* ------------------------------- */
1.1114 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1115 +};
1.1116 +
1.1117 +static const unsigned char twobyte_uses_SSE_prefix[256] = {
1.1118 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1119 + /* ------------------------------- */
1.1120 + /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */
1.1121 + /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */
1.1122 + /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */
1.1123 + /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */
1.1124 + /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */
1.1125 + /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */
1.1126 + /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */
1.1127 + /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 7f */
1.1128 + /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */
1.1129 + /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */
1.1130 + /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */
1.1131 + /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */
1.1132 + /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */
1.1133 + /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */
1.1134 + /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */
1.1135 + /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */
1.1136 + /* ------------------------------- */
1.1137 + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
1.1138 +};
1.1139 +
1.1140 +static char obuf[100];
1.1141 +static char *obufp;
1.1142 +static char scratchbuf[100];
1.1143 +static unsigned char *start_codep;
1.1144 +static unsigned char *insn_codep;
1.1145 +static unsigned char *codep;
1.1146 +static disassemble_info *the_info;
1.1147 +static int mod;
1.1148 +static int rm;
1.1149 +static int reg;
1.1150 +static unsigned char need_modrm;
1.1151 +
1.1152 +/* If we are accessing mod/rm/reg without need_modrm set, then the
1.1153 + values are stale. Hitting this abort likely indicates that you
1.1154 + need to update onebyte_has_modrm or twobyte_has_modrm. */
1.1155 +#define MODRM_CHECK if (!need_modrm) abort ()
1.1156 +
1.1157 +static const char **names64;
1.1158 +static const char **names32;
1.1159 +static const char **names16;
1.1160 +static const char **names8;
1.1161 +static const char **names8rex;
1.1162 +static const char **names_seg;
1.1163 +static const char **index16;
1.1164 +
1.1165 +static const char *intel_names64[] = {
1.1166 + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
1.1167 + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1.1168 +};
1.1169 +static const char *intel_names32[] = {
1.1170 + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
1.1171 + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
1.1172 +};
1.1173 +static const char *intel_names16[] = {
1.1174 + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
1.1175 + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
1.1176 +};
1.1177 +static const char *intel_names8[] = {
1.1178 + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
1.1179 +};
1.1180 +static const char *intel_names8rex[] = {
1.1181 + "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
1.1182 + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
1.1183 +};
1.1184 +static const char *intel_names_seg[] = {
1.1185 + "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
1.1186 +};
1.1187 +static const char *intel_index16[] = {
1.1188 + "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
1.1189 +};
1.1190 +
1.1191 +static const char *att_names64[] = {
1.1192 + "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
1.1193 + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
1.1194 +};
1.1195 +static const char *att_names32[] = {
1.1196 + "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
1.1197 + "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
1.1198 +};
1.1199 +static const char *att_names16[] = {
1.1200 + "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
1.1201 + "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
1.1202 +};
1.1203 +static const char *att_names8[] = {
1.1204 + "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
1.1205 +};
1.1206 +static const char *att_names8rex[] = {
1.1207 + "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
1.1208 + "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
1.1209 +};
1.1210 +static const char *att_names_seg[] = {
1.1211 + "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
1.1212 +};
1.1213 +static const char *att_index16[] = {
1.1214 + "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
1.1215 +};
1.1216 +
1.1217 +static const struct dis386 grps[][8] = {
1.1218 + /* GRP1b */
1.1219 + {
1.1220 + { "addA", Eb, Ib, XX },
1.1221 + { "orA", Eb, Ib, XX },
1.1222 + { "adcA", Eb, Ib, XX },
1.1223 + { "sbbA", Eb, Ib, XX },
1.1224 + { "andA", Eb, Ib, XX },
1.1225 + { "subA", Eb, Ib, XX },
1.1226 + { "xorA", Eb, Ib, XX },
1.1227 + { "cmpA", Eb, Ib, XX }
1.1228 + },
1.1229 + /* GRP1S */
1.1230 + {
1.1231 + { "addQ", Ev, Iv, XX },
1.1232 + { "orQ", Ev, Iv, XX },
1.1233 + { "adcQ", Ev, Iv, XX },
1.1234 + { "sbbQ", Ev, Iv, XX },
1.1235 + { "andQ", Ev, Iv, XX },
1.1236 + { "subQ", Ev, Iv, XX },
1.1237 + { "xorQ", Ev, Iv, XX },
1.1238 + { "cmpQ", Ev, Iv, XX }
1.1239 + },
1.1240 + /* GRP1Ss */
1.1241 + {
1.1242 + { "addQ", Ev, sIb, XX },
1.1243 + { "orQ", Ev, sIb, XX },
1.1244 + { "adcQ", Ev, sIb, XX },
1.1245 + { "sbbQ", Ev, sIb, XX },
1.1246 + { "andQ", Ev, sIb, XX },
1.1247 + { "subQ", Ev, sIb, XX },
1.1248 + { "xorQ", Ev, sIb, XX },
1.1249 + { "cmpQ", Ev, sIb, XX }
1.1250 + },
1.1251 + /* GRP2b */
1.1252 + {
1.1253 + { "rolA", Eb, Ib, XX },
1.1254 + { "rorA", Eb, Ib, XX },
1.1255 + { "rclA", Eb, Ib, XX },
1.1256 + { "rcrA", Eb, Ib, XX },
1.1257 + { "shlA", Eb, Ib, XX },
1.1258 + { "shrA", Eb, Ib, XX },
1.1259 + { "(bad)", XX, XX, XX },
1.1260 + { "sarA", Eb, Ib, XX },
1.1261 + },
1.1262 + /* GRP2S */
1.1263 + {
1.1264 + { "rolQ", Ev, Ib, XX },
1.1265 + { "rorQ", Ev, Ib, XX },
1.1266 + { "rclQ", Ev, Ib, XX },
1.1267 + { "rcrQ", Ev, Ib, XX },
1.1268 + { "shlQ", Ev, Ib, XX },
1.1269 + { "shrQ", Ev, Ib, XX },
1.1270 + { "(bad)", XX, XX, XX },
1.1271 + { "sarQ", Ev, Ib, XX },
1.1272 + },
1.1273 + /* GRP2b_one */
1.1274 + {
1.1275 + { "rolA", Eb, I1, XX },
1.1276 + { "rorA", Eb, I1, XX },
1.1277 + { "rclA", Eb, I1, XX },
1.1278 + { "rcrA", Eb, I1, XX },
1.1279 + { "shlA", Eb, I1, XX },
1.1280 + { "shrA", Eb, I1, XX },
1.1281 + { "(bad)", XX, XX, XX },
1.1282 + { "sarA", Eb, I1, XX },
1.1283 + },
1.1284 + /* GRP2S_one */
1.1285 + {
1.1286 + { "rolQ", Ev, I1, XX },
1.1287 + { "rorQ", Ev, I1, XX },
1.1288 + { "rclQ", Ev, I1, XX },
1.1289 + { "rcrQ", Ev, I1, XX },
1.1290 + { "shlQ", Ev, I1, XX },
1.1291 + { "shrQ", Ev, I1, XX },
1.1292 + { "(bad)", XX, XX, XX},
1.1293 + { "sarQ", Ev, I1, XX },
1.1294 + },
1.1295 + /* GRP2b_cl */
1.1296 + {
1.1297 + { "rolA", Eb, CL, XX },
1.1298 + { "rorA", Eb, CL, XX },
1.1299 + { "rclA", Eb, CL, XX },
1.1300 + { "rcrA", Eb, CL, XX },
1.1301 + { "shlA", Eb, CL, XX },
1.1302 + { "shrA", Eb, CL, XX },
1.1303 + { "(bad)", XX, XX, XX },
1.1304 + { "sarA", Eb, CL, XX },
1.1305 + },
1.1306 + /* GRP2S_cl */
1.1307 + {
1.1308 + { "rolQ", Ev, CL, XX },
1.1309 + { "rorQ", Ev, CL, XX },
1.1310 + { "rclQ", Ev, CL, XX },
1.1311 + { "rcrQ", Ev, CL, XX },
1.1312 + { "shlQ", Ev, CL, XX },
1.1313 + { "shrQ", Ev, CL, XX },
1.1314 + { "(bad)", XX, XX, XX },
1.1315 + { "sarQ", Ev, CL, XX }
1.1316 + },
1.1317 + /* GRP3b */
1.1318 + {
1.1319 + { "testA", Eb, Ib, XX },
1.1320 + { "(bad)", Eb, XX, XX },
1.1321 + { "notA", Eb, XX, XX },
1.1322 + { "negA", Eb, XX, XX },
1.1323 + { "mulA", Eb, XX, XX }, /* Don't print the implicit %al register, */
1.1324 + { "imulA", Eb, XX, XX }, /* to distinguish these opcodes from other */
1.1325 + { "divA", Eb, XX, XX }, /* mul/imul opcodes. Do the same for div */
1.1326 + { "idivA", Eb, XX, XX } /* and idiv for consistency. */
1.1327 + },
1.1328 + /* GRP3S */
1.1329 + {
1.1330 + { "testQ", Ev, Iv, XX },
1.1331 + { "(bad)", XX, XX, XX },
1.1332 + { "notQ", Ev, XX, XX },
1.1333 + { "negQ", Ev, XX, XX },
1.1334 + { "mulQ", Ev, XX, XX }, /* Don't print the implicit register. */
1.1335 + { "imulQ", Ev, XX, XX },
1.1336 + { "divQ", Ev, XX, XX },
1.1337 + { "idivQ", Ev, XX, XX },
1.1338 + },
1.1339 + /* GRP4 */
1.1340 + {
1.1341 + { "incA", Eb, XX, XX },
1.1342 + { "decA", Eb, XX, XX },
1.1343 + { "(bad)", XX, XX, XX },
1.1344 + { "(bad)", XX, XX, XX },
1.1345 + { "(bad)", XX, XX, XX },
1.1346 + { "(bad)", XX, XX, XX },
1.1347 + { "(bad)", XX, XX, XX },
1.1348 + { "(bad)", XX, XX, XX },
1.1349 + },
1.1350 + /* GRP5 */
1.1351 + {
1.1352 + { "incQ", Ev, XX, XX },
1.1353 + { "decQ", Ev, XX, XX },
1.1354 + { "callT", indirEv, XX, XX },
1.1355 + { "JcallT", indirEp, XX, XX },
1.1356 + { "jmpT", indirEv, XX, XX },
1.1357 + { "JjmpT", indirEp, XX, XX },
1.1358 + { "pushU", Ev, XX, XX },
1.1359 + { "(bad)", XX, XX, XX },
1.1360 + },
1.1361 + /* GRP6 */
1.1362 + {
1.1363 + { "sldtQ", Ev, XX, XX },
1.1364 + { "strQ", Ev, XX, XX },
1.1365 + { "lldt", Ew, XX, XX },
1.1366 + { "ltr", Ew, XX, XX },
1.1367 + { "verr", Ew, XX, XX },
1.1368 + { "verw", Ew, XX, XX },
1.1369 + { "(bad)", XX, XX, XX },
1.1370 + { "(bad)", XX, XX, XX }
1.1371 + },
1.1372 + /* GRP7 */
1.1373 + {
1.1374 + { "sgdtIQ", M, XX, XX },
1.1375 + { "sidtIQ", PNI_Fixup, 0, XX, XX },
1.1376 + { "lgdt{Q|Q||}", M, XX, XX },
1.1377 + { "lidt{Q|Q||}", M, XX, XX },
1.1378 + { "smswQ", Ev, XX, XX },
1.1379 + { "(bad)", XX, XX, XX },
1.1380 + { "lmsw", Ew, XX, XX },
1.1381 + { "invlpg", INVLPG_Fixup, w_mode, XX, XX },
1.1382 + },
1.1383 + /* GRP8 */
1.1384 + {
1.1385 + { "(bad)", XX, XX, XX },
1.1386 + { "(bad)", XX, XX, XX },
1.1387 + { "(bad)", XX, XX, XX },
1.1388 + { "(bad)", XX, XX, XX },
1.1389 + { "btQ", Ev, Ib, XX },
1.1390 + { "btsQ", Ev, Ib, XX },
1.1391 + { "btrQ", Ev, Ib, XX },
1.1392 + { "btcQ", Ev, Ib, XX },
1.1393 + },
1.1394 + /* GRP9 */
1.1395 + {
1.1396 + { "(bad)", XX, XX, XX },
1.1397 + { "cmpxchg8b", Eq, XX, XX },
1.1398 + { "(bad)", XX, XX, XX },
1.1399 + { "(bad)", XX, XX, XX },
1.1400 + { "(bad)", XX, XX, XX },
1.1401 + { "(bad)", XX, XX, XX },
1.1402 + { "(bad)", XX, XX, XX },
1.1403 + { "(bad)", XX, XX, XX },
1.1404 + },
1.1405 + /* GRP10 */
1.1406 + {
1.1407 + { "(bad)", XX, XX, XX },
1.1408 + { "(bad)", XX, XX, XX },
1.1409 + { "psrlw", MS, Ib, XX },
1.1410 + { "(bad)", XX, XX, XX },
1.1411 + { "psraw", MS, Ib, XX },
1.1412 + { "(bad)", XX, XX, XX },
1.1413 + { "psllw", MS, Ib, XX },
1.1414 + { "(bad)", XX, XX, XX },
1.1415 + },
1.1416 + /* GRP11 */
1.1417 + {
1.1418 + { "(bad)", XX, XX, XX },
1.1419 + { "(bad)", XX, XX, XX },
1.1420 + { "psrld", MS, Ib, XX },
1.1421 + { "(bad)", XX, XX, XX },
1.1422 + { "psrad", MS, Ib, XX },
1.1423 + { "(bad)", XX, XX, XX },
1.1424 + { "pslld", MS, Ib, XX },
1.1425 + { "(bad)", XX, XX, XX },
1.1426 + },
1.1427 + /* GRP12 */
1.1428 + {
1.1429 + { "(bad)", XX, XX, XX },
1.1430 + { "(bad)", XX, XX, XX },
1.1431 + { "psrlq", MS, Ib, XX },
1.1432 + { "psrldq", MS, Ib, XX },
1.1433 + { "(bad)", XX, XX, XX },
1.1434 + { "(bad)", XX, XX, XX },
1.1435 + { "psllq", MS, Ib, XX },
1.1436 + { "pslldq", MS, Ib, XX },
1.1437 + },
1.1438 + /* GRP13 */
1.1439 + {
1.1440 + { "fxsave", Ev, XX, XX },
1.1441 + { "fxrstor", Ev, XX, XX },
1.1442 + { "ldmxcsr", Ev, XX, XX },
1.1443 + { "stmxcsr", Ev, XX, XX },
1.1444 + { "(bad)", XX, XX, XX },
1.1445 + { "lfence", OP_0fae, 0, XX, XX },
1.1446 + { "mfence", OP_0fae, 0, XX, XX },
1.1447 + { "clflush", OP_0fae, 0, XX, XX },
1.1448 + },
1.1449 + /* GRP14 */
1.1450 + {
1.1451 + { "prefetchnta", Ev, XX, XX },
1.1452 + { "prefetcht0", Ev, XX, XX },
1.1453 + { "prefetcht1", Ev, XX, XX },
1.1454 + { "prefetcht2", Ev, XX, XX },
1.1455 + { "(bad)", XX, XX, XX },
1.1456 + { "(bad)", XX, XX, XX },
1.1457 + { "(bad)", XX, XX, XX },
1.1458 + { "(bad)", XX, XX, XX },
1.1459 + },
1.1460 + /* GRPAMD */
1.1461 + {
1.1462 + { "prefetch", Eb, XX, XX },
1.1463 + { "prefetchw", Eb, XX, XX },
1.1464 + { "(bad)", XX, XX, XX },
1.1465 + { "(bad)", XX, XX, XX },
1.1466 + { "(bad)", XX, XX, XX },
1.1467 + { "(bad)", XX, XX, XX },
1.1468 + { "(bad)", XX, XX, XX },
1.1469 + { "(bad)", XX, XX, XX },
1.1470 + },
1.1471 + /* GRPPADLCK1 */
1.1472 + {
1.1473 + { "xstorerng", OP_0f07, 0, XX, XX },
1.1474 + { "xcryptecb", OP_0f07, 0, XX, XX },
1.1475 + { "xcryptcbc", OP_0f07, 0, XX, XX },
1.1476 + { "(bad)", OP_0f07, 0, XX, XX },
1.1477 + { "xcryptcfb", OP_0f07, 0, XX, XX },
1.1478 + { "xcryptofb", OP_0f07, 0, XX, XX },
1.1479 + { "(bad)", OP_0f07, 0, XX, XX },
1.1480 + { "(bad)", OP_0f07, 0, XX, XX },
1.1481 + },
1.1482 + /* GRPPADLCK2 */
1.1483 + {
1.1484 + { "montmul", OP_0f07, 0, XX, XX },
1.1485 + { "xsha1", OP_0f07, 0, XX, XX },
1.1486 + { "xsha256", OP_0f07, 0, XX, XX },
1.1487 + { "(bad)", OP_0f07, 0, XX, XX },
1.1488 + { "(bad)", OP_0f07, 0, XX, XX },
1.1489 + { "(bad)", OP_0f07, 0, XX, XX },
1.1490 + { "(bad)", OP_0f07, 0, XX, XX },
1.1491 + { "(bad)", OP_0f07, 0, XX, XX },
1.1492 + }
1.1493 +};
1.1494 +
1.1495 +static const struct dis386 prefix_user_table[][4] = {
1.1496 + /* PREGRP0 */
1.1497 + {
1.1498 + { "addps", XM, EX, XX },
1.1499 + { "addss", XM, EX, XX },
1.1500 + { "addpd", XM, EX, XX },
1.1501 + { "addsd", XM, EX, XX },
1.1502 + },
1.1503 + /* PREGRP1 */
1.1504 + {
1.1505 + { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX. */
1.1506 + { "", XM, EX, OPSIMD },
1.1507 + { "", XM, EX, OPSIMD },
1.1508 + { "", XM, EX, OPSIMD },
1.1509 + },
1.1510 + /* PREGRP2 */
1.1511 + {
1.1512 + { "cvtpi2ps", XM, EM, XX },
1.1513 + { "cvtsi2ssY", XM, Ev, XX },
1.1514 + { "cvtpi2pd", XM, EM, XX },
1.1515 + { "cvtsi2sdY", XM, Ev, XX },
1.1516 + },
1.1517 + /* PREGRP3 */
1.1518 + {
1.1519 + { "cvtps2pi", MX, EX, XX },
1.1520 + { "cvtss2siY", Gv, EX, XX },
1.1521 + { "cvtpd2pi", MX, EX, XX },
1.1522 + { "cvtsd2siY", Gv, EX, XX },
1.1523 + },
1.1524 + /* PREGRP4 */
1.1525 + {
1.1526 + { "cvttps2pi", MX, EX, XX },
1.1527 + { "cvttss2siY", Gv, EX, XX },
1.1528 + { "cvttpd2pi", MX, EX, XX },
1.1529 + { "cvttsd2siY", Gv, EX, XX },
1.1530 + },
1.1531 + /* PREGRP5 */
1.1532 + {
1.1533 + { "divps", XM, EX, XX },
1.1534 + { "divss", XM, EX, XX },
1.1535 + { "divpd", XM, EX, XX },
1.1536 + { "divsd", XM, EX, XX },
1.1537 + },
1.1538 + /* PREGRP6 */
1.1539 + {
1.1540 + { "maxps", XM, EX, XX },
1.1541 + { "maxss", XM, EX, XX },
1.1542 + { "maxpd", XM, EX, XX },
1.1543 + { "maxsd", XM, EX, XX },
1.1544 + },
1.1545 + /* PREGRP7 */
1.1546 + {
1.1547 + { "minps", XM, EX, XX },
1.1548 + { "minss", XM, EX, XX },
1.1549 + { "minpd", XM, EX, XX },
1.1550 + { "minsd", XM, EX, XX },
1.1551 + },
1.1552 + /* PREGRP8 */
1.1553 + {
1.1554 + { "movups", XM, EX, XX },
1.1555 + { "movss", XM, EX, XX },
1.1556 + { "movupd", XM, EX, XX },
1.1557 + { "movsd", XM, EX, XX },
1.1558 + },
1.1559 + /* PREGRP9 */
1.1560 + {
1.1561 + { "movups", EX, XM, XX },
1.1562 + { "movss", EX, XM, XX },
1.1563 + { "movupd", EX, XM, XX },
1.1564 + { "movsd", EX, XM, XX },
1.1565 + },
1.1566 + /* PREGRP10 */
1.1567 + {
1.1568 + { "mulps", XM, EX, XX },
1.1569 + { "mulss", XM, EX, XX },
1.1570 + { "mulpd", XM, EX, XX },
1.1571 + { "mulsd", XM, EX, XX },
1.1572 + },
1.1573 + /* PREGRP11 */
1.1574 + {
1.1575 + { "rcpps", XM, EX, XX },
1.1576 + { "rcpss", XM, EX, XX },
1.1577 + { "(bad)", XM, EX, XX },
1.1578 + { "(bad)", XM, EX, XX },
1.1579 + },
1.1580 + /* PREGRP12 */
1.1581 + {
1.1582 + { "rsqrtps", XM, EX, XX },
1.1583 + { "rsqrtss", XM, EX, XX },
1.1584 + { "(bad)", XM, EX, XX },
1.1585 + { "(bad)", XM, EX, XX },
1.1586 + },
1.1587 + /* PREGRP13 */
1.1588 + {
1.1589 + { "sqrtps", XM, EX, XX },
1.1590 + { "sqrtss", XM, EX, XX },
1.1591 + { "sqrtpd", XM, EX, XX },
1.1592 + { "sqrtsd", XM, EX, XX },
1.1593 + },
1.1594 + /* PREGRP14 */
1.1595 + {
1.1596 + { "subps", XM, EX, XX },
1.1597 + { "subss", XM, EX, XX },
1.1598 + { "subpd", XM, EX, XX },
1.1599 + { "subsd", XM, EX, XX },
1.1600 + },
1.1601 + /* PREGRP15 */
1.1602 + {
1.1603 + { "(bad)", XM, EX, XX },
1.1604 + { "cvtdq2pd", XM, EX, XX },
1.1605 + { "cvttpd2dq", XM, EX, XX },
1.1606 + { "cvtpd2dq", XM, EX, XX },
1.1607 + },
1.1608 + /* PREGRP16 */
1.1609 + {
1.1610 + { "cvtdq2ps", XM, EX, XX },
1.1611 + { "cvttps2dq",XM, EX, XX },
1.1612 + { "cvtps2dq",XM, EX, XX },
1.1613 + { "(bad)", XM, EX, XX },
1.1614 + },
1.1615 + /* PREGRP17 */
1.1616 + {
1.1617 + { "cvtps2pd", XM, EX, XX },
1.1618 + { "cvtss2sd", XM, EX, XX },
1.1619 + { "cvtpd2ps", XM, EX, XX },
1.1620 + { "cvtsd2ss", XM, EX, XX },
1.1621 + },
1.1622 + /* PREGRP18 */
1.1623 + {
1.1624 + { "maskmovq", MX, MS, XX },
1.1625 + { "(bad)", XM, EX, XX },
1.1626 + { "maskmovdqu", XM, EX, XX },
1.1627 + { "(bad)", XM, EX, XX },
1.1628 + },
1.1629 + /* PREGRP19 */
1.1630 + {
1.1631 + { "movq", MX, EM, XX },
1.1632 + { "movdqu", XM, EX, XX },
1.1633 + { "movdqa", XM, EX, XX },
1.1634 + { "(bad)", XM, EX, XX },
1.1635 + },
1.1636 + /* PREGRP20 */
1.1637 + {
1.1638 + { "movq", EM, MX, XX },
1.1639 + { "movdqu", EX, XM, XX },
1.1640 + { "movdqa", EX, XM, XX },
1.1641 + { "(bad)", EX, XM, XX },
1.1642 + },
1.1643 + /* PREGRP21 */
1.1644 + {
1.1645 + { "(bad)", EX, XM, XX },
1.1646 + { "movq2dq", XM, MS, XX },
1.1647 + { "movq", EX, XM, XX },
1.1648 + { "movdq2q", MX, XS, XX },
1.1649 + },
1.1650 + /* PREGRP22 */
1.1651 + {
1.1652 + { "pshufw", MX, EM, Ib },
1.1653 + { "pshufhw", XM, EX, Ib },
1.1654 + { "pshufd", XM, EX, Ib },
1.1655 + { "pshuflw", XM, EX, Ib },
1.1656 + },
1.1657 + /* PREGRP23 */
1.1658 + {
1.1659 + { "movd", Edq, MX, XX },
1.1660 + { "movq", XM, EX, XX },
1.1661 + { "movd", Edq, XM, XX },
1.1662 + { "(bad)", Ed, XM, XX },
1.1663 + },
1.1664 + /* PREGRP24 */
1.1665 + {
1.1666 + { "(bad)", MX, EX, XX },
1.1667 + { "(bad)", XM, EX, XX },
1.1668 + { "punpckhqdq", XM, EX, XX },
1.1669 + { "(bad)", XM, EX, XX },
1.1670 + },
1.1671 + /* PREGRP25 */
1.1672 + {
1.1673 + { "movntq", EM, MX, XX },
1.1674 + { "(bad)", EM, XM, XX },
1.1675 + { "movntdq", EM, XM, XX },
1.1676 + { "(bad)", EM, XM, XX },
1.1677 + },
1.1678 + /* PREGRP26 */
1.1679 + {
1.1680 + { "(bad)", MX, EX, XX },
1.1681 + { "(bad)", XM, EX, XX },
1.1682 + { "punpcklqdq", XM, EX, XX },
1.1683 + { "(bad)", XM, EX, XX },
1.1684 + },
1.1685 + /* PREGRP27 */
1.1686 + {
1.1687 + { "(bad)", MX, EX, XX },
1.1688 + { "(bad)", XM, EX, XX },
1.1689 + { "addsubpd", XM, EX, XX },
1.1690 + { "addsubps", XM, EX, XX },
1.1691 + },
1.1692 + /* PREGRP28 */
1.1693 + {
1.1694 + { "(bad)", MX, EX, XX },
1.1695 + { "(bad)", XM, EX, XX },
1.1696 + { "haddpd", XM, EX, XX },
1.1697 + { "haddps", XM, EX, XX },
1.1698 + },
1.1699 + /* PREGRP29 */
1.1700 + {
1.1701 + { "(bad)", MX, EX, XX },
1.1702 + { "(bad)", XM, EX, XX },
1.1703 + { "hsubpd", XM, EX, XX },
1.1704 + { "hsubps", XM, EX, XX },
1.1705 + },
1.1706 + /* PREGRP30 */
1.1707 + {
1.1708 + { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */
1.1709 + { "movsldup", XM, EX, XX },
1.1710 + { "movlpd", XM, EX, XX },
1.1711 + { "movddup", XM, EX, XX },
1.1712 + },
1.1713 + /* PREGRP31 */
1.1714 + {
1.1715 + { "movhpX", XM, EX, SIMD_Fixup, 'l' },
1.1716 + { "movshdup", XM, EX, XX },
1.1717 + { "movhpd", XM, EX, XX },
1.1718 + { "(bad)", XM, EX, XX },
1.1719 + },
1.1720 + /* PREGRP32 */
1.1721 + {
1.1722 + { "(bad)", XM, EX, XX },
1.1723 + { "(bad)", XM, EX, XX },
1.1724 + { "(bad)", XM, EX, XX },
1.1725 + { "lddqu", XM, M, XX },
1.1726 + },
1.1727 +};
1.1728 +
1.1729 +static const struct dis386 x86_64_table[][2] = {
1.1730 + {
1.1731 + { "arpl", Ew, Gw, XX },
1.1732 + { "movs{||lq|xd}", Gv, Ed, XX },
1.1733 + },
1.1734 +};
1.1735 +
1.1736 +#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
1.1737 +
1.1738 +static void
1.1739 +ckprefix (void)
1.1740 +{
1.1741 + int newrex;
1.1742 + rex = 0;
1.1743 + prefixes = 0;
1.1744 + used_prefixes = 0;
1.1745 + rex_used = 0;
1.1746 + while (1)
1.1747 + {
1.1748 + FETCH_DATA (the_info, codep + 1);
1.1749 + newrex = 0;
1.1750 + switch (*codep)
1.1751 + {
1.1752 + /* REX prefixes family. */
1.1753 + case 0x40:
1.1754 + case 0x41:
1.1755 + case 0x42:
1.1756 + case 0x43:
1.1757 + case 0x44:
1.1758 + case 0x45:
1.1759 + case 0x46:
1.1760 + case 0x47:
1.1761 + case 0x48:
1.1762 + case 0x49:
1.1763 + case 0x4a:
1.1764 + case 0x4b:
1.1765 + case 0x4c:
1.1766 + case 0x4d:
1.1767 + case 0x4e:
1.1768 + case 0x4f:
1.1769 + if (mode_64bit)
1.1770 + newrex = *codep;
1.1771 + else
1.1772 + return;
1.1773 + break;
1.1774 + case 0xf3:
1.1775 + prefixes |= PREFIX_REPZ;
1.1776 + break;
1.1777 + case 0xf2:
1.1778 + prefixes |= PREFIX_REPNZ;
1.1779 + break;
1.1780 + case 0xf0:
1.1781 + prefixes |= PREFIX_LOCK;
1.1782 + break;
1.1783 + case 0x2e:
1.1784 + prefixes |= PREFIX_CS;
1.1785 + break;
1.1786 + case 0x36:
1.1787 + prefixes |= PREFIX_SS;
1.1788 + break;
1.1789 + case 0x3e:
1.1790 + prefixes |= PREFIX_DS;
1.1791 + break;
1.1792 + case 0x26:
1.1793 + prefixes |= PREFIX_ES;
1.1794 + break;
1.1795 + case 0x64:
1.1796 + prefixes |= PREFIX_FS;
1.1797 + break;
1.1798 + case 0x65:
1.1799 + prefixes |= PREFIX_GS;
1.1800 + break;
1.1801 + case 0x66:
1.1802 + prefixes |= PREFIX_DATA;
1.1803 + break;
1.1804 + case 0x67:
1.1805 + prefixes |= PREFIX_ADDR;
1.1806 + break;
1.1807 + case FWAIT_OPCODE:
1.1808 + /* fwait is really an instruction. If there are prefixes
1.1809 + before the fwait, they belong to the fwait, *not* to the
1.1810 + following instruction. */
1.1811 + if (prefixes)
1.1812 + {
1.1813 + prefixes |= PREFIX_FWAIT;
1.1814 + codep++;
1.1815 + return;
1.1816 + }
1.1817 + prefixes = PREFIX_FWAIT;
1.1818 + break;
1.1819 + default:
1.1820 + return;
1.1821 + }
1.1822 + /* Rex is ignored when followed by another prefix. */
1.1823 + if (rex)
1.1824 + {
1.1825 + oappend (prefix_name (rex, 0));
1.1826 + oappend (" ");
1.1827 + }
1.1828 + rex = newrex;
1.1829 + codep++;
1.1830 + }
1.1831 +}
1.1832 +
1.1833 +/* Return the name of the prefix byte PREF, or NULL if PREF is not a
1.1834 + prefix byte. */
1.1835 +
1.1836 +static const char *
1.1837 +prefix_name (int pref, int sizeflag)
1.1838 +{
1.1839 + switch (pref)
1.1840 + {
1.1841 + /* REX prefixes family. */
1.1842 + case 0x40:
1.1843 + return "rex";
1.1844 + case 0x41:
1.1845 + return "rexZ";
1.1846 + case 0x42:
1.1847 + return "rexY";
1.1848 + case 0x43:
1.1849 + return "rexYZ";
1.1850 + case 0x44:
1.1851 + return "rexX";
1.1852 + case 0x45:
1.1853 + return "rexXZ";
1.1854 + case 0x46:
1.1855 + return "rexXY";
1.1856 + case 0x47:
1.1857 + return "rexXYZ";
1.1858 + case 0x48:
1.1859 + return "rex64";
1.1860 + case 0x49:
1.1861 + return "rex64Z";
1.1862 + case 0x4a:
1.1863 + return "rex64Y";
1.1864 + case 0x4b:
1.1865 + return "rex64YZ";
1.1866 + case 0x4c:
1.1867 + return "rex64X";
1.1868 + case 0x4d:
1.1869 + return "rex64XZ";
1.1870 + case 0x4e:
1.1871 + return "rex64XY";
1.1872 + case 0x4f:
1.1873 + return "rex64XYZ";
1.1874 + case 0xf3:
1.1875 + return "repz";
1.1876 + case 0xf2:
1.1877 + return "repnz";
1.1878 + case 0xf0:
1.1879 + return "lock";
1.1880 + case 0x2e:
1.1881 + return "cs";
1.1882 + case 0x36:
1.1883 + return "ss";
1.1884 + case 0x3e:
1.1885 + return "ds";
1.1886 + case 0x26:
1.1887 + return "es";
1.1888 + case 0x64:
1.1889 + return "fs";
1.1890 + case 0x65:
1.1891 + return "gs";
1.1892 + case 0x66:
1.1893 + return (sizeflag & DFLAG) ? "data16" : "data32";
1.1894 + case 0x67:
1.1895 + if (mode_64bit)
1.1896 + return (sizeflag & AFLAG) ? "addr32" : "addr64";
1.1897 + else
1.1898 + return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32";
1.1899 + case FWAIT_OPCODE:
1.1900 + return "fwait";
1.1901 + default:
1.1902 + return NULL;
1.1903 + }
1.1904 +}
1.1905 +
1.1906 +static char op1out[100], op2out[100], op3out[100];
1.1907 +static int op_ad, op_index[3];
1.1908 +static int two_source_ops;
1.1909 +static bfd_vma op_address[3];
1.1910 +static bfd_vma op_riprel[3];
1.1911 +static bfd_vma start_pc;
1.1912 +
1.1913 +/*
1.1914 + * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
1.1915 + * (see topic "Redundant prefixes" in the "Differences from 8086"
1.1916 + * section of the "Virtual 8086 Mode" chapter.)
1.1917 + * 'pc' should be the address of this instruction, it will
1.1918 + * be used to print the target address if this is a relative jump or call
1.1919 + * The function returns the length of this instruction in bytes.
1.1920 + */
1.1921 +
1.1922 +static char intel_syntax;
1.1923 +static char open_char;
1.1924 +static char close_char;
1.1925 +static char separator_char;
1.1926 +static char scale_char;
1.1927 +
1.1928 +/* Here for backwards compatibility. When gdb stops using
1.1929 + print_insn_i386_att and print_insn_i386_intel these functions can
1.1930 + disappear, and print_insn_i386 be merged into print_insn. */
1.1931 +int
1.1932 +print_insn_i386_att (bfd_vma pc, disassemble_info *info)
1.1933 +{
1.1934 + intel_syntax = 0;
1.1935 +
1.1936 + return print_insn (pc, info);
1.1937 +}
1.1938 +
1.1939 +int
1.1940 +print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
1.1941 +{
1.1942 + intel_syntax = 1;
1.1943 +
1.1944 + return print_insn (pc, info);
1.1945 +}
1.1946 +
1.1947 +int
1.1948 +print_insn_i386 (bfd_vma pc, disassemble_info *info)
1.1949 +{
1.1950 + intel_syntax = -1;
1.1951 +
1.1952 + return print_insn (pc, info);
1.1953 +}
1.1954 +
1.1955 +static int
1.1956 +print_insn (bfd_vma pc, disassemble_info *info)
1.1957 +{
1.1958 + const struct dis386 *dp;
1.1959 + int i;
1.1960 + char *first, *second, *third;
1.1961 + int needcomma;
1.1962 + unsigned char uses_SSE_prefix, uses_LOCK_prefix;
1.1963 + int sizeflag;
1.1964 + const char *p;
1.1965 + struct dis_private priv;
1.1966 +
1.1967 + mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax
1.1968 + || info->mach == bfd_mach_x86_64);
1.1969 +
1.1970 + if (intel_syntax == (char) -1)
1.1971 + intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax
1.1972 + || info->mach == bfd_mach_x86_64_intel_syntax);
1.1973 +
1.1974 + if (info->mach == bfd_mach_i386_i386
1.1975 + || info->mach == bfd_mach_x86_64
1.1976 + || info->mach == bfd_mach_i386_i386_intel_syntax
1.1977 + || info->mach == bfd_mach_x86_64_intel_syntax)
1.1978 + priv.orig_sizeflag = AFLAG | DFLAG;
1.1979 + else if (info->mach == bfd_mach_i386_i8086)
1.1980 + priv.orig_sizeflag = 0;
1.1981 + else
1.1982 + abort ();
1.1983 +
1.1984 + for (p = info->disassembler_options; p != NULL; )
1.1985 + {
1.1986 + if (strncmp (p, "x86-64", 6) == 0)
1.1987 + {
1.1988 + mode_64bit = 1;
1.1989 + priv.orig_sizeflag = AFLAG | DFLAG;
1.1990 + }
1.1991 + else if (strncmp (p, "i386", 4) == 0)
1.1992 + {
1.1993 + mode_64bit = 0;
1.1994 + priv.orig_sizeflag = AFLAG | DFLAG;
1.1995 + }
1.1996 + else if (strncmp (p, "i8086", 5) == 0)
1.1997 + {
1.1998 + mode_64bit = 0;
1.1999 + priv.orig_sizeflag = 0;
1.2000 + }
1.2001 + else if (strncmp (p, "intel", 5) == 0)
1.2002 + {
1.2003 + intel_syntax = 1;
1.2004 + }
1.2005 + else if (strncmp (p, "att", 3) == 0)
1.2006 + {
1.2007 + intel_syntax = 0;
1.2008 + }
1.2009 + else if (strncmp (p, "addr", 4) == 0)
1.2010 + {
1.2011 + if (p[4] == '1' && p[5] == '6')
1.2012 + priv.orig_sizeflag &= ~AFLAG;
1.2013 + else if (p[4] == '3' && p[5] == '2')
1.2014 + priv.orig_sizeflag |= AFLAG;
1.2015 + }
1.2016 + else if (strncmp (p, "data", 4) == 0)
1.2017 + {
1.2018 + if (p[4] == '1' && p[5] == '6')
1.2019 + priv.orig_sizeflag &= ~DFLAG;
1.2020 + else if (p[4] == '3' && p[5] == '2')
1.2021 + priv.orig_sizeflag |= DFLAG;
1.2022 + }
1.2023 + else if (strncmp (p, "suffix", 6) == 0)
1.2024 + priv.orig_sizeflag |= SUFFIX_ALWAYS;
1.2025 +
1.2026 + p = strchr (p, ',');
1.2027 + if (p != NULL)
1.2028 + p++;
1.2029 + }
1.2030 +
1.2031 + if (intel_syntax)
1.2032 + {
1.2033 + names64 = intel_names64;
1.2034 + names32 = intel_names32;
1.2035 + names16 = intel_names16;
1.2036 + names8 = intel_names8;
1.2037 + names8rex = intel_names8rex;
1.2038 + names_seg = intel_names_seg;
1.2039 + index16 = intel_index16;
1.2040 + open_char = '[';
1.2041 + close_char = ']';
1.2042 + separator_char = '+';
1.2043 + scale_char = '*';
1.2044 + }
1.2045 + else
1.2046 + {
1.2047 + names64 = att_names64;
1.2048 + names32 = att_names32;
1.2049 + names16 = att_names16;
1.2050 + names8 = att_names8;
1.2051 + names8rex = att_names8rex;
1.2052 + names_seg = att_names_seg;
1.2053 + index16 = att_index16;
1.2054 + open_char = '(';
1.2055 + close_char = ')';
1.2056 + separator_char = ',';
1.2057 + scale_char = ',';
1.2058 + }
1.2059 +
1.2060 + /* The output looks better if we put 7 bytes on a line, since that
1.2061 + puts most long word instructions on a single line. */
1.2062 + info->bytes_per_line = 7;
1.2063 +
1.2064 + info->private_data = &priv;
1.2065 + priv.max_fetched = priv.the_buffer;
1.2066 + priv.insn_start = pc;
1.2067 +
1.2068 + obuf[0] = 0;
1.2069 + op1out[0] = 0;
1.2070 + op2out[0] = 0;
1.2071 + op3out[0] = 0;
1.2072 +
1.2073 + op_index[0] = op_index[1] = op_index[2] = -1;
1.2074 +
1.2075 + the_info = info;
1.2076 + start_pc = pc;
1.2077 + start_codep = priv.the_buffer;
1.2078 + codep = priv.the_buffer;
1.2079 +
1.2080 + if (setjmp (priv.bailout) != 0)
1.2081 + {
1.2082 + const char *name;
1.2083 +
1.2084 + /* Getting here means we tried for data but didn't get it. That
1.2085 + means we have an incomplete instruction of some sort. Just
1.2086 + print the first byte as a prefix or a .byte pseudo-op. */
1.2087 + if (codep > priv.the_buffer)
1.2088 + {
1.2089 + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
1.2090 + if (name != NULL)
1.2091 + (*info->fprintf_func) (info->stream, "%s", name);
1.2092 + else
1.2093 + {
1.2094 + /* Just print the first byte as a .byte instruction. */
1.2095 + (*info->fprintf_func) (info->stream, ".byte 0x%x",
1.2096 + (unsigned int) priv.the_buffer[0]);
1.2097 + }
1.2098 +
1.2099 + return 1;
1.2100 + }
1.2101 +
1.2102 + return -1;
1.2103 + }
1.2104 +
1.2105 + obufp = obuf;
1.2106 + ckprefix ();
1.2107 +
1.2108 + insn_codep = codep;
1.2109 + sizeflag = priv.orig_sizeflag;
1.2110 +
1.2111 + FETCH_DATA (info, codep + 1);
1.2112 + two_source_ops = (*codep == 0x62) || (*codep == 0xc8);
1.2113 +
1.2114 + if ((prefixes & PREFIX_FWAIT)
1.2115 + && ((*codep < 0xd8) || (*codep > 0xdf)))
1.2116 + {
1.2117 + const char *name;
1.2118 +
1.2119 + /* fwait not followed by floating point instruction. Print the
1.2120 + first prefix, which is probably fwait itself. */
1.2121 + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
1.2122 + if (name == NULL)
1.2123 + name = INTERNAL_DISASSEMBLER_ERROR;
1.2124 + (*info->fprintf_func) (info->stream, "%s", name);
1.2125 + return 1;
1.2126 + }
1.2127 +
1.2128 + if (*codep == 0x0f)
1.2129 + {
1.2130 + FETCH_DATA (info, codep + 2);
1.2131 + dp = &dis386_twobyte[*++codep];
1.2132 + need_modrm = twobyte_has_modrm[*codep];
1.2133 + uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep];
1.2134 + uses_LOCK_prefix = (*codep & ~0x02) == 0x20;
1.2135 + }
1.2136 + else
1.2137 + {
1.2138 + dp = &dis386[*codep];
1.2139 + need_modrm = onebyte_has_modrm[*codep];
1.2140 + uses_SSE_prefix = 0;
1.2141 + uses_LOCK_prefix = 0;
1.2142 + }
1.2143 + codep++;
1.2144 +
1.2145 + if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ))
1.2146 + {
1.2147 + oappend ("repz ");
1.2148 + used_prefixes |= PREFIX_REPZ;
1.2149 + }
1.2150 + if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ))
1.2151 + {
1.2152 + oappend ("repnz ");
1.2153 + used_prefixes |= PREFIX_REPNZ;
1.2154 + }
1.2155 + if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK))
1.2156 + {
1.2157 + oappend ("lock ");
1.2158 + used_prefixes |= PREFIX_LOCK;
1.2159 + }
1.2160 +
1.2161 + if (prefixes & PREFIX_ADDR)
1.2162 + {
1.2163 + sizeflag ^= AFLAG;
1.2164 + if (dp->bytemode3 != loop_jcxz_mode || intel_syntax)
1.2165 + {
1.2166 + if ((sizeflag & AFLAG) || mode_64bit)
1.2167 + oappend ("addr32 ");
1.2168 + else
1.2169 + oappend ("addr16 ");
1.2170 + used_prefixes |= PREFIX_ADDR;
1.2171 + }
1.2172 + }
1.2173 +
1.2174 + if (!uses_SSE_prefix && (prefixes & PREFIX_DATA))
1.2175 + {
1.2176 + sizeflag ^= DFLAG;
1.2177 + if (dp->bytemode3 == cond_jump_mode
1.2178 + && dp->bytemode1 == v_mode
1.2179 + && !intel_syntax)
1.2180 + {
1.2181 + if (sizeflag & DFLAG)
1.2182 + oappend ("data32 ");
1.2183 + else
1.2184 + oappend ("data16 ");
1.2185 + used_prefixes |= PREFIX_DATA;
1.2186 + }
1.2187 + }
1.2188 +
1.2189 + if (need_modrm)
1.2190 + {
1.2191 + FETCH_DATA (info, codep + 1);
1.2192 + mod = (*codep >> 6) & 3;
1.2193 + reg = (*codep >> 3) & 7;
1.2194 + rm = *codep & 7;
1.2195 + }
1.2196 +
1.2197 + if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
1.2198 + {
1.2199 + dofloat (sizeflag);
1.2200 + }
1.2201 + else
1.2202 + {
1.2203 + int index;
1.2204 + if (dp->name == NULL)
1.2205 + {
1.2206 + switch (dp->bytemode1)
1.2207 + {
1.2208 + case USE_GROUPS:
1.2209 + dp = &grps[dp->bytemode2][reg];
1.2210 + break;
1.2211 +
1.2212 + case USE_PREFIX_USER_TABLE:
1.2213 + index = 0;
1.2214 + used_prefixes |= (prefixes & PREFIX_REPZ);
1.2215 + if (prefixes & PREFIX_REPZ)
1.2216 + index = 1;
1.2217 + else
1.2218 + {
1.2219 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2220 + if (prefixes & PREFIX_DATA)
1.2221 + index = 2;
1.2222 + else
1.2223 + {
1.2224 + used_prefixes |= (prefixes & PREFIX_REPNZ);
1.2225 + if (prefixes & PREFIX_REPNZ)
1.2226 + index = 3;
1.2227 + }
1.2228 + }
1.2229 + dp = &prefix_user_table[dp->bytemode2][index];
1.2230 + break;
1.2231 +
1.2232 + case X86_64_SPECIAL:
1.2233 + dp = &x86_64_table[dp->bytemode2][mode_64bit];
1.2234 + break;
1.2235 +
1.2236 + default:
1.2237 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.2238 + break;
1.2239 + }
1.2240 + }
1.2241 +
1.2242 + if (putop (dp->name, sizeflag) == 0)
1.2243 + {
1.2244 + obufp = op1out;
1.2245 + op_ad = 2;
1.2246 + if (dp->op1)
1.2247 + (*dp->op1) (dp->bytemode1, sizeflag);
1.2248 +
1.2249 + obufp = op2out;
1.2250 + op_ad = 1;
1.2251 + if (dp->op2)
1.2252 + (*dp->op2) (dp->bytemode2, sizeflag);
1.2253 +
1.2254 + obufp = op3out;
1.2255 + op_ad = 0;
1.2256 + if (dp->op3)
1.2257 + (*dp->op3) (dp->bytemode3, sizeflag);
1.2258 + }
1.2259 + }
1.2260 +
1.2261 + /* See if any prefixes were not used. If so, print the first one
1.2262 + separately. If we don't do this, we'll wind up printing an
1.2263 + instruction stream which does not precisely correspond to the
1.2264 + bytes we are disassembling. */
1.2265 + if ((prefixes & ~used_prefixes) != 0)
1.2266 + {
1.2267 + const char *name;
1.2268 +
1.2269 + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag);
1.2270 + if (name == NULL)
1.2271 + name = INTERNAL_DISASSEMBLER_ERROR;
1.2272 + (*info->fprintf_func) (info->stream, "%s", name);
1.2273 + return 1;
1.2274 + }
1.2275 + if (rex & ~rex_used)
1.2276 + {
1.2277 + const char *name;
1.2278 + name = prefix_name (rex | 0x40, priv.orig_sizeflag);
1.2279 + if (name == NULL)
1.2280 + name = INTERNAL_DISASSEMBLER_ERROR;
1.2281 + (*info->fprintf_func) (info->stream, "%s ", name);
1.2282 + }
1.2283 +
1.2284 + obufp = obuf + strlen (obuf);
1.2285 + for (i = strlen (obuf); i < 6; i++)
1.2286 + oappend (" ");
1.2287 + oappend (" ");
1.2288 + (*info->fprintf_func) (info->stream, "%s", obuf);
1.2289 +
1.2290 + /* The enter and bound instructions are printed with operands in the same
1.2291 + order as the intel book; everything else is printed in reverse order. */
1.2292 + if (intel_syntax || two_source_ops)
1.2293 + {
1.2294 + first = op1out;
1.2295 + second = op2out;
1.2296 + third = op3out;
1.2297 + op_ad = op_index[0];
1.2298 + op_index[0] = op_index[2];
1.2299 + op_index[2] = op_ad;
1.2300 + }
1.2301 + else
1.2302 + {
1.2303 + first = op3out;
1.2304 + second = op2out;
1.2305 + third = op1out;
1.2306 + }
1.2307 + needcomma = 0;
1.2308 + if (*first)
1.2309 + {
1.2310 + if (op_index[0] != -1 && !op_riprel[0])
1.2311 + (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info);
1.2312 + else
1.2313 + (*info->fprintf_func) (info->stream, "%s", first);
1.2314 + needcomma = 1;
1.2315 + }
1.2316 + if (*second)
1.2317 + {
1.2318 + if (needcomma)
1.2319 + (*info->fprintf_func) (info->stream, ",");
1.2320 + if (op_index[1] != -1 && !op_riprel[1])
1.2321 + (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info);
1.2322 + else
1.2323 + (*info->fprintf_func) (info->stream, "%s", second);
1.2324 + needcomma = 1;
1.2325 + }
1.2326 + if (*third)
1.2327 + {
1.2328 + if (needcomma)
1.2329 + (*info->fprintf_func) (info->stream, ",");
1.2330 + if (op_index[2] != -1 && !op_riprel[2])
1.2331 + (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info);
1.2332 + else
1.2333 + (*info->fprintf_func) (info->stream, "%s", third);
1.2334 + }
1.2335 + for (i = 0; i < 3; i++)
1.2336 + if (op_index[i] != -1 && op_riprel[i])
1.2337 + {
1.2338 + (*info->fprintf_func) (info->stream, " # ");
1.2339 + (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep
1.2340 + + op_address[op_index[i]]), info);
1.2341 + }
1.2342 + return codep - priv.the_buffer;
1.2343 +}
1.2344 +
1.2345 +static const char *float_mem[] = {
1.2346 + /* d8 */
1.2347 + "fadd{s||s|}",
1.2348 + "fmul{s||s|}",
1.2349 + "fcom{s||s|}",
1.2350 + "fcomp{s||s|}",
1.2351 + "fsub{s||s|}",
1.2352 + "fsubr{s||s|}",
1.2353 + "fdiv{s||s|}",
1.2354 + "fdivr{s||s|}",
1.2355 + /* d9 */
1.2356 + "fld{s||s|}",
1.2357 + "(bad)",
1.2358 + "fst{s||s|}",
1.2359 + "fstp{s||s|}",
1.2360 + "fldenvIC",
1.2361 + "fldcw",
1.2362 + "fNstenvIC",
1.2363 + "fNstcw",
1.2364 + /* da */
1.2365 + "fiadd{l||l|}",
1.2366 + "fimul{l||l|}",
1.2367 + "ficom{l||l|}",
1.2368 + "ficomp{l||l|}",
1.2369 + "fisub{l||l|}",
1.2370 + "fisubr{l||l|}",
1.2371 + "fidiv{l||l|}",
1.2372 + "fidivr{l||l|}",
1.2373 + /* db */
1.2374 + "fild{l||l|}",
1.2375 + "fisttp{l||l|}",
1.2376 + "fist{l||l|}",
1.2377 + "fistp{l||l|}",
1.2378 + "(bad)",
1.2379 + "fld{t||t|}",
1.2380 + "(bad)",
1.2381 + "fstp{t||t|}",
1.2382 + /* dc */
1.2383 + "fadd{l||l|}",
1.2384 + "fmul{l||l|}",
1.2385 + "fcom{l||l|}",
1.2386 + "fcomp{l||l|}",
1.2387 + "fsub{l||l|}",
1.2388 + "fsubr{l||l|}",
1.2389 + "fdiv{l||l|}",
1.2390 + "fdivr{l||l|}",
1.2391 + /* dd */
1.2392 + "fld{l||l|}",
1.2393 + "fisttp{ll||ll|}",
1.2394 + "fst{l||l|}",
1.2395 + "fstp{l||l|}",
1.2396 + "frstorIC",
1.2397 + "(bad)",
1.2398 + "fNsaveIC",
1.2399 + "fNstsw",
1.2400 + /* de */
1.2401 + "fiadd",
1.2402 + "fimul",
1.2403 + "ficom",
1.2404 + "ficomp",
1.2405 + "fisub",
1.2406 + "fisubr",
1.2407 + "fidiv",
1.2408 + "fidivr",
1.2409 + /* df */
1.2410 + "fild",
1.2411 + "fisttp",
1.2412 + "fist",
1.2413 + "fistp",
1.2414 + "fbld",
1.2415 + "fild{ll||ll|}",
1.2416 + "fbstp",
1.2417 + "fistp{ll||ll|}",
1.2418 +};
1.2419 +
1.2420 +static const unsigned char float_mem_mode[] = {
1.2421 + /* d8 */
1.2422 + d_mode,
1.2423 + d_mode,
1.2424 + d_mode,
1.2425 + d_mode,
1.2426 + d_mode,
1.2427 + d_mode,
1.2428 + d_mode,
1.2429 + d_mode,
1.2430 + /* d9 */
1.2431 + d_mode,
1.2432 + 0,
1.2433 + d_mode,
1.2434 + d_mode,
1.2435 + 0,
1.2436 + w_mode,
1.2437 + 0,
1.2438 + w_mode,
1.2439 + /* da */
1.2440 + d_mode,
1.2441 + d_mode,
1.2442 + d_mode,
1.2443 + d_mode,
1.2444 + d_mode,
1.2445 + d_mode,
1.2446 + d_mode,
1.2447 + d_mode,
1.2448 + /* db */
1.2449 + d_mode,
1.2450 + d_mode,
1.2451 + d_mode,
1.2452 + d_mode,
1.2453 + 0,
1.2454 + t_mode,
1.2455 + 0,
1.2456 + t_mode,
1.2457 + /* dc */
1.2458 + q_mode,
1.2459 + q_mode,
1.2460 + q_mode,
1.2461 + q_mode,
1.2462 + q_mode,
1.2463 + q_mode,
1.2464 + q_mode,
1.2465 + q_mode,
1.2466 + /* dd */
1.2467 + q_mode,
1.2468 + q_mode,
1.2469 + q_mode,
1.2470 + q_mode,
1.2471 + 0,
1.2472 + 0,
1.2473 + 0,
1.2474 + w_mode,
1.2475 + /* de */
1.2476 + w_mode,
1.2477 + w_mode,
1.2478 + w_mode,
1.2479 + w_mode,
1.2480 + w_mode,
1.2481 + w_mode,
1.2482 + w_mode,
1.2483 + w_mode,
1.2484 + /* df */
1.2485 + w_mode,
1.2486 + w_mode,
1.2487 + w_mode,
1.2488 + w_mode,
1.2489 + t_mode,
1.2490 + q_mode,
1.2491 + t_mode,
1.2492 + q_mode
1.2493 +};
1.2494 +
1.2495 +#define ST OP_ST, 0
1.2496 +#define STi OP_STi, 0
1.2497 +
1.2498 +#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0
1.2499 +#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0
1.2500 +#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0
1.2501 +#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0
1.2502 +#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0
1.2503 +#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0
1.2504 +#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0
1.2505 +#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0
1.2506 +#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0
1.2507 +
1.2508 +static const struct dis386 float_reg[][8] = {
1.2509 + /* d8 */
1.2510 + {
1.2511 + { "fadd", ST, STi, XX },
1.2512 + { "fmul", ST, STi, XX },
1.2513 + { "fcom", STi, XX, XX },
1.2514 + { "fcomp", STi, XX, XX },
1.2515 + { "fsub", ST, STi, XX },
1.2516 + { "fsubr", ST, STi, XX },
1.2517 + { "fdiv", ST, STi, XX },
1.2518 + { "fdivr", ST, STi, XX },
1.2519 + },
1.2520 + /* d9 */
1.2521 + {
1.2522 + { "fld", STi, XX, XX },
1.2523 + { "fxch", STi, XX, XX },
1.2524 + { FGRPd9_2 },
1.2525 + { "(bad)", XX, XX, XX },
1.2526 + { FGRPd9_4 },
1.2527 + { FGRPd9_5 },
1.2528 + { FGRPd9_6 },
1.2529 + { FGRPd9_7 },
1.2530 + },
1.2531 + /* da */
1.2532 + {
1.2533 + { "fcmovb", ST, STi, XX },
1.2534 + { "fcmove", ST, STi, XX },
1.2535 + { "fcmovbe",ST, STi, XX },
1.2536 + { "fcmovu", ST, STi, XX },
1.2537 + { "(bad)", XX, XX, XX },
1.2538 + { FGRPda_5 },
1.2539 + { "(bad)", XX, XX, XX },
1.2540 + { "(bad)", XX, XX, XX },
1.2541 + },
1.2542 + /* db */
1.2543 + {
1.2544 + { "fcmovnb",ST, STi, XX },
1.2545 + { "fcmovne",ST, STi, XX },
1.2546 + { "fcmovnbe",ST, STi, XX },
1.2547 + { "fcmovnu",ST, STi, XX },
1.2548 + { FGRPdb_4 },
1.2549 + { "fucomi", ST, STi, XX },
1.2550 + { "fcomi", ST, STi, XX },
1.2551 + { "(bad)", XX, XX, XX },
1.2552 + },
1.2553 + /* dc */
1.2554 + {
1.2555 + { "fadd", STi, ST, XX },
1.2556 + { "fmul", STi, ST, XX },
1.2557 + { "(bad)", XX, XX, XX },
1.2558 + { "(bad)", XX, XX, XX },
1.2559 +#if UNIXWARE_COMPAT
1.2560 + { "fsub", STi, ST, XX },
1.2561 + { "fsubr", STi, ST, XX },
1.2562 + { "fdiv", STi, ST, XX },
1.2563 + { "fdivr", STi, ST, XX },
1.2564 +#else
1.2565 + { "fsubr", STi, ST, XX },
1.2566 + { "fsub", STi, ST, XX },
1.2567 + { "fdivr", STi, ST, XX },
1.2568 + { "fdiv", STi, ST, XX },
1.2569 +#endif
1.2570 + },
1.2571 + /* dd */
1.2572 + {
1.2573 + { "ffree", STi, XX, XX },
1.2574 + { "(bad)", XX, XX, XX },
1.2575 + { "fst", STi, XX, XX },
1.2576 + { "fstp", STi, XX, XX },
1.2577 + { "fucom", STi, XX, XX },
1.2578 + { "fucomp", STi, XX, XX },
1.2579 + { "(bad)", XX, XX, XX },
1.2580 + { "(bad)", XX, XX, XX },
1.2581 + },
1.2582 + /* de */
1.2583 + {
1.2584 + { "faddp", STi, ST, XX },
1.2585 + { "fmulp", STi, ST, XX },
1.2586 + { "(bad)", XX, XX, XX },
1.2587 + { FGRPde_3 },
1.2588 +#if UNIXWARE_COMPAT
1.2589 + { "fsubp", STi, ST, XX },
1.2590 + { "fsubrp", STi, ST, XX },
1.2591 + { "fdivp", STi, ST, XX },
1.2592 + { "fdivrp", STi, ST, XX },
1.2593 +#else
1.2594 + { "fsubrp", STi, ST, XX },
1.2595 + { "fsubp", STi, ST, XX },
1.2596 + { "fdivrp", STi, ST, XX },
1.2597 + { "fdivp", STi, ST, XX },
1.2598 +#endif
1.2599 + },
1.2600 + /* df */
1.2601 + {
1.2602 + { "ffreep", STi, XX, XX },
1.2603 + { "(bad)", XX, XX, XX },
1.2604 + { "(bad)", XX, XX, XX },
1.2605 + { "(bad)", XX, XX, XX },
1.2606 + { FGRPdf_4 },
1.2607 + { "fucomip",ST, STi, XX },
1.2608 + { "fcomip", ST, STi, XX },
1.2609 + { "(bad)", XX, XX, XX },
1.2610 + },
1.2611 +};
1.2612 +
1.2613 +static char *fgrps[][8] = {
1.2614 + /* d9_2 0 */
1.2615 + {
1.2616 + "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1.2617 + },
1.2618 +
1.2619 + /* d9_4 1 */
1.2620 + {
1.2621 + "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
1.2622 + },
1.2623 +
1.2624 + /* d9_5 2 */
1.2625 + {
1.2626 + "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
1.2627 + },
1.2628 +
1.2629 + /* d9_6 3 */
1.2630 + {
1.2631 + "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
1.2632 + },
1.2633 +
1.2634 + /* d9_7 4 */
1.2635 + {
1.2636 + "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
1.2637 + },
1.2638 +
1.2639 + /* da_5 5 */
1.2640 + {
1.2641 + "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1.2642 + },
1.2643 +
1.2644 + /* db_4 6 */
1.2645 + {
1.2646 + "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
1.2647 + "fNsetpm(287 only)","(bad)","(bad)","(bad)",
1.2648 + },
1.2649 +
1.2650 + /* de_3 7 */
1.2651 + {
1.2652 + "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1.2653 + },
1.2654 +
1.2655 + /* df_4 8 */
1.2656 + {
1.2657 + "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
1.2658 + },
1.2659 +};
1.2660 +
1.2661 +static void
1.2662 +dofloat (int sizeflag)
1.2663 +{
1.2664 + const struct dis386 *dp;
1.2665 + unsigned char floatop;
1.2666 +
1.2667 + floatop = codep[-1];
1.2668 +
1.2669 + if (mod != 3)
1.2670 + {
1.2671 + int fp_indx = (floatop - 0xd8) * 8 + reg;
1.2672 +
1.2673 + putop (float_mem[fp_indx], sizeflag);
1.2674 + obufp = op1out;
1.2675 + OP_E (float_mem_mode[fp_indx], sizeflag);
1.2676 + return;
1.2677 + }
1.2678 + /* Skip mod/rm byte. */
1.2679 + MODRM_CHECK;
1.2680 + codep++;
1.2681 +
1.2682 + dp = &float_reg[floatop - 0xd8][reg];
1.2683 + if (dp->name == NULL)
1.2684 + {
1.2685 + putop (fgrps[dp->bytemode1][rm], sizeflag);
1.2686 +
1.2687 + /* Instruction fnstsw is only one with strange arg. */
1.2688 + if (floatop == 0xdf && codep[-1] == 0xe0)
1.2689 + strcpy (op1out, names16[0]);
1.2690 + }
1.2691 + else
1.2692 + {
1.2693 + putop (dp->name, sizeflag);
1.2694 +
1.2695 + obufp = op1out;
1.2696 + if (dp->op1)
1.2697 + (*dp->op1) (dp->bytemode1, sizeflag);
1.2698 + obufp = op2out;
1.2699 + if (dp->op2)
1.2700 + (*dp->op2) (dp->bytemode2, sizeflag);
1.2701 + }
1.2702 +}
1.2703 +
1.2704 +static void
1.2705 +OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.2706 +{
1.2707 + oappend ("%st");
1.2708 +}
1.2709 +
1.2710 +static void
1.2711 +OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.2712 +{
1.2713 + sprintf (scratchbuf, "%%st(%d)", rm);
1.2714 + oappend (scratchbuf + intel_syntax);
1.2715 +}
1.2716 +
1.2717 +/* Capital letters in template are macros. */
1.2718 +static int
1.2719 +putop (const char *template, int sizeflag)
1.2720 +{
1.2721 + const char *p;
1.2722 + int alt = 0;
1.2723 +
1.2724 + for (p = template; *p; p++)
1.2725 + {
1.2726 + switch (*p)
1.2727 + {
1.2728 + default:
1.2729 + *obufp++ = *p;
1.2730 + break;
1.2731 + case '{':
1.2732 + alt = 0;
1.2733 + if (intel_syntax)
1.2734 + alt += 1;
1.2735 + if (mode_64bit)
1.2736 + alt += 2;
1.2737 + while (alt != 0)
1.2738 + {
1.2739 + while (*++p != '|')
1.2740 + {
1.2741 + if (*p == '}')
1.2742 + {
1.2743 + /* Alternative not valid. */
1.2744 + strcpy (obuf, "(bad)");
1.2745 + obufp = obuf + 5;
1.2746 + return 1;
1.2747 + }
1.2748 + else if (*p == '\0')
1.2749 + abort ();
1.2750 + }
1.2751 + alt--;
1.2752 + }
1.2753 + /* Fall through. */
1.2754 + case 'I':
1.2755 + alt = 1;
1.2756 + continue;
1.2757 + case '|':
1.2758 + while (*++p != '}')
1.2759 + {
1.2760 + if (*p == '\0')
1.2761 + abort ();
1.2762 + }
1.2763 + break;
1.2764 + case '}':
1.2765 + break;
1.2766 + case 'A':
1.2767 + if (intel_syntax)
1.2768 + break;
1.2769 + if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
1.2770 + *obufp++ = 'b';
1.2771 + break;
1.2772 + case 'B':
1.2773 + if (intel_syntax)
1.2774 + break;
1.2775 + if (sizeflag & SUFFIX_ALWAYS)
1.2776 + *obufp++ = 'b';
1.2777 + break;
1.2778 + case 'C':
1.2779 + if (intel_syntax && !alt)
1.2780 + break;
1.2781 + if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS))
1.2782 + {
1.2783 + if (sizeflag & DFLAG)
1.2784 + *obufp++ = intel_syntax ? 'd' : 'l';
1.2785 + else
1.2786 + *obufp++ = intel_syntax ? 'w' : 's';
1.2787 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2788 + }
1.2789 + break;
1.2790 + case 'E': /* For jcxz/jecxz */
1.2791 + if (mode_64bit)
1.2792 + {
1.2793 + if (sizeflag & AFLAG)
1.2794 + *obufp++ = 'r';
1.2795 + else
1.2796 + *obufp++ = 'e';
1.2797 + }
1.2798 + else
1.2799 + if (sizeflag & AFLAG)
1.2800 + *obufp++ = 'e';
1.2801 + used_prefixes |= (prefixes & PREFIX_ADDR);
1.2802 + break;
1.2803 + case 'F':
1.2804 + if (intel_syntax)
1.2805 + break;
1.2806 + if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS))
1.2807 + {
1.2808 + if (sizeflag & AFLAG)
1.2809 + *obufp++ = mode_64bit ? 'q' : 'l';
1.2810 + else
1.2811 + *obufp++ = mode_64bit ? 'l' : 'w';
1.2812 + used_prefixes |= (prefixes & PREFIX_ADDR);
1.2813 + }
1.2814 + break;
1.2815 + case 'H':
1.2816 + if (intel_syntax)
1.2817 + break;
1.2818 + if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS
1.2819 + || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS)
1.2820 + {
1.2821 + used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS);
1.2822 + *obufp++ = ',';
1.2823 + *obufp++ = 'p';
1.2824 + if (prefixes & PREFIX_DS)
1.2825 + *obufp++ = 't';
1.2826 + else
1.2827 + *obufp++ = 'n';
1.2828 + }
1.2829 + break;
1.2830 + case 'J':
1.2831 + if (intel_syntax)
1.2832 + break;
1.2833 + *obufp++ = 'l';
1.2834 + break;
1.2835 + case 'L':
1.2836 + if (intel_syntax)
1.2837 + break;
1.2838 + if (sizeflag & SUFFIX_ALWAYS)
1.2839 + *obufp++ = 'l';
1.2840 + break;
1.2841 + case 'N':
1.2842 + if ((prefixes & PREFIX_FWAIT) == 0)
1.2843 + *obufp++ = 'n';
1.2844 + else
1.2845 + used_prefixes |= PREFIX_FWAIT;
1.2846 + break;
1.2847 + case 'O':
1.2848 + USED_REX (REX_MODE64);
1.2849 + if (rex & REX_MODE64)
1.2850 + *obufp++ = 'o';
1.2851 + else
1.2852 + *obufp++ = 'd';
1.2853 + break;
1.2854 + case 'T':
1.2855 + if (intel_syntax)
1.2856 + break;
1.2857 + if (mode_64bit)
1.2858 + {
1.2859 + *obufp++ = 'q';
1.2860 + break;
1.2861 + }
1.2862 + /* Fall through. */
1.2863 + case 'P':
1.2864 + if (intel_syntax)
1.2865 + break;
1.2866 + if ((prefixes & PREFIX_DATA)
1.2867 + || (rex & REX_MODE64)
1.2868 + || (sizeflag & SUFFIX_ALWAYS))
1.2869 + {
1.2870 + USED_REX (REX_MODE64);
1.2871 + if (rex & REX_MODE64)
1.2872 + *obufp++ = 'q';
1.2873 + else
1.2874 + {
1.2875 + if (sizeflag & DFLAG)
1.2876 + *obufp++ = 'l';
1.2877 + else
1.2878 + *obufp++ = 'w';
1.2879 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2880 + }
1.2881 + }
1.2882 + break;
1.2883 + case 'U':
1.2884 + if (intel_syntax)
1.2885 + break;
1.2886 + if (mode_64bit)
1.2887 + {
1.2888 + *obufp++ = 'q';
1.2889 + break;
1.2890 + }
1.2891 + /* Fall through. */
1.2892 + case 'Q':
1.2893 + if (intel_syntax && !alt)
1.2894 + break;
1.2895 + USED_REX (REX_MODE64);
1.2896 + if (mod != 3 || (sizeflag & SUFFIX_ALWAYS))
1.2897 + {
1.2898 + if (rex & REX_MODE64)
1.2899 + *obufp++ = 'q';
1.2900 + else
1.2901 + {
1.2902 + if (sizeflag & DFLAG)
1.2903 + *obufp++ = intel_syntax ? 'd' : 'l';
1.2904 + else
1.2905 + *obufp++ = 'w';
1.2906 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2907 + }
1.2908 + }
1.2909 + break;
1.2910 + case 'R':
1.2911 + USED_REX (REX_MODE64);
1.2912 + if (intel_syntax)
1.2913 + {
1.2914 + if (rex & REX_MODE64)
1.2915 + {
1.2916 + *obufp++ = 'q';
1.2917 + *obufp++ = 't';
1.2918 + }
1.2919 + else if (sizeflag & DFLAG)
1.2920 + {
1.2921 + *obufp++ = 'd';
1.2922 + *obufp++ = 'q';
1.2923 + }
1.2924 + else
1.2925 + {
1.2926 + *obufp++ = 'w';
1.2927 + *obufp++ = 'd';
1.2928 + }
1.2929 + }
1.2930 + else
1.2931 + {
1.2932 + if (rex & REX_MODE64)
1.2933 + *obufp++ = 'q';
1.2934 + else if (sizeflag & DFLAG)
1.2935 + *obufp++ = 'l';
1.2936 + else
1.2937 + *obufp++ = 'w';
1.2938 + }
1.2939 + if (!(rex & REX_MODE64))
1.2940 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2941 + break;
1.2942 + case 'S':
1.2943 + if (intel_syntax)
1.2944 + break;
1.2945 + if (sizeflag & SUFFIX_ALWAYS)
1.2946 + {
1.2947 + if (rex & REX_MODE64)
1.2948 + *obufp++ = 'q';
1.2949 + else
1.2950 + {
1.2951 + if (sizeflag & DFLAG)
1.2952 + *obufp++ = 'l';
1.2953 + else
1.2954 + *obufp++ = 'w';
1.2955 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2956 + }
1.2957 + }
1.2958 + break;
1.2959 + case 'X':
1.2960 + if (prefixes & PREFIX_DATA)
1.2961 + *obufp++ = 'd';
1.2962 + else
1.2963 + *obufp++ = 's';
1.2964 + used_prefixes |= (prefixes & PREFIX_DATA);
1.2965 + break;
1.2966 + case 'Y':
1.2967 + if (intel_syntax)
1.2968 + break;
1.2969 + if (rex & REX_MODE64)
1.2970 + {
1.2971 + USED_REX (REX_MODE64);
1.2972 + *obufp++ = 'q';
1.2973 + }
1.2974 + break;
1.2975 + /* implicit operand size 'l' for i386 or 'q' for x86-64 */
1.2976 + case 'W':
1.2977 + /* operand size flag for cwtl, cbtw */
1.2978 + USED_REX (0);
1.2979 + if (rex)
1.2980 + *obufp++ = 'l';
1.2981 + else if (sizeflag & DFLAG)
1.2982 + *obufp++ = 'w';
1.2983 + else
1.2984 + *obufp++ = 'b';
1.2985 + if (intel_syntax)
1.2986 + {
1.2987 + if (rex)
1.2988 + {
1.2989 + *obufp++ = 'q';
1.2990 + *obufp++ = 'e';
1.2991 + }
1.2992 + if (sizeflag & DFLAG)
1.2993 + {
1.2994 + *obufp++ = 'd';
1.2995 + *obufp++ = 'e';
1.2996 + }
1.2997 + else
1.2998 + {
1.2999 + *obufp++ = 'w';
1.3000 + }
1.3001 + }
1.3002 + if (!rex)
1.3003 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3004 + break;
1.3005 + }
1.3006 + alt = 0;
1.3007 + }
1.3008 + *obufp = 0;
1.3009 + return 0;
1.3010 +}
1.3011 +
1.3012 +static void
1.3013 +oappend (const char *s)
1.3014 +{
1.3015 + strcpy (obufp, s);
1.3016 + obufp += strlen (s);
1.3017 +}
1.3018 +
1.3019 +static void
1.3020 +append_seg (void)
1.3021 +{
1.3022 + if (prefixes & PREFIX_CS)
1.3023 + {
1.3024 + used_prefixes |= PREFIX_CS;
1.3025 + oappend ("%cs:" + intel_syntax);
1.3026 + }
1.3027 + if (prefixes & PREFIX_DS)
1.3028 + {
1.3029 + used_prefixes |= PREFIX_DS;
1.3030 + oappend ("%ds:" + intel_syntax);
1.3031 + }
1.3032 + if (prefixes & PREFIX_SS)
1.3033 + {
1.3034 + used_prefixes |= PREFIX_SS;
1.3035 + oappend ("%ss:" + intel_syntax);
1.3036 + }
1.3037 + if (prefixes & PREFIX_ES)
1.3038 + {
1.3039 + used_prefixes |= PREFIX_ES;
1.3040 + oappend ("%es:" + intel_syntax);
1.3041 + }
1.3042 + if (prefixes & PREFIX_FS)
1.3043 + {
1.3044 + used_prefixes |= PREFIX_FS;
1.3045 + oappend ("%fs:" + intel_syntax);
1.3046 + }
1.3047 + if (prefixes & PREFIX_GS)
1.3048 + {
1.3049 + used_prefixes |= PREFIX_GS;
1.3050 + oappend ("%gs:" + intel_syntax);
1.3051 + }
1.3052 +}
1.3053 +
1.3054 +static void
1.3055 +OP_indirE (int bytemode, int sizeflag)
1.3056 +{
1.3057 + if (!intel_syntax)
1.3058 + oappend ("*");
1.3059 + OP_E (bytemode, sizeflag);
1.3060 +}
1.3061 +
1.3062 +static void
1.3063 +OP_E (int bytemode, int sizeflag)
1.3064 +{
1.3065 + bfd_vma disp;
1.3066 + int add = 0;
1.3067 + int riprel = 0;
1.3068 + USED_REX (REX_EXTZ);
1.3069 + if (rex & REX_EXTZ)
1.3070 + add += 8;
1.3071 +
1.3072 + /* Skip mod/rm byte. */
1.3073 + MODRM_CHECK;
1.3074 + codep++;
1.3075 +
1.3076 + if (mod == 3)
1.3077 + {
1.3078 + switch (bytemode)
1.3079 + {
1.3080 + case b_mode:
1.3081 + USED_REX (0);
1.3082 + if (rex)
1.3083 + oappend (names8rex[rm + add]);
1.3084 + else
1.3085 + oappend (names8[rm + add]);
1.3086 + break;
1.3087 + case w_mode:
1.3088 + oappend (names16[rm + add]);
1.3089 + break;
1.3090 + case d_mode:
1.3091 + oappend (names32[rm + add]);
1.3092 + break;
1.3093 + case q_mode:
1.3094 + oappend (names64[rm + add]);
1.3095 + break;
1.3096 + case m_mode:
1.3097 + if (mode_64bit)
1.3098 + oappend (names64[rm + add]);
1.3099 + else
1.3100 + oappend (names32[rm + add]);
1.3101 + break;
1.3102 + case v_mode:
1.3103 + case dq_mode:
1.3104 + case dqw_mode:
1.3105 + USED_REX (REX_MODE64);
1.3106 + if (rex & REX_MODE64)
1.3107 + oappend (names64[rm + add]);
1.3108 + else if ((sizeflag & DFLAG) || bytemode != v_mode)
1.3109 + oappend (names32[rm + add]);
1.3110 + else
1.3111 + oappend (names16[rm + add]);
1.3112 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3113 + break;
1.3114 + case 0:
1.3115 + break;
1.3116 + default:
1.3117 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3118 + break;
1.3119 + }
1.3120 + return;
1.3121 + }
1.3122 +
1.3123 + disp = 0;
1.3124 + append_seg ();
1.3125 +
1.3126 + if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */
1.3127 + {
1.3128 + int havesib;
1.3129 + int havebase;
1.3130 + int base;
1.3131 + int index = 0;
1.3132 + int scale = 0;
1.3133 +
1.3134 + havesib = 0;
1.3135 + havebase = 1;
1.3136 + base = rm;
1.3137 +
1.3138 + if (base == 4)
1.3139 + {
1.3140 + havesib = 1;
1.3141 + FETCH_DATA (the_info, codep + 1);
1.3142 + index = (*codep >> 3) & 7;
1.3143 + if (mode_64bit || index != 0x4)
1.3144 + /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored. */
1.3145 + scale = (*codep >> 6) & 3;
1.3146 + base = *codep & 7;
1.3147 + USED_REX (REX_EXTY);
1.3148 + USED_REX (REX_EXTZ);
1.3149 + if (rex & REX_EXTY)
1.3150 + index += 8;
1.3151 + if (rex & REX_EXTZ)
1.3152 + base += 8;
1.3153 + codep++;
1.3154 + }
1.3155 +
1.3156 + switch (mod)
1.3157 + {
1.3158 + case 0:
1.3159 + if ((base & 7) == 5)
1.3160 + {
1.3161 + havebase = 0;
1.3162 + if (mode_64bit && !havesib)
1.3163 + riprel = 1;
1.3164 + disp = get32s ();
1.3165 + }
1.3166 + break;
1.3167 + case 1:
1.3168 + FETCH_DATA (the_info, codep + 1);
1.3169 + disp = *codep++;
1.3170 + if ((disp & 0x80) != 0)
1.3171 + disp -= 0x100;
1.3172 + break;
1.3173 + case 2:
1.3174 + disp = get32s ();
1.3175 + break;
1.3176 + }
1.3177 +
1.3178 + if (!intel_syntax)
1.3179 + if (mod != 0 || (base & 7) == 5)
1.3180 + {
1.3181 + xlat_print_symbolic_operand (scratchbuf, !riprel, disp);
1.3182 + oappend (scratchbuf);
1.3183 + if (riprel)
1.3184 + {
1.3185 + set_op (disp, 1);
1.3186 + oappend ("(%rip)");
1.3187 + }
1.3188 + }
1.3189 +
1.3190 + if (havebase || (havesib && (index != 4 || scale != 0)))
1.3191 + {
1.3192 + if (intel_syntax)
1.3193 + {
1.3194 + switch (bytemode)
1.3195 + {
1.3196 + case b_mode:
1.3197 + oappend ("BYTE PTR ");
1.3198 + break;
1.3199 + case w_mode:
1.3200 + case dqw_mode:
1.3201 + oappend ("WORD PTR ");
1.3202 + break;
1.3203 + case v_mode:
1.3204 + case dq_mode:
1.3205 + USED_REX (REX_MODE64);
1.3206 + if (rex & REX_MODE64)
1.3207 + oappend ("QWORD PTR ");
1.3208 + else if ((sizeflag & DFLAG) || bytemode == dq_mode)
1.3209 + oappend ("DWORD PTR ");
1.3210 + else
1.3211 + oappend ("WORD PTR ");
1.3212 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3213 + break;
1.3214 + case d_mode:
1.3215 + oappend ("DWORD PTR ");
1.3216 + break;
1.3217 + case q_mode:
1.3218 + oappend ("QWORD PTR ");
1.3219 + break;
1.3220 + case m_mode:
1.3221 + if (mode_64bit)
1.3222 + oappend ("QWORD PTR ");
1.3223 + else
1.3224 + oappend ("DWORD PTR ");
1.3225 + break;
1.3226 + case f_mode:
1.3227 + if (sizeflag & DFLAG)
1.3228 + {
1.3229 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3230 + oappend ("FWORD PTR ");
1.3231 + }
1.3232 + else
1.3233 + oappend ("DWORD PTR ");
1.3234 + break;
1.3235 + case t_mode:
1.3236 + oappend ("TBYTE PTR ");
1.3237 + break;
1.3238 + case x_mode:
1.3239 + oappend ("XMMWORD PTR ");
1.3240 + break;
1.3241 + default:
1.3242 + break;
1.3243 + }
1.3244 + }
1.3245 + *obufp++ = open_char;
1.3246 + if (intel_syntax && riprel)
1.3247 + oappend ("rip + ");
1.3248 + *obufp = '\0';
1.3249 + USED_REX (REX_EXTZ);
1.3250 + if (!havesib && (rex & REX_EXTZ))
1.3251 + base += 8;
1.3252 + if (havebase)
1.3253 + oappend (mode_64bit && (sizeflag & AFLAG)
1.3254 + ? names64[base] : names32[base]);
1.3255 + if (havesib)
1.3256 + {
1.3257 + if (index != 4)
1.3258 + {
1.3259 + if (!intel_syntax || havebase)
1.3260 + {
1.3261 + *obufp++ = separator_char;
1.3262 + *obufp = '\0';
1.3263 + }
1.3264 + oappend (mode_64bit && (sizeflag & AFLAG)
1.3265 + ? names64[index] : names32[index]);
1.3266 + }
1.3267 + if (scale != 0 || (!intel_syntax && index != 4))
1.3268 + {
1.3269 + *obufp++ = scale_char;
1.3270 + *obufp = '\0';
1.3271 + sprintf (scratchbuf, "%d", 1 << scale);
1.3272 + oappend (scratchbuf);
1.3273 + }
1.3274 + }
1.3275 + if (intel_syntax)
1.3276 + if (mod != 0 || (base & 7) == 5)
1.3277 + {
1.3278 + /* Don't print zero displacements. */
1.3279 + if (disp != 0)
1.3280 + {
1.3281 + if ((bfd_signed_vma) disp > 0)
1.3282 + {
1.3283 + *obufp++ = '+';
1.3284 + *obufp = '\0';
1.3285 + }
1.3286 +
1.3287 + xlat_print_symbolic_operand (scratchbuf, 0, disp);
1.3288 + oappend (scratchbuf);
1.3289 + }
1.3290 + }
1.3291 +
1.3292 + *obufp++ = close_char;
1.3293 + *obufp = '\0';
1.3294 + }
1.3295 + else if (intel_syntax)
1.3296 + {
1.3297 + if (mod != 0 || (base & 7) == 5)
1.3298 + {
1.3299 + if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
1.3300 + | PREFIX_ES | PREFIX_FS | PREFIX_GS))
1.3301 + ;
1.3302 + else
1.3303 + {
1.3304 + oappend (names_seg[ds_reg - es_reg]);
1.3305 + oappend (":");
1.3306 + }
1.3307 + xlat_print_symbolic_operand (scratchbuf, 1, disp);
1.3308 + oappend (scratchbuf);
1.3309 + }
1.3310 + }
1.3311 + }
1.3312 + else
1.3313 + { /* 16 bit address mode */
1.3314 + switch (mod)
1.3315 + {
1.3316 + case 0:
1.3317 + if ((rm & 7) == 6)
1.3318 + {
1.3319 + disp = get16 ();
1.3320 + if ((disp & 0x8000) != 0)
1.3321 + disp -= 0x10000;
1.3322 + }
1.3323 + break;
1.3324 + case 1:
1.3325 + FETCH_DATA (the_info, codep + 1);
1.3326 + disp = *codep++;
1.3327 + if ((disp & 0x80) != 0)
1.3328 + disp -= 0x100;
1.3329 + break;
1.3330 + case 2:
1.3331 + disp = get16 ();
1.3332 + if ((disp & 0x8000) != 0)
1.3333 + disp -= 0x10000;
1.3334 + break;
1.3335 + }
1.3336 +
1.3337 + if (!intel_syntax)
1.3338 + if (mod != 0 || (rm & 7) == 6)
1.3339 + {
1.3340 + xlat_print_symbolic_operand (scratchbuf, 0, disp);
1.3341 + oappend (scratchbuf);
1.3342 + }
1.3343 +
1.3344 + if (mod != 0 || (rm & 7) != 6)
1.3345 + {
1.3346 + *obufp++ = open_char;
1.3347 + *obufp = '\0';
1.3348 + oappend (index16[rm + add]);
1.3349 + *obufp++ = close_char;
1.3350 + *obufp = '\0';
1.3351 + }
1.3352 + }
1.3353 +}
1.3354 +
1.3355 +static void
1.3356 +OP_G (int bytemode, int sizeflag)
1.3357 +{
1.3358 + int add = 0;
1.3359 + USED_REX (REX_EXTX);
1.3360 + if (rex & REX_EXTX)
1.3361 + add += 8;
1.3362 + switch (bytemode)
1.3363 + {
1.3364 + case b_mode:
1.3365 + USED_REX (0);
1.3366 + if (rex)
1.3367 + oappend (names8rex[reg + add]);
1.3368 + else
1.3369 + oappend (names8[reg + add]);
1.3370 + break;
1.3371 + case w_mode:
1.3372 + oappend (names16[reg + add]);
1.3373 + break;
1.3374 + case d_mode:
1.3375 + oappend (names32[reg + add]);
1.3376 + break;
1.3377 + case q_mode:
1.3378 + oappend (names64[reg + add]);
1.3379 + break;
1.3380 + case v_mode:
1.3381 + case dq_mode:
1.3382 + case dqw_mode:
1.3383 + USED_REX (REX_MODE64);
1.3384 + if (rex & REX_MODE64)
1.3385 + oappend (names64[reg + add]);
1.3386 + else if ((sizeflag & DFLAG) || bytemode != v_mode)
1.3387 + oappend (names32[reg + add]);
1.3388 + else
1.3389 + oappend (names16[reg + add]);
1.3390 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3391 + break;
1.3392 + default:
1.3393 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3394 + break;
1.3395 + }
1.3396 +}
1.3397 +
1.3398 +static bfd_vma
1.3399 +get64 (void)
1.3400 +{
1.3401 + bfd_vma x;
1.3402 +#ifdef BFD64
1.3403 + unsigned int a;
1.3404 + unsigned int b;
1.3405 +
1.3406 + FETCH_DATA (the_info, codep + 8);
1.3407 + a = *codep++ & 0xff;
1.3408 + a |= (*codep++ & 0xff) << 8;
1.3409 + a |= (*codep++ & 0xff) << 16;
1.3410 + a |= (*codep++ & 0xff) << 24;
1.3411 + b = *codep++ & 0xff;
1.3412 + b |= (*codep++ & 0xff) << 8;
1.3413 + b |= (*codep++ & 0xff) << 16;
1.3414 + b |= (*codep++ & 0xff) << 24;
1.3415 + x = a + ((bfd_vma) b << 32);
1.3416 +#else
1.3417 + abort ();
1.3418 + x = 0;
1.3419 +#endif
1.3420 + return x;
1.3421 +}
1.3422 +
1.3423 +static bfd_signed_vma
1.3424 +get32 (void)
1.3425 +{
1.3426 + bfd_signed_vma x = 0;
1.3427 +
1.3428 + FETCH_DATA (the_info, codep + 4);
1.3429 + x = *codep++ & (bfd_signed_vma) 0xff;
1.3430 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
1.3431 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
1.3432 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
1.3433 + return x;
1.3434 +}
1.3435 +
1.3436 +static bfd_signed_vma
1.3437 +get32s (void)
1.3438 +{
1.3439 + bfd_signed_vma x = 0;
1.3440 +
1.3441 + FETCH_DATA (the_info, codep + 4);
1.3442 + x = *codep++ & (bfd_signed_vma) 0xff;
1.3443 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 8;
1.3444 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 16;
1.3445 + x |= (*codep++ & (bfd_signed_vma) 0xff) << 24;
1.3446 +
1.3447 + x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
1.3448 +
1.3449 + return x;
1.3450 +}
1.3451 +
1.3452 +static int
1.3453 +get16 (void)
1.3454 +{
1.3455 + int x = 0;
1.3456 +
1.3457 + FETCH_DATA (the_info, codep + 2);
1.3458 + x = *codep++ & 0xff;
1.3459 + x |= (*codep++ & 0xff) << 8;
1.3460 + return x;
1.3461 +}
1.3462 +
1.3463 +static void
1.3464 +set_op (bfd_vma op, int riprel)
1.3465 +{
1.3466 + op_index[op_ad] = op_ad;
1.3467 + if (mode_64bit)
1.3468 + {
1.3469 + op_address[op_ad] = op;
1.3470 + op_riprel[op_ad] = riprel;
1.3471 + }
1.3472 + else
1.3473 + {
1.3474 + /* Mask to get a 32-bit address. */
1.3475 + op_address[op_ad] = op & 0xffffffff;
1.3476 + op_riprel[op_ad] = riprel & 0xffffffff;
1.3477 + }
1.3478 +}
1.3479 +
1.3480 +static void
1.3481 +OP_REG (int code, int sizeflag)
1.3482 +{
1.3483 + const char *s;
1.3484 + int add = 0;
1.3485 + USED_REX (REX_EXTZ);
1.3486 + if (rex & REX_EXTZ)
1.3487 + add = 8;
1.3488 +
1.3489 + switch (code)
1.3490 + {
1.3491 + case indir_dx_reg:
1.3492 + if (intel_syntax)
1.3493 + s = "[dx]";
1.3494 + else
1.3495 + s = "(%dx)";
1.3496 + break;
1.3497 + case ax_reg: case cx_reg: case dx_reg: case bx_reg:
1.3498 + case sp_reg: case bp_reg: case si_reg: case di_reg:
1.3499 + s = names16[code - ax_reg + add];
1.3500 + break;
1.3501 + case es_reg: case ss_reg: case cs_reg:
1.3502 + case ds_reg: case fs_reg: case gs_reg:
1.3503 + s = names_seg[code - es_reg + add];
1.3504 + break;
1.3505 + case al_reg: case ah_reg: case cl_reg: case ch_reg:
1.3506 + case dl_reg: case dh_reg: case bl_reg: case bh_reg:
1.3507 + USED_REX (0);
1.3508 + if (rex)
1.3509 + s = names8rex[code - al_reg + add];
1.3510 + else
1.3511 + s = names8[code - al_reg];
1.3512 + break;
1.3513 + case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
1.3514 + case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
1.3515 + if (mode_64bit)
1.3516 + {
1.3517 + s = names64[code - rAX_reg + add];
1.3518 + break;
1.3519 + }
1.3520 + code += eAX_reg - rAX_reg;
1.3521 + /* Fall through. */
1.3522 + case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
1.3523 + case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
1.3524 + USED_REX (REX_MODE64);
1.3525 + if (rex & REX_MODE64)
1.3526 + s = names64[code - eAX_reg + add];
1.3527 + else if (sizeflag & DFLAG)
1.3528 + s = names32[code - eAX_reg + add];
1.3529 + else
1.3530 + s = names16[code - eAX_reg + add];
1.3531 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3532 + break;
1.3533 + default:
1.3534 + s = INTERNAL_DISASSEMBLER_ERROR;
1.3535 + break;
1.3536 + }
1.3537 + oappend (s);
1.3538 +}
1.3539 +
1.3540 +static void
1.3541 +OP_IMREG (int code, int sizeflag)
1.3542 +{
1.3543 + const char *s;
1.3544 +
1.3545 + switch (code)
1.3546 + {
1.3547 + case indir_dx_reg:
1.3548 + if (intel_syntax)
1.3549 + s = "[dx]";
1.3550 + else
1.3551 + s = "(%dx)";
1.3552 + break;
1.3553 + case ax_reg: case cx_reg: case dx_reg: case bx_reg:
1.3554 + case sp_reg: case bp_reg: case si_reg: case di_reg:
1.3555 + s = names16[code - ax_reg];
1.3556 + break;
1.3557 + case es_reg: case ss_reg: case cs_reg:
1.3558 + case ds_reg: case fs_reg: case gs_reg:
1.3559 + s = names_seg[code - es_reg];
1.3560 + break;
1.3561 + case al_reg: case ah_reg: case cl_reg: case ch_reg:
1.3562 + case dl_reg: case dh_reg: case bl_reg: case bh_reg:
1.3563 + USED_REX (0);
1.3564 + if (rex)
1.3565 + s = names8rex[code - al_reg];
1.3566 + else
1.3567 + s = names8[code - al_reg];
1.3568 + break;
1.3569 + case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
1.3570 + case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
1.3571 + USED_REX (REX_MODE64);
1.3572 + if (rex & REX_MODE64)
1.3573 + s = names64[code - eAX_reg];
1.3574 + else if (sizeflag & DFLAG)
1.3575 + s = names32[code - eAX_reg];
1.3576 + else
1.3577 + s = names16[code - eAX_reg];
1.3578 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3579 + break;
1.3580 + default:
1.3581 + s = INTERNAL_DISASSEMBLER_ERROR;
1.3582 + break;
1.3583 + }
1.3584 + oappend (s);
1.3585 +}
1.3586 +
1.3587 +static void
1.3588 +OP_I (int bytemode, int sizeflag)
1.3589 +{
1.3590 + bfd_signed_vma op;
1.3591 + bfd_signed_vma mask = -1;
1.3592 +
1.3593 + switch (bytemode)
1.3594 + {
1.3595 + case b_mode:
1.3596 + FETCH_DATA (the_info, codep + 1);
1.3597 + op = *codep++;
1.3598 + mask = 0xff;
1.3599 + break;
1.3600 + case q_mode:
1.3601 + if (mode_64bit)
1.3602 + {
1.3603 + op = get32s ();
1.3604 + break;
1.3605 + }
1.3606 + /* Fall through. */
1.3607 + case v_mode:
1.3608 + USED_REX (REX_MODE64);
1.3609 + if (rex & REX_MODE64)
1.3610 + op = get32s ();
1.3611 + else if (sizeflag & DFLAG)
1.3612 + {
1.3613 + op = get32 ();
1.3614 + mask = 0xffffffff;
1.3615 + }
1.3616 + else
1.3617 + {
1.3618 + op = get16 ();
1.3619 + mask = 0xfffff;
1.3620 + }
1.3621 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3622 + break;
1.3623 + case w_mode:
1.3624 + mask = 0xfffff;
1.3625 + op = get16 ();
1.3626 + break;
1.3627 + case const_1_mode:
1.3628 + if (intel_syntax)
1.3629 + oappend ("1");
1.3630 + return;
1.3631 + default:
1.3632 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3633 + return;
1.3634 + }
1.3635 +
1.3636 + op &= mask;
1.3637 + scratchbuf[0] = '$';
1.3638 + xlat_print_symbolic_operand (scratchbuf + 1, 1, op);
1.3639 + oappend (scratchbuf + intel_syntax);
1.3640 + scratchbuf[0] = '\0';
1.3641 +}
1.3642 +
1.3643 +static void
1.3644 +OP_I64 (int bytemode, int sizeflag)
1.3645 +{
1.3646 + bfd_signed_vma op;
1.3647 + bfd_signed_vma mask = -1;
1.3648 +
1.3649 + if (!mode_64bit)
1.3650 + {
1.3651 + OP_I (bytemode, sizeflag);
1.3652 + return;
1.3653 + }
1.3654 +
1.3655 + switch (bytemode)
1.3656 + {
1.3657 + case b_mode:
1.3658 + FETCH_DATA (the_info, codep + 1);
1.3659 + op = *codep++;
1.3660 + mask = 0xff;
1.3661 + break;
1.3662 + case v_mode:
1.3663 + USED_REX (REX_MODE64);
1.3664 + if (rex & REX_MODE64)
1.3665 + op = get64 ();
1.3666 + else if (sizeflag & DFLAG)
1.3667 + {
1.3668 + op = get32 ();
1.3669 + mask = 0xffffffff;
1.3670 + }
1.3671 + else
1.3672 + {
1.3673 + op = get16 ();
1.3674 + mask = 0xfffff;
1.3675 + }
1.3676 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3677 + break;
1.3678 + case w_mode:
1.3679 + mask = 0xfffff;
1.3680 + op = get16 ();
1.3681 + break;
1.3682 + default:
1.3683 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3684 + return;
1.3685 + }
1.3686 +
1.3687 + op &= mask;
1.3688 + scratchbuf[0] = '$';
1.3689 + xlat_print_symbolic_operand (scratchbuf + 1, 1, op);
1.3690 + oappend (scratchbuf + intel_syntax);
1.3691 + scratchbuf[0] = '\0';
1.3692 +}
1.3693 +
1.3694 +static void
1.3695 +OP_sI (int bytemode, int sizeflag)
1.3696 +{
1.3697 + bfd_signed_vma op;
1.3698 + bfd_signed_vma mask = -1;
1.3699 +
1.3700 + switch (bytemode)
1.3701 + {
1.3702 + case b_mode:
1.3703 + FETCH_DATA (the_info, codep + 1);
1.3704 + op = *codep++;
1.3705 + if ((op & 0x80) != 0)
1.3706 + op -= 0x100;
1.3707 + mask = 0xffffffff;
1.3708 + break;
1.3709 + case v_mode:
1.3710 + USED_REX (REX_MODE64);
1.3711 + if (rex & REX_MODE64)
1.3712 + op = get32s ();
1.3713 + else if (sizeflag & DFLAG)
1.3714 + {
1.3715 + op = get32s ();
1.3716 + mask = 0xffffffff;
1.3717 + }
1.3718 + else
1.3719 + {
1.3720 + mask = 0xffffffff;
1.3721 + op = get16 ();
1.3722 + if ((op & 0x8000) != 0)
1.3723 + op -= 0x10000;
1.3724 + }
1.3725 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3726 + break;
1.3727 + case w_mode:
1.3728 + op = get16 ();
1.3729 + mask = 0xffffffff;
1.3730 + if ((op & 0x8000) != 0)
1.3731 + op -= 0x10000;
1.3732 + break;
1.3733 + default:
1.3734 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3735 + return;
1.3736 + }
1.3737 +
1.3738 + scratchbuf[0] = '$';
1.3739 + xlat_print_symbolic_operand (scratchbuf + 1, 1, op);
1.3740 + oappend (scratchbuf + intel_syntax);
1.3741 +}
1.3742 +
1.3743 +static void
1.3744 +OP_J (int bytemode, int sizeflag)
1.3745 +{
1.3746 + bfd_vma disp;
1.3747 + bfd_vma mask = -1;
1.3748 +
1.3749 + switch (bytemode)
1.3750 + {
1.3751 + case b_mode:
1.3752 + FETCH_DATA (the_info, codep + 1);
1.3753 + disp = *codep++;
1.3754 + if ((disp & 0x80) != 0)
1.3755 + disp -= 0x100;
1.3756 + break;
1.3757 + case v_mode:
1.3758 + if (sizeflag & DFLAG)
1.3759 + disp = get32s ();
1.3760 + else
1.3761 + {
1.3762 + disp = get16 ();
1.3763 + /* For some reason, a data16 prefix on a jump instruction
1.3764 + means that the pc is masked to 16 bits after the
1.3765 + displacement is added! */
1.3766 + mask = 0xffff;
1.3767 + }
1.3768 + break;
1.3769 + default:
1.3770 + oappend (INTERNAL_DISASSEMBLER_ERROR);
1.3771 + return;
1.3772 + }
1.3773 + disp = (start_pc + codep - start_codep + disp) & mask;
1.3774 + set_op (disp, 0);
1.3775 + xlat_print_symbolic_operand (scratchbuf, 1, disp);
1.3776 + oappend (scratchbuf);
1.3777 +}
1.3778 +
1.3779 +static void
1.3780 +OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3781 +{
1.3782 + oappend (names_seg[reg]);
1.3783 +}
1.3784 +
1.3785 +static void
1.3786 +OP_DIR (int dummy ATTRIBUTE_UNUSED, int sizeflag)
1.3787 +{
1.3788 + int seg, offset;
1.3789 +
1.3790 + if (sizeflag & DFLAG)
1.3791 + {
1.3792 + offset = get32 ();
1.3793 + seg = get16 ();
1.3794 + }
1.3795 + else
1.3796 + {
1.3797 + offset = get16 ();
1.3798 + seg = get16 ();
1.3799 + }
1.3800 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3801 + if (intel_syntax)
1.3802 + sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
1.3803 + else
1.3804 + sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset);
1.3805 + oappend (scratchbuf);
1.3806 +}
1.3807 +
1.3808 +static void
1.3809 +OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag)
1.3810 +{
1.3811 + bfd_vma off;
1.3812 +
1.3813 + append_seg ();
1.3814 +
1.3815 + if ((sizeflag & AFLAG) || mode_64bit)
1.3816 + off = get32 ();
1.3817 + else
1.3818 + off = get16 ();
1.3819 +
1.3820 + if (intel_syntax)
1.3821 + {
1.3822 + if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
1.3823 + | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
1.3824 + {
1.3825 + oappend (names_seg[ds_reg - es_reg]);
1.3826 + oappend (":");
1.3827 + }
1.3828 + }
1.3829 + xlat_print_symbolic_operand (scratchbuf, 1, off);
1.3830 + oappend (scratchbuf);
1.3831 +}
1.3832 +
1.3833 +static void
1.3834 +OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3835 +{
1.3836 + bfd_vma off;
1.3837 +
1.3838 + if (!mode_64bit)
1.3839 + {
1.3840 + OP_OFF (bytemode, sizeflag);
1.3841 + return;
1.3842 + }
1.3843 +
1.3844 + append_seg ();
1.3845 +
1.3846 + off = get64 ();
1.3847 +
1.3848 + if (intel_syntax)
1.3849 + {
1.3850 + if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS
1.3851 + | PREFIX_ES | PREFIX_FS | PREFIX_GS)))
1.3852 + {
1.3853 + oappend (names_seg[ds_reg - es_reg]);
1.3854 + oappend (":");
1.3855 + }
1.3856 + }
1.3857 + xlat_print_symbolic_operand (scratchbuf, 1, off);
1.3858 + oappend (scratchbuf);
1.3859 +}
1.3860 +
1.3861 +static void
1.3862 +ptr_reg (int code, int sizeflag)
1.3863 +{
1.3864 + const char *s;
1.3865 +
1.3866 + *obufp++ = open_char;
1.3867 + used_prefixes |= (prefixes & PREFIX_ADDR);
1.3868 + if (mode_64bit)
1.3869 + {
1.3870 + if (!(sizeflag & AFLAG))
1.3871 + s = names32[code - eAX_reg];
1.3872 + else
1.3873 + s = names64[code - eAX_reg];
1.3874 + }
1.3875 + else if (sizeflag & AFLAG)
1.3876 + s = names32[code - eAX_reg];
1.3877 + else
1.3878 + s = names16[code - eAX_reg];
1.3879 + oappend (s);
1.3880 + *obufp++ = close_char;
1.3881 + *obufp = 0;
1.3882 +}
1.3883 +
1.3884 +static void
1.3885 +OP_ESreg (int code, int sizeflag)
1.3886 +{
1.3887 + if (intel_syntax)
1.3888 + {
1.3889 + if (codep[-1] & 1)
1.3890 + {
1.3891 + USED_REX (REX_MODE64);
1.3892 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3893 + if (rex & REX_MODE64)
1.3894 + oappend ("QWORD PTR ");
1.3895 + else if ((sizeflag & DFLAG))
1.3896 + oappend ("DWORD PTR ");
1.3897 + else
1.3898 + oappend ("WORD PTR ");
1.3899 + }
1.3900 + else
1.3901 + oappend ("BYTE PTR ");
1.3902 + }
1.3903 +
1.3904 + oappend ("%es:" + intel_syntax);
1.3905 + ptr_reg (code, sizeflag);
1.3906 +}
1.3907 +
1.3908 +static void
1.3909 +OP_DSreg (int code, int sizeflag)
1.3910 +{
1.3911 + if (intel_syntax)
1.3912 + {
1.3913 + if (codep[-1] != 0xd7 && (codep[-1] & 1))
1.3914 + {
1.3915 + USED_REX (REX_MODE64);
1.3916 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3917 + if (rex & REX_MODE64)
1.3918 + oappend ("QWORD PTR ");
1.3919 + else if ((sizeflag & DFLAG))
1.3920 + oappend ("DWORD PTR ");
1.3921 + else
1.3922 + oappend ("WORD PTR ");
1.3923 + }
1.3924 + else
1.3925 + oappend ("BYTE PTR ");
1.3926 + }
1.3927 +
1.3928 + if ((prefixes
1.3929 + & (PREFIX_CS
1.3930 + | PREFIX_DS
1.3931 + | PREFIX_SS
1.3932 + | PREFIX_ES
1.3933 + | PREFIX_FS
1.3934 + | PREFIX_GS)) == 0)
1.3935 + prefixes |= PREFIX_DS;
1.3936 + append_seg ();
1.3937 + ptr_reg (code, sizeflag);
1.3938 +}
1.3939 +
1.3940 +static void
1.3941 +OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3942 +{
1.3943 + int add = 0;
1.3944 + if (rex & REX_EXTX)
1.3945 + {
1.3946 + USED_REX (REX_EXTX);
1.3947 + add = 8;
1.3948 + }
1.3949 + else if (!mode_64bit && (prefixes & PREFIX_LOCK))
1.3950 + {
1.3951 + used_prefixes |= PREFIX_LOCK;
1.3952 + add = 8;
1.3953 + }
1.3954 + sprintf (scratchbuf, "%%cr%d", reg + add);
1.3955 + oappend (scratchbuf + intel_syntax);
1.3956 +}
1.3957 +
1.3958 +static void
1.3959 +OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3960 +{
1.3961 + int add = 0;
1.3962 + USED_REX (REX_EXTX);
1.3963 + if (rex & REX_EXTX)
1.3964 + add = 8;
1.3965 + if (intel_syntax)
1.3966 + sprintf (scratchbuf, "db%d", reg + add);
1.3967 + else
1.3968 + sprintf (scratchbuf, "%%db%d", reg + add);
1.3969 + oappend (scratchbuf);
1.3970 +}
1.3971 +
1.3972 +static void
1.3973 +OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3974 +{
1.3975 + sprintf (scratchbuf, "%%tr%d", reg);
1.3976 + oappend (scratchbuf + intel_syntax);
1.3977 +}
1.3978 +
1.3979 +static void
1.3980 +OP_Rd (int bytemode, int sizeflag)
1.3981 +{
1.3982 + if (mod == 3)
1.3983 + OP_E (bytemode, sizeflag);
1.3984 + else
1.3985 + BadOp ();
1.3986 +}
1.3987 +
1.3988 +static void
1.3989 +OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.3990 +{
1.3991 + used_prefixes |= (prefixes & PREFIX_DATA);
1.3992 + if (prefixes & PREFIX_DATA)
1.3993 + {
1.3994 + int add = 0;
1.3995 + USED_REX (REX_EXTX);
1.3996 + if (rex & REX_EXTX)
1.3997 + add = 8;
1.3998 + sprintf (scratchbuf, "%%xmm%d", reg + add);
1.3999 + }
1.4000 + else
1.4001 + sprintf (scratchbuf, "%%mm%d", reg);
1.4002 + oappend (scratchbuf + intel_syntax);
1.4003 +}
1.4004 +
1.4005 +static void
1.4006 +OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.4007 +{
1.4008 + int add = 0;
1.4009 + USED_REX (REX_EXTX);
1.4010 + if (rex & REX_EXTX)
1.4011 + add = 8;
1.4012 + sprintf (scratchbuf, "%%xmm%d", reg + add);
1.4013 + oappend (scratchbuf + intel_syntax);
1.4014 +}
1.4015 +
1.4016 +static void
1.4017 +OP_EM (int bytemode, int sizeflag)
1.4018 +{
1.4019 + if (mod != 3)
1.4020 + {
1.4021 + if (intel_syntax && bytemode == v_mode)
1.4022 + {
1.4023 + bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode;
1.4024 + used_prefixes |= (prefixes & PREFIX_DATA);
1.4025 + }
1.4026 + OP_E (bytemode, sizeflag);
1.4027 + return;
1.4028 + }
1.4029 +
1.4030 + /* Skip mod/rm byte. */
1.4031 + MODRM_CHECK;
1.4032 + codep++;
1.4033 + used_prefixes |= (prefixes & PREFIX_DATA);
1.4034 + if (prefixes & PREFIX_DATA)
1.4035 + {
1.4036 + int add = 0;
1.4037 +
1.4038 + USED_REX (REX_EXTZ);
1.4039 + if (rex & REX_EXTZ)
1.4040 + add = 8;
1.4041 + sprintf (scratchbuf, "%%xmm%d", rm + add);
1.4042 + }
1.4043 + else
1.4044 + sprintf (scratchbuf, "%%mm%d", rm);
1.4045 + oappend (scratchbuf + intel_syntax);
1.4046 +}
1.4047 +
1.4048 +static void
1.4049 +OP_EX (int bytemode, int sizeflag)
1.4050 +{
1.4051 + int add = 0;
1.4052 + if (mod != 3)
1.4053 + {
1.4054 + if (intel_syntax && bytemode == v_mode)
1.4055 + {
1.4056 + switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ))
1.4057 + {
1.4058 + case 0: bytemode = x_mode; break;
1.4059 + case PREFIX_REPZ: bytemode = d_mode; used_prefixes |= PREFIX_REPZ; break;
1.4060 + case PREFIX_DATA: bytemode = x_mode; used_prefixes |= PREFIX_DATA; break;
1.4061 + case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break;
1.4062 + default: bytemode = 0; break;
1.4063 + }
1.4064 + }
1.4065 + OP_E (bytemode, sizeflag);
1.4066 + return;
1.4067 + }
1.4068 + USED_REX (REX_EXTZ);
1.4069 + if (rex & REX_EXTZ)
1.4070 + add = 8;
1.4071 +
1.4072 + /* Skip mod/rm byte. */
1.4073 + MODRM_CHECK;
1.4074 + codep++;
1.4075 + sprintf (scratchbuf, "%%xmm%d", rm + add);
1.4076 + oappend (scratchbuf + intel_syntax);
1.4077 +}
1.4078 +
1.4079 +static void
1.4080 +OP_MS (int bytemode, int sizeflag)
1.4081 +{
1.4082 + if (mod == 3)
1.4083 + OP_EM (bytemode, sizeflag);
1.4084 + else
1.4085 + BadOp ();
1.4086 +}
1.4087 +
1.4088 +static void
1.4089 +OP_XS (int bytemode, int sizeflag)
1.4090 +{
1.4091 + if (mod == 3)
1.4092 + OP_EX (bytemode, sizeflag);
1.4093 + else
1.4094 + BadOp ();
1.4095 +}
1.4096 +
1.4097 +static void
1.4098 +OP_M (int bytemode, int sizeflag)
1.4099 +{
1.4100 + if (mod == 3)
1.4101 + BadOp (); /* bad lea,lds,les,lfs,lgs,lss modrm */
1.4102 + else
1.4103 + OP_E (bytemode, sizeflag);
1.4104 +}
1.4105 +
1.4106 +static void
1.4107 +OP_0f07 (int bytemode, int sizeflag)
1.4108 +{
1.4109 + if (mod != 3 || rm != 0)
1.4110 + BadOp ();
1.4111 + else
1.4112 + OP_E (bytemode, sizeflag);
1.4113 +}
1.4114 +
1.4115 +static void
1.4116 +OP_0fae (int bytemode, int sizeflag)
1.4117 +{
1.4118 + if (mod == 3)
1.4119 + {
1.4120 + if (reg == 7)
1.4121 + strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence");
1.4122 +
1.4123 + if (reg < 5 || rm != 0)
1.4124 + {
1.4125 + BadOp (); /* bad sfence, mfence, or lfence */
1.4126 + return;
1.4127 + }
1.4128 + }
1.4129 + else if (reg != 7)
1.4130 + {
1.4131 + BadOp (); /* bad clflush */
1.4132 + return;
1.4133 + }
1.4134 +
1.4135 + OP_E (bytemode, sizeflag);
1.4136 +}
1.4137 +
1.4138 +static void
1.4139 +NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.4140 +{
1.4141 + /* NOP with REPZ prefix is called PAUSE. */
1.4142 + if (prefixes == PREFIX_REPZ)
1.4143 + strcpy (obuf, "pause");
1.4144 +}
1.4145 +
1.4146 +static const char *const Suffix3DNow[] = {
1.4147 +/* 00 */ NULL, NULL, NULL, NULL,
1.4148 +/* 04 */ NULL, NULL, NULL, NULL,
1.4149 +/* 08 */ NULL, NULL, NULL, NULL,
1.4150 +/* 0C */ "pi2fw", "pi2fd", NULL, NULL,
1.4151 +/* 10 */ NULL, NULL, NULL, NULL,
1.4152 +/* 14 */ NULL, NULL, NULL, NULL,
1.4153 +/* 18 */ NULL, NULL, NULL, NULL,
1.4154 +/* 1C */ "pf2iw", "pf2id", NULL, NULL,
1.4155 +/* 20 */ NULL, NULL, NULL, NULL,
1.4156 +/* 24 */ NULL, NULL, NULL, NULL,
1.4157 +/* 28 */ NULL, NULL, NULL, NULL,
1.4158 +/* 2C */ NULL, NULL, NULL, NULL,
1.4159 +/* 30 */ NULL, NULL, NULL, NULL,
1.4160 +/* 34 */ NULL, NULL, NULL, NULL,
1.4161 +/* 38 */ NULL, NULL, NULL, NULL,
1.4162 +/* 3C */ NULL, NULL, NULL, NULL,
1.4163 +/* 40 */ NULL, NULL, NULL, NULL,
1.4164 +/* 44 */ NULL, NULL, NULL, NULL,
1.4165 +/* 48 */ NULL, NULL, NULL, NULL,
1.4166 +/* 4C */ NULL, NULL, NULL, NULL,
1.4167 +/* 50 */ NULL, NULL, NULL, NULL,
1.4168 +/* 54 */ NULL, NULL, NULL, NULL,
1.4169 +/* 58 */ NULL, NULL, NULL, NULL,
1.4170 +/* 5C */ NULL, NULL, NULL, NULL,
1.4171 +/* 60 */ NULL, NULL, NULL, NULL,
1.4172 +/* 64 */ NULL, NULL, NULL, NULL,
1.4173 +/* 68 */ NULL, NULL, NULL, NULL,
1.4174 +/* 6C */ NULL, NULL, NULL, NULL,
1.4175 +/* 70 */ NULL, NULL, NULL, NULL,
1.4176 +/* 74 */ NULL, NULL, NULL, NULL,
1.4177 +/* 78 */ NULL, NULL, NULL, NULL,
1.4178 +/* 7C */ NULL, NULL, NULL, NULL,
1.4179 +/* 80 */ NULL, NULL, NULL, NULL,
1.4180 +/* 84 */ NULL, NULL, NULL, NULL,
1.4181 +/* 88 */ NULL, NULL, "pfnacc", NULL,
1.4182 +/* 8C */ NULL, NULL, "pfpnacc", NULL,
1.4183 +/* 90 */ "pfcmpge", NULL, NULL, NULL,
1.4184 +/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt",
1.4185 +/* 98 */ NULL, NULL, "pfsub", NULL,
1.4186 +/* 9C */ NULL, NULL, "pfadd", NULL,
1.4187 +/* A0 */ "pfcmpgt", NULL, NULL, NULL,
1.4188 +/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1",
1.4189 +/* A8 */ NULL, NULL, "pfsubr", NULL,
1.4190 +/* AC */ NULL, NULL, "pfacc", NULL,
1.4191 +/* B0 */ "pfcmpeq", NULL, NULL, NULL,
1.4192 +/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw",
1.4193 +/* B8 */ NULL, NULL, NULL, "pswapd",
1.4194 +/* BC */ NULL, NULL, NULL, "pavgusb",
1.4195 +/* C0 */ NULL, NULL, NULL, NULL,
1.4196 +/* C4 */ NULL, NULL, NULL, NULL,
1.4197 +/* C8 */ NULL, NULL, NULL, NULL,
1.4198 +/* CC */ NULL, NULL, NULL, NULL,
1.4199 +/* D0 */ NULL, NULL, NULL, NULL,
1.4200 +/* D4 */ NULL, NULL, NULL, NULL,
1.4201 +/* D8 */ NULL, NULL, NULL, NULL,
1.4202 +/* DC */ NULL, NULL, NULL, NULL,
1.4203 +/* E0 */ NULL, NULL, NULL, NULL,
1.4204 +/* E4 */ NULL, NULL, NULL, NULL,
1.4205 +/* E8 */ NULL, NULL, NULL, NULL,
1.4206 +/* EC */ NULL, NULL, NULL, NULL,
1.4207 +/* F0 */ NULL, NULL, NULL, NULL,
1.4208 +/* F4 */ NULL, NULL, NULL, NULL,
1.4209 +/* F8 */ NULL, NULL, NULL, NULL,
1.4210 +/* FC */ NULL, NULL, NULL, NULL,
1.4211 +};
1.4212 +
1.4213 +static void
1.4214 +OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.4215 +{
1.4216 + const char *mnemonic;
1.4217 +
1.4218 + FETCH_DATA (the_info, codep + 1);
1.4219 + /* AMD 3DNow! instructions are specified by an opcode suffix in the
1.4220 + place where an 8-bit immediate would normally go. ie. the last
1.4221 + byte of the instruction. */
1.4222 + obufp = obuf + strlen (obuf);
1.4223 + mnemonic = Suffix3DNow[*codep++ & 0xff];
1.4224 + if (mnemonic)
1.4225 + oappend (mnemonic);
1.4226 + else
1.4227 + {
1.4228 + /* Since a variable sized modrm/sib chunk is between the start
1.4229 + of the opcode (0x0f0f) and the opcode suffix, we need to do
1.4230 + all the modrm processing first, and don't know until now that
1.4231 + we have a bad opcode. This necessitates some cleaning up. */
1.4232 + op1out[0] = '\0';
1.4233 + op2out[0] = '\0';
1.4234 + BadOp ();
1.4235 + }
1.4236 +}
1.4237 +
1.4238 +static const char *simd_cmp_op[] = {
1.4239 + "eq",
1.4240 + "lt",
1.4241 + "le",
1.4242 + "unord",
1.4243 + "neq",
1.4244 + "nlt",
1.4245 + "nle",
1.4246 + "ord"
1.4247 +};
1.4248 +
1.4249 +static void
1.4250 +OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
1.4251 +{
1.4252 + unsigned int cmp_type;
1.4253 +
1.4254 + FETCH_DATA (the_info, codep + 1);
1.4255 + obufp = obuf + strlen (obuf);
1.4256 + cmp_type = *codep++ & 0xff;
1.4257 + if (cmp_type < 8)
1.4258 + {
1.4259 + char suffix1 = 'p', suffix2 = 's';
1.4260 + used_prefixes |= (prefixes & PREFIX_REPZ);
1.4261 + if (prefixes & PREFIX_REPZ)
1.4262 + suffix1 = 's';
1.4263 + else
1.4264 + {
1.4265 + used_prefixes |= (prefixes & PREFIX_DATA);
1.4266 + if (prefixes & PREFIX_DATA)
1.4267 + suffix2 = 'd';
1.4268 + else
1.4269 + {
1.4270 + used_prefixes |= (prefixes & PREFIX_REPNZ);
1.4271 + if (prefixes & PREFIX_REPNZ)
1.4272 + suffix1 = 's', suffix2 = 'd';
1.4273 + }
1.4274 + }
1.4275 + sprintf (scratchbuf, "cmp%s%c%c",
1.4276 + simd_cmp_op[cmp_type], suffix1, suffix2);
1.4277 + used_prefixes |= (prefixes & PREFIX_REPZ);
1.4278 + oappend (scratchbuf);
1.4279 + }
1.4280 + else
1.4281 + {
1.4282 + /* We have a bad extension byte. Clean up. */
1.4283 + op1out[0] = '\0';
1.4284 + op2out[0] = '\0';
1.4285 + BadOp ();
1.4286 + }
1.4287 +}
1.4288 +
1.4289 +static void
1.4290 +SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED)
1.4291 +{
1.4292 + /* Change movlps/movhps to movhlps/movlhps for 2 register operand
1.4293 + forms of these instructions. */
1.4294 + if (mod == 3)
1.4295 + {
1.4296 + char *p = obuf + strlen (obuf);
1.4297 + *(p + 1) = '\0';
1.4298 + *p = *(p - 1);
1.4299 + *(p - 1) = *(p - 2);
1.4300 + *(p - 2) = *(p - 3);
1.4301 + *(p - 3) = extrachar;
1.4302 + }
1.4303 +}
1.4304 +
1.4305 +static void
1.4306 +PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag)
1.4307 +{
1.4308 + if (mod == 3 && reg == 1 && rm <= 1)
1.4309 + {
1.4310 + /* Override "sidt". */
1.4311 + char *p = obuf + strlen (obuf) - 4;
1.4312 +
1.4313 + /* We might have a suffix. */
1.4314 + if (*p == 'i')
1.4315 + --p;
1.4316 +
1.4317 + if (rm)
1.4318 + {
1.4319 + /* mwait %eax,%ecx */
1.4320 + strcpy (p, "mwait");
1.4321 + if (!intel_syntax)
1.4322 + strcpy (op1out, names32[0]);
1.4323 + }
1.4324 + else
1.4325 + {
1.4326 + /* monitor %eax,%ecx,%edx" */
1.4327 + strcpy (p, "monitor");
1.4328 + if (!intel_syntax)
1.4329 + {
1.4330 + if (!mode_64bit)
1.4331 + strcpy (op1out, names32[0]);
1.4332 + else if (!(prefixes & PREFIX_ADDR))
1.4333 + strcpy (op1out, names64[0]);
1.4334 + else
1.4335 + {
1.4336 + strcpy (op1out, names32[0]);
1.4337 + used_prefixes |= PREFIX_ADDR;
1.4338 + }
1.4339 + strcpy (op3out, names32[2]);
1.4340 + }
1.4341 + }
1.4342 + if (!intel_syntax)
1.4343 + {
1.4344 + strcpy (op2out, names32[1]);
1.4345 + two_source_ops = 1;
1.4346 + }
1.4347 +
1.4348 + codep++;
1.4349 + }
1.4350 + else
1.4351 + OP_E (0, sizeflag);
1.4352 +}
1.4353 +
1.4354 +static void
1.4355 +INVLPG_Fixup (int bytemode, int sizeflag)
1.4356 +{
1.4357 + const char *alt;
1.4358 +
1.4359 + switch (*codep)
1.4360 + {
1.4361 + case 0xf8:
1.4362 + alt = "swapgs";
1.4363 + break;
1.4364 + case 0xf9:
1.4365 + alt = "rdtscp";
1.4366 + break;
1.4367 + default:
1.4368 + OP_E (bytemode, sizeflag);
1.4369 + return;
1.4370 + }
1.4371 + /* Override "invlpg". */
1.4372 + strcpy (obuf + strlen (obuf) - 6, alt);
1.4373 + codep++;
1.4374 +}
1.4375 +
1.4376 +static void
1.4377 +BadOp (void)
1.4378 +{
1.4379 + /* Throw away prefixes and 1st. opcode byte. */
1.4380 + codep = insn_codep + 1;
1.4381 + oappend ("(bad)");
1.4382 +}
.