Fixes to enable TrackLiveTemps optimization on x86.
- Created new kRegRegStore instruction class for Movdrx, where the
source is first, and the destination is second.
- Reverted neg_float and neg_double implementation to prevent confusion
of register types when optimizations are performed.
- Swapped order of loads for wide values to prevent base pointer from
being clobbered when the base pointer equals the low destination reg.
- Implemented opRegCopyWide for general purpose reg source to floating
point reg destination and vice versa.
- Added more opcode coverage to x86 disassembler.
Change-Id: I4e58eec91742cc51333003fa5a678ba5b23eb575
diff --git a/src/disassembler_x86.cc b/src/disassembler_x86.cc
index 4aff822..969feb8 100644
--- a/src/disassembler_x86.cc
+++ b/src/disassembler_x86.cc
@@ -225,10 +225,13 @@
case 0x10: case 0x11:
if (prefix[0] == 0xF2) {
opcode << "movsd";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF3) {
opcode << "movss";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[2] == 0x66) {
opcode << "movupd";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
opcode << "movups";
}
@@ -237,6 +240,71 @@
load = *instr == 0x10;
store = !load;
break;
+ case 0x2A:
+ if (prefix[2] == 0x66) {
+ opcode << "cvtpi2pd";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF2) {
+ opcode << "cvtsi2sd";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF3) {
+ opcode << "cvtsi2ss";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ opcode << "cvtpi2ps";
+ }
+ load = true;
+ has_modrm = true;
+ dst_reg_file = SSE;
+ break;
+ case 0x2C:
+ if (prefix[2] == 0x66) {
+ opcode << "cvttpd2pi";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF2) {
+ opcode << "cvttsd2si";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF3) {
+ opcode << "cvttss2si";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ opcode << "cvttps2pi";
+ }
+ load = true;
+ has_modrm = true;
+ src_reg_file = SSE;
+ break;
+ case 0x2D:
+ if (prefix[2] == 0x66) {
+ opcode << "cvtpd2pi";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF2) {
+ opcode << "cvtsd2si";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else if (prefix[0] == 0xF3) {
+ opcode << "cvtss2si";
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ opcode << "cvtps2pi";
+ }
+ load = true;
+ has_modrm = true;
+ src_reg_file = SSE;
+ break;
+ case 0x2E:
+ opcode << "u";
+ // FALLTHROUGH
+ case 0x2F:
+ if (prefix[2] == 0x66) {
+ opcode << "comisd";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ opcode << "comiss";
+ }
+ has_modrm = true;
+ load = true;
+ src_reg_file = dst_reg_file = SSE;
+ break;
case 0x38: // 3 byte extended opcode
opcode << StringPrintf("unknown opcode '0F 38 %02X'", *instr);
break;
@@ -264,13 +332,13 @@
}
if (prefix[2] == 0x66) {
opcode << "pd";
- prefix[2] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF2) {
opcode << "sd";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF3) {
opcode << "ss";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
opcode << "ps";
}
@@ -282,13 +350,13 @@
case 0x5A:
if (prefix[2] == 0x66) {
opcode << "cvtpd2ps";
- prefix[2] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF2) {
opcode << "cvtsd2ss";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF3) {
opcode << "cvtss2sd";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
opcode << "cvtps2pd";
}
@@ -299,12 +367,12 @@
case 0x5B:
if (prefix[2] == 0x66) {
opcode << "cvtps2dq";
- prefix[2] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF2) {
opcode << "bad opcode F2 0F 5B";
} else if (prefix[0] == 0xF3) {
opcode << "cvttps2dq";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
opcode << "cvtdq2ps";
}
@@ -315,12 +383,11 @@
case 0x6E:
if (prefix[2] == 0x66) {
dst_reg_file = SSE;
- opcode << "movq";
- prefix[2] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
dst_reg_file = MMX;
- opcode << "movd";
}
+ opcode << "movd";
load = true;
has_modrm = true;
break;
@@ -328,10 +395,11 @@
if (prefix[2] == 0x66) {
dst_reg_file = SSE;
opcode << "movdqa";
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
} else if (prefix[0] == 0xF3) {
dst_reg_file = SSE;
opcode << "movdqu";
- prefix[0] = 0; // clear prefix now its served its purpose as part of the opcode
+ prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode
} else {
dst_reg_file = MMX;
opcode << "movq";
@@ -339,6 +407,59 @@
load = true;
has_modrm = true;
break;
+ case 0x71:
+ if (prefix[2] == 0x66) {
+ dst_reg_file = SSE;
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ dst_reg_file = MMX;
+ }
+ static const char* x71_opcodes[] = {"unknown-71", "unknown-71", "psrlw", "unknown-71", "psraw", "unknown-71", "psllw", "unknown-71"};
+ modrm_opcodes = x71_opcodes;
+ reg_is_opcode = true;
+ has_modrm = true;
+ store = true;
+ immediate_bytes = 1;
+ break;
+ case 0x72:
+ if (prefix[2] == 0x66) {
+ dst_reg_file = SSE;
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ dst_reg_file = MMX;
+ }
+ static const char* x72_opcodes[] = {"unknown-72", "unknown-72", "psrld", "unknown-72", "psrad", "unknown-72", "pslld", "unknown-72"};
+ modrm_opcodes = x72_opcodes;
+ reg_is_opcode = true;
+ has_modrm = true;
+ store = true;
+ immediate_bytes = 1;
+ break;
+ case 0x73:
+ if (prefix[2] == 0x66) {
+ dst_reg_file = SSE;
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ dst_reg_file = MMX;
+ }
+ static const char* x73_opcodes[] = {"unknown-73", "unknown-73", "psrlq", "unknown-73", "unknown-73", "unknown-73", "psllq", "unknown-73"};
+ modrm_opcodes = x73_opcodes;
+ reg_is_opcode = true;
+ has_modrm = true;
+ store = true;
+ immediate_bytes = 1;
+ break;
+ case 0x7E:
+ if (prefix[2] == 0x66) {
+ src_reg_file = SSE;
+ prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode
+ } else {
+ src_reg_file = MMX;
+ }
+ opcode << "movd";
+ has_modrm = true;
+ store = true;
+ break;
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
opcode << "j" << condition_codes[*instr & 0xF];
@@ -510,7 +631,7 @@
}
}
if (ax) {
- args << ", ";
+ // If this opcode implicitly uses ax, ax is always the first arg.
DumpReg(args, rex, 0 /* EAX */, byte_operand, prefix[2], GPR);
}
if (cx) {