summaryrefslogtreecommitdiffstats
path: root/disassembler/disassembler_arm.cc
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-10-04 08:23:32 -0700
committerIan Rogers <irogers@google.com>2013-10-04 08:23:32 -0700
commita9650dd5e7195aec987a69a6ebbdaf33f73a6b00 (patch)
treebf7bf34e4ce1791c24b3d7f9cc588d8d37bec160 /disassembler/disassembler_arm.cc
parent9f69b62e6b009b29e6420c49e7444e91466a6a33 (diff)
downloadart-a9650dd5e7195aec987a69a6ebbdaf33f73a6b00.zip
art-a9650dd5e7195aec987a69a6ebbdaf33f73a6b00.tar.gz
art-a9650dd5e7195aec987a69a6ebbdaf33f73a6b00.tar.bz2
Implement thumb expansion of immediates.
Change-Id: Ie50c17f82cbf97a16b58350b378914030cc0499f
Diffstat (limited to 'disassembler/disassembler_arm.cc')
-rw-r--r--disassembler/disassembler_arm.cc26
1 files changed, 23 insertions, 3 deletions
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index 879d3ac..782c1f3 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -278,6 +278,26 @@ void DisassemblerArm::DumpArm(std::ostream& os, const uint8_t* instr_ptr) {
os << StringPrintf("%p: %08x\t%-7s ", instr_ptr, instruction, opcode.c_str()) << args.str() << '\n';
}
+int32_t ThumbExpand(int32_t imm12) {
+ if ((imm12 & 0xC00) == 0) {
+ switch ((imm12 >> 8) & 3) {
+ case 0:
+ return imm12 & 0xFF;
+ case 1:
+ return ((imm12 & 0xFF) << 16) | (imm12 & 0xFF);
+ case 2:
+ return ((imm12 & 0xFF) << 24) | ((imm12 & 0xFF) << 8);
+ default: // 3
+ return ((imm12 & 0xFF) << 24) | ((imm12 & 0xFF) << 16) | ((imm12 & 0xFF) << 8) |
+ (imm12 & 0xFF);
+ }
+ } else {
+ uint32_t val = 0x80 | (imm12 & 0x7F);
+ int32_t rotate = (imm12 >> 7) & 0x1F;
+ return (val >> rotate) | (val << (32 - rotate));
+ }
+}
+
size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr) {
uint32_t instr = (ReadU16(instr_ptr) << 16) | ReadU16(instr_ptr + 2);
// |111|1 1|1000000|0000|1111110000000000|
@@ -628,7 +648,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
opcode << "s";
}
}
- args << Rd << ", ThumbExpand(" << imm32 << ")";
+ args << Rd << ", #" << ThumbExpand(imm32);
} else if (Rd.r == 0xF && S == 1 &&
(op3 == 0x0 || op3 == 0x4 || op3 == 0x8 || op3 == 0xD)) {
if (op3 == 0x0) {
@@ -640,7 +660,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
} else {
opcode << "cmp.w";
}
- args << Rn << ", ThumbExpand(" << imm32 << ")";
+ args << Rn << ", #" << ThumbExpand(imm32);
} else {
switch (op3) {
case 0x0: opcode << "and"; break;
@@ -658,7 +678,7 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
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)