/* 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 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 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 disassemble_info *,
+ enum disassembler_style,
+ const char *, ...);
/* This character is used to encode style information within the output
buffers. See oappend_insert_style for more details. */
/* The maximum operand buffer size. */
#define MAX_OPERAND_BUFFER_SIZE 128
-struct dis_private {
- /* Points to first byte not fetched. */
- bfd_byte *max_fetched;
- bfd_byte the_buffer[MAX_MNEM_SIZE];
- bfd_vma insn_start;
- int orig_sizeflag;
- OPCODES_SIGJMP_BUF bailout;
-};
-
enum address_mode
{
mode_16bit,
mode_64bit
};
+static const char *prefix_name (enum address_mode, uint8_t, int);
+
enum x86_64_isa
{
amd64 = 1,
int prefixes;
/* REX prefix the current instruction. See below. */
- unsigned char rex;
+ uint8_t rex;
/* Bits of REX we've already used. */
- unsigned char rex_used;
+ uint8_t rex_used;
bool need_modrm;
bool need_vex;
char obuf[MAX_OPERAND_BUFFER_SIZE];
char *obufp;
char *mnemonicendp;
- unsigned char *start_codep;
- unsigned char *insn_codep;
- unsigned char *codep;
- unsigned char *end_codep;
+ const uint8_t *start_codep;
+ uint8_t *codep;
+ const uint8_t *end_codep;
+ unsigned char nr_prefixes;
signed char last_lock_prefix;
signed char last_repz_prefix;
signed char last_repnz_prefix;
#define MAX_CODE_LENGTH 15
/* We can up to 14 ins->prefixes since the maximum instruction length is
15bytes. */
- unsigned char all_prefixes[MAX_CODE_LENGTH - 1];
+ uint8_t all_prefixes[MAX_CODE_LENGTH - 1];
disassemble_info *info;
struct
enum x86_64_isa isa64;
};
+struct dis_private {
+ bfd_vma insn_start;
+ int orig_sizeflag;
+
+ /* Indexes first byte not fetched. */
+ unsigned int fetched;
+ uint8_t the_buffer[2 * MAX_CODE_LENGTH - 1];
+};
+
/* Mark parts used in the REX prefix. When we are testing for
empty prefix (for 8bit register REX extension), just mask it
out. Otherwise test for REX bit is excuse for existence of REX
#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, const uint8_t *until)
{
- int status;
- struct dis_private *priv = (struct dis_private *) info->private_data;
- bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
-
- if (addr <= priv->the_buffer + MAX_MNEM_SIZE)
- status = (*info->read_memory_func) (start,
- priv->max_fetched,
- addr - priv->max_fetched,
- info);
- else
- status = -1;
+ int status = -1;
+ struct dis_private *priv = info->private_data;
+ bfd_vma start = priv->insn_start + priv->fetched;
+ uint8_t *fetch_end = priv->the_buffer + priv->fetched;
+ ptrdiff_t needed = until - fetch_end;
+
+ if (needed <= 0)
+ return true;
+
+ if (priv->fetched + (size_t) needed <= ARRAY_SIZE (priv->the_buffer))
+ status = (*info->read_memory_func) (start, fetch_end, needed, info);
if (status != 0)
{
/* If we did manage to read at least one byte, then
print_insn_i386 will do something sensible. Otherwise, print
an error. We do that here because this is where we know
STATUS. */
- if (priv->max_fetched == priv->the_buffer)
+ if (!priv->fetched)
(*info->memory_error_func) (status, start, info);
- OPCODES_SIGLONGJMP (priv->bailout, 1);
+ return false;
}
+
+ priv->fetched += needed;
+ return true;
+}
+
+static bool
+fetch_modrm (instr_info *ins)
+{
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+
+ ins->modrm.mod = (*ins->codep >> 6) & 3;
+ ins->modrm.reg = (*ins->codep >> 3) & 7;
+ ins->modrm.rm = *ins->codep & 7;
+
+ return true;
+}
+
+static int
+fetch_error (const instr_info *ins)
+{
+ /* Getting here means we tried for data but didn't get it. That
+ means we have an incomplete instruction of some sort. Just
+ print the first byte as a prefix or a .byte pseudo-op. */
+ const struct dis_private *priv = ins->info->private_data;
+ const char *name = NULL;
+
+ if (ins->codep <= priv->the_buffer)
+ return -1;
+
+ if (ins->prefixes || ins->fwait_prefix >= 0 || (ins->rex & REX_OPCODE))
+ name = prefix_name (ins->address_mode, priv->the_buffer[0],
+ priv->orig_sizeflag);
+ if (name != NULL)
+ i386_dis_printf (ins->info, dis_style_mnemonic, "%s", name);
else
- priv->max_fetched = addr;
+ {
+ /* Just print the first byte as a .byte instruction. */
+ i386_dis_printf (ins->info, dis_style_assembler_directive, ".byte ");
+ i386_dis_printf (ins->info, dis_style_immediate, "%#x",
+ (unsigned int) priv->the_buffer[0]);
+ }
+
return 1;
}
REG_VEX_0F72_M_0,
REG_VEX_0F73_M_0,
REG_VEX_0FAE,
- REG_VEX_0F3849_X86_64_P_0_W_0_M_1,
+ REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0,
REG_VEX_0F38F3_L_0,
REG_XOP_09_01_L_0,
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_0F382D,
MOD_VEX_0F382E,
MOD_VEX_0F382F,
- MOD_VEX_0F3849_X86_64_P_0_W_0,
- MOD_VEX_0F3849_X86_64_P_2_W_0,
- MOD_VEX_0F3849_X86_64_P_3_W_0,
- MOD_VEX_0F384B_X86_64_P_1_W_0,
- MOD_VEX_0F384B_X86_64_P_2_W_0,
- MOD_VEX_0F384B_X86_64_P_3_W_0,
+ MOD_VEX_0F3849_X86_64_L_0_W_0,
+ MOD_VEX_0F384B_X86_64_L_0_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_0F385C_X86_64,
+ MOD_VEX_0F385E_X86_64,
+ MOD_VEX_0F386C_X86_64,
MOD_VEX_0F388C,
MOD_VEX_0F388E,
MOD_VEX_0F3A30_L_0,
RM_0FAE_REG_7_MOD_3,
RM_0F3A0F_P_1_MOD_3_REG_0,
- RM_VEX_0F3849_X86_64_P_0_W_0_M_1_R_0
+ RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0,
+ RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3,
};
enum
{
PREFIX_90 = 0,
+ PREFIX_0F00_REG_6_X86_64,
PREFIX_0F01_REG_0_MOD_3_RM_6,
+ PREFIX_0F01_REG_1_RM_2,
PREFIX_0F01_REG_1_RM_4,
PREFIX_0F01_REG_1_RM_5,
PREFIX_0F01_REG_1_RM_6,
PREFIX_VEX_0FD0,
PREFIX_VEX_0FE6,
PREFIX_VEX_0FF0,
- PREFIX_VEX_0F3849_X86_64,
- PREFIX_VEX_0F384B_X86_64,
+ PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0,
+ PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1,
+ PREFIX_VEX_0F384B_X86_64_L_0_W_0_M_0,
PREFIX_VEX_0F3850_W_0,
PREFIX_VEX_0F3851_W_0,
- PREFIX_VEX_0F385C_X86_64,
- PREFIX_VEX_0F385E_X86_64,
+ PREFIX_VEX_0F385C_X86_64_M_1_L_0_W_0,
+ PREFIX_VEX_0F385E_X86_64_M_1_L_0_W_0,
+ PREFIX_VEX_0F386C_X86_64_M_1_L_0_W_0,
PREFIX_VEX_0F3872,
PREFIX_VEX_0F38B0_W_0,
PREFIX_VEX_0F38B1_W_0,
X86_64_E8,
X86_64_E9,
X86_64_EA,
+ X86_64_0F00_REG_6,
X86_64_0F01_REG_0,
X86_64_0F01_REG_0_MOD_3_RM_6_P_1,
X86_64_0F01_REG_0_MOD_3_RM_6_P_3,
X86_64_0F01_REG_1,
+ X86_64_0F01_REG_1_RM_2_PREFIX_1,
+ X86_64_0F01_REG_1_RM_2_PREFIX_3,
X86_64_0F01_REG_1_RM_5_PREFIX_2,
X86_64_0F01_REG_1_RM_6_PREFIX_2,
X86_64_0F01_REG_1_RM_7_PREFIX_2,
X86_64_VEX_0F384B,
X86_64_VEX_0F385C,
X86_64_VEX_0F385E,
+ X86_64_VEX_0F386C,
X86_64_VEX_0F38E0,
X86_64_VEX_0F38E1,
X86_64_VEX_0F38E2,
VEX_LEN_0F381A_M_0,
VEX_LEN_0F3836,
VEX_LEN_0F3841,
- VEX_LEN_0F3849_X86_64_P_0_W_0_M_0,
- VEX_LEN_0F3849_X86_64_P_0_W_0_M_1_REG_0_RM_0,
- VEX_LEN_0F3849_X86_64_P_2_W_0_M_0,
- VEX_LEN_0F3849_X86_64_P_3_W_0_M_0,
- VEX_LEN_0F384B_X86_64_P_1_W_0_M_0,
- VEX_LEN_0F384B_X86_64_P_2_W_0_M_0,
- VEX_LEN_0F384B_X86_64_P_3_W_0_M_0,
+ VEX_LEN_0F3849_X86_64,
+ VEX_LEN_0F384B_X86_64,
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_0F385C_X86_64_M_1,
+ VEX_LEN_0F385E_X86_64_M_1,
+ VEX_LEN_0F386C_X86_64_M_1,
VEX_LEN_0F38DB,
VEX_LEN_0F38F2,
VEX_LEN_0F38F3,
VEX_W_0F382F_M_0,
VEX_W_0F3836,
VEX_W_0F3846,
- VEX_W_0F3849_X86_64_P_0,
- VEX_W_0F3849_X86_64_P_2,
- VEX_W_0F3849_X86_64_P_3,
- VEX_W_0F384B_X86_64_P_1,
- VEX_W_0F384B_X86_64_P_2,
- VEX_W_0F384B_X86_64_P_3,
+ VEX_W_0F3849_X86_64_L_0,
+ VEX_W_0F384B_X86_64_L_0,
VEX_W_0F3850,
VEX_W_0F3851,
VEX_W_0F3852,
VEX_W_0F3858,
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_0F385C_X86_64_M_1_L_0,
+ VEX_W_0F385E_X86_64_M_1_L_0,
+ VEX_W_0F386C_X86_64_M_1_L_0,
VEX_W_0F3872_P_1,
VEX_W_0F3878,
VEX_W_0F3879,
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"
};
{ "ltr", { Ew }, 0 },
{ "verr", { Ew }, 0 },
{ "verw", { Ew }, 0 },
- { Bad_Opcode },
+ { X86_64_TABLE (X86_64_0F00_REG_6) },
{ Bad_Opcode },
},
/* REG_0F01 */
{ MOD_TABLE (MOD_VEX_0FAE_REG_2) },
{ MOD_TABLE (MOD_VEX_0FAE_REG_3) },
},
- /* REG_VEX_0F3849_X86_64_P_0_W_0_M_1 */
+ /* REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0 */
{
- { RM_TABLE (RM_VEX_0F3849_X86_64_P_0_W_0_M_1_R_0) },
+ { RM_TABLE (RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0) },
},
/* REG_VEX_0F38F3_L_0 */
{
{ NULL, { { NULL, 0 } }, PREFIX_IGNORED }
},
+ /* PREFIX_0F00_REG_6_X86_64 */
+ {
+ { Bad_Opcode },
+ { Bad_Opcode },
+ { Bad_Opcode },
+ { "lkgs", { Ew }, 0 },
+ },
+
/* 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_3) },
},
+ /* PREFIX_0F01_REG_1_RM_2 */
+ {
+ { "clac", { Skip_MODRM }, 0 },
+ { X86_64_TABLE (X86_64_0F01_REG_1_RM_2_PREFIX_1) },
+ { Bad_Opcode },
+ { X86_64_TABLE (X86_64_0F01_REG_1_RM_2_PREFIX_3)},
+ },
+
/* PREFIX_0F01_REG_1_RM_4 */
{
{ Bad_Opcode },
{ MOD_TABLE (MOD_VEX_0FF0_PREFIX_3) },
},
- /* PREFIX_VEX_0F3849_X86_64 */
+ /* PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0 */
{
- { VEX_W_TABLE (VEX_W_0F3849_X86_64_P_0) },
+ { "ldtilecfg", { M }, 0 },
{ Bad_Opcode },
- { VEX_W_TABLE (VEX_W_0F3849_X86_64_P_2) },
- { VEX_W_TABLE (VEX_W_0F3849_X86_64_P_3) },
+ { "sttilecfg", { M }, 0 },
},
- /* PREFIX_VEX_0F384B_X86_64 */
+ /* PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1 */
{
+ { REG_TABLE (REG_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0) },
+ { Bad_Opcode },
{ Bad_Opcode },
- { VEX_W_TABLE (VEX_W_0F384B_X86_64_P_1) },
- { VEX_W_TABLE (VEX_W_0F384B_X86_64_P_2) },
- { VEX_W_TABLE (VEX_W_0F384B_X86_64_P_3) },
+ { RM_TABLE (RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3) },
+ },
+
+ /* PREFIX_VEX_0F384B_X86_64_L_0_W_0_M_0 */
+ {
+ { Bad_Opcode },
+ { "tilestored", { MVexSIBMEM, TMM }, 0 },
+ { "tileloaddt1", { TMM, MVexSIBMEM }, 0 },
+ { "tileloadd", { TMM, MVexSIBMEM }, 0 },
},
/* PREFIX_VEX_0F3850_W_0 */
{ "%XVvpdpbusds", { XM, Vex, EXx }, 0 },
{ "vpdpbssds", { XM, Vex, EXx }, 0 },
},
- /* PREFIX_VEX_0F385C_X86_64 */
+ /* PREFIX_VEX_0F385C_X86_64_M_1_L_0_W_0 */
{
{ Bad_Opcode },
- { VEX_W_TABLE (VEX_W_0F385C_X86_64_P_1) },
+ { "tdpbf16ps", { TMM, EXtmm, VexTmm }, 0 },
{ Bad_Opcode },
- { VEX_W_TABLE (VEX_W_0F385C_X86_64_P_3) },
+ { "tdpfp16ps", { TMM, EXtmm, VexTmm }, 0 },
},
- /* PREFIX_VEX_0F385E_X86_64 */
+ /* PREFIX_VEX_0F385E_X86_64_M_1_L_0_W_0 */
{
- { VEX_W_TABLE (VEX_W_0F385E_X86_64_P_0) },
- { VEX_W_TABLE (VEX_W_0F385E_X86_64_P_1) },
- { VEX_W_TABLE (VEX_W_0F385E_X86_64_P_2) },
- { VEX_W_TABLE (VEX_W_0F385E_X86_64_P_3) },
+ { "tdpbuud", {TMM, EXtmm, VexTmm }, 0 },
+ { "tdpbsud", {TMM, EXtmm, VexTmm }, 0 },
+ { "tdpbusd", {TMM, EXtmm, VexTmm }, 0 },
+ { "tdpbssd", {TMM, EXtmm, VexTmm }, 0 },
+ },
+
+ /* PREFIX_VEX_0F386C_X86_64_M_1_L_0_W_0 */
+ {
+ { "tcmmrlfp16ps", { TMM, EXtmm, VexTmm }, 0 },
+ { Bad_Opcode },
+ { "tcmmimfp16ps", { TMM, EXtmm, VexTmm }, 0 },
},
/* PREFIX_VEX_0F3872 */
{ "{l|}jmp{P|}", { Ap }, 0 },
},
+ /* X86_64_0F00_REG_6 */
+ {
+ { Bad_Opcode },
+ { PREFIX_TABLE (PREFIX_0F00_REG_6_X86_64) },
+ },
+
/* X86_64_0F01_REG_0 */
{
{ "sgdt{Q|Q}", { M }, 0 },
{ "sidt", { M }, 0 },
},
+ /* X86_64_0F01_REG_1_RM_2_PREFIX_1 */
+ {
+ { Bad_Opcode },
+ { "eretu", { Skip_MODRM }, 0 },
+ },
+
+ /* X86_64_0F01_REG_1_RM_2_PREFIX_3 */
+ {
+ { Bad_Opcode },
+ { "erets", { Skip_MODRM }, 0 },
+ },
+
/* X86_64_0F01_REG_1_RM_5_PREFIX_2 */
{
{ Bad_Opcode },
/* X86_64_VEX_0F3849 */
{
{ Bad_Opcode },
- { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64) },
+ { VEX_LEN_TABLE (VEX_LEN_0F3849_X86_64) },
},
/* X86_64_VEX_0F384B */
{
{ Bad_Opcode },
- { PREFIX_TABLE (PREFIX_VEX_0F384B_X86_64) },
+ { VEX_LEN_TABLE (VEX_LEN_0F384B_X86_64) },
},
/* X86_64_VEX_0F385C */
{
{ Bad_Opcode },
- { PREFIX_TABLE (PREFIX_VEX_0F385C_X86_64) },
+ { MOD_TABLE (MOD_VEX_0F385C_X86_64) },
},
/* X86_64_VEX_0F385E */
{
{ Bad_Opcode },
- { PREFIX_TABLE (PREFIX_VEX_0F385E_X86_64) },
+ { MOD_TABLE (MOD_VEX_0F385E_X86_64) },
+ },
+
+ /* X86_64_VEX_0F386C */
+ {
+ { Bad_Opcode },
+ { MOD_TABLE (MOD_VEX_0F386C_X86_64) },
},
/* X86_64_VEX_0F38E0 */
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
- { Bad_Opcode },
+ { X86_64_TABLE (X86_64_VEX_0F386C) },
{ Bad_Opcode },
{ Bad_Opcode },
{ Bad_Opcode },
{ "vphminposuw", { XM, EXx }, PREFIX_DATA },
},
- /* VEX_LEN_0F3849_X86_64_P_0_W_0_M_0 */
- {
- { "ldtilecfg", { M }, 0 },
- },
-
- /* VEX_LEN_0F3849_X86_64_P_0_W_0_M_1_REG_0_RM_0 */
+ /* VEX_LEN_0F3849_X86_64 */
{
- { "tilerelease", { Skip_MODRM }, 0 },
+ { VEX_W_TABLE (VEX_W_0F3849_X86_64_L_0) },
},
- /* VEX_LEN_0F3849_X86_64_P_2_W_0_M_0 */
+ /* VEX_LEN_0F384B_X86_64 */
{
- { "sttilecfg", { M }, 0 },
- },
-
- /* VEX_LEN_0F3849_X86_64_P_3_W_0_M_0 */
- {
- { "tilezero", { TMM, Skip_MODRM }, 0 },
- },
-
- /* VEX_LEN_0F384B_X86_64_P_1_W_0_M_0 */
- {
- { "tilestored", { MVexSIBMEM, TMM }, 0 },
- },
- /* VEX_LEN_0F384B_X86_64_P_2_W_0_M_0 */
- {
- { "tileloaddt1", { TMM, MVexSIBMEM }, 0 },
- },
-
- /* VEX_LEN_0F384B_X86_64_P_3_W_0_M_0 */
- {
- { "tileloadd", { TMM, MVexSIBMEM }, 0 },
+ { VEX_W_TABLE (VEX_W_0F384B_X86_64_L_0) },
},
/* VEX_LEN_0F385A_M_0 */
{ VEX_W_TABLE (VEX_W_0F385A_M_0_L_0) },
},
- /* VEX_LEN_0F385C_X86_64_P_1_W_0_M_0 */
- {
- { "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 */
+ /* VEX_LEN_0F385C_X86_64_M_1 */
{
- { "tdpbuud", {TMM, EXtmm, VexTmm }, 0 },
+ { VEX_W_TABLE (VEX_W_0F385C_X86_64_M_1_L_0) },
},
- /* VEX_LEN_0F385E_X86_64_P_1_W_0_M_0 */
+ /* VEX_LEN_0F385E_X86_64_M_1 */
{
- { "tdpbsud", {TMM, EXtmm, VexTmm }, 0 },
+ { VEX_W_TABLE (VEX_W_0F385E_X86_64_M_1_L_0) },
},
- /* VEX_LEN_0F385E_X86_64_P_2_W_0_M_0 */
+ /* VEX_LEN_0F386C_X86_64_M_1 */
{
- { "tdpbusd", {TMM, EXtmm, VexTmm }, 0 },
- },
-
- /* VEX_LEN_0F385E_X86_64_P_3_W_0_M_0 */
- {
- { "tdpbssd", {TMM, EXtmm, VexTmm }, 0 },
+ { VEX_W_TABLE (VEX_W_0F386C_X86_64_M_1_L_0) },
},
/* VEX_LEN_0F38DB */
{ "vpsravd", { XM, Vex, EXx }, PREFIX_DATA },
},
{
- /* VEX_W_0F3849_X86_64_P_0 */
- { MOD_TABLE (MOD_VEX_0F3849_X86_64_P_0_W_0) },
- },
- {
- /* VEX_W_0F3849_X86_64_P_2 */
- { MOD_TABLE (MOD_VEX_0F3849_X86_64_P_2_W_0) },
- },
- {
- /* VEX_W_0F3849_X86_64_P_3 */
- { MOD_TABLE (MOD_VEX_0F3849_X86_64_P_3_W_0) },
- },
- {
- /* VEX_W_0F384B_X86_64_P_1 */
- { MOD_TABLE (MOD_VEX_0F384B_X86_64_P_1_W_0) },
- },
- {
- /* VEX_W_0F384B_X86_64_P_2 */
- { MOD_TABLE (MOD_VEX_0F384B_X86_64_P_2_W_0) },
+ /* VEX_W_0F3849_X86_64_L_0 */
+ { MOD_TABLE (MOD_VEX_0F3849_X86_64_L_0_W_0) },
},
{
- /* VEX_W_0F384B_X86_64_P_3 */
- { MOD_TABLE (MOD_VEX_0F384B_X86_64_P_3_W_0) },
+ /* VEX_W_0F384B_X86_64_L_0 */
+ { MOD_TABLE (MOD_VEX_0F384B_X86_64_L_0_W_0) },
},
{
/* VEX_W_0F3850 */
{ "vbroadcasti128", { XM, Mxmm }, PREFIX_DATA },
},
{
- /* 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_1 */
- { MOD_TABLE (MOD_VEX_0F385E_X86_64_P_1_W_0) },
+ /* VEX_W_0F385C_X86_64_M_1_L_0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F385C_X86_64_M_1_L_0_W_0) },
},
{
- /* VEX_W_0F385E_X86_64_P_2 */
- { MOD_TABLE (MOD_VEX_0F385E_X86_64_P_2_W_0) },
+ /* VEX_W_0F385E_X86_64_M_1_L_0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F385E_X86_64_M_1_L_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_M_1_L_0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F386C_X86_64_M_1_L_0_W_0) },
},
{
/* VEX_W_0F3872_P_1 */
{ "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 },
{ VEX_W_TABLE (VEX_W_0F382F_M_0) },
},
{
- /* MOD_VEX_0F3849_X86_64_P_0_W_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F3849_X86_64_P_0_W_0_M_0) },
- { REG_TABLE (REG_VEX_0F3849_X86_64_P_0_W_0_M_1) },
+ /* MOD_VEX_0F3849_X86_64_L_0_W_0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_0) },
+ { PREFIX_TABLE (PREFIX_VEX_0F3849_X86_64_L_0_W_0_M_1) },
},
{
- /* MOD_VEX_0F3849_X86_64_P_2_W_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F3849_X86_64_P_2_W_0_M_0) },
- },
- {
- /* MOD_VEX_0F3849_X86_64_P_3_W_0 */
- { Bad_Opcode },
- { VEX_LEN_TABLE (VEX_LEN_0F3849_X86_64_P_3_W_0_M_0) },
- },
- {
- /* MOD_VEX_0F384B_X86_64_P_1_W_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F384B_X86_64_P_1_W_0_M_0) },
- },
- {
- /* MOD_VEX_0F384B_X86_64_P_2_W_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F384B_X86_64_P_2_W_0_M_0) },
- },
- {
- /* MOD_VEX_0F384B_X86_64_P_3_W_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F384B_X86_64_P_3_W_0_M_0) },
+ /* MOD_VEX_0F384B_X86_64_L_0_W_0 */
+ { PREFIX_TABLE (PREFIX_VEX_0F384B_X86_64_L_0_W_0_M_0) },
},
{
/* MOD_VEX_0F385A */
{ VEX_LEN_TABLE (VEX_LEN_0F385A_M_0) },
},
{
- /* MOD_VEX_0F385C_X86_64_P_1_W_0 */
- { 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 },
- { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_0_W_0_M_0) },
- },
- {
- /* MOD_VEX_0F385E_X86_64_P_1_W_0 */
+ /* MOD_VEX_0F385C_X86_64 */
{ Bad_Opcode },
- { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_1_W_0_M_0) },
+ { VEX_LEN_TABLE (VEX_LEN_0F385C_X86_64_M_1) },
},
{
- /* MOD_VEX_0F385E_X86_64_P_2_W_0 */
+ /* MOD_VEX_0F385E_X86_64 */
{ Bad_Opcode },
- { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_2_W_0_M_0) },
+ { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_M_1) },
},
{
- /* MOD_VEX_0F385E_X86_64_P_3_W_0 */
+ /* MOD_VEX_0F386C_X86_64 */
{ Bad_Opcode },
- { VEX_LEN_TABLE (VEX_LEN_0F385E_X86_64_P_3_W_0_M_0) },
+ { VEX_LEN_TABLE (VEX_LEN_0F386C_X86_64_M_1) },
},
{
/* MOD_VEX_0F388C */
/* RM_0F01_REG_1 */
{ "monitor", { { OP_Monitor, 0 } }, 0 },
{ "mwait", { { OP_Mwait, 0 } }, 0 },
- { "clac", { Skip_MODRM }, 0 },
+ { PREFIX_TABLE (PREFIX_0F01_REG_1_RM_2) },
{ "stac", { Skip_MODRM }, 0 },
{ PREFIX_TABLE (PREFIX_0F01_REG_1_RM_4) },
{ PREFIX_TABLE (PREFIX_0F01_REG_1_RM_5) },
{ "hreset", { Skip_MODRM, Ib }, 0 },
},
{
- /* RM_VEX_0F3849_X86_64_P_0_W_0_M_1_R_0 */
- { VEX_LEN_TABLE (VEX_LEN_0F3849_X86_64_P_0_W_0_M_1_REG_0_RM_0) },
+ /* RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_0_R_0 */
+ { "tilerelease", { Skip_MODRM }, 0 },
+ },
+ {
+ /* RM_VEX_0F3849_X86_64_L_0_W_0_M_1_P_3 */
+ { "tilezero", { TMM, Skip_MODRM }, 0 },
},
};
#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;
+ int i, length;
+ uint8_t newrex;
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 (enum address_mode mode, uint8_t pref, int sizeflag)
{
static const char *rexes [16] =
{
case 0x66:
return (sizeflag & DFLAG) ? "data16" : "data32";
case 0x67:
- if (ins->address_mode == mode_64bit)
+ if (mode == mode_64bit)
return (sizeflag & AFLAG) ? "addr32" : "addr64";
else
return (sizeflag & AFLAG) ? "addr16" : "addr32";
/* 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_with_style (below) but always with text style. */
+
+static void
+oappend (instr_info *ins, const char *s)
+{
+ oappend_with_style (ins, s, dis_style_text);
}
-/* Like oappend (below), but S is a string starting with '%'. In
+/* Like oappend (above), but S is a string starting with '%'. In
Intel syntax, the '%' is elided. */
static void
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 disassemble_info *info, enum disassembler_style style,
const char *fmt, ...)
{
va_list ap;
{
/* 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);
+ int n = (*info->fprintf_styled_func) (info->stream, curr_style,
+ "%.*s", len, start);
if (n < 0)
break;
{
const struct dis386 *dp;
int i;
+ int ret;
char *op_txt[MAX_OPERANDS];
int needcomma;
bool intel_swap_2_3;
if (ins.address_mode == mode_64bit && sizeof (bfd_vma) < 8)
{
- i386_dis_printf (&ins, dis_style_text, _("64-bit address is disabled"));
+ i386_dis_printf (info, dis_style_text, _("64-bit address is disabled"));
return -1;
}
info->bytes_per_line = 7;
info->private_data = &priv;
- priv.max_fetched = priv.the_buffer;
+ priv.fetched = 0;
priv.insn_start = pc;
for (i = 0; i < MAX_OPERANDS; ++i)
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];
i++)
- i386_dis_printf (&ins, dis_style_mnemonic, "%s%s",
+ i386_dis_printf (info, dis_style_mnemonic, "%s%s",
(i == 0 ? "" : " "),
- prefix_name (&ins, ins.all_prefixes[i], sizeflag));
- return i;
+ prefix_name (ins.address_mode, ins.all_prefixes[i],
+ sizeflag));
+ ret = i;
+ goto out;
+
+ case ckp_fetch_error:
+ goto fetch_error_out;
}
- ins.insn_codep = ins.codep;
+ ins.nr_prefixes = ins.codep - ins.start_codep;
+
+ if (!fetch_code (info, ins.codep + 1))
+ {
+ fetch_error_out:
+ ret = fetch_error (&ins);
+ goto out;
+ }
- FETCH_DATA (info, ins.codep + 1);
- ins.two_source_ops = (*ins.codep == 0x62) || (*ins.codep == 0xc8);
+ 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];
i++)
- 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;
+ i386_dis_printf (info, dis_style_mnemonic, "%s ",
+ prefix_name (ins.address_mode, ins.all_prefixes[i],
+ sizeflag));
+ i386_dis_printf (info, dis_style_mnemonic, "fwait");
+ 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)
are all 0s in inverted form. */
if (ins.need_vex && ins.vex.register_specifier != 0)
{
- i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ i386_dis_printf (info, 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)
{
- i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ i386_dis_printf (info, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
switch (dp->prefix_requirement)
the encoding invalid. Most other PREFIX_OPCODE rules still apply. */
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;
+ i386_dis_printf (info, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
ins.used_prefixes |= PREFIX_DATA;
/* Fall through. */
|| (ins.vex.evex && dp->prefix_requirement != PREFIX_DATA
&& !ins.vex.w != !(ins.used_prefixes & PREFIX_DATA)))
{
- i386_dis_printf (&ins, dis_style_text, "(bad)");
- return ins.end_codep - priv.the_buffer;
+ i386_dis_printf (info, dis_style_text, "(bad)");
+ ret = ins.end_codep - priv.the_buffer;
+ goto out;
}
break;
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);
+ const char *name = prefix_name (ins.address_mode, ins.all_prefixes[i],
+ orig_sizeflag);
+
if (name == NULL)
abort ();
prefix_length += strlen (name) + 1;
- i386_dis_printf (&ins, dis_style_mnemonic, "%s ", name);
+ i386_dis_printf (info, dis_style_mnemonic, "%s ", name);
}
/* Check maximum code length. */
if ((ins.codep - ins.start_codep) > MAX_CODE_LENGTH)
{
- i386_dis_printf (&ins, dis_style_text, "(bad)");
- return MAX_CODE_LENGTH;
+ i386_dis_printf (info, dis_style_text, "(bad)");
+ ret = MAX_CODE_LENGTH;
+ goto out;
}
/* Calculate the number of operands this instruction has. */
i = 0;
/* Print the instruction mnemonic along with any trailing whitespace. */
- i386_dis_printf (&ins, dis_style_mnemonic, "%s%*s", ins.obuf, i, "");
+ i386_dis_printf (info, 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. */
break;
}
if (needcomma)
- i386_dis_printf (&ins, dis_style_text, ",");
+ i386_dis_printf (info, 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]];
(*info->print_address_func) (target, info);
}
else
- i386_dis_printf (&ins, dis_style_text, "%s", op_txt[i]);
+ i386_dis_printf (info, 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])
{
- i386_dis_printf (&ins, dis_style_comment_start, " # ");
+ i386_dis_printf (info, 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
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;
- unsigned char floatop;
-
- floatop = ins->codep[-1];
+ unsigned char floatop = ins->codep[-1];
if (ins->modrm.mod != 3)
{
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. */
*ins->obufp++ = ' ';
break;
case 'L':
- if (!(ins->rex & REX_W))
- break;
- *ins->obufp++ = 'a';
- *ins->obufp++ = 'b';
- *ins->obufp++ = 's';
- break;
+ if (ins->rex & REX_W)
+ {
+ *ins->obufp++ = 'a';
+ *ins->obufp++ = 'b';
+ *ins->obufp++ = 's';
+ }
+ goto case_S;
default:
abort ();
}
}
else
abort ();
- goto case_S;
+ break;
case 'W':
if (l == 0)
{
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. */
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
{
char tmp[30];
- if (ins->address_mode == mode_64bit)
- sprintf (tmp, "0x%" PRIx64, (uint64_t) disp);
- else
- sprintf (tmp, "0x%x", (unsigned int) disp);
+ if (ins->address_mode != mode_64bit)
+ disp &= 0xffffffff;
+ sprintf (tmp, "0x%" PRIx64, (uint64_t) disp);
oappend_with_style (ins, tmp, style);
}
/* 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 bool
+get8s (instr_info *ins, bfd_vma *res)
+{
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+ *res = ((bfd_vma) *ins->codep++ ^ 0x80) - 0x80;
+ return true;
+}
+
+static bool
+get16 (instr_info *ins, bfd_vma *res)
+{
+ if (!fetch_code (ins->info, ins->codep + 2))
+ return false;
+ *res = *ins->codep++;
+ *res |= (bfd_vma) *ins->codep++ << 8;
+ return true;
+}
+
+static bool
+get16s (instr_info *ins, bfd_vma *res)
+{
+ if (!get16 (ins, res))
+ return false;
+ *res = (*res ^ 0x8000) - 0x8000;
+ return true;
+}
+
+static bool
+get32 (instr_info *ins, bfd_vma *res)
+{
+ if (!fetch_code (ins->info, ins->codep + 4))
+ return false;
+ *res = *ins->codep++;
+ *res |= (bfd_vma) *ins->codep++ << 8;
+ *res |= (bfd_vma) *ins->codep++ << 16;
+ *res |= (bfd_vma) *ins->codep++ << 24;
+ return true;
+}
+
+static bool
+get32s (instr_info *ins, bfd_vma *res)
+{
+ if (!get32 (ins, res))
+ return false;
+
+ *res = (*res ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
+
+ return true;
+}
+
+static bool
+get64 (instr_info *ins, uint64_t *res)
+{
+ unsigned int a;
+ unsigned int b;
+
+ if (!fetch_code (ins->info, ins->codep + 8))
+ return false;
+ a = *ins->codep++;
+ a |= (unsigned int) *ins->codep++ << 8;
+ a |= (unsigned int) *ins->codep++ << 16;
+ a |= (unsigned int) *ins->codep++ << 24;
+ b = *ins->codep++;
+ b |= (unsigned int) *ins->codep++ << 8;
+ b |= (unsigned int) *ins->codep++ << 16;
+ b |= (unsigned int) *ins->codep++ << 24;
+ *res = a + ((uint64_t) b << 32);
+ return true;
+}
+
static void
+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;
+ else /* Mask to get a 32-bit address. */
+ ins->op_address[ins->op_ad] = op & 0xffffffff;
+ ins->op_riprel[ins->op_ad] = riprel;
+}
+
+static bool
+BadOp (instr_info *ins)
+{
+ /* Throw away prefixes and 1st. opcode byte. */
+ struct dis_private *priv = ins->info->private_data;
+
+ ins->codep = priv->the_buffer + ins->nr_prefixes + 1;
+ ins->obufp = stpcpy (ins->obufp, "(bad)");
+ return true;
+}
+
+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_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);
- disp = *ins->codep++;
- if ((disp & 0x80) != 0)
- disp -= 0x100;
+ if (!get8s (ins, &disp))
+ return false;
if (ins->vex.evex && shift > 0)
disp <<= shift;
break;
case 2:
- disp = get32s (ins);
+ if (!get32s (ins, &disp))
+ return false;
break;
}
{
/* Without base nor index registers, zero-extend the
lower 32-bit displacement to 64 bits. */
- disp = (unsigned int) disp;
+ disp &= 0xffffffff;
needindex = 1;
}
needaddr32 = 1;
{
if (!havedisp || (bfd_signed_vma) 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 */
+ bfd_vma disp = 0;
+
ins->used_prefixes |= ins->prefixes & PREFIX_ADDR;
switch (ins->modrm.mod)
{
case 0:
if (ins->modrm.rm == 6)
{
- disp = get16 (ins);
- if ((disp & 0x8000) != 0)
- disp -= 0x10000;
+ case 2:
+ if (!get16s (ins, &disp))
+ return false;
}
break;
case 1:
- FETCH_DATA (ins->info, ins->codep + 1);
- disp = *ins->codep++;
- if ((disp & 0x80) != 0)
- disp -= 0x100;
+ if (!get8s (ins, &disp))
+ return false;
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)
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);
-}
-
-#ifdef BFD64
-static bfd_vma
-get64 (instr_info *ins)
-{
- bfd_vma x;
- unsigned int a;
- unsigned int b;
-
- FETCH_DATA (ins->info, ins->codep + 8);
- a = *ins->codep++ & 0xff;
- a |= (*ins->codep++ & 0xff) << 8;
- a |= (*ins->codep++ & 0xff) << 16;
- a |= (*ins->codep++ & 0xffu) << 24;
- b = *ins->codep++ & 0xff;
- 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;
-}
-#endif
-
-static bfd_signed_vma
-get32 (instr_info *ins)
-{
- 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;
-}
-
-static bfd_signed_vma
-get32s (instr_info *ins)
-{
- 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;
-
- x = (x ^ ((bfd_vma) 1 << 31)) - ((bfd_vma) 1 << 31);
-
- return x;
-}
-
-static int
-get16 (instr_info *ins)
-{
- int x = 0;
-
- FETCH_DATA (ins->info, ins->codep + 2);
- x = *ins->codep++ & 0xff;
- x |= (*ins->codep++ & 0xff) << 8;
- return x;
-}
-
-static void
-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;
- else /* Mask to get a 32-bit address. */
- ins->op_address[ins->op_ad] = op & 0xffffffff;
- ins->op_riprel[ins->op_ad] = riprel;
+ oappend (ins, "(bad)");
+ else
+ print_register (ins, ins->modrm.reg, REX_R, bytemode, sizeflag);
+ return true;
}
-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;
- bfd_signed_vma mask = -1;
+ bfd_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);
- mask = 0xffffffff;
+ case d_mode:
+ if (!get32 (ins, &op))
+ return false;
}
else
{
- op = get16 (ins);
- mask = 0xfffff;
+ /* Fall through. */
+ case w_mode:
+ if (!get16 (ins, &op))
+ return false;
}
- 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;
+ bfd_vma op;
switch (bytemode)
{
case b_mode:
case b_T_mode:
- FETCH_DATA (ins->info, ins->codep + 1);
- op = *ins->codep++;
- if ((op & 0x80) != 0)
- op -= 0x100;
+ if (!get8s (ins, &op))
+ return false;
if (bytemode == b_T_mode)
{
if (ins->address_mode != mode_64bit
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))
+ {
+ if (!get16 (ins, &op))
+ return false;
+ }
+ 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);
- disp = *ins->codep++;
- if ((disp & 0x80) != 0)
- disp -= 0x100;
+ if (!get8s (ins, &disp))
+ return false;
break;
case v_mode:
case dqw_mode:
|| (ins->address_mode == mode_64bit
&& ((ins->isa64 == intel64 && bytemode != dqw_mode)
|| (ins->rex & REX_W))))
- disp = get32s (ins);
+ {
+ if (!get32s (ins, &disp))
+ return false;
+ }
else
{
- disp = get16 (ins);
- if ((disp & 0x8000) != 0)
- disp -= 0x10000;
+ if (!get16s (ins, &disp))
+ return false;
/* 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;
+ bfd_vma seg, offset;
+ int res;
char scratch[24];
if (sizeflag & DFLAG)
{
- offset = get32 (ins);
- seg = get16 (ins);
- }
- else
- {
- offset = get16 (ins);
- seg = get16 (ins);
+ if (!get32 (ins, &offset))
+ return false;;
}
+ 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),
ins->intel_syntax ? "0x%x:0x%x" : "$0x%x,$0x%x",
- seg, offset);
+ (unsigned) seg, (unsigned) 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);
+ {
+ if (!get32 (ins, &off))
+ return false;
+ }
else
- off = get16 (ins);
+ {
+ if (!get16 (ins, &off))
+ return false;
+ }
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. */
ins->obufp = ins->mnemonicendp;
- mnemonic = Suffix3DNow[*ins->codep++ & 0xff];
+ mnemonic = Suffix3DNow[*ins->codep++];
if (mnemonic)
ins->obufp = stpcpy (ins->obufp, mnemonic);
else
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);
- cmp_type = *ins->codep++ & 0xff;
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+ cmp_type = *ins->codep++;
if (cmp_type < ARRAY_SIZE (simd_cmp_op))
{
char suffix[3];
/* 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
-BadOp (instr_info *ins)
-{
- /* Throw away prefixes and 1st. opcode byte. */
- ins->codep = ins->insn_codep + 1;
- ins->obufp = stpcpy (ins->obufp, "(bad)");
-}
-
-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);
- cmp_type = *ins->codep++ & 0xff;
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+ cmp_type = *ins->codep++;
/* There are aliases for immediates 0, 1, 2, 4, 5, 6.
If it's the case, print suffix, otherwise - print the immediate. */
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 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);
- cmp_type = *ins->codep++ & 0xff;
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+ cmp_type = *ins->codep++;
if (cmp_type < ARRAY_SIZE (xop_cmp_op))
{
char suffix[3];
/* 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);
- pclmul_type = *ins->codep++ & 0xff;
+ if (!fetch_code (ins->info, ins->codep + 1))
+ return false;
+ pclmul_type = *ins->codep++;
switch (pclmul_type)
{
case 0x10:
/* 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);
}