diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2015-05-15 09:47:39 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2015-05-15 09:48:10 -0700 |
commit | 5db04b0965e3e7a9344a93de22caae3c111de2cc (patch) | |
tree | 40942f68d18dc161c6512acad6f408d1e55ce18b /opcodes/i386-dis.c | |
parent | 0e602686df5677fee06cbd1718b4a7aa5379cd2a (diff) | |
download | gdb-5db04b0965e3e7a9344a93de22caae3c111de2cc.zip gdb-5db04b0965e3e7a9344a93de22caae3c111de2cc.tar.gz gdb-5db04b0965e3e7a9344a93de22caae3c111de2cc.tar.bz2 |
Support AMD64/Intel ISAs in assembler/disassembler
AMD64 spec and Intel64 spec differ in direct unconditional branches in
64-bit mode. AMD64 supports direct unconditional branches with 16-bit
offset via the data size prefix, which truncates RIP to 16 bits, while
the data size prefix is ignored by Intel64.
This patch adds -mamd64/-mintel64 option to x86-64 assembler and
-Mamd64/-Mintel64 option to x86-64 disassembler. The most permissive
ISA, which is AMD64, is the default.
GDB can add an option, similar to
(gdb) help set disassembly-flavor
Set the disassembly flavor.
The valid values are "att" and "intel", and the default value is "att".
to select which ISA to disassemble.
binutils/
PR binutis/18386
* doc/binutils.texi: Document -Mamd64 and -Mintel64.
gas/
PR binutis/18386
* config/tc-i386.c (OPTION_MAMD64): New.
(OPTION_MINTEL64): Likewise.
(md_longopts): Add -mamd64 and -mintel64.
(md_parse_option): Handle OPTION_MAMD64 and OPTION_MINTEL64.
(md_show_usage): Add -mamd64 and -mintel64.
* doc/c-i386.texi: Document -mamd64 and -mintel64.
gas/testsuite/
PR binutis/18386
* gas/i386/i386.exp: Run x86-64-branch-2 and x86-64-branch-3.
* gas/i386/x86-64-branch.d: Also pass -Mintel64 to objdump.
* gas/i386/ilp32/x86-64-branch.d: Likewise.
* gas/i386/x86-64-branch-2.d: New file.
* gas/i386/x86-64-branch-2.s: Likewise.
* gas/i386/x86-64-branch-3.l: Likewise.
* gas/i386/x86-64-branch-3.s: Likewise.
ld/testsuite/
PR binutis/18386
* ld-x86-64/tlsgdesc.dd: Also pass -Mintel64 to objdump.
* ld-x86-64/tlspic.dd: Likewise.
* ld-x86-64/x86-64.exp (x86_64tests): Also pass -Mintel64 to
objdump for tlspic.dd and tlsgdesc.dd.
opcodes/
PR binutis/18386
* i386-dis.c: Add comments for '@'.
(x86_64_table): Use '@' on call/jmp for X86_64_E8/X86_64_E9.
(enum x86_64_isa): New.
(isa64): Likewise.
(print_i386_disassembler_options): Add amd64 and intel64.
(print_insn): Handle amd64 and intel64.
(putop): Handle '@'.
(OP_J): Don't ignore the operand size prefix for AMD64 in 64-bit.
* i386-gen.c (cpu_flags): Add CpuAMD64 and CpuIntel64.
* i386-opc.h (AMD64): New.
(CpuIntel64): Likewise.
(i386_cpu_flags): Add cpuamd64 and cpuintel64.
* i386-opc.tbl: Add direct call/jmp with Disp16|Disp32 for AMD64.
Mark direct call/jmp without Disp16|Disp32 as Intel64.
* i386-init.h: Regenerated.
* i386-tbl.h: Likewise.
Diffstat (limited to 'opcodes/i386-dis.c')
-rw-r--r-- | opcodes/i386-dis.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/opcodes/i386-dis.c b/opcodes/i386-dis.c index 941f699..76f3ead 100644 --- a/opcodes/i386-dis.c +++ b/opcodes/i386-dis.c @@ -2418,6 +2418,8 @@ struct dis386 { '%' => add 1 upper case letter to the macro. '^' => print 'w' or 'l' depending on operand size prefix or suffix_always is true (lcall/ljmp). + '@' => print 'q' for Intel64 ISA, 'w' or 'q' for AMD64 ISA depending + on operand size prefix. 2 upper case letter macros: "XY" => print 'x' or 'y' if suffix_always is true or no register @@ -6844,13 +6846,13 @@ static const struct dis386 x86_64_table[][2] = { /* X86_64_E8 */ { { "callP", { Jv, BND }, 0 }, - { "callq", { Jv, BND }, 0 } + { "call@", { Jv, BND }, 0 } }, /* X86_64_E9 */ { { "jmpP", { Jv, BND }, 0 }, - { "jmpq", { Jv, BND }, 0 } + { "jmp@", { Jv, BND }, 0 } }, /* X86_64_EA */ @@ -12342,6 +12344,14 @@ static char close_char; static char separator_char; static char scale_char; +enum x86_64_isa +{ + amd64 = 0, + intel64 +}; + +static enum x86_64_isa isa64; + /* Here for backwards compatibility. When gdb stops using print_insn_i386_att and print_insn_i386_intel these functions can disappear, and print_insn_i386 be merged into print_insn. */ @@ -12391,6 +12401,8 @@ with the -M switch (multiple options should be separated by commas):\n")); fprintf (stream, _(" data32 Assume 32bit data size\n")); fprintf (stream, _(" data16 Assume 16bit data size\n")); fprintf (stream, _(" suffix Always display instruction suffix in AT&T syntax\n")); + fprintf (stream, _(" amd64 Display instruction in AMD64 ISA\n")); + fprintf (stream, _(" intel64 Display instruction in Intel64 ISA\n")); } /* Bad opcode. */ @@ -12874,7 +12886,11 @@ print_insn (bfd_vma pc, disassemble_info *info) for (p = info->disassembler_options; p != NULL; ) { - if (CONST_STRNEQ (p, "x86-64")) + if (CONST_STRNEQ (p, "amd64")) + isa64 = amd64; + else if (CONST_STRNEQ (p, "intel64")) + isa64 = intel64; + else if (CONST_STRNEQ (p, "x86-64")) { address_mode = mode_64bit; priv.orig_sizeflag = AFLAG | DFLAG; @@ -14208,6 +14224,20 @@ case_S: used_prefixes |= (prefixes & PREFIX_DATA); } break; + case '@': + if (intel_syntax) + break; + if (address_mode == mode_64bit + && (isa64 == intel64 + || ((sizeflag & DFLAG) || (rex & REX_W)))) + *obufp++ = 'q'; + else if ((prefixes & PREFIX_DATA)) + { + if (!(sizeflag & DFLAG)) + *obufp++ = 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + break; } alt = 0; } @@ -15724,7 +15754,11 @@ OP_J (int bytemode, int sizeflag) disp -= 0x100; break; case v_mode: - if (address_mode == mode_64bit || (sizeflag & DFLAG)) + if (isa64 == amd64) + USED_REX (REX_W); + if ((sizeflag & DFLAG) + || (address_mode == mode_64bit + && (isa64 != amd64 || (rex & REX_W)))) disp = get32s (); else { @@ -15740,7 +15774,8 @@ OP_J (int bytemode, int sizeflag) segment = ((start_pc + codep - start_codep) & ~((bfd_vma) 0xffff)); } - if (address_mode != mode_64bit) + if (address_mode != mode_64bit + || (isa64 == amd64 && !(rex & REX_W))) used_prefixes |= (prefixes & PREFIX_DATA); break; default: |