| Index: src/mips64/disasm-mips64.cc
|
| diff --git a/src/mips/disasm-mips.cc b/src/mips64/disasm-mips64.cc
|
| similarity index 84%
|
| copy from src/mips/disasm-mips.cc
|
| copy to src/mips64/disasm-mips64.cc
|
| index d64adbfd771eee4e2f6eded8044ecd106e529131..9b9cd348f754bfa9d63b5d0824b18ebab5098528 100644
|
| --- a/src/mips/disasm-mips.cc
|
| +++ b/src/mips64/disasm-mips64.cc
|
| @@ -30,12 +30,12 @@
|
|
|
| #include "src/v8.h"
|
|
|
| -#if V8_TARGET_ARCH_MIPS
|
| +#if V8_TARGET_ARCH_MIPS64
|
|
|
| #include "src/base/platform/platform.h"
|
| #include "src/disasm.h"
|
| #include "src/macro-assembler.h"
|
| -#include "src/mips/constants-mips.h"
|
| +#include "src/mips64/constants-mips64.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -97,9 +97,10 @@ class Decoder {
|
| int FormatOption(Instruction* instr, const char* option);
|
| void Format(Instruction* instr, const char* format);
|
| void Unknown(Instruction* instr);
|
| + int DecodeBreakInstr(Instruction* instr);
|
|
|
| // Each of these functions decodes one particular instruction type.
|
| - void DecodeTypeRegister(Instruction* instr);
|
| + int DecodeTypeRegister(Instruction* instr);
|
| void DecodeTypeImmediate(Instruction* instr);
|
| void DecodeTypeJump(Instruction* instr);
|
|
|
| @@ -437,7 +438,31 @@ void Decoder::Unknown(Instruction* instr) {
|
| }
|
|
|
|
|
| -void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| +int Decoder::DecodeBreakInstr(Instruction* instr) {
|
| + // This is already known to be BREAK instr, just extract the code.
|
| + if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) {
|
| + // This is stop(msg).
|
| + Format(instr, "break, code: 'code");
|
| + out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| + "\n%p %08lx stop msg: %s",
|
| + static_cast<void*>
|
| + (reinterpret_cast<int32_t*>(instr
|
| + + Instruction::kInstrSize)),
|
| + reinterpret_cast<uint64_t>
|
| + (*reinterpret_cast<char**>(instr
|
| + + Instruction::kInstrSize)),
|
| + *reinterpret_cast<char**>(instr
|
| + + Instruction::kInstrSize));
|
| + // Size 3: the break_ instr, plus embedded 64-bit char pointer.
|
| + return 3 * Instruction::kInstrSize;
|
| + } else {
|
| + Format(instr, "break, code: 'code");
|
| + return Instruction::kInstrSize;
|
| + }
|
| +}
|
| +
|
| +
|
| +int Decoder::DecodeTypeRegister(Instruction* instr) {
|
| switch (instr->OpcodeFieldRaw()) {
|
| case COP1: // Coprocessor instructions.
|
| switch (instr->RsFieldRaw()) {
|
| @@ -447,12 +472,18 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| case MFC1:
|
| Format(instr, "mfc1 'rt, 'fs");
|
| break;
|
| + case DMFC1:
|
| + Format(instr, "dmfc1 'rt, 'fs");
|
| + break;
|
| case MFHC1:
|
| Format(instr, "mfhc1 'rt, 'fs");
|
| break;
|
| case MTC1:
|
| Format(instr, "mtc1 'rt, 'fs");
|
| break;
|
| + case DMTC1:
|
| + Format(instr, "dmtc1 'rt, 'fs");
|
| + break;
|
| // These are called "fs" too, although they are not FPU registers.
|
| case CTC1:
|
| Format(instr, "ctc1 'rt, 'fs");
|
| @@ -492,34 +523,33 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| case CVT_W_D:
|
| Format(instr, "cvt.w.d 'fd, 'fs");
|
| break;
|
| - case CVT_L_D: {
|
| - if (kArchVariant == kMips32r2) {
|
| - Format(instr, "cvt.l.d 'fd, 'fs");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| + case CVT_L_D:
|
| + Format(instr, "cvt.l.d 'fd, 'fs");
|
| break;
|
| - }
|
| case TRUNC_W_D:
|
| Format(instr, "trunc.w.d 'fd, 'fs");
|
| break;
|
| - case TRUNC_L_D: {
|
| - if (kArchVariant == kMips32r2) {
|
| - Format(instr, "trunc.l.d 'fd, 'fs");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| + case TRUNC_L_D:
|
| + Format(instr, "trunc.l.d 'fd, 'fs");
|
| break;
|
| - }
|
| case ROUND_W_D:
|
| Format(instr, "round.w.d 'fd, 'fs");
|
| break;
|
| + case ROUND_L_D:
|
| + Format(instr, "round.l.d 'fd, 'fs");
|
| + break;
|
| case FLOOR_W_D:
|
| Format(instr, "floor.w.d 'fd, 'fs");
|
| break;
|
| + case FLOOR_L_D:
|
| + Format(instr, "floor.l.d 'fd, 'fs");
|
| + break;
|
| case CEIL_W_D:
|
| Format(instr, "ceil.w.d 'fd, 'fs");
|
| break;
|
| + case CEIL_L_D:
|
| + Format(instr, "ceil.l.d 'fd, 'fs");
|
| + break;
|
| case CVT_S_D:
|
| Format(instr, "cvt.s.d 'fd, 'fs");
|
| break;
|
| @@ -569,22 +599,12 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| break;
|
| case L:
|
| switch (instr->FunctionFieldRaw()) {
|
| - case CVT_D_L: {
|
| - if (kArchVariant == kMips32r2) {
|
| - Format(instr, "cvt.d.l 'fd, 'fs");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| + case CVT_D_L:
|
| + Format(instr, "cvt.d.l 'fd, 'fs");
|
| break;
|
| - }
|
| - case CVT_S_L: {
|
| - if (kArchVariant == kMips32r2) {
|
| - Format(instr, "cvt.s.l 'fd, 'fs");
|
| - } else {
|
| - Unknown(instr);
|
| - }
|
| + case CVT_S_L:
|
| + Format(instr, "cvt.s.l 'fd, 'fs");
|
| break;
|
| - }
|
| default:
|
| UNREACHABLE();
|
| }
|
| @@ -619,37 +639,80 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| else
|
| Format(instr, "sll 'rd, 'rt, 'sa");
|
| break;
|
| + case DSLL:
|
| + Format(instr, "dsll 'rd, 'rt, 'sa");
|
| + break;
|
| + case DSLL32:
|
| + Format(instr, "dsll32 'rd, 'rt, 'sa");
|
| + break;
|
| case SRL:
|
| if (instr->RsValue() == 0) {
|
| Format(instr, "srl 'rd, 'rt, 'sa");
|
| } else {
|
| - if (kArchVariant == kMips32r2) {
|
| + if (kArchVariant == kMips64r2) {
|
| Format(instr, "rotr 'rd, 'rt, 'sa");
|
| } else {
|
| Unknown(instr);
|
| }
|
| }
|
| break;
|
| + case DSRL:
|
| + if (instr->RsValue() == 0) {
|
| + Format(instr, "dsrl 'rd, 'rt, 'sa");
|
| + } else {
|
| + if (kArchVariant == kMips64r2) {
|
| + Format(instr, "drotr 'rd, 'rt, 'sa");
|
| + } else {
|
| + Unknown(instr);
|
| + }
|
| + }
|
| + break;
|
| + case DSRL32:
|
| + Format(instr, "dsrl32 'rd, 'rt, 'sa");
|
| + break;
|
| case SRA:
|
| Format(instr, "sra 'rd, 'rt, 'sa");
|
| break;
|
| + case DSRA:
|
| + Format(instr, "dsra 'rd, 'rt, 'sa");
|
| + break;
|
| + case DSRA32:
|
| + Format(instr, "dsra32 'rd, 'rt, 'sa");
|
| + break;
|
| case SLLV:
|
| Format(instr, "sllv 'rd, 'rt, 'rs");
|
| break;
|
| + case DSLLV:
|
| + Format(instr, "dsllv 'rd, 'rt, 'rs");
|
| + break;
|
| case SRLV:
|
| if (instr->SaValue() == 0) {
|
| Format(instr, "srlv 'rd, 'rt, 'rs");
|
| } else {
|
| - if (kArchVariant == kMips32r2) {
|
| + if (kArchVariant == kMips64r2) {
|
| Format(instr, "rotrv 'rd, 'rt, 'rs");
|
| } else {
|
| Unknown(instr);
|
| }
|
| }
|
| break;
|
| + case DSRLV:
|
| + if (instr->SaValue() == 0) {
|
| + Format(instr, "dsrlv 'rd, 'rt, 'rs");
|
| + } else {
|
| + if (kArchVariant == kMips64r2) {
|
| + Format(instr, "drotrv 'rd, 'rt, 'rs");
|
| + } else {
|
| + Unknown(instr);
|
| + }
|
| + }
|
| + break;
|
| case SRAV:
|
| Format(instr, "srav 'rd, 'rt, 'rs");
|
| break;
|
| + case DSRAV:
|
| + Format(instr, "dsrav 'rd, 'rt, 'rs");
|
| + break;
|
| case MFHI:
|
| Format(instr, "mfhi 'rd");
|
| break;
|
| @@ -659,27 +722,51 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| case MULT:
|
| Format(instr, "mult 'rs, 'rt");
|
| break;
|
| + case DMULT:
|
| + Format(instr, "dmult 'rs, 'rt");
|
| + break;
|
| case MULTU:
|
| Format(instr, "multu 'rs, 'rt");
|
| break;
|
| + case DMULTU:
|
| + Format(instr, "dmultu 'rs, 'rt");
|
| + break;
|
| case DIV:
|
| Format(instr, "div 'rs, 'rt");
|
| break;
|
| + case DDIV:
|
| + Format(instr, "ddiv 'rs, 'rt");
|
| + break;
|
| case DIVU:
|
| Format(instr, "divu 'rs, 'rt");
|
| break;
|
| + case DDIVU:
|
| + Format(instr, "ddivu 'rs, 'rt");
|
| + break;
|
| case ADD:
|
| Format(instr, "add 'rd, 'rs, 'rt");
|
| break;
|
| + case DADD:
|
| + Format(instr, "dadd 'rd, 'rs, 'rt");
|
| + break;
|
| case ADDU:
|
| Format(instr, "addu 'rd, 'rs, 'rt");
|
| break;
|
| + case DADDU:
|
| + Format(instr, "daddu 'rd, 'rs, 'rt");
|
| + break;
|
| case SUB:
|
| Format(instr, "sub 'rd, 'rs, 'rt");
|
| break;
|
| + case DSUB:
|
| + Format(instr, "dsub 'rd, 'rs, 'rt");
|
| + break;
|
| case SUBU:
|
| Format(instr, "subu 'rd, 'rs, 'rt");
|
| break;
|
| + case DSUBU:
|
| + Format(instr, "dsubu 'rd, 'rs, 'rt");
|
| + break;
|
| case AND:
|
| Format(instr, "and 'rd, 'rs, 'rt");
|
| break;
|
| @@ -705,8 +792,7 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| Format(instr, "sltu 'rd, 'rs, 'rt");
|
| break;
|
| case BREAK:
|
| - Format(instr, "break, code: 'code");
|
| - break;
|
| + return DecodeBreakInstr(instr);
|
| case TGE:
|
| Format(instr, "tge 'rs, 'rt, code: 'code");
|
| break;
|
| @@ -757,7 +843,7 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| case SPECIAL3:
|
| switch (instr->FunctionFieldRaw()) {
|
| case INS: {
|
| - if (kArchVariant == kMips32r2) {
|
| + if (kArchVariant == kMips64r2) {
|
| Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
|
| } else {
|
| Unknown(instr);
|
| @@ -765,7 +851,7 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| break;
|
| }
|
| case EXT: {
|
| - if (kArchVariant == kMips32r2) {
|
| + if (kArchVariant == kMips64r2) {
|
| Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
|
| } else {
|
| Unknown(instr);
|
| @@ -779,6 +865,7 @@ void Decoder::DecodeTypeRegister(Instruction* instr) {
|
| default:
|
| UNREACHABLE();
|
| }
|
| + return Instruction::kInstrSize;
|
| }
|
|
|
|
|
| @@ -833,9 +920,15 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| case ADDI:
|
| Format(instr, "addi 'rt, 'rs, 'imm16s");
|
| break;
|
| + case DADDI:
|
| + Format(instr, "daddi 'rt, 'rs, 'imm16s");
|
| + break;
|
| case ADDIU:
|
| Format(instr, "addiu 'rt, 'rs, 'imm16s");
|
| break;
|
| + case DADDIU:
|
| + Format(instr, "daddiu 'rt, 'rs, 'imm16s");
|
| + break;
|
| case SLTI:
|
| Format(instr, "slti 'rt, 'rs, 'imm16s");
|
| break;
|
| @@ -864,9 +957,18 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| case LWL:
|
| Format(instr, "lwl 'rt, 'imm16s('rs)");
|
| break;
|
| + case LDL:
|
| + Format(instr, "ldl 'rt, 'imm16s('rs)");
|
| + break;
|
| case LW:
|
| Format(instr, "lw 'rt, 'imm16s('rs)");
|
| break;
|
| + case LWU:
|
| + Format(instr, "lwu 'rt, 'imm16s('rs)");
|
| + break;
|
| + case LD:
|
| + Format(instr, "ld 'rt, 'imm16s('rs)");
|
| + break;
|
| case LBU:
|
| Format(instr, "lbu 'rt, 'imm16s('rs)");
|
| break;
|
| @@ -876,6 +978,9 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| case LWR:
|
| Format(instr, "lwr 'rt, 'imm16s('rs)");
|
| break;
|
| + case LDR:
|
| + Format(instr, "ldr 'rt, 'imm16s('rs)");
|
| + break;
|
| case PREF:
|
| Format(instr, "pref 'rt, 'imm16s('rs)");
|
| break;
|
| @@ -891,6 +996,9 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| case SW:
|
| Format(instr, "sw 'rt, 'imm16s('rs)");
|
| break;
|
| + case SD:
|
| + Format(instr, "sd 'rt, 'imm16s('rs)");
|
| + break;
|
| case SWR:
|
| Format(instr, "swr 'rt, 'imm16s('rs)");
|
| break;
|
| @@ -907,7 +1015,8 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| Format(instr, "sdc1 'ft, 'imm16s('rs)");
|
| break;
|
| default:
|
| - UNREACHABLE();
|
| + printf("a 0x%x \n", instr->OpcodeFieldRaw());
|
| + UNREACHABLE();
|
| break;
|
| }
|
| }
|
| @@ -928,16 +1037,18 @@ void Decoder::DecodeTypeJump(Instruction* instr) {
|
|
|
|
|
| // Disassemble the instruction at *instr_ptr into the output buffer.
|
| +// All instructions are one word long, except for the simulator
|
| +// psuedo-instruction stop(msg). For that one special case, we return
|
| +// size larger than one kInstrSize.
|
| int Decoder::InstructionDecode(byte* instr_ptr) {
|
| Instruction* instr = Instruction::At(instr_ptr);
|
| // Print raw instruction bytes.
|
| out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
| - "%08x ",
|
| - instr->InstructionBits());
|
| + "%08x ",
|
| + instr->InstructionBits());
|
| switch (instr->InstructionType()) {
|
| case Instruction::kRegisterType: {
|
| - DecodeTypeRegister(instr);
|
| - break;
|
| + return DecodeTypeRegister(instr);
|
| }
|
| case Instruction::kImmediateType: {
|
| DecodeTypeImmediate(instr);
|
| @@ -1038,4 +1149,4 @@ void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
|
|
|
| } // namespace disasm
|
|
|
| -#endif // V8_TARGET_ARCH_MIPS
|
| +#endif // V8_TARGET_ARCH_MIPS64
|
|
|