diff options
Diffstat (limited to 'disassembler/disassembler_mips.cc')
| -rw-r--r-- | disassembler/disassembler_mips.cc | 37 | 
1 files changed, 23 insertions, 14 deletions
| diff --git a/disassembler/disassembler_mips.cc b/disassembler/disassembler_mips.cc index 47873951fe..c82600b109 100644 --- a/disassembler/disassembler_mips.cc +++ b/disassembler/disassembler_mips.cc @@ -22,6 +22,8 @@  #include "android-base/logging.h"  #include "android-base/stringprintf.h" +#include "base/bit_utils.h" +  using android::base::StringPrintf;  namespace art { @@ -154,6 +156,7 @@ static const MipsInstruction gMipsInstructions[] = {    { kSpecial3Mask | 0x3f, (31 << kOpcodeShift), "ext", "TSAZ", },    { kSpecial3Mask | 0x3f, (31 << kOpcodeShift) | 3, "dext", "TSAZ", },    { kSpecial3Mask | 0x3f, (31 << kOpcodeShift) | 4, "ins", "TSAz", }, +  { kSpecial3Mask | 0x3f, (31 << kOpcodeShift) | 6, "dinsu", "TSFz", },    { kSpecial3Mask | (0x1f << 21) | (0x1f << 6) | 0x3f,      (31 << kOpcodeShift) | (16 << 6) | 32,      "seb", @@ -218,8 +221,8 @@ static const MipsInstruction gMipsInstructions[] = {    { kITypeMask, 12 << kOpcodeShift, "andi", "TSi", },    { kITypeMask, 13 << kOpcodeShift, "ori", "TSi", },    { kITypeMask, 14 << kOpcodeShift, "xori", "TSi", }, -  { kITypeMask | (0x1f << 21), 15 << kOpcodeShift, "lui", "TI", }, -  { kITypeMask, 15 << kOpcodeShift, "aui", "TSI", }, +  { kITypeMask | (0x1f << 21), 15 << kOpcodeShift, "lui", "Ti", }, +  { kITypeMask, 15 << kOpcodeShift, "aui", "TSi", },    { kITypeMask | (0x3e3 << 16), (17 << kOpcodeShift) | (8 << 21), "bc1f", "cB" },    { kITypeMask | (0x3e3 << 16), (17 << kOpcodeShift) | (8 << 21) | (1 << 16), "bc1t", "cB" }, @@ -335,6 +338,8 @@ static const MipsInstruction gMipsInstructions[] = {    { kITypeMask | (0x1f << 16), (59u << kOpcodeShift) | (30 << 16), "auipc", "Si" },    { kITypeMask | (0x3 << 19), (59u << kOpcodeShift) | (0 << 19), "addiupc", "Sp" },    { kITypeMask | (0x3 << 19), (59u << kOpcodeShift) | (1 << 19), "lwpc", "So" }, +  { kITypeMask | (0x3 << 19), (59u << kOpcodeShift) | (2 << 19), "lwupc", "So" }, +  { kITypeMask | (0x7 << 18), (59u << kOpcodeShift) | (6 << 18), "ldpc", "S0" },    { kITypeMask, 61u << kOpcodeShift, "sdc1", "tO", },    { kITypeMask | (0x1f << 21), 62u << kOpcodeShift, "jialc", "Ti" },    { kITypeMask | (1 << 21), (62u << kOpcodeShift) | (1 << 21), "bnezc", "Sb" },  // TODO: de-dup? @@ -468,6 +473,7 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {            case 'D': args << 'r' << rd; break;            case 'd': args << 'f' << rd; break;            case 'a': args << 'f' << sa; break; +          case 'F': args << (sa + 32); break;  // dinsu position.            case 'f':  // Floating point "fmt".              {                size_t fmt = (instruction >> 21) & 0x7;  // TODO: other fmts? @@ -481,9 +487,6 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {                }                continue;  // No ", ".              } -          case 'I':  // Upper 16-bit immediate. -            args << reinterpret_cast<void*>((instruction & 0xffff) << 16); -            break;            case 'i':  // Sign-extended lower 16-bit immediate.              args << static_cast<int16_t>(instruction & 0xffff);              break; @@ -512,7 +515,7 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {                }              }              break; -          case 'o':  // 19-bit offset in lwpc. +          case 'o':  // 19-bit offset in lwpc and lwupc.              {                int32_t offset = (instruction & 0x7ffff) - ((instruction & 0x40000) << 1);                offset <<= 2; @@ -520,6 +523,15 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {                args << StringPrintf("  ; %+d", offset);              }              break; +          case '0':  // 18-bit offset in ldpc. +            { +              int32_t offset = (instruction & 0x3ffff) - ((instruction & 0x20000) << 1); +              offset <<= 3; +              uintptr_t ptr = RoundDown(reinterpret_cast<uintptr_t>(instr_ptr), 8); +              args << FormatInstructionPointer(reinterpret_cast<const uint8_t*>(ptr + offset)); +              args << StringPrintf("  ; %+d", offset); +            } +            break;            case 'P':  // 26-bit offset in bc and balc.              {                int32_t offset = (instruction & 0x3ffffff) - ((instruction & 0x2000000) << 1); @@ -541,7 +553,7 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {            case 'T': args << 'r' << 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 size). +          case 'z': args << (rd - sa + 1); break;  // sz ([d]ins, dinsu size).          }          if (*(args_fmt + 1)) {            args << ", "; @@ -551,17 +563,14 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {      }    } -  // TODO: Simplify this once these sequences are simplified in the compiler.    // Special cases for sequences of:    //   pc-relative +/- 2GB branch:    //     auipc  reg, imm    //     jic    reg, imm    //   pc-relative +/- 2GB branch and link:    //     auipc  reg, imm -  //     daddiu reg, reg, imm -  //     jialc  reg, 0 -  if (((op == 0x36 && rs == 0 && rt != 0) ||  // jic -       (op == 0x19 && rs == rt && rt != 0)) &&  // daddiu +  //     jialc  reg, imm +  if (((op == 0x36 || op == 0x3E) && rs == 0 && rt != 0) &&  // ji[al]c        last_ptr_ && (intptr_t)instr_ptr - (intptr_t)last_ptr_ == 4 &&        (last_instr_ & 0xFC1F0000) == 0xEC1E0000 &&  // auipc        ((last_instr_ >> 21) & 0x1F) == rt) { @@ -569,9 +578,9 @@ size_t DisassemblerMips::Dump(std::ostream& os, const uint8_t* instr_ptr) {      offset -= (offset & 0x8000) << 1;      offset -= 4;      if (op == 0x36) { -      args << "  ; b "; +      args << "  ; bc ";      } else { -      args << "  ; move r" << rt << ", "; +      args << "  ; balc ";      }      args << FormatInstructionPointer(instr_ptr + (int32_t)offset);      args << StringPrintf("  ; %+d", (int32_t)offset); |