/* 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 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 OP_E_memory (instr_info *, int, int);
-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 bool get32s (instr_info *, bfd_signed_vma *);
+static bool get16 (instr_info *, int *);
static void set_op (instr_info *, bfd_vma, bool);
-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_Fixup (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 void PREFETCHI_Fixup (instr_info *, int, int);
+
+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. */
bfd_byte the_buffer[MAX_MNEM_SIZE];
bfd_vma insn_start;
int orig_sizeflag;
- OPCODES_SIGJMP_BUF bailout;
};
enum address_mode
#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 }
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_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,
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_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,
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_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_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_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,
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;
/* 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 },
need to update onebyte_has_modrm or twobyte_has_modrm. */
#define MODRM_CHECK if (!ins->need_modrm) abort ()
-static const char *const intel_index16[] = {
+static const char intel_index16[][6] = {
"bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
};
-static const char *const 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 *const 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 *const 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 *const att_names8[] = {
+static const char att_names8[][8] = {
"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
};
-static const char *const 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 *const 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 *const att_index16[] = {
+static const char att_index16[][8] = {
"%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
};
-static const char *const att_names_mm[] = {
+static const char att_names_mm[][8] = {
"%mm0", "%mm1", "%mm2", "%mm3",
"%mm4", "%mm5", "%mm6", "%mm7"
};
-static const char *const att_names_bnd[] = {
+static const char att_names_bnd[][8] = {
"%bnd0", "%bnd1", "%bnd2", "%bnd3"
};
-static const char *const 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 *const 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 *const 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 *const att_names_tmm[] = {
+static const char att_names_tmm[][8] = {
"%tmm0", "%tmm1", "%tmm2", "%tmm3",
"%tmm4", "%tmm5", "%tmm6", "%tmm7"
};
-static const char *const att_names_mask[] = {
+static const char att_names_mask[][8] = {
"%k0", "%k1", "%k2", "%k3", "%k4", "%k5", "%k6", "%k7"
};
{ 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_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 },
{ 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_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 },
{ 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 */
- { Bad_Opcode },
- { Bad_Opcode },
+ { VEX_W_TABLE (VEX_W_0F38B0) },
+ { VEX_W_TABLE (VEX_W_0F38B1) },
{ Bad_Opcode },
{ Bad_Opcode },
{ VEX_W_TABLE (VEX_W_0F38B4) },
{ "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 },
{ "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_W_0F3850 */
- { "%XVvpdpbusd", { XM, Vex, EXx }, PREFIX_DATA },
+ { PREFIX_TABLE (PREFIX_VEX_0F3850_W_0) },
},
{
/* VEX_W_0F3851 */
- { "%XVvpdpbusds", { XM, Vex, EXx }, PREFIX_DATA },
+ { PREFIX_TABLE (PREFIX_VEX_0F3851_W_0) },
},
{
/* VEX_W_0F3852 */
/* 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 */
{ "%XEvpbroadcastb", { XM, EXb }, PREFIX_DATA },
/* VEX_W_0F3879 */
{ "%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 },
{ "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 },
{ 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 BND_PREFIX 0x04
#define NOTRACK_PREFIX 0x05
-static int
+static enum {
+ ckp_okay,
+ ckp_bogus,
+ ckp_fetch_error,
+}
ckprefix (instr_info *ins)
{
int newrex, i, length;
/* 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] =
{
/* 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". */
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))
{
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
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:
ins->two_source_ops = false;
/* EVEX prefix. */
ins->vex.evex = true;
- FETCH_DATA (ins->info, ins->codep + 4);
+ 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;
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;
}
else
ins->has_sib = false;
+
+ return true;
}
/* Like oappend (below), but S is a string starting with '%'. In
used in the next fprintf_styled_func call. */
static void ATTRIBUTE_PRINTF_3
-i386_dis_printf (instr_info *ins, enum disassembler_style style,
+i386_dis_printf (const instr_info *ins, enum disassembler_style style,
const char *fmt, ...)
{
va_list ap;
{
const struct dis386 *dp;
int i;
+ int ret;
char *op_txt[MAX_OPERANDS];
int needcomma;
bool intel_swap_2_3;
ins.op_out[i] = op_out[i];
}
- if (OPCODES_SIGSETJMP (priv.bailout) != 0)
- {
- /* 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)
- {
- const char *name = NULL;
-
- 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
- {
- /* 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, "0x%x",
- (unsigned int) priv.the_buffer[0]);
- }
-
- return 1;
- }
-
- return -1;
- }
-
sizeflag = priv.orig_sizeflag;
- if (!ckprefix (&ins) || ins.rex_used)
+ switch (ckprefix (&ins))
{
+ case ckp_okay:
+ break;
+
+ case ckp_bogus:
/* Too many prefixes or unused REX prefixes. */
for (i = 0;
i < (int) ARRAY_SIZE (ins.all_prefixes) && ins.all_prefixes[i];
i386_dis_printf (&ins, dis_style_mnemonic, "%s%s",
(i == 0 ? "" : " "),
prefix_name (&ins, ins.all_prefixes[i], sizeflag));
- return i;
+ ret = i;
+ goto out;
+
+ case ckp_fetch_error:
+ goto fetch_error_out;
}
ins.insn_codep = ins.codep;
- FETCH_DATA (info, ins.codep + 1);
+ if (!fetch_code (info, ins.codep + 1))
+ {
+ fetch_error_out:
+ ret = fetch_error (&ins);
+ goto out;
+ }
+
ins.two_source_ops = (*ins.codep == 0x62) || (*ins.codep == 0xc8);
if (((ins.prefixes & PREFIX_FWAIT)
i386_dis_printf (&ins, dis_style_mnemonic, "%s ",
prefix_name (&ins, ins.all_prefixes[i], sizeflag));
i386_dis_printf (&ins, dis_style_mnemonic, "fwait");
- return i + 1;
+ ret = i + 1;
+ goto out;
}
if (*ins.codep == 0x0f)
unsigned char threebyte;
ins.codep++;
- FETCH_DATA (info, ins.codep + 1);
+ 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];
sizeflag ^= DFLAG;
ins.end_codep = ins.codep;
- if (ins.need_modrm)
- {
- FETCH_DATA (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 (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 == &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);
+ 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 (ins.need_vex && ins.vex.register_specifier != 0)
{
i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ 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)
{
i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
switch (dp->prefix_requirement)
if (ins.need_vex ? !ins.vex.prefix : !(ins.prefixes & PREFIX_DATA))
{
i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
ins.used_prefixes |= PREFIX_DATA;
/* Fall through. */
&& !ins.vex.w != !(ins.used_prefixes & PREFIX_DATA)))
{
i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
break;
if ((ins.codep - ins.start_codep) > MAX_CODE_LENGTH)
{
i386_dis_printf (&ins, dis_style_text, "(bad)");
- return MAX_CODE_LENGTH;
+ ret = MAX_CODE_LENGTH;
+ goto out;
}
/* Calculate the number of operands this instruction has. */
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
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;
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;
}
-static void
+static bool
OP_ST (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
oappend_register (ins, "%st");
+ return true;
}
-static void
+static bool
OP_STi (instr_info *ins, int bytemode ATTRIBUTE_UNUSED,
int sizeflag ATTRIBUTE_UNUSED)
{
if (res < 0 || (size_t) res >= ARRAY_SIZE (scratch))
abort ();
oappend_register (ins, scratch);
+ return true;
}
/* Capital letters in template are macros. */
switch (ins->active_seg_prefix)
{
case PREFIX_CS:
- oappend_register (ins, "%cs");
+ oappend_register (ins, att_names_seg[1]);
break;
case PREFIX_DS:
- oappend_register (ins, "%ds");
+ oappend_register (ins, att_names_seg[3]);
break;
case PREFIX_SS:
- oappend_register (ins, "%ss");
+ oappend_register (ins, att_names_seg[2]);
break;
case PREFIX_ES:
- oappend_register (ins, "%es");
+ oappend_register (ins, att_names_seg[0]);
break;
case PREFIX_FS:
- oappend_register (ins, "%fs");
+ oappend_register (ins, att_names_seg[4]);
break;
case PREFIX_GS:
- oappend_register (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
/* Put DISP in BUF as signed hex number. */
static void
-print_displacement (instr_info *ins, bfd_vma disp)
+print_displacement (instr_info *ins, bfd_signed_vma val)
{
- bfd_signed_vma val = disp;
char tmp[30];
if (val < 0)
{
oappend_char_with_style (ins, '-', dis_style_address_offset);
- val = -disp;
+ val = (bfd_vma) 0 - val;
/* Check for possible overflow. */
if (val < 0)
print_register (instr_info *ins, unsigned int reg, unsigned int rexmask,
int bytemode, int sizeflag)
{
- const char *const *names;
+ const char (*names)[8];
USED_REX (rexmask);
if (ins->rex & rexmask)
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 havebase;
int needindex;
|| bytemode == bnd_mode
|| bytemode == bnd_swap_mode);
bool check_gather = false;
- const char *const *indexes = NULL;
+ const char (*indexes)[8] = NULL;
havebase = 1;
base = ins->modrm.rm;
|| bytemode == vex_sibmem_mode)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
}
rbase = base + add;
havebase = 0;
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;
}
if (ins->intel_syntax
&& (disp || ins->modrm.mod != 0 || base == 5))
{
- if (!havedisp || (bfd_signed_vma) disp >= 0)
+ if (!havedisp || disp >= 0)
oappend_char (ins, '+');
- else if (ins->modrm.mod != 1 && disp != -disp)
- {
- oappend_char (ins, '-');
- disp = -disp;
- }
-
if (havedisp)
print_displacement (ins, disp);
else
|| 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)
{
oappend_char (ins, ins->open_char);
- oappend (ins, (ins->intel_syntax ? intel_index16
- : att_index16)[ins->modrm.rm]);
+ 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)
+ if (disp >= 0)
oappend_char (ins, '+');
- else if (ins->modrm.mod != 1)
- {
- oappend_char (ins, '-');
- disp = -disp;
- }
-
print_displacement (ins, disp);
}
{
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
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_vma x = 0;
-
- FETCH_DATA (ins->info, ins->codep + 4);
- x = *ins->codep++ & (bfd_vma) 0xff;
- x |= (*ins->codep++ & (bfd_vma) 0xff) << 8;
- x |= (*ins->codep++ & (bfd_vma) 0xff) << 16;
- x |= (*ins->codep++ & (bfd_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_vma x = 0;
+ if (!get32 (ins, res))
+ return false;
- FETCH_DATA (ins->info, ins->codep + 4);
- x = *ins->codep++ & (bfd_vma) 0xff;
- x |= (*ins->codep++ & (bfd_vma) 0xff) << 8;
- x |= (*ins->codep++ & (bfd_vma) 0xff) << 16;
- x |= (*ins->codep++ & (bfd_vma) 0xff) << 24;
+ *res = (*res ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
- x = (x ^ ((bfd_vma) 1 << 31)) - ((bfd_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
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_register (ins, att_names_seg[code - es_reg]);
- return;
+ return true;
}
USED_REX (REX_B);
break;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
- return;
+ return true;
}
oappend_register (ins, s);
+ return true;
}
-static void
+static bool
OP_IMREG (instr_info *ins, int code, int sizeflag)
{
const char *s;
if (!ins->intel_syntax)
{
oappend (ins, "(%dx)");
- return;
+ return true;
}
s = att_names16[dx_reg - ax_reg];
break;
break;
default:
oappend (ins, INTERNAL_DISASSEMBLER_ERROR);
- return;
+ return true;
}
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;
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);
- oappend_immediate (ins, get64 (ins));
+ 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;
}
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, 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_register (ins, att_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, res;
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);
res = snprintf (scratch, ARRAY_SIZE (scratch),
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)
{
}
}
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)
{
}
}
print_operand_value (ins, off, dis_style_address_offset);
+ return true;
}
static void
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_register (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)
{
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)
{
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)
{
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 *const *names;
+ const char (*names)[8];
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
if (ins->prefixes & PREFIX_DATA)
else
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 *const *names;
+ const char (*names)[8];
if (bytemode == xmmq_mode
|| bytemode == evex_half_bcst_xmmqh_mode
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;
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 *const *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)
else
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. */
ins->codep++;
ins->used_prefixes |= (ins->prefixes & PREFIX_DATA);
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_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
+static bool
NOP_Fixup (instr_info *ins, int opnd, int sizeflag)
{
if ((ins->prefixes & PREFIX_DATA) == 0 && (ins->rex & REX_B) == 0)
- ins->mnemonicendp = stpcpy (ins->obuf, "nop");
- else if (opnd == 0)
- OP_REG (ins, eAX_reg, sizeflag);
- else
- OP_IMREG (ins, eAX_reg, sizeflag);
+ {
+ 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. */
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))
{
/* We have a reserved extension byte. Output it directly. */
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 */
/* 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 *const *names = (ins->address_mode == mode_64bit
- ? att_names64 : att_names32);
+ const char (*names)[8] = (ins->address_mode == mode_64bit
+ ? att_names64 : att_names32);
if (ins->prefixes & PREFIX_ADDR)
{
/* 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;
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 *const *names = att_names_xmm;
+ const char (*names)[8] = att_names_xmm;
if (ins->need_vex)
{
}
}
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 *const *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;
{
case scalar_mode:
oappend_register (ins, att_names_xmm[reg]);
- return;
+ return true;
case vex_vsib_d_w_dq_mode:
case vex_vsib_q_w_dq_mode:
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. */
strcat (ins->op_out[1], "/(bad)");
}
- return;
+ return true;
}
switch (ins->vex.length)
if (reg > 0x7)
{
oappend (ins, "(bad)");
- return;
+ return true;
}
names = att_names_mask;
break;
default:
abort ();
- return;
+ return true;
}
break;
case 256:
break;
case mask_bd_mode:
case mask_mode:
- if (reg > 0x7)
+ if (reg <= 0x7)
{
- oappend (ins, "(bad)");
- return;
+ names = att_names_mask;
+ break;
}
- names = att_names_mask;
- break;
+ /* Fall through. */
default:
/* See PR binutils/20893 for a reproducer. */
oappend (ins, "(bad)");
- return;
+ return true;
}
break;
case 512:
break;
}
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);
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 *const *names = att_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)
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)
{
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. */
/* We have a reserved extension byte. Output it directly. */
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))
{
/* We have a reserved extension byte. Output it directly. */
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)
{
/* We have a reserved extension byte. Output it directly. */
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 void
+static bool
PREFETCHI_Fixup (instr_info *ins, int bytemode, int sizeflag)
{
if (ins->modrm.mod != 0 || ins->modrm.rm != 5)
bytemode = v_mode;
}
- OP_M (ins, bytemode, sizeflag);
+ return OP_M (ins, bytemode, sizeflag);
}