summaryrefslogtreecommitdiffstats
path: root/disassembler
diff options
context:
space:
mode:
authorDave Allison <dallison@google.com>2014-02-19 14:05:39 -0800
committerDave Allison <dallison@google.com>2014-04-04 16:07:46 -0700
commit754ddad084ccb610d0cf486f6131bdc69bae5bc6 (patch)
tree18d8314f3f6760b035c2bcda7760782ad4f0e0bf /disassembler
parent97a332b4476d5a2b4ad0650dacc6bfcff882fc57 (diff)
downloadandroid_art-754ddad084ccb610d0cf486f6131bdc69bae5bc6.tar.gz
android_art-754ddad084ccb610d0cf486f6131bdc69bae5bc6.tar.bz2
android_art-754ddad084ccb610d0cf486f6131bdc69bae5bc6.zip
Use trampolines for calls to helpers
This is an ARM specific optimization to the compiler that uses trampoline islands to make calls to runtime helper functions. The intention is to reduce the size of the generated code (by 2 bytes per call) without affecting performance. By default this is on when generating an OAT file. It is off when compiling to memory. To switch this off in dex2oat, use the command line option: --no-helper-trampolines Enhances disassembler to print the trampoline entry on the BL instruction like this: 0xb6a850c0: f7ffff9e bl -196 (0xb6a85000) ; pTestSuspend Bug: 12607709 Change-Id: I9202bdb7cf21252ad807bd48701f1f6ce8e3d0fe
Diffstat (limited to 'disassembler')
-rw-r--r--disassembler/disassembler_arm.cc30
1 files changed, 25 insertions, 5 deletions
diff --git a/disassembler/disassembler_arm.cc b/disassembler/disassembler_arm.cc
index d6d20586b7..05e7576085 100644
--- a/disassembler/disassembler_arm.cc
+++ b/disassembler/disassembler_arm.cc
@@ -1221,23 +1221,43 @@ size_t DisassemblerArm::DumpThumb32(std::ostream& os, const uint8_t* instr_ptr)
// |332|22|2|2222221111|11|1 |1|1 |10000000000|
// |1 9|87|6|5 0 6|54|3 |2|1 |0 5 0|
// |---|--|-|----------|--|--|-|--|-----------|
- // |111|10|S| imm10 |11|J1|L|J2| imm11 |
+ // |111|10|S| imm10 |11|J1|X|J2| imm11 |
uint32_t S = (instr >> 26) & 1;
uint32_t J2 = (instr >> 11) & 1;
- uint32_t L = (instr >> 12) & 1;
+ uint32_t X = (instr >> 12) & 1;
uint32_t J1 = (instr >> 13) & 1;
uint32_t imm10 = (instr >> 16) & 0x3FF;
uint32_t imm11 = instr & 0x7FF;
- if (L == 0) {
- opcode << "bx";
- } else {
+ if (X == 0) {
+ // This bit is unnamed in spec, but if zero, the instruction
+ // is BLX.
opcode << "blx";
+ } else {
+ opcode << "bl";
}
uint32_t I1 = ~(J1 ^ S);
uint32_t I2 = ~(J2 ^ S);
int32_t imm32 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
imm32 = (imm32 << 8) >> 8; // sign extend 24 bit immediate.
DumpBranchTarget(args, instr_ptr + 4, imm32);
+ if (X == 1) {
+ // For a BL instruction we look and see if it's an entrypoint
+ // trampoline.
+ const uint16_t* target = reinterpret_cast<const uint16_t*>(instr_ptr + 4 + imm32);
+ if (target == nullptr) {
+ // Defensive, will probably never happen.
+ break;
+ }
+ const uint32_t targetinst = static_cast<uint32_t>(*target << 16 | *(target + 1));
+
+ // Is the target instruction an entrypoint trampoline:
+ // ldr pc,[r9,#foo]
+ if ((targetinst & 0xfffff000) == (0xf8d0f000 | (9 << 16))) {
+ uint16_t offset = targetinst & 0xfff;
+ args << " ; ";
+ Thread::DumpThreadOffset<4>(args, offset);
+ }
+ }
break;
}
}