summaryrefslogtreecommitdiff
path: root/opcodes/i386-dis.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2013-07-24 15:47:23 +0000
committerH.J. Lu <hjl.tools@gmail.com>2013-07-24 15:47:23 +0000
commitccd8f4a84d05fe0e25afe90e73a268e0492f7646 (patch)
tree80f136501560d785c8bb3fd20040c15c0ed00f04 /opcodes/i386-dis.c
parent93d23fa16ca5c3b793d61c3d867b22fadc073c34 (diff)
downloadbinutils-redhat-ccd8f4a84d05fe0e25afe90e73a268e0492f7646.tar.gz
Support Intel MPX
gas/ 2013-07-24 Anna Tikhonova <anna.tikhonova@intel.com> Kirill Yukhin <kirill.yukhin@intel.com> Michael Zolotukhin <michael.v.zolotukhin@intel.com> * config/tc-i386.c (BND_PREFIX): New. (struct _i386_insn): Add new field bnd_prefix. (add_bnd_prefix): New. (cpu_arch): Add MPX. (i386_operand_type): Add regbnd. (md_assemble): Handle BND prefixes. (parse_insn): Likewise. (output_branch): Likewise. (output_jump): Likewise. (build_modrm_byte): Handle regbnd. (OPTION_MADD_BND_PREFIX): New. (md_longopts): Add entry for 'madd-bnd-prefix'. (md_parse_option): Handle madd-bnd-prefix option. (md_show_usage): Add description for madd-bnd-prefix option. * doc/c-i386.texi: Document mpx/.mpx and -madd-bnd-prefix. gas/testsuite/ 2013-07-24 Anna Tikhonova <anna.tikhonova@intel.com> Kirill Yukhin <kirill.yukhin@intel.com> Michael Zolotukhin <michael.v.zolotukhin@intel.com> * gas/i386/mpx-add-bnd-prefix.s: New. * gas/i386/mpx-add-bnd-prefix.d: New. * gas/i386/mpx-inval-1.l: New. * gas/i386/mpx-inval-1.s: New. * gas/i386/mpx.d: New. * gas/i386/mpx.s: New. * gas/i386/x86-64-mpx-add-bnd-prefix.d: New. * gas/i386/x86-64-mpx-add-bnd-prefix.s: New. * gas/i386/x86-64-mpx-addr32.d: New. * gas/i386/x86-64-mpx-addr32.s: New. * gas/i386/x86-64-mpx-inval-1.l: New. * gas/i386/x86-64-mpx-inval-1.s: New. * gas/i386/x86-64-mpx-inval-2.l: New. * gas/i386/x86-64-mpx-inval-2.s: New. * gas/i386/x86-64-mpx.d: New. * gas/i386/x86-64-mpx.s: New. * gas/i386/nops.d: Adjust to MPX changes. * gas/i386/nops.s: Likewise. * gas/i386/x86-64-nops.d: Likewise. * gas/i386/x86-64-nops.s: Likewise. * gas/i386/ilp32/x86-64-nops.d: Likewise. * gas/i386/i386.exp: Run new MPX tests. include/opcode/ 2013-07-24 Anna Tikhonova <anna.tikhonova@intel.com> Kirill Yukhin <kirill.yukhin@intel.com> Michael Zolotukhin <michael.v.zolotukhin@intel.com> * i386.h (BND_PREFIX_OPCODE): New. opcodes/ 2013-07-24 Anna Tikhonova <anna.tikhonova@intel.com> Kirill Yukhin <kirill.yukhin@intel.com> Michael Zolotukhin <michael.v.zolotukhin@intel.com> * i386-dis.c (BND_Fixup): New. (Ebnd): New. (Ev_bnd): New. (Gbnd): New. (BND): New. (v_bnd_mode): New. (bnd_mode): New. (MOD enum): Add new entries. (PREFIX enum): Likewise. (dis tables): Replace XX with BND for near branch and call instructions. (prefix_table): Add new entries. (mod_table): Likewise. (names_bnd): New. (intel_names_bnd): New. (att_names_bnd): New. (BND_PREFIX): New. (prefix_name): Handle BND_PREFIX. (print_insn): Initialize names_bnd. (intel_operand_size): Handle new modes. (OP_E_register): Likewise. (OP_E_memory): Likewise. (OP_G): Likewise. * i386-gen.c (cpu_flag_init): Add CpuMPX. (cpu_flags): Add CpuMPX. (operand_type_init): Add RegBND. (opcode_modifiers): Add BNDPrefixOk. (operand_types): Add RegBND. * i386-init.h: Regenerate. * i386-opc.h (CpuMPX): New. (CpuUnused): Comment out. (i386_cpu_flags): Add cpumpx. (BNDPrefixOk): New. (i386_opcode_modifier): Add bndprefixok. (RegBND): New. (i386_operand_type): Add regbnd. * i386-opc.tbl: Add BNDPrefixOk to near jumps, calls and rets. Add MPX instructions and bnd prefix. * i386-reg.tbl: Add bnd0-bnd3 registers. * i386-tbl.h: Regenerate.
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r--opcodes/i386-dis.c173
1 files changed, 126 insertions, 47 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index eeaf22e45e..eaaebf0073 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -108,6 +108,7 @@ static void OP_3DNowSuffix (int, int);
static void CMP_Fixup (int, int);
static void BadOp (void);
static void REP_Fixup (int, int);
+static void BND_Fixup (int, int);
static void HLE_Fixup1 (int, int);
static void HLE_Fixup2 (int, int);
static void HLE_Fixup3 (int, int);
@@ -222,8 +223,10 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
#define Bad_Opcode NULL, { { NULL, 0 } }
#define Eb { OP_E, b_mode }
+#define Ebnd { OP_E, bnd_mode }
#define EbS { OP_E, b_swap_mode }
#define Ev { OP_E, v_mode }
+#define Ev_bnd { OP_E, v_bnd_mode }
#define EvS { OP_E, v_swap_mode }
#define Ed { OP_E, d_mode }
#define Edq { OP_E, dq_mode }
@@ -246,6 +249,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
#define Mx { OP_M, x_mode }
#define Mxmm { OP_M, xmm_mode }
#define Gb { OP_G, b_mode }
+#define Gbnd { OP_G, bnd_mode }
#define Gv { OP_G, v_mode }
#define Gd { OP_G, d_mode }
#define Gdq { OP_G, dq_mode }
@@ -423,6 +427,8 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
#define Ebh3 { HLE_Fixup3, b_mode }
#define Evh3 { HLE_Fixup3, v_mode }
+#define BND { BND_Fixup, 0 }
+
#define cond_jump_flag { NULL, cond_jump_mode }
#define loop_jcxz_flag { NULL, loop_jcxz_mode }
@@ -485,10 +491,12 @@ enum
a_mode,
cond_jump_mode,
loop_jcxz_mode,
+ v_bnd_mode,
/* operand size depends on REX prefixes. */
dq_mode,
/* registers like dq_mode, memory like w_mode. */
dqw_mode,
+ bnd_mode,
/* 4- or 6-byte pointer operand */
f_mode,
const_1_mode,
@@ -672,6 +680,9 @@ enum
MOD_0F18_REG_5,
MOD_0F18_REG_6,
MOD_0F18_REG_7,
+ MOD_0F1A_PREFIX_0,
+ MOD_0F1B_PREFIX_0,
+ MOD_0F1B_PREFIX_1,
MOD_0F20,
MOD_0F21,
MOD_0F22,
@@ -766,6 +777,8 @@ enum
PREFIX_0F11,
PREFIX_0F12,
PREFIX_0F16,
+ PREFIX_0F1A,
+ PREFIX_0F1B,
PREFIX_0F2A,
PREFIX_0F2B,
PREFIX_0F2C,
@@ -1800,23 +1813,23 @@ static const struct dis386 dis386[] = {
{ "outs{b|}", { indirDXr, Xb } },
{ X86_64_TABLE (X86_64_6F) },
/* 70 */
- { "joH", { Jb, XX, cond_jump_flag } },
- { "jnoH", { Jb, XX, cond_jump_flag } },
- { "jbH", { Jb, XX, cond_jump_flag } },
- { "jaeH", { Jb, XX, cond_jump_flag } },
- { "jeH", { Jb, XX, cond_jump_flag } },
- { "jneH", { Jb, XX, cond_jump_flag } },
- { "jbeH", { Jb, XX, cond_jump_flag } },
- { "jaH", { Jb, XX, cond_jump_flag } },
+ { "joH", { Jb, BND, cond_jump_flag } },
+ { "jnoH", { Jb, BND, cond_jump_flag } },
+ { "jbH", { Jb, BND, cond_jump_flag } },
+ { "jaeH", { Jb, BND, cond_jump_flag } },
+ { "jeH", { Jb, BND, cond_jump_flag } },
+ { "jneH", { Jb, BND, cond_jump_flag } },
+ { "jbeH", { Jb, BND, cond_jump_flag } },
+ { "jaH", { Jb, BND, cond_jump_flag } },
/* 78 */
- { "jsH", { Jb, XX, cond_jump_flag } },
- { "jnsH", { Jb, XX, cond_jump_flag } },
- { "jpH", { Jb, XX, cond_jump_flag } },
- { "jnpH", { Jb, XX, cond_jump_flag } },
- { "jlH", { Jb, XX, cond_jump_flag } },
- { "jgeH", { Jb, XX, cond_jump_flag } },
- { "jleH", { Jb, XX, cond_jump_flag } },
- { "jgH", { Jb, XX, cond_jump_flag } },
+ { "jsH", { Jb, BND, cond_jump_flag } },
+ { "jnsH", { Jb, BND, cond_jump_flag } },
+ { "jpH", { Jb, BND, cond_jump_flag } },
+ { "jnpH", { Jb, BND, cond_jump_flag } },
+ { "jlH", { Jb, BND, cond_jump_flag } },
+ { "jgeH", { Jb, BND, cond_jump_flag } },
+ { "jleH", { Jb, BND, cond_jump_flag } },
+ { "jgH", { Jb, BND, cond_jump_flag } },
/* 80 */
{ REG_TABLE (REG_80) },
{ REG_TABLE (REG_81) },
@@ -1892,8 +1905,8 @@ static const struct dis386 dis386[] = {
/* c0 */
{ REG_TABLE (REG_C0) },
{ REG_TABLE (REG_C1) },
- { "retT", { Iw } },
- { "retT", { XX } },
+ { "retT", { Iw, BND } },
+ { "retT", { BND } },
{ X86_64_TABLE (X86_64_C4) },
{ X86_64_TABLE (X86_64_C5) },
{ REG_TABLE (REG_C6) },
@@ -1935,10 +1948,10 @@ static const struct dis386 dis386[] = {
{ "outB", { Ib, AL } },
{ "outG", { Ib, zAX } },
/* e8 */
- { "callT", { Jv } },
- { "jmpT", { Jv } },
+ { "callT", { Jv, BND } },
+ { "jmpT", { Jv, BND } },
{ X86_64_TABLE (X86_64_EA) },
- { "jmp", { Jb } },
+ { "jmp", { Jb, BND } },
{ "inB", { AL, indirDX } },
{ "inG", { zAX, indirDX } },
{ "outB", { indirDX, AL } },
@@ -1994,8 +2007,8 @@ static const struct dis386 dis386_twobyte[] = {
/* 18 */
{ REG_TABLE (REG_0F18) },
{ "nopQ", { Ev } },
- { "nopQ", { Ev } },
- { "nopQ", { Ev } },
+ { PREFIX_TABLE (PREFIX_0F1A) },
+ { PREFIX_TABLE (PREFIX_0F1B) },
{ "nopQ", { Ev } },
{ "nopQ", { Ev } },
{ "nopQ", { Ev } },
@@ -2109,23 +2122,23 @@ static const struct dis386 dis386_twobyte[] = {
{ PREFIX_TABLE (PREFIX_0F7E) },
{ PREFIX_TABLE (PREFIX_0F7F) },
/* 80 */
- { "joH", { Jv, XX, cond_jump_flag } },
- { "jnoH", { Jv, XX, cond_jump_flag } },
- { "jbH", { Jv, XX, cond_jump_flag } },
- { "jaeH", { Jv, XX, cond_jump_flag } },
- { "jeH", { Jv, XX, cond_jump_flag } },
- { "jneH", { Jv, XX, cond_jump_flag } },
- { "jbeH", { Jv, XX, cond_jump_flag } },
- { "jaH", { Jv, XX, cond_jump_flag } },
+ { "joH", { Jv, BND, cond_jump_flag } },
+ { "jnoH", { Jv, BND, cond_jump_flag } },
+ { "jbH", { Jv, BND, cond_jump_flag } },
+ { "jaeH", { Jv, BND, cond_jump_flag } },
+ { "jeH", { Jv, BND, cond_jump_flag } },
+ { "jneH", { Jv, BND, cond_jump_flag } },
+ { "jbeH", { Jv, BND, cond_jump_flag } },
+ { "jaH", { Jv, BND, cond_jump_flag } },
/* 88 */
- { "jsH", { Jv, XX, cond_jump_flag } },
- { "jnsH", { Jv, XX, cond_jump_flag } },
- { "jpH", { Jv, XX, cond_jump_flag } },
- { "jnpH", { Jv, XX, cond_jump_flag } },
- { "jlH", { Jv, XX, cond_jump_flag } },
- { "jgeH", { Jv, XX, cond_jump_flag } },
- { "jleH", { Jv, XX, cond_jump_flag } },
- { "jgH", { Jv, XX, cond_jump_flag } },
+ { "jsH", { Jv, BND, cond_jump_flag } },
+ { "jnsH", { Jv, BND, cond_jump_flag } },
+ { "jpH", { Jv, BND, cond_jump_flag } },
+ { "jnpH", { Jv, BND, cond_jump_flag } },
+ { "jlH", { Jv, BND, cond_jump_flag } },
+ { "jgeH", { Jv, BND, cond_jump_flag } },
+ { "jleH", { Jv, BND, cond_jump_flag } },
+ { "jgH", { Jv, BND, cond_jump_flag } },
/* 90 */
{ "seto", { Eb } },
{ "setno", { Eb } },
@@ -2366,6 +2379,7 @@ static const char **names_seg;
static const char *index64;
static const char *index32;
static const char **index16;
+static const char **names_bnd;
static const char *intel_names64[] = {
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
@@ -2433,6 +2447,14 @@ static const char *att_names_mm[] = {
"%mm4", "%mm5", "%mm6", "%mm7"
};
+static const char *intel_names_bnd[] = {
+ "bnd0", "bnd1", "bnd2", "bnd3"
+};
+
+static const char *att_names_bnd[] = {
+ "%bnd0", "%bnd1", "%bnd2", "%bnd3"
+};
+
static const char **names_xmm;
static const char *intel_names_xmm[] = {
"xmm0", "xmm1", "xmm2", "xmm3",
@@ -2623,9 +2645,9 @@ static const struct dis386 reg_table[][8] = {
{
{ "incQ", { Evh1 } },
{ "decQ", { Evh1 } },
- { "call{T|}", { indirEv } },
+ { "call{T|}", { indirEv, BND } },
{ "Jcall{T|}", { indirEp } },
- { "jmp{T|}", { indirEv } },
+ { "jmp{T|}", { indirEv, BND } },
{ "Jjmp{T|}", { indirEp } },
{ "pushU", { stackEv } },
{ Bad_Opcode },
@@ -2870,6 +2892,22 @@ static const struct dis386 prefix_table[][4] = {
{ "movhpd", { XM, EXq } },
},
+ /* PREFIX_0F1A */
+ {
+ { MOD_TABLE (MOD_0F1A_PREFIX_0) },
+ { "bndcl", { Gbnd, Ev_bnd } },
+ { "bndmov", { Gbnd, Ebnd } },
+ { "bndcu", { Gbnd, Ev_bnd } },
+ },
+
+ /* PREFIX_0F1B */
+ {
+ { MOD_TABLE (MOD_0F1B_PREFIX_0) },
+ { MOD_TABLE (MOD_0F1B_PREFIX_1) },
+ { "bndmov", { Ebnd, Gbnd } },
+ { "bndcn", { Gbnd, Ev_bnd } },
+ },
+
/* PREFIX_0F2A */
{
{ "cvtpi2ps", { XM, EMCq } },
@@ -10251,6 +10289,21 @@ static const struct dis386 mod_table[][2] = {
{ "nop/reserved", { Mb } },
},
{
+ /* MOD_0F1A_PREFIX_0 */
+ { "bndldx", { Gbnd, Ev_bnd } },
+ { "nopQ", { Ev } },
+ },
+ {
+ /* MOD_0F1B_PREFIX_0 */
+ { "bndstx", { Ev_bnd, Gbnd } },
+ { "nopQ", { Ev } },
+ },
+ {
+ /* MOD_0F1B_PREFIX_1 */
+ { "bndmk", { Gbnd, Ev_bnd } },
+ { "nopQ", { Ev } },
+ },
+ {
/* MOD_0F20 */
{ Bad_Opcode },
{ "movZ", { Rm, Cm } },
@@ -10655,6 +10708,7 @@ static const struct dis386 rm_table[][8] = {
#define REP_PREFIX (0xf3 | 0x100)
#define XACQUIRE_PREFIX (0xf2 | 0x200)
#define XRELEASE_PREFIX (0xf3 | 0x400)
+#define BND_PREFIX (0xf2 | 0x400)
static int
ckprefix (void)
@@ -10892,6 +10946,8 @@ prefix_name (int pref, int sizeflag)
return "xacquire";
case XRELEASE_PREFIX:
return "xrelease";
+ case BND_PREFIX:
+ return "bnd";
default:
return NULL;
}
@@ -11397,6 +11453,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
names8rex = intel_names8rex;
names_seg = intel_names_seg;
names_mm = intel_names_mm;
+ names_bnd = intel_names_bnd;
names_xmm = intel_names_xmm;
names_ymm = intel_names_ymm;
index64 = intel_index64;
@@ -11416,6 +11473,7 @@ print_insn (bfd_vma pc, disassemble_info *info)
names8rex = att_names8rex;
names_seg = att_names_seg;
names_mm = att_names_mm;
+ names_bnd = att_names_bnd;
names_xmm = att_names_xmm;
names_ymm = att_names_ymm;
index64 = att_index64;
@@ -12766,6 +12824,7 @@ intel_operand_size (int bytemode, int sizeflag)
}
/* FALLTHRU */
case v_mode:
+ case v_bnd_mode:
case v_swap_mode:
case dq_mode:
USED_REX (REX_W);
@@ -13035,6 +13094,9 @@ OP_E_register (int bytemode, int sizeflag)
case m_mode:
names = address_mode == mode_64bit ? names64 : names32;
break;
+ case bnd_mode:
+ names = names_bnd;
+ break;
case stack_v_mode:
if (address_mode == mode_64bit && ((sizeflag & DFLAG) || (rex & REX_W)))
{
@@ -13044,6 +13106,7 @@ OP_E_register (int bytemode, int sizeflag)
bytemode = v_mode;
/* FALLTHRU */
case v_mode:
+ case v_bnd_mode:
case v_swap_mode:
case dq_mode:
case dqb_mode:
@@ -13095,6 +13158,9 @@ OP_E_memory (int bytemode, int sizeflag)
int base, rbase;
int vindex = 0;
int scale = 0;
+ int addr32flag = !((sizeflag & AFLAG)
+ || bytemode == v_bnd_mode
+ || bytemode == bnd_mode);
const char **indexes64 = names64;
const char **indexes32 = names32;
@@ -13190,7 +13256,9 @@ OP_E_memory (int bytemode, int sizeflag)
}
}
- if (havebase || haveindex || riprel)
+ if ((havebase || haveindex || riprel)
+ && (bytemode != v_bnd_mode)
+ && (bytemode != bnd_mode))
used_prefixes |= PREFIX_ADDR;
if (havedisp || (intel_syntax && riprel))
@@ -13203,7 +13271,7 @@ OP_E_memory (int bytemode, int sizeflag)
}
*obufp = '\0';
if (havebase)
- oappend (address_mode == mode_64bit && (sizeflag & AFLAG)
+ oappend (address_mode == mode_64bit && !addr32flag
? names64[rbase] : names32[rbase]);
if (havesib)
{
@@ -13220,12 +13288,10 @@ OP_E_memory (int bytemode, int sizeflag)
*obufp = '\0';
}
if (haveindex)
- oappend (address_mode == mode_64bit
- && (sizeflag & AFLAG)
+ oappend (address_mode == mode_64bit && !addr32flag
? indexes64[vindex] : indexes32[vindex]);
else
- oappend (address_mode == mode_64bit
- && (sizeflag & AFLAG)
+ oappend (address_mode == mode_64bit && !addr32flag
? index64 : index32);
*obufp++ = scale_char;
@@ -13391,6 +13457,9 @@ OP_G (int bytemode, int sizeflag)
case q_mode:
oappend (names64[modrm.reg + add]);
break;
+ case bnd_mode:
+ oappend (names_bnd[modrm.reg]);
+ break;
case v_mode:
case dq_mode:
case dqb_mode:
@@ -14521,6 +14590,16 @@ REP_Fixup (int bytemode, int sizeflag)
}
}
+/* For BND-prefixed instructions 0xF2 prefix should be displayed as
+ "bnd". */
+
+static void
+BND_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED)
+{
+ if (prefixes & PREFIX_REPNZ)
+ all_prefixes[last_repnz_prefix] = BND_PREFIX;
+}
+
/* Similar to OP_E. But the 0xf2/0xf3 prefixes should be displayed as
"xacquire"/"xrelease" for memory operand if there is a LOCK prefix.
*/