summaryrefslogtreecommitdiffstats
path: root/disassembler/disassembler_x86.cc
diff options
context:
space:
mode:
authorVladimir Kostyukov <vladimir.kostyukov@intel.com>2014-06-30 15:44:12 +0700
committerAndreas Gampe <agampe@google.com>2014-07-03 16:23:28 -0700
commite443a8063518fb1c5229afa3081b9fd1f6d33b16 (patch)
treea4e64dea6743e787e77369241ec14f3969c43c0d /disassembler/disassembler_x86.cc
parentca8ff32bbb1f034b3b1f25de1fe20a9015bc87ec (diff)
downloadart-e443a8063518fb1c5229afa3081b9fd1f6d33b16.zip
art-e443a8063518fb1c5229afa3081b9fd1f6d33b16.tar.gz
art-e443a8063518fb1c5229afa3081b9fd1f6d33b16.tar.bz2
ART: FF-opcodes are target-specific
Some of the FF-opcodes' (i.e., push, call, jmp) register names depend on the the target (32-bit vs 64-bit). This patch makes such opcodes target-specific. Change-Id: I4fa0b7ee5310e14f4022850ac2160c21be5d1c99 Signed-off-by: Vladimir Kostyukov <vladimir.kostyukov@intel.com>
Diffstat (limited to 'disassembler/disassembler_x86.cc')
-rw-r--r--disassembler/disassembler_x86.cc23
1 files changed, 15 insertions, 8 deletions
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index 1021789..14a5b5f 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -1012,11 +1012,18 @@ DISASSEMBLER_ENTRY(cmp,
immediate_bytes = ((instr[1] & 0x38) == 0) ? 1 : 0;
break;
case 0xFF:
- static const char* ff_opcodes[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push", "unknown-ff"};
- modrm_opcodes = ff_opcodes;
- has_modrm = true;
- reg_is_opcode = true;
- load = true;
+ {
+ static const char* ff_opcodes[] = {"inc", "dec", "call", "call", "jmp", "jmp", "push", "unknown-ff"};
+ modrm_opcodes = ff_opcodes;
+ has_modrm = true;
+ reg_is_opcode = true;
+ load = true;
+ const uint8_t opcode_digit = (instr[1] >> 3) & 7;
+ // 'call', 'jmp' and 'push' are target specific instructions
+ if (opcode_digit == 2 || opcode_digit == 4 || opcode_digit == 6) {
+ target_specific = true;
+ }
+ }
break;
default:
opcode << StringPrintf("unknown opcode '%02X'", *instr);
@@ -1026,10 +1033,10 @@ DISASSEMBLER_ENTRY(cmp,
// We force the REX prefix to be available for 64-bit target
// in order to dump addr (base/index) registers correctly.
uint8_t rex64 = supports_rex_ ? (rex | 0x40) : rex;
+ // REX.W should be forced for 64-target and target-specific instructions (i.e., push or pop).
+ uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex;
if (reg_in_opcode) {
DCHECK(!has_modrm);
- // REX.W should be forced for 64-target and target-specific instructions (i.e., push or pop).
- uint8_t rex_w = (supports_rex_ && target_specific) ? (rex | 0x48) : rex;
DumpOpcodeReg(args, rex_w, *instr & 0x7);
}
instr++;
@@ -1090,7 +1097,7 @@ DISASSEMBLER_ENTRY(cmp,
} else {
if (mod == 3) {
if (!no_ops) {
- DumpRmReg(address, rex, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file);
+ DumpRmReg(address, rex_w, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file);
}
} else {
address << "[";