blob: 26d667a3b0ec07817be5adf5a0b9ff9df4eaee7e [file] [log] [blame]
/* 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 },