| /* Print i386 instructions for GDB, the GNU debugger. |
| Copyright (C) 1988-2024 Free Software Foundation, Inc. |
| |
| This file is part of the GNU opcodes library. |
| |
| This library 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 3, or (at your option) |
| any later version. |
| |
| It 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, write to the Free Software |
| Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
| MA 02110-1301, USA. */ |
| |
| |
| /* 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 "sysdep.h" |
| #include "disassemble.h" |
| #include "opintl.h" |
| #include "opcode/i386.h" |
| #include "libiberty.h" |
| #include "safe-ctype.h" |
| |
| typedef struct instr_info instr_info; |
| |
| static bool dofloat (instr_info *, int); |
| static int putop (instr_info *, const char *, int); |
| static void oappend_with_style (instr_info *, const char *, |
| enum disassembler_style); |
| |
| static bool OP_E (instr_info *, int, int); |
| static bool OP_E_memory (instr_info *, int, int); |
| static bool OP_indirE (instr_info *, int, int); |
| static bool OP_G (instr_info *, int, int); |
| static bool OP_ST (instr_info *, int, int); |
| static bool OP_STi (instr_info *, int, int); |
| static bool OP_Skip_MODRM (instr_info *, int, int); |
| static bool OP_REG (instr_info *, int, int); |
| static bool OP_IMREG (instr_info *, int, int); |
| static bool OP_I (instr_info *, int, int); |
| static bool OP_I64 (instr_info *, int, int); |
| static bool OP_sI (instr_info *, int, int); |
| static bool OP_J (instr_info *, int, int); |
| static bool OP_SEG (instr_info *, int, int); |
| static bool OP_DIR (instr_info *, int, int); |
| static bool OP_OFF (instr_info *, int, int); |
| static bool OP_OFF64 (instr_info *, int, int); |
| static bool OP_ESreg (instr_info *, int, int); |
| static bool OP_DSreg (instr_info *, int, int); |
| static bool OP_C (instr_info *, int, int); |
| static bool OP_D (instr_info *, int, int); |
| static bool OP_T (instr_info *, int, int); |
| static bool OP_MMX (instr_info *, int, int); |
| static bool OP_XMM (instr_info *, int, int); |
| static bool OP_EM (instr_info *, int, int); |
| static bool OP_EX (instr_info *, int, int); |
| static bool OP_EMC (instr_info *, int,int); |
| static bool OP_MXC (instr_info *, int,int); |
| static bool OP_R (instr_info *, int, int); |
| static bool OP_M (instr_info *, int, int); |
| static bool OP_VEX (instr_info *, int, int); |
| static bool OP_VexR (instr_info *, int, int); |
| static bool OP_VexW (instr_info *, int, int); |
| static bool OP_Rounding (instr_info *, int, int); |
| static bool OP_REG_VexI4 (instr_info *, int, int); |
| static bool OP_VexI4 (instr_info *, int, int); |
| static bool OP_0f07 (instr_info *, int, int); |
| static bool OP_Monitor (instr_info *, int, int); |
| static bool OP_Mwait (instr_info *, int, int); |
| |
| static bool PCLMUL_Fixup (instr_info *, int, int); |
| static bool VPCMP_Fixup (instr_info *, int, int); |
| static bool VPCOM_Fixup (instr_info *, int, int); |
| static bool NOP_Fixup (instr_info *, int, int); |
| static bool OP_3DNowSuffix (instr_info *, int, int); |
| static bool CMP_Fixup (instr_info *, int, int); |
| static bool REP_Fixup (instr_info *, int, int); |
| static bool SEP_Fixup (instr_info *, int, int); |
| static bool BND_Fixup (instr_info *, int, int); |
| static bool NOTRACK_Fixup (instr_info *, int, int); |
| static bool HLE_Fixup1 (instr_info *, int, int); |
| static bool HLE_Fixup2 (instr_info *, int, int); |
| static bool HLE_Fixup3 (instr_info *, int, int); |
| static bool CMPXCHG8B_Fixup (instr_info *, int, int); |
| static bool XMM_Fixup (instr_info *, int, int); |
| static bool FXSAVE_Fixup (instr_info *, int, int); |
| static bool MOVSXD_Fixup (instr_info *, int, int); |
| static bool DistinctDest_Fixup (instr_info *, int, int); |
| static bool PREFETCHI_Fixup (instr_info *, int, int); |
| static bool PUSH2_POP2_Fixup (instr_info *, int, int); |
| static bool JMPABS_Fixup (instr_info *, int, int); |
| static bool CFCMOV_Fixup (instr_info *, int, int); |
| |
| static void ATTRIBUTE_PRINTF_3 i386_dis_printf (const disassemble_info *, |
| enum disassembler_style, |
| const char *, ...); |
| |
| /* This character is used to encode style information within the output |
| buffers. See oappend_insert_style for more details. */ |
| #define STYLE_MARKER_CHAR '\002' |
| |
| /* The maximum operand buffer size. */ |
| #define MAX_OPERAND_BUFFER_SIZE 128 |
| |
| enum address_mode |
| { |
| mode_16bit, |
| mode_32bit, |
| mode_64bit |
| }; |
| |
| static const char *prefix_name (enum address_mode, uint8_t, int); |
| |
| enum x86_64_isa |
| { |
| amd64 = 1, |
| intel64 |
| }; |
| |
| enum evex_type |
| { |
| evex_default = 0, |
| evex_from_legacy, |
| evex_from_vex, |
| }; |
| |
| struct instr_info |
| { |
| enum address_mode address_mode; |
| |
| /* Flags for the prefixes for the current instruction. See below. */ |
| int prefixes; |
| |
| /* REX prefix the current instruction. See below. */ |
| uint8_t rex; |
| /* Bits of REX we've already used. */ |
| uint8_t rex_used; |
| |
| /* Record W R4 X4 B4 bits for rex2. */ |
| unsigned char rex2; |
| /* Bits of rex2 we've already used. */ |
| unsigned char rex2_used; |
| unsigned char rex2_payload; |
| |
| bool need_modrm; |
| unsigned char condition_code; |
| unsigned char need_vex; |
| bool has_sib; |
| |
| /* Flags for ins->prefixes which we somehow handled when printing the |
| current instruction. */ |
| int used_prefixes; |
| |
| /* Flags for EVEX bits which we somehow handled when printing the |
| current instruction. */ |
| int evex_used; |
| |
| char obuf[MAX_OPERAND_BUFFER_SIZE]; |
| char *obufp; |
| char *mnemonicendp; |
| const uint8_t *start_codep; |
| uint8_t *codep; |
| const uint8_t *end_codep; |
| unsigned char nr_prefixes; |
| signed char last_lock_prefix; |
| signed char last_repz_prefix; |
| signed char last_repnz_prefix; |
| signed char last_data_prefix; |
| signed char last_addr_prefix; |
| signed char last_rex_prefix; |
| signed char last_rex2_prefix; |
| signed char last_seg_prefix; |
| signed char fwait_prefix; |
| /* The active segment register prefix. */ |
| unsigned char active_seg_prefix; |
| |
| #define MAX_CODE_LENGTH 15 |
| /* We can up to 14 ins->prefixes since the maximum instruction length is |
| 15bytes. */ |
| uint8_t all_prefixes[MAX_CODE_LENGTH - 1]; |
| disassemble_info *info; |
| |
| struct |
| { |
| int mod; |
| int reg; |
| int rm; |
| } |
| modrm; |
| |
| struct |
| { |
| int scale; |
| int index; |
| int base; |
| } |
| sib; |
| |
| struct |
| { |
| int register_specifier; |
| int length; |
| int prefix; |
| int mask_register_specifier; |
| int scc; |
| int ll; |
| bool w; |
| bool evex; |
| bool v; |
| bool zeroing; |
| bool b; |
| bool no_broadcast; |
| bool nf; |
| bool u; |
| } |
| vex; |
| |
| /* For APX EVEX-promoted prefix, EVEX.ND shares the same bit as vex.b. */ |
| #define nd b |
| |
| enum evex_type evex_type; |
| |
| /* Remember if the current op is a jump instruction. */ |
| bool op_is_jump; |
| |
| bool two_source_ops; |
| |
| /* Record whether EVEX masking is used incorrectly. */ |
| bool illegal_masking; |
| |
| /* Record whether the modrm byte has been skipped. */ |
| bool has_skipped_modrm; |
| |
| unsigned char op_ad; |
| signed char op_index[MAX_OPERANDS]; |
| bool op_riprel[MAX_OPERANDS]; |
| char *op_out[MAX_OPERANDS]; |
| bfd_vma op_address[MAX_OPERANDS]; |
| bfd_vma start_pc; |
| |
| /* On the 386's of 1988, the maximum length of an instruction is 15 bytes. |
| * (see topic "Redundant ins->prefixes" in the "Differences from 8086" |
| * section of the "Virtual 8086 Mode" chapter.) |
| * 'pc' should be the address of this instruction, it will |
| * be used to print the target address if this is a relative jump or call |
| * The function returns the length of this instruction in bytes. |
| */ |
| char intel_syntax; |
| bool intel_mnemonic; |
| char open_char; |
| char close_char; |
| char separator_char; |
| char scale_char; |
| |
| enum x86_64_isa isa64; |
| }; |
| |
| struct dis_private { |
| bfd_vma insn_start; |
| int orig_sizeflag; |
| |
| /* Indexes first byte not fetched. */ |
| unsigned int fetched; |
| uint8_t the_buffer[2 * MAX_CODE_LENGTH - 1]; |
| }; |
| |
| /* 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 (ins->rex & value) \ |
| ins->rex_used |= (value) | REX_OPCODE; \ |
| if (ins->rex2 & value) \ |
| { \ |
| ins->rex2_used |= (value); \ |
| ins->rex_used |= REX_OPCODE; \ |
| } \ |
| } \ |
| else \ |
| ins->rex_used |= REX_OPCODE; \ |
| } |
| |
| |
| #define EVEX_b_used 1 |
| #define EVEX_len_used 2 |
| |
| |
| /* {rex2} is not printed when the REX2_SPECIAL is set. */ |
| #define REX2_SPECIAL 16 |
| |
| /* Flags stored in PREFIXES. */ |
| #define PREFIX_REPZ 1 |
| #define PREFIX_REPNZ 2 |
| #define PREFIX_CS 4 |
| #define PREFIX_SS 8 |
| #define PREFIX_DS 0x10 |
| #define PREFIX_ES 0x20 |
| #define PREFIX_FS 0x40 |
| #define PREFIX_GS 0x80 |
| #define PREFIX_LOCK 0x100 |
| #define PREFIX_DATA 0x200 |
| #define PREFIX_ADDR 0x400 |
| #define PREFIX_FWAIT 0x800 |
| #define PREFIX_REX2 0x1000 |
| #define PREFIX_NP_OR_DATA 0x2000 |
| #define NO_PREFIX 0x4000 |
| |
| /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) |
| to ADDR (exclusive) are valid. Returns true for success, false |
| on error. */ |
| static bool |
| fetch_code (struct disassemble_info *info, const uint8_t *until) |
| { |
| int status = -1; |
| struct dis_private *priv = info->private_data; |
| bfd_vma start = priv->insn_start + priv->fetched; |
| uint8_t *fetch_end = priv->the_buffer + priv->fetched; |
| ptrdiff_t needed = until - fetch_end; |
| |
| if (needed <= 0) |
| return true; |
| |
| if (priv->fetched + (size_t) needed <= ARRAY_SIZE (priv->the_buffer)) |
| status = (*info->read_memory_func) (start, fetch_end, needed, info); |
| 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->fetched) |
| (*info->memory_error_func) (status, start, info); |
| return false; |
| } |
| |
| priv->fetched += needed; |
| return true; |
| } |
| |
| static bool |
| fetch_modrm (instr_info *ins) |
| { |
| if (!fetch_code (ins->info, ins->codep + 1)) |
| return false; |
| |
| ins->modrm.mod = (*ins->codep >> 6) & 3; |
| ins->modrm.reg = (*ins->codep >> 3) & 7; |
| ins->modrm.rm = *ins->codep & 7; |
| |
| return true; |
| } |
| |
| static int |
| fetch_error (const instr_info *ins) |
| { |
| /* Getting here means we tried for data but didn't get it. That |
| means we have an incomplete instruction of some sort. Just |
| print the first byte as a prefix or a .byte pseudo-op. */ |
| const struct dis_private *priv = ins->info->private_data; |
| const char *name = NULL; |
| |
| if (ins->codep <= priv->the_buffer) |
| return -1; |
| |
| if (ins->prefixes || ins->fwait_prefix >= 0 || (ins->rex & REX_OPCODE)) |
| name = prefix_name (ins->address_mode, priv->the_buffer[0], |
| priv->orig_sizeflag); |
| if (name != NULL) |
| i386_dis_printf (ins->info, dis_style_mnemonic, "%s", name); |
| else |
| { |
| /* Just print the first byte as a .byte instruction. */ |
| i386_dis_printf (ins->info, dis_style_assembler_directive, ".byte "); |
| i386_dis_printf (ins->info, dis_style_immediate, "%#x", |
| (unsigned int) priv->the_buffer[0]); |
| } |
| |
| return 1; |
| } |
| |
| /* Possible values for prefix requirement. */ |
| #define PREFIX_IGNORED_SHIFT 16 |
| #define PREFIX_IGNORED_REPZ (PREFIX_REPZ << PREFIX_IGNORED_SHIFT) |
| #define PREFIX_IGNORED_REPNZ (PREFIX_REPNZ << PREFIX_IGNORED_SHIFT) |
| #define PREFIX_IGNORED_DATA (PREFIX_DATA << PREFIX_IGNORED_SHIFT) |
| #define PREFIX_IGNORED_ADDR (PREFIX_ADDR << PREFIX_IGNORED_SHIFT) |
| #define PREFIX_IGNORED_LOCK (PREFIX_LOCK << PREFIX_IGNORED_SHIFT) |
| #define PREFIX_REX2_ILLEGAL (PREFIX_REX2 << PREFIX_IGNORED_SHIFT) |
| |
| /* Opcode prefixes. */ |
| #define PREFIX_OPCODE (PREFIX_REPZ \ |
| | PREFIX_REPNZ \ |
| | PREFIX_DATA) |
| |
| /* Prefixes ignored. */ |
| #define PREFIX_IGNORED (PREFIX_IGNORED_REPZ \ |
| | PREFIX_IGNORED_REPNZ \ |
| | PREFIX_IGNORED_DATA) |
| |
| #define XX { NULL, 0 } |
| #define Bad_Opcode NULL, { { NULL, 0 } }, 0 |
| |
| #define Eb { OP_E, b_mode } |
| #define Ebnd { OP_E, bnd_mode } |
| #define EbS { OP_E, b_swap_mode } |
| #define EbndS { OP_E, bnd_swap_mode } |
| #define Ev { OP_E, v_mode } |
| #define Eva { OP_E, va_mode } |
| #define Ev_bnd { OP_E, v_bnd_mode } |
| #define EvS { OP_E, v_swap_mode } |
| #define Ed { OP_E, d_mode } |
| #define Edq { OP_E, dq_mode } |
| #define Edb { OP_E, db_mode } |
| #define Edw { OP_E, dw_mode } |
| #define Eq { OP_E, q_mode } |
| #define indirEv { OP_indirE, indir_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, a_mode } |
| #define Mb { OP_M, b_mode } |
| #define Md { OP_M, d_mode } |
| #define Mdq { OP_M, dq_mode } |
| #define Mo { OP_M, o_mode } |
| #define Mp { OP_M, f_mode } /* 32 or 48 bit memory operand for LDS, LES etc */ |
| #define Mq { OP_M, q_mode } |
| #define Mv { OP_M, v_mode } |
| #define Mv_bnd { OP_M, v_bndmk_mode } |
| #define Mw { OP_M, w_mode } |
| #define Mx { OP_M, x_mode } |
| #define Mxmm { OP_M, xmm_mode } |
| #define Mymm { OP_M, ymm_mode } |
| #define Gb { OP_G, b_mode } |
| #define Gbnd { OP_G, bnd_mode } |
| #define Gv { OP_G, v_mode } |
| #define Gd { OP_G, d_mode } |
| #define Gdq { OP_G, dq_mode } |
| #define Gq { OP_G, q_mode } |
| #define Gm { OP_G, m_mode } |
| #define Gva { OP_G, va_mode } |
| #define Gw { OP_G, w_mode } |
| #define Ib { OP_I, b_mode } |
| #define sIb { OP_sI, b_mode } /* sign extened byte */ |
| #define sIbT { OP_sI, b_T_mode } /* sign extened byte like 'T' */ |
| #define Iv { OP_I, v_mode } |
| #define sIv { OP_sI, v_mode } |
| #define Iv64 { OP_I64, v_mode } |
| #define Id { OP_I, d_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 Jdqw { OP_J, dqw_mode } |
| #define Cm { OP_C, m_mode } |
| #define Dm { OP_D, m_mode } |
| #define Td { OP_T, d_mode } |
| #define Skip_MODRM { OP_Skip_MODRM, 0 } |
| |
| #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 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 AL { OP_IMREG, al_reg } |
| #define CL { OP_IMREG, cl_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 XMScalar { OP_XMM, scalar_mode } |
| #define XMGatherD { OP_XMM, vex_vsib_d_w_dq_mode } |
| #define XMGatherQ { OP_XMM, vex_vsib_q_w_dq_mode } |
| #define XMM { OP_XMM, xmm_mode } |
| #define TMM { OP_XMM, tmm_mode } |
| #define XMxmmq { OP_XMM, xmmq_mode } |
| #define EM { OP_EM, v_mode } |
| #define EMS { OP_EM, v_swap_mode } |
| #define EMd { OP_EM, d_mode } |
| #define EMx { OP_EM, x_mode } |
| #define EXbwUnit { OP_EX, bw_unit_mode } |
| #define EXb { OP_EX, b_mode } |
| #define EXw { OP_EX, w_mode } |
| #define EXd { OP_EX, d_mode } |
| #define EXdS { OP_EX, d_swap_mode } |
| #define EXwS { OP_EX, w_swap_mode } |
| #define EXq { OP_EX, q_mode } |
| #define EXqS { OP_EX, q_swap_mode } |
| #define EXdq { OP_EX, dq_mode } |
| #define EXx { OP_EX, x_mode } |
| #define EXxh { OP_EX, xh_mode } |
| #define EXxS { OP_EX, x_swap_mode } |
| #define EXxmm { OP_EX, xmm_mode } |
| #define EXymm { OP_EX, ymm_mode } |
| #define EXxmmq { OP_EX, xmmq_mode } |
| #define EXxmmqh { OP_EX, evex_half_bcst_xmmqh_mode } |
| #define EXEvexHalfBcstXmmq { OP_EX, evex_half_bcst_xmmq_mode } |
| #define EXxmmdw { OP_EX, xmmdw_mode } |
| #define EXxmmqd { OP_EX, xmmqd_mode } |
| #define EXxmmqdh { OP_EX, evex_half_bcst_xmmqdh_mode } |
| #define EXymmq { OP_EX, ymmq_mode } |
| #define EXEvexXGscat { OP_EX, evex_x_gscat_mode } |
| #define EXEvexXNoBcst { OP_EX, evex_x_nobcst_mode } |
| #define Rd { OP_R, d_mode } |
| #define Rdq { OP_R, dq_mode } |
| #define Rq { OP_R, q_mode } |
| #define Nq { OP_R, q_mm_mode } |
| #define Ux { OP_R, x_mode } |
| #define Uxmm { OP_R, xmm_mode } |
| #define Rxmmq { OP_R, xmmq_mode } |
| #define Rymm { OP_R, ymm_mode } |
| #define Rtmm { OP_R, tmm_mode } |
| #define EMCq { OP_EMC, q_mode } |
| #define MXC { OP_MXC, 0 } |
| #define OPSUF { OP_3DNowSuffix, 0 } |
| #define SEP { SEP_Fixup, 0 } |
| #define CMP { CMP_Fixup, 0 } |
| #define XMM0 { XMM_Fixup, 0 } |
| #define FXSAVE { FXSAVE_Fixup, 0 } |
| |
| #define Vex { OP_VEX, x_mode } |
| #define VexW { OP_VexW, x_mode } |
| #define VexScalar { OP_VEX, scalar_mode } |
| #define VexScalarR { OP_VexR, scalar_mode } |
| #define VexGatherD { OP_VEX, vex_vsib_d_w_dq_mode } |
| #define VexGatherQ { OP_VEX, vex_vsib_q_w_dq_mode } |
| #define VexGdq { OP_VEX, dq_mode } |
| #define VexGb { OP_VEX, b_mode } |
| #define VexGv { OP_VEX, v_mode } |
| #define VexTmm { OP_VEX, tmm_mode } |
| #define XMVexI4 { OP_REG_VexI4, x_mode } |
| #define XMVexScalarI4 { OP_REG_VexI4, scalar_mode } |
| #define VexI4 { OP_VexI4, 0 } |
| #define PCLMUL { PCLMUL_Fixup, 0 } |
| #define VPCMP { VPCMP_Fixup, 0 } |
| #define VPCOM { VPCOM_Fixup, 0 } |
| |
| #define EXxEVexR { OP_Rounding, evex_rounding_mode } |
| #define EXxEVexR64 { OP_Rounding, evex_rounding_64_mode } |
| #define EXxEVexS { OP_Rounding, evex_sae_mode } |
| |
| #define MaskG { OP_G, mask_mode } |
| #define MaskE { OP_E, mask_mode } |
| #define MaskR { OP_R, mask_mode } |
| #define MaskBDE { OP_E, mask_bd_mode } |
| #define MaskVex { OP_VEX, mask_mode } |
| |
| #define MVexVSIBDWpX { OP_M, vex_vsib_d_w_dq_mode } |
| #define MVexVSIBQWpX { OP_M, vex_vsib_q_w_dq_mode } |
| |
| #define MVexSIBMEM { OP_M, vex_sibmem_mode } |
| |
| /* 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 } |
| |
| /* Used handle HLE prefix for lockable instructions. */ |
| #define Ebh1 { HLE_Fixup1, b_mode } |
| #define Evh1 { HLE_Fixup1, v_mode } |
| #define Ebh2 { HLE_Fixup2, b_mode } |
| #define Evh2 { HLE_Fixup2, v_mode } |
| #define Ebh3 { HLE_Fixup3, b_mode } |
| #define Evh3 { HLE_Fixup3, v_mode } |
| |
| #define BND { BND_Fixup, 0 } |
| #define NOTRACK { NOTRACK_Fixup, 0 } |
| |
| #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 |
| |
| enum |
| { |
| /* byte operand */ |
| b_mode = 1, |
| /* byte operand with operand swapped */ |
| b_swap_mode, |
| /* byte operand, sign extend like 'T' suffix */ |
| b_T_mode, |
| /* operand size depends on prefixes */ |
| v_mode, |
| /* operand size depends on prefixes with operand swapped */ |
| v_swap_mode, |
| /* operand size depends on address prefix */ |
| va_mode, |
| /* word operand */ |
| w_mode, |
| /* double word operand */ |
| d_mode, |
| /* word operand with operand swapped */ |
| w_swap_mode, |
| /* double word operand with operand swapped */ |
| d_swap_mode, |
| /* quad word operand */ |
| q_mode, |
| /* 8-byte MM operand */ |
| q_mm_mode, |
| /* quad word operand with operand swapped */ |
| q_swap_mode, |
| /* ten-byte operand */ |
| t_mode, |
| /* 16-byte XMM, 32-byte YMM or 64-byte ZMM operand. In EVEX with |
| broadcast enabled. */ |
| x_mode, |
| /* Similar to x_mode, but with different EVEX mem shifts. */ |
| evex_x_gscat_mode, |
| /* Similar to x_mode, but with yet different EVEX mem shifts. */ |
| bw_unit_mode, |
| /* Similar to x_mode, but with disabled broadcast. */ |
| evex_x_nobcst_mode, |
| /* Similar to x_mode, but with operands swapped and disabled broadcast |
| in EVEX. */ |
| x_swap_mode, |
| /* 16-byte XMM, 32-byte YMM or 64-byte ZMM operand. In EVEX with |
| broadcast of 16bit enabled. */ |
| xh_mode, |
| /* 16-byte XMM operand */ |
| xmm_mode, |
| /* XMM, XMM or YMM register operand, or quad word, xmmword or ymmword |
| memory operand (depending on vector length). Broadcast isn't |
| allowed. */ |
| xmmq_mode, |
| /* Same as xmmq_mode, but broadcast is allowed. */ |
| evex_half_bcst_xmmq_mode, |
| /* XMM, XMM or YMM register operand, or quad word, xmmword or ymmword |
| memory operand (depending on vector length). 16bit broadcast. */ |
| evex_half_bcst_xmmqh_mode, |
| /* 16-byte XMM, word, double word or quad word operand. */ |
| xmmdw_mode, |
| /* 16-byte XMM, double word, quad word operand or xmm word operand. */ |
| xmmqd_mode, |
| /* 16-byte XMM, double word, quad word operand or xmm word operand. |
| 16bit broadcast. */ |
| evex_half_bcst_xmmqdh_mode, |
| /* 32-byte YMM operand */ |
| ymm_mode, |
| /* quad word, ymmword or zmmword memory operand. */ |
| ymmq_mode, |
| /* TMM operand */ |
| tmm_mode, |
| /* d_mode in 32bit, q_mode in 64bit mode. */ |
| m_mode, |
| /* pair of v_mode operands */ |
| a_mode, |
| cond_jump_mode, |
| loop_jcxz_mode, |
| movsxd_mode, |
| v_bnd_mode, |
| /* like v_bnd_mode in 32bit, no RIP-rel in 64bit mode. */ |
| v_bndmk_mode, |
| /* operand size depends on REX.W / VEX.W. */ |
| dq_mode, |
| /* Displacements like v_mode without considering Intel64 ISA. */ |
| dqw_mode, |
| /* bounds operand */ |
| bnd_mode, |
| /* bounds operand with operand swapped */ |
| bnd_swap_mode, |
| /* 4- or 6-byte pointer operand */ |
| f_mode, |
| const_1_mode, |
| /* v_mode for indirect branch opcodes. */ |
| indir_v_mode, |
| /* v_mode for stack-related opcodes. */ |
| stack_v_mode, |
| /* non-quad operand size depends on prefixes */ |
| z_mode, |
| /* 16-byte operand */ |
| o_mode, |
| /* registers like d_mode, memory like b_mode. */ |
| db_mode, |
| /* registers like d_mode, memory like w_mode. */ |
| dw_mode, |
| |
| /* Operand size depends on the VEX.W bit, with VSIB dword indices. */ |
| vex_vsib_d_w_dq_mode, |
| /* Operand size depends on the VEX.W bit, with VSIB qword indices. */ |
| vex_vsib_q_w_dq_mode, |
| /* mandatory non-vector SIB. */ |
| vex_sibmem_mode, |
| |
| /* scalar, ignore vector length. */ |
| scalar_mode, |
| |
| /* Static rounding. */ |
| evex_rounding_mode, |
| /* Static rounding, 64-bit mode only. */ |
| evex_rounding_64_mode, |
| /* Supress all exceptions. */ |
| evex_sae_mode, |
| |
| /* Mask register operand. */ |
| mask_mode, |
| /* Mask register operand. */ |
| mask_bd_mode, |
| |
| es_reg, |
| cs_reg, |
| ss_reg, |
| ds_reg, |
| fs_reg, |
| gs_reg, |
| |
| eAX_reg, |
| eCX_reg, |
| eDX_reg, |
| eBX_reg, |
| eSP_reg, |
| eBP_reg, |
| eSI_reg, |
| eDI_reg, |
| |
| al_reg, |
| cl_reg, |
| dl_reg, |
| bl_reg, |
| ah_reg, |
| ch_reg, |
| dh_reg, |
| bh_reg, |
| |
| ax_reg, |
| cx_reg, |
| dx_reg, |
| bx_reg, |
| sp_reg, |
| bp_reg, |
| si_reg, |
| di_reg, |
| |
| rAX_reg, |
| rCX_reg, |
| rDX_reg, |
| rBX_reg, |
| rSP_reg, |
| rBP_reg, |
| rSI_reg, |
| rDI_reg, |
| |
| z_mode_ax_reg, |
| indir_dx_reg |
| }; |
| |
| enum |
| { |
| FLOATCODE = 1, |
| USE_REG_TABLE, |
| USE_MOD_TABLE, |
| USE_RM_TABLE, |
| USE_PREFIX_TABLE, |
| USE_X86_64_TABLE, |
| USE_X86_64_EVEX_FROM_VEX_TABLE, |
| USE_X86_64_EVEX_PFX_TABLE, |
| USE_X86_64_EVEX_W_TABLE, |
| USE_X86_64_EVEX_MEM_W_TABLE, |
| USE_3BYTE_TABLE, |
| USE_XOP_8F_TABLE, |
| USE_VEX_C4_TABLE, |
| USE_VEX_C5_TABLE, |
| USE_VEX_LEN_TABLE, |
| USE_VEX_W_TABLE, |
| USE_EVEX_TABLE, |
| USE_EVEX_LEN_TABLE |
| }; |
| |
| #define FLOAT NULL, { { NULL, FLOATCODE } }, 0 |
| |
| #define DIS386(T, I) NULL, { { NULL, (T)}, { NULL, (I) } }, 0 |
| #define REG_TABLE(I) DIS386 (USE_REG_TABLE, (I)) |
| #define MOD_TABLE(I) DIS386 (USE_MOD_TABLE, (I)) |
| #define RM_TABLE(I) DIS386 (USE_RM_TABLE, (I)) |
| #define PREFIX_TABLE(I) DIS386 (USE_PREFIX_TABLE, (I)) |
| #define X86_64_TABLE(I) DIS386 (USE_X86_64_TABLE, (I)) |
| #define X86_64_EVEX_FROM_VEX_TABLE(I) \ |
| DIS386 (USE_X86_64_EVEX_FROM_VEX_TABLE, (I)) |
| #define X86_64_EVEX_PFX_TABLE(I) DIS386 (USE_X86_64_EVEX_PFX_TABLE, (I)) |
| #define X86_64_EVEX_W_TABLE(I) DIS386 (USE_X86_64_EVEX_W_TABLE, (I)) |
| #define X86_64_EVEX_MEM_W_TABLE(I) DIS386 (USE_X86_64_EVEX_MEM_W_TABLE, (I)) |
| #define THREE_BYTE_TABLE(I) DIS386 (USE_3BYTE_TABLE, (I)) |
| #define XOP_8F_TABLE() DIS386 (USE_XOP_8F_TABLE, 0) |
| #define VEX_C4_TABLE() DIS386 (USE_VEX_C4_TABLE, 0) |
| #define VEX_C5_TABLE() DIS386 (USE_VEX_C5_TABLE, 0) |
| #define VEX_LEN_TABLE(I) DIS386 (USE_VEX_LEN_TABLE, (I)) |
| #define VEX_W_TABLE(I) DIS386 (USE_VEX_W_TABLE, (I)) |
| #define EVEX_TABLE() DIS386 (USE_EVEX_TABLE, 0) |
| #define EVEX_LEN_TABLE(I) DIS386 (USE_EVEX_LEN_TABLE, (I)) |
| |
| enum |
| { |
| REG_80 = 0, |
| REG_81, |
| REG_83, |
| REG_8F, |
| REG_C0, |
| REG_C1, |
| REG_C6, |
| REG_C7, |
| REG_D0, |
| REG_D1, |
| REG_D2, |
| REG_D3, |
| REG_F6, |
| REG_F7, |
| REG_FE, |
| REG_FF, |
| REG_0F00, |
| REG_0F01, |
| REG_0F0D, |
| REG_0F18, |
| REG_0F1C_P_0_MOD_0, |
| REG_0F1E_P_1_MOD_3, |
| REG_0F38D8_PREFIX_1, |
| REG_0F3A0F_P_1, |
| REG_0F71, |
| REG_0F72, |
| REG_0F73, |
| REG_0FA6, |
| REG_0FA7, |
| REG_0FAE, |
| REG_0FBA, |
| REG_0FC7, |
| REG_VEX_0F71, |
| REG_VEX_0F72, |
| REG_VEX_0F73, |
| REG_VEX_0FAE, |
| REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0, |
| REG_VEX_0F38F3_L_0_P_0, |
| REG_VEX_MAP7_F8_L_0_W_0, |
| |
| REG_XOP_09_01_L_0, |
| REG_XOP_09_02_L_0, |
| REG_XOP_09_12_L_0, |
| REG_XOP_0A_12_L_0, |
| |
| REG_EVEX_0F71, |
| REG_EVEX_0F72, |
| REG_EVEX_0F73, |
| REG_EVEX_0F38C6_L_2, |
| REG_EVEX_0F38C7_L_2, |
| REG_EVEX_MAP4_80, |
| REG_EVEX_MAP4_81, |
| REG_EVEX_MAP4_83, |
| REG_EVEX_MAP4_8F, |
| REG_EVEX_MAP4_F6, |
| REG_EVEX_MAP4_F7, |
| REG_EVEX_MAP4_FE, |
| REG_EVEX_MAP4_FF, |
| }; |
| |
| enum |
| { |
| MOD_62_32BIT = 0, |
| MOD_C4_32BIT, |
| MOD_C5_32BIT, |
| MOD_0F01_REG_0, |
| MOD_0F01_REG_1, |
| MOD_0F01_REG_2, |
| MOD_0F01_REG_3, |
| MOD_0F01_REG_5, |
| MOD_0F01_REG_7, |
| MOD_0F12_PREFIX_0, |
| MOD_0F16_PREFIX_0, |
| MOD_0F18_REG_0, |
| MOD_0F18_REG_1, |
| MOD_0F18_REG_2, |
| MOD_0F18_REG_3, |
| MOD_0F18_REG_6, |
| MOD_0F18_REG_7, |
| MOD_0F1A_PREFIX_0, |
| MOD_0F1B_PREFIX_0, |
| MOD_0F1B_PREFIX_1, |
| MOD_0F1C_PREFIX_0, |
| MOD_0F1E_PREFIX_1, |
| MOD_0FAE_REG_0, |
| MOD_0FAE_REG_1, |
| MOD_0FAE_REG_2, |
| MOD_0FAE_REG_3, |
| MOD_0FAE_REG_4, |
| MOD_0FAE_REG_5, |
| MOD_0FAE_REG_6, |
| MOD_0FAE_REG_7, |
| MOD_0FC7_REG_6, |
| MOD_0FC7_REG_7, |
| MOD_0F38DC_PREFIX_1, |
| MOD_0F38F8, |
| |
| MOD_VEX_0F3849_X86_64_L_0_W_0, |
| |
| MOD_EVEX_MAP4_60, |
| MOD_EVEX_MAP4_61, |
| MOD_EVEX_MAP4_F8_P_1, |
| MOD_EVEX_MAP4_F8_P_3, |
| }; |
| |
| enum |
| { |
| RM_C6_REG_7 = 0, |
| RM_C7_REG_7, |
| RM_0F01_REG_0, |
| RM_0F01_REG_1, |
| RM_0F01_REG_2, |
| RM_0F01_REG_3, |
| RM_0F01_REG_5_MOD_3, |
| RM_0F01_REG_7_MOD_3, |
| RM_0F1E_P_1_MOD_3_REG_7, |
| RM_0FAE_REG_6_MOD_3_P_0, |
| RM_0FAE_REG_7_MOD_3, |
| RM_0F3A0F_P_1_R_0, |
| |
| RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0, |
| RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3, |
| }; |
| |
| enum |
| { |
| PREFIX_90 = 0, |
| PREFIX_0F00_REG_6_X86_64, |
| PREFIX_0F01_REG_0_MOD_3_RM_6, |
| PREFIX_0F01_REG_0_MOD_3_RM_7, |
| PREFIX_0F01_REG_1_RM_2, |
| PREFIX_0F01_REG_1_RM_4, |
| PREFIX_0F01_REG_1_RM_5, |
| PREFIX_0F01_REG_1_RM_6, |
| PREFIX_0F01_REG_1_RM_7, |
| PREFIX_0F01_REG_3_RM_1, |
| PREFIX_0F01_REG_5_MOD_0, |
| PREFIX_0F01_REG_5_MOD_3_RM_0, |
| PREFIX_0F01_REG_5_MOD_3_RM_1, |
| PREFIX_0F01_REG_5_MOD_3_RM_2, |
| PREFIX_0F01_REG_5_MOD_3_RM_4, |
| PREFIX_0F01_REG_5_MOD_3_RM_5, |
| PREFIX_0F01_REG_5_MOD_3_RM_6, |
| PREFIX_0F01_REG_5_MOD_3_RM_7, |
| PREFIX_0F01_REG_7_MOD_3_RM_2, |
| PREFIX_0F01_REG_7_MOD_3_RM_5, |
| PREFIX_0F01_REG_7_MOD_3_RM_6, |
| PREFIX_0F01_REG_7_MOD_3_RM_7, |
| PREFIX_0F09, |
| PREFIX_0F10, |
| PREFIX_0F11, |
| PREFIX_0F12, |
| PREFIX_0F16, |
| PREFIX_0F18_REG_6_MOD_0_X86_64, |
| PREFIX_0F18_REG_7_MOD_0_X86_64, |
| PREFIX_0F1A, |
| PREFIX_0F1B, |
| PREFIX_0F1C, |
| PREFIX_0F1E, |
| PREFIX_0F2A, |
| PREFIX_0F2B, |
| PREFIX_0F2C, |
| PREFIX_0F2D, |
| PREFIX_0F2E, |
| PREFIX_0F2F, |
| PREFIX_0F51, |
| PREFIX_0F52, |
| PREFIX_0F53, |
| PREFIX_0F58, |
| PREFIX_0F59, |
| PREFIX_0F5A, |
| PREFIX_0F5B, |
| PREFIX_0F5C, |
| PREFIX_0F5D, |
| PREFIX_0F5E, |
| PREFIX_0F5F, |
| PREFIX_0F60, |
| PREFIX_0F61, |
| PREFIX_0F62, |
| PREFIX_0F6F, |
| PREFIX_0F70, |
| PREFIX_0F78, |
| PREFIX_0F79, |
| PREFIX_0F7C, |
| PREFIX_0F7D, |
| PREFIX_0F7E, |
| PREFIX_0F7F, |
| PREFIX_0FAE_REG_0_MOD_3, |
| PREFIX_0FAE_REG_1_MOD_3, |
| PREFIX_0FAE_REG_2_MOD_3, |
| PREFIX_0FAE_REG_3_MOD_3, |
| PREFIX_0FAE_REG_4_MOD_0, |
| PREFIX_0FAE_REG_4_MOD_3, |
| PREFIX_0FAE_REG_5_MOD_3, |
| PREFIX_0FAE_REG_6_MOD_0, |
| PREFIX_0FAE_REG_6_MOD_3, |
| PREFIX_0FAE_REG_7_MOD_0, |
| PREFIX_0FB8, |
| PREFIX_0FBC, |
| PREFIX_0FBD, |
| PREFIX_0FC2, |
| PREFIX_0FC7_REG_6_MOD_0, |
| PREFIX_0FC7_REG_6_MOD_3, |
| PREFIX_0FC7_REG_7_MOD_3, |
| PREFIX_0FD0, |
| PREFIX_0FD6, |
| PREFIX_0FE6, |
| PREFIX_0FE7, |
| PREFIX_0FF0, |
| PREFIX_0FF7, |
| PREFIX_0F38D8, |
| PREFIX_0F38DC, |
| PREFIX_0F38DD, |
| PREFIX_0F38DE, |
| PREFIX_0F38DF, |
| PREFIX_0F38F0, |
| PREFIX_0F38F1, |
| PREFIX_0F38F6, |
| PREFIX_0F38F8_M_0, |
| PREFIX_0F38F8_M_1_X86_64, |
| PREFIX_0F38FA, |
| PREFIX_0F38FB, |
| PREFIX_0F38FC, |
| PREFIX_0F3A0F, |
| PREFIX_VEX_0F12, |
| PREFIX_VEX_0F16, |
| PREFIX_VEX_0F2A, |
| PREFIX_VEX_0F2C, |
| PREFIX_VEX_0F2D, |
| PREFIX_VEX_0F41_L_1_W_0, |
| PREFIX_VEX_0F41_L_1_W_1, |
| PREFIX_VEX_0F42_L_1_W_0, |
| PREFIX_VEX_0F42_L_1_W_1, |
| PREFIX_VEX_0F44_L_0_W_0, |
| PREFIX_VEX_0F44_L_0_W_1, |
| PREFIX_VEX_0F45_L_1_W_0, |
| PREFIX_VEX_0F45_L_1_W_1, |
| PREFIX_VEX_0F46_L_1_W_0, |
| PREFIX_VEX_0F46_L_1_W_1, |
| PREFIX_VEX_0F47_L_1_W_0, |
| PREFIX_VEX_0F47_L_1_W_1, |
| PREFIX_VEX_0F4A_L_1_W_0, |
| PREFIX_VEX_0F4A_L_1_W_1, |
| PREFIX_VEX_0F4B_L_1_W_0, |
| PREFIX_VEX_0F4B_L_1_W_1, |
| PREFIX_VEX_0F6F, |
| PREFIX_VEX_0F70, |
| PREFIX_VEX_0F7E, |
| PREFIX_VEX_0F7F, |
| PREFIX_VEX_0F90_L_0_W_0, |
| PREFIX_VEX_0F90_L_0_W_1, |
| PREFIX_VEX_0F91_L_0_W_0, |
| PREFIX_VEX_0F91_L_0_W_1, |
| PREFIX_VEX_0F92_L_0_W_0, |
| PREFIX_VEX_0F92_L_0_W_1, |
| PREFIX_VEX_0F93_L_0_W_0, |
| PREFIX_VEX_0F93_L_0_W_1, |
| PREFIX_VEX_0F98_L_0_W_0, |
| PREFIX_VEX_0F98_L_0_W_1, |
| PREFIX_VEX_0F99_L_0_W_0, |
| PREFIX_VEX_0F99_L_0_W_1, |
| PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0, |
| PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1, |
| PREFIX_VEX_0F384B_X86_64_L_0_W_0, |
| PREFIX_VEX_0F3850_W_0, |
| PREFIX_VEX_0F3851_W_0, |
| PREFIX_VEX_0F385C_X86_64_L_0_W_0, |
| PREFIX_VEX_0F385E_X86_64_L_0_W_0, |
| PREFIX_VEX_0F386C_X86_64_L_0_W_0, |
| PREFIX_VEX_0F3872, |
| PREFIX_VEX_0F38B0_W_0, |
| PREFIX_VEX_0F38B1_W_0, |
| PREFIX_VEX_0F38D2_W_0, |
| PREFIX_VEX_0F38D3_W_0, |
| PREFIX_VEX_0F38CB, |
| PREFIX_VEX_0F38CC, |
| PREFIX_VEX_0F38CD, |
| PREFIX_VEX_0F38DA_W_0, |
| PREFIX_VEX_0F38F2_L_0, |
| PREFIX_VEX_0F38F3_L_0, |
| PREFIX_VEX_0F38F5_L_0, |
| PREFIX_VEX_0F38F6_L_0, |
| PREFIX_VEX_0F38F7_L_0, |
| PREFIX_VEX_0F3AF0_L_0, |
| PREFIX_VEX_MAP7_F8_L_0_W_0_R_0_X86_64, |
| |
| PREFIX_EVEX_0F5B, |
| PREFIX_EVEX_0F6F, |
| PREFIX_EVEX_0F70, |
| PREFIX_EVEX_0F78, |
| PREFIX_EVEX_0F79, |
| PREFIX_EVEX_0F7A, |
| PREFIX_EVEX_0F7B, |
| PREFIX_EVEX_0F7E, |
| PREFIX_EVEX_0F7F, |
| PREFIX_EVEX_0FC2, |
| PREFIX_EVEX_0FE6, |
| PREFIX_EVEX_0F3810, |
| PREFIX_EVEX_0F3811, |
| PREFIX_EVEX_0F3812, |
| PREFIX_EVEX_0F3813, |
| PREFIX_EVEX_0F3814, |
| PREFIX_EVEX_0F3815, |
| PREFIX_EVEX_0F3820, |
| PREFIX_EVEX_0F3821, |
| PREFIX_EVEX_0F3822, |
| PREFIX_EVEX_0F3823, |
| PREFIX_EVEX_0F3824, |
| PREFIX_EVEX_0F3825, |
| PREFIX_EVEX_0F3826, |
| PREFIX_EVEX_0F3827, |
| PREFIX_EVEX_0F3828, |
| PREFIX_EVEX_0F3829, |
| PREFIX_EVEX_0F382A, |
| PREFIX_EVEX_0F3830, |
| PREFIX_EVEX_0F3831, |
| PREFIX_EVEX_0F3832, |
| PREFIX_EVEX_0F3833, |
| PREFIX_EVEX_0F3834, |
| PREFIX_EVEX_0F3835, |
| PREFIX_EVEX_0F3838, |
| PREFIX_EVEX_0F3839, |
| PREFIX_EVEX_0F383A, |
| PREFIX_EVEX_0F3852, |
| PREFIX_EVEX_0F3853, |
| PREFIX_EVEX_0F3868, |
| PREFIX_EVEX_0F3872, |
| PREFIX_EVEX_0F389A, |
| PREFIX_EVEX_0F389B, |
| PREFIX_EVEX_0F38AA, |
| PREFIX_EVEX_0F38AB, |
| |
| PREFIX_EVEX_0F3A08, |
| PREFIX_EVEX_0F3A0A, |
| PREFIX_EVEX_0F3A26, |
| PREFIX_EVEX_0F3A27, |
| PREFIX_EVEX_0F3A56, |
| PREFIX_EVEX_0F3A57, |
| PREFIX_EVEX_0F3A66, |
| PREFIX_EVEX_0F3A67, |
| PREFIX_EVEX_0F3AC2, |
| |
| PREFIX_EVEX_MAP4_4x, |
| PREFIX_EVEX_MAP4_F0, |
| PREFIX_EVEX_MAP4_F1, |
| PREFIX_EVEX_MAP4_F2, |
| PREFIX_EVEX_MAP4_F8, |
| |
| PREFIX_EVEX_MAP5_10, |
| PREFIX_EVEX_MAP5_11, |
| PREFIX_EVEX_MAP5_1D, |
| PREFIX_EVEX_MAP5_2A, |
| PREFIX_EVEX_MAP5_2C, |
| PREFIX_EVEX_MAP5_2D, |
| PREFIX_EVEX_MAP5_2E, |
| PREFIX_EVEX_MAP5_2F, |
| PREFIX_EVEX_MAP5_51, |
| PREFIX_EVEX_MAP5_58, |
| PREFIX_EVEX_MAP5_59, |
| PREFIX_EVEX_MAP5_5A, |
| PREFIX_EVEX_MAP5_5B, |
| PREFIX_EVEX_MAP5_5C, |
| PREFIX_EVEX_MAP5_5D, |
| PREFIX_EVEX_MAP5_5E, |
| PREFIX_EVEX_MAP5_5F, |
| PREFIX_EVEX_MAP5_78, |
| PREFIX_EVEX_MAP5_79, |
| PREFIX_EVEX_MAP5_7A, |
| PREFIX_EVEX_MAP5_7B, |
| PREFIX_EVEX_MAP5_7C, |
| PREFIX_EVEX_MAP5_7D, |
| |
| PREFIX_EVEX_MAP6_13, |
| PREFIX_EVEX_MAP6_56, |
| PREFIX_EVEX_MAP6_57, |
| PREFIX_EVEX_MAP6_D6, |
| PREFIX_EVEX_MAP6_D7, |
| }; |
| |
| enum |
| { |
| X86_64_06 = 0, |
| X86_64_07, |
| X86_64_0E, |
| X86_64_16, |
| X86_64_17, |
| X86_64_1E, |
| X86_64_1F, |
| X86_64_27, |
| X86_64_2F, |
| X86_64_37, |
| X86_64_3F, |
| X86_64_60, |
| X86_64_61, |
| X86_64_62, |
| X86_64_63, |
| X86_64_6D, |
| X86_64_6F, |
| X86_64_82, |
| X86_64_9A, |
| X86_64_C2, |
| X86_64_C3, |
| X86_64_C4, |
| X86_64_C5, |
| X86_64_CE, |
| X86_64_D4, |
| X86_64_D5, |
| X86_64_E8, |
| X86_64_E9, |
| X86_64_EA, |
| X86_64_0F00_REG_6, |
| X86_64_0F01_REG_0, |
| X86_64_0F01_REG_0_MOD_3_RM_6_P_1, |
| X86_64_0F01_REG_0_MOD_3_RM_6_P_3, |
| X86_64_0F01_REG_0_MOD_3_RM_7_P_0, |
| X86_64_0F01_REG_1, |
| X86_64_0F01_REG_1_RM_2_PREFIX_1, |
| X86_64_0F01_REG_1_RM_2_PREFIX_3, |
| X86_64_0F01_REG_1_RM_5_PREFIX_2, |
| X86_64_0F01_REG_1_RM_6_PREFIX_2, |
| X86_64_0F01_REG_1_RM_7_PREFIX_2, |
| X86_64_0F01_REG_2, |
| X86_64_0F01_REG_3, |
| X86_64_0F01_REG_5_MOD_3_RM_4_PREFIX_1, |
| X86_64_0F01_REG_5_MOD_3_RM_5_PREFIX_1, |
| X86_64_0F01_REG_5_MOD_3_RM_6_PREFIX_1, |
| X86_64_0F01_REG_5_MOD_3_RM_7_PREFIX_1, |
| X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1, |
| X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1, |
| X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_3, |
| X86_64_0F01_REG_7_MOD_3_RM_7_PREFIX_1, |
| X86_64_0F18_REG_6_MOD_0, |
| X86_64_0F18_REG_7_MOD_0, |
| X86_64_0F24, |
| X86_64_0F26, |
| X86_64_0F38F8_M_1, |
| X86_64_0FC7_REG_6_MOD_3_PREFIX_1, |
| |
| X86_64_VEX_0F3849, |
| X86_64_VEX_0F384B, |
| X86_64_VEX_0F385C, |
| X86_64_VEX_0F385E, |
| X86_64_VEX_0F386C, |
| X86_64_VEX_0F38Ex, |
| |
| X86_64_VEX_MAP7_F8_L_0_W_0_R_0, |
| }; |
| |
| enum |
| { |
| THREE_BYTE_0F38 = 0, |
| THREE_BYTE_0F3A |
| }; |
| |
| enum |
| { |
| XOP_08 = 0, |
| XOP_09, |
| XOP_0A |
| }; |
| |
| enum |
| { |
| VEX_0F = 0, |
| VEX_0F38, |
| VEX_0F3A, |
| VEX_MAP7, |
| }; |
| |
| enum |
| { |
| EVEX_0F = 0, |
| EVEX_0F38, |
| EVEX_0F3A, |
| EVEX_MAP4, |
| EVEX_MAP5, |
| EVEX_MAP6, |
| EVEX_MAP7, |
| }; |
| |
| enum |
| { |
| VEX_LEN_0F12_P_0 = 0, |
| VEX_LEN_0F12_P_2, |
| VEX_LEN_0F13, |
| VEX_LEN_0F16_P_0, |
| VEX_LEN_0F16_P_2, |
| VEX_LEN_0F17, |
| VEX_LEN_0F41, |
| VEX_LEN_0F42, |
| VEX_LEN_0F44, |
| VEX_LEN_0F45, |
| VEX_LEN_0F46, |
| VEX_LEN_0F47, |
| VEX_LEN_0F4A, |
| VEX_LEN_0F4B, |
| VEX_LEN_0F6E, |
| VEX_LEN_0F77, |
| VEX_LEN_0F7E_P_1, |
| VEX_LEN_0F7E_P_2, |
| VEX_LEN_0F90, |
| VEX_LEN_0F91, |
| VEX_LEN_0F92, |
| VEX_LEN_0F93, |
| VEX_LEN_0F98, |
| VEX_LEN_0F99, |
| VEX_LEN_0FAE_R_2, |
| VEX_LEN_0FAE_R_3, |
| VEX_LEN_0FC4, |
| VEX_LEN_0FD6, |
| VEX_LEN_0F3816, |
| VEX_LEN_0F3819, |
| VEX_LEN_0F381A, |
| VEX_LEN_0F3836, |
| VEX_LEN_0F3841, |
| VEX_LEN_0F3849_X86_64, |
| VEX_LEN_0F384B_X86_64, |
| VEX_LEN_0F385A, |
| VEX_LEN_0F385C_X86_64, |
| VEX_LEN_0F385E_X86_64, |
| VEX_LEN_0F386C_X86_64, |
| VEX_LEN_0F38CB_P_3_W_0, |
| VEX_LEN_0F38CC_P_3_W_0, |
| VEX_LEN_0F38CD_P_3_W_0, |
| VEX_LEN_0F38DA_W_0_P_0, |
| VEX_LEN_0F38DA_W_0_P_2, |
| VEX_LEN_0F38DB, |
| VEX_LEN_0F38F2, |
| VEX_LEN_0F38F3, |
| VEX_LEN_0F38F5, |
| VEX_LEN_0F38F6, |
| VEX_LEN_0F38F7, |
| VEX_LEN_0F3A00, |
| VEX_LEN_0F3A01, |
| VEX_LEN_0F3A06, |
| VEX_LEN_0F3A14, |
| VEX_LEN_0F3A15, |
| VEX_LEN_0F3A16, |
| VEX_LEN_0F3A17, |
| VEX_LEN_0F3A18, |
| VEX_LEN_0F3A19, |
| VEX_LEN_0F3A20, |
| VEX_LEN_0F3A21, |
| VEX_LEN_0F3A22, |
| VEX_LEN_0F3A30, |
| VEX_LEN_0F3A31, |
| VEX_LEN_0F3A32, |
| VEX_LEN_0F3A33, |
| VEX_LEN_0F3A38, |
| VEX_LEN_0F3A39, |
| VEX_LEN_0F3A41, |
| VEX_LEN_0F3A46, |
| VEX_LEN_0F3A60, |
| VEX_LEN_0F3A61, |
| VEX_LEN_0F3A62, |
| VEX_LEN_0F3A63, |
| VEX_LEN_0F3ADE_W_0, |
| VEX_LEN_0F3ADF, |
| VEX_LEN_0F3AF0, |
| VEX_LEN_MAP7_F8, |
| VEX_LEN_XOP_08_85, |
| VEX_LEN_XOP_08_86, |
| VEX_LEN_XOP_08_87, |
| VEX_LEN_XOP_08_8E, |
| VEX_LEN_XOP_08_8F, |
| VEX_LEN_XOP_08_95, |
| VEX_LEN_XOP_08_96, |
| VEX_LEN_XOP_08_97, |
| VEX_LEN_XOP_08_9E, |
| VEX_LEN_XOP_08_9F, |
| VEX_LEN_XOP_08_A3, |
| VEX_LEN_XOP_08_A6, |
| VEX_LEN_XOP_08_B6, |
| VEX_LEN_XOP_08_C0, |
| VEX_LEN_XOP_08_C1, |
| VEX_LEN_XOP_08_C2, |
| VEX_LEN_XOP_08_C3, |
| VEX_LEN_XOP_08_CC, |
| VEX_LEN_XOP_08_CD, |
| VEX_LEN_XOP_08_CE, |
| VEX_LEN_XOP_08_CF, |
| VEX_LEN_XOP_08_EC, |
| VEX_LEN_XOP_08_ED, |
| VEX_LEN_XOP_08_EE, |
| VEX_LEN_XOP_08_EF, |
| VEX_LEN_XOP_09_01, |
| VEX_LEN_XOP_09_02, |
| VEX_LEN_XOP_09_12, |
| VEX_LEN_XOP_09_82_W_0, |
| VEX_LEN_XOP_09_83_W_0, |
| VEX_LEN_XOP_09_90, |
| VEX_LEN_XOP_09_91, |
| VEX_LEN_XOP_09_92, |
| VEX_LEN_XOP_09_93, |
| VEX_LEN_XOP_09_94, |
| VEX_LEN_XOP_09_95, |
| VEX_LEN_XOP_09_96, |
| VEX_LEN_XOP_09_97, |
| VEX_LEN_XOP_09_98, |
| VEX_LEN_XOP_09_99, |
| VEX_LEN_XOP_09_9A, |
| VEX_LEN_XOP_09_9B, |
| VEX_LEN_XOP_09_C1, |
| VEX_LEN_XOP_09_C2, |
| VEX_LEN_XOP_09_C3, |
| VEX_LEN_XOP_09_C6, |
| VEX_LEN_XOP_09_C7, |
| VEX_LEN_XOP_09_CB, |
| VEX_LEN_XOP_09_D1, |
| VEX_LEN_XOP_09_D2, |
| VEX_LEN_XOP_09_D3, |
| VEX_LEN_XOP_09_D6, |
| VEX_LEN_XOP_09_D7, |
| VEX_LEN_XOP_09_DB, |
| VEX_LEN_XOP_09_E1, |
| VEX_LEN_XOP_09_E2, |
| VEX_LEN_XOP_09_E3, |
| VEX_LEN_XOP_0A_12, |
| }; |
| |
| enum |
| { |
| EVEX_LEN_0F3816 = 0, |
| EVEX_LEN_0F3819, |
| EVEX_LEN_0F381A, |
| EVEX_LEN_0F381B, |
| EVEX_LEN_0F3836, |
| EVEX_LEN_0F385A, |
| EVEX_LEN_0F385B, |
| EVEX_LEN_0F38C6, |
| EVEX_LEN_0F38C7, |
| EVEX_LEN_0F3A00, |
| EVEX_LEN_0F3A01, |
| EVEX_LEN_0F3A18, |
| EVEX_LEN_0F3A19, |
| EVEX_LEN_0F3A1A, |
| EVEX_LEN_0F3A1B, |
| EVEX_LEN_0F3A23, |
| EVEX_LEN_0F3A38, |
| EVEX_LEN_0F3A39, |
| EVEX_LEN_0F3A3A, |
| EVEX_LEN_0F3A3B, |
| EVEX_LEN_0F3A43 |
| }; |
| |
| enum |
| { |
| VEX_W_0F41_L_1 = 0, |
| VEX_W_0F42_L_1, |
| VEX_W_0F44_L_0, |
| VEX_W_0F45_L_1, |
| VEX_W_0F46_L_1, |
| VEX_W_0F47_L_1, |
| VEX_W_0F4A_L_1, |
| VEX_W_0F4B_L_1, |
| VEX_W_0F90_L_0, |
| VEX_W_0F91_L_0, |
| VEX_W_0F92_L_0, |
| VEX_W_0F93_L_0, |
| VEX_W_0F98_L_0, |
| VEX_W_0F99_L_0, |
| VEX_W_0F380C, |
| VEX_W_0F380D, |
| VEX_W_0F380E, |
| VEX_W_0F380F, |
| VEX_W_0F3813, |
| VEX_W_0F3816_L_1, |
| VEX_W_0F3818, |
| VEX_W_0F3819_L_1, |
| VEX_W_0F381A_L_1, |
| VEX_W_0F382C, |
| VEX_W_0F382D, |
| VEX_W_0F382E, |
| VEX_W_0F382F, |
| VEX_W_0F3836, |
| VEX_W_0F3846, |
| VEX_W_0F3849_X86_64_L_0, |
| VEX_W_0F384B_X86_64_L_0, |
| VEX_W_0F3850, |
| VEX_W_0F3851, |
| VEX_W_0F3852, |
| VEX_W_0F3853, |
| VEX_W_0F3858, |
| VEX_W_0F3859, |
| VEX_W_0F385A_L_0, |
| VEX_W_0F385C_X86_64_L_0, |
| VEX_W_0F385E_X86_64_L_0, |
| VEX_W_0F386C_X86_64_L_0, |
| VEX_W_0F3872_P_1, |
| VEX_W_0F3878, |
| VEX_W_0F3879, |
| VEX_W_0F38B0, |
| VEX_W_0F38B1, |
| VEX_W_0F38B4, |
| VEX_W_0F38B5, |
| VEX_W_0F38CB_P_3, |
| VEX_W_0F38CC_P_3, |
| VEX_W_0F38CD_P_3, |
| VEX_W_0F38CF, |
| VEX_W_0F38D2, |
| VEX_W_0F38D3, |
| VEX_W_0F38DA, |
| VEX_W_0F3A00_L_1, |
| VEX_W_0F3A01_L_1, |
| VEX_W_0F3A02, |
| VEX_W_0F3A04, |
| VEX_W_0F3A05, |
| VEX_W_0F3A06_L_1, |
| VEX_W_0F3A18_L_1, |
| VEX_W_0F3A19_L_1, |
| VEX_W_0F3A1D, |
| VEX_W_0F3A38_L_1, |
| VEX_W_0F3A39_L_1, |
| VEX_W_0F3A46_L_1, |
| VEX_W_0F3A4A, |
| VEX_W_0F3A4B, |
| VEX_W_0F3A4C, |
| VEX_W_0F3ACE, |
| VEX_W_0F3ACF, |
| VEX_W_0F3ADE, |
| VEX_W_MAP7_F8_L_0, |
| |
| VEX_W_XOP_08_85_L_0, |
| VEX_W_XOP_08_86_L_0, |
| VEX_W_XOP_08_87_L_0, |
| VEX_W_XOP_08_8E_L_0, |
| VEX_W_XOP_08_8F_L_0, |
| VEX_W_XOP_08_95_L_0, |
| VEX_W_XOP_08_96_L_0, |
| VEX_W_XOP_08_97_L_0, |
| VEX_W_XOP_08_9E_L_0, |
| VEX_W_XOP_08_9F_L_0, |
| VEX_W_XOP_08_A6_L_0, |
| VEX_W_XOP_08_B6_L_0, |
| VEX_W_XOP_08_C0_L_0, |
| VEX_W_XOP_08_C1_L_0, |
| VEX_W_XOP_08_C2_L_0, |
| VEX_W_XOP_08_C3_L_0, |
| VEX_W_XOP_08_CC_L_0, |
| VEX_W_XOP_08_CD_L_0, |
| VEX_W_XOP_08_CE_L_0, |
| VEX_W_XOP_08_CF_L_0, |
| VEX_W_XOP_08_EC_L_0, |
| VEX_W_XOP_08_ED_L_0, |
| VEX_W_XOP_08_EE_L_0, |
| VEX_W_XOP_08_EF_L_0, |
| |
| VEX_W_XOP_09_80, |
| VEX_W_XOP_09_81, |
| VEX_W_XOP_09_82, |
| VEX_W_XOP_09_83, |
| VEX_W_XOP_09_C1_L_0, |
| VEX_W_XOP_09_C2_L_0, |
| VEX_W_XOP_09_C3_L_0, |
| VEX_W_XOP_09_C6_L_0, |
| VEX_W_XOP_09_C7_L_0, |
| VEX_W_XOP_09_CB_L_0, |
| VEX_W_XOP_09_D1_L_0, |
| VEX_W_XOP_09_D2_L_0, |
| VEX_W_XOP_09_D3_L_0, |
| VEX_W_XOP_09_D6_L_0, |
| VEX_W_XOP_09_D7_L_0, |
| VEX_W_XOP_09_DB_L_0, |
| VEX_W_XOP_09_E1_L_0, |
| VEX_W_XOP_09_E2_L_0, |
| VEX_W_XOP_09_E3_L_0, |
| |
| EVEX_W_0F5B_P_0, |
| EVEX_W_0F62, |
| EVEX_W_0F66, |
| EVEX_W_0F6A, |
| EVEX_W_0F6B, |
| EVEX_W_0F6C, |
| EVEX_W_0F6D, |
| EVEX_W_0F6F_P_1, |
| EVEX_W_0F6F_P_2, |
| EVEX_W_0F6F_P_3, |
| EVEX_W_0F70_P_2, |
| EVEX_W_0F72_R_2, |
| EVEX_W_0F72_R_6, |
| EVEX_W_0F73_R_2, |
| EVEX_W_0F73_R_6, |
| EVEX_W_0F76, |
| EVEX_W_0F78_P_0, |
| EVEX_W_0F78_P_2, |
| EVEX_W_0F79_P_0, |
| EVEX_W_0F79_P_2, |
| EVEX_W_0F7A_P_1, |
| EVEX_W_0F7A_P_2, |
| EVEX_W_0F7A_P_3, |
| EVEX_W_0F7B_P_2, |
| EVEX_W_0F7E_P_1, |
| EVEX_W_0F7F_P_1, |
| EVEX_W_0F7F_P_2, |
| EVEX_W_0F7F_P_3, |
| EVEX_W_0FD2, |
| EVEX_W_0FD3, |
| EVEX_W_0FD4, |
| EVEX_W_0FD6, |
| EVEX_W_0FE6_P_1, |
| EVEX_W_0FE7, |
| EVEX_W_0FF2, |
| EVEX_W_0FF3, |
| EVEX_W_0FF4, |
| EVEX_W_0FFA, |
| EVEX_W_0FFB, |
| EVEX_W_0FFE, |
| |
| EVEX_W_0F3810_P_1, |
| EVEX_W_0F3810_P_2, |
| EVEX_W_0F3811_P_1, |
| EVEX_W_0F3811_P_2, |
| EVEX_W_0F3812_P_1, |
| EVEX_W_0F3812_P_2, |
| EVEX_W_0F3813_P_1, |
| EVEX_W_0F3814_P_1, |
| EVEX_W_0F3815_P_1, |
| EVEX_W_0F3819_L_n, |
| EVEX_W_0F381A_L_n, |
| EVEX_W_0F381B_L_2, |
| EVEX_W_0F381E, |
| EVEX_W_0F381F, |
| EVEX_W_0F3820_P_1, |
| EVEX_W_0F3821_P_1, |
| EVEX_W_0F3822_P_1, |
| EVEX_W_0F3823_P_1, |
| EVEX_W_0F3824_P_1, |
| EVEX_W_0F3825_P_1, |
| EVEX_W_0F3825_P_2, |
| EVEX_W_0F3828_P_2, |
| EVEX_W_0F3829_P_2, |
| EVEX_W_0F382A_P_1, |
| EVEX_W_0F382A_P_2, |
| EVEX_W_0F382B, |
| EVEX_W_0F3830_P_1, |
| EVEX_W_0F3831_P_1, |
| EVEX_W_0F3832_P_1, |
| EVEX_W_0F3833_P_1, |
| EVEX_W_0F3834_P_1, |
| EVEX_W_0F3835_P_1, |
| EVEX_W_0F3835_P_2, |
| EVEX_W_0F3837, |
| EVEX_W_0F383A_P_1, |
| EVEX_W_0F3859, |
| EVEX_W_0F385A_L_n, |
| EVEX_W_0F385B_L_2, |
| EVEX_W_0F3870, |
| EVEX_W_0F3872_P_2, |
| EVEX_W_0F387A, |
| EVEX_W_0F387B, |
| EVEX_W_0F3883, |
| |
| EVEX_W_0F3A18_L_n, |
| EVEX_W_0F3A19_L_n, |
| EVEX_W_0F3A1A_L_2, |
| EVEX_W_0F3A1B_L_2, |
| EVEX_W_0F3A21, |
| EVEX_W_0F3A23_L_n, |
| EVEX_W_0F3A38_L_n, |
| EVEX_W_0F3A39_L_n, |
| EVEX_W_0F3A3A_L_2, |
| EVEX_W_0F3A3B_L_2, |
| EVEX_W_0F3A42, |
| EVEX_W_0F3A43_L_n, |
| EVEX_W_0F3A70, |
| EVEX_W_0F3A72, |
| |
| EVEX_W_MAP4_8F_R_0, |
| EVEX_W_MAP4_F8_P1_M_1, |
| EVEX_W_MAP4_F8_P3_M_1, |
| EVEX_W_MAP4_FF_R_6, |
| |
| EVEX_W_MAP5_5B_P_0, |
| EVEX_W_MAP5_7A_P_3, |
| }; |
| |
| typedef bool (*op_rtn) (instr_info *ins, int bytemode, int sizeflag); |
| |
| struct dis386 { |
| const char *name; |
| struct |
| { |
| op_rtn rtn; |
| int bytemode; |
| } op[MAX_OPERANDS]; |
| unsigned int prefix_requirement; |
| }; |
| |
| /* Upper case letters in the instruction names here are macros. |
| 'A' => print 'b' if no (suitable) register operand 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' unused. |
| 'J' unused. |
| 'K' => print 'd' or 'q' if rex prefix is present. |
| 'L' => print 'l' or 'q' if suffix_always is true |
| 'M' => print 'r' if intel_mnemonic is false. |
| 'N' => print 'n' if instruction has no wait "prefix" |
| 'O' => print 'd' or 'o' (or 'q' in Intel mode) |
| 'P' => behave as 'T' except with register operand outside of suffix_always |
| mode |
| 'Q' => print 'w', 'l' or 'q' if no (suitable) register operand 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 'w', 'l'/'d', or 'q' if instruction has an operand size |
| prefix or if suffix_always is true. |
| 'U' unused. |
| 'V' => print 'v' for VEX/EVEX and nothing for legacy encodings. |
| 'W' => print 'b', 'w' or 'l' ('d' in Intel mode) |
| 'X' => print 's', 'd' depending on data16 prefix (for XMM) |
| 'Y' => no output, mark EVEX.aaa != 0 as bad. |
| 'Z' => print 'q' in 64bit mode and 'l' otherwise, if suffix_always is true. |
| '!' => change condition from true to false or from false to true. |
| '%' => add 1 upper case letter to the macro. |
| '^' => print 'w', 'l', or 'q' (Intel64 ISA only) depending on operand size |
| prefix or suffix_always is true (lcall/ljmp). |
| '@' => in 64bit mode for Intel64 ISA or if instruction |
| has no operand sizing prefix, print 'q' if suffix_always is true or |
| nothing otherwise; behave as 'P' in all other cases |
| |
| 2 upper case letter macros: |
| "CC" => print condition code |
| "XY" => print 'x' or 'y' if suffix_always is true or no register |
| operands and no broadcast. |
| "XZ" => print 'x', 'y', or 'z' if suffix_always is true or no |
| register operands and no broadcast. |
| "XW" => print 's', 'd' depending on the VEX.W bit (for FMA) |
| "XD" => print 'd' if !EVEX or EVEX.W=1, EVEX.W=0 is not a valid encoding |
| "XH" => print 'h' if EVEX.W=0, EVEX.W=1 is not a valid encoding (for FP16) |
| "XS" => print 's' if !EVEX or EVEX.W=0, EVEX.W=1 is not a valid encoding |
| "XV" => print "{vex} " pseudo prefix |
| "XE" => print "{evex} " pseudo prefix if no EVEX-specific functionality is |
| is used by an EVEX-encoded (AVX512VL) instruction. |
| "NF" => print "{nf} " pseudo prefix when EVEX.NF = 1 and print "{evex} " |
| pseudo prefix when instructions without NF, EGPR and VVVV, |
| "NE" => don't print "{evex} " pseudo prefix for some special instructions |
| in MAP4. |
| "ZU" => print 'zu' if EVEX.ZU=1. |
| "SC" => print suffix SCC for SCC insns |
| "YK" keep unused, to avoid ambiguity with the combined use of Y and K. |
| "YX" keep unused, to avoid ambiguity with the combined use of Y and X. |
| "LQ" => print 'l' ('d' in Intel mode) or 'q' for memory operand, cond |
| being false, or no operand at all in 64bit mode, or if suffix_always |
| is true. |
| "LB" => print "abs" in 64bit mode and behave as 'B' otherwise |
| "LS" => print "abs" in 64bit mode and behave as 'S' otherwise |
| "LV" => print "abs" for 64bit operand and behave as 'S' otherwise |
| "DQ" => print 'd' or 'q' depending on the VEX.W bit |
| "DF" => print default flag value for SCC insns |
| "BW" => print 'b' or 'w' depending on the VEX.W bit |
| "LP" => print 'w' or 'l' ('d' in Intel mode) if instruction has |
| an operand size prefix, or suffix_always is true. print |
| 'q' if rex prefix is present. |
| |
| 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 and Intel. */ |
| |
| static const struct dis386 dis386[] = { |
| /* 00 */ |
| { "addB", { Ebh1, Gb }, 0 }, |
| { "addS", { Evh1, Gv }, 0 }, |
| { "addB", { Gb, EbS }, 0 }, |
| { "addS", { Gv, EvS }, 0 }, |
| { "addB", { AL, Ib }, 0 }, |
| { "addS", { eAX, Iv }, 0 }, |
| { X86_64_TABLE (X86_64_06) }, |
| { X86_64_TABLE (X86_64_07) }, |
| /* 08 */ |
| { "orB", { Ebh1, Gb }, 0 }, |
| { "orS", { Evh1, Gv }, 0 }, |
| { "orB", { Gb, EbS }, 0 }, |
| { "orS", { Gv, EvS }, 0 }, |
| { "orB", { AL, Ib }, 0 }, |
| { "orS", { eAX, Iv }, 0 }, |
| { X86_64_TABLE (X86_64_0E) }, |
| { Bad_Opcode }, /* 0x0f extended opcode escape */ |
| /* 10 */ |
| { "adcB", { Ebh1, Gb }, 0 }, |
| { "adcS", { Evh1, Gv }, 0 }, |
| { "adcB", { Gb, EbS }, 0 }, |
| { "adcS", { Gv, EvS }, 0 }, |
| { "adcB", { AL, Ib }, 0 }, |
| { "adcS", { eAX, Iv }, 0 }, |
| { X86_64_TABLE (X86_64_16) }, |
| { X86_64_TABLE (X86_64_17) }, |
| /* 18 */ |
| { "sbbB", { Ebh1, Gb }, 0 }, |
| { "sbbS", { Evh1, Gv }, 0 }, |
| { "sbbB", { Gb, EbS }, 0 }, |
| { "sbbS", { Gv, EvS }, 0 }, |
| { "sbbB", { AL, Ib }, 0 }, |
| { "sbbS", { eAX, Iv }, 0 }, |
| { X86_64_TABLE (X86_64_1E) }, |
| { X86_64_TABLE (X86_64_1F) }, |
| /* 20 */ |
| { "andB", { Ebh1, Gb }, 0 }, |
| { "andS", { Evh1, Gv }, 0 }, |
| { "andB", { Gb, EbS }, 0 }, |
| { "andS", { Gv, EvS }, 0 }, |
| { "andB", { AL, Ib }, 0 }, |
| { "andS", { eAX, Iv }, 0 }, |
| { Bad_Opcode }, /* SEG ES prefix */ |
| { X86_64_TABLE (X86_64_27) }, |
| /* 28 */ |
| { "subB", { Ebh1, Gb }, 0 }, |
| { "subS", { Evh1, Gv }, 0 }, |
| { "subB", { Gb, EbS }, 0 }, |
| { "subS", { Gv, EvS }, 0 }, |
| { "subB", { AL, Ib }, 0 }, |
| { "subS", { eAX, Iv }, 0 }, |
| { Bad_Opcode }, /* SEG CS prefix */ |
| { X86_64_TABLE (X86_64_2F) }, |
| /* 30 */ |
| { "xorB", { Ebh1, Gb }, 0 }, |
| { "xorS", { Evh1, Gv }, 0 }, |
| { "xorB", { Gb, EbS }, 0 }, |
| { "xorS", { Gv, EvS }, 0 }, |
| { "xorB", { AL, Ib }, 0 }, |
| { "xorS", { eAX, Iv }, 0 }, |
| { Bad_Opcode }, /* SEG SS prefix */ |
| { X86_64_TABLE (X86_64_37) }, |
| /* 38 */ |
| { "cmpB", { Eb, Gb }, 0 }, |
| { "cmpS", { Ev, Gv }, 0 }, |
| { "cmpB", { Gb, EbS }, 0 }, |
| { "cmpS", { Gv, EvS }, 0 }, |
| { "cmpB", { AL, Ib }, 0 }, |
| { "cmpS", { eAX, Iv }, 0 }, |
| { Bad_Opcode }, /* SEG DS prefix */ |
| { X86_64_TABLE (X86_64_3F) }, |
| /* 40 */ |
| { "inc{S|}", { RMeAX }, 0 }, |
| { "inc{S|}", { RMeCX }, 0 }, |
| { "inc{S|}", { RMeDX }, 0 }, |
| { "inc{S|}", { RMeBX }, 0 }, |
| { "inc{S|}", { RMeSP }, 0 }, |
| { "inc{S|}", { RMeBP }, 0 }, |
| { "inc{S|}", { RMeSI }, 0 }, |
| { "inc{S|}", { RMeDI }, 0 }, |
| /* 48 */ |
| { "dec{S|}", { RMeAX }, 0 }, |
| { "dec{S|}", { RMeCX }, 0 }, |
| { "dec{S|}", { RMeDX }, 0 }, |
| { "dec{S|}", { RMeBX }, 0 }, |
| { "dec{S|}", { RMeSP }, 0 }, |
| { "dec{S|}", { RMeBP }, 0 }, |
| { "dec{S|}", { RMeSI }, 0 }, |
| { "dec{S|}", { RMeDI }, 0 }, |
| /* 50 */ |
| { "push!P", { RMrAX }, 0 }, |
| { "push!P", { RMrCX }, 0 }, |
| { "push!P", { RMrDX }, 0 }, |
| { "push!P", { RMrBX }, 0 }, |
| { "push!P", { RMrSP }, 0 }, |
| { "push!P", { RMrBP }, 0 }, |
| { "push!P", { RMrSI }, 0 }, |
| { "push!P", { RMrDI }, 0 }, |
| /* 58 */ |
| { "pop!P", { RMrAX }, 0 }, |
| { "pop!P", { RMrCX }, 0 }, |
| { "pop!P", { RMrDX }, 0 }, |
| { "pop!P", { RMrBX }, 0 }, |
| { "pop!P", { RMrSP }, 0 }, |
| { "pop!P", { RMrBP }, 0 }, |
| { "pop!P", { RMrSI }, 0 }, |
| { "pop!P", { RMrDI }, 0 }, |
| /* 60 */ |
| { X86_64_TABLE (X86_64_60) }, |
| { X86_64_TABLE (X86_64_61) }, |
| { X86_64_TABLE (X86_64_62) }, |
| { X86_64_TABLE (X86_64_63) }, |
| { Bad_Opcode }, /* seg fs */ |
| { Bad_Opcode }, /* seg gs */ |
| { Bad_Opcode }, /* op size prefix */ |
| { Bad_Opcode }, /* adr size prefix */ |
| /* 68 */ |
| { "pushP", { sIv }, 0 }, |
| { "imulS", { Gv, Ev, Iv }, 0 }, |
| { "pushP", { sIbT }, 0 }, |
| { "imulS", { Gv, Ev, sIb }, 0 }, |
| { "ins{b|}", { Ybr, indirDX }, 0 }, |
| { X86_64_TABLE (X86_64_6D) }, |
| { "outs{b|}", { indirDXr, Xb }, 0 }, |
| { X86_64_TABLE (X86_64_6F) }, |
| /* 70 */ |
| { "joH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnoH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jbH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jaeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jneH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jbeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jaH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| /* 78 */ |
| { "jsH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnsH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jpH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnpH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jlH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jgeH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jleH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jgH", { Jb, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| /* 80 */ |
| { REG_TABLE (REG_80) }, |
| { REG_TABLE (REG_81) }, |
| { X86_64_TABLE (X86_64_82) }, |
| { REG_TABLE (REG_83) }, |
| { "testB", { Eb, Gb }, 0 }, |
| { "testS", { Ev, Gv }, 0 }, |
| { "xchgB", { Ebh2, Gb }, 0 }, |
| { "xchgS", { Evh2, Gv }, 0 }, |
| /* 88 */ |
| { "movB", { Ebh3, Gb }, 0 }, |
| { "movS", { Evh3, Gv }, 0 }, |
| { "movB", { Gb, EbS }, 0 }, |
| { "movS", { Gv, EvS }, 0 }, |
| { "movD", { Sv, Sw }, 0 }, |
| { "leaS", { Gv, M }, 0 }, |
| { "movD", { Sw, Sv }, 0 }, |
| { REG_TABLE (REG_8F) }, |
| /* 90 */ |
| { PREFIX_TABLE (PREFIX_90) }, |
| { "xchgS", { RMeCX, eAX }, 0 }, |
| { "xchgS", { RMeDX, eAX }, 0 }, |
| { "xchgS", { RMeBX, eAX }, 0 }, |
| { "xchgS", { RMeSP, eAX }, 0 }, |
| { "xchgS", { RMeBP, eAX }, 0 }, |
| { "xchgS", { RMeSI, eAX }, 0 }, |
| { "xchgS", { RMeDI, eAX }, 0 }, |
| /* 98 */ |
| { "cW{t|}R", { XX }, 0 }, |
| { "cR{t|}O", { XX }, 0 }, |
| { X86_64_TABLE (X86_64_9A) }, |
| { Bad_Opcode }, /* fwait */ |
| { "pushfP", { XX }, 0 }, |
| { "popfP", { XX }, 0 }, |
| { "sahf", { XX }, 0 }, |
| { "lahf", { XX }, 0 }, |
| /* a0 */ |
| { "mov%LB", { AL, Ob }, PREFIX_REX2_ILLEGAL }, |
| { "mov%LS", { { JMPABS_Fixup, eAX_reg }, { JMPABS_Fixup, v_mode } }, PREFIX_REX2_ILLEGAL }, |
| { "mov%LB", { Ob, AL }, PREFIX_REX2_ILLEGAL }, |
| { "mov%LS", { Ov, eAX }, PREFIX_REX2_ILLEGAL }, |
| { "movs{b|}", { Ybr, Xb }, PREFIX_REX2_ILLEGAL }, |
| { "movs{R|}", { Yvr, Xv }, PREFIX_REX2_ILLEGAL }, |
| { "cmps{b|}", { Xb, Yb }, PREFIX_REX2_ILLEGAL }, |
| { "cmps{R|}", { Xv, Yv }, PREFIX_REX2_ILLEGAL }, |
| /* a8 */ |
| { "testB", { AL, Ib }, PREFIX_REX2_ILLEGAL }, |
| { "testS", { eAX, Iv }, PREFIX_REX2_ILLEGAL }, |
| { "stosB", { Ybr, AL }, PREFIX_REX2_ILLEGAL }, |
| { "stosS", { Yvr, eAX }, PREFIX_REX2_ILLEGAL }, |
| { "lodsB", { ALr, Xb }, PREFIX_REX2_ILLEGAL }, |
| { "lodsS", { eAXr, Xv }, PREFIX_REX2_ILLEGAL }, |
| { "scasB", { AL, Yb }, PREFIX_REX2_ILLEGAL }, |
| { "scasS", { eAX, Yv }, PREFIX_REX2_ILLEGAL }, |
| /* b0 */ |
| { "movB", { RMAL, Ib }, 0 }, |
| { "movB", { RMCL, Ib }, 0 }, |
| { "movB", { RMDL, Ib }, 0 }, |
| { "movB", { RMBL, Ib }, 0 }, |
| { "movB", { RMAH, Ib }, 0 }, |
| { "movB", { RMCH, Ib }, 0 }, |
| { "movB", { RMDH, Ib }, 0 }, |
| { "movB", { RMBH, Ib }, 0 }, |
| /* b8 */ |
| { "mov%LV", { RMeAX, Iv64 }, 0 }, |
| { "mov%LV", { RMeCX, Iv64 }, 0 }, |
| { "mov%LV", { RMeDX, Iv64 }, 0 }, |
| { "mov%LV", { RMeBX, Iv64 }, 0 }, |
| { "mov%LV", { RMeSP, Iv64 }, 0 }, |
| { "mov%LV", { RMeBP, Iv64 }, 0 }, |
| { "mov%LV", { RMeSI, Iv64 }, 0 }, |
| { "mov%LV", { RMeDI, Iv64 }, 0 }, |
| /* c0 */ |
| { REG_TABLE (REG_C0) }, |
| { REG_TABLE (REG_C1) }, |
| { X86_64_TABLE (X86_64_C2) }, |
| { X86_64_TABLE (X86_64_C3) }, |
| { X86_64_TABLE (X86_64_C4) }, |
| { X86_64_TABLE (X86_64_C5) }, |
| { REG_TABLE (REG_C6) }, |
| { REG_TABLE (REG_C7) }, |
| /* c8 */ |
| { "enterP", { Iw, Ib }, 0 }, |
| { "leaveP", { XX }, 0 }, |
| { "{l|}ret{|f}%LP", { Iw }, 0 }, |
| { "{l|}ret{|f}%LP", { XX }, 0 }, |
| { "int3", { XX }, 0 }, |
| { "int", { Ib }, 0 }, |
| { X86_64_TABLE (X86_64_CE) }, |
| { "iret%LP", { XX }, 0 }, |
| /* d0 */ |
| { REG_TABLE (REG_D0) }, |
| { REG_TABLE (REG_D1) }, |
| { REG_TABLE (REG_D2) }, |
| { REG_TABLE (REG_D3) }, |
| { X86_64_TABLE (X86_64_D4) }, |
| { X86_64_TABLE (X86_64_D5) }, |
| { Bad_Opcode }, |
| { "xlat", { DSBX }, 0 }, |
| /* d8 */ |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| { FLOAT }, |
| /* e0 */ |
| { "loopneFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, |
| { "loopeFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, |
| { "loopFH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jEcxzH", { Jb, XX, loop_jcxz_flag }, PREFIX_REX2_ILLEGAL }, |
| { "inB", { AL, Ib }, PREFIX_REX2_ILLEGAL }, |
| { "inG", { zAX, Ib }, PREFIX_REX2_ILLEGAL }, |
| { "outB", { Ib, AL }, PREFIX_REX2_ILLEGAL }, |
| { "outG", { Ib, zAX }, PREFIX_REX2_ILLEGAL }, |
| /* e8 */ |
| { X86_64_TABLE (X86_64_E8) }, |
| { X86_64_TABLE (X86_64_E9) }, |
| { X86_64_TABLE (X86_64_EA) }, |
| { "jmp", { Jb, BND }, PREFIX_REX2_ILLEGAL }, |
| { "inB", { AL, indirDX }, PREFIX_REX2_ILLEGAL }, |
| { "inG", { zAX, indirDX }, PREFIX_REX2_ILLEGAL }, |
| { "outB", { indirDX, AL }, PREFIX_REX2_ILLEGAL }, |
| { "outG", { indirDX, zAX }, PREFIX_REX2_ILLEGAL }, |
| /* f0 */ |
| { Bad_Opcode }, /* lock prefix */ |
| { "int1", { XX }, 0 }, |
| { Bad_Opcode }, /* repne */ |
| { Bad_Opcode }, /* repz */ |
| { "hlt", { XX }, 0 }, |
| { "cmc", { XX }, 0 }, |
| { REG_TABLE (REG_F6) }, |
| { REG_TABLE (REG_F7) }, |
| /* f8 */ |
| { "clc", { XX }, 0 }, |
| { "stc", { XX }, 0 }, |
| { "cli", { XX }, 0 }, |
| { "sti", { XX }, 0 }, |
| { "cld", { XX }, 0 }, |
| { "std", { XX }, 0 }, |
| { REG_TABLE (REG_FE) }, |
| { REG_TABLE (REG_FF) }, |
| }; |
| |
| static const struct dis386 dis386_twobyte[] = { |
| /* 00 */ |
| { REG_TABLE (REG_0F00 ) }, |
| { REG_TABLE (REG_0F01 ) }, |
| { "larS", { Gv, Sv }, 0 }, |
| { "lslS", { Gv, Sv }, 0 }, |
| { Bad_Opcode }, |
| { "syscall", { XX }, 0 }, |
| { "clts", { XX }, 0 }, |
| { "sysret%LQ", { XX }, 0 }, |
| /* 08 */ |
| { "invd", { XX }, 0 }, |
| { PREFIX_TABLE (PREFIX_0F09) }, |
| { Bad_Opcode }, |
| { "ud2", { XX }, 0 }, |
| { Bad_Opcode }, |
| { REG_TABLE (REG_0F0D) }, |
| { "femms", { XX }, 0 }, |
| { "", { MX, EM, OPSUF }, 0 }, /* See OP_3DNowSuffix. */ |
| /* 10 */ |
| { PREFIX_TABLE (PREFIX_0F10) }, |
| { PREFIX_TABLE (PREFIX_0F11) }, |
| { PREFIX_TABLE (PREFIX_0F12) }, |
| { "movlpX", { Mq, XM }, PREFIX_OPCODE }, |
| { "unpcklpX", { XM, EXx }, PREFIX_OPCODE }, |
| { "unpckhpX", { XM, EXx }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0F16) }, |
| { "movhpX", { Mq, XM }, PREFIX_OPCODE }, |
| /* 18 */ |
| { REG_TABLE (REG_0F18) }, |
| { "nopQ", { Ev }, 0 }, |
| { PREFIX_TABLE (PREFIX_0F1A) }, |
| { PREFIX_TABLE (PREFIX_0F1B) }, |
| { PREFIX_TABLE (PREFIX_0F1C) }, |
| { "nopQ", { Ev }, 0 }, |
| { PREFIX_TABLE (PREFIX_0F1E) }, |
| { "nopQ", { Ev }, 0 }, |
| /* 20 */ |
| { "movZ", { Em, Cm }, 0 }, |
| { "movZ", { Em, Dm }, 0 }, |
| { "movZ", { Cm, Em }, 0 }, |
| { "movZ", { Dm, Em }, 0 }, |
| { X86_64_TABLE (X86_64_0F24) }, |
| { Bad_Opcode }, |
| { X86_64_TABLE (X86_64_0F26) }, |
| { Bad_Opcode }, |
| /* 28 */ |
| { "movapX", { XM, EXx }, PREFIX_OPCODE }, |
| { "movapX", { EXxS, XM }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0F2A) }, |
| { PREFIX_TABLE (PREFIX_0F2B) }, |
| { PREFIX_TABLE (PREFIX_0F2C) }, |
| { PREFIX_TABLE (PREFIX_0F2D) }, |
| { PREFIX_TABLE (PREFIX_0F2E) }, |
| { PREFIX_TABLE (PREFIX_0F2F) }, |
| /* 30 */ |
| { "wrmsr", { XX }, PREFIX_REX2_ILLEGAL }, |
| { "rdtsc", { XX }, PREFIX_REX2_ILLEGAL }, |
| { "rdmsr", { XX }, PREFIX_REX2_ILLEGAL }, |
| { "rdpmc", { XX }, PREFIX_REX2_ILLEGAL }, |
| { "sysenter", { SEP }, PREFIX_REX2_ILLEGAL }, |
| { "sysexit%LQ", { SEP }, PREFIX_REX2_ILLEGAL }, |
| { Bad_Opcode }, |
| { "getsec", { XX }, 0 }, |
| /* 38 */ |
| { THREE_BYTE_TABLE (THREE_BYTE_0F38) }, |
| { Bad_Opcode }, |
| { THREE_BYTE_TABLE (THREE_BYTE_0F3A) }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| /* 40 */ |
| { "cmovoS", { Gv, Ev }, 0 }, |
| { "cmovnoS", { Gv, Ev }, 0 }, |
| { "cmovbS", { Gv, Ev }, 0 }, |
| { "cmovaeS", { Gv, Ev }, 0 }, |
| { "cmoveS", { Gv, Ev }, 0 }, |
| { "cmovneS", { Gv, Ev }, 0 }, |
| { "cmovbeS", { Gv, Ev }, 0 }, |
| { "cmovaS", { Gv, Ev }, 0 }, |
| /* 48 */ |
| { "cmovsS", { Gv, Ev }, 0 }, |
| { "cmovnsS", { Gv, Ev }, 0 }, |
| { "cmovpS", { Gv, Ev }, 0 }, |
| { "cmovnpS", { Gv, Ev }, 0 }, |
| { "cmovlS", { Gv, Ev }, 0 }, |
| { "cmovgeS", { Gv, Ev }, 0 }, |
| { "cmovleS", { Gv, Ev }, 0 }, |
| { "cmovgS", { Gv, Ev }, 0 }, |
| /* 50 */ |
| { "movmskpX", { Gdq, Ux }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0F51) }, |
| { PREFIX_TABLE (PREFIX_0F52) }, |
| { PREFIX_TABLE (PREFIX_0F53) }, |
| { "andpX", { XM, EXx }, PREFIX_OPCODE }, |
| { "andnpX", { XM, EXx }, PREFIX_OPCODE }, |
| { "orpX", { XM, EXx }, PREFIX_OPCODE }, |
| { "xorpX", { XM, EXx }, PREFIX_OPCODE }, |
| /* 58 */ |
| { PREFIX_TABLE (PREFIX_0F58) }, |
| { PREFIX_TABLE (PREFIX_0F59) }, |
| { PREFIX_TABLE (PREFIX_0F5A) }, |
| { PREFIX_TABLE (PREFIX_0F5B) }, |
| { PREFIX_TABLE (PREFIX_0F5C) }, |
| { PREFIX_TABLE (PREFIX_0F5D) }, |
| { PREFIX_TABLE (PREFIX_0F5E) }, |
| { PREFIX_TABLE (PREFIX_0F5F) }, |
| /* 60 */ |
| { PREFIX_TABLE (PREFIX_0F60) }, |
| { PREFIX_TABLE (PREFIX_0F61) }, |
| { PREFIX_TABLE (PREFIX_0F62) }, |
| { "packsswb", { MX, EM }, PREFIX_OPCODE }, |
| { "pcmpgtb", { MX, EM }, PREFIX_OPCODE }, |
| { "pcmpgtw", { MX, EM }, PREFIX_OPCODE }, |
| { "pcmpgtd", { MX, EM }, PREFIX_OPCODE }, |
| { "packuswb", { MX, EM }, PREFIX_OPCODE }, |
| /* 68 */ |
| { "punpckhbw", { MX, EM }, PREFIX_OPCODE }, |
| { "punpckhwd", { MX, EM }, PREFIX_OPCODE }, |
| { "punpckhdq", { MX, EM }, PREFIX_OPCODE }, |
| { "packssdw", { MX, EM }, PREFIX_OPCODE }, |
| { "punpcklqdq", { XM, EXx }, PREFIX_DATA }, |
| { "punpckhqdq", { XM, EXx }, PREFIX_DATA }, |
| { "movK", { MX, Edq }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0F6F) }, |
| /* 70 */ |
| { PREFIX_TABLE (PREFIX_0F70) }, |
| { REG_TABLE (REG_0F71) }, |
| { REG_TABLE (REG_0F72) }, |
| { REG_TABLE (REG_0F73) }, |
| { "pcmpeqb", { MX, EM }, PREFIX_OPCODE }, |
| { "pcmpeqw", { MX, EM }, PREFIX_OPCODE }, |
| { "pcmpeqd", { MX, EM }, PREFIX_OPCODE }, |
| { "emms", { XX }, PREFIX_OPCODE }, |
| /* 78 */ |
| { PREFIX_TABLE (PREFIX_0F78) }, |
| { PREFIX_TABLE (PREFIX_0F79) }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { PREFIX_TABLE (PREFIX_0F7C) }, |
| { PREFIX_TABLE (PREFIX_0F7D) }, |
| { PREFIX_TABLE (PREFIX_0F7E) }, |
| { PREFIX_TABLE (PREFIX_0F7F) }, |
| /* 80 */ |
| { "joH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnoH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jbH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jaeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jneH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jbeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jaH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| /* 88 */ |
| { "jsH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnsH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jpH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jnpH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jlH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jgeH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jleH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| { "jgH", { Jv, BND, cond_jump_flag }, PREFIX_REX2_ILLEGAL }, |
| /* 90 */ |
| { "seto", { Eb }, 0 }, |
| { "setno", { Eb }, 0 }, |
| { "setb", { Eb }, 0 }, |
| { "setae", { Eb }, 0 }, |
| { "sete", { Eb }, 0 }, |
| { "setne", { Eb }, 0 }, |
| { "setbe", { Eb }, 0 }, |
| { "seta", { Eb }, 0 }, |
| /* 98 */ |
| { "sets", { Eb }, 0 }, |
| { "setns", { Eb }, 0 }, |
| { "setp", { Eb }, 0 }, |
| { "setnp", { Eb }, 0 }, |
| { "setl", { Eb }, 0 }, |
| { "setge", { Eb }, 0 }, |
| { "setle", { Eb }, 0 }, |
| { "setg", { Eb }, 0 }, |
| /* a0 */ |
| { "pushP", { fs }, 0 }, |
| { "popP", { fs }, 0 }, |
| { "cpuid", { XX }, 0 }, |
| { "btS", { Ev, Gv }, 0 }, |
| { "shldS", { Ev, Gv, Ib }, 0 }, |
| { "shldS", { Ev, Gv, CL }, 0 }, |
| { REG_TABLE (REG_0FA6) }, |
| { REG_TABLE (REG_0FA7) }, |
| /* a8 */ |
| { "pushP", { gs }, 0 }, |
| { "popP", { gs }, 0 }, |
| { "rsm", { XX }, 0 }, |
| { "btsS", { Evh1, Gv }, 0 }, |
| { "shrdS", { Ev, Gv, Ib }, 0 }, |
| { "shrdS", { Ev, Gv, CL }, 0 }, |
| { REG_TABLE (REG_0FAE) }, |
| { "imulS", { Gv, Ev }, 0 }, |
| /* b0 */ |
| { "cmpxchgB", { Ebh1, Gb }, 0 }, |
| { "cmpxchgS", { Evh1, Gv }, 0 }, |
| { "lssS", { Gv, Mp }, 0 }, |
| { "btrS", { Evh1, Gv }, 0 }, |
| { "lfsS", { Gv, Mp }, 0 }, |
| { "lgsS", { Gv, Mp }, 0 }, |
| { "movz{bR|x}", { Gv, Eb }, 0 }, |
| { "movz{wR|x}", { Gv, Ew }, 0 }, /* yes, there really is movzww ! */ |
| /* b8 */ |
| { PREFIX_TABLE (PREFIX_0FB8) }, |
| { "ud1S", { Gv, Ev }, 0 }, |
| { REG_TABLE (REG_0FBA) }, |
| { "btcS", { Evh1, Gv }, 0 }, |
| { PREFIX_TABLE (PREFIX_0FBC) }, |
| { PREFIX_TABLE (PREFIX_0FBD) }, |
| { "movs{bR|x}", { Gv, Eb }, 0 }, |
| { "movs{wR|x}", { Gv, Ew }, 0 }, /* yes, there really is movsww ! */ |
| /* c0 */ |
| { "xaddB", { Ebh1, Gb }, 0 }, |
| { "xaddS", { Evh1, Gv }, 0 }, |
| { PREFIX_TABLE (PREFIX_0FC2) }, |
| { "movntiS", { Mdq, Gdq }, PREFIX_OPCODE }, |
| { "pinsrw", { MX, Edw, Ib }, PREFIX_OPCODE }, |
| { "pextrw", { Gd, Nq, Ib }, PREFIX_OPCODE }, |
| { "shufpX", { XM, EXx, Ib }, PREFIX_OPCODE }, |
| { REG_TABLE (REG_0FC7) }, |
| /* c8 */ |
| { "bswap", { RMeAX }, 0 }, |
| { "bswap", { RMeCX }, 0 }, |
| { "bswap", { RMeDX }, 0 }, |
| { "bswap", { RMeBX }, 0 }, |
| { "bswap", { RMeSP }, 0 }, |
| { "bswap", { RMeBP }, 0 }, |
| { "bswap", { RMeSI }, 0 }, |
| { "bswap", { RMeDI }, 0 }, |
| /* d0 */ |
| { PREFIX_TABLE (PREFIX_0FD0) }, |
| { "psrlw", { MX, EM }, PREFIX_OPCODE }, |
| { "psrld", { MX, EM }, PREFIX_OPCODE }, |
| { "psrlq", { MX, EM }, PREFIX_OPCODE }, |
| { "paddq", { MX, EM }, PREFIX_OPCODE }, |
| { "pmullw", { MX, EM }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0FD6) }, |
| { "pmovmskb", { Gdq, Nq }, PREFIX_OPCODE }, |
| /* d8 */ |
| { "psubusb", { MX, EM }, PREFIX_OPCODE }, |
| { "psubusw", { MX, EM }, PREFIX_OPCODE }, |
| { "pminub", { MX, EM }, PREFIX_OPCODE }, |
| { "pand", { MX, EM }, PREFIX_OPCODE }, |
| { "paddusb", { MX, EM }, PREFIX_OPCODE }, |
| { "paddusw", { MX, EM }, PREFIX_OPCODE }, |
| { "pmaxub", { MX, EM }, PREFIX_OPCODE }, |
| { "pandn", { MX, EM }, PREFIX_OPCODE }, |
| /* e0 */ |
| { "pavgb", { MX, EM }, PREFIX_OPCODE }, |
| { "psraw", { MX, EM }, PREFIX_OPCODE }, |
| { "psrad", { MX, EM }, PREFIX_OPCODE }, |
| { "pavgw", { MX, EM }, PREFIX_OPCODE }, |
| { "pmulhuw", { MX, EM }, PREFIX_OPCODE }, |
| { "pmulhw", { MX, EM }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0FE6) }, |
| { PREFIX_TABLE (PREFIX_0FE7) }, |
| /* e8 */ |
| { "psubsb", { MX, EM }, PREFIX_OPCODE }, |
| { "psubsw", { MX, EM }, PREFIX_OPCODE }, |
| { "pminsw", { MX, EM }, PREFIX_OPCODE }, |
| { "por", { MX, EM }, PREFIX_OPCODE }, |
| { "paddsb", { MX, EM }, PREFIX_OPCODE }, |
| { "paddsw", { MX, EM }, PREFIX_OPCODE }, |
| { "pmaxsw", { MX, EM }, PREFIX_OPCODE }, |
| { "pxor", { MX, EM }, PREFIX_OPCODE }, |
| /* f0 */ |
| { PREFIX_TABLE (PREFIX_0FF0) }, |
| { "psllw", { MX, EM }, PREFIX_OPCODE }, |
| { "pslld", { MX, EM }, PREFIX_OPCODE }, |
| { "psllq", { MX, EM }, PREFIX_OPCODE }, |
| { "pmuludq", { MX, EM }, PREFIX_OPCODE }, |
| { "pmaddwd", { MX, EM }, PREFIX_OPCODE }, |
| { "psadbw", { MX, EM }, PREFIX_OPCODE }, |
| { PREFIX_TABLE (PREFIX_0FF7) }, |
| /* f8 */ |
| { "psubb", { MX, EM }, PREFIX_OPCODE }, |
| { "psubw", { MX, EM }, PREFIX_OPCODE }, |
| { "psubd", { MX, EM }, PREFIX_OPCODE }, |
| { "psubq", { MX, EM }, PREFIX_OPCODE }, |
| { "paddb", { MX, EM }, PREFIX_OPCODE }, |
| { "paddw", { MX, EM }, PREFIX_OPCODE }, |
| { "paddd", { MX, EM }, PREFIX_OPCODE }, |
| { "ud0S", { Gv, Ev }, 0 }, |
| }; |
| |
| static const bool 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 bool 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,1,1,1,1,1,1,1, /* 1f */ |
| /* 20 */ 1,1,1,1,1,1,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,1,1,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,1,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,1 /* ff */ |
| /* ------------------------------- */ |
| /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ |
| }; |
| |
| |
| struct op |
| { |
| const char *name; |
| unsigned int len; |
| }; |
| |
| /* 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 (!ins->need_modrm) abort () |
| |
| static const char intel_index16[][6] = { |
| "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" |
| }; |
| |
| static const char att_names64[][8] = { |
| "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", |
| "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", |
| "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", |
| "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31", |
| }; |
| static const char att_names32[][8] = { |
| "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", |
| "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d", |
| "%r16d", "%r17d", "%r18d", "%r19d", "%r20d", "%r21d", "%r22d", "%r23d", |
| "%r24d", "%r25d", "%r26d", "%r27d", "%r28d", "%r29d", "%r30d", "%r31d", |
| }; |
| static const char att_names16[][8] = { |
| "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", |
| "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w", |
| "%r16w", "%r17w", "%r18w", "%r19w", "%r20w", "%r21w", "%r22w", "%r23w", |
| "%r24w", "%r25w", "%r26w", "%r27w", "%r28w", "%r29w", "%r30w", "%r31w", |
| }; |
| static const char att_names8[][8] = { |
| "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", |
| }; |
| static const char att_names8rex[][8] = { |
| "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", |
| "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b", |
| "%r16b", "%r17b", "%r18b", "%r19b", "%r20b", "%r21b", "%r22b", "%r23b", |
| "%r24b", "%r25b", "%r26b", "%r27b", "%r28b", "%r29b", "%r30b", "%r31b", |
| }; |
| static const char att_names_seg[][4] = { |
| "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", |
| }; |
| static const char att_index64[] = "%riz"; |
| static const char att_index32[] = "%eiz"; |
| static const char att_index16[][8] = { |
| "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx" |
| }; |
| |
| static const char att_names_mm[][8] = { |
| "%mm0", "%mm1", "%mm2", "%mm3", |
| "%mm4", "%mm5", "%mm6", "%mm7" |
| }; |
| |
| static const char att_names_bnd[][8] = { |
| "%bnd0", "%bnd1", "%bnd2", "%bnd3" |
| }; |
| |
| static const char att_names_xmm[][8] = { |
| "%xmm0", "%xmm1", "%xmm2", "%xmm3", |
| "%xmm4", "%xmm5", "%xmm6", "%xmm7", |
| "%xmm8", "%xmm9", "%xmm10", "%xmm11", |
| "%xmm12", "%xmm13", "%xmm14", "%xmm15", |
| "%xmm16", "%xmm17", "%xmm18", "%xmm19", |
| "%xmm20", "%xmm21", "%xmm22", "%xmm23", |
| "%xmm24", "%xmm25", "%xmm26", "%xmm27", |
| "%xmm28", "%xmm29", "%xmm30", "%xmm31" |
| }; |
| |
| static const char att_names_ymm[][8] = { |
| "%ymm0", "%ymm1", "%ymm2", "%ymm3", |
| "%ymm4", "%ymm5", "%ymm6", "%ymm7", |
| "%ymm8", "%ymm9", "%ymm10", "%ymm11", |
| "%ymm12", "%ymm13", "%ymm14", "%ymm15", |
| "%ymm16", "%ymm17", "%ymm18", "%ymm19", |
| "%ymm20", "%ymm21", "%ymm22", "%ymm23", |
| "%ymm24", "%ymm25", "%ymm26", "%ymm27", |
| "%ymm28", "%ymm29", "%ymm30", "%ymm31" |
| }; |
| |
| static const char att_names_zmm[][8] = { |
| "%zmm0", "%zmm1", "%zmm2", "%zmm3", |
| "%zmm4", "%zmm5", "%zmm6", "%zmm7", |
| "%zmm8", "%zmm9", "%zmm10", "%zmm11", |
| "%zmm12", "%zmm13", "%zmm14", "%zmm15", |
| "%zmm16", "%zmm17", "%zmm18", "%zmm19", |
| "%zmm20", "%zmm21", "%zmm22", "%zmm23", |
| "%zmm24", "%zmm25", "%zmm26", "%zmm27", |
| "%zmm28", "%zmm29", "%zmm30", "%zmm31" |
| }; |
| |
| static const char att_names_tmm[][8] = { |
| "%tmm0", "%tmm1", "%tmm2", "%tmm3", |
| "%tmm4", "%tmm5", "%tmm6", "%tmm7" |
| }; |
| |
| static const char att_names_mask[][8] = { |
| "%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7" |
| }; |
| |
| static const char *const names_rounding[] = |
| { |
| "{rn-", |
| "{rd-", |
| "{ru-", |
| "{rz-" |
| }; |
| |
| static const struct dis386 reg_table[][8] = { |
| /* REG_80 */ |
| { |
| { "addA", { Ebh1, Ib }, 0 }, |
| { "orA", { Ebh1, Ib }, 0 }, |
| { "adcA", { Ebh1, Ib }, 0 }, |
| { "sbbA", { Ebh1, Ib }, 0 }, |
| { "andA", { Ebh1, Ib }, 0 }, |
| { "subA", { Ebh1, Ib }, 0 }, |
| { "xorA", { Ebh1, Ib }, 0 }, |
| { "cmpA", { Eb, Ib }, 0 }, |
| }, |
| /* REG_81 */ |
| { |
| { "addQ", { Evh1, Iv }, 0 }, |
| { "orQ", { Evh1, Iv }, 0 }, |
| { "adcQ", { Evh1, Iv }, 0 }, |
| { "sbbQ", { Evh1, Iv }, 0 }, |
| { "andQ", { Evh1, Iv }, 0 }, |
| { "subQ", { Evh1, Iv }, 0 }, |
| { "xorQ", { Evh1, Iv }, 0 }, |
| { "cmpQ", { Ev, Iv }, 0 }, |
| }, |
| /* REG_83 */ |
| { |
| { "addQ", { Evh1, sIb }, 0 }, |
| { "orQ", { Evh1, sIb }, 0 }, |
| { "adcQ", { Evh1, sIb }, 0 }, |
| { "sbbQ", { Evh1, sIb }, 0 }, |
| { "andQ", { Evh1, sIb }, 0 }, |
| { "subQ", { Evh1, sIb }, 0 }, |
| { "xorQ", { Evh1, sIb }, 0 }, |
| { "cmpQ", { Ev, sIb }, 0 }, |
| }, |
| /* REG_8F */ |
| { |
| { "pop{P|}", { stackEv }, 0 }, |
| { XOP_8F_TABLE () }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { XOP_8F_TABLE () }, |
| }, |
| /* REG_C0 */ |
| { |
| { "%NFrolA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "%NFrorA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "rclA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "rcrA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "%NFshrA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| { "%NFsarA", { VexGb, Eb, Ib }, NO_PREFIX }, |
| }, |
| /* REG_C1 */ |
| { |
| { "%NFrolQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "%NFrorQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "rclQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "rcrQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "%NFshrQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| { "%NFsarQ", { VexGv, Ev, Ib }, PREFIX_NP_OR_DATA }, |
| }, |
| /* REG_C6 */ |
| { |
| { "movA", { Ebh3, Ib }, 0 }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { RM_TABLE (RM_C6_REG_7) }, |
| }, |
| /* REG_C7 */ |
| { |
| { "movQ", { Evh3, Iv }, 0 }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { Bad_Opcode }, |
| { RM_TABLE (RM_C7_REG_7) }, |
| }, |
| /* REG_D0 */ |
| { |
| { "%NFrolA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "%NFrorA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "rclA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "rcrA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "%NFshrA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| { "%NFsarA", { VexGb, Eb, I1 }, NO_PREFIX }, |
| }, |
| /* REG_D1 */ |
| { |
| { "%NFrolQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "%NFrorQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "rclQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "rcrQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "%NFshrQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| { "%NFsarQ", { VexGv, Ev, I1 }, PREFIX_NP_OR_DATA }, |
| }, |
| /* REG_D2 */ |
| { |
| { "%NFrolA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "%NFrorA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "rclA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "rcrA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "%NFshrA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "%NFshlA", { VexGb, Eb, CL }, NO_PREFIX }, |
| { "%NFsarA", { VexGb, Eb, CL }, NO_PREFIX }, |
| }, |
| /* REG_D3 */ |
| { |
| { "%NFrolQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "%NFrorQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "rclQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "rcrQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "%NFshrQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "%NFshlQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| { "%NFsarQ", { VexGv, Ev, CL }, PREFIX_NP_OR_DATA }, |
| }, |
| /* REG_F6 */ |
| { |
| { "testA", { Eb, Ib }, 0 }, |
| { "testA", { Eb, Ib }, 0 }, |
| { "notA", { Ebh1 }, 0 }, |
| { "negA", { Ebh1 }, 0 }, |
| { "mulA", { Eb }, 0 }, /* Don't print the implicit %al register, */ |
| { "imulA", { Eb }, 0 }, /* to distinguish these opcodes from other */ |
| { "divA", { Eb }, 0 }, /* mul/imul opcodes. Do the same for div */ |
| { "idivA", { Eb }, 0 }, /* and idiv for consistency. */ |
| }, |
| /* REG_F7 */ |
| { |
| { "testQ", { Ev, Iv }, 0 }, |
| { "testQ", { Ev, Iv }, 0 }, |
| { "notQ", { Evh1 }, 0 }, |
| { "negQ", { Evh1 }, 0 }, |
| { "mulQ", { Ev }, 0 }, /* Don't print the implicit register. */ |
| { "imulQ", { Ev }, 0 }, |
| { "divQ", { Ev }, 0 }, |
| { "idivQ", { Ev }, 0 }, |
| }, |
| /* REG_FE */ |
| { |
| { "incA", { Ebh1 }, 0 }, |
| { "decA", { Ebh1 }, 0 }, |
| }, |
| /* REG_FF */ |
| { |
| { "incQ", { Evh1 }, 0 }, |
| { "decQ", { Evh1 }, 0 }, |
| { "call{@|}", { NOTRACK, indirEv, BND }, 0 }, |
| { "{l|}call^", { indirEp }, 0 }, |
| { "jmp{@|}", { NOTRACK, indirEv, BND }, 0 }, |
| { "{l|}jmp^", { indirEp }, 0 }, |
| { "push{P|}", { stackEv }, 0 }, |
| { Bad_Opcode }, |
| }, |
| /* REG_0F00 */ |
| { |
| { "sldtD", { Sv }, 0 }, |
| { "strD", { Sv }, 0 }, |
| { "lldtD", { Sv }, 0 }, |
| { "ltrD", { Sv }, 0 }, |
| { "verrD", { Sv }, 0 }, |
| { "verwD", { Sv }, 0 }, |
| { X86_64_TABLE (X86_64_0F00_REG_6) }, |
| { Bad_Opcode }, |
| }, |
| /* REG_0F01 */ |
| { |
| { MOD_TABLE (MOD_0F01_REG_0) }, |
| { MOD_TABLE (MOD_0F01_REG_1) }, |
| { MOD_TABLE (MOD_0F01_REG_2) }, |
| { MOD_TABLE (MOD_0F01_REG_3) }, |
| { "smswD", { Sv }, 0 }, |
| |