| Index: runtime/vm/disassembler_mips.cc
|
| diff --git a/runtime/vm/disassembler_mips.cc b/runtime/vm/disassembler_mips.cc
|
| deleted file mode 100644
|
| index 23244b37071cd1c6067c1fef5b8e4e2fca782cfb..0000000000000000000000000000000000000000
|
| --- a/runtime/vm/disassembler_mips.cc
|
| +++ /dev/null
|
| @@ -1,792 +0,0 @@
|
| -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -#include "vm/disassembler.h"
|
| -
|
| -#include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
|
| -#if defined(TARGET_ARCH_MIPS)
|
| -#include "platform/assert.h"
|
| -#include "vm/instructions.h"
|
| -
|
| -namespace dart {
|
| -
|
| -#ifndef PRODUCT
|
| -
|
| -class MIPSDecoder : public ValueObject {
|
| - public:
|
| - MIPSDecoder(char* buffer, size_t buffer_size)
|
| - : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) {
|
| - buffer_[buffer_pos_] = '\0';
|
| - }
|
| -
|
| - ~MIPSDecoder() {}
|
| -
|
| - // Writes one disassembled instruction into 'buffer' (0-terminated).
|
| - // Returns true if the instruction was successfully decoded, false otherwise.
|
| - void InstructionDecode(Instr* instr);
|
| -
|
| - private:
|
| - // Bottleneck functions to print into the out_buffer.
|
| - void Print(const char* str);
|
| -
|
| - // Printing of common values.
|
| - void PrintRegister(Register reg);
|
| - void PrintFRegister(FRegister reg);
|
| - void PrintFormat(Instr* instr);
|
| -
|
| - int FormatRegister(Instr* instr, const char* format);
|
| - int FormatFRegister(Instr* instr, const char* format);
|
| - int FormatOption(Instr* instr, const char* format);
|
| - void Format(Instr* instr, const char* format);
|
| - void Unknown(Instr* instr);
|
| -
|
| - void DecodeSpecial(Instr* instr);
|
| - void DecodeSpecial2(Instr* instr);
|
| - void DecodeRegImm(Instr* instr);
|
| - void DecodeCop1(Instr* instr);
|
| -
|
| - // Convenience functions.
|
| - char* get_buffer() const { return buffer_; }
|
| - char* current_position_in_buffer() { return buffer_ + buffer_pos_; }
|
| - size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; }
|
| -
|
| - char* buffer_; // Decode instructions into this buffer.
|
| - size_t buffer_size_; // The size of the character buffer.
|
| - size_t buffer_pos_; // Current character position in buffer.
|
| -
|
| - DISALLOW_ALLOCATION();
|
| - DISALLOW_COPY_AND_ASSIGN(MIPSDecoder);
|
| -};
|
| -
|
| -
|
| -// Support for assertions in the MIPSDecoder formatting functions.
|
| -#define STRING_STARTS_WITH(string, compare_string) \
|
| - (strncmp(string, compare_string, strlen(compare_string)) == 0)
|
| -
|
| -
|
| -// Append the str to the output buffer.
|
| -void MIPSDecoder::Print(const char* str) {
|
| - char cur = *str++;
|
| - while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) {
|
| - buffer_[buffer_pos_++] = cur;
|
| - cur = *str++;
|
| - }
|
| - buffer_[buffer_pos_] = '\0';
|
| -}
|
| -
|
| -
|
| -static const char* reg_names[kNumberOfCpuRegisters] = {
|
| - "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3", "t0", "t1", "t2",
|
| - "t3", "t4", "t5", "t6", "t7", "s0", "s1", "s2", "thr", "s4", "s5",
|
| - "s6", "pp", "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
|
| -};
|
| -
|
| -
|
| -static const char* freg_names[kNumberOfFRegisters] = {
|
| - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10",
|
| - "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21",
|
| - "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
|
| -};
|
| -
|
| -
|
| -void MIPSDecoder::PrintRegister(Register reg) {
|
| - ASSERT(0 <= reg);
|
| - ASSERT(reg < kNumberOfCpuRegisters);
|
| - Print(reg_names[reg]);
|
| -}
|
| -
|
| -
|
| -void MIPSDecoder::PrintFRegister(FRegister reg) {
|
| - ASSERT(0 <= reg);
|
| - ASSERT(reg < kNumberOfFRegisters);
|
| - Print(freg_names[reg]);
|
| -}
|
| -
|
| -
|
| -// Handle all register based formatting in these functions to reduce the
|
| -// complexity of FormatOption.
|
| -int MIPSDecoder::FormatRegister(Instr* instr, const char* format) {
|
| - ASSERT(format[0] == 'r');
|
| - switch (format[1]) {
|
| - case 's': { // 'rs: Rs register
|
| - PrintRegister(instr->RsField());
|
| - return 2;
|
| - }
|
| - case 't': { // 'rt: Rt register
|
| - PrintRegister(instr->RtField());
|
| - return 2;
|
| - }
|
| - case 'd': { // 'rd: Rd register
|
| - PrintRegister(instr->RdField());
|
| - return 2;
|
| - }
|
| - }
|
| - UNREACHABLE();
|
| - return -1;
|
| -}
|
| -
|
| -
|
| -int MIPSDecoder::FormatFRegister(Instr* instr, const char* format) {
|
| - ASSERT(format[0] == 'f');
|
| - switch (format[1]) {
|
| - case 's': { // 'fs: Fs register
|
| - PrintFRegister(instr->FsField());
|
| - return 2;
|
| - }
|
| - case 't': { // 'ft: Ft register
|
| - PrintFRegister(instr->FtField());
|
| - return 2;
|
| - }
|
| - case 'd': { // 'fd: Fd register
|
| - PrintFRegister(instr->FdField());
|
| - return 2;
|
| - }
|
| - }
|
| - UNREACHABLE();
|
| - return -1;
|
| -}
|
| -
|
| -
|
| -void MIPSDecoder::PrintFormat(Instr* instr) {
|
| - switch (instr->FormatField()) {
|
| - case FMT_S: {
|
| - Print("s");
|
| - break;
|
| - }
|
| - case FMT_D: {
|
| - Print("d");
|
| - break;
|
| - }
|
| - case FMT_W: {
|
| - Print("w");
|
| - break;
|
| - }
|
| - case FMT_L: {
|
| - Print("l");
|
| - break;
|
| - }
|
| - case FMT_PS: {
|
| - Print("ps");
|
| - break;
|
| - }
|
| - default: {
|
| - Print("unknown");
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -// FormatOption takes a formatting string and interprets it based on
|
| -// the current instructions. The format string points to the first
|
| -// character of the option string (the option escape has already been
|
| -// consumed by the caller.) FormatOption returns the number of
|
| -// characters that were consumed from the formatting string.
|
| -int MIPSDecoder::FormatOption(Instr* instr, const char* format) {
|
| - switch (format[0]) {
|
| - case 'c': {
|
| - ASSERT(STRING_STARTS_WITH(format, "code"));
|
| - buffer_pos_ +=
|
| - OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
|
| - "0x%x", instr->BreakCodeField());
|
| - return 4;
|
| - }
|
| - case 'h': {
|
| - ASSERT(STRING_STARTS_WITH(format, "hint"));
|
| - if (instr->SaField() == 0x10) {
|
| - // The high bit of the SA field is the only one that means something for
|
| - // JALR and JR. TODO(zra): Fill in the other cases for PREF if needed.
|
| - buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| - remaining_size_in_buffer(), ".hb");
|
| - } else if (instr->SaField() != 0) {
|
| - buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| - remaining_size_in_buffer(), ".unknown");
|
| - }
|
| - return 4;
|
| - }
|
| - case 'd': {
|
| - ASSERT(STRING_STARTS_WITH(format, "dest"));
|
| - int off = instr->SImmField() << 2;
|
| - uword destination =
|
| - reinterpret_cast<uword>(instr) + off + Instr::kInstrSize;
|
| - buffer_pos_ +=
|
| - OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
|
| - "%#" Px "", destination);
|
| - return 4;
|
| - }
|
| - case 'i': {
|
| - ASSERT(STRING_STARTS_WITH(format, "imm"));
|
| - if (format[3] == 'u') {
|
| - int32_t imm = instr->UImmField();
|
| - buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| - remaining_size_in_buffer(), "0x%x", imm);
|
| - } else {
|
| - ASSERT(STRING_STARTS_WITH(format, "imms"));
|
| - int32_t imm = instr->SImmField();
|
| - buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
|
| - remaining_size_in_buffer(), "%d", imm);
|
| - }
|
| - return 4;
|
| - }
|
| - case 'r': {
|
| - return FormatRegister(instr, format);
|
| - }
|
| - case 'f': {
|
| - if (format[1] == 'm') {
|
| - ASSERT(STRING_STARTS_WITH(format, "fmt"));
|
| - PrintFormat(instr);
|
| - return 3;
|
| - } else {
|
| - return FormatFRegister(instr, format);
|
| - }
|
| - }
|
| - case 's': {
|
| - ASSERT(STRING_STARTS_WITH(format, "sa"));
|
| - buffer_pos_ +=
|
| - OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
|
| - "%d", instr->SaField());
|
| - return 2;
|
| - }
|
| - default: { UNREACHABLE(); }
|
| - }
|
| - UNREACHABLE();
|
| - return -1;
|
| -}
|
| -
|
| -
|
| -// Format takes a formatting string for a whole instruction and prints it into
|
| -// the output buffer. All escaped options are handed to FormatOption to be
|
| -// parsed further.
|
| -void MIPSDecoder::Format(Instr* instr, const char* format) {
|
| - char cur = *format++;
|
| - while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) {
|
| - if (cur == '\'') { // Single quote is used as the formatting escape.
|
| - format += FormatOption(instr, format);
|
| - } else {
|
| - buffer_[buffer_pos_++] = cur;
|
| - }
|
| - cur = *format++;
|
| - }
|
| - buffer_[buffer_pos_] = '\0';
|
| -}
|
| -
|
| -
|
| -// For currently unimplemented decodings the disassembler calls Unknown(instr)
|
| -// which will just print "unknown" of the instruction bits.
|
| -void MIPSDecoder::Unknown(Instr* instr) {
|
| - Format(instr, "unknown");
|
| -}
|
| -
|
| -
|
| -void MIPSDecoder::DecodeSpecial(Instr* instr) {
|
| - ASSERT(instr->OpcodeField() == SPECIAL);
|
| - switch (instr->FunctionField()) {
|
| - case ADDU: {
|
| - Format(instr, "addu 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case AND: {
|
| - Format(instr, "and 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case BREAK: {
|
| - Format(instr, "break 'code");
|
| - if (instr->BreakCodeField() == Instr::kStopMessageCode) {
|
| - const char* message = *reinterpret_cast<const char**>(
|
| - reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
|
| - buffer_pos_ +=
|
| - OS::SNPrint(current_position_in_buffer(),
|
| - remaining_size_in_buffer(), " ; \"%s\"", message);
|
| - }
|
| - break;
|
| - }
|
| - case DIV: {
|
| - Format(instr, "div 'rs, 'rt");
|
| - break;
|
| - }
|
| - case DIVU: {
|
| - Format(instr, "divu 'rs, 'rt");
|
| - break;
|
| - }
|
| - case JALR: {
|
| - Format(instr, "jalr'hint 'rd, 'rs");
|
| - break;
|
| - }
|
| - case JR: {
|
| - Format(instr, "jr'hint 'rs");
|
| - break;
|
| - }
|
| - case MFHI: {
|
| - Format(instr, "mfhi 'rd");
|
| - break;
|
| - }
|
| - case MFLO: {
|
| - Format(instr, "mflo 'rd");
|
| - break;
|
| - }
|
| - case MOVCI: {
|
| - if (instr->Bit(16)) {
|
| - Format(instr, "movt 'rd, 'rs");
|
| - } else {
|
| - Format(instr, "movf 'rd, 'rs");
|
| - }
|
| - break;
|
| - }
|
| - case MOVN: {
|
| - Format(instr, "movn 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case MOVZ: {
|
| - Format(instr, "movz 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case MTHI: {
|
| - Format(instr, "mthi 'rs");
|
| - break;
|
| - }
|
| - case MTLO: {
|
| - Format(instr, "mtlo 'rs");
|
| - break;
|
| - }
|
| - case MULT: {
|
| - Format(instr, "mult 'rs, 'rt");
|
| - break;
|
| - }
|
| - case MULTU: {
|
| - Format(instr, "multu 'rs, 'rt");
|
| - break;
|
| - }
|
| - case NOR: {
|
| - Format(instr, "nor 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case OR: {
|
| - if (instr->RsField() == 0 && instr->RtField() == 0) {
|
| - Format(instr, "mov 'rd, 0");
|
| - } else if (instr->RsField() == R0) {
|
| - Format(instr, "mov 'rd, 'rt");
|
| - } else if (instr->RtField() == R0) {
|
| - Format(instr, "mov 'rd, 'rs");
|
| - } else {
|
| - Format(instr, "or 'rd, 'rs, 'rt");
|
| - }
|
| - break;
|
| - }
|
| - case SLL: {
|
| - if ((instr->RdField() == R0) && (instr->RtField() == R0) &&
|
| - (instr->SaField() == 0)) {
|
| - Format(instr, "nop");
|
| - } else {
|
| - Format(instr, "sll 'rd, 'rt, 'sa");
|
| - }
|
| - break;
|
| - }
|
| - case SLLV: {
|
| - Format(instr, "sllv 'rd, 'rt, 'rs");
|
| - break;
|
| - }
|
| - case SLT: {
|
| - Format(instr, "slt 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case SLTU: {
|
| - Format(instr, "sltu 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case SRA: {
|
| - if (instr->RsField() == 0) {
|
| - Format(instr, "sra 'rd, 'rt, 'sa");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| - break;
|
| - }
|
| - case SRAV: {
|
| - Format(instr, "srav 'rd, 'rt, 'rs");
|
| - break;
|
| - }
|
| - case SRL: {
|
| - if (instr->RsField() == 0) {
|
| - Format(instr, "srl 'rd, 'rt, 'sa");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| - break;
|
| - }
|
| - case SRLV: {
|
| - if (instr->SaField() == 0) {
|
| - Format(instr, "srlv 'rd, 'rt, 'rs");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| - break;
|
| - }
|
| - case SUBU: {
|
| - Format(instr, "subu 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - case XOR: {
|
| - Format(instr, "xor 'rd, 'rs, 'rt");
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -void MIPSDecoder::DecodeSpecial2(Instr* instr) {
|
| - ASSERT(instr->OpcodeField() == SPECIAL2);
|
| - switch (instr->FunctionField()) {
|
| - case MADD: {
|
| - Format(instr, "madd 'rs, 'rt");
|
| - break;
|
| - }
|
| - case MADDU: {
|
| - Format(instr, "maddu 'rs, 'rt");
|
| - break;
|
| - }
|
| - case CLO: {
|
| - Format(instr, "clo 'rd, 'rs");
|
| - break;
|
| - }
|
| - case CLZ: {
|
| - Format(instr, "clz 'rd, 'rs");
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -void MIPSDecoder::DecodeRegImm(Instr* instr) {
|
| - ASSERT(instr->OpcodeField() == REGIMM);
|
| - switch (instr->RegImmFnField()) {
|
| - case BGEZ: {
|
| - Format(instr, "bgez 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BGEZAL: {
|
| - Format(instr, "bgezal 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BLTZAL: {
|
| - Format(instr, "bltzal 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BGEZL: {
|
| - Format(instr, "bgezl 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BLTZ: {
|
| - Format(instr, "bltz 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BLTZL: {
|
| - Format(instr, "bltzl 'rs, 'dest");
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -void MIPSDecoder::DecodeCop1(Instr* instr) {
|
| - ASSERT(instr->OpcodeField() == COP1);
|
| - if (instr->HasFormat()) {
|
| - // If the rs field is a valid format, then the function field identifies
|
| - // the instruction.
|
| - switch (instr->Cop1FunctionField()) {
|
| - case COP1_ADD: {
|
| - Format(instr, "add.'fmt 'fd, 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_SUB: {
|
| - Format(instr, "sub.'fmt 'fd, 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_MUL: {
|
| - Format(instr, "mul.'fmt 'fd, 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_DIV: {
|
| - Format(instr, "div.'fmt 'fd, 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_SQRT: {
|
| - Format(instr, "sqrt.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - case COP1_MOV: {
|
| - Format(instr, "mov.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - case COP1_NEG: {
|
| - Format(instr, "neg.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - case COP1_C_F: {
|
| - Format(instr, "c.f.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_UN: {
|
| - Format(instr, "c.un.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_EQ: {
|
| - Format(instr, "c.eq.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_UEQ: {
|
| - Format(instr, "c.ueq.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_OLT: {
|
| - Format(instr, "c.olt.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_ULT: {
|
| - Format(instr, "c.ult.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_OLE: {
|
| - Format(instr, "c.ole.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_C_ULE: {
|
| - Format(instr, "c.ule.'fmt 'fs, 'ft");
|
| - break;
|
| - }
|
| - case COP1_TRUNC_W: {
|
| - Format(instr, "trunc.w.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - case COP1_CVT_S: {
|
| - Format(instr, "cvt.s.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - case COP1_CVT_D: {
|
| - Format(instr, "cvt.d.'fmt 'fd, 'fs");
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| - } else {
|
| - // If the rs field isn't a valid format, then it must be a sub-opcode.
|
| - switch (instr->Cop1SubField()) {
|
| - case COP1_MF: {
|
| - if (instr->Bits(0, 11) != 0) {
|
| - Unknown(instr);
|
| - } else {
|
| - Format(instr, "mfc1 'rt, 'fs");
|
| - }
|
| - break;
|
| - }
|
| - case COP1_MT: {
|
| - if (instr->Bits(0, 11) != 0) {
|
| - Unknown(instr);
|
| - } else {
|
| - Format(instr, "mtc1 'rt, 'fs");
|
| - }
|
| - break;
|
| - }
|
| - case COP1_BC: {
|
| - ASSERT(instr->Bit(17) == 0);
|
| - if (instr->Bit(16) == 1) { // Branch on true.
|
| - Format(instr, "bc1t 'dest");
|
| - } else { // Branch on false.
|
| - Format(instr, "bc1f 'dest");
|
| - }
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void MIPSDecoder::InstructionDecode(Instr* instr) {
|
| - switch (instr->OpcodeField()) {
|
| - case SPECIAL: {
|
| - DecodeSpecial(instr);
|
| - break;
|
| - }
|
| - case SPECIAL2: {
|
| - DecodeSpecial2(instr);
|
| - break;
|
| - }
|
| - case REGIMM: {
|
| - DecodeRegImm(instr);
|
| - break;
|
| - }
|
| - case COP1: {
|
| - DecodeCop1(instr);
|
| - break;
|
| - }
|
| - case ADDIU: {
|
| - Format(instr, "addiu 'rt, 'rs, 'imms");
|
| - break;
|
| - }
|
| - case ANDI: {
|
| - Format(instr, "andi 'rt, 'rs, 'immu");
|
| - break;
|
| - }
|
| - case BEQ: {
|
| - Format(instr, "beq 'rs, 'rt, 'dest");
|
| - break;
|
| - }
|
| - case BEQL: {
|
| - Format(instr, "beql 'rs, 'rt, 'dest");
|
| - break;
|
| - }
|
| - case BGTZ: {
|
| - Format(instr, "bgtz 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BGTZL: {
|
| - Format(instr, "bgtzl 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BLEZ: {
|
| - Format(instr, "blez 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BLEZL: {
|
| - Format(instr, "blezl 'rs, 'dest");
|
| - break;
|
| - }
|
| - case BNE: {
|
| - Format(instr, "bne 'rs, 'rt, 'dest");
|
| - break;
|
| - }
|
| - case BNEL: {
|
| - Format(instr, "bnel 'rs, 'rt, 'dest");
|
| - break;
|
| - }
|
| - case LB: {
|
| - Format(instr, "lb 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LBU: {
|
| - Format(instr, "lbu 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LDC1: {
|
| - Format(instr, "ldc1 'ft, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LH: {
|
| - Format(instr, "lh 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LHU: {
|
| - Format(instr, "lhu 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LUI: {
|
| - Format(instr, "lui 'rt, 'immu");
|
| - break;
|
| - }
|
| - case LL: {
|
| - Format(instr, "ll 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LW: {
|
| - Format(instr, "lw 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case LWC1: {
|
| - Format(instr, "lwc1 'ft, 'imms('rs)");
|
| - break;
|
| - }
|
| - case ORI: {
|
| - Format(instr, "ori 'rt, 'rs, 'immu");
|
| - break;
|
| - }
|
| - case SB: {
|
| - Format(instr, "sb 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case SC: {
|
| - Format(instr, "sc 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case SLTI: {
|
| - Format(instr, "slti 'rt, 'rs, 'imms");
|
| - break;
|
| - }
|
| - case SLTIU: {
|
| - Format(instr, "sltiu 'rt, 'rs, 'imms");
|
| - break;
|
| - }
|
| - case SH: {
|
| - Format(instr, "sh 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case SDC1: {
|
| - Format(instr, "sdc1 'ft, 'imms('rs)");
|
| - break;
|
| - }
|
| - case SW: {
|
| - Format(instr, "sw 'rt, 'imms('rs)");
|
| - break;
|
| - }
|
| - case SWC1: {
|
| - Format(instr, "swc1 'ft, 'imms('rs)");
|
| - break;
|
| - }
|
| - case XORI: {
|
| - Format(instr, "xori 'rt, 'rs, 'immu");
|
| - break;
|
| - }
|
| - default: {
|
| - Unknown(instr);
|
| - break;
|
| - }
|
| - }
|
| -}
|
| -
|
| -
|
| -void Disassembler::DecodeInstruction(char* hex_buffer,
|
| - intptr_t hex_size,
|
| - char* human_buffer,
|
| - intptr_t human_size,
|
| - int* out_instr_len,
|
| - const Code& code,
|
| - Object** object,
|
| - uword pc) {
|
| - MIPSDecoder decoder(human_buffer, human_size);
|
| - Instr* instr = Instr::At(pc);
|
| - decoder.InstructionDecode(instr);
|
| - OS::SNPrint(hex_buffer, hex_size, "%08x", instr->InstructionBits());
|
| - if (out_instr_len) {
|
| - *out_instr_len = Instr::kInstrSize;
|
| - }
|
| -
|
| - *object = NULL;
|
| - if (!code.IsNull()) {
|
| - *object = &Object::Handle();
|
| - if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
|
| - *object = NULL;
|
| - }
|
| - }
|
| -}
|
| -
|
| -#endif // !PRODUCT
|
| -
|
| -} // namespace dart
|
| -
|
| -#endif // defined TARGET_ARCH_MIPS
|
|
|