/* Print i386 instructions for GDB, the GNU debugger.
- Copyright (C) 1988-2022 Free Software Foundation, Inc.
+ Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of the GNU opcodes library.
#include "libiberty.h"
#include "safe-ctype.h"
-#include <setjmp.h>
typedef struct instr_info instr_info;
-static int print_insn (bfd_vma, instr_info *);
-static void dofloat (instr_info *, int);
-static void OP_ST (instr_info *, int, int);
-static void OP_STi (instr_info *, int, int);
+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 void oappend (instr_info *, const char *);
static void append_seg (instr_info *);
-static void OP_indirE (instr_info *, int, int);
-static void print_operand_value (instr_info *, char *, int, bfd_vma);
-static void OP_E_memory (instr_info *, int, int);
-static void print_displacement (instr_info *, char *, bfd_vma);
-static void OP_E (instr_info *, int, int);
-static void OP_G (instr_info *, int, int);
-static bfd_vma get64 (instr_info *);
-static bfd_signed_vma get32 (instr_info *);
-static bfd_signed_vma get32s (instr_info *);
-static int get16 (instr_info *);
-static void set_op (instr_info *, bfd_vma, int);
-static void OP_Skip_MODRM (instr_info *, int, int);
-static void OP_REG (instr_info *, int, int);
-static void OP_IMREG (instr_info *, int, int);
-static void OP_I (instr_info *, int, int);
-static void OP_I64 (instr_info *, int, int);
-static void OP_sI (instr_info *, int, int);
-static void OP_J (instr_info *, int, int);
-static void OP_SEG (instr_info *, int, int);
-static void OP_DIR (instr_info *, int, int);
-static void OP_OFF (instr_info *, int, int);
-static void OP_OFF64 (instr_info *, int, int);
-static void ptr_reg (instr_info *, int, int);
-static void OP_ESreg (instr_info *, int, int);
-static void OP_DSreg (instr_info *, int, int);
-static void OP_C (instr_info *, int, int);
-static void OP_D (instr_info *, int, int);
-static void OP_T (instr_info *, int, int);
-static void OP_MMX (instr_info *, int, int);
-static void OP_XMM (instr_info *, int, int);
-static void OP_EM (instr_info *, int, int);
-static void OP_EX (instr_info *, int, int);
-static void OP_EMC (instr_info *, int,int);
-static void OP_MXC (instr_info *, int,int);
-static void OP_MS (instr_info *, int, int);
-static void OP_XS (instr_info *, int, int);
-static void OP_M (instr_info *, int, int);
-static void OP_VEX (instr_info *, int, int);
-static void OP_VexR (instr_info *, int, int);
-static void OP_VexW (instr_info *, int, int);
-static void OP_Rounding (instr_info *, int, int);
-static void OP_REG_VexI4 (instr_info *, int, int);
-static void OP_VexI4 (instr_info *, int, int);
-static void PCLMUL_Fixup (instr_info *, int, int);
-static void VPCMP_Fixup (instr_info *, int, int);
-static void VPCOM_Fixup (instr_info *, int, int);
-static void OP_0f07 (instr_info *, int, int);
-static void OP_Monitor (instr_info *, int, int);
-static void OP_Mwait (instr_info *, int, int);
-static void NOP_Fixup1 (instr_info *, int, int);
-static void NOP_Fixup2 (instr_info *, int, int);
-static void OP_3DNowSuffix (instr_info *, int, int);
-static void CMP_Fixup (instr_info *, int, int);
-static void BadOp (instr_info *);
-static void REP_Fixup (instr_info *, int, int);
-static void SEP_Fixup (instr_info *, int, int);
-static void BND_Fixup (instr_info *, int, int);
-static void NOTRACK_Fixup (instr_info *, int, int);
-static void HLE_Fixup1 (instr_info *, int, int);
-static void HLE_Fixup2 (instr_info *, int, int);
-static void HLE_Fixup3 (instr_info *, int, int);
-static void CMPXCHG8B_Fixup (instr_info *, int, int);
-static void XMM_Fixup (instr_info *, int, int);
-static void FXSAVE_Fixup (instr_info *, int, int);
-
-static void MOVSXD_Fixup (instr_info *, int, int);
-static void DistinctDest_Fixup (instr_info *, int, int);
+static bool get32s (instr_info *, bfd_signed_vma *);
+static bool get16 (instr_info *, int *);
+static void set_op (instr_info *, bfd_vma, bool);
+
+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_MS (instr_info *, int, int);
+static bool OP_XS (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 BadOp (instr_info *);
+
+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 void ATTRIBUTE_PRINTF_3 i386_dis_printf (const instr_info *,
+ enum disassembler_style,
+ const char *, ...);
+static const char *prefix_name (const instr_info *, int, int);
+
+/* 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
struct dis_private {
/* Points to first byte not fetched. */
bfd_byte the_buffer[MAX_MNEM_SIZE];
bfd_vma insn_start;
int orig_sizeflag;
- OPCODES_SIGJMP_BUF bailout;
};
enum address_mode
int prefixes;
/* REX prefix the current instruction. See below. */
- int rex;
+ unsigned char rex;
/* Bits of REX we've already used. */
- int rex_used;
+ unsigned char rex_used;
+
+ bool need_modrm;
+ bool need_vex;
+ bool has_sib;
/* Flags for ins->prefixes which we somehow handled when printing the
current instruction. */
current instruction. */
int evex_used;
- char obuf[100];
+ char obuf[MAX_OPERAND_BUFFER_SIZE];
char *obufp;
char *mnemonicendp;
- char scratchbuf[100];
unsigned char *start_codep;
unsigned char *insn_codep;
unsigned char *codep;
unsigned char *end_codep;
- int last_lock_prefix;
- int last_repz_prefix;
- int last_repnz_prefix;
- int last_data_prefix;
- int last_addr_prefix;
- int last_rex_prefix;
- int last_seg_prefix;
- int fwait_prefix;
+ 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_seg_prefix;
+ signed char fwait_prefix;
/* The active segment register prefix. */
- int active_seg_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. */
- int all_prefixes[MAX_CODE_LENGTH - 1];
+ unsigned char all_prefixes[MAX_CODE_LENGTH - 1];
disassemble_info *info;
struct
int rm;
}
modrm;
- unsigned char need_modrm;
struct
{
int register_specifier;
int length;
int prefix;
- int w;
- int evex;
- int r;
- int v;
int mask_register_specifier;
- int zeroing;
int ll;
- int b;
- int no_broadcast;
+ bool w;
+ bool evex;
+ bool r;
+ bool v;
+ bool zeroing;
+ bool b;
+ bool no_broadcast;
}
vex;
- unsigned char need_vex;
-
- const char **names64;
- const char **names32;
- const char **names16;
- const char **names8;
- const char **names8rex;
- const char **names_seg;
- const char *index64;
- const char *index32;
- const char **index16;
- const char **names_bnd;
- const char **names_mm;
- const char **names_xmm;
- const char **names_ymm;
- const char **names_zmm;
- const char **names_tmm;
- const char **names_mask;
/* Remember if the current op is a jump instruction. */
bool op_is_jump;
- char op_out[MAX_OPERANDS][100];
- int op_ad, op_index[MAX_OPERANDS];
- int two_source_ops;
+ bool two_source_ops;
+
+ 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 op_riprel[MAX_OPERANDS];
bfd_vma start_pc;
/* On the 386's of 1988, the maximum length of an instruction is 15 bytes.
* The function returns the length of this instruction in bytes.
*/
char intel_syntax;
- char intel_mnemonic;
+ bool intel_mnemonic;
char open_char;
char close_char;
char separator_char;
char scale_char;
enum x86_64_isa isa64;
-
};
/* Mark parts used in the REX prefix. When we are testing for
#define EVEX_b_used 1
+#define EVEX_len_used 2
/* Flags stored in PREFIXES. */
#define PREFIX_REPZ 1
#define PREFIX_REPNZ 2
-#define PREFIX_LOCK 4
-#define PREFIX_CS 8
-#define PREFIX_SS 0x10
-#define PREFIX_DS 0x20
-#define PREFIX_ES 0x40
-#define PREFIX_FS 0x80
-#define PREFIX_GS 0x100
+#define PREFIX_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
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
- to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ to ADDR (exclusive) are valid. Returns true for success, false
on error. */
-#define FETCH_DATA(info, addr) \
- ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \
- ? 1 : fetch_data ((info), (addr)))
-
-static int
-fetch_data (struct disassemble_info *info, bfd_byte *addr)
+static bool
+fetch_code (struct disassemble_info *info, bfd_byte *until)
{
- int status;
- struct dis_private *priv = (struct dis_private *) info->private_data;
+ int status = -1;
+ struct dis_private *priv = info->private_data;
bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
- if (addr <= priv->the_buffer + MAX_MNEM_SIZE)
+ if (until <= priv->max_fetched)
+ return true;
+
+ if (until <= priv->the_buffer + MAX_MNEM_SIZE)
status = (*info->read_memory_func) (start,
priv->max_fetched,
- addr - priv->max_fetched,
+ until - priv->max_fetched,
info);
- else
- status = -1;
if (status != 0)
{
/* If we did manage to read at least one byte, then
STATUS. */
if (priv->max_fetched == priv->the_buffer)
(*info->memory_error_func) (status, start, info);
- OPCODES_SIGLONGJMP (priv->bailout, 1);
+ return false;
}
+
+ priv->max_fetched = until;
+ 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, priv->the_buffer[0], priv->orig_sizeflag);
+ if (name != NULL)
+ i386_dis_printf (ins, dis_style_mnemonic, "%s", name);
else
- priv->max_fetched = addr;
+ {
+ /* Just print the first byte as a .byte instruction. */
+ i386_dis_printf (ins, dis_style_assembler_directive, ".byte ");
+ i386_dis_printf (ins, dis_style_immediate, "%#x",
+ (unsigned int) priv->the_buffer[0]);
+ }
+
return 1;
}
#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 Gb { OP_G, b_mode }
ymm_mode,
/* quad word, ymmword or zmmword memory operand. */
ymmq_mode,
- /* 32-byte YMM or 16-byte word operand */
- ymmxmm_mode,
/* TMM operand */
tmm_mode,
/* d_mode in 32bit, q_mode in 64bit mode. */
MOD_0F01_REG_3,
MOD_0F01_REG_5,
MOD_0F01_REG_7,
+ MOD_0F02,
+ MOD_0F03,
MOD_0F12_PREFIX_0,
MOD_0F12_PREFIX_2,
MOD_0F13,
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_VEX_0F384B_X86_64_P_3_W_0,
MOD_VEX_0F385A,
MOD_VEX_0F385C_X86_64_P_1_W_0,
+ MOD_VEX_0F385C_X86_64_P_3_W_0,
MOD_VEX_0F385E_X86_64_P_0_W_0,
MOD_VEX_0F385E_X86_64_P_1_W_0,
MOD_VEX_0F385E_X86_64_P_2_W_0,
MOD_VEX_0F385E_X86_64_P_3_W_0,
+ MOD_VEX_0F386C_X86_64_W_0,
MOD_VEX_0F388C,
MOD_VEX_0F388E,
MOD_VEX_0F3A30_L_0,
MOD_XOP_09_12,
- MOD_EVEX_0F12_PREFIX_0,
- MOD_EVEX_0F12_PREFIX_2,
- MOD_EVEX_0F13,
- MOD_EVEX_0F16_PREFIX_0,
- MOD_EVEX_0F16_PREFIX_2,
- MOD_EVEX_0F17,
- MOD_EVEX_0F2B,
MOD_EVEX_0F381A,
MOD_EVEX_0F381B,
MOD_EVEX_0F3828_P_1,
enum
{
PREFIX_90 = 0,
+ PREFIX_0F01_REG_0_MOD_3_RM_6,
PREFIX_0F01_REG_1_RM_4,
PREFIX_0F01_REG_1_RM_5,
PREFIX_0F01_REG_1_RM_6,
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_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_0F38F8,
PREFIX_0F38FA,
PREFIX_0F38FB,
+ PREFIX_0F38FC,
PREFIX_0F3A0F,
PREFIX_VEX_0F10,
PREFIX_VEX_0F11,
PREFIX_VEX_0FF0,
PREFIX_VEX_0F3849_X86_64,
PREFIX_VEX_0F384B_X86_64,
+ PREFIX_VEX_0F3850_W_0,
+ PREFIX_VEX_0F3851_W_0,
PREFIX_VEX_0F385C_X86_64,
PREFIX_VEX_0F385E_X86_64,
+ PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0,
+ PREFIX_VEX_0F3872,
+ PREFIX_VEX_0F38B0_W_0,
+ PREFIX_VEX_0F38B1_W_0,
PREFIX_VEX_0F38F5_L_0,
PREFIX_VEX_0F38F6_L_0,
PREFIX_VEX_0F38F7_L_0,
PREFIX_VEX_0F3AF0_L_0,
- PREFIX_EVEX_0F10,
- PREFIX_EVEX_0F11,
- PREFIX_EVEX_0F12,
- PREFIX_EVEX_0F16,
- PREFIX_EVEX_0F2A,
- PREFIX_EVEX_0F51,
- PREFIX_EVEX_0F58,
- PREFIX_EVEX_0F59,
- PREFIX_EVEX_0F5A,
PREFIX_EVEX_0F5B,
- PREFIX_EVEX_0F5C,
- PREFIX_EVEX_0F5D,
- PREFIX_EVEX_0F5E,
- PREFIX_EVEX_0F5F,
PREFIX_EVEX_0F6F,
PREFIX_EVEX_0F70,
PREFIX_EVEX_0F78,
X86_64_E9,
X86_64_EA,
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_1,
X86_64_0F01_REG_1_RM_5_PREFIX_2,
X86_64_0F01_REG_1_RM_6_PREFIX_2,
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_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_0F385E,
+ X86_64_VEX_0F386C,
+ X86_64_VEX_0F38E0,
+ X86_64_VEX_0F38E1,
+ X86_64_VEX_0F38E2,
+ X86_64_VEX_0F38E3,
+ X86_64_VEX_0F38E4,
+ X86_64_VEX_0F38E5,
+ X86_64_VEX_0F38E6,
+ X86_64_VEX_0F38E7,
+ X86_64_VEX_0F38E8,
+ X86_64_VEX_0F38E9,
+ X86_64_VEX_0F38EA,
+ X86_64_VEX_0F38EB,
+ X86_64_VEX_0F38EC,
+ X86_64_VEX_0F38ED,
+ X86_64_VEX_0F38EE,
+ X86_64_VEX_0F38EF,
};
enum
VEX_LEN_0F384B_X86_64_P_3_W_0_M_0,
VEX_LEN_0F385A_M_0,
VEX_LEN_0F385C_X86_64_P_1_W_0_M_0,
+ VEX_LEN_0F385C_X86_64_P_3_W_0_M_0,
VEX_LEN_0F385E_X86_64_P_0_W_0_M_0,
VEX_LEN_0F385E_X86_64_P_1_W_0_M_0,
VEX_LEN_0F385E_X86_64_P_2_W_0_M_0,
VEX_LEN_0F385E_X86_64_P_3_W_0_M_0,
+ VEX_LEN_0F386C_X86_64_W_0_M_1,
VEX_LEN_0F38DB,
VEX_LEN_0F38F2,
VEX_LEN_0F38F3,
VEX_W_0F3859,
VEX_W_0F385A_M_0_L_0,
VEX_W_0F385C_X86_64_P_1,
+ VEX_W_0F385C_X86_64_P_3,
VEX_W_0F385E_X86_64_P_0,
VEX_W_0F385E_X86_64_P_1,
VEX_W_0F385E_X86_64_P_2,
VEX_W_0F385E_X86_64_P_3,
+ VEX_W_0F386C_X86_64,
+ 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_0F38CF,
VEX_W_0F3A00_L_1,
VEX_W_0F3A01_L_1,
VEX_W_0FXOP_09_E2_L_0,
VEX_W_0FXOP_09_E3_L_0,
- EVEX_W_0F10_P_1,
- EVEX_W_0F10_P_3,
- EVEX_W_0F11_P_1,
- EVEX_W_0F11_P_3,
- EVEX_W_0F12_P_0_M_1,
- EVEX_W_0F12_P_1,
- EVEX_W_0F12_P_3,
- EVEX_W_0F16_P_0_M_1,
- EVEX_W_0F16_P_1,
- EVEX_W_0F51_P_1,
- EVEX_W_0F51_P_3,
- EVEX_W_0F58_P_1,
- EVEX_W_0F58_P_3,
- EVEX_W_0F59_P_1,
- EVEX_W_0F59_P_3,
- EVEX_W_0F5A_P_0,
- EVEX_W_0F5A_P_1,
- EVEX_W_0F5A_P_2,
- EVEX_W_0F5A_P_3,
EVEX_W_0F5B_P_0,
- EVEX_W_0F5B_P_1,
- EVEX_W_0F5B_P_2,
- EVEX_W_0F5C_P_1,
- EVEX_W_0F5C_P_3,
- EVEX_W_0F5D_P_1,
- EVEX_W_0F5D_P_3,
- EVEX_W_0F5E_P_1,
- EVEX_W_0F5E_P_3,
- EVEX_W_0F5F_P_1,
- EVEX_W_0F5F_P_3,
EVEX_W_0F62,
EVEX_W_0F66,
EVEX_W_0F6A,
EVEX_W_0F7F_P_1,
EVEX_W_0F7F_P_2,
EVEX_W_0F7F_P_3,
- EVEX_W_0FC2_P_1,
- EVEX_W_0FC2_P_3,
EVEX_W_0FD2,
EVEX_W_0FD3,
EVEX_W_0FD4,
EVEX_W_0FD6,
EVEX_W_0FE6_P_1,
- EVEX_W_0FE6_P_2,
- EVEX_W_0FE6_P_3,
EVEX_W_0FE7,
EVEX_W_0FF2,
EVEX_W_0FF3,
EVEX_W_0FFA,
EVEX_W_0FFB,
EVEX_W_0FFE,
- EVEX_W_0F380D,
+
EVEX_W_0F3810_P_1,
EVEX_W_0F3810_P_2,
EVEX_W_0F3811_P_1,
EVEX_W_0F3812_P_1,
EVEX_W_0F3812_P_2,
EVEX_W_0F3813_P_1,
- EVEX_W_0F3813_P_2,
EVEX_W_0F3814_P_1,
EVEX_W_0F3815_P_1,
EVEX_W_0F3819_L_n,
EVEX_W_0F3835_P_2,
EVEX_W_0F3837,
EVEX_W_0F383A_P_1,
- EVEX_W_0F3852_P_1,
EVEX_W_0F3859,
EVEX_W_0F385A_M_0_L_n,
EVEX_W_0F385B_M_0_L_2,
EVEX_W_0F3870,
- EVEX_W_0F3872_P_1,
EVEX_W_0F3872_P_2,
- EVEX_W_0F3872_P_3,
EVEX_W_0F387A,
EVEX_W_0F387B,
EVEX_W_0F3883,
- EVEX_W_0F3A05,
- EVEX_W_0F3A09,
- EVEX_W_0F3A0B,
EVEX_W_0F3A18_L_n,
EVEX_W_0F3A19_L_n,
EVEX_W_0F3A1A_L_2,
EVEX_W_MAP5_7A_P_3,
};
-typedef void (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
+typedef bool (*op_rtn) (instr_info *ins, int bytemode, int sizeflag);
struct dis386 {
const char *name;
"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.W=1, EVEX.W=0 is not a valid encoding
+ "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.W=0, EVEX.W=1 is not a valid encoding
- "XV" => print "{vex3}" pseudo prefix
+ "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.
"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.
/* 00 */
{ REG_TABLE (REG_0F00 ) },
{ REG_TABLE (REG_0F01 ) },
- { "larS", { Gv, Ew }, 0 },
- { "lslS", { Gv, Ew }, 0 },
+ { MOD_TABLE (MOD_0F02) },
+ { MOD_TABLE (MOD_0F03) },
{ Bad_Opcode },
{ "syscall", { XX }, 0 },
{ "clts", { XX }, 0 },
{ "ud0S", { Gv, Ev }, 0 },
};
-static const unsigned char onebyte_has_modrm[256] = {
+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 */
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
};
-static const unsigned char twobyte_has_modrm[256] = {
+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 */
need to update onebyte_has_modrm or twobyte_has_modrm. */
#define MODRM_CHECK if (!ins->need_modrm) abort ()
-static const char *intel_names64[] = {
- "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
-};
-static const char *intel_names32[] = {
- "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
- "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
-};
-static const char *intel_names16[] = {
- "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
- "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
-};
-static const char *intel_names8[] = {
- "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
-};
-static const char *intel_names8rex[] = {
- "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
- "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
-};
-static const char *intel_names_seg[] = {
- "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
-};
-static const char *intel_index64 = "riz";
-static const char *intel_index32 = "eiz";
-static const char *intel_index16[] = {
+static const char intel_index16[][6] = {
"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
};
-static const char *att_names64[] = {
+static const char att_names64[][8] = {
"%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
};
-static const char *att_names32[] = {
+static const char att_names32[][8] = {
"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
"%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
};
-static const char *att_names16[] = {
+static const char att_names16[][8] = {
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
};
-static const char *att_names8[] = {
+static const char att_names8[][8] = {
"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
};
-static const char *att_names8rex[] = {
+static const char att_names8rex[][8] = {
"%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
};
-static const char *att_names_seg[] = {
+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[] = {
+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 *intel_names_mm[] = {
- "mm0", "mm1", "mm2", "mm3",
- "mm4", "mm5", "mm6", "mm7"
-};
-static const char *att_names_mm[] = {
+static const char att_names_mm[][8] = {
"%mm0", "%mm1", "%mm2", "%mm3",
"%mm4", "%mm5", "%mm6", "%mm7"
};
-static const char *intel_names_bnd[] = {
- "bnd0", "bnd1", "bnd2", "bnd3"
-};
-
-static const char *att_names_bnd[] = {
+static const char att_names_bnd[][8] = {
"%bnd0", "%bnd1", "%bnd2", "%bnd3"
};
-static const char *intel_names_xmm[] = {
- "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_xmm[] = {
+static const char att_names_xmm[][8] = {
"%xmm0", "%xmm1", "%xmm2", "%xmm3",
"%xmm4", "%xmm5", "%xmm6", "%xmm7",
"%xmm8", "%xmm9", "%xmm10", "%xmm11",
"%xmm28", "%xmm29", "%xmm30", "%xmm31"
};
-static const char *intel_names_ymm[] = {
- "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_ymm[] = {
+static const char att_names_ymm[][8] = {
"%ymm0", "%ymm1", "%ymm2", "%ymm3",
"%ymm4", "%ymm5", "%ymm6", "%ymm7",
"%ymm8", "%ymm9", "%ymm10", "%ymm11",
"%ymm28", "%ymm29", "%ymm30", "%ymm31"
};
-static const char *intel_names_zmm[] = {
- "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_zmm[] = {
+static const char att_names_zmm[][8] = {
"%zmm0", "%zmm1", "%zmm2", "%zmm3",
"%zmm4", "%zmm5", "%zmm6", "%zmm7",
"%zmm8", "%zmm9", "%zmm10", "%zmm11",
"%zmm28", "%zmm29", "%zmm30", "%zmm31"
};
-static const char *intel_names_tmm[] = {
- "tmm0", "tmm1", "tmm2", "tmm3",
- "tmm4", "tmm5", "tmm6", "tmm7"
-};
-static const char *att_names_tmm[] = {
+static const char att_names_tmm[][8] = {
"%tmm0", "%tmm1", "%tmm2", "%tmm3",
"%tmm4", "%tmm5", "%tmm6", "%tmm7"
};
-static const char *intel_names_mask[] = {
- "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
-};
-static const char *att_names_mask[] = {
+static const char att_names_mask[][8] = {
"%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7"
};
{ MOD_TABLE (MOD_0F18_REG_3) },
{ "nopQ", { Ev }, 0 },
{ "nopQ", { Ev }, 0 },
- { "nopQ", { Ev }, 0 },
- { "nopQ", { Ev }, 0 },
+ { MOD_TABLE (MOD_0F18_REG_6) },
+ { MOD_TABLE (MOD_0F18_REG_7) },
},
/* REG_0F1C_P_0_MOD_0 */
{
static const struct dis386 prefix_table[][4] = {
/* PREFIX_90 */
{
- { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } }, 0 },
+ { "xchgS", { { NOP_Fixup, 0 }, { NOP_Fixup, 1 } }, 0 },
{ "pause", { XX }, 0 },
- { "xchgS", { { NOP_Fixup1, eAX_reg }, { NOP_Fixup2, eAX_reg } }, 0 },
+ { "xchgS", { { NOP_Fixup, 0 }, { NOP_Fixup, 1 } }, 0 },
{ NULL, { { NULL, 0 } }, PREFIX_IGNORED }
},
+ /* PREFIX_0F01_REG_0_MOD_3_RM_6 */
+ {
+ { "wrmsrns", { Skip_MODRM }, 0 },
+ { X86_64_TABLE (X86_64_0F01_REG_0_MOD_3_RM_6_P_1) },
+ { Bad_Opcode },
+ { X86_64_TABLE (X86_64_0F01_REG_0_MOD_3_RM_6_P_3) },
+ },
+
/* PREFIX_0F01_REG_1_RM_4 */
{
{ Bad_Opcode },
{ "mcommit", { Skip_MODRM }, 0 },
},
+ /* PREFIX_0F01_REG_7_MOD_3_RM_5 */
+ {
+ { "rdpru", { Skip_MODRM }, 0 },
+ { X86_64_TABLE (X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1) },
+ },
+
/* PREFIX_0F01_REG_7_MOD_3_RM_6 */
{
{ "invlpgb", { Skip_MODRM }, 0 },
{ MOD_TABLE (MOD_0F16_PREFIX_2) },
},
+ /* PREFIX_0F18_REG_6_MOD_0_X86_64 */
+ {
+ { "prefetchit1", { { PREFETCHI_Fixup, b_mode } }, 0 },
+ { "nopQ", { Ev }, 0 },
+ { "nopQ", { Ev }, 0 },
+ { "nopQ", { Ev }, 0 },
+ },
+
+ /* PREFIX_0F18_REG_7_MOD_0_X86_64 */
+ {
+ { "prefetchit0", { { PREFETCHI_Fixup, b_mode } }, 0 },
+ { "nopQ", { Ev }, 0 },
+ { "nopQ", { Ev }, 0 },
+ { "nopQ", { Ev }, 0 },
+ },
+
/* PREFIX_0F1A */
{
{ MOD_TABLE (MOD_0F1A_PREFIX_0) },
{ MOD_TABLE (MOD_0F38FB_PREFIX_1) },
},
+ /* PREFIX_0F38FC */
+ {
+ { "aadd", { Mdq, Gdq }, 0 },
+ { "axor", { Mdq, Gdq }, 0 },
+ { "aand", { Mdq, Gdq }, 0 },
+ { "aor", { Mdq, Gdq }, 0 },
+ },
+
/* PREFIX_0F3A0F */
{
{ Bad_Opcode },
/* PREFIX_VEX_0F10 */
{
- { "vmovups", { XM, EXx }, 0 },
- { "vmovss", { XMScalar, VexScalarR, EXd }, 0 },
- { "vmovupd", { XM, EXx }, 0 },
- { "vmovsd", { XMScalar, VexScalarR, EXq }, 0 },
+ { "%XEvmovupX", { XM, EXEvexXNoBcst }, 0 },
+ { "%XEvmovs%XS", { XMScalar, VexScalarR, EXd }, 0 },
+ { "%XEvmovupX", { XM, EXEvexXNoBcst }, 0 },
+ { "%XEvmovs%XD", { XMScalar, VexScalarR, EXq }, 0 },
},
/* PREFIX_VEX_0F11 */
{
- { "vmovups", { EXxS, XM }, 0 },
- { "vmovss", { EXdS, VexScalarR, XMScalar }, 0 },
- { "vmovupd", { EXxS, XM }, 0 },
- { "vmovsd", { EXqS, VexScalarR, XMScalar }, 0 },
+ { "%XEvmovupX", { EXxS, XM }, 0 },
+ { "%XEvmovs%XS", { EXdS, VexScalarR, XMScalar }, 0 },
+ { "%XEvmovupX", { EXxS, XM }, 0 },
+ { "%XEvmovs%XD", { EXqS, VexScalarR, XMScalar }, 0 },
},
/* PREFIX_VEX_0F12 */
{
{ MOD_TABLE (MOD_VEX_0F12_PREFIX_0) },
- { "vmovsldup", { XM, EXx }, 0 },
+ { "%XEvmov%XSldup", { XM, EXEvexXNoBcst }, 0 },
{ MOD_TABLE (MOD_VEX_0F12_PREFIX_2) },
- { "vmovddup", { XM, EXymmq }, 0 },
+ { "%XEvmov%XDdup", { XM, EXymmq }, 0 },
},
/* PREFIX_VEX_0F16 */
{
{ MOD_TABLE (MOD_VEX_0F16_PREFIX_0) },
- { "vmovshdup", { XM, EXx }, 0 },
+ { "%XEvmov%XShdup", { XM, EXEvexXNoBcst }, 0 },
{ MOD_TABLE (MOD_VEX_0F16_PREFIX_2) },
},
/* PREFIX_VEX_0F2A */
{
{ Bad_Opcode },
- { "vcvtsi2ss{%LQ|}", { XMScalar, VexScalar, Edq }, 0 },
+ { "%XEvcvtsi2ss{%LQ|}", { XMScalar, VexScalar, EXxEVexR, Edq }, 0 },
{ Bad_Opcode },
- { "vcvtsi2sd{%LQ|}", { XMScalar, VexScalar, Edq }, 0 },
+ { "%XEvcvtsi2sd{%LQ|}", { XMScalar, VexScalar, EXxEVexR64, Edq }, 0 },
},
/* PREFIX_VEX_0F2C */
{
{ Bad_Opcode },
- { "vcvttss2si", { Gdq, EXd, EXxEVexS }, 0 },
+ { "%XEvcvttss2si", { Gdq, EXd, EXxEVexS }, 0 },
{ Bad_Opcode },
- { "vcvttsd2si", { Gdq, EXq, EXxEVexS }, 0 },
+ { "%XEvcvttsd2si", { Gdq, EXq, EXxEVexS }, 0 },
},
/* PREFIX_VEX_0F2D */
{
{ Bad_Opcode },
- { "vcvtss2si", { Gdq, EXd, EXxEVexR }, 0 },
+ { "%XEvcvtss2si", { Gdq, EXd, EXxEVexR }, 0 },
{ Bad_Opcode },
- { "vcvtsd2si", { Gdq, EXq, EXxEVexR }, 0 },
+ { "%XEvcvtsd2si", { Gdq, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F2E */
{
- { "vucomisX", { XMScalar, EXd, EXxEVexS }, PREFIX_OPCODE },
+ { "%XEvucomisX", { XMScalar, EXd, EXxEVexS }, 0 },
{ Bad_Opcode },
- { "vucomisX", { XMScalar, EXq, EXxEVexS }, PREFIX_OPCODE },
+ { "%XEvucomisX", { XMScalar, EXq, EXxEVexS }, 0 },
},
/* PREFIX_VEX_0F2F */
{
- { "vcomisX", { XMScalar, EXd, EXxEVexS }, PREFIX_OPCODE },
+ { "%XEvcomisX", { XMScalar, EXd, EXxEVexS }, 0 },
{ Bad_Opcode },
- { "vcomisX", { XMScalar, EXq, EXxEVexS }, PREFIX_OPCODE },
+ { "%XEvcomisX", { XMScalar, EXq, EXxEVexS }, 0 },
},
/* PREFIX_VEX_0F41_L_1_M_1_W_0 */
/* PREFIX_VEX_0F51 */
{
- { "vsqrtps", { XM, EXx }, 0 },
- { "vsqrtss", { XMScalar, VexScalar, EXd }, 0 },
- { "vsqrtpd", { XM, EXx }, 0 },
- { "vsqrtsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvsqrtpX", { XM, EXx, EXxEVexR }, 0 },
+ { "%XEvsqrts%XS", { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+ { "%XEvsqrtpX", { XM, EXx, EXxEVexR }, 0 },
+ { "%XEvsqrts%XD", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F52 */
/* PREFIX_VEX_0F58 */
{
- { "vaddps", { XM, Vex, EXx }, 0 },
- { "vaddss", { XMScalar, VexScalar, EXd }, 0 },
- { "vaddpd", { XM, Vex, EXx }, 0 },
- { "vaddsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvaddpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvadds%XS", { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+ { "%XEvaddpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvadds%XD", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F59 */
{
- { "vmulps", { XM, Vex, EXx }, 0 },
- { "vmulss", { XMScalar, VexScalar, EXd }, 0 },
- { "vmulpd", { XM, Vex, EXx }, 0 },
- { "vmulsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvmulpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvmuls%XS", { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+ { "%XEvmulpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvmuls%XD", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F5A */
{
- { "vcvtps2pd", { XM, EXxmmq }, 0 },
- { "vcvtss2sd", { XMScalar, VexScalar, EXd }, 0 },
- { "vcvtpd2ps%XY",{ XMM, EXx }, 0 },
- { "vcvtsd2ss", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvcvtp%XS2pd", { XM, EXEvexHalfBcstXmmq, EXxEVexS }, 0 },
+ { "%XEvcvts%XS2sd", { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+ { "%XEvcvtp%XD2ps%XY", { XMxmmq, EXx, EXxEVexR }, 0 },
+ { "%XEvcvts%XD2ss", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F5B */
/* PREFIX_VEX_0F5C */
{
- { "vsubps", { XM, Vex, EXx }, 0 },
- { "vsubss", { XMScalar, VexScalar, EXd }, 0 },
- { "vsubpd", { XM, Vex, EXx }, 0 },
- { "vsubsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvsubpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvsubs%XS", { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+ { "%XEvsubpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvsubs%XD", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F5D */
{
- { "vminps", { XM, Vex, EXx }, 0 },
- { "vminss", { XMScalar, VexScalar, EXd }, 0 },
- { "vminpd", { XM, Vex, EXx }, 0 },
- { "vminsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvminpX", { XM, Vex, EXx, EXxEVexS }, 0 },
+ { "%XEvmins%XS", { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+ { "%XEvminpX", { XM, Vex, EXx, EXxEVexS }, 0 },
+ { "%XEvmins%XD", { XMScalar, VexScalar, EXq, EXxEVexS }, 0 },
},
/* PREFIX_VEX_0F5E */
{
- { "vdivps", { XM, Vex, EXx }, 0 },
- { "vdivss", { XMScalar, VexScalar, EXd }, 0 },
- { "vdivpd", { XM, Vex, EXx }, 0 },
- { "vdivsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvdivpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvdivs%XS", { XMScalar, VexScalar, EXd, EXxEVexR }, 0 },
+ { "%XEvdivpX", { XM, Vex, EXx, EXxEVexR }, 0 },
+ { "%XEvdivs%XD", { XMScalar, VexScalar, EXq, EXxEVexR }, 0 },
},
/* PREFIX_VEX_0F5F */
{
- { "vmaxps", { XM, Vex, EXx }, 0 },
- { "vmaxss", { XMScalar, VexScalar, EXd }, 0 },
- { "vmaxpd", { XM, Vex, EXx }, 0 },
- { "vmaxsd", { XMScalar, VexScalar, EXq }, 0 },
+ { "%XEvmaxpX", { XM, Vex, EXx, EXxEVexS }, 0 },
+ { "%XEvmaxs%XS", { XMScalar, VexScalar, EXd, EXxEVexS }, 0 },
+ { "%XEvmaxpX", { XM, Vex, EXx, EXxEVexS }, 0 },
+ { "%XEvmaxs%XD", { XMScalar, VexScalar, EXq, EXxEVexS }, 0 },
},
/* PREFIX_VEX_0F6F */
{ VEX_W_TABLE (VEX_W_0F384B_X86_64_P_3) },
},
+ /* PREFIX_VEX_0F3850_W_0 */
+ {
+ { "vpdpbuud", { XM, Vex, EXx }, 0 },
+ { "vpdpbsud", { XM, Vex, EXx }, 0 },
+ { "%XVvpdpbusd", { XM, Vex, EXx }, 0 },
+ { "vpdpbssd", { XM, Vex, EXx }, 0 },
+ },
+
+ /* PREFIX_VEX_0F3851_W_0 */
+ {
+ { "vpdpbuuds", { XM, Vex, EXx }, 0 },
+ { "vpdpbsuds", { XM, Vex, EXx }, 0 },
+ { "%XVvpdpbusds", { XM, Vex, EXx }, 0 },
+ { "vpdpbssds", { XM, Vex, EXx }, 0 },
+ },
/* PREFIX_VEX_0F385C_X86_64 */
{
{ Bad_Opcode },
{ VEX_W_TABLE (VEX_W_0F385C_X86_64_P_1) },
{ Bad_Opcode },
+ { VEX_W_TABLE (VEX_W_0F385C_X86_64_P_3) },
},
/* PREFIX_VEX_0F385E_X86_64 */
{ VEX_W_TABLE (VEX_W_0F385E_X86_64_P_3) },
},
+ /* PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0 */
+ {
+ { "tcmmrlfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+ { Bad_Opcode },
+ { "tcmmimfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+ },
+
+ /* PREFIX_VEX_0F3872 */
+ {
+ { Bad_Opcode },
+ { VEX_W_TABLE (VEX_W_0F3872_P_1) },
+ },
+
+ /* PREFIX_VEX_0F38B0_W_0 */
+ {
+ { "vcvtneoph2ps", { XM, Mx }, 0 },
+ { "vcvtneebf162ps", { XM, Mx }, 0 },
+ { "vcvtneeph2ps", { XM, Mx }, 0 },
+ { "vcvtneobf162ps", { XM, Mx }, 0 },
+ },
+
+ /* PREFIX_VEX_0F38B1_W_0 */
+ {
+ { Bad_Opcode },
+ { "vbcstnebf162ps", { XM, Mw }, 0 },
+ { "vbcstnesh2ps", { XM, Mw }, 0 },
+ },
+
/* PREFIX_VEX_0F38F5_L_0 */
{
{ "bzhiS", { Gdq, Edq, VexGdq }, 0 },
{ "sgdt", { M }, 0 },
},
+ /* X86_64_0F01_REG_0_MOD_3_RM_6_P_1 */
+ {
+ { Bad_Opcode },
+ { "wrmsrlist", { Skip_MODRM }, 0 },
+ },
+
+ /* X86_64_0F01_REG_0_MOD_3_RM_6_P_3 */
+ {
+ { Bad_Opcode },
+ { "rdmsrlist", { Skip_MODRM }, 0 },
+ },
+
/* X86_64_0F01_REG_1 */
{
{ "sidt{Q|Q}", { M }, 0 },
{ "stui", { Skip_MODRM }, 0 },
},
+ /* X86_64_0F01_REG_7_MOD_3_RM_5_PREFIX_1 */
+ {
+ { Bad_Opcode },
+ { "rmpquery", { Skip_MODRM }, 0 },
+ },
+
/* X86_64_0F01_REG_7_MOD_3_RM_6_PREFIX_1 */
{
{ Bad_Opcode },
{ "psmash", { Skip_MODRM }, 0 },
},
+ /* X86_64_0F18_REG_6_MOD_0 */
+ {
+ { "nopQ", { Ev }, 0 },
+ { PREFIX_TABLE (PREFIX_0F18_REG_6_MOD_0_X86_64) },
+ },
+
+ /* X86_64_0F18_REG_7_MOD_0 */
+ {
+ { "nopQ", { Ev }, 0 },
+ { PREFIX_TABLE (PREFIX_0F18_REG_7_MOD_0_X86_64) },
+ },
+
{
/* X86_64_0F24 */
{ "movZ", { Em, Td }, 0 },
{ Bad_Opcode },
{ PREFIX_TABLE (PREFIX_VEX_0F385E_X86_64) },
},
+
+ /* X86_64_VEX_0F386C */
+ {
+ { Bad_Opcode },
+ { VEX_W_TABLE (VEX_W_0F386C_X86_64) },
+ },
+
+ /* X86_64_VEX_0F38E0 */
+ {
+ { Bad_Opcode },
+ { "cmpoxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E1 */
+ {
+ { Bad_Opcode },
+ { "cmpnoxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E2 */
+ {
+ { Bad_Opcode },
+ { "cmpbxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E3 */
+ {
+ { Bad_Opcode },
+ { "cmpnbxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E4 */
+ {
+ { Bad_Opcode },
+ { "cmpzxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E5 */
+ {
+ { Bad_Opcode },
+ { "cmpnzxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E6 */
+ {
+ { Bad_Opcode },
+ { "cmpbexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E7 */
+ {
+ { Bad_Opcode },
+ { "cmpnbexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E8 */
+ {
+ { Bad_Opcode },
+ { "cmpsxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38E9 */
+ {
+ { Bad_Opcode },
+ { "cmpnsxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38EA */
+ {
+ { Bad_Opcode },
+ { "cmppxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38EB */
+ {
+ { Bad_Opcode },
+ { "cmpnpxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38EC */
+ {
+ { Bad_Opcode },
+ { "cmplxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38ED */
+ {
+ { Bad_Opcode },
+ { "cmpnlxadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38EE */
+ {
+ { Bad_Opcode },
+ { "cmplexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
+
+ /* X86_64_VEX_0F38EF */
+ {
+ { Bad_Opcode },
+ { "cmpnlexadd", { Mdq, Gdq, VexGdq }, PREFIX_DATA },
+ },
};
static const struct dis386 three_byte_table[][256] = {
{ MOD_TABLE (MOD_0F38F9) },
{ PREFIX_TABLE (PREFIX_0F38FA) },
{ PREFIX_TABLE (PREFIX_0F38FB) },
- { Bad_Opcode },
+ { PREFIX_TABLE (PREFIX_0F38FC) },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
- { Bad_Opcode },
+ { X86_64_TABLE (X86_64_VEX_0F386C) },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
/* 70 */
{ Bad_Opcode },
{ Bad_Opcode },
- { Bad_Opcode },
+ { PREFIX_TABLE (PREFIX_VEX_0F3872) },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
{ "vfnmsub213p%XW", { XM, Vex, EXx }, PREFIX_DATA },
{ "vfnmsub213s%XW", { XMScalar, VexScalar, EXdq }, PREFIX_DATA },
/* b0 */
+ { VEX_W_TABLE (VEX_W_0F38B0) },
+ { VEX_W_TABLE (VEX_W_0F38B1) },
{ Bad_Opcode },
{ Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
+ { VEX_W_TABLE (VEX_W_0F38B4) },
+ { VEX_W_TABLE (VEX_W_0F38B5) },
{ "vfmaddsub231p%XW", { XM, Vex, EXx }, PREFIX_DATA },
{ "vfmsubadd231p%XW", { XM, Vex, EXx }, PREFIX_DATA },
/* b8 */
{ "vaesdec", { XM, Vex, EXx }, PREFIX_DATA },
{ "vaesdeclast", { XM, Vex, EXx }, PREFIX_DATA },
/* e0 */
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
+ { X86_64_TABLE (X86_64_VEX_0F38E0) },
+ { X86_64_TABLE (X86_64_VEX_0F38E1) },
+ { X86_64_TABLE (X86_64_VEX_0F38E2) },
+ { X86_64_TABLE (X86_64_VEX_0F38E3) },
+ { X86_64_TABLE (X86_64_VEX_0F38E4) },
+ { X86_64_TABLE (X86_64_VEX_0F38E5) },
+ { X86_64_TABLE (X86_64_VEX_0F38E6) },
+ { X86_64_TABLE (X86_64_VEX_0F38E7) },
/* e8 */
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
- { Bad_Opcode },
+ { X86_64_TABLE (X86_64_VEX_0F38E8) },
+ { X86_64_TABLE (X86_64_VEX_0F38E9) },
+ { X86_64_TABLE (X86_64_VEX_0F38EA) },
+ { X86_64_TABLE (X86_64_VEX_0F38EB) },
+ { X86_64_TABLE (X86_64_VEX_0F38EC) },
+ { X86_64_TABLE (X86_64_VEX_0F38ED) },
+ { X86_64_TABLE (X86_64_VEX_0F38EE) },
+ { X86_64_TABLE (X86_64_VEX_0F38EF) },
/* f0 */
{ Bad_Opcode },
{ Bad_Opcode },
static const struct dis386 vex_len_table[][2] = {
/* VEX_LEN_0F12_P_0_M_0 / VEX_LEN_0F12_P_2_M_0 */
{
- { "vmovlpX", { XM, Vex, EXq }, 0 },
+ { "%XEvmovlpX", { XM, Vex, EXq }, 0 },
},
/* VEX_LEN_0F12_P_0_M_1 */
{
- { "vmovhlps", { XM, Vex, EXq }, 0 },
+ { "%XEvmovhlp%XS", { XM, Vex, EXq }, 0 },
},
/* VEX_LEN_0F13_M_0 */
{
- { "vmovlpX", { EXq, XM }, PREFIX_OPCODE },
+ { "%XEvmovlpX", { EXq, XM }, PREFIX_OPCODE },
},
/* VEX_LEN_0F16_P_0_M_0 / VEX_LEN_0F16_P_2_M_0 */
{
- { "vmovhpX", { XM, Vex, EXq }, 0 },
+ { "%XEvmovhpX", { XM, Vex, EXq }, 0 },
},
/* VEX_LEN_0F16_P_0_M_1 */
{
- { "vmovlhps", { XM, Vex, EXq }, 0 },
+ { "%XEvmovlhp%XS", { XM, Vex, EXq }, 0 },
},
/* VEX_LEN_0F17_M_0 */
{
- { "vmovhpX", { EXq, XM }, PREFIX_OPCODE },
+ { "%XEvmovhpX", { EXq, XM }, PREFIX_OPCODE },
},
/* VEX_LEN_0F41 */
/* VEX_LEN_0F6E */
{
- { "vmovK", { XMScalar, Edq }, PREFIX_DATA },
+ { "%XEvmovK", { XMScalar, Edq }, PREFIX_DATA },
},
/* VEX_LEN_0F77 */
/* VEX_LEN_0F7E_P_1 */
{
- { "vmovq", { XMScalar, EXq }, 0 },
+ { "%XEvmovq", { XMScalar, EXq }, 0 },
},
/* VEX_LEN_0F7E_P_2 */
{
- { "vmovK", { Edq, XMScalar }, 0 },
+ { "%XEvmovK", { Edq, XMScalar }, 0 },
},
/* VEX_LEN_0F90 */
/* VEX_LEN_0FC4 */
{
- { "vpinsrw", { XM, Vex, Edw, Ib }, PREFIX_DATA },
+ { "%XEvpinsrw", { XM, Vex, Edw, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0FC5 */
{
- { "vpextrw", { Gd, XS, Ib }, PREFIX_DATA },
+ { "%XEvpextrw", { Gd, XS, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0FD6 */
{
- { "vmovq", { EXqS, XMScalar }, PREFIX_DATA },
+ { "%XEvmovq", { EXqS, XMScalar }, PREFIX_DATA },
},
/* VEX_LEN_0FF7 */
{ "tdpbf16ps", { TMM, EXtmm, VexTmm }, 0 },
},
+ /* VEX_LEN_0F385C_X86_64_P_3_W_0_M_0 */
+ {
+ { "tdpfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+ },
+
/* VEX_LEN_0F385E_X86_64_P_0_W_0_M_0 */
{
{ "tdpbuud", {TMM, EXtmm, VexTmm }, 0 },
{ "tdpbssd", {TMM, EXtmm, VexTmm }, 0 },
},
+ /* VEX_LEN_0F386C_X86_64_W_0_M_1 */
+ {
+ { PREFIX_TABLE (PREFIX_VEX_0F386C_X86_64_W_0_M_1_L_0) },
+ },
+
/* VEX_LEN_0F38DB */
{
{ "vaesimc", { XM, EXx }, PREFIX_DATA },
/* VEX_LEN_0F3A14 */
{
- { "vpextrb", { Edb, XM, Ib }, PREFIX_DATA },
+ { "%XEvpextrb", { Edb, XM, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A15 */
{
- { "vpextrw", { Edw, XM, Ib }, PREFIX_DATA },
+ { "%XEvpextrw", { Edw, XM, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A16 */
{
- { "vpextrK", { Edq, XM, Ib }, PREFIX_DATA },
+ { "%XEvpextrK", { Edq, XM, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A17 */
{
- { "vextractps", { Ed, XM, Ib }, PREFIX_DATA },
+ { "%XEvextractps", { Ed, XM, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A18 */
/* VEX_LEN_0F3A20 */
{
- { "vpinsrb", { XM, Vex, Edb, Ib }, PREFIX_DATA },
+ { "%XEvpinsrb", { XM, Vex, Edb, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A21 */
{
- { "vinsertps", { XM, Vex, EXd, Ib }, PREFIX_DATA },
+ { "%XEvinsertps", { XM, Vex, EXd, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A22 */
{
- { "vpinsrK", { XM, Vex, Edq, Ib }, PREFIX_DATA },
+ { "%XEvpinsrK", { XM, Vex, Edq, Ib }, PREFIX_DATA },
},
/* VEX_LEN_0F3A30 */
},
{
/* VEX_W_0F380C */
- { "vpermilps", { XM, Vex, EXx }, PREFIX_DATA },
+ { "%XEvpermilps", { XM, Vex, EXx }, PREFIX_DATA },
},
{
/* VEX_W_0F380D */
},
{
/* VEX_W_0F3818 */
- { "vbroadcastss", { XM, EXd }, PREFIX_DATA },
+ { "%XEvbroadcastss", { XM, EXd }, PREFIX_DATA },
},
{
/* VEX_W_0F3819_L_1 */
},
{
/* VEX_W_0F3850 */
- { "%XV vpdpbusd", { XM, Vex, EXx }, 0 },
+ { PREFIX_TABLE (PREFIX_VEX_0F3850_W_0) },
},
{
/* VEX_W_0F3851 */
- { "%XV vpdpbusds", { XM, Vex, EXx }, 0 },
+ { PREFIX_TABLE (PREFIX_VEX_0F3851_W_0) },
},
{
/* VEX_W_0F3852 */
- { "%XV vpdpwssd", { XM, Vex, EXx }, 0 },
+ { "%XVvpdpwssd", { XM, Vex, EXx }, PREFIX_DATA },
},
{
/* VEX_W_0F3853 */
- { "%XV vpdpwssds", { XM, Vex, EXx }, 0 },
+ { "%XVvpdpwssds", { XM, Vex, EXx }, PREFIX_DATA },
},
{
/* VEX_W_0F3858 */
- { "vpbroadcastd", { XM, EXd }, PREFIX_DATA },
+ { "%XEvpbroadcastd", { XM, EXd }, PREFIX_DATA },
},
{
/* VEX_W_0F3859 */
/* VEX_W_0F385C_X86_64_P_1 */
{ MOD_TABLE (MOD_VEX_0F385C_X86_64_P_1_W_0) },
},
+ {
+ /* VEX_W_0F385C_X86_64_P_3 */
+ { MOD_TABLE (MOD_VEX_0F385C_X86_64_P_3_W_0) },
+ },
{
/* VEX_W_0F385E_X86_64_P_0 */
{ MOD_TABLE (MOD_VEX_0F385E_X86_64_P_0_W_0) },
/* VEX_W_0F385E_X86_64_P_3 */
{ MOD_TABLE (MOD_VEX_0F385E_X86_64_P_3_W_0) },
},
+ {
+ /* VEX_W_0F386C_X86_64 */
+ { MOD_TABLE (MOD_VEX_0F386C_X86_64_W_0) },
+ },
+ {
+ /* VEX_W_0F3872_P_1 */
+ { "%XVvcvtneps2bf16%XY", { XMM, EXx }, 0 },
+ },
{
/* VEX_W_0F3878 */
- { "vpbroadcastb", { XM, EXb }, PREFIX_DATA },
+ { "%XEvpbroadcastb", { XM, EXb }, PREFIX_DATA },
},
{
/* VEX_W_0F3879 */
- { "vpbroadcastw", { XM, EXw }, PREFIX_DATA },
+ { "%XEvpbroadcastw", { XM, EXw }, PREFIX_DATA },
+ },
+ {
+ /* VEX_W_0F38B0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F38B0_W_0) },
+ },
+ {
+ /* VEX_W_0F38B1 */
+ { PREFIX_TABLE (PREFIX_VEX_0F38B1_W_0) },
+ },
+ {
+ /* VEX_W_0F38B4 */
+ { Bad_Opcode },
+ { "%XVvpmadd52luq", { XM, Vex, EXx }, PREFIX_DATA },
+ },
+ {
+ /* VEX_W_0F38B5 */
+ { Bad_Opcode },
+ { "%XVvpmadd52huq", { XM, Vex, EXx }, PREFIX_DATA },
},
{
/* VEX_W_0F38CF */
- { "vgf2p8mulb", { XM, Vex, EXx }, PREFIX_DATA },
+ { "%XEvgf2p8mulb", { XM, Vex, EXx }, PREFIX_DATA },
},
{
/* VEX_W_0F3A00_L_1 */
{ Bad_Opcode },
- { "vpermq", { XM, EXx, Ib }, PREFIX_DATA },
+ { "%XEvpermq", { XM, EXx, Ib }, PREFIX_DATA },
},
{
/* VEX_W_0F3A01_L_1 */
{ Bad_Opcode },
- { "vpermpd", { XM, EXx, Ib }, PREFIX_DATA },
+ { "%XEvpermpd", { XM, EXx, Ib }, PREFIX_DATA },
},
{
/* VEX_W_0F3A02 */
},
{
/* VEX_W_0F3A04 */
- { "vpermilps", { XM, EXx, Ib }, PREFIX_DATA },
+ { "%XEvpermilps", { XM, EXx, Ib }, PREFIX_DATA },
},
{
/* VEX_W_0F3A05 */
},
{
/* VEX_W_0F3A1D */
- { "vcvtps2ph", { EXxmmq, XM, EXxEVexS, Ib }, PREFIX_DATA },
+ { "%XEvcvtps2ph", { EXxmmq, XM, EXxEVexS, Ib }, PREFIX_DATA },
},
{
/* VEX_W_0F3A38_L_1 */
{
/* VEX_W_0F3ACE */
{ Bad_Opcode },
- { "vgf2p8affineqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
+ { "%XEvgf2p8affineqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
},
{
/* VEX_W_0F3ACF */
{ Bad_Opcode },
- { "vgf2p8affineinvqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
+ { "%XEvgf2p8affineinvqb", { XM, Vex, EXx, Ib }, PREFIX_DATA },
},
/* VEX_W_0FXOP_08_85_L_0 */
{
{ "invlpg", { Mb }, 0 },
{ RM_TABLE (RM_0F01_REG_7_MOD_3) },
},
+ {
+ /* MOD_0F02 */
+ { "larS", { Gv, Mw }, 0 },
+ { "larS", { Gv, Ev }, 0 },
+ },
+ {
+ /* MOD_0F03 */
+ { "lslS", { Gv, Mw }, 0 },
+ { "lslS", { Gv, Ev }, 0 },
+ },
{
/* MOD_0F12_PREFIX_0 */
{ "movlpX", { XM, EXq }, 0 },
{ "prefetcht2", { Mb }, 0 },
{ "nopQ", { Ev }, 0 },
},
+ {
+ /* MOD_0F18_REG_6 */
+ { X86_64_TABLE (X86_64_0F18_REG_6_MOD_0) },
+ { "nopQ", { Ev }, 0 },
+ },
+ {
+ /* MOD_0F18_REG_7 */
+ { X86_64_TABLE (X86_64_0F18_REG_7_MOD_0) },
+ { "nopQ", { Ev }, 0 },
+ },
{
/* MOD_0F1A_PREFIX_0 */
{ "bndldx", { Gbnd, Mv_bnd }, 0 },
},
{
/* MOD_VEX_0F2B */
- { "vmovntpX", { Mx, XM }, PREFIX_OPCODE },
+ { "%XEvmovntpX", { Mx, XM }, PREFIX_OPCODE },
},
{
/* MOD_VEX_0F41_L_1 */
{ Bad_Opcode },
{ VEX_LEN_TABLE (VEX_LEN_0F385C_X86_64_P_1_W_0_M_0) },
},
+ {
+ /* MOD_VEX_0F385C_X86_64_P_3_W_0 */
+ { Bad_Opcode },
+ { VEX_LEN_TABLE (VEX_LEN_0F385C_X86_64_P_3_W_0_M_0) },
+ },
{
/* MOD_VEX_0F385E_X86_64_P_0_W_0 */
{ Bad_Opcode },
{ Bad_Opcode },
{ VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_3_W_0_M_0) },
},
+ {
+ /* MOD_VEX_0F386C_X86_64_W_0 */
+ { Bad_Opcode },
+ { VEX_LEN_TABLE (VEX_LEN_0F386C_X86_64_W_0_M_1) },
+ },
{
/* MOD_VEX_0F388C */
{ "vpmaskmov%DQ", { XM, Vex, Mx }, PREFIX_DATA },
{ "vmresume", { Skip_MODRM }, 0 },
{ "vmxoff", { Skip_MODRM }, 0 },
{ "pconfig", { Skip_MODRM }, 0 },
+ { PREFIX_TABLE (PREFIX_0F01_REG_0_MOD_3_RM_6) },
},
{
/* RM_0F01_REG_1 */
{ PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_2) },
{ "mwaitx", { { OP_Mwait, eBX_reg } }, PREFIX_OPCODE },
{ "clzero", { Skip_MODRM }, 0 },
- { "rdpru", { Skip_MODRM }, 0 },
+ { PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_5) },
{ PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_6) },
{ PREFIX_TABLE (PREFIX_0F01_REG_7_MOD_3_RM_7) },
},
#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
-/* We use the high bit to indicate different name for the same
- prefix. */
-#define REP_PREFIX (0xf3 | 0x100)
-#define XACQUIRE_PREFIX (0xf2 | 0x200)
-#define XRELEASE_PREFIX (0xf3 | 0x400)
-#define BND_PREFIX (0xf2 | 0x400)
-#define NOTRACK_PREFIX (0x3e | 0x100)
-
-static int
+/* The values used here must be non-zero, fit in 'unsigned char', and not be
+ in conflict with actual prefix opcodes. */
+#define REP_PREFIX 0x01
+#define XACQUIRE_PREFIX 0x02
+#define XRELEASE_PREFIX 0x03
+#define BND_PREFIX 0x04
+#define NOTRACK_PREFIX 0x05
+
+static enum {
+ ckp_okay,
+ ckp_bogus,
+ ckp_fetch_error,
+}
ckprefix (instr_info *ins)
{
int newrex, i, length;
- ins->rex = 0;
- ins->prefixes = 0;
- ins->used_prefixes = 0;
- ins->rex_used = 0;
- ins->evex_used = 0;
- ins->last_lock_prefix = -1;
- ins->last_repz_prefix = -1;
- ins->last_repnz_prefix = -1;
- ins->last_data_prefix = -1;
- ins->last_addr_prefix = -1;
- ins->last_rex_prefix = -1;
- ins->last_seg_prefix = -1;
- ins->fwait_prefix = -1;
- ins->active_seg_prefix = 0;
- for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++)
- ins->all_prefixes[i] = 0;
+
i = 0;
length = 0;
/* The maximum instruction length is 15bytes. */
while (length < MAX_CODE_LENGTH - 1)
{
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return ckp_fetch_error;
newrex = 0;
switch (*ins->codep)
{
if (ins->address_mode == mode_64bit)
newrex = *ins->codep;
else
- return 1;
+ return ckp_okay;
ins->last_rex_prefix = i;
break;
case 0xf3:
ins->codep++;
/* This ensures that the previous REX prefixes are noticed
as unused prefixes, as in the return case below. */
- ins->rex_used = ins->rex;
- return 1;
+ return ins->rex ? ckp_bogus : ckp_okay;
}
ins->prefixes = PREFIX_FWAIT;
break;
default:
- return 1;
+ return ckp_okay;
}
/* Rex is ignored when followed by another prefix. */
if (ins->rex)
- {
- ins->rex_used = ins->rex;
- return 1;
- }
+ return ckp_bogus;
if (*ins->codep != FWAIT_OPCODE)
ins->all_prefixes[i++] = *ins->codep;
ins->rex = newrex;
ins->codep++;
length++;
}
- return 0;
+ return ckp_bogus;
}
/* Return the name of the prefix byte PREF, or NULL if PREF is not a
prefix byte. */
static const char *
-prefix_name (instr_info *ins, int pref, int sizeflag)
+prefix_name (const instr_info *ins, int pref, int sizeflag)
{
static const char *rexes [16] =
{
}
}
-/* Here for backwards compatibility. When gdb stops using
- print_insn_i386_att and print_insn_i386_intel these functions can
- disappear, and print_insn_i386 be merged into print_insn. */
-int
-print_insn_i386_att (bfd_vma pc, disassemble_info *info)
-{
- instr_info ins;
- ins.info = info;
- ins.intel_syntax = 0;
-
- return print_insn (pc, &ins);
-}
-
-int
-print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
-{
- instr_info ins;
- ins.info = info;
- ins.intel_syntax = 1;
-
- return print_insn (pc, &ins);
-}
-
-int
-print_insn_i386 (bfd_vma pc, disassemble_info *info)
-{
- instr_info ins;
- ins.info = info;
- ins.intel_syntax = -1;
-
- return print_insn (pc, &ins);
-}
-
void
print_i386_disassembler_options (FILE *stream)
{
/* Bad opcode. */
static const struct dis386 bad_opcode = { "(bad)", { XX }, 0 };
+/* Fetch error indicator. */
+static const struct dis386 err_opcode = { NULL, { XX }, 0 };
+
/* Get a pointer to struct dis386 with a valid name. */
static const struct dis386 *
break;
case USE_3BYTE_TABLE:
- FETCH_DATA (ins->info, ins->codep + 2);
+ if (!fetch_code (ins->info, ins->codep + 2))
+ return &err_opcode;
vindex = *ins->codep++;
dp = &three_byte_table[dp->op[1].bytemode][vindex];
ins->end_codep = ins->codep;
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
+ if (!fetch_modrm (ins))
+ return &err_opcode;
break;
case USE_VEX_LEN_TABLE:
break;
case USE_XOP_8F_TABLE:
- FETCH_DATA (ins->info, ins->codep + 3);
+ if (!fetch_code (ins->info, ins->codep + 3))
+ return &err_opcode;
ins->rex = ~(*ins->codep >> 5) & 0x7;
/* VEX_TABLE_INDEX is the mmmmm part of the XOP byte 1 "RCB.mmmmm". */
ins->vex.prefix = REPNE_PREFIX_OPCODE;
break;
}
- ins->need_vex = 1;
+ ins->need_vex = true;
ins->codep++;
vindex = *ins->codep++;
dp = &xop_table[vex_table_index][vindex];
ins->end_codep = ins->codep;
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
+ if (!fetch_modrm (ins))
+ return &err_opcode;
/* No XOP encoding so far allows for a non-zero embedded prefix. Avoid
having to decode the bits for every otherwise valid encoding. */
case USE_VEX_C4_TABLE:
/* VEX prefix. */
- FETCH_DATA (ins->info, ins->codep + 3);
+ if (!fetch_code (ins->info, ins->codep + 3))
+ return &err_opcode;
ins->rex = ~(*ins->codep >> 5) & 0x7;
switch ((*ins->codep & 0x1f))
{
ins->vex.prefix = REPNE_PREFIX_OPCODE;
break;
}
- ins->need_vex = 1;
+ ins->need_vex = true;
ins->codep++;
vindex = *ins->codep++;
dp = &vex_table[vex_table_index][vindex];
ins->end_codep = ins->codep;
/* There is no MODRM byte for VEX0F 77. */
- if (vex_table_index != VEX_0F || vindex != 0x77)
- {
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
- }
+ if ((vex_table_index != VEX_0F || vindex != 0x77)
+ && !fetch_modrm (ins))
+ return &err_opcode;
break;
case USE_VEX_C5_TABLE:
/* VEX prefix. */
- FETCH_DATA (ins->info, ins->codep + 2);
+ if (!fetch_code (ins->info, ins->codep + 2))
+ return &err_opcode;
ins->rex = (*ins->codep & 0x80) ? 0 : REX_R;
/* For the 2-byte VEX prefix in 32-bit mode, the highest bit in
ins->vex.prefix = REPNE_PREFIX_OPCODE;
break;
}
- ins->need_vex = 1;
+ ins->need_vex = true;
ins->codep++;
vindex = *ins->codep++;
dp = &vex_table[dp->op[1].bytemode][vindex];
ins->end_codep = ins->codep;
/* There is no MODRM byte for VEX 77. */
- if (vindex != 0x77)
- {
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
- }
+ if (vindex != 0x77 && !fetch_modrm (ins))
+ return &err_opcode;
break;
case USE_VEX_W_TABLE:
if (!ins->need_vex)
abort ();
- dp = &vex_w_table[dp->op[1].bytemode][ins->vex.w ? 1 : 0];
+ dp = &vex_w_table[dp->op[1].bytemode][ins->vex.w];
break;
case USE_EVEX_TABLE:
- ins->two_source_ops = 0;
+ ins->two_source_ops = false;
/* EVEX prefix. */
- ins->vex.evex = 1;
- FETCH_DATA (ins->info, ins->codep + 4);
+ ins->vex.evex = true;
+ if (!fetch_code (ins->info, ins->codep + 4))
+ return &err_opcode;
/* The first byte after 0x62. */
ins->rex = ~(*ins->codep >> 5) & 0x7;
ins->vex.r = *ins->codep & 0x10;
/* Remember the static rounding bits. */
ins->vex.ll = (*ins->codep >> 5) & 3;
- ins->vex.b = (*ins->codep & 0x10) != 0;
+ ins->vex.b = *ins->codep & 0x10;
ins->vex.v = *ins->codep & 0x8;
ins->vex.mask_register_specifier = *ins->codep & 0x7;
{
/* In 16/32-bit mode silently ignore following bits. */
ins->rex &= ~REX_B;
- ins->vex.r = 1;
+ ins->vex.r = true;
}
- ins->need_vex = 1;
+ ins->need_vex = true;
ins->codep++;
vindex = *ins->codep++;
dp = &evex_table[vex_table_index][vindex];
ins->end_codep = ins->codep;
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
+ if (!fetch_modrm (ins))
+ return &err_opcode;
/* Set vector length. */
if (ins->modrm.mod == 3 && ins->vex.b)
return get_valid_dis386 (dp, ins);
}
-static void
+static bool
get_sib (instr_info *ins, int sizeflag)
{
/* If modrm.mod == 3, operand must be register. */
&& ins->modrm.mod != 3
&& ins->modrm.rm == 4)
{
- FETCH_DATA (ins->info, ins->codep + 2);
+ if (!fetch_code (ins->info, ins->codep + 2))
+ return false;
ins->sib.index = (ins->codep[1] >> 3) & 7;
ins->sib.scale = (ins->codep[1] >> 6) & 3;
ins->sib.base = ins->codep[1] & 7;
+ ins->has_sib = true;
}
+ else
+ ins->has_sib = false;
+
+ return true;
+}
+
+/* Like oappend (below), but S is a string starting with '%'. In
+ Intel syntax, the '%' is elided. */
+
+static void
+oappend_register (instr_info *ins, const char *s)
+{
+ oappend_with_style (ins, s + ins->intel_syntax, dis_style_register);
+}
+
+/* Wrap around a call to INS->info->fprintf_styled_func, printing FMT.
+ STYLE is the default style to use in the fprintf_styled_func calls,
+ however, FMT might include embedded style markers (see oappend_style),
+ these embedded markers are not printed, but instead change the style
+ used in the next fprintf_styled_func call. */
+
+static void ATTRIBUTE_PRINTF_3
+i386_dis_printf (const instr_info *ins, enum disassembler_style style,
+ const char *fmt, ...)
+{
+ va_list ap;
+ enum disassembler_style curr_style = style;
+ const char *start, *curr;
+ char staging_area[40];
+
+ va_start (ap, fmt);
+ /* In particular print_insn()'s processing of op_txt[] can hand rather long
+ strings here. Bypass vsnprintf() in such cases to avoid capacity issues
+ with the staging area. */
+ if (strcmp (fmt, "%s"))
+ {
+ int res = vsnprintf (staging_area, sizeof (staging_area), fmt, ap);
+
+ va_end (ap);
+
+ if (res < 0)
+ return;
+
+ if ((size_t) res >= sizeof (staging_area))
+ abort ();
+
+ start = curr = staging_area;
+ }
+ else
+ {
+ start = curr = va_arg (ap, const char *);
+ va_end (ap);
+ }
+
+ do
+ {
+ if (*curr == '\0'
+ || (*curr == STYLE_MARKER_CHAR
+ && ISXDIGIT (*(curr + 1))
+ && *(curr + 2) == STYLE_MARKER_CHAR))
+ {
+ /* Output content between our START position and CURR. */
+ int len = curr - start;
+ int n = (*ins->info->fprintf_styled_func) (ins->info->stream,
+ curr_style,
+ "%.*s", len, start);
+ if (n < 0)
+ break;
+
+ if (*curr == '\0')
+ break;
+
+ /* Skip over the initial STYLE_MARKER_CHAR. */
+ ++curr;
+
+ /* Update the CURR_STYLE. As there are less than 16 styles, it
+ is possible, that if the input is corrupted in some way, that
+ we might set CURR_STYLE to an invalid value. Don't worry
+ though, we check for this situation. */
+ if (*curr >= '0' && *curr <= '9')
+ curr_style = (enum disassembler_style) (*curr - '0');
+ else if (*curr >= 'a' && *curr <= 'f')
+ curr_style = (enum disassembler_style) (*curr - 'a' + 10);
+ else
+ curr_style = dis_style_text;
+
+ /* Check for an invalid style having been selected. This should
+ never happen, but it doesn't hurt to be a little paranoid. */
+ if (curr_style > dis_style_comment_start)
+ curr_style = dis_style_text;
+
+ /* Skip the hex character, and the closing STYLE_MARKER_CHAR. */
+ curr += 2;
+
+ /* Reset the START to after the style marker. */
+ start = curr;
+ }
+ else
+ ++curr;
+ }
+ while (true);
}
static int
-print_insn (bfd_vma pc, instr_info *ins)
+print_insn (bfd_vma pc, disassemble_info *info, int intel_syntax)
{
const struct dis386 *dp;
int i;
+ int ret;
char *op_txt[MAX_OPERANDS];
int needcomma;
+ bool intel_swap_2_3;
int sizeflag, orig_sizeflag;
const char *p;
struct dis_private priv;
int prefix_length;
+ int op_count;
+ instr_info ins = {
+ .info = info,
+ .intel_syntax = intel_syntax >= 0
+ ? intel_syntax
+ : (info->mach & bfd_mach_i386_intel_syntax) != 0,
+ .intel_mnemonic = !SYSV386_COMPAT,
+ .op_index[0 ... MAX_OPERANDS - 1] = -1,
+ .start_pc = pc,
+ .start_codep = priv.the_buffer,
+ .codep = priv.the_buffer,
+ .obufp = ins.obuf,
+ .last_lock_prefix = -1,
+ .last_repz_prefix = -1,
+ .last_repnz_prefix = -1,
+ .last_data_prefix = -1,
+ .last_addr_prefix = -1,
+ .last_rex_prefix = -1,
+ .last_seg_prefix = -1,
+ .fwait_prefix = -1,
+ };
+ char op_out[MAX_OPERANDS][MAX_OPERAND_BUFFER_SIZE];
- ins->isa64 = 0;
- ins->intel_mnemonic = !SYSV386_COMPAT;
- ins->op_is_jump = false;
priv.orig_sizeflag = AFLAG | DFLAG;
- if ((ins->info->mach & bfd_mach_i386_i386) != 0)
- ins->address_mode = mode_32bit;
- else if (ins->info->mach == bfd_mach_i386_i8086)
+ if ((info->mach & bfd_mach_i386_i386) != 0)
+ ins.address_mode = mode_32bit;
+ else if (info->mach == bfd_mach_i386_i8086)
{
- ins->address_mode = mode_16bit;
+ ins.address_mode = mode_16bit;
priv.orig_sizeflag = 0;
}
else
- ins->address_mode = mode_64bit;
-
- if (ins->intel_syntax == (char) -1)
- ins->intel_syntax = (ins->info->mach & bfd_mach_i386_intel_syntax) != 0;
+ ins.address_mode = mode_64bit;
- for (p = ins->info->disassembler_options; p != NULL;)
+ for (p = info->disassembler_options; p != NULL;)
{
if (startswith (p, "amd64"))
- ins->isa64 = amd64;
+ ins.isa64 = amd64;
else if (startswith (p, "intel64"))
- ins->isa64 = intel64;
+ ins.isa64 = intel64;
else if (startswith (p, "x86-64"))
{
- ins->address_mode = mode_64bit;
+ ins.address_mode = mode_64bit;
priv.orig_sizeflag |= AFLAG | DFLAG;
}
else if (startswith (p, "i386"))
{
- ins->address_mode = mode_32bit;
+ ins.address_mode = mode_32bit;
priv.orig_sizeflag |= AFLAG | DFLAG;
}
else if (startswith (p, "i8086"))
{
- ins->address_mode = mode_16bit;
+ ins.address_mode = mode_16bit;
priv.orig_sizeflag &= ~(AFLAG | DFLAG);
}
else if (startswith (p, "intel"))
{
- ins->intel_syntax = 1;
+ ins.intel_syntax = 1;
if (startswith (p + 5, "-mnemonic"))
- ins->intel_mnemonic = 1;
+ ins.intel_mnemonic = true;
}
else if (startswith (p, "att"))
{
- ins->intel_syntax = 0;
+ ins.intel_syntax = 0;
if (startswith (p + 3, "-mnemonic"))
- ins->intel_mnemonic = 0;
+ ins.intel_mnemonic = false;
}
else if (startswith (p, "addr"))
{
- if (ins->address_mode == mode_64bit)
+ if (ins.address_mode == mode_64bit)
{
if (p[4] == '3' && p[5] == '2')
priv.orig_sizeflag &= ~AFLAG;
p++;
}
- if (ins->address_mode == mode_64bit && sizeof (bfd_vma) < 8)
+ if (ins.address_mode == mode_64bit && sizeof (bfd_vma) < 8)
{
- (*ins->info->fprintf_func) (ins->info->stream,
- _("64-bit address is disabled"));
+ i386_dis_printf (&ins, dis_style_text, _("64-bit address is disabled"));
return -1;
}
- if (ins->intel_syntax)
+ if (ins.intel_syntax)
{
- ins->names64 = intel_names64;
- ins->names32 = intel_names32;
- ins->names16 = intel_names16;
- ins->names8 = intel_names8;
- ins->names8rex = intel_names8rex;
- ins->names_seg = intel_names_seg;
- ins->names_mm = intel_names_mm;
- ins->names_bnd = intel_names_bnd;
- ins->names_xmm = intel_names_xmm;
- ins->names_ymm = intel_names_ymm;
- ins->names_zmm = intel_names_zmm;
- ins->names_tmm = intel_names_tmm;
- ins->index64 = intel_index64;
- ins->index32 = intel_index32;
- ins->names_mask = intel_names_mask;
- ins->index16 = intel_index16;
- ins->open_char = '[';
- ins->close_char = ']';
- ins->separator_char = '+';
- ins->scale_char = '*';
+ ins.open_char = '[';
+ ins.close_char = ']';
+ ins.separator_char = '+';
+ ins.scale_char = '*';
}
else
{
- ins->names64 = att_names64;
- ins->names32 = att_names32;
- ins->names16 = att_names16;
- ins->names8 = att_names8;
- ins->names8rex = att_names8rex;
- ins->names_seg = att_names_seg;
- ins->names_mm = att_names_mm;
- ins->names_bnd = att_names_bnd;
- ins->names_xmm = att_names_xmm;
- ins->names_ymm = att_names_ymm;
- ins->names_zmm = att_names_zmm;
- ins->names_tmm = att_names_tmm;
- ins->index64 = att_index64;
- ins->index32 = att_index32;
- ins->names_mask = att_names_mask;
- ins->index16 = att_index16;
- ins->open_char = '(';
- ins->close_char = ')';
- ins->separator_char = ',';
- ins->scale_char = ',';
+ ins.open_char = '(';
+ ins.close_char = ')';
+ ins.separator_char = ',';
+ ins.scale_char = ',';
}
/* The output looks better if we put 7 bytes on a line, since that
- puts most long word instructions on a single line. Use 8 bytes
- for Intel L1OM. */
- if ((ins->info->mach & bfd_mach_l1om) != 0)
- ins->info->bytes_per_line = 8;
- else
- ins->info->bytes_per_line = 7;
+ puts most long word instructions on a single line. */
+ info->bytes_per_line = 7;
- ins->info->private_data = &priv;
+ info->private_data = &priv;
priv.max_fetched = priv.the_buffer;
priv.insn_start = pc;
- ins->obuf[0] = 0;
for (i = 0; i < MAX_OPERANDS; ++i)
{
- ins->op_out[i][0] = 0;
- ins->op_index[i] = -1;
+ op_out[i][0] = 0;
+ ins.op_out[i] = op_out[i];
}
- ins->start_pc = pc;
- ins->start_codep = priv.the_buffer;
- ins->codep = priv.the_buffer;
+ sizeflag = priv.orig_sizeflag;
- if (OPCODES_SIGSETJMP (priv.bailout) != 0)
+ switch (ckprefix (&ins))
{
- const char *name;
-
- /* 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. */
- if (ins->codep > priv.the_buffer)
- {
- name = prefix_name (ins, priv.the_buffer[0], priv.orig_sizeflag);
- if (name != NULL)
- (*ins->info->fprintf_func) (ins->info->stream, "%s", name);
- else
- {
- /* Just print the first byte as a .byte instruction. */
- (*ins->info->fprintf_func) (ins->info->stream, ".byte 0x%x",
- (unsigned int) priv.the_buffer[0]);
- }
-
- return 1;
- }
+ case ckp_okay:
+ break;
- return -1;
+ case ckp_bogus:
+ /* Too many prefixes or unused REX prefixes. */
+ for (i = 0;
+ i < (int) ARRAY_SIZE (ins.all_prefixes) && ins.all_prefixes[i];
+ i++)
+ i386_dis_printf (&ins, dis_style_mnemonic, "%s%s",
+ (i == 0 ? "" : " "),
+ prefix_name (&ins, ins.all_prefixes[i], sizeflag));
+ ret = i;
+ goto out;
+
+ case ckp_fetch_error:
+ goto fetch_error_out;
}
- ins->obufp = ins->obuf;
- sizeflag = priv.orig_sizeflag;
+ ins.insn_codep = ins.codep;
- if (!ckprefix (ins) || ins->rex_used)
+ if (!fetch_code (info, ins.codep + 1))
{
- /* Too many ins->prefixes or unused REX ins->prefixes. */
- for (i = 0;
- i < (int) ARRAY_SIZE (ins->all_prefixes) && ins->all_prefixes[i];
- i++)
- (*ins->info->fprintf_func) (ins->info->stream, "%s%s",
- i == 0 ? "" : " ",
- prefix_name (ins, ins->all_prefixes[i],
- sizeflag));
- return i;
+ fetch_error_out:
+ ret = fetch_error (&ins);
+ goto out;
}
- ins->insn_codep = ins->codep;
+ ins.two_source_ops = (*ins.codep == 0x62) || (*ins.codep == 0xc8);
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->two_source_ops = (*ins->codep == 0x62) || (*ins->codep == 0xc8);
-
- if (((ins->prefixes & PREFIX_FWAIT)
- && ((*ins->codep < 0xd8) || (*ins->codep > 0xdf))))
+ if (((ins.prefixes & PREFIX_FWAIT)
+ && ((*ins.codep < 0xd8) || (*ins.codep > 0xdf))))
{
- /* Handle ins->prefixes before fwait. */
- for (i = 0; i < ins->fwait_prefix && ins->all_prefixes[i];
+ /* Handle ins.prefixes before fwait. */
+ for (i = 0; i < ins.fwait_prefix && ins.all_prefixes[i];
i++)
- (*ins->info->fprintf_func) (ins->info->stream, "%s ",
- prefix_name (ins, ins->all_prefixes[i],
- sizeflag));
- (*ins->info->fprintf_func) (ins->info->stream, "fwait");
- return i + 1;
+ i386_dis_printf (&ins, dis_style_mnemonic, "%s ",
+ prefix_name (&ins, ins.all_prefixes[i], sizeflag));
+ i386_dis_printf (&ins, dis_style_mnemonic, "fwait");
+ ret = i + 1;
+ goto out;
}
- if (*ins->codep == 0x0f)
+ if (*ins.codep == 0x0f)
{
unsigned char threebyte;
- ins->codep++;
- FETCH_DATA (ins->info, ins->codep + 1);
- threebyte = *ins->codep;
+ ins.codep++;
+ if (!fetch_code (info, ins.codep + 1))
+ goto fetch_error_out;
+ threebyte = *ins.codep;
dp = &dis386_twobyte[threebyte];
- ins->need_modrm = twobyte_has_modrm[threebyte];
- ins->codep++;
+ ins.need_modrm = twobyte_has_modrm[threebyte];
+ ins.codep++;
}
else
{
- dp = &dis386[*ins->codep];
- ins->need_modrm = onebyte_has_modrm[*ins->codep];
- ins->codep++;
+ dp = &dis386[*ins.codep];
+ ins.need_modrm = onebyte_has_modrm[*ins.codep];
+ ins.codep++;
}
- /* Save sizeflag for printing the extra ins->prefixes later before updating
+ /* Save sizeflag for printing the extra ins.prefixes later before updating
it for mnemonic and operand processing. The prefix names depend
only on the address mode. */
orig_sizeflag = sizeflag;
- if (ins->prefixes & PREFIX_ADDR)
+ if (ins.prefixes & PREFIX_ADDR)
sizeflag ^= AFLAG;
- if ((ins->prefixes & PREFIX_DATA))
+ if ((ins.prefixes & PREFIX_DATA))
sizeflag ^= DFLAG;
- ins->end_codep = ins->codep;
- if (ins->need_modrm)
- {
- FETCH_DATA (ins->info, ins->codep + 1);
- ins->modrm.mod = (*ins->codep >> 6) & 3;
- ins->modrm.reg = (*ins->codep >> 3) & 7;
- ins->modrm.rm = *ins->codep & 7;
- }
- else
- memset (&ins->modrm, 0, sizeof (ins->modrm));
-
- ins->need_vex = 0;
- memset (&ins->vex, 0, sizeof (ins->vex));
+ ins.end_codep = ins.codep;
+ if (ins.need_modrm && !fetch_modrm (&ins))
+ goto fetch_error_out;
if (dp->name == NULL && dp->op[0].bytemode == FLOATCODE)
{
- get_sib (ins, sizeflag);
- dofloat (ins, sizeflag);
+ if (!get_sib (&ins, sizeflag)
+ || !dofloat (&ins, sizeflag))
+ goto fetch_error_out;
}
else
{
- dp = get_valid_dis386 (dp, ins);
- if (dp != NULL && putop (ins, dp->name, sizeflag) == 0)
+ dp = get_valid_dis386 (dp, &ins);
+ if (dp == &err_opcode)
+ goto fetch_error_out;
+ if (dp != NULL && putop (&ins, dp->name, sizeflag) == 0)
{
- get_sib (ins, sizeflag);
+ if (!get_sib (&ins, sizeflag))
+ goto fetch_error_out;
for (i = 0; i < MAX_OPERANDS; ++i)
{
- ins->obufp = ins->op_out[i];
- ins->op_ad = MAX_OPERANDS - 1 - i;
- if (dp->op[i].rtn)
- (*dp->op[i].rtn) (ins, dp->op[i].bytemode, sizeflag);
+ ins.obufp = ins.op_out[i];
+ ins.op_ad = MAX_OPERANDS - 1 - i;
+ if (dp->op[i].rtn
+ && !dp->op[i].rtn (&ins, dp->op[i].bytemode, sizeflag))
+ goto fetch_error_out;
/* For EVEX instruction after the last operand masking
should be printed. */
- if (i == 0 && ins->vex.evex)
+ if (i == 0 && ins.vex.evex)
{
/* Don't print {%k0}. */
- if (ins->vex.mask_register_specifier)
+ if (ins.vex.mask_register_specifier)
{
- oappend (ins, "{");
- oappend (ins,
- ins->names_mask[ins->vex.mask_register_specifier]);
- oappend (ins, "}");
+ const char *reg_name
+ = att_names_mask[ins.vex.mask_register_specifier];
+
+ oappend (&ins, "{");
+ oappend_register (&ins, reg_name);
+ oappend (&ins, "}");
}
- if (ins->vex.zeroing)
- oappend (ins, "{z}");
+ if (ins.vex.zeroing)
+ oappend (&ins, "{z}");
/* S/G insns require a mask and don't allow
zeroing-masking. */
if ((dp->op[0].bytemode == vex_vsib_d_w_dq_mode
|| dp->op[0].bytemode == vex_vsib_q_w_dq_mode)
- && (ins->vex.mask_register_specifier == 0
- || ins->vex.zeroing))
- oappend (ins, "/(bad)");
+ && (ins.vex.mask_register_specifier == 0
+ || ins.vex.zeroing))
+ oappend (&ins, "/(bad)");
}
}
/* Check whether rounding control was enabled for an insn not
supporting it. */
- if (ins->modrm.mod == 3 && ins->vex.b
- && !(ins->evex_used & EVEX_b_used))
+ if (ins.modrm.mod == 3 && ins.vex.b
+ && !(ins.evex_used & EVEX_b_used))
{
for (i = 0; i < MAX_OPERANDS; ++i)
{
- ins->obufp = ins->op_out[i];
- if (*ins->obufp)
+ ins.obufp = ins.op_out[i];
+ if (*ins.obufp)
continue;
- oappend (ins, names_rounding[ins->vex.ll]);
- oappend (ins, "bad}");
+ oappend (&ins, names_rounding[ins.vex.ll]);
+ oappend (&ins, "bad}");
break;
}
}
}
/* Clear instruction information. */
- ins->info->insn_info_valid = 0;
- ins->info->branch_delay_insns = 0;
- ins->info->data_size = 0;
- ins->info->insn_type = dis_noninsn;
- ins->info->target = 0;
- ins->info->target2 = 0;
+ info->insn_info_valid = 0;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_noninsn;
+ info->target = 0;
+ info->target2 = 0;
/* Reset jump operation indicator. */
- ins->op_is_jump = false;
+ ins.op_is_jump = false;
{
int jump_detection = 0;
/* Determine if this is a jump or branch. */
if ((jump_detection & 0x3) == 0x3)
{
- ins->op_is_jump = true;
+ ins.op_is_jump = true;
if (jump_detection & 0x4)
- ins->info->insn_type = dis_condbranch;
+ info->insn_type = dis_condbranch;
else
- ins->info->insn_type = (dp->name && !strncmp (dp->name, "call", 4))
+ info->insn_type = (dp->name && !strncmp (dp->name, "call", 4))
? dis_jsr : dis_branch;
}
}
/* If VEX.vvvv and EVEX.vvvv are unused, they must be all 1s, which
are all 0s in inverted form. */
- if (ins->need_vex && ins->vex.register_specifier != 0)
+ if (ins.need_vex && ins.vex.register_specifier != 0)
{
- (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
- return ins->end_codep - priv.the_buffer;
+ i386_dis_printf (&ins, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
/* If EVEX.z is set, there must be an actual mask register in use. */
- if (ins->vex.zeroing && ins->vex.mask_register_specifier == 0)
+ if (ins.vex.zeroing && ins.vex.mask_register_specifier == 0)
{
- (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
- return ins->end_codep - priv.the_buffer;
+ i386_dis_printf (&ins, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
switch (dp->prefix_requirement)
case PREFIX_DATA:
/* If only the data prefix is marked as mandatory, its absence renders
the encoding invalid. Most other PREFIX_OPCODE rules still apply. */
- if (ins->need_vex ? !ins->vex.prefix : !(ins->prefixes & PREFIX_DATA))
+ if (ins.need_vex ? !ins.vex.prefix : !(ins.prefixes & PREFIX_DATA))
{
- (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
- return ins->end_codep - priv.the_buffer;
+ i386_dis_printf (&ins, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
- ins->used_prefixes |= PREFIX_DATA;
+ ins.used_prefixes |= PREFIX_DATA;
/* Fall through. */
case PREFIX_OPCODE:
/* If the mandatory PREFIX_REPZ/PREFIX_REPNZ/PREFIX_DATA prefix is
used by putop and MMX/SSE operand and may be overridden by the
PREFIX_REPZ/PREFIX_REPNZ fix, we check the PREFIX_DATA prefix
separately. */
- if (((ins->need_vex
- ? ins->vex.prefix == REPE_PREFIX_OPCODE
- || ins->vex.prefix == REPNE_PREFIX_OPCODE
- : (ins->prefixes
+ if (((ins.need_vex
+ ? ins.vex.prefix == REPE_PREFIX_OPCODE
+ || ins.vex.prefix == REPNE_PREFIX_OPCODE
+ : (ins.prefixes
& (PREFIX_REPZ | PREFIX_REPNZ)) != 0)
- && (ins->used_prefixes
+ && (ins.used_prefixes
& (PREFIX_REPZ | PREFIX_REPNZ)) == 0)
- || (((ins->need_vex
- ? ins->vex.prefix == DATA_PREFIX_OPCODE
- : ((ins->prefixes
+ || (((ins.need_vex
+ ? ins.vex.prefix == DATA_PREFIX_OPCODE
+ : ((ins.prefixes
& (PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA))
== PREFIX_DATA))
- && (ins->used_prefixes & PREFIX_DATA) == 0))
- || (ins->vex.evex && dp->prefix_requirement != PREFIX_DATA
- && !ins->vex.w != !(ins->used_prefixes & PREFIX_DATA)))
+ && (ins.used_prefixes & PREFIX_DATA) == 0))
+ || (ins.vex.evex && dp->prefix_requirement != PREFIX_DATA
+ && !ins.vex.w != !(ins.used_prefixes & PREFIX_DATA)))
{
- (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
- return ins->end_codep - priv.the_buffer;
+ i386_dis_printf (&ins, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
break;
case PREFIX_IGNORED:
/* Zap data size and rep prefixes from used_prefixes and reinstate their
origins in all_prefixes. */
- ins->used_prefixes &= ~PREFIX_OPCODE;
- if (ins->last_data_prefix >= 0)
- ins->all_prefixes[ins->last_data_prefix] = 0x66;
- if (ins->last_repz_prefix >= 0)
- ins->all_prefixes[ins->last_repz_prefix] = 0xf3;
- if (ins->last_repnz_prefix >= 0)
- ins->all_prefixes[ins->last_repnz_prefix] = 0xf2;
+ ins.used_prefixes &= ~PREFIX_OPCODE;
+ if (ins.last_data_prefix >= 0)
+ ins.all_prefixes[ins.last_data_prefix] = 0x66;
+ if (ins.last_repz_prefix >= 0)
+ ins.all_prefixes[ins.last_repz_prefix] = 0xf3;
+ if (ins.last_repnz_prefix >= 0)
+ ins.all_prefixes[ins.last_repnz_prefix] = 0xf2;
break;
}
/* Check if the REX prefix is used. */
- if ((ins->rex ^ ins->rex_used) == 0
- && !ins->need_vex && ins->last_rex_prefix >= 0)
- ins->all_prefixes[ins->last_rex_prefix] = 0;
+ if ((ins.rex ^ ins.rex_used) == 0
+ && !ins.need_vex && ins.last_rex_prefix >= 0)
+ ins.all_prefixes[ins.last_rex_prefix] = 0;
/* Check if the SEG prefix is used. */
- if ((ins->prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
- | PREFIX_FS | PREFIX_GS)) != 0
- && (ins->used_prefixes & ins->active_seg_prefix) != 0)
- ins->all_prefixes[ins->last_seg_prefix] = 0;
+ if ((ins.prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS | PREFIX_ES
+ | PREFIX_FS | PREFIX_GS)) != 0
+ && (ins.used_prefixes & ins.active_seg_prefix) != 0)
+ ins.all_prefixes[ins.last_seg_prefix] = 0;
/* Check if the ADDR prefix is used. */
- if ((ins->prefixes & PREFIX_ADDR) != 0
- && (ins->used_prefixes & PREFIX_ADDR) != 0)
- ins->all_prefixes[ins->last_addr_prefix] = 0;
+ if ((ins.prefixes & PREFIX_ADDR) != 0
+ && (ins.used_prefixes & PREFIX_ADDR) != 0)
+ ins.all_prefixes[ins.last_addr_prefix] = 0;
/* Check if the DATA prefix is used. */
- if ((ins->prefixes & PREFIX_DATA) != 0
- && (ins->used_prefixes & PREFIX_DATA) != 0
- && !ins->need_vex)
- ins->all_prefixes[ins->last_data_prefix] = 0;
+ if ((ins.prefixes & PREFIX_DATA) != 0
+ && (ins.used_prefixes & PREFIX_DATA) != 0
+ && !ins.need_vex)
+ ins.all_prefixes[ins.last_data_prefix] = 0;
- /* Print the extra ins->prefixes. */
+ /* Print the extra ins.prefixes. */
prefix_length = 0;
- for (i = 0; i < (int) ARRAY_SIZE (ins->all_prefixes); i++)
- if (ins->all_prefixes[i])
+ for (i = 0; i < (int) ARRAY_SIZE (ins.all_prefixes); i++)
+ if (ins.all_prefixes[i])
{
const char *name;
- name = prefix_name (ins, ins->all_prefixes[i], orig_sizeflag);
+ name = prefix_name (&ins, ins.all_prefixes[i], orig_sizeflag);
if (name == NULL)
abort ();
prefix_length += strlen (name) + 1;
- (*ins->info->fprintf_func) (ins->info->stream, "%s ", name);
+ i386_dis_printf (&ins, dis_style_mnemonic, "%s ", name);
}
/* Check maximum code length. */
- if ((ins->codep - ins->start_codep) > MAX_CODE_LENGTH)
+ if ((ins.codep - ins.start_codep) > MAX_CODE_LENGTH)
{
- (*ins->info->fprintf_func) (ins->info->stream, "(bad)");
- return MAX_CODE_LENGTH;
+ i386_dis_printf (&ins, dis_style_text, "(bad)");
+ ret = MAX_CODE_LENGTH;
+ goto out;
}
- ins->obufp = ins->mnemonicendp;
- for (i = strlen (ins->obuf) + prefix_length; i < 6; i++)
- oappend (ins, " ");
- oappend (ins, " ");
- (*ins->info->fprintf_func) (ins->info->stream, "%s", ins->obuf);
+ /* Calculate the number of operands this instruction has. */
+ op_count = 0;
+ for (i = 0; i < MAX_OPERANDS; ++i)
+ if (*ins.op_out[i] != '\0')
+ ++op_count;
+
+ /* Calculate the number of spaces to print after the mnemonic. */
+ ins.obufp = ins.mnemonicendp;
+ if (op_count > 0)
+ {
+ i = strlen (ins.obuf) + prefix_length;
+ if (i < 7)
+ i = 7 - i;
+ else
+ i = 1;
+ }
+ else
+ i = 0;
+
+ /* Print the instruction mnemonic along with any trailing whitespace. */
+ i386_dis_printf (&ins, dis_style_mnemonic, "%s%*s", ins.obuf, i, "");
/* The enter and bound instructions are printed with operands in the same
order as the intel book; everything else is printed in reverse order. */
- if (ins->intel_syntax || ins->two_source_ops)
+ intel_swap_2_3 = false;
+ if (ins.intel_syntax || ins.two_source_ops)
{
- bfd_vma riprel;
-
for (i = 0; i < MAX_OPERANDS; ++i)
- op_txt[i] = ins->op_out[i];
+ op_txt[i] = ins.op_out[i];
- if (ins->intel_syntax && dp && dp->op[2].rtn == OP_Rounding
+ if (ins.intel_syntax && dp && dp->op[2].rtn == OP_Rounding
&& dp->op[3].rtn == OP_E && dp->op[4].rtn == NULL)
{
- op_txt[2] = ins->op_out[3];
- op_txt[3] = ins->op_out[2];
+ op_txt[2] = ins.op_out[3];
+ op_txt[3] = ins.op_out[2];
+ intel_swap_2_3 = true;
}
for (i = 0; i < (MAX_OPERANDS >> 1); ++i)
{
- ins->op_ad = ins->op_index[i];
- ins->op_index[i] = ins->op_index[MAX_OPERANDS - 1 - i];
- ins->op_index[MAX_OPERANDS - 1 - i] = ins->op_ad;
- riprel = ins->op_riprel[i];
- ins->op_riprel[i] = ins->op_riprel[MAX_OPERANDS - 1 - i];
- ins->op_riprel[MAX_OPERANDS - 1 - i] = riprel;
+ bool riprel;
+
+ ins.op_ad = ins.op_index[i];
+ ins.op_index[i] = ins.op_index[MAX_OPERANDS - 1 - i];
+ ins.op_index[MAX_OPERANDS - 1 - i] = ins.op_ad;
+ riprel = ins.op_riprel[i];
+ ins.op_riprel[i] = ins.op_riprel[MAX_OPERANDS - 1 - i];
+ ins.op_riprel[MAX_OPERANDS - 1 - i] = riprel;
}
}
else
{
for (i = 0; i < MAX_OPERANDS; ++i)
- op_txt[MAX_OPERANDS - 1 - i] = ins->op_out[i];
+ op_txt[MAX_OPERANDS - 1 - i] = ins.op_out[i];
}
needcomma = 0;
for (i = 0; i < MAX_OPERANDS; ++i)
if (*op_txt[i])
{
+ /* In Intel syntax embedded rounding / SAE are not separate operands.
+ Instead they're attached to the prior register operand. Simply
+ suppress emission of the comma to achieve that effect. */
+ switch (i & -(ins.intel_syntax && dp))
+ {
+ case 2:
+ if (dp->op[2].rtn == OP_Rounding && !intel_swap_2_3)
+ needcomma = 0;
+ break;
+ case 3:
+ if (dp->op[3].rtn == OP_Rounding || intel_swap_2_3)
+ needcomma = 0;
+ break;
+ }
if (needcomma)
- (*ins->info->fprintf_func) (ins->info->stream, ",");
- if (ins->op_index[i] != -1 && !ins->op_riprel[i])
+ i386_dis_printf (&ins, dis_style_text, ",");
+ if (ins.op_index[i] != -1 && !ins.op_riprel[i])
{
- bfd_vma target = (bfd_vma) ins->op_address[ins->op_index[i]];
+ bfd_vma target = (bfd_vma) ins.op_address[ins.op_index[i]];
- if (ins->op_is_jump)
+ if (ins.op_is_jump)
{
- ins->info->insn_info_valid = 1;
- ins->info->branch_delay_insns = 0;
- ins->info->data_size = 0;
- ins->info->target = target;
- ins->info->target2 = 0;
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->target = target;
+ info->target2 = 0;
}
- (*ins->info->print_address_func) (target, ins->info);
+ (*info->print_address_func) (target, info);
}
else
- (*ins->info->fprintf_func) (ins->info->stream, "%s", op_txt[i]);
+ i386_dis_printf (&ins, dis_style_text, "%s", op_txt[i]);
needcomma = 1;
}
for (i = 0; i < MAX_OPERANDS; i++)
- if (ins->op_index[i] != -1 && ins->op_riprel[i])
+ if (ins.op_index[i] != -1 && ins.op_riprel[i])
{
- (*ins->info->fprintf_func) (ins->info->stream, " # ");
- (*ins->info->print_address_func) ((bfd_vma)
- (ins->start_pc + (ins->codep - ins->start_codep)
- + ins->op_address[ins->op_index[i]]), ins->info);
+ i386_dis_printf (&ins, dis_style_comment_start, " # ");
+ (*info->print_address_func)
+ ((bfd_vma)(ins.start_pc + (ins.codep - ins.start_codep)
+ + ins.op_address[ins.op_index[i]]),
+ info);
break;
}
- return ins->codep - priv.the_buffer;
+ ret = ins.codep - priv.the_buffer;
+ out:
+ info->private_data = NULL;
+ return ret;
+}
+
+/* Here for backwards compatibility. When gdb stops using
+ print_insn_i386_att and print_insn_i386_intel these functions can
+ disappear, and print_insn_i386 be merged into print_insn. */
+int
+print_insn_i386_att (bfd_vma pc, disassemble_info *info)
+{
+ return print_insn (pc, info, 0);
+}
+
+int
+print_insn_i386_intel (bfd_vma pc, disassemble_info *info)
+{
+ return print_insn (pc, info, 1);
+}
+
+int
+print_insn_i386 (bfd_vma pc, disassemble_info *info)
+{
+ return print_insn (pc, info, -1);
}
static const char *float_mem[] = {
},
};
-static char *fgrps[][8] = {
+static const char *const fgrps[][8] = {
/* Bad opcode 0 */
{
"(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
ins->mnemonicendp += 2;
}
-static void
+static bool
OP_Skip_MODRM (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
/* Skip mod/rm byte. */
MODRM_CHECK;
ins->codep++;
+ return true;
}
-static void
+static bool
dofloat (instr_info *ins, int sizeflag)
{
const struct dis386 *dp;
putop (ins, float_mem[fp_indx], sizeflag);
ins->obufp = ins->op_out[0];
ins->op_ad = 2;
- OP_E (ins, float_mem_mode[fp_indx], sizeflag);
- return;
+ return OP_E (ins, float_mem_mode[fp_indx], sizeflag);
}
/* Skip mod/rm byte. */
MODRM_CHECK;
/* Instruction fnstsw is only one with strange arg. */
if (floatop == 0xdf && ins->codep[-1] == 0xe0)
- strcpy (ins->op_out[0], ins->names16[0]);
+ strcpy (ins->op_out[0], att_names16[0] + ins->intel_syntax);
}
else
{
ins->obufp = ins->op_out[0];
ins->op_ad = 2;
- if (dp->op[0].rtn)
- (*dp->op[0].rtn) (ins, dp->op[0].bytemode, sizeflag);
+ if (dp->op[0].rtn
+ && !dp->op[0].rtn (ins, dp->op[0].bytemode, sizeflag))
+ return false;
ins->obufp = ins->op_out[1];
ins->op_ad = 1;
- if (dp->op[1].rtn)
- (*dp->op[1].rtn) (ins, dp->op[1].bytemode, sizeflag);
+ if (dp->op[1].rtn
+ && !dp->op[1].rtn (ins, dp->op[1].bytemode, sizeflag))
+ return false;
}
+ return true;
}
-/* Like oappend (below), but S is a string starting with '%'.
- In Intel syntax, the '%' is elided. */
-static void
-oappend_maybe_intel (instr_info *ins, const char *s)
-{
- oappend (ins, s + ins->intel_syntax);
-}
-
-static void
+static bool
OP_ST (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- oappend_maybe_intel (ins, "%st");
+ oappend_register (ins, "%st");
+ return true;
}
-static void
+static bool
OP_STi (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- sprintf (ins->scratchbuf, "%%st(%d)", ins->modrm.rm);
- oappend_maybe_intel (ins, ins->scratchbuf);
+ char scratch[8];
+ int res = snprintf (scratch, ARRAY_SIZE (scratch), "%%st(%d)", ins->modrm.rm);
+
+ if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+ abort ();
+ oappend_register (ins, scratch);
+ return true;
}
/* Capital letters in template are macros. */
switch (last[0])
{
case 'X':
- if (ins->vex.w)
+ if (!ins->vex.evex || ins->vex.w)
*ins->obufp++ = 'd';
else
oappend (ins, "{bad}");
else
*ins->obufp++ = 'w';
break;
- case 'E': /* For jcxz/jecxz */
+ case 'E':
+ if (l == 1)
+ {
+ switch (last[0])
+ {
+ case 'X':
+ if (!ins->vex.evex || ins->vex.b || ins->vex.ll >= 2
+ || !ins->vex.r
+ || (ins->modrm.mod == 3 && (ins->rex & REX_X))
+ || !ins->vex.v || ins->vex.mask_register_specifier)
+ break;
+ /* AVX512 extends a number of V*D insns to also have V*Q variants,
+ merely distinguished by EVEX.W. Look for a use of the
+ respective macro. */
+ if (ins->vex.w)
+ {
+ const char *pct = strchr (p + 1, '%');
+
+ if (pct != NULL && pct[1] == 'D' && pct[2] == 'Q')
+ break;
+ }
+ *ins->obufp++ = '{';
+ *ins->obufp++ = 'e';
+ *ins->obufp++ = 'v';
+ *ins->obufp++ = 'e';
+ *ins->obufp++ = 'x';
+ *ins->obufp++ = '}';
+ *ins->obufp++ = ' ';
+ break;
+ default:
+ abort ();
+ }
+ break;
+ }
+ /* For jcxz/jecxz */
if (ins->address_mode == mode_64bit)
{
if (sizeflag & AFLAG)
}
else if (l == 1 && last[0] == 'X')
{
- if (ins->vex.w == 0)
+ if (!ins->vex.w)
*ins->obufp++ = 'h';
else
oappend (ins, "{bad}");
goto case_S;
case 'X':
- if (!ins->vex.w)
+ if (!ins->vex.evex || !ins->vex.w)
*ins->obufp++ = 's';
else
oappend (ins, "{bad}");
case 'V':
if (l == 0)
abort ();
- else if (l == 1
- && (last[0] == 'L' || last[0] == 'X'))
+ else if (l == 1)
{
- if (last[0] == 'X')
+ switch (last[0])
{
+ case 'X':
+ if (ins->vex.evex)
+ break;
*ins->obufp++ = '{';
*ins->obufp++ = 'v';
*ins->obufp++ = 'e';
*ins->obufp++ = 'x';
*ins->obufp++ = '}';
- }
- else if (ins->rex & REX_W)
- {
+ *ins->obufp++ = ' ';
+ break;
+ case 'L':
+ if (!(ins->rex & REX_W))
+ break;
*ins->obufp++ = 'a';
*ins->obufp++ = 'b';
*ins->obufp++ = 's';
+ break;
+ default:
+ abort ();
}
}
else
return 0;
}
+/* Add a style marker to *INS->obufp that encodes STYLE. This assumes that
+ the buffer pointed to by INS->obufp has space. A style marker is made
+ from the STYLE_MARKER_CHAR followed by STYLE converted to a single hex
+ digit, followed by another STYLE_MARKER_CHAR. This function assumes
+ that the number of styles is not greater than 16. */
+
static void
-oappend (instr_info *ins, const char *s)
+oappend_insert_style (instr_info *ins, enum disassembler_style style)
+{
+ unsigned num = (unsigned) style;
+
+ /* We currently assume that STYLE can be encoded as a single hex
+ character. If more styles are added then this might start to fail,
+ and we'll need to expand this code. */
+ if (num > 0xf)
+ abort ();
+
+ *ins->obufp++ = STYLE_MARKER_CHAR;
+ *ins->obufp++ = (num < 10 ? ('0' + num)
+ : ((num < 16) ? ('a' + (num - 10)) : '0'));
+ *ins->obufp++ = STYLE_MARKER_CHAR;
+
+ /* This final null character is not strictly necessary, after inserting a
+ style marker we should always be inserting some additional content.
+ However, having the buffer null terminated doesn't cost much, and make
+ it easier to debug what's going on. Also, if we do ever forget to add
+ any additional content after this style marker, then the buffer will
+ still be well formed. */
+ *ins->obufp = '\0';
+}
+
+static void
+oappend_with_style (instr_info *ins, const char *s,
+ enum disassembler_style style)
{
+ oappend_insert_style (ins, style);
ins->obufp = stpcpy (ins->obufp, s);
}
+/* Like oappend_with_style but always with text style. */
+
+static void
+oappend (instr_info *ins, const char *s)
+{
+ oappend_with_style (ins, s, dis_style_text);
+}
+
+/* Add a single character C to the buffer pointer to by INS->obufp, marking
+ the style for the character as STYLE. */
+
+static void
+oappend_char_with_style (instr_info *ins, const char c,
+ enum disassembler_style style)
+{
+ oappend_insert_style (ins, style);
+ *ins->obufp++ = c;
+ *ins->obufp = '\0';
+}
+
+/* Like oappend_char_with_style, but always uses dis_style_text. */
+
+static void
+oappend_char (instr_info *ins, const char c)
+{
+ oappend_char_with_style (ins, c, dis_style_text);
+}
+
static void
append_seg (instr_info *ins)
{
switch (ins->active_seg_prefix)
{
case PREFIX_CS:
- oappend_maybe_intel (ins, "%cs:");
+ oappend_register (ins, att_names_seg[1]);
break;
case PREFIX_DS:
- oappend_maybe_intel (ins, "%ds:");
+ oappend_register (ins, att_names_seg[3]);
break;
case PREFIX_SS:
- oappend_maybe_intel (ins, "%ss:");
+ oappend_register (ins, att_names_seg[2]);
break;
case PREFIX_ES:
- oappend_maybe_intel (ins, "%es:");
+ oappend_register (ins, att_names_seg[0]);
break;
case PREFIX_FS:
- oappend_maybe_intel (ins, "%fs:");
+ oappend_register (ins, att_names_seg[4]);
break;
case PREFIX_GS:
- oappend_maybe_intel (ins, "%gs:");
+ oappend_register (ins, att_names_seg[5]);
break;
default:
break;
}
+ oappend_char (ins, ':');
}
-static void
+static bool
OP_indirE (instr_info *ins, int bytemode, int sizeflag)
{
if (!ins->intel_syntax)
oappend (ins, "*");
- OP_E (ins, bytemode, sizeflag);
+ return OP_E (ins, bytemode, sizeflag);
}
static void
-print_operand_value (instr_info *ins, char *buf, int hex, bfd_vma disp)
+print_operand_value (instr_info *ins, bfd_vma disp,
+ enum disassembler_style style)
{
- if (ins->address_mode == mode_64bit)
- {
- if (hex)
- {
- char tmp[30];
- int i;
- buf[0] = '0';
- buf[1] = 'x';
- sprintf_vma (tmp, disp);
- for (i = 0; tmp[i] == '0' && tmp[i + 1]; i++);
- strcpy (buf + 2, tmp + i);
- }
- else
- {
- bfd_signed_vma v = disp;
- char tmp[30];
- int i;
- if (v < 0)
- {
- *(buf++) = '-';
- v = -disp;
- /* Check for possible overflow on 0x8000000000000000. */
- if (v < 0)
- {
- strcpy (buf, "9223372036854775808");
- return;
- }
- }
- if (!v)
- {
- strcpy (buf, "0");
- return;
- }
+ char tmp[30];
- i = 0;
- tmp[29] = 0;
- while (v)
- {
- tmp[28 - i] = (v % 10) + '0';
- v /= 10;
- i++;
- }
- strcpy (buf, tmp + 29 - i);
- }
- }
+ if (ins->address_mode == mode_64bit)
+ sprintf (tmp, "0x%" PRIx64, (uint64_t) disp);
else
- {
- if (hex)
- sprintf (buf, "0x%x", (unsigned int) disp);
- else
- sprintf (buf, "%d", (int) disp);
- }
+ sprintf (tmp, "0x%x", (unsigned int) disp);
+ oappend_with_style (ins, tmp, style);
+}
+
+/* Like oappend, but called for immediate operands. */
+
+static void
+oappend_immediate (instr_info *ins, bfd_vma imm)
+{
+ if (!ins->intel_syntax)
+ oappend_char_with_style (ins, '$', dis_style_immediate);
+ print_operand_value (ins, imm, dis_style_immediate);
}
/* Put DISP in BUF as signed hex number. */
static void
-print_displacement (instr_info *ins, char *buf, bfd_vma disp)
+print_displacement (instr_info *ins, bfd_signed_vma val)
{
- bfd_signed_vma val = disp;
char tmp[30];
- int i, j = 0;
if (val < 0)
{
- buf[j++] = '-';
- val = -disp;
+ oappend_char_with_style (ins, '-', dis_style_address_offset);
+ val = (bfd_vma) 0 - val;
/* Check for possible overflow. */
if (val < 0)
switch (ins->address_mode)
{
case mode_64bit:
- strcpy (buf + j, "0x8000000000000000");
+ oappend_with_style (ins, "0x8000000000000000",
+ dis_style_address_offset);
break;
case mode_32bit:
- strcpy (buf + j, "0x80000000");
+ oappend_with_style (ins, "0x80000000",
+ dis_style_address_offset);
break;
case mode_16bit:
- strcpy (buf + j, "0x8000");
+ oappend_with_style (ins, "0x8000",
+ dis_style_address_offset);
break;
}
return;
}
}
- buf[j++] = '0';
- buf[j++] = 'x';
-
- sprintf_vma (tmp, (bfd_vma) val);
- for (i = 0; tmp[i] == '0'; i++)
- continue;
- if (tmp[i] == '\0')
- i--;
- strcpy (buf + j, tmp + i);
+ sprintf (tmp, "0x%" PRIx64, (int64_t) val);
+ oappend_with_style (ins, tmp, dis_style_address_offset);
}
static void
case x_mode:
case evex_half_bcst_xmmq_mode:
if (ins->vex.w)
- oappend (ins, "QWORD PTR ");
+ oappend (ins, "QWORD BCST ");
else
- oappend (ins, "DWORD PTR ");
+ oappend (ins, "DWORD BCST ");
break;
case xh_mode:
case evex_half_bcst_xmmqh_mode:
case evex_half_bcst_xmmqdh_mode:
- oappend (ins, "WORD PTR ");
+ oappend (ins, "WORD BCST ");
break;
default:
- ins->vex.no_broadcast = 1;
+ ins->vex.no_broadcast = true;
break;
}
return;
abort ();
}
break;
- case ymmxmm_mode:
- if (!ins->need_vex)
- abort ();
-
- switch (ins->vex.length)
- {
- case 128:
- case 256:
- oappend (ins, "XMMWORD PTR ");
- break;
- default:
- abort ();
- }
- break;
case o_mode:
oappend (ins, "OWORD PTR ");
break;
print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
int bytemode, int sizeflag)
{
- const char **names;
+ const char (*names)[8];
USED_REX (rexmask);
if (ins->rex & rexmask)
if (reg & 4)
USED_REX (0);
if (ins->rex)
- names = ins->names8rex;
+ names = att_names8rex;
else
- names = ins->names8;
+ names = att_names8;
break;
case w_mode:
- names = ins->names16;
+ names = att_names16;
break;
case d_mode:
case dw_mode:
case db_mode:
- names = ins->names32;
+ names = att_names32;
break;
case q_mode:
- names = ins->names64;
+ names = att_names64;
break;
case m_mode:
case v_bnd_mode:
- names = ins->address_mode == mode_64bit ? ins->names64 : ins->names32;
+ names = ins->address_mode == mode_64bit ? att_names64 : att_names32;
break;
case bnd_mode:
case bnd_swap_mode:
oappend (ins, "(bad)");
return;
}
- names = ins->names_bnd;
+ names = att_names_bnd;
break;
case indir_v_mode:
if (ins->address_mode == mode_64bit && ins->isa64 == intel64)
{
- names = ins->names64;
+ names = att_names64;
break;
}
/* Fall through. */
if (ins->address_mode == mode_64bit && ((sizeflag & DFLAG)
|| (ins->rex & REX_W)))
{
- names = ins->names64;
+ names = att_names64;
break;
}
bytemode = v_mode;
case dq_mode:
USED_REX (REX_W);
if (ins->rex & REX_W)
- names = ins->names64;
+ names = att_names64;
else if (bytemode != v_mode && bytemode != v_swap_mode)
- names = ins->names32;
+ names = att_names32;
else
{
if (sizeflag & DFLAG)
- names = ins->names32;
+ names = att_names32;
else
- names = ins->names16;
+ names = att_names16;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
}
break;
case movsxd_mode:
if (!(sizeflag & DFLAG) && ins->isa64 == intel64)
- names = ins->names16;
+ names = att_names16;
else
- names = ins->names32;
+ names = att_names32;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
break;
case va_mode:
names = (ins->address_mode == mode_64bit
- ? ins->names64 : ins->names32);
+ ? att_names64 : att_names32);
if (!(ins->prefixes & PREFIX_ADDR))
names = (ins->address_mode == mode_16bit
- ? ins->names16 : names);
+ ? att_names16 : names);
else
{
/* Remove "addr16/addr32". */
ins->all_prefixes[ins->last_addr_prefix] = 0;
names = (ins->address_mode != mode_32bit
- ? ins->names32 : ins->names16);
+ ? att_names32 : att_names16);
ins->used_prefixes |= PREFIX_ADDR;
}
break;
oappend (ins, "(bad)");
return;
}
- names = ins->names_mask;
+ names = att_names_mask;
break;
case 0:
return;
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
return;
}
- oappend (ins, names[reg]);
+ oappend_register (ins, names[reg]);
}
-static void
+static bool
OP_E_memory (instr_info *ins, int bytemode, int sizeflag)
{
- bfd_vma disp = 0;
int add = (ins->rex & REX_B) ? 8 : 0;
int riprel = 0;
int shift;
if ((sizeflag & AFLAG) || ins->address_mode == mode_64bit)
{
/* 32/64 bit address mode */
+ bfd_signed_vma disp = 0;
int havedisp;
- int havesib;
int havebase;
- int haveindex;
int needindex;
int needaddr32;
int base, rbase;
|| bytemode == bnd_mode
|| bytemode == bnd_swap_mode);
bool check_gather = false;
- const char **indexes64 = ins->names64;
- const char **indexes32 = ins->names32;
+ const char (*indexes)[8] = NULL;
- havesib = 0;
havebase = 1;
- haveindex = 0;
base = ins->modrm.rm;
if (base == 4)
{
- havesib = 1;
vindex = ins->sib.index;
USED_REX (REX_X);
if (ins->rex & REX_X)
check_gather = ins->obufp == ins->op_out[1];
}
- haveindex = 1;
switch (ins->vex.length)
{
case 128:
- indexes64 = indexes32 = ins->names_xmm;
+ indexes = att_names_xmm;
break;
case 256:
if (!ins->vex.w
|| bytemode == vex_vsib_q_w_dq_mode)
- indexes64 = indexes32 = ins->names_ymm;
+ indexes = att_names_ymm;
else
- indexes64 = indexes32 = ins->names_xmm;
+ indexes = att_names_xmm;
break;
case 512:
if (!ins->vex.w
|| bytemode == vex_vsib_q_w_dq_mode)
- indexes64 = indexes32 = ins->names_zmm;
+ indexes = att_names_zmm;
else
- indexes64 = indexes32 = ins->names_ymm;
+ indexes = att_names_ymm;
break;
default:
abort ();
}
break;
default:
- haveindex = vindex != 4;
+ if (vindex != 4)
+ indexes = ins->address_mode == mode_64bit && !addr32flag
+ ? att_names64 : att_names32;
break;
}
scale = ins->sib.scale;
|| bytemode == vex_sibmem_mode)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
}
rbase = base + add;
if (base == 5)
{
havebase = 0;
- if (ins->address_mode == mode_64bit && !havesib)
+ if (ins->address_mode == mode_64bit && !ins->has_sib)
riprel = 1;
- disp = get32s (ins);
+ if (!get32s (ins, &disp))
+ return false;
if (riprel && bytemode == v_bndmk_mode)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
}
break;
case 1:
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
disp = *ins->codep++;
if ((disp & 0x80) != 0)
disp -= 0x100;
disp <<= shift;
break;
case 2:
- disp = get32s (ins);
+ if (!get32s (ins, &disp))
+ return false;
break;
}
needindex = 0;
needaddr32 = 0;
- if (havesib
+ if (ins->has_sib
&& !havebase
- && !haveindex
+ && !indexes
&& ins->address_mode != mode_16bit)
{
if (ins->address_mode == mode_64bit)
havedisp = (havebase
|| needindex
- || (havesib && (haveindex || scale != 0)));
+ || (ins->has_sib && (indexes || scale != 0)));
if (!ins->intel_syntax)
if (ins->modrm.mod != 0 || base == 5)
{
if (havedisp || riprel)
- print_displacement (ins, ins->scratchbuf, disp);
+ print_displacement (ins, disp);
else
- print_operand_value (ins, ins->scratchbuf, 1, disp);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, disp, dis_style_address_offset);
if (riprel)
{
- set_op (ins, disp, 1);
- oappend (ins, !addr32flag ? "(%rip)" : "(%eip)");
+ set_op (ins, disp, true);
+ oappend_char (ins, '(');
+ oappend_with_style (ins, !addr32flag ? "%rip" : "%eip",
+ dis_style_register);
+ oappend_char (ins, ')');
}
}
- if ((havebase || haveindex || needindex || needaddr32 || riprel)
+ if ((havebase || indexes || needindex || needaddr32 || riprel)
&& (ins->address_mode != mode_64bit
|| ((bytemode != v_bnd_mode)
&& (bytemode != v_bndmk_mode)
if (havedisp || (ins->intel_syntax && riprel))
{
- *ins->obufp++ = ins->open_char;
+ oappend_char (ins, ins->open_char);
if (ins->intel_syntax && riprel)
{
- set_op (ins, disp, 1);
- oappend (ins, !addr32flag ? "rip" : "eip");
+ set_op (ins, disp, true);
+ oappend_with_style (ins, !addr32flag ? "rip" : "eip",
+ dis_style_register);
}
- *ins->obufp = '\0';
if (havebase)
- oappend (ins, ins->address_mode == mode_64bit && !addr32flag
- ? ins->names64[rbase] : ins->names32[rbase]);
- if (havesib)
+ oappend_register
+ (ins,
+ (ins->address_mode == mode_64bit && !addr32flag
+ ? att_names64 : att_names32)[rbase]);
+ if (ins->has_sib)
{
/* ESP/RSP won't allow index. If base isn't ESP/RSP,
print index to tell base + index from base. */
if (scale != 0
|| needindex
- || haveindex
+ || indexes
|| (havebase && base != ESP_REG_NUM))
{
if (!ins->intel_syntax || havebase)
- {
- *ins->obufp++ = ins->separator_char;
- *ins->obufp = '\0';
- }
- if (haveindex)
+ oappend_char (ins, ins->separator_char);
+ if (indexes)
{
if (ins->address_mode == mode_64bit || vindex < 16)
- oappend (ins, ins->address_mode == mode_64bit
- && !addr32flag
- ? indexes64[vindex] : indexes32[vindex]);
+ oappend_register (ins, indexes[vindex]);
else
oappend (ins, "(bad)");
}
else
- oappend (ins, ins->address_mode == mode_64bit && !addr32flag
- ? ins->index64 : ins->index32);
-
- *ins->obufp++ = ins->scale_char;
- *ins->obufp = '\0';
- sprintf (ins->scratchbuf, "%d", 1 << scale);
- oappend (ins, ins->scratchbuf);
+ oappend_register (ins,
+ ins->address_mode == mode_64bit
+ && !addr32flag
+ ? att_index64
+ : att_index32);
+
+ oappend_char (ins, ins->scale_char);
+ oappend_char_with_style (ins, '0' + (1 << scale),
+ dis_style_immediate);
}
}
if (ins->intel_syntax
&& (disp || ins->modrm.mod != 0 || base == 5))
{
- if (!havedisp || (bfd_signed_vma) disp >= 0)
- {
- *ins->obufp++ = '+';
- *ins->obufp = '\0';
- }
- else if (ins->modrm.mod != 1 && disp != -disp)
- {
- *ins->obufp++ = '-';
- *ins->obufp = '\0';
- disp = - (bfd_signed_vma) disp;
- }
-
+ if (!havedisp || disp >= 0)
+ oappend_char (ins, '+');
if (havedisp)
- print_displacement (ins, ins->scratchbuf, disp);
+ print_displacement (ins, disp);
else
- print_operand_value (ins, ins->scratchbuf, 1, disp);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, disp, dis_style_address_offset);
}
- *ins->obufp++ = ins->close_char;
- *ins->obufp = '\0';
+ oappend_char (ins, ins->close_char);
if (check_gather)
{
{
if (!ins->active_seg_prefix)
{
- oappend (ins, ins->names_seg[ds_reg - es_reg]);
+ oappend_register (ins, att_names_seg[ds_reg - es_reg]);
oappend (ins, ":");
}
- print_operand_value (ins, ins->scratchbuf, 1, disp);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, disp, dis_style_text);
}
}
}
|| bytemode == vex_vsib_q_w_dq_mode)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
else
{
/* 16 bit address mode */
+ int disp = 0;
+
ins->used_prefixes |= ins->prefixes & PREFIX_ADDR;
switch (ins->modrm.mod)
{
case 0:
if (ins->modrm.rm == 6)
{
- disp = get16 (ins);
+ case 2:
+ if (!get16 (ins, &disp))
+ return false;
if ((disp & 0x8000) != 0)
disp -= 0x10000;
}
break;
case 1:
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
disp = *ins->codep++;
if ((disp & 0x80) != 0)
disp -= 0x100;
if (ins->vex.evex && shift > 0)
disp <<= shift;
break;
- case 2:
- disp = get16 (ins);
- if ((disp & 0x8000) != 0)
- disp -= 0x10000;
- break;
}
if (!ins->intel_syntax)
if (ins->modrm.mod != 0 || ins->modrm.rm == 6)
- {
- print_displacement (ins, ins->scratchbuf, disp);
- oappend (ins, ins->scratchbuf);
- }
+ print_displacement (ins, disp);
if (ins->modrm.mod != 0 || ins->modrm.rm != 6)
{
- *ins->obufp++ = ins->open_char;
- *ins->obufp = '\0';
- oappend (ins, ins->index16[ins->modrm.rm]);
+ oappend_char (ins, ins->open_char);
+ oappend (ins, ins->intel_syntax ? intel_index16[ins->modrm.rm]
+ : att_index16[ins->modrm.rm]);
if (ins->intel_syntax
&& (disp || ins->modrm.mod != 0 || ins->modrm.rm == 6))
{
- if ((bfd_signed_vma) disp >= 0)
- {
- *ins->obufp++ = '+';
- *ins->obufp = '\0';
- }
- else if (ins->modrm.mod != 1)
- {
- *ins->obufp++ = '-';
- *ins->obufp = '\0';
- disp = - (bfd_signed_vma) disp;
- }
-
- print_displacement (ins, ins->scratchbuf, disp);
- oappend (ins, ins->scratchbuf);
+ if (disp >= 0)
+ oappend_char (ins, '+');
+ print_displacement (ins, disp);
}
- *ins->obufp++ = ins->close_char;
- *ins->obufp = '\0';
+ oappend_char (ins, ins->close_char);
}
else if (ins->intel_syntax)
{
if (!ins->active_seg_prefix)
{
- oappend (ins, ins->names_seg[ds_reg - es_reg]);
+ oappend_register (ins, att_names_seg[ds_reg - es_reg]);
oappend (ins, ":");
}
- print_operand_value (ins, ins->scratchbuf, 1, disp & 0xffff);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, disp & 0xffff, dis_style_text);
}
}
if (ins->vex.b)
{
ins->evex_used |= EVEX_b_used;
- if (!ins->vex.no_broadcast)
+
+ /* Broadcast can only ever be valid for memory sources. */
+ if (ins->obufp == ins->op_out[0])
+ ins->vex.no_broadcast = true;
+
+ if (!ins->vex.no_broadcast
+ && (!ins->intel_syntax || !(ins->evex_used & EVEX_len_used)))
{
if (bytemode == xh_mode)
{
- if (ins->vex.w)
- oappend (ins, "{bad}");
- else
+ switch (ins->vex.length)
{
- switch (ins->vex.length)
- {
- case 128:
- oappend (ins, "{1to8}");
- break;
- case 256:
- oappend (ins, "{1to16}");
- break;
- case 512:
- oappend (ins, "{1to32}");
- break;
- default:
- abort ();
- }
+ case 128:
+ oappend (ins, "{1to8}");
+ break;
+ case 256:
+ oappend (ins, "{1to16}");
+ break;
+ case 512:
+ oappend (ins, "{1to32}");
+ break;
+ default:
+ abort ();
}
}
+ else if (bytemode == q_mode
+ || bytemode == ymmq_mode)
+ ins->vex.no_broadcast = true;
else if (ins->vex.w
|| bytemode == evex_half_bcst_xmmqdh_mode
|| bytemode == evex_half_bcst_xmmq_mode)
}
}
else
- ins->vex.no_broadcast = 1;
+ ins->vex.no_broadcast = true;
}
if (ins->vex.no_broadcast)
oappend (ins, "{bad}");
}
+
+ return true;
}
-static void
+static bool
OP_E (instr_info *ins, int bytemode, int sizeflag)
{
/* Skip mod/rm byte. */
swap_operand (ins);
print_register (ins, ins->modrm.rm, REX_B, bytemode, sizeflag);
+ return true;
}
- else
- OP_E_memory (ins, bytemode, sizeflag);
+
+ return OP_E_memory (ins, bytemode, sizeflag);
}
-static void
+static bool
OP_G (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->vex.evex && !ins->vex.r && ins->address_mode == mode_64bit)
- {
- oappend (ins, "(bad)");
- return;
- }
-
- print_register (ins, ins->modrm.reg, REX_R, bytemode, sizeflag);
+ oappend (ins, "(bad)");
+ else
+ print_register (ins, ins->modrm.reg, REX_R, bytemode, sizeflag);
+ return true;
}
-#ifdef BFD64
-static bfd_vma
-get64 (instr_info *ins)
+static bool
+get64 (instr_info *ins, uint64_t *res)
{
- bfd_vma x;
unsigned int a;
unsigned int b;
- FETCH_DATA (ins->info, ins->codep + 8);
+ if (!fetch_code (ins->info, ins->codep + 8))
+ return false;
a = *ins->codep++ & 0xff;
a |= (*ins->codep++ & 0xff) << 8;
a |= (*ins->codep++ & 0xff) << 16;
b |= (*ins->codep++ & 0xff) << 8;
b |= (*ins->codep++ & 0xff) << 16;
b |= (*ins->codep++ & 0xffu) << 24;
- x = a + ((bfd_vma) b << 32);
- return x;
-}
-#else
-static bfd_vma
-get64 (instr_info *ins ATTRIBUTE_UNUSED)
-{
- abort ();
- return 0;
+ *res = a + ((uint64_t) b << 32);
+ return true;
}
-#endif
-static bfd_signed_vma
-get32 (instr_info *ins)
+static bool
+get32 (instr_info *ins, bfd_signed_vma *res)
{
- bfd_signed_vma x = 0;
-
- FETCH_DATA (ins->info, ins->codep + 4);
- x = *ins->codep++ & (bfd_signed_vma) 0xff;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 8;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 16;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 24;
- return x;
+ if (!fetch_code (ins->info, ins->codep + 4))
+ return false;
+ *res = *ins->codep++ & (bfd_vma) 0xff;
+ *res |= (*ins->codep++ & (bfd_vma) 0xff) << 8;
+ *res |= (*ins->codep++ & (bfd_vma) 0xff) << 16;
+ *res |= (*ins->codep++ & (bfd_vma) 0xff) << 24;
+ return true;
}
-static bfd_signed_vma
-get32s (instr_info *ins)
+static bool
+get32s (instr_info *ins, bfd_signed_vma *res)
{
- bfd_signed_vma x = 0;
+ if (!get32 (ins, res))
+ return false;
- FETCH_DATA (ins->info, ins->codep + 4);
- x = *ins->codep++ & (bfd_signed_vma) 0xff;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 8;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 16;
- x |= (*ins->codep++ & (bfd_signed_vma) 0xff) << 24;
+ *res = (*res ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
- x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31);
-
- return x;
+ return true;
}
-static int
-get16 (instr_info *ins)
+static bool
+get16 (instr_info *ins, int *res)
{
- int x = 0;
-
- FETCH_DATA (ins->info, ins->codep + 2);
- x = *ins->codep++ & 0xff;
- x |= (*ins->codep++ & 0xff) << 8;
- return x;
+ if (!fetch_code (ins->info, ins->codep + 2))
+ return false;
+ *res = *ins->codep++ & 0xff;
+ *res |= (*ins->codep++ & 0xff) << 8;
+ return true;
}
static void
-set_op (instr_info *ins, bfd_vma op, int riprel)
+set_op (instr_info *ins, bfd_vma op, bool riprel)
{
ins->op_index[ins->op_ad] = ins->op_ad;
if (ins->address_mode == mode_64bit)
- {
- ins->op_address[ins->op_ad] = op;
- ins->op_riprel[ins->op_ad] = riprel;
- }
- else
- {
- /* Mask to get a 32-bit address. */
- ins->op_address[ins->op_ad] = op & 0xffffffff;
- ins->op_riprel[ins->op_ad] = riprel & 0xffffffff;
- }
+ ins->op_address[ins->op_ad] = op;
+ else /* Mask to get a 32-bit address. */
+ ins->op_address[ins->op_ad] = op & 0xffffffff;
+ ins->op_riprel[ins->op_ad] = riprel;
}
-static void
+static bool
OP_REG (instr_info *ins, int code, int sizeflag)
{
const char *s;
{
case es_reg: case ss_reg: case cs_reg:
case ds_reg: case fs_reg: case gs_reg:
- oappend (ins, ins->names_seg[code - es_reg]);
- return;
+ oappend_register (ins, att_names_seg[code - es_reg]);
+ return true;
}
USED_REX (REX_B);
{
case ax_reg: case cx_reg: case dx_reg: case bx_reg:
case sp_reg: case bp_reg: case si_reg: case di_reg:
- s = ins->names16[code - ax_reg + add];
+ s = att_names16[code - ax_reg + add];
break;
case ah_reg: case ch_reg: case dh_reg: case bh_reg:
USED_REX (0);
/* Fall through. */
case al_reg: case cl_reg: case dl_reg: case bl_reg:
if (ins->rex)
- s = ins->names8rex[code - al_reg + add];
+ s = att_names8rex[code - al_reg + add];
else
- s = ins->names8[code - al_reg];
+ s = att_names8[code - al_reg];
break;
case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg:
case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg:
if (ins->address_mode == mode_64bit
&& ((sizeflag & DFLAG) || (ins->rex & REX_W)))
{
- s = ins->names64[code - rAX_reg + add];
+ s = att_names64[code - rAX_reg + add];
break;
}
code += eAX_reg - rAX_reg;
case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
USED_REX (REX_W);
if (ins->rex & REX_W)
- s = ins->names64[code - eAX_reg + add];
+ s = att_names64[code - eAX_reg + add];
else
{
if (sizeflag & DFLAG)
- s = ins->names32[code - eAX_reg + add];
+ s = att_names32[code - eAX_reg + add];
else
- s = ins->names16[code - eAX_reg + add];
+ s = att_names16[code - eAX_reg + add];
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
}
break;
default:
- s = INTERNAL_DISASSEMBLER_ERROR;
- break;
+ oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
+ return true;
}
- oappend (ins, s);
+ oappend_register (ins, s);
+ return true;
}
-static void
+static bool
OP_IMREG (instr_info *ins, int code, int sizeflag)
{
const char *s;
switch (code)
{
case indir_dx_reg:
- if (ins->intel_syntax)
- s = "dx";
- else
- s = "(%dx)";
+ if (!ins->intel_syntax)
+ {
+ oappend (ins, "(%dx)");
+ return true;
+ }
+ s = att_names16[dx_reg - ax_reg];
break;
case al_reg: case cl_reg:
- s = ins->names8[code - al_reg];
+ s = att_names8[code - al_reg];
break;
case eAX_reg:
USED_REX (REX_W);
if (ins->rex & REX_W)
{
- s = *ins->names64;
+ s = *att_names64;
break;
}
/* Fall through. */
case z_mode_ax_reg:
if ((ins->rex & REX_W) || (sizeflag & DFLAG))
- s = *ins->names32;
+ s = *att_names32;
else
- s = *ins->names16;
+ s = *att_names16;
if (!(ins->rex & REX_W))
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
break;
default:
- s = INTERNAL_DISASSEMBLER_ERROR;
- break;
+ oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
+ return true;
}
- oappend (ins, s);
+ oappend_register (ins, s);
+ return true;
}
-static void
+static bool
OP_I (instr_info *ins, int bytemode, int sizeflag)
{
bfd_signed_vma op;
switch (bytemode)
{
case b_mode:
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
op = *ins->codep++;
mask = 0xff;
break;
case v_mode:
USED_REX (REX_W);
if (ins->rex & REX_W)
- op = get32s (ins);
+ {
+ if (!get32s (ins, &op))
+ return false;
+ }
else
{
+ ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
if (sizeflag & DFLAG)
{
- op = get32 (ins);
+ case d_mode:
+ if (!get32 (ins, &op))
+ return false;
mask = 0xffffffff;
}
else
{
- op = get16 (ins);
+ int num;
+
+ case w_mode:
+ if (!get16 (ins, &num))
+ return false;
+ op = num;
mask = 0xfffff;
}
- ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
}
break;
- case d_mode:
- mask = 0xffffffff;
- op = get32 (ins);
- break;
- case w_mode:
- mask = 0xfffff;
- op = get16 (ins);
- break;
case const_1_mode:
if (ins->intel_syntax)
oappend (ins, "1");
- return;
+ return true;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
- return;
+ return true;
}
op &= mask;
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, op);
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ oappend_immediate (ins, op);
+ return true;
}
-static void
+static bool
OP_I64 (instr_info *ins, int bytemode, int sizeflag)
{
+ uint64_t op;
+
if (bytemode != v_mode || ins->address_mode != mode_64bit
|| !(ins->rex & REX_W))
- {
- OP_I (ins, bytemode, sizeflag);
- return;
- }
+ return OP_I (ins, bytemode, sizeflag);
USED_REX (REX_W);
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, get64 (ins));
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ if (!get64 (ins, &op))
+ return false;
+
+ oappend_immediate (ins, op);
+ return true;
}
-static void
+static bool
OP_sI (instr_info *ins, int bytemode, int sizeflag)
{
bfd_signed_vma op;
{
case b_mode:
case b_T_mode:
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
op = *ins->codep++;
if ((op & 0x80) != 0)
op -= 0x100;
break;
case v_mode:
/* The operand-size prefix is overridden by a REX prefix. */
- if ((sizeflag & DFLAG) || (ins->rex & REX_W))
- op = get32s (ins);
- else
- op = get16 (ins);
+ if (!(sizeflag & DFLAG) && !(ins->rex & REX_W))
+ {
+ int val;
+
+ if (!get16 (ins, &val))
+ return false;
+ op = val;
+ }
+ else if (!get32s (ins, &op))
+ return false;
break;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
- return;
+ return true;
}
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, op);
- oappend_maybe_intel (ins, ins->scratchbuf);
+ oappend_immediate (ins, op);
+ return true;
}
-static void
+static bool
OP_J (instr_info *ins, int bytemode, int sizeflag)
{
bfd_vma disp;
switch (bytemode)
{
case b_mode:
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
disp = *ins->codep++;
if ((disp & 0x80) != 0)
disp -= 0x100;
|| (ins->address_mode == mode_64bit
&& ((ins->isa64 == intel64 && bytemode != dqw_mode)
|| (ins->rex & REX_W))))
- disp = get32s (ins);
+ {
+ bfd_signed_vma val;
+
+ if (!get32s (ins, &val))
+ return false;
+ disp = val;
+ }
else
{
- disp = get16 (ins);
- if ((disp & 0x8000) != 0)
- disp -= 0x10000;
+ int val;
+
+ if (!get16 (ins, &val))
+ return false;
+ disp = val & 0x8000 ? val - 0x10000 : val;
/* In 16bit mode, address is wrapped around at 64k within
the same segment. Otherwise, a data16 prefix on a jump
instruction means that the pc is masked to 16 bits after
break;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
- return;
+ return true;
}
disp = ((ins->start_pc + (ins->codep - ins->start_codep) + disp) & mask)
| segment;
- set_op (ins, disp, 0);
- print_operand_value (ins, ins->scratchbuf, 1, disp);
- oappend (ins, ins->scratchbuf);
+ set_op (ins, disp, false);
+ print_operand_value (ins, disp, dis_style_text);
+ return true;
}
-static void
+static bool
OP_SEG (instr_info *ins, int bytemode, int sizeflag)
{
if (bytemode == w_mode)
- oappend (ins, ins->names_seg[ins->modrm.reg]);
- else
- OP_E (ins, ins->modrm.mod == 3 ? bytemode : w_mode, sizeflag);
+ {
+ oappend_register (ins, att_names_seg[ins->modrm.reg]);
+ return true;
+ }
+ return OP_E (ins, ins->modrm.mod == 3 ? bytemode : w_mode, sizeflag);
}
-static void
+static bool
OP_DIR (instr_info *ins, int dummy ATTRIBUTE_UNUSED, int sizeflag)
{
- int seg, offset;
+ int seg, offset, res;
+ char scratch[24];
if (sizeflag & DFLAG)
{
- offset = get32 (ins);
- seg = get16 (ins);
- }
- else
- {
- offset = get16 (ins);
- seg = get16 (ins);
+ bfd_signed_vma val;
+
+ if (!get32 (ins, &val))
+ return false;;
+ offset = val;
}
+ else if (!get16 (ins, &offset))
+ return false;
+ if (!get16 (ins, &seg))
+ return false;;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
- if (ins->intel_syntax)
- sprintf (ins->scratchbuf, "0x%x:0x%x", seg, offset);
- else
- sprintf (ins->scratchbuf, "$0x%x,$0x%x", seg, offset);
- oappend (ins, ins->scratchbuf);
+
+ res = snprintf (scratch, ARRAY_SIZE (scratch),
+ ins->intel_syntax ? "0x%x:0x%x" : "$0x%x,$0x%x",
+ seg, offset);
+ if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+ abort ();
+ oappend (ins, scratch);
+ return true;
}
-static void
+static bool
OP_OFF (instr_info *ins, int bytemode, int sizeflag)
{
bfd_vma off;
append_seg (ins);
if ((sizeflag & AFLAG) || ins->address_mode == mode_64bit)
- off = get32 (ins);
+ {
+ bfd_signed_vma val;
+
+ if (!get32 (ins, &val))
+ return false;
+ off = val;
+ }
else
- off = get16 (ins);
+ {
+ int val;
+
+ if (!get16 (ins, &val))
+ return false;
+ off = val;
+ }
if (ins->intel_syntax)
{
if (!ins->active_seg_prefix)
{
- oappend (ins, ins->names_seg[ds_reg - es_reg]);
+ oappend_register (ins, att_names_seg[ds_reg - es_reg]);
oappend (ins, ":");
}
}
- print_operand_value (ins, ins->scratchbuf, 1, off);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, off, dis_style_address_offset);
+ return true;
}
-static void
+static bool
OP_OFF64 (instr_info *ins, int bytemode, int sizeflag)
{
- bfd_vma off;
+ uint64_t off;
if (ins->address_mode != mode_64bit
|| (ins->prefixes & PREFIX_ADDR))
- {
- OP_OFF (ins, bytemode, sizeflag);
- return;
- }
+ return OP_OFF (ins, bytemode, sizeflag);
if (ins->intel_syntax && (sizeflag & SUFFIX_ALWAYS))
intel_operand_size (ins, bytemode, sizeflag);
append_seg (ins);
- off = get64 (ins);
+ if (!get64 (ins, &off))
+ return false;
if (ins->intel_syntax)
{
if (!ins->active_seg_prefix)
{
- oappend (ins, ins->names_seg[ds_reg - es_reg]);
+ oappend_register (ins, att_names_seg[ds_reg - es_reg]);
oappend (ins, ":");
}
}
- print_operand_value (ins, ins->scratchbuf, 1, off);
- oappend (ins, ins->scratchbuf);
+ print_operand_value (ins, off, dis_style_address_offset);
+ return true;
}
static void
if (ins->address_mode == mode_64bit)
{
if (!(sizeflag & AFLAG))
- s = ins->names32[code - eAX_reg];
+ s = att_names32[code - eAX_reg];
else
- s = ins->names64[code - eAX_reg];
+ s = att_names64[code - eAX_reg];
}
else if (sizeflag & AFLAG)
- s = ins->names32[code - eAX_reg];
+ s = att_names32[code - eAX_reg];
else
- s = ins->names16[code - eAX_reg];
- oappend (ins, s);
- *ins->obufp++ = ins->close_char;
- *ins->obufp = 0;
+ s = att_names16[code - eAX_reg];
+ oappend_register (ins, s);
+ oappend_char (ins, ins->close_char);
}
-static void
+static bool
OP_ESreg (instr_info *ins, int code, int sizeflag)
{
if (ins->intel_syntax)
intel_operand_size (ins, b_mode, sizeflag);
}
}
- oappend_maybe_intel (ins, "%es:");
+ oappend_register (ins, att_names_seg[0]);
+ oappend_char (ins, ':');
ptr_reg (ins, code, sizeflag);
+ return true;
}
-static void
+static bool
OP_DSreg (instr_info *ins, int code, int sizeflag)
{
if (ins->intel_syntax)
ins->active_seg_prefix = PREFIX_DS;
append_seg (ins);
ptr_reg (ins, code, sizeflag);
+ return true;
}
-static void
+static bool
OP_C (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- int add;
+ int add, res;
+ char scratch[8];
+
if (ins->rex & REX_R)
{
USED_REX (REX_R);
}
else
add = 0;
- sprintf (ins->scratchbuf, "%%cr%d", ins->modrm.reg + add);
- oappend_maybe_intel (ins, ins->scratchbuf);
+ res = snprintf (scratch, ARRAY_SIZE (scratch), "%%cr%d",
+ ins->modrm.reg + add);
+ if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+ abort ();
+ oappend_register (ins, scratch);
+ return true;
}
-static void
+static bool
OP_D (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- int add;
+ int add, res;
+ char scratch[8];
+
USED_REX (REX_R);
if (ins->rex & REX_R)
add = 8;
else
add = 0;
- if (ins->intel_syntax)
- sprintf (ins->scratchbuf, "dr%d", ins->modrm.reg + add);
- else
- sprintf (ins->scratchbuf, "%%db%d", ins->modrm.reg + add);
- oappend (ins, ins->scratchbuf);
+ res = snprintf (scratch, ARRAY_SIZE (scratch),
+ ins->intel_syntax ? "dr%d" : "%%db%d",
+ ins->modrm.reg + add);
+ if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+ abort ();
+ oappend (ins, scratch);
+ return true;
}
-static void
+static bool
OP_T (instr_info *ins, int dummy ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- sprintf (ins->scratchbuf, "%%tr%d", ins->modrm.reg);
- oappend_maybe_intel (ins, ins->scratchbuf);
+ int res;
+ char scratch[8];
+
+ res = snprintf (scratch, ARRAY_SIZE (scratch), "%%tr%d", ins->modrm.reg);
+ if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
+ abort ();
+ oappend_register (ins, scratch);
+ return true;
}
-static void
+static bool
OP_MMX (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
int reg = ins->modrm.reg;
- const char **names;
+ const char (*names)[8];
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
if (ins->prefixes & PREFIX_DATA)
{
- names = ins->names_xmm;
+ names = att_names_xmm;
USED_REX (REX_R);
if (ins->rex & REX_R)
reg += 8;
}
else
- names = ins->names_mm;
- oappend (ins, names[reg]);
+ names = att_names_mm;
+ oappend_register (ins, names[reg]);
+ return true;
}
static void
print_vector_reg (instr_info *ins, unsigned int reg, int bytemode)
{
- const char **names;
+ const char (*names)[8];
if (bytemode == xmmq_mode
|| bytemode == evex_half_bcst_xmmqh_mode
{
case 128:
case 256:
- names = ins->names_xmm;
+ names = att_names_xmm;
break;
case 512:
- names = ins->names_ymm;
+ names = att_names_ymm;
+ ins->evex_used |= EVEX_len_used;
break;
default:
abort ();
}
}
else if (bytemode == ymm_mode)
- names = ins->names_ymm;
+ names = att_names_ymm;
else if (bytemode == tmm_mode)
{
if (reg >= 8)
oappend (ins, "(bad)");
return;
}
- names = ins->names_tmm;
+ names = att_names_tmm;
}
else if (ins->need_vex
&& bytemode != xmm_mode
&& bytemode != d_mode
&& bytemode != q_mode)
{
+ ins->evex_used |= EVEX_len_used;
switch (ins->vex.length)
{
case 128:
- names = ins->names_xmm;
+ names = att_names_xmm;
break;
case 256:
if (ins->vex.w
|| bytemode != vex_vsib_q_w_dq_mode)
- names = ins->names_ymm;
+ names = att_names_ymm;
else
- names = ins->names_xmm;
+ names = att_names_xmm;
break;
case 512:
if (ins->vex.w
|| bytemode != vex_vsib_q_w_dq_mode)
- names = ins->names_zmm;
+ names = att_names_zmm;
else
- names = ins->names_ymm;
+ names = att_names_ymm;
break;
default:
abort ();
}
}
else
- names = ins->names_xmm;
- oappend (ins, names[reg]);
+ names = att_names_xmm;
+ oappend_register (ins, names[reg]);
}
-static void
+static bool
OP_XMM (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
{
unsigned int reg = ins->modrm.reg;
if (bytemode == tmm_mode)
ins->modrm.reg = reg;
else if (bytemode == scalar_mode)
- ins->vex.no_broadcast = 1;
+ ins->vex.no_broadcast = true;
print_vector_reg (ins, reg, bytemode);
+ return true;
}
-static void
+static bool
OP_EM (instr_info *ins, int bytemode, int sizeflag)
{
int reg;
- const char **names;
+ const char (*names)[8];
if (ins->modrm.mod != 3)
{
bytemode = (ins->prefixes & PREFIX_DATA) ? x_mode : q_mode;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
}
- OP_E (ins, bytemode, sizeflag);
- return;
+ return OP_E (ins, bytemode, sizeflag);
}
if ((sizeflag & SUFFIX_ALWAYS) && bytemode == v_swap_mode)
reg = ins->modrm.rm;
if (ins->prefixes & PREFIX_DATA)
{
- names = ins->names_xmm;
+ names = att_names_xmm;
USED_REX (REX_B);
if (ins->rex & REX_B)
reg += 8;
}
else
- names = ins->names_mm;
- oappend (ins, names[reg]);
+ names = att_names_mm;
+ oappend_register (ins, names[reg]);
+ return true;
}
/* cvt* are the only instructions in sse2 which have
in their opcode. 0x66 was originally used to differentiate
between SSE and MMX instruction(operands). So we have to handle the
cvt* separately using OP_EMC and OP_MXC */
-static void
+static bool
OP_EMC (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 3)
bytemode = (ins->prefixes & PREFIX_DATA) ? x_mode : q_mode;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
}
- OP_E (ins, bytemode, sizeflag);
- return;
+ return OP_E (ins, bytemode, sizeflag);
}
/* Skip mod/rm byte. */
MODRM_CHECK;
ins->codep++;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
- oappend (ins, ins->names_mm[ins->modrm.rm]);
+ oappend_register (ins, att_names_mm[ins->modrm.rm]);
+ return true;
}
-static void
+static bool
OP_MXC (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
- oappend (ins, ins->names_mm[ins->modrm.reg]);
+ oappend_register (ins, att_names_mm[ins->modrm.reg]);
+ return true;
}
-static void
+static bool
OP_EX (instr_info *ins, int bytemode, int sizeflag)
{
int reg;
bytemode = ins->vex.w ? q_mode : d_mode;
if (ins->modrm.mod != 3)
- {
- OP_E_memory (ins, bytemode, sizeflag);
- return;
- }
+ return OP_E_memory (ins, bytemode, sizeflag);
reg = ins->modrm.rm;
USED_REX (REX_B);
ins->modrm.rm = reg;
print_vector_reg (ins, reg, bytemode);
+ return true;
}
-static void
+static bool
OP_MS (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod == 3)
- OP_EM (ins, bytemode, sizeflag);
- else
- BadOp (ins);
+ return OP_EM (ins, bytemode, sizeflag);
+ return BadOp (ins);
}
-static void
+static bool
OP_XS (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod == 3)
- OP_EX (ins, bytemode, sizeflag);
- else
- BadOp (ins);
+ return OP_EX (ins, bytemode, sizeflag);
+ return BadOp (ins);
}
-static void
+static bool
OP_M (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod == 3)
/* bad bound,lea,lds,les,lfs,lgs,lss,cmpxchg8b,vmptrst modrm */
- BadOp (ins);
- else
- OP_E (ins, bytemode, sizeflag);
+ return BadOp (ins);
+ return OP_E (ins, bytemode, sizeflag);
}
-static void
+static bool
OP_0f07 (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 3 || ins->modrm.rm != 0)
- BadOp (ins);
- else
- OP_E (ins, bytemode, sizeflag);
+ return BadOp (ins);
+ return OP_E (ins, bytemode, sizeflag);
}
/* NOP is an alias of "xchg %ax,%ax" in 16bit mode, "xchg %eax,%eax" in
32bit mode and "xchg %rax,%rax" in 64bit mode. */
-static void
-NOP_Fixup1 (instr_info *ins, int bytemode, int sizeflag)
-{
- if ((ins->prefixes & PREFIX_DATA) != 0
- || (ins->rex != 0
- && ins->rex != 0x48
- && ins->address_mode == mode_64bit))
- OP_REG (ins, bytemode, sizeflag);
- else
- strcpy (ins->obuf, "nop");
-}
-
-static void
-NOP_Fixup2 (instr_info *ins, int bytemode, int sizeflag)
+static bool
+NOP_Fixup (instr_info *ins, int opnd, int sizeflag)
{
- if ((ins->prefixes & PREFIX_DATA) != 0
- || (ins->rex != 0
- && ins->rex != 0x48
- && ins->address_mode == mode_64bit))
- OP_IMREG (ins, bytemode, sizeflag);
+ if ((ins->prefixes & PREFIX_DATA) == 0 && (ins->rex & REX_B) == 0)
+ {
+ ins->mnemonicendp = stpcpy (ins->obuf, "nop");
+ return true;
+ }
+ if (opnd == 0)
+ return OP_REG (ins, eAX_reg, sizeflag);
+ return OP_IMREG (ins, eAX_reg, sizeflag);
}
static const char *const Suffix3DNow[] = {
/* FC */ NULL, NULL, NULL, NULL,
};
-static void
+static bool
OP_3DNowSuffix (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
const char *mnemonic;
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
/* AMD 3DNow! instructions are specified by an opcode suffix in the
place where an 8-bit immediate would normally go. ie. the last
byte of the instruction. */
ins->obufp = ins->mnemonicendp;
mnemonic = Suffix3DNow[*ins->codep++ & 0xff];
if (mnemonic)
- oappend (ins, mnemonic);
+ ins->obufp = stpcpy (ins->obufp, mnemonic);
else
{
/* Since a variable sized ins->modrm/ins->sib chunk is between the start
BadOp (ins);
}
ins->mnemonicendp = ins->obufp;
+ return true;
}
static const struct op simd_cmp_op[] =
{ STRING_COMMA_LEN ("true_us") },
};
-static void
+static bool
CMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
unsigned int cmp_type;
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
cmp_type = *ins->codep++ & 0xff;
if (cmp_type < ARRAY_SIZE (simd_cmp_op))
{
else
{
/* We have a reserved extension byte. Output it directly. */
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ oappend_immediate (ins, cmp_type);
}
+ return true;
}
-static void
+static bool
OP_Mwait (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
{
/* mwait %eax,%ecx / mwaitx %eax,%ecx,%ebx */
if (!ins->intel_syntax)
{
- strcpy (ins->op_out[0], ins->names32[0]);
- strcpy (ins->op_out[1], ins->names32[1]);
+ strcpy (ins->op_out[0], att_names32[0] + ins->intel_syntax);
+ strcpy (ins->op_out[1], att_names32[1] + ins->intel_syntax);
if (bytemode == eBX_reg)
- strcpy (ins->op_out[2], ins->names32[3]);
- ins->two_source_ops = 1;
+ strcpy (ins->op_out[2], att_names32[3] + ins->intel_syntax);
+ ins->two_source_ops = true;
}
/* Skip mod/rm byte. */
MODRM_CHECK;
ins->codep++;
+ return true;
}
-static void
+static bool
OP_Monitor (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
/* monitor %{e,r,}ax,%ecx,%edx" */
if (!ins->intel_syntax)
{
- const char **names = (ins->address_mode == mode_64bit
- ? ins->names64 : ins->names32);
+ const char (*names)[8] = (ins->address_mode == mode_64bit
+ ? att_names64 : att_names32);
if (ins->prefixes & PREFIX_ADDR)
{
/* Remove "addr16/addr32". */
ins->all_prefixes[ins->last_addr_prefix] = 0;
names = (ins->address_mode != mode_32bit
- ? ins->names32 : ins->names16);
+ ? att_names32 : att_names16);
ins->used_prefixes |= PREFIX_ADDR;
}
else if (ins->address_mode == mode_16bit)
- names = ins->names16;
- strcpy (ins->op_out[0], names[0]);
- strcpy (ins->op_out[1], ins->names32[1]);
- strcpy (ins->op_out[2], ins->names32[2]);
- ins->two_source_ops = 1;
+ names = att_names16;
+ strcpy (ins->op_out[0], names[0] + ins->intel_syntax);
+ strcpy (ins->op_out[1], att_names32[1] + ins->intel_syntax);
+ strcpy (ins->op_out[2], att_names32[2] + ins->intel_syntax);
+ ins->two_source_ops = true;
}
/* Skip mod/rm byte. */
MODRM_CHECK;
ins->codep++;
+ return true;
}
-static void
+static bool
BadOp (instr_info *ins)
{
/* Throw away prefixes and 1st. opcode byte. */
ins->codep = ins->insn_codep + 1;
- oappend (ins, "(bad)");
+ ins->obufp = stpcpy (ins->obufp, "(bad)");
+ return true;
}
-static void
+static bool
REP_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
/* The 0xf3 prefix should be displayed as "rep" for ins, outs, movs,
case al_reg:
case eAX_reg:
case indir_dx_reg:
- OP_IMREG (ins, bytemode, sizeflag);
- break;
+ return OP_IMREG (ins, bytemode, sizeflag);
case eDI_reg:
- OP_ESreg (ins, bytemode, sizeflag);
- break;
+ return OP_ESreg (ins, bytemode, sizeflag);
case eSI_reg:
- OP_DSreg (ins, bytemode, sizeflag);
- break;
+ return OP_DSreg (ins, bytemode, sizeflag);
default:
abort ();
break;
}
+ return true;
}
-static void
+static bool
SEP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
if (ins->isa64 != amd64)
- return;
+ return true;
ins->obufp = ins->obuf;
BadOp (ins);
ins->mnemonicendp = ins->obufp;
++ins->codep;
+ return true;
}
/* For BND-prefixed instructions 0xF2 prefix should be displayed as
"bnd". */
-static void
+static bool
BND_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
if (ins->prefixes & PREFIX_REPNZ)
ins->all_prefixes[ins->last_repnz_prefix] = BND_PREFIX;
+ return true;
}
/* For NOTRACK-prefixed instructions, 0x3E prefix should be displayed as
"notrack". */
-static void
+static bool
NOTRACK_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
ins->active_seg_prefix = 0;
ins->all_prefixes[ins->last_seg_prefix] = NOTRACK_PREFIX;
}
+ return true;
}
/* Similar to OP_E. But the 0xf2/0xf3 ins->prefixes should be displayed as
"xacquire"/"xrelease" for memory operand if there is a LOCK prefix.
*/
-static void
+static bool
HLE_Fixup1 (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 3
ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
}
- OP_E (ins, bytemode, sizeflag);
+ return OP_E (ins, bytemode, sizeflag);
}
/* Similar to OP_E. But the 0xf2/0xf3 ins->prefixes should be displayed as
"xacquire"/"xrelease" for memory operand. No check for LOCK prefix.
*/
-static void
+static bool
HLE_Fixup2 (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 3)
ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
}
- OP_E (ins, bytemode, sizeflag);
+ return OP_E (ins, bytemode, sizeflag);
}
/* Similar to OP_E. But the 0xf3 prefixes should be displayed as
"xrelease" for memory operand. No check for LOCK prefix. */
-static void
+static bool
HLE_Fixup3 (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 3
&& (ins->prefixes & PREFIX_REPZ) != 0)
ins->all_prefixes[ins->last_repz_prefix] = XRELEASE_PREFIX;
- OP_E (ins, bytemode, sizeflag);
+ return OP_E (ins, bytemode, sizeflag);
}
-static void
+static bool
CMPXCHG8B_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
USED_REX (REX_W);
ins->all_prefixes[ins->last_repnz_prefix] = XACQUIRE_PREFIX;
}
- OP_M (ins, bytemode, sizeflag);
+ return OP_M (ins, bytemode, sizeflag);
}
-static void
+static bool
XMM_Fixup (instr_info *ins, int reg, int sizeflag ATTRIBUTE_UNUSED)
{
- const char **names;
+ const char (*names)[8] = att_names_xmm;
if (ins->need_vex)
{
switch (ins->vex.length)
{
case 128:
- names = ins->names_xmm;
break;
case 256:
- names = ins->names_ymm;
+ names = att_names_ymm;
break;
default:
abort ();
}
}
- else
- names = ins->names_xmm;
- oappend (ins, names[reg]);
+ oappend_register (ins, names[reg]);
+ return true;
}
-static void
+static bool
FXSAVE_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
/* Add proper suffix to "fxsave" and "fxrstor". */
*p = '\0';
ins->mnemonicendp = p;
}
- OP_M (ins, bytemode, sizeflag);
+ return OP_M (ins, bytemode, sizeflag);
}
/* Display the destination register operand for instructions with
VEX. */
-static void
+static bool
OP_VEX (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
{
int reg, modrm_reg, sib_index = -1;
- const char **names;
+ const char (*names)[8];
if (!ins->need_vex)
abort ();
if (ins->vex.evex && !ins->vex.v)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
reg &= 7;
switch (bytemode)
{
case scalar_mode:
- oappend (ins, ins->names_xmm[reg]);
- return;
+ oappend_register (ins, att_names_xmm[reg]);
+ return true;
case vex_vsib_d_w_dq_mode:
case vex_vsib_q_w_dq_mode:
if (ins->vex.length == 128
|| (bytemode != vex_vsib_d_w_dq_mode
&& !ins->vex.w))
- oappend (ins, ins->names_xmm[reg]);
+ oappend_register (ins, att_names_xmm[reg]);
else
- oappend (ins, ins->names_ymm[reg]);
+ oappend_register (ins, att_names_ymm[reg]);
/* All 3 XMM/YMM registers must be distinct. */
modrm_reg = ins->modrm.reg;
if (ins->rex & REX_R)
modrm_reg += 8;
- if (ins->modrm.rm == 4)
+ if (ins->has_sib && ins->modrm.rm == 4)
{
sib_index = ins->sib.index;
if (ins->rex & REX_X)
if (sib_index == modrm_reg || sib_index == reg)
strcat (ins->op_out[1], "/(bad)");
- return;
+ return true;
case tmm_mode:
/* All 3 TMM registers must be distinct. */
/* This must be the 3rd operand. */
if (ins->obufp != ins->op_out[2])
abort ();
- oappend (ins, ins->names_tmm[reg]);
+ oappend_register (ins, att_names_tmm[reg]);
if (reg == ins->modrm.reg || reg == ins->modrm.rm)
strcpy (ins->obufp, "/(bad)");
}
strcat (ins->op_out[1], "/(bad)");
}
- return;
+ return true;
}
switch (ins->vex.length)
switch (bytemode)
{
case x_mode:
- names = ins->names_xmm;
+ names = att_names_xmm;
+ ins->evex_used |= EVEX_len_used;
break;
case dq_mode:
if (ins->rex & REX_W)
- names = ins->names64;
+ names = att_names64;
else
- names = ins->names32;
+ names = att_names32;
break;
case mask_bd_mode:
case mask_mode:
if (reg > 0x7)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
- names = ins->names_mask;
+ names = att_names_mask;
break;
default:
abort ();
- return;
+ return true;
}
break;
case 256:
switch (bytemode)
{
case x_mode:
- names = ins->names_ymm;
+ names = att_names_ymm;
+ ins->evex_used |= EVEX_len_used;
break;
case mask_bd_mode:
case mask_mode:
- if (reg > 0x7)
+ if (reg <= 0x7)
{
- oappend (ins, "(bad)");
- return;
+ names = att_names_mask;
+ break;
}
- names = ins->names_mask;
- break;
+ /* Fall through. */
default:
/* See PR binutils/20893 for a reproducer. */
oappend (ins, "(bad)");
- return;
+ return true;
}
break;
case 512:
- names = ins->names_zmm;
+ names = att_names_zmm;
+ ins->evex_used |= EVEX_len_used;
break;
default:
abort ();
break;
}
- oappend (ins, names[reg]);
+ oappend_register (ins, names[reg]);
+ return true;
}
-static void
+static bool
OP_VexR (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod == 3)
- OP_VEX (ins, bytemode, sizeflag);
+ return OP_VEX (ins, bytemode, sizeflag);
+ return true;
}
-static void
+static bool
OP_VexW (instr_info *ins, int bytemode, int sizeflag)
{
OP_VEX (ins, bytemode, sizeflag);
if (ins->vex.w)
{
/* Swap 2nd and 3rd operands. */
- strcpy (ins->scratchbuf, ins->op_out[2]);
- strcpy (ins->op_out[2], ins->op_out[1]);
- strcpy (ins->op_out[1], ins->scratchbuf);
+ char *tmp = ins->op_out[2];
+
+ ins->op_out[2] = ins->op_out[1];
+ ins->op_out[1] = tmp;
}
+ return true;
}
-static void
+static bool
OP_REG_VexI4 (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
{
int reg;
- const char **names = ins->names_xmm;
+ const char (*names)[8] = att_names_xmm;
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
reg = *ins->codep++;
if (bytemode != x_mode && bytemode != scalar_mode)
reg &= 7;
if (bytemode == x_mode && ins->vex.length == 256)
- names = ins->names_ymm;
+ names = att_names_ymm;
- oappend (ins, names[reg]);
+ oappend_register (ins, names[reg]);
if (ins->vex.w)
{
/* Swap 3rd and 4th operands. */
- strcpy (ins->scratchbuf, ins->op_out[3]);
- strcpy (ins->op_out[3], ins->op_out[2]);
- strcpy (ins->op_out[2], ins->scratchbuf);
+ char *tmp = ins->op_out[3];
+
+ ins->op_out[3] = ins->op_out[2];
+ ins->op_out[2] = tmp;
}
+ return true;
}
-static void
+static bool
OP_VexI4 (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, ins->codep[-1] & 0xf);
- oappend_maybe_intel (ins, ins->scratchbuf);
+ oappend_immediate (ins, ins->codep[-1] & 0xf);
+ return true;
}
-static void
+static bool
VPCMP_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
if (!ins->vex.evex)
abort ();
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
cmp_type = *ins->codep++ & 0xff;
/* There are aliases for immediates 0, 1, 2, 4, 5, 6.
If it's the case, print suffix, otherwise - print the immediate. */
else
{
/* We have a reserved extension byte. Output it directly. */
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ oappend_immediate (ins, cmp_type);
}
+ return true;
}
static const struct op xop_cmp_op[] =
{ STRING_COMMA_LEN ("true") }
};
-static void
+static bool
VPCOM_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
unsigned int cmp_type;
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
cmp_type = *ins->codep++ & 0xff;
if (cmp_type < ARRAY_SIZE (xop_cmp_op))
{
else
{
/* We have a reserved extension byte. Output it directly. */
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, cmp_type);
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ oappend_immediate (ins, cmp_type);
}
+ return true;
}
static const struct op pclmul_op[] =
{ STRING_COMMA_LEN ("hqh") }
};
-static void
+static bool
PCLMUL_Fixup (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
unsigned int pclmul_type;
- FETCH_DATA (ins->info, ins->codep + 1);
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
pclmul_type = *ins->codep++ & 0xff;
switch (pclmul_type)
{
else
{
/* We have a reserved extension byte. Output it directly. */
- ins->scratchbuf[0] = '$';
- print_operand_value (ins, ins->scratchbuf + 1, 1, pclmul_type);
- oappend_maybe_intel (ins, ins->scratchbuf);
- ins->scratchbuf[0] = '\0';
+ oappend_immediate (ins, pclmul_type);
}
+ return true;
}
-static void
+static bool
MOVSXD_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
/* Add proper suffix to "movsxd". */
ins->mnemonicendp = p;
*p = '\0';
- OP_E (ins, bytemode, sizeflag);
+ return OP_E (ins, bytemode, sizeflag);
}
-static void
+static bool
DistinctDest_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
unsigned int reg = ins->vex.register_specifier;
&& modrm_reg == modrm_rm))
{
oappend (ins, "(bad)");
+ return true;
}
- else
- OP_XMM (ins, bytemode, sizeflag);
+ return OP_XMM (ins, bytemode, sizeflag);
}
-static void
+static bool
OP_Rounding (instr_info *ins, int bytemode, int sizeflag ATTRIBUTE_UNUSED)
{
if (ins->modrm.mod != 3 || !ins->vex.b)
- return;
+ return true;
switch (bytemode)
{
case evex_rounding_64_mode:
if (ins->address_mode != mode_64bit || !ins->vex.w)
- return;
+ return true;
/* Fall through. */
case evex_rounding_mode:
ins->evex_used |= EVEX_b_used;
abort ();
}
oappend (ins, "sae}");
+ return true;
+}
+
+static bool
+PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
+{
+ if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
+ {
+ if (ins->intel_syntax)
+ {
+ ins->mnemonicendp = stpcpy (ins->obuf, "nop ");
+ }
+ else
+ {
+ USED_REX (REX_W);
+ if (ins->rex & REX_W)
+ ins->mnemonicendp = stpcpy (ins->obuf, "nopq ");
+ else
+ {
+ if (sizeflag & DFLAG)
+ ins->mnemonicendp = stpcpy (ins->obuf, "nopl ");
+ else
+ ins->mnemonicendp = stpcpy (ins->obuf, "nopw ");
+ ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
+ }
+ }
+ bytemode = v_mode;
+ }
+
+ return OP_M (ins, bytemode, sizeflag);
}