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
diff --git a/disassembler/disassembler.cc b/disassembler/disassembler.cc
index 8eecc62..5af51c1 100644
--- a/disassembler/disassembler.cc
+++ b/disassembler/disassembler.cc
@@ -40,8 +40,10 @@
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 91203cb..7cb216e 100644
--- a/disassembler/disassembler_mips.cc
+++ b/disassembler/disassembler_mips.cc
@@ -40,6 +40,20 @@
}
};
+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 @@
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 @@
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 @@
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 @@
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 @@
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 6342f22..afa6af3 100644
--- a/disassembler/disassembler_mips.h
+++ b/disassembler/disassembler_mips.h
@@ -26,11 +26,13 @@
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 @@
// 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 3dce23f..6d3abb1 100644
--- a/test/536-checker-intrinsic-optimization/src/Main.java
+++ b/test/536-checker-intrinsic-optimization/src/Main.java
@@ -340,7 +340,7 @@
/// 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,