blob: bd3bebf20fdafae3c743ada4da4e11d91bd8bff5 [file] [log] [blame]
Serban Constantinescue6622be2014-02-27 15:36:47 +00001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "disassembler_arm64.h"
18
19#include <inttypes.h>
20
Ian Rogerscf7f1912014-10-22 22:06:39 -070021#include <ostream>
Serban Constantinescue6622be2014-02-27 15:36:47 +000022
23#include "base/logging.h"
24#include "base/stringprintf.h"
25#include "thread.h"
26
27namespace art {
28namespace arm64 {
29
Alexandre Ramesa37d9252014-10-27 11:28:14 +000030void CustomDisassembler::AppendRegisterNameToOutput(
31 const vixl::Instruction* instr,
32 const vixl::CPURegister& reg) {
33 USE(instr);
34 if (reg.IsRegister()) {
35 // This enumeration should mirror the declarations in
36 // runtime/arch/arm64/registers_arm64.h. We do not include that file to
37 // avoid a dependency on libart.
38 enum {
39 TR = 18,
40 ETR = 21,
41 IP0 = 16,
42 IP1 = 17,
43 FP = 29,
44 LR = 30
45 };
46 switch (reg.code()) {
47 case IP0: AppendToOutput(reg.Is64Bits() ? "ip0" : "wip0"); return;
48 case IP1: AppendToOutput(reg.Is64Bits() ? "ip1" : "wip1"); return;
49 case TR: AppendToOutput(reg.Is64Bits() ? "tr" : "w18"); return;
50 case ETR: AppendToOutput(reg.Is64Bits() ? "etr" : "w21"); return;
51 case FP: AppendToOutput(reg.Is64Bits() ? "fp" : "w29"); return;
52 case LR: AppendToOutput(reg.Is64Bits() ? "lr" : "w30"); return;
53 default:
54 // Fall through.
55 break;
56 }
57 }
58 // Print other register names as usual.
59 Disassembler::AppendRegisterNameToOutput(instr, reg);
60}
61
62void CustomDisassembler::VisitLoadLiteral(const vixl::Instruction* instr) {
63 Disassembler::VisitLoadLiteral(instr);
64
65 if (!read_literals_) {
66 return;
67 }
68
69 char* buffer = buffer_;
70 char* buffer_end = buffer_ + buffer_size_;
71
72 // Find the end position in the buffer.
73 while ((*buffer != 0) && (buffer < buffer_end)) {
74 ++buffer;
75 }
76
Serban Constantinescu32f5b4d2014-11-25 20:05:46 +000077 void* data_address = instr->LiteralAddress<void*>();
Alexandre Ramesa37d9252014-10-27 11:28:14 +000078 ptrdiff_t buf_size_remaining = buffer_end - buffer;
79 vixl::Instr op = instr->Mask(vixl::LoadLiteralMask);
80
81 switch (op) {
82 case vixl::LDR_w_lit:
83 case vixl::LDR_x_lit:
84 case vixl::LDRSW_x_lit: {
85 int64_t data = op == vixl::LDR_x_lit ? *reinterpret_cast<int64_t*>(data_address)
86 : *reinterpret_cast<int32_t*>(data_address);
87 snprintf(buffer, buf_size_remaining, " (0x%" PRIx64 " / %" PRId64 ")", data, data);
88 break;
89 }
90 case vixl::LDR_s_lit:
91 case vixl::LDR_d_lit: {
92 double data = (op == vixl::LDR_s_lit) ? *reinterpret_cast<float*>(data_address)
93 : *reinterpret_cast<double*>(data_address);
94 snprintf(buffer, buf_size_remaining, " (%g)", data);
95 break;
96 }
97 default:
98 break;
99 }
100}
101
Serban Constantinescue6622be2014-02-27 15:36:47 +0000102size_t DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin) {
Alexandre Ramesfef019c2014-10-10 17:14:18 +0100103 const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin);
104 decoder.Decode(instr);
Alexandre Ramesa37d9252014-10-27 11:28:14 +0000105 // TODO: Use FormatInstructionPointer() once VIXL provides the appropriate
106 // features.
107 // VIXL does not yet allow remapping addresses disassembled. Using
108 // FormatInstructionPointer() would show incoherences between the instruction
109 // location addresses and the target addresses disassembled by VIXL (eg. for
110 // branch instructions).
111 os << StringPrintf("%p", instr)
Alexandre Ramesfef019c2014-10-10 17:14:18 +0100112 << StringPrintf(": %08x\t%s\n", instr->InstructionBits(), disasm.GetOutput());
Serban Constantinescue6622be2014-02-27 15:36:47 +0000113 return vixl::kInstructionSize;
114}
115
116void DisassemblerArm64::Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) {
117 for (const uint8_t* cur = begin; cur < end; cur += vixl::kInstructionSize) {
118 Dump(os, cur);
119 }
120}
121
122} // namespace arm64
123} // namespace art