Numerous fixes to enable PromoteRegs, though it's still broken.
- Fixed ThrowNullPointerFromCode launchpad to load the array length
directly into the necessary arg reg without clobbering the array
pointer, since that value may be live afterwards.
- genArrayPut use a temporary reg for bytes if the source reg is >= 4,
since x86 can't express this.
- Fixed the order that core regs are spilled and unspilled.
- Correctly emit instructions when base == rBP and disp == 0.
- Added checks to the compiler to ensure that byte opcodes aren't used
on registers that can't be byte accessed.
- Fixed generation of a number of ops which use byte opcodes, including
floating point comparison, int-to-byte, and and-int/lit16.
- Added rBP, rSI, and rDI to spill registers for the x86 jni compiler.
- Various fixes and additions to the x86 disassembler.
Change-Id: I365fe7dec5cc64d181248fd58e90789f100b45e7
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index 969feb8..d45d641 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -36,8 +36,8 @@
}
static const char* gReg8Names[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
-static const char* gReg16Names[] = { "ax", "cx", "dx", "bx", "sp", "bp", "di", "si" };
-static const char* gReg32Names[] = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "edi", "esi" };
+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 void DumpReg0(std::ostream& os, uint8_t /*rex*/, size_t reg,
bool byte_operand, uint8_t size_override) {
@@ -147,6 +147,7 @@
bool ax = false; // implicit use of ax
bool cx = false; // implicit use of cx
bool reg_in_opcode = false; // low 3-bits of opcode encode register parameter
+ bool no_ops = false;
RegFile src_reg_file = GPR;
RegFile dst_reg_file = GPR;
switch (*instr) {
@@ -473,6 +474,43 @@
has_modrm = true;
store = true;
break;
+ case 0xAE:
+ if (prefix[0] == 0xF3) {
+ static const char* xAE_opcodes[] = {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE"};
+ modrm_opcodes = xAE_opcodes;
+ reg_is_opcode = true;
+ has_modrm = true;
+ uint8_t reg_or_opcode = (instr[1] >> 3) & 7;
+ switch (reg_or_opcode) {
+ case 0:
+ prefix[1] = kFs;
+ load = true;
+ break;
+ case 1:
+ prefix[1] = kGs;
+ load = true;
+ break;
+ case 2:
+ prefix[1] = kFs;
+ store = true;
+ break;
+ case 3:
+ prefix[1] = kGs;
+ store = true;
+ break;
+ default:
+ load = true;
+ break;
+ }
+ } else {
+ static const char* xAE_opcodes[] = {"unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "unknown-AE", "lfence", "mfence", "sfence"};
+ modrm_opcodes = xAE_opcodes;
+ reg_is_opcode = true;
+ has_modrm = true;
+ load = true;
+ no_ops = true;
+ }
+ break;
case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; break;
case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break;
default:
@@ -489,11 +527,23 @@
byte_operand = (*instr & 1) == 0;
immediate_bytes = *instr == 0x81 ? 4 : 1;
break;
+ case 0x84: case 0x85:
+ opcode << "test";
+ has_modrm = true;
+ load = true;
+ byte_operand = (*instr & 1) == 0;
+ break;
case 0x8D:
opcode << "lea";
has_modrm = true;
load = true;
break;
+ case 0x8F:
+ opcode << "pop";
+ has_modrm = true;
+ reg_is_opcode = true;
+ store = true;
+ break;
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
opcode << "mov";
immediate_bytes = 1;
@@ -595,7 +645,9 @@
address << "]";
} else {
if (mod == 3) {
- DumpReg(address, rex, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file);
+ if (!no_ops) {
+ DumpReg(address, rex, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file);
+ }
} else {
address << "[";
DumpBaseReg(address, rex, rm);