summaryrefslogtreecommitdiff
path: root/disassembler/disassembler_arm64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'disassembler/disassembler_arm64.cc')
-rw-r--r--disassembler/disassembler_arm64.cc82
1 files changed, 75 insertions, 7 deletions
diff --git a/disassembler/disassembler_arm64.cc b/disassembler/disassembler_arm64.cc
index 5d0c2189cc..d195efc0f9 100644
--- a/disassembler/disassembler_arm64.cc
+++ b/disassembler/disassembler_arm64.cc
@@ -18,7 +18,7 @@
#include <inttypes.h>
-#include <iostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
@@ -27,15 +27,83 @@
namespace art {
namespace arm64 {
-static uint32_t ReadU32(const uint8_t* ptr) {
- return *((const uint32_t*)ptr);
+// This enumeration should mirror the declarations in
+// runtime/arch/arm64/registers_arm64.h. We do not include that file to
+// avoid a dependency on libart.
+enum {
+ TR = 18,
+ ETR = 21,
+ IP0 = 16,
+ IP1 = 17,
+ FP = 29,
+ LR = 30
+};
+
+void CustomDisassembler::AppendRegisterNameToOutput(
+ const vixl::Instruction* instr,
+ const vixl::CPURegister& reg) {
+ USE(instr);
+ if (reg.IsRegister() && reg.Is64Bits()) {
+ if (reg.code() == TR) {
+ AppendToOutput("tr");
+ return;
+ } else if (reg.code() == LR) {
+ AppendToOutput("lr");
+ return;
+ }
+ // Fall through.
+ }
+ // Print other register names as usual.
+ Disassembler::AppendRegisterNameToOutput(instr, reg);
+}
+
+void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) {
+ Disassembler::VisitLoadLiteral(instr);
+
+ if (!read_literals_) {
+ return;
+ }
+
+ void* data_address = instr->LiteralAddress<void*>();
+ vixl::Instr op = instr->Mask(vixl::LoadLiteralMask);
+
+ switch (op) {
+ case vixl::LDR_w_lit:
+ case vixl::LDR_x_lit:
+ case vixl::LDRSW_x_lit: {
+ int64_t data = op == vixl::LDR_x_lit ? *reinterpret_cast<int64_t*>(data_address)
+ : *reinterpret_cast<int32_t*>(data_address);
+ AppendToOutput(" (0x%" PRIx64 " / %" PRId64 ")", data, data);
+ break;
+ }
+ case vixl::LDR_s_lit:
+ case vixl::LDR_d_lit: {
+ double data = (op == vixl::LDR_s_lit) ? *reinterpret_cast<float*>(data_address)
+ : *reinterpret_cast<double*>(data_address);
+ AppendToOutput(" (%g)", data);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void CustomDisassembler::VisitLoadStoreUnsignedOffset(const vixl::Instruction* instr) {
+ Disassembler::VisitLoadStoreUnsignedOffset(instr);
+
+ if (instr->Rn() == TR) {
+ int64_t offset = instr->ImmLSUnsigned() << instr->SizeLS();
+ std::ostringstream tmp_stream;
+ Thread::DumpThreadOffset<8>(tmp_stream, static_cast<uint32_t>(offset));
+ AppendToOutput(" (%s)", tmp_stream.str().c_str());
+ }
}
size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
- uint32_t instruction = ReadU32(begin);
- decoder.Decode(reinterpret_cast<vixl::Instruction*>(&instruction));
- os << FormatInstructionPointer(begin)
- << StringPrintf(": %08x\t%s\n", instruction, disasm.GetOutput());
+ const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin);
+ decoder.Decode(instr);
+ os << FormatInstructionPointer(begin)
+ << StringPrintf(": %08x\t%s\n", instr->InstructionBits(), disasm.GetOutput());
return vixl::kInstructionSize;
}