x86-64 disassembler support.
Change-Id: I0ae39ae1ffdae2500ff368354f9e4702445176f0
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc
index d86ba7b..ab0ee52 100644
--- a/disassembler/disassembler_x86.cc
+++ b/disassembler/disassembler_x86.cc
@@ -25,8 +25,6 @@
namespace art {
namespace x86 {
-DisassemblerX86::DisassemblerX86() {}
-
size_t DisassemblerX86::Dump(std::ostream& os, const uint8_t* begin) {
return DumpInstruction(os, begin);
}
@@ -41,16 +39,21 @@
static const char* gReg8Names[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
static const char* gReg16Names[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
static const char* gReg32Names[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
+static const char* gReg64Names[] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
-static void DumpReg0(std::ostream& os, uint8_t /*rex*/, size_t reg,
+static void DumpReg0(std::ostream& os, uint8_t rex, size_t reg,
bool byte_operand, uint8_t size_override) {
- DCHECK_LT(reg, 8u);
- // TODO: combine rex into size
- size_t size = byte_operand ? 1 : (size_override == 0x66 ? 2 : 4);
+ DCHECK_LT(reg, (rex == 0) ? 8u : 16u);
+ bool rex_w = (rex & 0b1000) != 0;
+ size_t size = byte_operand ? 1 : (size_override == 0x66 ? 2 : (rex_w ? 8 :4));
switch (size) {
case 1: os << gReg8Names[reg]; break;
case 2: os << gReg16Names[reg]; break;
case 4: os << gReg32Names[reg]; break;
+ case 8: os << gReg64Names[reg]; break;
default: LOG(FATAL) << "unexpected size " << size;
}
}
@@ -59,7 +62,8 @@
static void DumpReg(std::ostream& os, uint8_t rex, uint8_t reg,
bool byte_operand, uint8_t size_override, RegFile reg_file) {
- size_t reg_num = reg; // TODO: combine with REX.R on 64bit
+ bool rex_r = (rex & 0b0100) != 0;
+ size_t reg_num = rex_r ? (reg + 8) : reg;
if (reg_file == GPR) {
DumpReg0(os, rex, reg_num, byte_operand, size_override);
} else if (reg_file == SSE) {
@@ -70,12 +74,14 @@
}
static void DumpBaseReg(std::ostream& os, uint8_t rex, uint8_t reg) {
- size_t reg_num = reg; // TODO: combine with REX.B on 64bit
+ bool rex_b = (rex & 0b0001) != 0;
+ size_t reg_num = rex_b ? (reg + 8) : reg;
DumpReg0(os, rex, reg_num, false, 0);
}
static void DumpIndexReg(std::ostream& os, uint8_t rex, uint8_t reg) {
- int reg_num = reg; // TODO: combine with REX.X on 64bit
+ bool rex_x = (rex & 0b0010) != 0;
+ uint8_t reg_num = rex_x ? (reg + 8) : reg;
DumpReg0(os, rex, reg_num, false, 0);
}
@@ -138,7 +144,7 @@
instr++;
}
} while (have_prefixes);
- uint8_t rex = (*instr >= 0x40 && *instr <= 0x4F) ? *instr : 0;
+ uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0;
bool has_modrm = false;
bool reg_is_opcode = false;
size_t immediate_bytes = 0;