diff options
author | Elliott Hughes <enh@google.com> | 2012-04-10 15:04:25 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2012-04-10 15:04:25 -0700 |
commit | 105afd2bd8f9f0ddfcfcb4b8db9f356ee82ae8cd (patch) | |
tree | fc5b59d5cd6f5ad4dccbe42c19fbd71e86271cef | |
parent | b92bcabcbb28f69fe99e1c2f2e5559ab2c47aa60 (diff) | |
download | art-105afd2bd8f9f0ddfcfcb4b8db9f356ee82ae8cd.zip art-105afd2bd8f9f0ddfcfcb4b8db9f356ee82ae8cd.tar.gz art-105afd2bd8f9f0ddfcfcb4b8db9f356ee82ae8cd.tar.bz2 |
Fancy disassembly of Thumb2 IT blocks.
Example:
0x60ce6ea4: 4291 cmp r1, r2
0x60ce6ea6: bf0e itee eq
0x60ce6ea8: 2001 movseq r0, #1
0x60ce6eaa: 1c10 movne r0, r2
0x60ce6eac: 47f0 blxne lr
0x60ce6eae: 1c06 mov r6, r0
Change-Id: I85deae2e471b8bfc513281be421e0bd46c1b60a0
-rw-r--r-- | src/disassembler.h | 7 | ||||
-rw-r--r-- | src/disassembler_arm.cc | 31 | ||||
-rw-r--r-- | src/disassembler_arm.h | 6 | ||||
-rw-r--r-- | src/utils.h | 1 |
4 files changed, 43 insertions, 2 deletions
diff --git a/src/disassembler.h b/src/disassembler.h index bd745a8..9f99ca6 100644 --- a/src/disassembler.h +++ b/src/disassembler.h @@ -22,6 +22,7 @@ #include <iosfwd> #include "instruction_set.h" +#include "macros.h" namespace art { @@ -31,6 +32,12 @@ class Disassembler { virtual ~Disassembler() {} virtual void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) = 0; + + protected: + Disassembler() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Disassembler); }; } // namespace art diff --git a/src/disassembler_arm.cc b/src/disassembler_arm.cc index 57fcec3..2492f50 100644 --- a/src/disassembler_arm.cc +++ b/src/disassembler_arm.cc @@ -899,9 +899,29 @@ size_t DisassemblerArm::DumpThumb16(std::ostream& os, const uint8_t* instr_ptr) default: break; } } else { + uint32_t first_cond = opA; + uint32_t mask = opB; opcode << "it"; - args << reinterpret_cast<void*>(opB) << " "; - DumpCond(args, opA); + + // Flesh out the base "it" opcode with the specific collection of 't's and 'e's, + // and store up the actual condition codes we'll want to add to the next few opcodes. + size_t count = 3 - CTZ(mask); + it_conditions_.resize(count + 2); // Plus the implicit 't', plus the "" for the IT itself. + for (size_t i = 0; i < count; ++i) { + bool positive_cond = ((first_cond & 1) != 0); + bool positive_mask = ((mask & (1 << (3 - i))) != 0); + if (positive_mask == positive_cond) { + opcode << 't'; + it_conditions_[i] = kConditionCodeNames[first_cond]; + } else { + opcode << 'e'; + it_conditions_[i] = kConditionCodeNames[first_cond ^ 1]; + } + } + it_conditions_[count] = kConditionCodeNames[first_cond]; // The implicit 't'. + + it_conditions_[count + 1] = ""; // No condition code for the IT itself... + DumpCond(args, first_cond); // ...because it's considered an argument. } break; } @@ -943,6 +963,13 @@ size_t DisassemblerArm::DumpThumb16(std::ostream& os, const uint8_t* instr_ptr) opcode << "b"; DumpBranchTarget(args, instr_ptr + 4, imm32); } + + // Apply any IT-block conditions to the opcode if necessary. + if (!it_conditions_.empty()) { + opcode << it_conditions_.back(); + it_conditions_.pop_back(); + } + os << StringPrintf("\t\t\t%p: %04x \t%-7s ", instr_ptr, instr, opcode.str().c_str()) << args.str() << '\n'; } return 2; diff --git a/src/disassembler_arm.h b/src/disassembler_arm.h index 336d277..c59d395 100644 --- a/src/disassembler_arm.h +++ b/src/disassembler_arm.h @@ -17,6 +17,8 @@ #ifndef ART_SRC_DISASSEMBLER_ARM_H_ #define ART_SRC_DISASSEMBLER_ARM_H_ +#include <vector> + #include "disassembler.h" namespace art { @@ -36,6 +38,10 @@ class DisassemblerArm : public Disassembler { void DumpBranchTarget(std::ostream& os, const uint8_t* instr_ptr, int32_t imm32); void DumpCond(std::ostream& os, uint32_t cond); + + std::vector<const char*> it_conditions_; + + DISALLOW_COPY_AND_ASSIGN(DisassemblerArm); }; } // namespace arm diff --git a/src/utils.h b/src/utils.h index c709f9a..f11a769 100644 --- a/src/utils.h +++ b/src/utils.h @@ -131,6 +131,7 @@ static inline int CountOneBits(uint32_t x) { } #define CLZ(x) __builtin_clz(x) +#define CTZ(x) __builtin_ctz(x) static inline bool NeedsEscaping(uint16_t ch) { return (ch < ' ' || ch > '~'); |