| /* opcodes/i386-dis.c r1.126 */ |
| /* Print i386 instructions for GDB, the GNU debugger. |
| Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. |
| |
| This file is part of GDB. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
| |
| /* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) |
| July 1988 |
| modified by John Hassey (hassey@dg-rtp.dg.com) |
| x86-64 support added by Jan Hubicka (jh@suse.cz) |
| VIA PadLock support by Michal Ludvig (mludvig@suse.cz). */ |
| |
| /* The main tables describing the instructions is essentially a copy |
| of the "Opcode Map" chapter (Appendix A) of the Intel 80386 |
| Programmers Manual. Usually, there is a capital letter, followed |
| by a small letter. The capital letter tell the addressing mode, |
| and the small letter tells about the operand size. Refer to |
| the Intel manual for details. */ |
| |
| #include <stdlib.h> |
| #include "disas/bfd.h" |
| /* include/opcode/i386.h r1.78 */ |
| |
| /* opcode/i386.h -- Intel 80386 opcode macros |
| Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
| 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 |
| Free Software Foundation, Inc. |
| |
| This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
| |
| /* The SystemV/386 SVR3.2 assembler, and probably all AT&T derived |
| ix86 Unix assemblers, generate floating point instructions with |
| reversed source and destination registers in certain cases. |
| Unfortunately, gcc and possibly many other programs use this |
| reversed syntax, so we're stuck with it. |
| |
| eg. `fsub %st(3),%st' results in st = st - st(3) as expected, but |
| `fsub %st,%st(3)' results in st(3) = st - st(3), rather than |
| the expected st(3) = st(3) - st |
| |
| This happens with all the non-commutative arithmetic floating point |
| operations with two register operands, where the source register is |
| %st, and destination register is %st(i). |
| |
| The affected opcode map is dceX, dcfX, deeX, defX. */ |
| |
| #ifndef SYSV386_COMPAT |
| /* Set non-zero for broken, compatible instructions. Set to zero for |
| non-broken opcodes at your peril. gcc generates SystemV/386 |
| compatible instructions. */ |
| #define SYSV386_COMPAT 1 |
| #endif |
| #ifndef OLDGCC_COMPAT |
| /* Set non-zero to cater for old (<= 2.8.1) versions of gcc that could |
| generate nonsense fsubp, fsubrp, fdivp and fdivrp with operands |
| reversed. */ |
| #define OLDGCC_COMPAT SYSV386_COMPAT |
| #endif |
| |
| #define MOV_AX_DISP32 0xa0 |
| #define POP_SEG_SHORT 0x07 |
| #define JUMP_PC_RELATIVE 0xeb |
| #define INT_OPCODE 0xcd |
| #define INT3_OPCODE 0xcc |
| /* The opcode for the fwait instruction, which disassembler treats as a |
| prefix when it can. */ |
| #define FWAIT_OPCODE 0x9b |
| #define ADDR_PREFIX_OPCODE 0x67 |
| #define DATA_PREFIX_OPCODE 0x66 |
| #define LOCK_PREFIX_OPCODE 0xf0 |
| #define CS_PREFIX_OPCODE 0x2e |
| #define DS_PREFIX_OPCODE 0x3e |
| #define ES_PREFIX_OPCODE 0x26 |
| #define FS_PREFIX_OPCODE 0x64 |
| #define GS_PREFIX_OPCODE 0x65 |
| #define SS_PREFIX_OPCODE 0x36 |
| #define REPNE_PREFIX_OPCODE 0xf2 |
| #define REPE_PREFIX_OPCODE 0xf3 |
| |
| #define TWO_BYTE_OPCODE_ESCAPE 0x0f |
| #define NOP_OPCODE (char) 0x90 |
| |
| /* register numbers */ |
| #define EBP_REG_NUM 5 |
| #define ESP_REG_NUM 4 |
| |
| /* modrm_byte.regmem for twobyte escape */ |
| #define ESCAPE_TO_TWO_BYTE_ADDRESSING ESP_REG_NUM |
| /* index_base_byte.index for no index register addressing */ |
| #define NO_INDEX_REGISTER ESP_REG_NUM |
| /* index_base_byte.base for no base register addressing */ |
| #define NO_BASE_REGISTER EBP_REG_NUM |
| #define NO_BASE_REGISTER_16 6 |
| |
| /* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */ |
| #define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */ |
| #define REGMEM_FIELD_HAS_MEM (~REGMEM_FIELD_HAS_REG) |
| |
| /* x86-64 extension prefix. */ |
| #define REX_OPCODE 0x40 |
| |
| /* Indicates 64 bit operand size. */ |
| #define REX_W 8 |
| /* High extension to reg field of modrm byte. */ |
| #define REX_R 4 |
| /* High extension to SIB index field. */ |
| #define REX_X 2 |
| /* High extension to base field of modrm or SIB, or reg field of opcode. */ |
| #define REX_B 1 |
| |
| /* max operands per insn */ |
| #define MAX_OPERANDS 4 |
| |
| /* max immediates per insn (lcall, ljmp, insertq, extrq) */ |
| #define MAX_IMMEDIATE_OPERANDS 2 |
| |
| /* max memory refs per insn (string ops) */ |
| #define MAX_MEMORY_OPERANDS 2 |
| |
| /* max size of insn mnemonics. */ |
| #define MAX_MNEM_SIZE 16 |
| |
| /* max size of register name in insn mnemonics. */ |
| #define MAX_REG_NAME_SIZE 8 |
| |
| /* opcodes/i386-dis.c r1.126 */ |
| #include "qemu-common.h" |
| |
| #include <setjmp.h> |
| |
| static int fetch_data2(struct disassemble_info *, bfd_byte *); |
| static int fetch_data(struct disassemble_info *, bfd_byte *); |
| static void ckprefix (void); |
| static const char *prefix_name (int, int); |
| static int print_insn (bfd_vma, disassemble_info *); |
| static void dofloat (int); |
| static void OP_ST (int, int); |
| static void OP_STi (int, int); |
| static int putop (const char *, int); |
| static void oappend (const char *); |
| static void append_seg (void); |
| static void OP_indirE (int, int); |
| static void print_operand_value (char *buf, size_t bufsize, int hex, bfd_vma disp); |
| static void print_displacement (char *, bfd_vma); |
| static void OP_E (int, int); |
| static void OP_G (int, int); |
| static void OP_vvvv (int, int); |
| static bfd_vma get64 (void); |
| static bfd_signed_vma get32 (void); |
| static bfd_signed_vma get32s (void); |
| static int get16 (void); |
| static void set_op (bfd_vma, int); |
| static void OP_REG (int, int); |
| static void OP_IMREG (int, int); |
| static void OP_I (int, int); |
| static void OP_I64 (int, int); |
| static void OP_sI (int, int); |
| static void OP_J (int, int); |
| static void OP_SEG (int, int); |
| static void OP_DIR (int, int); |
| static void OP_OFF (int, int); |
| static void OP_OFF64 (int, int); |
| static void ptr_reg (int, int); |
| static void OP_ESreg (int, int); |
| static void OP_DSreg (int, int); |
| static void OP_C (int, int); |
| static void OP_D (int, int); |
| static void OP_T (int, int); |
| static void OP_R (int, int); |
| static void OP_MMX (int, int); |
| static void OP_XMM (int, int); |
| static void OP_EM (int, int); |
| static void OP_EX (int, int); |
| static void OP_EMC (int,int); |
| static void OP_MXC (int,int); |
| static void OP_MS (int, int); |
| static void OP_XS (int, int); |
| static void OP_M (int, int); |
| static void OP_VMX (int, int); |
| static void OP_0fae (int, int); |
| static void OP_0f07 (int, int); |
| static void NOP_Fixup1 (int, int); |
| static void NOP_Fixup2 (int, int); |
| static void OP_3DNowSuffix (int, int); |
| static void OP_SIMD_Suffix (int, int); |
| static void SIMD_Fixup (int, int); |
| static void PNI_Fixup (int, int); |
| static void SVME_Fixup (int, int); |
| static void INVLPG_Fixup (int, int); |
| static void BadOp (void); |
| static void VMX_Fixup (int, int); |
| static void REP_Fixup (int, int); |
| static void CMPXCHG8B_Fixup (int, int); |
| static void XMM_Fixup (int, int); |
| static void CRC32_Fixup (int, int); |
| |
| struct dis_private { |
| /* Points to first byte not fetched. */ |
| bfd_byte *max_fetched; |
| bfd_byte the_buffer[MAX_MNEM_SIZE]; |
| bfd_vma insn_start; |
| int orig_sizeflag; |
| sigjmp_buf bailout; |
| }; |
| |
| enum address_mode |
| { |
| mode_16bit, |
| mode_32bit, |
| mode_64bit |
| }; |
| |
| static enum address_mode address_mode; |
| |
| /* Flags for the prefixes for the current instruction. See below. */ |
| static int prefixes; |
| |
| /* REX prefix the current instruction. See below. */ |
| static int rex; |
| /* Bits of REX we've already used. */ |
| static int rex_used; |
| /* Mark parts used in the REX prefix. When we are testing for |
| empty prefix (for 8bit register REX extension), just mask it |
| out. Otherwise test for REX bit is excuse for existence of REX |
| only in case value is nonzero. */ |
| #define USED_REX(value) \ |
| { \ |
| if (value) \ |
| { \ |
| if ((rex & value)) \ |
| rex_used |= (value) | REX_OPCODE; \ |
| } \ |
| else \ |
| rex_used |= REX_OPCODE; \ |
| } |
| |
| /* Flags for prefixes which we somehow handled when printing the |
| current instruction. */ |
| static int used_prefixes; |
| |
| /* The VEX.vvvv register, unencoded. */ |
| static int vex_reg; |
| |
| /* Flags stored in PREFIXES. */ |
| #define PREFIX_REPZ 1 |
| #define PREFIX_REPNZ 2 |
| #define PREFIX_LOCK 4 |
| #define PREFIX_CS 8 |
| #define PREFIX_SS 0x10 |
| #define PREFIX_DS 0x20 |
| #define PREFIX_ES 0x40 |
| #define PREFIX_FS 0x80 |
| #define PREFIX_GS 0x100 |
| #define PREFIX_DATA 0x200 |
| #define PREFIX_ADDR 0x400 |
| #define PREFIX_FWAIT 0x800 |
| |
| #define PREFIX_VEX_0F 0x1000 |
| #define PREFIX_VEX_0F38 0x2000 |
| #define PREFIX_VEX_0F3A 0x4000 |
| |
| /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) |
| to ADDR (exclusive) are valid. Returns 1 for success, longjmps |
| on error. */ |
| static int |
| fetch_data2(struct disassemble_info *info, bfd_byte *addr) |
| { |
| int status; |
| struct dis_private *priv = (struct dis_private *) info->private_data; |
| bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); |
| |
| if (addr <= priv->the_buffer + MAX_MNEM_SIZE) |
| status = (*info->read_memory_func) (start, |
| priv->max_fetched, |
| addr - priv->max_fetched, |
| info); |
| else |
| status = -1; |
| if (status != 0) |
| { |
| /* If we did manage to read at least one byte, then |
| print_insn_i386 will do something sensible. Otherwise, print |
| an error. We do that here because this is where we know |
| STATUS. */ |
| if (priv->max_fetched == priv->the_buffer) |
| (*info->memory_error_func) (status, start, info); |
| siglongjmp(priv->bailout, 1); |
| } |
| else |
| priv->max_fetched = addr; |
| return 1; |
| } |
| |
| static int |
| fetch_data(struct disassemble_info *info, bfd_byte *addr) |
| { |
| if (addr <= ((struct dis_private *) (info->private_data))->max_fetched) { |
| return 1; |
| } else { |
| return fetch_data2(info, addr); |
| } |
| } |
| |
| |
| #define XX { NULL, 0 } |
| |
| #define Bv { OP_vvvv, v_mode } |
| #define Eb { OP_E, b_mode } |
| #define Ev { OP_E, v_mode } |
| #define Ed { OP_E, d_mode } |
| #define Edq { OP_E, dq_mode } |
| #define Edqw { OP_E, dqw_mode } |
| #define Edqb { OP_E, dqb_mode } |
| #define Edqd { OP_E, dqd_mode } |
| #define indirEv { OP_indirE, stack_v_mode } |
| #define indirEp { OP_indirE, f_mode } |
| #define stackEv { OP_E, stack_v_mode } |
| #define Em { OP_E, m_mode } |
| #define Ew { OP_E, w_mode } |
| #define M { OP_M, 0 } /* lea, lgdt, etc. */ |
| #define Ma { OP_M, v_mode } |
| #define Mp { OP_M, f_mode } /* 32 or 48 bit memory operand for LDS, LES etc */ |
| #define Mq { OP_M, q_mode } |
| #define Gb { OP_G, b_mode } |
| #define Gv { OP_G, v_mode } |
| #define Gd { OP_G, d_mode } |
| #define Gdq { OP_G, dq_mode } |
| #define Gm { OP_G, m_mode } |
| #define Gw { OP_G, w_mode } |
| #define Rd { OP_R, d_mode } |
| #define Rm { OP_R, m_mode } |
| #define Ib { OP_I, b_mode } |
| #define sIb { OP_sI, b_mode } /* sign extened byte */ |
| #define Iv { OP_I, v_mode } |
| #define Iq { OP_I, q_mode } |
| #define Iv64 { OP_I64, v_mode } |
| #define Iw { OP_I, w_mode } |
| #define I1 { OP_I, const_1_mode } |
| #define Jb { OP_J, b_mode } |
| #define Jv { OP_J, v_mode } |
| #define Cm { OP_C, m_mode } |
| #define Dm { OP_D, m_mode } |
| #define Td { OP_T, d_mode } |
| |
| #define RMeAX { OP_REG, eAX_reg } |
| #define RMeBX { OP_REG, eBX_reg } |
| #define RMeCX { OP_REG, eCX_reg } |
| #define RMeDX { OP_REG, eDX_reg } |
| #define RMeSP { OP_REG, eSP_reg } |
| #define RMeBP { OP_REG, eBP_reg } |
| #define RMeSI { OP_REG, eSI_reg } |
| #define RMeDI { OP_REG, eDI_reg } |
| #define RMrAX { OP_REG, rAX_reg } |
| #define RMrBX { OP_REG, rBX_reg } |
| #define RMrCX { OP_REG, rCX_reg } |
| #define RMrDX { OP_REG, rDX_reg } |
| #define RMrSP { OP_REG, rSP_reg } |
| #define RMrBP { OP_REG, rBP_reg } |
| #define RMrSI { OP_REG, rSI_reg } |
| #define RMrDI { OP_REG, rDI_reg } |
| #define RMAL { OP_REG, al_reg } |
| #define RMAL { OP_REG, al_reg } |
| #define RMCL { OP_REG, cl_reg } |
| #define RMDL { OP_REG, dl_reg } |
| #define RMBL { OP_REG, bl_reg } |
| #define RMAH { OP_REG, ah_reg } |
| #define RMCH { OP_REG, ch_reg } |
| #define RMDH { OP_REG, dh_reg } |
| #define RMBH { OP_REG, bh_reg } |
| #define RMAX { OP_REG, ax_reg } |
| #define RMDX { OP_REG, dx_reg } |
| |
| #define eAX { OP_IMREG, eAX_reg } |
| #define eBX { OP_IMREG, eBX_reg } |
| #define eCX { OP_IMREG, eCX_reg } |
| #define eDX { OP_IMREG, eDX_reg } |
| #define eSP { OP_IMREG, eSP_reg } |
| #define eBP { OP_IMREG, eBP_reg } |
| #define eSI { OP_IMREG, eSI_reg } |
| #define eDI { OP_IMREG, eDI_reg } |
| #define AL { OP_IMREG, al_reg } |
| #define CL { OP_IMREG, cl_reg } |
| #define DL { OP_IMREG, dl_reg } |
| #define BL { OP_IMREG, bl_reg } |
| #define AH { OP_IMREG, ah_reg } |
| #define CH { OP_IMREG, ch_reg } |
| #define DH { OP_IMREG, dh_reg } |
| #define BH { OP_IMREG, bh_reg } |
| #define AX { OP_IMREG, ax_reg } |
| #define DX { OP_IMREG, dx_reg } |
| #define zAX { OP_IMREG, z_mode_ax_reg } |
| #define indirDX { OP_IMREG, indir_dx_reg } |
| |
| #define Sw { OP_SEG, w_mode } |
| #define Sv { OP_SEG, v_mode } |
| #define Ap { OP_DIR, 0 } |
| #define Ob { OP_OFF64, b_mode } |
| #define Ov { OP_OFF64, v_mode } |
| #define Xb { OP_DSreg, eSI_reg } |
| #define Xv { OP_DSreg, eSI_reg } |
| #define Xz { OP_DSreg, eSI_reg } |
| #define Yb { OP_ESreg, eDI_reg } |
| #define Yv { OP_ESreg, eDI_reg } |
| #define DSBX { OP_DSreg, eBX_reg } |
| |
| #define es { OP_REG, es_reg } |
| #define ss { OP_REG, ss_reg } |
| #define cs { OP_REG, cs_reg } |
| #define ds { OP_REG, ds_reg } |
| #define fs { OP_REG, fs_reg } |
| #define gs { OP_REG, gs_reg } |
| |
| #define MX { OP_MMX, 0 } |
| #define XM { OP_XMM, 0 } |
| #define EM { OP_EM, v_mode } |
| #define EMd { OP_EM, d_mode } |
| #define EMq { OP_EM, q_mode } |
| #define EXd { OP_EX, d_mode } |
| #define EXq { OP_EX, q_mode } |
| #define EXx { OP_EX, x_mode } |
| #define MS { OP_MS, v_mode } |
| #define XS { OP_XS, v_mode } |
| #define EMC { OP_EMC, v_mode } |
| #define MXC { OP_MXC, 0 } |
| #define VM { OP_VMX, q_mode } |
| #define OPSUF { OP_3DNowSuffix, 0 } |
| #define OPSIMD { OP_SIMD_Suffix, 0 } |
| #define XMM0 { XMM_Fixup, 0 } |
| |
| /* Used handle "rep" prefix for string instructions. */ |
| #define Xbr { REP_Fixup, eSI_reg } |
| #define Xvr { REP_Fixup, eSI_reg } |
| #define Ybr { REP_Fixup, eDI_reg } |
| #define Yvr { REP_Fixup, eDI_reg } |
| #define Yzr { REP_Fixup, eDI_reg } |
| #define indirDXr { REP_Fixup, indir_dx_reg } |
| #define ALr { REP_Fixup, al_reg } |
| #define eAXr { REP_Fixup, eAX_reg } |
| |
| #define cond_jump_flag { NULL, cond_jump_mode } |
| #define loop_jcxz_flag { NULL, loop_jcxz_mode } |
| |
| /* bits in sizeflag */ |
| #define SUFFIX_ALWAYS 4 |
| #define AFLAG 2 |
| #define DFLAG 1 |
| |
| #define b_mode 1 /* byte operand */ |
| #define v_mode 2 /* operand size depends on prefixes */ |
| #define w_mode 3 /* word operand */ |
| #define d_mode 4 /* double word operand */ |
| #define q_mode 5 /* quad word operand */ |
| #define t_mode 6 /* ten-byte operand */ |
| #define x_mode 7 /* 16-byte XMM operand */ |
| #define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */ |
| #define cond_jump_mode 9 |
| #define loop_jcxz_mode 10 |
| #define dq_mode 11 /* operand size depends on REX prefixes. */ |
| #define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */ |
| #define f_mode 13 /* 4- or 6-byte pointer operand */ |
| #define const_1_mode 14 |
| #define stack_v_mode 15 /* v_mode for stack-related opcodes. */ |
| #define z_mode 16 /* non-quad operand size depends on prefixes */ |
| #define o_mode 17 /* 16-byte operand */ |
| #define dqb_mode 18 /* registers like dq_mode, memory like b_mode. */ |
| #define dqd_mode 19 /* registers like dq_mode, memory like d_mode. */ |
| |
| #define es_reg 100 |
| #define cs_reg 101 |
| #define ss_reg 102 |
| #define ds_reg 103 |
| #define fs_reg 104 |
| #define gs_reg 105 |
| |
| #define eAX_reg 108 |
| #define eCX_reg 109 |
| #define eDX_reg 110 |
| #define eBX_reg 111 |
| #define eSP_reg 112 |
| #define eBP_reg 113 |
| #define eSI_reg 114 |
| #define eDI_reg 115 |
| |
| #define al_reg 116 |
| #define cl_reg 117 |
| #define dl_reg 118 |
| #define bl_reg 119 |
| #define ah_reg 120 |
| #define ch_reg 121 |
| #define dh_reg 122 |
| #define bh_reg 123 |
| |
| #define ax_reg 124 |
| #define cx_reg 125 |
| #define dx_reg 126 |
| #define bx_reg 127 |
| #define sp_reg 128 |
| #define bp_reg 129 |
| #define si_reg 130 |
| #define di_reg 131 |
| |
| #define rAX_reg 132 |
| #define rCX_reg 133 |
| #define rDX_reg 134 |
| #define rBX_reg 135 |
| #define rSP_reg 136 |
| #define rBP_reg 137 |
| #define rSI_reg 138 |
| #define rDI_reg 139 |
| |
| #define z_mode_ax_reg 149 |
| #define indir_dx_reg 150 |
| |
| #define FLOATCODE 1 |
| #define USE_GROUPS 2 |
| #define USE_PREFIX_USER_TABLE 3 |
| #define X86_64_SPECIAL 4 |
| #define IS_3BYTE_OPCODE 5 |
| |
| #define FLOAT NULL, { { NULL, FLOATCODE } } |
| |
| #define GRP1a NULL, { { NULL, USE_GROUPS }, { NULL, 0 } } |
| #define GRP1b NULL, { { NULL, USE_GROUPS }, { NULL, 1 } } |
| #define GRP1S NULL, { { NULL, USE_GROUPS }, { NULL, 2 } } |
| #define GRP1Ss NULL, { { NULL, USE_GROUPS }, { NULL, 3 } } |
| #define GRP2b NULL, { { NULL, USE_GROUPS }, { NULL, 4 } } |
| #define GRP2S NULL, { { NULL, USE_GROUPS }, { NULL, 5 } } |
| #define GRP2b_one NULL, { { NULL, USE_GROUPS }, { NULL, 6 } } |
| #define GRP2S_one NULL, { { NULL, USE_GROUPS }, { NULL, 7 } } |
| #define GRP2b_cl NULL, { { NULL, USE_GROUPS }, { NULL, 8 } } |
| #define GRP2S_cl NULL, { { NULL, USE_GROUPS }, { NULL, 9 } } |
| #define GRP3b NULL, { { NULL, USE_GROUPS }, { NULL, 10 } } |
| #define GRP3S NULL, { { NULL, USE_GROUPS }, { NULL, 11 } } |
| #define GRP4 NULL, { { NULL, USE_GROUPS }, { NULL, 12 } } |
| #define GRP5 NULL, { { NULL, USE_GROUPS }, { NULL, 13 } } |
| #define GRP6 NULL, { { NULL, USE_GROUPS }, { NULL, 14 } } |
| #define GRP7 NULL, { { NULL, USE_GROUPS }, { NULL, 15 } } |
| #define GRP8 NULL, { { NULL, USE_GROUPS }, { NULL, 16 } } |
| #define GRP9 NULL, { { NULL, USE_GROUPS }, { NULL, 17 } } |
| #define GRP11_C6 NULL, { { NULL, USE_GROUPS }, { NULL, 18 } } |
| #define GRP11_C7 NULL, { { NULL, USE_GROUPS }, { NULL, 19 } } |
| #define GRP12 NULL, { { NULL, USE_GROUPS }, { NULL, 20 } } |
| #define GRP13 NULL, { { NULL, USE_GROUPS }, { NULL, 21 } } |
| #define GRP14 NULL, { { NULL, USE_GROUPS }, { NULL, 22 } } |
| #define GRP15 NULL, { { NULL, USE_GROUPS }, { NULL, 23 } } |
| #define GRP16 NULL, { { NULL, USE_GROUPS }, { NULL, 24 } } |
| #define GRPAMD NULL, { { NULL, USE_GROUPS }, { NULL, 25 } } |
| #define GRPPADLCK1 NULL, { { NULL, USE_GROUPS }, { NULL, 26 } } |
| #define GRPPADLCK2 NULL, { { NULL, USE_GROUPS }, { NULL, 27 } } |
| |
| #define PREGRP0 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 0 } } |
| #define PREGRP1 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 1 } } |
| #define PREGRP2 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 2 } } |
| #define PREGRP3 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 3 } } |
| #define PREGRP4 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 4 } } |
| #define PREGRP5 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 5 } } |
| #define PREGRP6 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 6 } } |
| #define PREGRP7 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 7 } } |
| #define PREGRP8 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 8 } } |
| #define PREGRP9 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 9 } } |
| #define PREGRP10 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 10 } } |
| #define PREGRP11 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 11 } } |
| #define PREGRP12 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 12 } } |
| #define PREGRP13 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 13 } } |
| #define PREGRP14 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 14 } } |
| #define PREGRP15 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 15 } } |
| #define PREGRP16 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 16 } } |
| #define PREGRP17 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 17 } } |
| #define PREGRP18 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 18 } } |
| #define PREGRP19 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 19 } } |
| #define PREGRP20 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 20 } } |
| #define PREGRP21 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 21 } } |
| #define PREGRP22 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 22 } } |
| #define PREGRP23 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 23 } } |
| #define PREGRP24 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 24 } } |
| #define PREGRP25 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 25 } } |
| #define PREGRP26 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 26 } } |
| #define PREGRP27 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 27 } } |
| #define PREGRP28 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 28 } } |
| #define PREGRP29 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 29 } } |
| #define PREGRP30 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 30 } } |
| #define PREGRP31 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 31 } } |
| #define PREGRP32 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 32 } } |
| #define PREGRP33 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 33 } } |
| #define PREGRP34 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 34 } } |
| #define PREGRP35 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 35 } } |
| #define PREGRP36 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 36 } } |
| #define PREGRP37 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 37 } } |
| #define PREGRP38 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 38 } } |
| #define PREGRP39 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 39 } } |
| #define PREGRP40 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 40 } } |
| #define PREGRP41 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 41 } } |
| #define PREGRP42 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 42 } } |
| #define PREGRP43 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 43 } } |
| #define PREGRP44 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 44 } } |
| #define PREGRP45 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 45 } } |
| #define PREGRP46 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 46 } } |
| #define PREGRP47 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 47 } } |
| #define PREGRP48 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 48 } } |
| #define PREGRP49 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 49 } } |
| #define PREGRP50 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 50 } } |
| #define PREGRP51 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 51 } } |
| #define PREGRP52 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 52 } } |
| #define PREGRP53 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 53 } } |
| #define PREGRP54 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 54 } } |
| #define PREGRP55 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 55 } } |
| #define PREGRP56 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 56 } } |
| #define PREGRP57 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 57 } } |
| #define PREGRP58 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 58 } } |
| #define PREGRP59 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 59 } } |
| #define PREGRP60 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 60 } } |
| #define PREGRP61 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 61 } } |
| #define PREGRP62 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 62 } } |
| #define PREGRP63 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 63 } } |
| #define PREGRP64 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 64 } } |
| #define PREGRP65 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 65 } } |
| #define PREGRP66 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 66 } } |
| #define PREGRP67 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 67 } } |
| #define PREGRP68 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 68 } } |
| #define PREGRP69 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 69 } } |
| #define PREGRP70 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 70 } } |
| #define PREGRP71 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 71 } } |
| #define PREGRP72 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 72 } } |
| #define PREGRP73 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 73 } } |
| #define PREGRP74 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 74 } } |
| #define PREGRP75 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 75 } } |
| #define PREGRP76 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 76 } } |
| #define PREGRP77 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 77 } } |
| #define PREGRP78 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 78 } } |
| #define PREGRP79 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 79 } } |
| #define PREGRP80 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 80 } } |
| #define PREGRP81 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 81 } } |
| #define PREGRP82 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 82 } } |
| #define PREGRP83 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 83 } } |
| #define PREGRP84 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 84 } } |
| #define PREGRP85 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 85 } } |
| #define PREGRP86 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 86 } } |
| #define PREGRP87 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 87 } } |
| #define PREGRP88 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 88 } } |
| #define PREGRP89 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 89 } } |
| #define PREGRP90 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 90 } } |
| #define PREGRP91 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 91 } } |
| #define PREGRP92 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 92 } } |
| #define PREGRP93 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 93 } } |
| #define PREGRP94 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 94 } } |
| #define PREGRP95 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 95 } } |
| #define PREGRP96 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 96 } } |
| #define PREGRP97 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 97 } } |
| #define PREGRP98 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 98 } } |
| #define PREGRP99 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 99 } } |
| #define PREGRP100 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 100 } } |
| #define PREGRP101 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 101 } } |
| #define PREGRP102 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 102 } } |
| #define PREGRP103 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 103 } } |
| #define PREGRP104 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 104 } } |
| #define PREGRP105 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 105 } } |
| #define PREGRP106 NULL, { { NULL, USE_PREFIX_USER_TABLE }, { NULL, 106 } } |
| |
| #define X86_64_0 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 0 } } |
| #define X86_64_1 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 1 } } |
| #define X86_64_2 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 2 } } |
| #define X86_64_3 NULL, { { NULL, X86_64_SPECIAL }, { NULL, 3 } } |
| |
| #define THREE_BYTE_0 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 0 } } |
| #define THREE_BYTE_1 NULL, { { NULL, IS_3BYTE_OPCODE }, { NULL, 1 } } |
| |
| typedef void (*op_rtn) (int bytemode, int sizeflag); |
| |
| struct dis386 { |
| const char *name; |
| struct |
| { |
| op_rtn rtn; |
| int bytemode; |
| } op[MAX_OPERANDS]; |
| }; |
| |
| /* Upper case letters in the instruction names here are macros. |
| 'A' => print 'b' if no register operands or suffix_always is true |
| 'B' => print 'b' if suffix_always is true |
| 'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand |
| . size prefix |
| 'D' => print 'w' if no register operands or 'w', 'l' or 'q', if |
| . suffix_always is true |
| 'E' => print 'e' if 32-bit form of jcxz |
| 'F' => print 'w' or 'l' depending on address size prefix (loop insns) |
| 'G' => print 'w' or 'l' depending on operand size prefix (i/o insns) |
| 'H' => print ",pt" or ",pn" branch hint |
| 'I' => honor following macro letter even in Intel mode (implemented only |
| . for some of the macro letters) |
| 'J' => print 'l' |
| 'K' => print 'd' or 'q' if rex prefix is present. |
| 'L' => print 'l' if suffix_always is true |
| 'N' => print 'n' if instruction has no wait "prefix" |
| 'O' => print 'd' or 'o' (or 'q' in Intel mode) |
| 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, |
| . or suffix_always is true. print 'q' if rex prefix is present. |
| 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always |
| . is true |
| 'R' => print 'w', 'l' or 'q' ('d' for 'l' and 'e' in Intel mode) |
| 'S' => print 'w', 'l' or 'q' if suffix_always is true |
| 'T' => print 'q' in 64bit mode and behave as 'P' otherwise |
| 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise |
| 'V' => print 'q' in 64bit mode and behave as 'S' otherwise |
| 'W' => print 'b', 'w' or 'l' ('d' in Intel mode) |
| 'X' => print 's', 'd' depending on data16 prefix (for XMM) |
| 'Y' => 'q' if instruction has an REX 64bit overwrite prefix |
| 'Z' => print 'q' in 64bit mode and behave as 'L' otherwise |
| |
| Many of the above letters print nothing in Intel mode. See "putop" |
| for the details. |
| |
| Braces '{' and '}', and vertical bars '|', indicate alternative |
| mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel |
| modes. In cases where there are only two alternatives, the X86_64 |
| instruction is reserved, and "(bad)" is printed. |
| */ |
| |
| static const struct dis386 dis386[] = { |
| /* 00 */ |
| { "addB", { Eb, Gb } }, |
| { "addS", { Ev, Gv } }, |
| { "addB", { Gb, Eb } }, |
| { "addS", { Gv, Ev } }, |
| { "addB", { AL, Ib } }, |
| { "addS", { eAX, Iv } }, |
| { "push{T|}", { es } }, |
| { "pop{T|}", { es } }, |
| /* 08 */ |
| { "orB", { Eb, Gb } }, |
| { "orS", { Ev, Gv } }, |
| { "orB", { Gb, Eb } }, |
| { "orS", { Gv, Ev } }, |
| { "orB", { AL, Ib } }, |
| { "orS", { eAX, Iv } }, |
| { "push{T|}", { cs } }, |
| { "(bad)", { XX } }, /* 0x0f extended opcode escape */ |
| /* 10 */ |
| { "adcB", { Eb, Gb } }, |
| { "adcS", { Ev, Gv } }, |
| { "adcB", { Gb, Eb } }, |
| { "adcS", { Gv, Ev } }, |
| { "adcB", { AL, Ib } }, |
| { "adcS", { eAX, Iv } }, |
| { "push{T|}", { ss } }, |
| { "pop{T|}", { ss } }, |
| /* 18 */ |
| { "sbbB", { Eb, Gb } }, |
| { "sbbS", { Ev, Gv } }, |
| { "sbbB", { Gb, Eb } }, |
| { "sbbS", { Gv, Ev } }, |
| { "sbbB", { AL, Ib } }, |
| { "sbbS", { eAX, Iv } }, |
| { "push{T|}", { ds } }, |
| { "pop{T|}", { ds } }, |
| /* 20 */ |
| { "andB", { Eb, Gb } }, |
| { "andS", { Ev, Gv } }, |
| { "andB", { Gb, Eb } }, |
| { "andS", { Gv, Ev } }, |
| { "andB", { AL, Ib } }, |
| { "andS", { eAX, Iv } }, |
| { "(bad)", { XX } }, /* SEG ES prefix */ |
| { "daa{|}", { XX } }, |
| /* 28 */ |
| { "subB", { Eb, Gb } }, |
| { "subS", { Ev, Gv } }, |
| { "subB", { Gb, Eb } }, |
| { "subS", { Gv, Ev } }, |
| { "subB", { AL, Ib } }, |
| { "subS", { eAX, Iv } }, |
| { "(bad)", { XX } }, /* SEG CS prefix */ |
| { "das{|}", { XX } }, |
| /* 30 */ |
| { "xorB", { Eb, Gb } }, |
| { "xorS", { Ev, Gv } }, |
| { "xorB", { Gb, Eb } }, |
| { "xorS", { Gv, Ev } }, |
| { "xorB", { AL, Ib } }, |
| { "xorS", { eAX, Iv } }, |
| { "(bad)", { XX } }, /* SEG SS prefix */ |
| { "aaa{|}", { XX } }, |
| /* 38 */ |
| { "cmpB", { Eb, Gb } }, |
| { "cmpS", { Ev, Gv } }, |
| { "cmpB", { Gb, Eb } }, |
| { "cmpS", { Gv, Ev } }, |
| { "cmpB", { AL, Ib } }, |
| { "cmpS", { eAX, Iv } }, |
| { "(bad)", { XX } }, /* SEG DS prefix */ |
| { "aas{|}", { XX } }, |
| /* 40 */ |
| { "inc{S|}", { RMeAX } }, |
| { "inc{S|}", { RMeCX } }, |
| { "inc{S|}", { RMeDX } }, |
| { "inc{S|}", { RMeBX } }, |
| { "inc{S|}", { RMeSP } }, |
| { "inc{S|}", { RMeBP } }, |
| { "inc{S|}", { RMeSI } }, |
| { "inc{S|}", { RMeDI } }, |
| /* 48 */ |
| { "dec{S|}", { RMeAX } }, |
| { "dec{S|}", { RMeCX } }, |
| { "dec{S|}", { RMeDX } }, |
| { "dec{S|}", { RMeBX } }, |
| { "dec{S|}", { RMeSP } }, |
| { "dec{S|}", { RMeBP } }, |
| { "dec{S|}", { RMeSI } }, |
| { "dec{S|}", { RMeDI } }, |
| /* 50 */ |
| { "pushV", { RMrAX } }, |
| { "pushV", { RMrCX } }, |
| { "pushV", { RMrDX } }, |
| { "pushV", { RMrBX } }, |
| { "pushV", { RMrSP } }, |
| { "pushV", { RMrBP } }, |
| { "pushV", { RMrSI } }, |
| { "pushV", { RMrDI } }, |
| /* 58 */ |
| { "popV", { RMrAX } }, |
| { "popV", { RMrCX } }, |
| { "popV", { RMrDX } }, |
| { "popV", { RMrBX } }, |
| { "popV", { RMrSP } }, |
| { "popV", { RMrBP } }, |
| { "popV", { RMrSI } }, |
| { "popV", { RMrDI } }, |
| /* 60 */ |
| { X86_64_0 }, |
| { X86_64_1 }, |
| { X86_64_2 }, |
| { X86_64_3 }, |
| { "(bad)", { XX } }, /* seg fs */ |
| { "(bad)", { XX } }, /* seg gs */ |
| { "(bad)", { XX } }, /* op size prefix */ |
| { "(bad)", { XX } }, /* adr size prefix */ |
| /* 68 */ |
| { "pushT", { Iq } }, |
| { "imulS", { Gv, Ev, Iv } }, |
| { "pushT", { sIb } }, |
| { "imulS", { Gv, Ev, sIb } }, |
| { "ins{b||b|}", { Ybr, indirDX } }, |
| { "ins{R||G|}", { Yzr, indirDX } }, |
| { "outs{b||b|}", { indirDXr, Xb } }, |
| { "outs{R||G|}", { indirDXr, Xz } }, |
| /* 70 */ |
| { "joH", { Jb, XX, cond_jump_flag } }, |
| { "jnoH", { Jb, XX, cond_jump_flag } }, |
| { "jbH", { Jb, XX, cond_jump_flag } }, |
| { "jaeH", { Jb, XX, cond_jump_flag } }, |
| { "jeH", { Jb, XX, cond_jump_flag } }, |
| { "jneH", { Jb, XX, cond_jump_flag } }, |
| { "jbeH", { Jb, XX, cond_jump_flag } }, |
| { "jaH", { Jb, XX, cond_jump_flag } }, |
| /* 78 */ |
| { "jsH", { Jb, XX, cond_jump_flag } }, |
| { "jnsH", { Jb, XX, cond_jump_flag } }, |
| { "jpH", { Jb, XX, cond_jump_flag } }, |
| { "jnpH", { Jb, XX, cond_jump_flag } }, |
| { "jlH", { Jb, XX, cond_jump_flag } }, |
| { "jgeH", { Jb, XX, cond_jump_flag } }, |
| { "jleH", { Jb, XX, cond_jump_flag } }, |
| { "jgH", { Jb, XX, cond_jump_flag } }, |
| /* 80 */ |
| { GRP1b }, |
| { GRP1S }, |
| { "(bad)", { XX } }, |
| { GRP1Ss }, |
| { "testB", { Eb, Gb } }, |
| { "testS", { Ev, Gv } }, |
| { "xchgB", { Eb, Gb } }, |
| { "xchgS", { Ev, Gv } }, |
| /* 88 */ |
| { "movB", { Eb, Gb } }, |
| { "movS", { Ev, Gv } }, |
| { "movB", { Gb, Eb } }, |
| { "movS", { Gv, Ev } }, |
| { "movD", { Sv, Sw } }, |
| { "leaS", { Gv, M } }, |
| { "movD", { Sw, Sv } }, |
| { GRP1a }, |
| /* 90 */ |
| { PREGRP38 }, |
| { "xchgS", { RMeCX, eAX } }, |
| { "xchgS", { RMeDX, eAX } }, |
| { "xchgS", { RMeBX, eAX } }, |
| { "xchgS", { RMeSP, eAX } }, |
| { "xchgS", { RMeBP, eAX } }, |
| { "xchgS", { RMeSI, eAX } }, |
| { "xchgS", { RMeDI, eAX } }, |
| /* 98 */ |
| { "cW{t||t|}R", { XX } }, |
| { "cR{t||t|}O", { XX } }, |
| { "Jcall{T|}", { Ap } }, |
| { "(bad)", { XX } }, /* fwait */ |
| { "pushfT", { XX } }, |
| { "popfT", { XX } }, |
| { "sahf{|}", { XX } }, |
| { "lahf{|}", { XX } }, |
| /* a0 */ |
| { "movB", { AL, Ob } }, |
| { "movS", { eAX, Ov } }, |
| { "movB", { Ob, AL } }, |
| { "movS", { Ov, eAX } }, |
| { "movs{b||b|}", { Ybr, Xb } }, |
| { "movs{R||R|}", { Yvr, Xv } }, |
| { "cmps{b||b|}", { Xb, Yb } }, |
| { "cmps{R||R|}", { Xv, Yv } }, |
| /* a8 */ |
| { "testB", { AL, Ib } }, |
| { "testS", { eAX, Iv } }, |
| { "stosB", { Ybr, AL } }, |
| { "stosS", { Yvr, eAX } }, |
| { "lodsB", { ALr, Xb } }, |
| { "lodsS", { eAXr, Xv } }, |
| { "scasB", { AL, Yb } }, |
| { "scasS", { eAX, Yv } }, |
| /* b0 */ |
| { "movB", { RMAL, Ib } }, |
| { "movB", { RMCL, Ib } }, |
| { "movB", { RMDL, Ib } }, |
| { "movB", { RMBL, Ib } }, |
| { "movB", { RMAH, Ib } }, |
| { "movB", { RMCH, Ib } }, |
| { "movB", { RMDH, Ib } }, |
| { "movB", { RMBH, Ib } }, |
| /* b8 */ |
| { "movS", { RMeAX, Iv64 } }, |
| { "movS", { RMeCX, Iv64 } }, |
| { "movS", { RMeDX, Iv64 } }, |
| { "movS", { RMeBX, Iv64 } }, |
| { "movS", { RMeSP, Iv64 } }, |
| { "movS", { RMeBP, Iv64 } }, |
| { "movS", { RMeSI, Iv64 } }, |
| { "movS", { RMeDI, Iv64 } }, |
| /* c0 */ |
| { GRP2b }, |
| { GRP2S }, |
| { "retT", { Iw } }, |
| { "retT", { XX } }, |
| { "les{S|}", { Gv, Mp } }, |
| { "ldsS", { Gv, Mp } }, |
| { GRP11_C6 }, |
| { GRP11_C7 }, |
| /* c8 */ |
| { "enterT", { Iw, Ib } }, |
| { "leaveT", { XX } }, |
| { "lretP", { Iw } }, |
| { "lretP", { XX } }, |
| { "int3", { XX } }, |
| { "int", { Ib } }, |
| { "into{|}", { XX } }, |
| { "iretP", { XX } }, |
| /* d0 */ |
| { GRP2b_one }, |
| { GRP2S_one }, |
| { GRP2b_cl }, |
| { GRP2S_cl }, |
| { "aam{|}", { sIb } }, |
| { "aad{|}", { sIb } }, |
| { "(bad)", { XX } }, |
| { "xlat", { DSBX } }, |
| /* d8 */ |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| /* e0 */ |
| { "loopneFH", { Jb, XX, loop_jcxz_flag } }, |
| { "loopeFH", { Jb, XX, loop_jcxz_flag } }, |
| { "loopFH", { Jb, XX, loop_jcxz_flag } }, |
| { "jEcxzH", { Jb, XX, loop_jcxz_flag } }, |
| { "inB", { AL, Ib } }, |
| { "inG", { zAX, Ib } }, |
| { "outB", { Ib, AL } }, |
| { "outG", { Ib, zAX } }, |
| /* e8 */ |
| { "callT", { Jv } }, |
| { "jmpT", { Jv } }, |
| { "Jjmp{T|}", { Ap } }, |
| { "jmp", { Jb } }, |
| { "inB", { AL, indirDX } }, |
| { "inG", { zAX, indirDX } }, |
| { "outB", { indirDX, AL } }, |
| { "outG", { indirDX, zAX } }, |
| /* f0 */ |
| { "(bad)", { XX } }, /* lock prefix */ |
| { "icebp", { XX } }, |
| { "(bad)", { XX } }, /* repne */ |
| { "(bad)", { XX } }, /* repz */ |
| { "hlt", { XX } }, |
| { "cmc", { XX } }, |
| { GRP3b }, |
| { GRP3S }, |
| /* f8 */ |
| { "clc", { XX } }, |
| { "stc", { XX } }, |
| { "cli", { XX } }, |
| { "sti", { XX } }, |
| { "cld", { XX } }, |
| { "std", { XX } }, |
| { GRP4 }, |
| { GRP5 }, |
| }; |
| |
| static const struct dis386 dis386_twobyte[] = { |
| /* 00 */ |
| { GRP6 }, |
| { GRP7 }, |
| { "larS", { Gv, Ew } }, |
| { "lslS", { Gv, Ew } }, |
| { "(bad)", { XX } }, |
| { "syscall", { XX } }, |
| { "clts", { XX } }, |
| { "sysretP", { XX } }, |
| /* 08 */ |
| { "invd", { XX } }, |
| { "wbinvd", { XX } }, |
| { "(bad)", { XX } }, |
| { "ud2a", { XX } }, |
| { "(bad)", { XX } }, |
| { GRPAMD }, |
| { "femms", { XX } }, |
| { "", { MX, EM, OPSUF } }, /* See OP_3DNowSuffix. */ |
| /* 10 */ |
| { PREGRP8 }, |
| { PREGRP9 }, |
| { PREGRP30 }, |
| { "movlpX", { EXq, XM, { SIMD_Fixup, 'h' } } }, |
| { "unpcklpX", { XM, EXq } }, |
| { "unpckhpX", { XM, EXq } }, |
| { PREGRP31 }, |
| { "movhpX", { EXq, XM, { SIMD_Fixup, 'l' } } }, |
| /* 18 */ |
| { GRP16 }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "nopQ", { Ev } }, |
| /* 20 */ |
| { "movZ", { Rm, Cm } }, |
| { "movZ", { Rm, Dm } }, |
| { "movZ", { Cm, Rm } }, |
| { "movZ", { Dm, Rm } }, |
| { "movL", { Rd, Td } }, |
| { "(bad)", { XX } }, |
| { "movL", { Td, Rd } }, |
| { "(bad)", { XX } }, |
| /* 28 */ |
| { "movapX", { XM, EXx } }, |
| { "movapX", { EXx, XM } }, |
| { PREGRP2 }, |
| { PREGRP33 }, |
| { PREGRP4 }, |
| { PREGRP3 }, |
| { PREGRP93 }, |
| { PREGRP94 }, |
| /* 30 */ |
| { "wrmsr", { XX } }, |
| { "rdtsc", { XX } }, |
| { "rdmsr", { XX } }, |
| { "rdpmc", { XX } }, |
| { "sysenter", { XX } }, |
| { "sysexit", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| /* 38 */ |
| { THREE_BYTE_0 }, |
| { "(bad)", { XX } }, |
| { THREE_BYTE_1 }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| /* 40 */ |
| { "cmovo", { Gv, Ev } }, |
| { "cmovno", { Gv, Ev } }, |
| { "cmovb", { Gv, Ev } }, |
| { "cmovae", { Gv, Ev } }, |
| { "cmove", { Gv, Ev } }, |
| { "cmovne", { Gv, Ev } }, |
| { "cmovbe", { Gv, Ev } }, |
| { "cmova", { Gv, Ev } }, |
| /* 48 */ |
| { "cmovs", { Gv, Ev } }, |
| { "cmovns", { Gv, Ev } }, |
| { "cmovp", { Gv, Ev } }, |
| { "cmovnp", { Gv, Ev } }, |
| { "cmovl", { Gv, Ev } }, |
| { "cmovge", { Gv, Ev } }, |
| { "cmovle", { Gv, Ev } }, |
| { "cmovg", { Gv, Ev } }, |
| /* 50 */ |
| { "movmskpX", { Gdq, XS } }, |
| { PREGRP13 }, |
| { PREGRP12 }, |
| { PREGRP11 }, |
| { "andpX", { XM, EXx } }, |
| { "andnpX", { XM, EXx } }, |
| { "orpX", { XM, EXx } }, |
| { "xorpX", { XM, EXx } }, |
| /* 58 */ |
| { PREGRP0 }, |
| { PREGRP10 }, |
| { PREGRP17 }, |
| { PREGRP16 }, |
| { PREGRP14 }, |
| { PREGRP7 }, |
| { PREGRP5 }, |
| { PREGRP6 }, |
| /* 60 */ |
| { PREGRP95 }, |
| { PREGRP96 }, |
| { PREGRP97 }, |
| { "packsswb", { MX, EM } }, |
| { "pcmpgtb", { MX, EM } }, |
| { "pcmpgtw", { MX, EM } }, |
| { "pcmpgtd", { MX, EM } }, |
| { "packuswb", { MX, EM } }, |
| /* 68 */ |
| { "punpckhbw", { MX, EM } }, |
| { "punpckhwd", { MX, EM } }, |
| { "punpckhdq", { MX, EM } }, |
| { "packssdw", { MX, EM } }, |
| { PREGRP26 }, |
| { PREGRP24 }, |
| { "movd", { MX, Edq } }, |
| { PREGRP19 }, |
| /* 70 */ |
| { PREGRP22 }, |
| { GRP12 }, |
| { GRP13 }, |
| { GRP14 }, |
| { "pcmpeqb", { MX, EM } }, |
| { "pcmpeqw", { MX, EM } }, |
| { "pcmpeqd", { MX, EM } }, |
| { "emms", { XX } }, |
| /* 78 */ |
| { PREGRP34 }, |
| { PREGRP35 }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { PREGRP28 }, |
| { PREGRP29 }, |
| { PREGRP23 }, |
| { PREGRP20 }, |
| /* 80 */ |
| { "joH", { Jv, XX, cond_jump_flag } }, |
| { "jnoH", { Jv, XX, cond_jump_flag } }, |
| { "jbH", { Jv, XX, cond_jump_flag } }, |
| { "jaeH", { Jv, XX, cond_jump_flag } }, |
| { "jeH", { Jv, XX, cond_jump_flag } }, |
| { "jneH", { Jv, XX, cond_jump_flag } }, |
| { "jbeH", { Jv, XX, cond_jump_flag } }, |
| { "jaH", { Jv, XX, cond_jump_flag } }, |
| /* 88 */ |
| { "jsH", { Jv, XX, cond_jump_flag } }, |
| { "jnsH", { Jv, XX, cond_jump_flag } }, |
| { "jpH", { Jv, XX, cond_jump_flag } }, |
| { "jnpH", { Jv, XX, cond_jump_flag } }, |
| { "jlH", { Jv, XX, cond_jump_flag } }, |
| { "jgeH", { Jv, XX, cond_jump_flag } }, |
| { "jleH", { Jv, XX, cond_jump_flag } }, |
| { "jgH", { Jv, XX, cond_jump_flag } }, |
| /* 90 */ |
| { "seto", { Eb } }, |
| { "setno", { Eb } }, |
| { "setb", { Eb } }, |
| { "setae", { Eb } }, |
| { "sete", { Eb } }, |
| { "setne", { Eb } }, |
| { "setbe", { Eb } }, |
| { "seta", { Eb } }, |
| /* 98 */ |
| { "sets", { Eb } }, |
| { "setns", { Eb } }, |
| { "setp", { Eb } }, |
| { "setnp", { Eb } }, |
| { "setl", { Eb } }, |
| { "setge", { Eb } }, |
| { "setle", { Eb } }, |
| { "setg", { Eb } }, |
| /* a0 */ |
| { "pushT", { fs } }, |
| { "popT", { fs } }, |
| { "cpuid", { XX } }, |
| { "btS", { Ev, Gv } }, |
| { "shldS", { Ev, Gv, Ib } }, |
| { "shldS", { Ev, Gv, CL } }, |
| { GRPPADLCK2 }, |
| { GRPPADLCK1 }, |
| /* a8 */ |
| { "pushT", { gs } }, |
| { "popT", { gs } }, |
| { "rsm", { XX } }, |
| { "btsS", { Ev, Gv } }, |
| { "shrdS", { Ev, Gv, Ib } }, |
| { "shrdS", { Ev, Gv, CL } }, |
| { GRP15 }, |
| { "imulS", { Gv, Ev } }, |
| /* b0 */ |
| { "cmpxchgB", { Eb, Gb } }, |
| { "cmpxchgS", { Ev, Gv } }, |
| { "lssS", { Gv, Mp } }, |
| { "btrS", { Ev, Gv } }, |
| { "lfsS", { Gv, Mp } }, |
| { "lgsS", { Gv, Mp } }, |
| { "movz{bR|x|bR|x}", { Gv, Eb } }, |
| { "movz{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movzww ! */ |
| /* b8 */ |
| { PREGRP37 }, |
| { "ud2b", { XX } }, |
| { GRP8 }, |
| { "btcS", { Ev, Gv } }, |
| { "bsfS", { Gv, Ev } }, |
| { PREGRP36 }, |
| { "movs{bR|x|bR|x}", { Gv, Eb } }, |
| { "movs{wR|x|wR|x}", { Gv, Ew } }, /* yes, there really is movsww ! */ |
| /* c0 */ |
| { "xaddB", { Eb, Gb } }, |
| { "xaddS", { Ev, Gv } }, |
| { PREGRP1 }, |
| { "movntiS", { Ev, Gv } }, |
| { "pinsrw", { MX, Edqw, Ib } }, |
| { "pextrw", { Gdq, MS, Ib } }, |
| { "shufpX", { XM, EXx, Ib } }, |
| { GRP9 }, |
| /* c8 */ |
| { "bswap", { RMeAX } }, |
| { "bswap", { RMeCX } }, |
| { "bswap", { RMeDX } }, |
| { "bswap", { RMeBX } }, |
| { "bswap", { RMeSP } }, |
| { "bswap", { RMeBP } }, |
| { "bswap", { RMeSI } }, |
| { "bswap", { RMeDI } }, |
| /* d0 */ |
| { PREGRP27 }, |
| { "psrlw", { MX, EM } }, |
| { "psrld", { MX, EM } }, |
| { "psrlq", { MX, EM } }, |
| { "paddq", { MX, EM } }, |
| { "pmullw", { MX, EM } }, |
| { PREGRP21 }, |
| { "pmovmskb", { Gdq, MS } }, |
| /* d8 */ |
| { "psubusb", { MX, EM } }, |
| { "psubusw", { MX, EM } }, |
| { "pminub", { MX, EM } }, |
| { "pand", { MX, EM } }, |
| { "paddusb", { MX, EM } }, |
| { "paddusw", { MX, EM } }, |
| { "pmaxub", { MX, EM } }, |
| { "pandn", { MX, EM } }, |
| /* e0 */ |
| { "pavgb", { MX, EM } }, |
| { "psraw", { MX, EM } }, |
| { "psrad", { MX, EM } }, |
| { "pavgw", { MX, EM } }, |
| { "pmulhuw", { MX, EM } }, |
| { "pmulhw", { MX, EM } }, |
| { PREGRP15 }, |
| { PREGRP25 }, |
| /* e8 */ |
| { "psubsb", { MX, EM } }, |
| { "psubsw", { MX, EM } }, |
| { "pminsw", { MX, EM } }, |
| { "por", { MX, EM } }, |
| { "paddsb", { MX, EM } }, |
| { "paddsw", { MX, EM } }, |
| { "pmaxsw", { MX, EM } }, |
| { "pxor", { MX, EM } }, |
| /* f0 */ |
| { PREGRP32 }, |
| { "psllw", { MX, EM } }, |
| { "pslld", { MX, EM } }, |
| { "psllq", { MX, EM } }, |
| { "pmuludq", { MX, EM } }, |
| { "pmaddwd", { MX, EM } }, |
| { "psadbw", { MX, EM } }, |
| { PREGRP18 }, |
| /* f8 */ |
| { "psubb", { MX, EM } }, |
| { "psubw", { MX, EM } }, |
| { "psubd", { MX, EM } }, |
| { "psubq", { MX, EM } }, |
| { "paddb", { MX, EM } }, |
| { "paddw", { MX, EM } }, |
| { "paddd", { MX, EM } }, |
| { "(bad)", { XX } }, |
| }; |
| |
| static const unsigned char onebyte_has_modrm[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */ |
| /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */ |
| /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */ |
| /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ |
| /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ |
| /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */ |
| /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */ |
| /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */ |
| /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| static const unsigned char twobyte_has_modrm[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ |
| /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1, /* 1f */ |
| /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ |
| /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ |
| /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ |
| /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ |
| /* 70 */ 1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ |
| /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */ |
| /* b0 */ 1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1, /* bf */ |
| /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */ |
| /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */ |
| /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| static const unsigned char twobyte_uses_DATA_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ |
| /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| static const unsigned char twobyte_uses_REPNZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,1,0,0,0,0,0,0,1,1,1,0,1,1,1,1, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 1,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| static const unsigned char twobyte_uses_REPZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* 6f */ |
| /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, /* bf */ |
| /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 38 XX uses DATA prefix. */ |
| static const unsigned char threebyte_0x38_uses_DATA_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 0f */ |
| /* 10 */ 1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0, /* 1f */ |
| /* 20 */ 1,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0, /* 2f */ |
| /* 30 */ 1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1, /* 3f */ |
| /* 40 */ 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 38 XX uses REPNZ prefix. */ |
| static const unsigned char threebyte_0x38_uses_REPNZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 38 XX uses REPZ prefix. */ |
| static const unsigned char threebyte_0x38_uses_REPZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 3a XX uses DATA prefix. */ |
| static const unsigned char threebyte_0x3a_uses_DATA_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, /* 0f */ |
| /* 10 */ 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 3a XX uses REPNZ prefix. */ |
| static const unsigned char threebyte_0x3a_uses_REPNZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| /* This is used to determine if opcode 0f 3a XX uses REPZ prefix. */ |
| static const unsigned char threebyte_0x3a_uses_REPZ_prefix[256] = { |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| /* ------------------------------- */ |
| /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ |
| /* 10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 1f */ |
| /* 20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 2f */ |
| /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ |
| /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ |
| /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 5f */ |
| /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 6f */ |
| /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 7f */ |
| /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ |
| /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ |
| /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ |
| /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ |
| /* c0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ |
| /* d0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* df */ |
| /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ef */ |
| /* f0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| static char obuf[100]; |
| static char *obufp; |
| static char scratchbuf[100]; |
| static unsigned char *start_codep; |
| static unsigned char *insn_codep; |
| static unsigned char *codep; |
| static disassemble_info *the_info; |
| static struct |
| { |
| int mod; |
| int reg; |
| int rm; |
| } |
| modrm; |
| static unsigned char need_modrm; |
| |
| /* If we are accessing mod/rm/reg without need_modrm set, then the |
| values are stale. Hitting this abort likely indicates that you |
| need to update onebyte_has_modrm or twobyte_has_modrm. */ |
| #define MODRM_CHECK if (!need_modrm) abort () |
| |
| static const char * const *names64; |
| static const char * const *names32; |
| static const char * const *names16; |
| static const char * const *names8; |
| static const char * const *names8rex; |
| static const char * const *names_seg; |
| static const char * const *index16; |
| |
| static const char * const intel_names64[] = { |
| "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", |
| "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" |
| }; |
| static const char * const intel_names32[] = { |
| "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", |
| "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" |
| }; |
| static const char * const intel_names16[] = { |
| "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", |
| "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" |
| }; |
| static const char * const intel_names8[] = { |
| "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", |
| }; |
| static const char * const intel_names8rex[] = { |
| "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", |
| "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" |
| }; |
| static const char * const intel_names_seg[] = { |
| "es", "cs", "ss", "ds", "fs", "gs", "?", "?", |
| }; |
| static const char * const intel_index16[] = { |
| "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" |
| }; |
| |
| static const char * const att_names64[] = { |
| "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", |
| "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" |
| }; |
| static const char * const att_names32[] = { |
| "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", |
| "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" |
| }; |
| static const char * const att_names16[] = { |
| "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", |
| "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" |
| }; |
| static const char * const att_names8[] = { |
| "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", |
| }; |
| static const char * const att_names8rex[] = { |
| "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", |
| "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" |
| }; |
| static const char * const att_names_seg[] = { |
| "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", |
| }; |
| static const char * const att_index16[] = { |
| "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx" |
| }; |
| |
| static const struct dis386 grps[][8] = { |
| /* GRP1a */ |
| { |
| { "popU", { stackEv } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP1b */ |
| { |
| { "addA", { Eb, Ib } }, |
| { "orA", { Eb, Ib } }, |
| { "adcA", { Eb, Ib } }, |
| { "sbbA", { Eb, Ib } }, |
| { "andA", { Eb, Ib } }, |
| { "subA", { Eb, Ib } }, |
| { "xorA", { Eb, Ib } }, |
| { "cmpA", { Eb, Ib } }, |
| }, |
| /* GRP1S */ |
| { |
| { "addQ", { Ev, Iv } }, |
| { "orQ", { Ev, Iv } }, |
| { "adcQ", { Ev, Iv } }, |
| { "sbbQ", { Ev, Iv } }, |
| { "andQ", { Ev, Iv } }, |
| { "subQ", { Ev, Iv } }, |
| { "xorQ", { Ev, Iv } }, |
| { "cmpQ", { Ev, Iv } }, |
| }, |
| /* GRP1Ss */ |
| { |
| { "addQ", { Ev, sIb } }, |
| { "orQ", { Ev, sIb } }, |
| { "adcQ", { Ev, sIb } }, |
| { "sbbQ", { Ev, sIb } }, |
| { "andQ", { Ev, sIb } }, |
| { "subQ", { Ev, sIb } }, |
| { "xorQ", { Ev, sIb } }, |
| { "cmpQ", { Ev, sIb } }, |
| }, |
| /* GRP2b */ |
| { |
| { "rolA", { Eb, Ib } }, |
| { "rorA", { Eb, Ib } }, |
| { "rclA", { Eb, Ib } }, |
| { "rcrA", { Eb, Ib } }, |
| { "shlA", { Eb, Ib } }, |
| { "shrA", { Eb, Ib } }, |
| { "(bad)", { XX } }, |
| { "sarA", { Eb, Ib } }, |
| }, |
| /* GRP2S */ |
| { |
| { "rolQ", { Ev, Ib } }, |
| { "rorQ", { Ev, Ib } }, |
| { "rclQ", { Ev, Ib } }, |
| { "rcrQ", { Ev, Ib } }, |
| { "shlQ", { Ev, Ib } }, |
| { "shrQ", { Ev, Ib } }, |
| { "(bad)", { XX } }, |
| { "sarQ", { Ev, Ib } }, |
| }, |
| /* GRP2b_one */ |
| { |
| { "rolA", { Eb, I1 } }, |
| { "rorA", { Eb, I1 } }, |
| { "rclA", { Eb, I1 } }, |
| { "rcrA", { Eb, I1 } }, |
| { "shlA", { Eb, I1 } }, |
| { "shrA", { Eb, I1 } }, |
| { "(bad)", { XX } }, |
| { "sarA", { Eb, I1 } }, |
| }, |
| /* GRP2S_one */ |
| { |
| { "rolQ", { Ev, I1 } }, |
| { "rorQ", { Ev, I1 } }, |
| { "rclQ", { Ev, I1 } }, |
| { "rcrQ", { Ev, I1 } }, |
| { "shlQ", { Ev, I1 } }, |
| { "shrQ", { Ev, I1 } }, |
| { "(bad)", { XX } }, |
| { "sarQ", { Ev, I1 } }, |
| }, |
| /* GRP2b_cl */ |
| { |
| { "rolA", { Eb, CL } }, |
| { "rorA", { Eb, CL } }, |
| { "rclA", { Eb, CL } }, |
| { "rcrA", { Eb, CL } }, |
| { "shlA", { Eb, CL } }, |
| { "shrA", { Eb, CL } }, |
| { "(bad)", { XX } }, |
| { "sarA", { Eb, CL } }, |
| }, |
| /* GRP2S_cl */ |
| { |
| { "rolQ", { Ev, CL } }, |
| { "rorQ", { Ev, CL } }, |
| { "rclQ", { Ev, CL } }, |
| { "rcrQ", { Ev, CL } }, |
| { "shlQ", { Ev, CL } }, |
| { "shrQ", { Ev, CL } }, |
| { "(bad)", { XX } }, |
| { "sarQ", { Ev, CL } }, |
| }, |
| /* GRP3b */ |
| { |
| { "testA", { Eb, Ib } }, |
| { "(bad)", { Eb } }, |
| { "notA", { Eb } }, |
| { "negA", { Eb } }, |
| { "mulA", { Eb } }, /* Don't print the implicit %al register, */ |
| { "imulA", { Eb } }, /* to distinguish these opcodes from other */ |
| { "divA", { Eb } }, /* mul/imul opcodes. Do the same for div */ |
| { "idivA", { Eb } }, /* and idiv for consistency. */ |
| }, |
| /* GRP3S */ |
| { |
| { "testQ", { Ev, Iv } }, |
| { "(bad)", { XX } }, |
| { "notQ", { Ev } }, |
| { "negQ", { Ev } }, |
| { "mulQ", { Ev } }, /* Don't print the implicit register. */ |
| { "imulQ", { Ev } }, |
| { "divQ", { Ev } }, |
| { "idivQ", { Ev } }, |
| }, |
| /* GRP4 */ |
| { |
| { "incA", { Eb } }, |
| { "decA", { Eb } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP5 */ |
| { |
| { "incQ", { Ev } }, |
| { "decQ", { Ev } }, |
| { "callT", { indirEv } }, |
| { "JcallT", { indirEp } }, |
| { "jmpT", { indirEv } }, |
| { "JjmpT", { indirEp } }, |
| { "pushU", { stackEv } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP6 */ |
| { |
| { "sldtD", { Sv } }, |
| { "strD", { Sv } }, |
| { "lldt", { Ew } }, |
| { "ltr", { Ew } }, |
| { "verr", { Ew } }, |
| { "verw", { Ew } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP7 */ |
| { |
| { "sgdt{Q|IQ||}", { { VMX_Fixup, 0 } } }, |
| { "sidt{Q|IQ||}", { { PNI_Fixup, 0 } } }, |
| { "lgdt{Q|Q||}", { M } }, |
| { "lidt{Q|Q||}", { { SVME_Fixup, 0 } } }, |
| { "smswD", { Sv } }, |
| { "(bad)", { XX } }, |
| { "lmsw", { Ew } }, |
| { "invlpg", { { INVLPG_Fixup, w_mode } } }, |
| }, |
| /* GRP8 */ |
| { |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "btQ", { Ev, Ib } }, |
| { "btsQ", { Ev, Ib } }, |
| { "btrQ", { Ev, Ib } }, |
| { "btcQ", { Ev, Ib } }, |
| }, |
| /* GRP9 */ |
| { |
| { "(bad)", { XX } }, |
| { "cmpxchg8b", { { CMPXCHG8B_Fixup, q_mode } } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "", { VM } }, /* See OP_VMX. */ |
| { "vmptrst", { Mq } }, |
| }, |
| /* GRP11_C6 */ |
| { |
| { "movA", { Eb, Ib } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP11_C7 */ |
| { |
| { "movQ", { Ev, Iv } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP12 */ |
| { |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "psrlw", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| { "psraw", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| { "psllw", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP13 */ |
| { |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "psrld", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| { "psrad", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| { "pslld", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRP14 */ |
| { |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "psrlq", { MS, Ib } }, |
| { "psrldq", { MS, Ib } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "psllq", { MS, Ib } }, |
| { "pslldq", { MS, Ib } }, |
| }, |
| /* GRP15 */ |
| { |
| { "fxsave", { Ev } }, |
| { "fxrstor", { Ev } }, |
| { "ldmxcsr", { Ev } }, |
| { "stmxcsr", { Ev } }, |
| { "(bad)", { XX } }, |
| { "lfence", { { OP_0fae, 0 } } }, |
| { "mfence", { { OP_0fae, 0 } } }, |
| { "clflush", { { OP_0fae, 0 } } }, |
| }, |
| /* GRP16 */ |
| { |
| { "prefetchnta", { Ev } }, |
| { "prefetcht0", { Ev } }, |
| { "prefetcht1", { Ev } }, |
| { "prefetcht2", { Ev } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRPAMD */ |
| { |
| { "prefetch", { Eb } }, |
| { "prefetchw", { Eb } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| { "(bad)", { XX } }, |
| }, |
| /* GRPPADLCK1 */ |
| { |
| { "xstore-rng", { { OP_0f07, 0 } } }, |
| { "xcrypt-ecb", { { OP_0f07, 0 } } }, |
| { "xcrypt-cbc", { { OP_0f07, 0 } } }, |
| { "xcrypt-ctr", { { OP_0f07, 0 } } }, |
| { "xcrypt-cfb", { { OP_0f07, 0 } } }, |
| { "xcrypt-ofb", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| }, |
| /* GRPPADLCK2 */ |
| { |
| { "montmul", { { OP_0f07, 0 } } }, |
| { "xsha1", { { OP_0f07, 0 } } }, |
| { "xsha256", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| { "(bad)", { { OP_0f07, 0 } } }, |
| } |
| }; |
| |
| static const struct dis386 prefix_user_table[][4] = { |
| /* PREGRP0 */ |
| { |
| { "addps", { XM, EXx } }, |
| { "addss", { XM, EXd } }, |
| { "addpd", { XM, EXx } }, |
| { "addsd", { XM, EXq } }, |
| }, |
| /* PREGRP1 */ |
| { |
| { "", { XM, EXx, OPSIMD } }, /* See OP_SIMD_SUFFIX. */ |
| { "", { XM, EXx, OPSIMD } }, |
| { "", { XM, EXx, OPSIMD } }, |
| { "", { XM, EXx, OPSIMD } }, |
| }, |
| /* PREGRP2 */ |
| { |
| { "cvtpi2ps", { XM, EMC } }, |
| { "cvtsi2ssY", { XM, Ev } }, |
| { "cvtpi2pd", { XM, EMC } }, |
| { "cvtsi2sdY", { XM, Ev } }, |
| }, |
| /* PREGRP3 */ |
| { |
| { "cvtps2pi", { MXC, EXx } }, |
| { "cvtss2siY", { Gv, EXx } }, |
| { "cvtpd2pi", { MXC, EXx } }, |
| { "cvtsd2siY", { Gv, EXx } }, |
| }, |
| /* PREGRP4 */ |
| { |
| { "cvttps2pi", { MXC, EXx } }, |
| { "cvttss2siY", { Gv, EXx } }, |
| { "cvttpd2pi", { MXC, EXx } }, |
| { "cvttsd2siY", { Gv, EXx } }, |
| }, |
| /* PREGRP5 */ |
| { |
| { "divps", { XM, EXx } }, |
| { "divss", { XM, EXx } }, |
| { "divpd", { XM, EXx } }, |
| { "divsd", { XM, EXx } }, |
| }, |
| /* PREGRP6 */ |
| { |
| { "maxps", { XM, EXx } }, |
| { "maxss", { XM, EXx } }, |
| { "maxpd", { XM, EXx } }, |
| { "maxsd", { XM, EXx } }, |
| }, |
| /* PREGRP7 */ |
| { |
| { "minps", { XM, EXx } }, |
| { "minss", { XM, EXx } }, |
| { "minpd", { XM, EXx } }, |
| { "minsd", { XM |