diff options
author | 2013-02-04 16:15:27 -0800 | |
---|---|---|
committer | 2013-02-04 16:15:27 -0800 | |
commit | 7cb0f9cf9c7798ae9c4d6cad47e7861f7a511f7e (patch) | |
tree | 9717f08d1cc5cf1b9f1c6b2dc5f7764dd69952ce | |
parent | cb4bf70c20301a61d0148c23b2ddb403331ab1e6 (diff) |
Fix ARM 32-bit thumb dissassembly for certain special cases.
Fixed 32-bit thumb instructions of the form "Data-processing (modified
immediate)". Disassembler didn't handle special cases where Rn was 0xF
or Rd:S was 0x1F.
Change-Id: I821a040cf3f91fadc890ddd0a7bf7162a2519854
-rw-r--r-- | src/disassembler_arm.cc | 62 |
1 files changed, 45 insertions, 17 deletions
diff --git a/src/disassembler_arm.cc b/src/disassembler_arm.cc index eb0ca8a324..f3a142472a 100644 --- a/src/disassembler_arm.cc +++ b/src/disassembler_arm.cc @@ -554,24 +554,52 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) uint32_t imm3 = (instr >> 12) & 7; ArmRegister Rd(instr, 8); uint32_t imm8 = instr & 0xFF; - int32_t imm32 = (i << 12) | (imm3 << 8) | imm8; - switch (op3) { - case 0x0: opcode << "and"; break; - case 0x1: opcode << "bic"; break; - case 0x2: opcode << "orr"; break; - case 0x3: opcode << "orn"; break; - case 0x4: opcode << "eor"; break; - case 0x8: opcode << "add"; break; - case 0xA: opcode << "adc"; break; - case 0xB: opcode << "sbc"; break; - case 0xD: opcode << "sub"; break; - case 0xE: opcode << "rsb"; break; - default: opcode << "UNKNOWN DPMI-" << op3; break; - } - if (S == 1) { - opcode << "s"; + int32_t imm32 = (i << 11) | (imm3 << 8) | imm8; + if (Rn.r == 0xF && (op3 == 0x2 || op3 == 0x3)) { + if (op3 == 0x2) { + opcode << "mov"; + if (S == 1) { + opcode << "s"; + } + opcode << ".w"; + } else { + opcode << "mvn"; + if (S == 1) { + opcode << "s"; + } + } + args << Rd << ", ThumbExpand(" << imm32 << ")"; + } else if (Rd.r == 0xF && S == 1 && + (op3 == 0x0 || op3 == 0x4 || op3 == 0x8 || op3 == 0xD)) { + if (op3 == 0x0) { + opcode << "tst"; + } else if (op3 == 0x4) { + opcode << "teq"; + } else if (op3 == 0x8) { + opcode << "cmw"; + } else { + opcode << "cmp.w"; + } + args << Rn << ", ThumbExpand(" << imm32 << ")"; + } else { + switch (op3) { + case 0x0: opcode << "and"; break; + case 0x1: opcode << "bic"; break; + case 0x2: opcode << "orr"; break; + case 0x3: opcode << "orn"; break; + case 0x4: opcode << "eor"; break; + case 0x8: opcode << "add"; break; + case 0xA: opcode << "adc"; break; + case 0xB: opcode << "sbc"; break; + case 0xD: opcode << "sub"; break; + case 0xE: opcode << "rsb"; break; + default: opcode << "UNKNOWN DPMI-" << op3; break; + } + if (S == 1) { + opcode << "s"; + } + args << Rd << ", " << Rn << ", ThumbExpand(" << imm32 << ")"; } - args << Rd << ", " << Rn << ", ThumbExpand(" << imm32 << ")"; } else if ((instr & 0x8000) == 0 && (op2 & 0x20) != 0) { // Data-processing (plain binary immediate) // |111|11|10|00000|0000|1|111110000000000| |