aboutsummaryrefslogtreecommitdiff
path: root/opcodes/i386-dis.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-06-03 15:55:29 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-06-03 15:55:29 -0700
commit07f5af7d3c635234284e7a0f7dd7a410b1628b8b (patch)
treea37189780861055d8db8e3e7b624f9fd25288b2d /opcodes/i386-dis.c
parent1aa70332cab048c3a7bb6dd7dc8b7a1b686ea657 (diff)
downloadbinutils-07f5af7d3c635234284e7a0f7dd7a410b1628b8b.zip
binutils-07f5af7d3c635234284e7a0f7dd7a410b1628b8b.tar.gz
binutils-07f5af7d3c635234284e7a0f7dd7a410b1628b8b.tar.bz2
Handle indirect branches for AMD64 and Intel64
AMD64 spec and Intel64 spec differ in indirect branches in 64-bit mode. AMD64 supports indirect branches with 16-bit address via the data size prefix while the data size prefix is ignored by Intel64. gas/ PR binutis/18386 * testsuite/gas/i386/i386.exp: Run x86-64-branch-4. * testsuite/gas/i386/x86-64-branch.d: Updated. * testsuite/gas/i386/ilp32/x86-64-branch.d: Likewise. * testsuite/gas/i386/x86-64-branch-4.l: New file. * testsuite/gas/i386/x86-64-branch-4.s: Likewise. opcodes/ PR binutis/18386 * i386-dis.c (indirEv): Replace stack_v_mode with indir_v_mode. (indir_v_mode): New. Add comments for '&'. (reg_table): Replace "{T|}" with "{&|}" on call and jmp. (putop): Handle '&'. (intel_operand_size): Handle indir_v_mode. (OP_E_register): Likewise. * i386-opc.tbl: Mark 64-bit indirect call/jmp as AMD64. Add 64-bit indirect call/jmp for AMD64. * i386-tbl.h: Regenerated
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r--opcodes/i386-dis.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c
index b0ade38..da20d36 100644
--- a/opcodes/i386-dis.c
+++ b/opcodes/i386-dis.c
@@ -258,7 +258,7 @@ fetch_data (struct disassemble_info *info, bfd_byte *addr)
#define Edw { OP_E, dw_mode }
#define Edqd { OP_E, dqd_mode }
#define Eq { OP_E, q_mode }
-#define indirEv { OP_indirE, stack_v_mode }
+#define indirEv { OP_indirE, indir_v_mode }
#define indirEp { OP_indirE, f_mode }
#define stackEv { OP_E, stack_v_mode }
#define Em { OP_E, m_mode }
@@ -561,6 +561,8 @@ enum
/* 4- or 6-byte pointer operand */
f_mode,
const_1_mode,
+ /* v_mode for indirect branch opcodes. */
+ indir_v_mode,
/* v_mode for stack-related opcodes. */
stack_v_mode,
/* non-quad operand size depends on prefixes */
@@ -2483,6 +2485,9 @@ struct dis386 {
suffix_always is true (lcall/ljmp).
'@' => print 'q' for Intel64 ISA, 'w' or 'q' for AMD64 ISA depending
on operand size prefix.
+ '&' => print 'q' in 64bit mode for Intel64 ISA or if instruction
+ has no operand size prefix for AMD64 ISA, behave as 'P'
+ otherwise
2 upper case letter macros:
"XY" => print 'x' or 'y' if suffix_always is true or no register
@@ -3531,9 +3536,9 @@ static const struct dis386 reg_table[][8] = {
{
{ "incQ", { Evh1 }, 0 },
{ "decQ", { Evh1 }, 0 },
- { "call{T|}", { indirEv, BND }, 0 },
+ { "call{&|}", { indirEv, BND }, 0 },
{ MOD_TABLE (MOD_FF_REG_3) },
- { "jmp{T|}", { indirEv, BND }, 0 },
+ { "jmp{&|}", { indirEv, BND }, 0 },
{ MOD_TABLE (MOD_FF_REG_5) },
{ "pushU", { stackEv }, 0 },
{ Bad_Opcode },
@@ -14296,6 +14301,15 @@ case_L:
if (!(rex & REX_W))
used_prefixes |= (prefixes & PREFIX_DATA);
break;
+ case '&':
+ if (!intel_syntax
+ && address_mode == mode_64bit
+ && isa64 == intel64)
+ {
+ *obufp++ = 'q';
+ break;
+ }
+ /* Fall through. */
case 'T':
if (!intel_syntax
&& address_mode == mode_64bit
@@ -14816,6 +14830,12 @@ intel_operand_size (int bytemode, int sizeflag)
case dqw_swap_mode:
oappend ("WORD PTR ");
break;
+ case indir_v_mode:
+ if (address_mode == mode_64bit && isa64 == intel64)
+ {
+ oappend ("QWORD PTR ");
+ break;
+ }
case stack_v_mode:
if (address_mode == mode_64bit && ((sizeflag & DFLAG) || (rex & REX_W)))
{
@@ -15193,6 +15213,12 @@ OP_E_register (int bytemode, int sizeflag)
case bnd_mode:
names = names_bnd;
break;
+ case indir_v_mode:
+ if (address_mode == mode_64bit && isa64 == intel64)
+ {
+ names = names64;
+ break;
+ }
case stack_v_mode:
if (address_mode == mode_64bit && ((sizeflag & DFLAG) || (rex & REX_W)))
{