#include <inttypes.h>
#include <string>
+#include <sstream>
#include "backend_arm.h"
#include "base/logging.h"
buf += *fmt++;
}
}
+ // Dump thread offset.
+ std::string fmt_str = GetTargetInstFmt(lir->opcode);
+ if (std::string::npos != fmt_str.find(", [!1C, #!2") && rARM_SELF == lir->operands[1] &&
+ std::string::npos != buf.find(", [")) {
+ int offset = lir->operands[2];
+ if (std::string::npos != fmt_str.find("#!2d")) {
+ } else if (std::string::npos != fmt_str.find("#!2E")) {
+ offset *= 4;
+ } else if (std::string::npos != fmt_str.find("#!2F")) {
+ offset *= 2;
+ } else {
+ LOG(FATAL) << "Should not reach here";
+ }
+ std::ostringstream tmp_stream;
+ Thread::DumpThreadOffset<4>(tmp_stream, offset);
+ buf += " ; ";
+ buf += tmp_stream.str();
+ }
return buf;
}
#include <inttypes.h>
#include <string>
+#include <sstream>
#include "backend_arm64.h"
#include "base/logging.h"
buf += *fmt++;
}
}
+ // Dump thread offset.
+ std::string fmt_str = GetTargetInstFmt(lir->opcode);
+ if (std::string::npos != fmt_str.find(", [!1X, #!2") && rxSELF == lir->operands[1] &&
+ std::string::npos != buf.find(", [")) {
+ int offset = lir->operands[2];
+ if (std::string::npos != fmt_str.find("#!2d")) {
+ } else if (std::string::npos != fmt_str.find("#!2D")) {
+ offset *= (IS_WIDE(lir->opcode)) ? 8 : 4;
+ } else if (std::string::npos != fmt_str.find("#!2F")) {
+ offset *= 2;
+ } else {
+ LOG(FATAL) << "Should not reach here";
+ }
+ std::ostringstream tmp_stream;
+ Thread::DumpThreadOffset<8>(tmp_stream, offset);
+ buf += " ; ";
+ buf += tmp_stream.str();
+ }
return buf;
}
#include <inttypes.h>
-#include <ostream>
+#include <sstream>
#include "base/logging.h"
#include "base/stringprintf.h"
namespace art {
namespace arm64 {
+// 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()) {
- // 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
- };
switch (reg.code()) {
case IP0: AppendToOutput(reg.Is64Bits() ? "ip0" : "wip0"); return;
case IP1: AppendToOutput(reg.Is64Bits() ? "ip1" : "wip1"); return;
return;
}
- char* buffer = buffer_;
- char* buffer_end = buffer_ + buffer_size_;
-
- // Find the end position in the buffer.
- while ((*buffer != 0) && (buffer < buffer_end)) {
- ++buffer;
- }
-
void* data_address = instr->LiteralAddress<void*>();
- ptrdiff_t buf_size_remaining = buffer_end - buffer;
vixl::Instr op = instr->Mask(vixl::LoadLiteralMask);
switch (op) {
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);
- snprintf(buffer, buf_size_remaining, " (0x%" PRIx64 " / %" PRId64 ")", data, data);
+ 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);
- snprintf(buffer, buf_size_remaining, " (%g)", data);
+ AppendToOutput(" (%g)", data);
break;
}
default:
}
}
+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) {
const vixl::Instruction* instr = reinterpret_cast<const vixl::Instruction*>(begin);
decoder.Decode(instr);
vixl::Disassembler(), read_literals_(read_literals) {}
// Use register aliases in the disassembly.
- virtual void AppendRegisterNameToOutput(const vixl::Instruction* instr,
- const vixl::CPURegister& reg) OVERRIDE;
+ void AppendRegisterNameToOutput(const vixl::Instruction* instr,
+ const vixl::CPURegister& reg) OVERRIDE;
// Improve the disassembly of literal load instructions.
- virtual void VisitLoadLiteral(const vixl::Instruction* instr) OVERRIDE;
+ void VisitLoadLiteral(const vixl::Instruction* instr) OVERRIDE;
+
+ // Improve the disassembly of thread offset.
+ void VisitLoadStoreUnsignedOffset(const vixl::Instruction* instr) OVERRIDE;
private:
// Indicate if the disassembler should read data loaded from literal pools.