diff options
author | 2017-06-28 10:53:58 +0200 | |
---|---|---|
committer | 2017-07-10 17:37:08 +0200 | |
commit | 43e99b099a8ca71eda14d8009fd38cb0d441b694 (patch) | |
tree | 627382bd12b0321c54aa7d06fa5092313b7634c3 | |
parent | 6375a04cae864416499865453fecd2b50706b3b2 (diff) |
MIPS: Print register names instead of register numbers in disassembler
Test: ./testrunner.py --optimizing --target on CI20 and in QEMU
Test: mma test-art-host-gtest
Change-Id: I1fc375ae34ee8fd994192705c45d8f30a35dfc56
-rw-r--r-- | disassembler/disassembler.cc | 6 | ||||
-rw-r--r-- | disassembler/disassembler_mips.cc | 36 | ||||
-rw-r--r-- | disassembler/disassembler_mips.h | 7 | ||||
-rw-r--r-- | test/536-checker-intrinsic-optimization/src/Main.java | 2 |
4 files changed, 39 insertions, 12 deletions
diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc index 8eecc62cd5..5af51c1355 100644 --- a/disassembler/disassembler.cc +++ b/disassembler/disassembler.cc @@ -40,8 +40,10 @@ Disassembler* Disassembler::Create(InstructionSet instruction_set, DisassemblerO return new arm::DisassemblerArm(options); } else if (instruction_set == kArm64) { return new arm64::DisassemblerArm64(options); - } else if (instruction_set == kMips || instruction_set == kMips64) { - return new mips::DisassemblerMips(options); + } else if (instruction_set == kMips) { + return new mips::DisassemblerMips(options, /* is_o32_abi */ true); + } else if (instruction_set == kMips64) { + return new mips::DisassemblerMips(options, /* is_o32_abi */ false); } else if (instruction_set == kX86) { return new x86::DisassemblerX86(options, false); } else if (instruction_set == kX86_64) { diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc index 91203cb9f9..7cb216e766 100644 --- a/disassembler/disassembler_mips.cc +++ b/disassembler/disassembler_mips.cc @@ -40,6 +40,20 @@ struct MipsInstruction { } }; +static const char* gO32AbiRegNames[] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" +}; + +static const char* gN64AbiRegNames[] = { + "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", + "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", + "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" +}; + static const uint32_t kOpcodeShift = 26; static const uint32_t kCop1 = (17 << kOpcodeShift); @@ -470,6 +484,14 @@ static uint32_t ReadU32(const uint8_t* ptr) { return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); } +const char* DisassemblerMips::RegName(uint32_t reg) { + if (is_o32_abi_) { + return gO32AbiRegNames[reg]; + } else { + return gN64AbiRegNames[reg]; + } +} + size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) { uint32_t instruction = ReadU32(instr_ptr); @@ -518,7 +540,7 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) { case 'c': // Floating-point condition code flag in bc1f/bc1t and movf/movt. args << "cc" << (rt >> 2); break; - case 'D': args << 'r' << rd; break; + case 'D': args << RegName(rd); break; case 'd': args << 'f' << rd; break; case 'a': args << 'f' << sa; break; case 'F': args << (sa + 32); break; // dinsu position. @@ -553,13 +575,13 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) { case 'l': // 9-bit signed offset { int32_t offset = static_cast<int16_t>(instruction) >> 7; - args << StringPrintf("%+d(r%d)", offset, rs); + args << StringPrintf("%+d(%s)", offset, RegName(rs)); } break; case 'O': // +x(rs) { int32_t offset = static_cast<int16_t>(instruction & 0xffff); - args << StringPrintf("%+d(r%d)", offset, rs); + args << StringPrintf("%+d(%s)", offset, RegName(rs)); if (rs == 17) { args << " ; "; GetDisassemblerOptions()->thread_offset_name_function_(args, offset); @@ -595,13 +617,13 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) { case 'p': // 19-bit offset in addiupc. { int32_t offset = (instruction & 0x7ffff) - ((instruction & 0x40000) << 1); - args << offset << " ; move r" << rs << ", "; + args << offset << " ; move " << RegName(rs) << ", "; args << FormatInstructionPointer(instr_ptr + (offset << 2)); } break; - case 'S': args << 'r' << rs; break; + case 'S': args << RegName(rs); break; case 's': args << 'f' << rs; break; - case 'T': args << 'r' << rt; break; + case 'T': args << RegName(rt); break; case 't': args << 'f' << rt; break; case 'Z': args << (rd + 1); break; // sz ([d]ext size). case 'z': args << (rd - sa + 1); break; // sz ([d]ins, dinsu size). @@ -683,7 +705,7 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) { case 2: opcode += ".w"; break; case 3: opcode += ".d"; break; } - args << StringPrintf("%+d(r%d)", s10 << df, rd); + args << StringPrintf("%+d(%s)", s10 << df, RegName(rd)); break; } case 'X': // MSA df/n - ws[x]. diff --git a/disassembler/disassembler_mips.h b/disassembler/disassembler_mips.h index 6342f22962..afa6af366f 100644 --- a/disassembler/disassembler_mips.h +++ b/disassembler/disassembler_mips.h @@ -26,11 +26,13 @@ namespace mips { class DisassemblerMips FINAL : public Disassembler { public: - explicit DisassemblerMips(DisassemblerOptions* options) + explicit DisassemblerMips(DisassemblerOptions* options, bool is_o32_abi) : Disassembler(options), last_ptr_(nullptr), - last_instr_(0) {} + last_instr_(0), + is_o32_abi_(is_o32_abi) {} + const char* RegName(uint32_t reg); size_t Dump(std::ostream& os, const uint8_t* begin) OVERRIDE; void Dump(std::ostream& os, const uint8_t* begin, const uint8_t* end) OVERRIDE; @@ -39,6 +41,7 @@ class DisassemblerMips FINAL : public Disassembler { // Needed to produce more readable disassembly of certain 2-instruction sequences. const uint8_t* last_ptr_; uint32_t last_instr_; + const bool is_o32_abi_; DISALLOW_COPY_AND_ASSIGN(DisassemblerMips); }; diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java index 3dce23fb31..6d3abb1026 100644 --- a/test/536-checker-intrinsic-optimization/src/Main.java +++ b/test/536-checker-intrinsic-optimization/src/Main.java @@ -340,7 +340,7 @@ public class Main { /// CHECK-START-MIPS: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals - /// CHECK-NOT: beq r0, + /// CHECK-NOT: beq zero, /// CHECK-NOT: beqz /// CHECK-NOT: beqzc // Terminate the scope for the CHECK-NOT search at the class field or length comparison, |