diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2016-06-03 15:55:29 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2016-06-03 15:55:29 -0700 |
commit | 07f5af7d3c635234284e7a0f7dd7a410b1628b8b (patch) | |
tree | a37189780861055d8db8e3e7b624f9fd25288b2d /opcodes/i386-dis.c | |
parent | 1aa70332cab048c3a7bb6dd7dc8b7a1b686ea657 (diff) | |
download | binutils-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.c | 32 |
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))) { |