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
diff --git a/src/disassembler_arm.cc b/src/disassembler_arm.cc
index eb0ca8a..f3a1424 100644
--- a/src/disassembler_arm.cc
+++ b/src/disassembler_arm.cc
@@ -554,24 +554,52 @@
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;
+ 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 << ")";
}
- if (S == 1) {
- opcode << "s";
- }
- 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|