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 |