diff options
Diffstat (limited to 'disassembler')
| -rw-r--r-- | disassembler/disassembler_x86.cc | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/disassembler/disassembler_x86.cc b/disassembler/disassembler_x86.cc index 14a5b5f2bf..a6f9a8a22b 100644 --- a/disassembler/disassembler_x86.cc +++ b/disassembler/disassembler_x86.cc @@ -201,7 +201,8 @@ size_t DisassemblerX86::DumpInstruction(std::ostream& os, const uint8_t* instr) std::ostringstream opcode; bool store = false; // stores to memory (ie rm is on the left) bool load = false; // loads from memory (ie rm is on the right) - bool byte_operand = false; + bool byte_operand = false; // true when the opcode is dealing with byte operands + bool byte_second_operand = false; // true when the source operand is a byte register but the target register isn't (ie movsxb/movzxb). bool target_specific = false; // register name depends on target (64 vs 32 bits). bool ax = false; // implicit use of ax bool cx = false; // implicit use of cx @@ -426,6 +427,20 @@ DISASSEMBLER_ENTRY(cmp, instr++; if (prefix[2] == 0x66) { switch (*instr) { + case 0x01: + opcode << "phaddw"; + prefix[2] = 0; + has_modrm = true; + load = true; + src_reg_file = dst_reg_file = SSE; + break; + case 0x02: + opcode << "phaddd"; + prefix[2] = 0; + has_modrm = true; + load = true; + src_reg_file = dst_reg_file = SSE; + break; case 0x40: opcode << "pmulld"; prefix[2] = 0; @@ -449,7 +464,7 @@ DISASSEMBLER_ENTRY(cmp, prefix[2] = 0; has_modrm = true; store = true; - dst_reg_file = SSE; + src_reg_file = SSE; immediate_bytes = 1; break; case 0x16: @@ -457,7 +472,7 @@ DISASSEMBLER_ENTRY(cmp, prefix[2] = 0; has_modrm = true; store = true; - dst_reg_file = SSE; + src_reg_file = SSE; immediate_bytes = 1; break; default: @@ -641,6 +656,21 @@ DISASSEMBLER_ENTRY(cmp, store = true; immediate_bytes = 1; break; + case 0x7C: + if (prefix[0] == 0xF2) { + opcode << "haddps"; + prefix[0] = 0; // clear prefix now it's served its purpose as part of the opcode + } else if (prefix[2] == 0x66) { + opcode << "haddpd"; + prefix[2] = 0; // clear prefix now it's served its purpose as part of the opcode + } else { + opcode << StringPrintf("unknown opcode '0F %02X'", *instr); + break; + } + src_reg_file = dst_reg_file = SSE; + has_modrm = true; + load = true; + break; case 0x7E: if (prefix[2] == 0x66) { src_reg_file = SSE; @@ -717,9 +747,9 @@ DISASSEMBLER_ENTRY(cmp, break; case 0xAF: opcode << "imul"; has_modrm = true; load = true; break; case 0xB1: opcode << "cmpxchg"; has_modrm = true; store = true; break; - case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; break; + case 0xB6: opcode << "movzxb"; has_modrm = true; load = true; byte_second_operand = true; break; case 0xB7: opcode << "movzxw"; has_modrm = true; load = true; break; - case 0xBE: opcode << "movsxb"; has_modrm = true; load = true; break; + case 0xBE: opcode << "movsxb"; has_modrm = true; load = true; byte_second_operand = true; rex |= (rex == 0 ? 0 : 0b1000); break; case 0xBF: opcode << "movsxw"; has_modrm = true; load = true; break; case 0xC5: if (prefix[2] == 0x66) { @@ -727,12 +757,24 @@ DISASSEMBLER_ENTRY(cmp, prefix[2] = 0; has_modrm = true; store = true; - src_reg_file = dst_reg_file = SSE; + src_reg_file = SSE; immediate_bytes = 1; } else { opcode << StringPrintf("unknown opcode '0F %02X'", *instr); } break; + case 0xC6: + if (prefix[2] == 0x66) { + opcode << "shufpd"; + prefix[2] = 0; + } else { + opcode << "shufps"; + } + has_modrm = true; + store = true; + src_reg_file = dst_reg_file = SSE; + immediate_bytes = 1; + break; case 0xC7: static const char* x0FxC7_opcodes[] = { "unknown-0f-c7", "cmpxchg8b", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7", "unknown-0f-c7" }; modrm_opcodes = x0FxC7_opcodes; @@ -1097,7 +1139,8 @@ DISASSEMBLER_ENTRY(cmp, } else { if (mod == 3) { if (!no_ops) { - DumpRmReg(address, rex_w, rm, byte_operand, prefix[2], load ? src_reg_file : dst_reg_file); + DumpRmReg(address, rex_w, rm, byte_operand || byte_second_operand, + prefix[2], load ? src_reg_file : dst_reg_file); } } else { address << "["; |