Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc
index 4f725cf..936514a 100644
--- a/src/mips/disasm-mips.cc
+++ b/src/mips/disasm-mips.cc
@@ -22,14 +22,11 @@
// of code into a FILE*, meaning that the above functionality could also be
// achieved by just calling Disassembler::Disassemble(stdout, begin, end);
-
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
-#include "src/v8.h"
-
#if V8_TARGET_ARCH_MIPS
#include "src/base/platform/platform.h"
@@ -69,6 +66,7 @@
// Printing of common values.
void PrintRegister(int reg);
void PrintFPURegister(int freg);
+ void PrintFPUStatusRegister(int freg);
void PrintRs(Instruction* instr);
void PrintRt(Instruction* instr);
void PrintRd(Instruction* instr);
@@ -76,19 +74,32 @@
void PrintFt(Instruction* instr);
void PrintFd(Instruction* instr);
void PrintSa(Instruction* instr);
+ void PrintLsaSa(Instruction* instr);
void PrintSd(Instruction* instr);
void PrintSs1(Instruction* instr);
void PrintSs2(Instruction* instr);
void PrintBc(Instruction* instr);
void PrintCc(Instruction* instr);
+ void PrintBp2(Instruction* instr);
void PrintFunction(Instruction* instr);
void PrintSecondaryField(Instruction* instr);
void PrintUImm16(Instruction* instr);
void PrintSImm16(Instruction* instr);
void PrintXImm16(Instruction* instr);
+ void PrintPCImm16(Instruction* instr, int delta_pc, int n_bits);
+ void PrintXImm18(Instruction* instr);
+ void PrintSImm18(Instruction* instr);
+ void PrintXImm19(Instruction* instr);
+ void PrintSImm19(Instruction* instr);
void PrintXImm21(Instruction* instr);
+ void PrintSImm21(Instruction* instr);
+ void PrintPCImm21(Instruction* instr, int delta_pc, int n_bits);
void PrintXImm26(Instruction* instr);
+ void PrintSImm26(Instruction* instr);
+ void PrintPCImm26(Instruction* instr, int delta_pc, int n_bits);
+ void PrintPCImm26(Instruction* instr);
void PrintCode(Instruction* instr); // For break and trap instructions.
+ void PrintFormat(Instruction* instr); // For floating format postfix.
// Printing of instruction name.
void PrintInstructionName(Instruction* instr);
@@ -99,7 +110,16 @@
void Format(Instruction* instr, const char* format);
void Unknown(Instruction* instr);
+
// Each of these functions decodes one particular instruction type.
+ bool DecodeTypeRegisterRsType(Instruction* instr);
+ void DecodeTypeRegisterSRsType(Instruction* instr);
+ void DecodeTypeRegisterDRsType(Instruction* instr);
+ void DecodeTypeRegisterLRsType(Instruction* instr);
+ void DecodeTypeRegisterWRsType(Instruction* instr);
+ void DecodeTypeRegisterSPECIAL(Instruction* instr);
+ void DecodeTypeRegisterSPECIAL2(Instruction* instr);
+ void DecodeTypeRegisterSPECIAL3(Instruction* instr);
void DecodeTypeRegister(Instruction* instr);
void DecodeTypeImmediate(Instruction* instr);
void DecodeTypeJump(Instruction* instr);
@@ -164,6 +184,17 @@
}
+void Decoder::PrintFPUStatusRegister(int freg) {
+ switch (freg) {
+ case kFCSRRegister:
+ Print("FCSR");
+ break;
+ default:
+ Print(converter_.NameOfXMMRegister(freg));
+ }
+}
+
+
void Decoder::PrintFs(Instruction* instr) {
int freg = instr->RsValue();
PrintFPURegister(freg);
@@ -189,6 +220,13 @@
}
+// Print the integer value of the sa field of a lsa instruction.
+void Decoder::PrintLsaSa(Instruction* instr) {
+ int sa = instr->LsaSaValue() + 1;
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa);
+}
+
+
// Print the integer value of the rd field, when it is not used as reg.
void Decoder::PrintSd(Instruction* instr) {
int sd = instr->RdValue();
@@ -226,6 +264,12 @@
}
+void Decoder::PrintBp2(Instruction* instr) {
+ int bp2 = instr->Bp2Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp2);
+}
+
+
// Print 16-bit unsigned immediate value.
void Decoder::PrintUImm16(Instruction* instr) {
int32_t imm = instr->Imm16Value();
@@ -247,6 +291,50 @@
}
+// Print absoulte address for 16-bit offset or immediate value.
+// The absolute address is calculated according following expression:
+// PC + delta_pc + (offset << n_bits)
+void Decoder::PrintPCImm16(Instruction* instr, int delta_pc, int n_bits) {
+ int16_t offset = instr->Imm16Value();
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
+ delta_pc + (offset << n_bits)));
+}
+
+
+// Print 18-bit signed immediate value.
+void Decoder::PrintSImm18(Instruction* instr) {
+ int32_t imm =
+ ((instr->Imm18Value()) << (32 - kImm18Bits)) >> (32 - kImm18Bits);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm);
+}
+
+
+// Print 18-bit hexa immediate value.
+void Decoder::PrintXImm18(Instruction* instr) {
+ int32_t imm = instr->Imm18Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
+}
+
+
+// Print 19-bit hexa immediate value.
+void Decoder::PrintXImm19(Instruction* instr) {
+ int32_t imm = instr->Imm19Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
+}
+
+
+// Print 19-bit signed immediate value.
+void Decoder::PrintSImm19(Instruction* instr) {
+ int32_t imm19 = instr->Imm19Value();
+ // set sign
+ imm19 <<= (32 - kImm19Bits);
+ imm19 >>= (32 - kImm19Bits);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm19);
+}
+
+
// Print 21-bit immediate value.
void Decoder::PrintXImm21(Instruction* instr) {
uint32_t imm = instr->Imm21Value();
@@ -254,10 +342,75 @@
}
-// Print 26-bit immediate value.
+// Print 21-bit signed immediate value.
+void Decoder::PrintSImm21(Instruction* instr) {
+ int32_t imm21 = instr->Imm21Value();
+ // set sign
+ imm21 <<= (32 - kImm21Bits);
+ imm21 >>= (32 - kImm21Bits);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm21);
+}
+
+
+// Print absoulte address for 21-bit offset or immediate value.
+// The absolute address is calculated according following expression:
+// PC + delta_pc + (offset << n_bits)
+void Decoder::PrintPCImm21(Instruction* instr, int delta_pc, int n_bits) {
+ int32_t imm21 = instr->Imm21Value();
+ // set sign
+ imm21 <<= (32 - kImm21Bits);
+ imm21 >>= (32 - kImm21Bits);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
+ delta_pc + (imm21 << n_bits)));
+}
+
+
+// Print 26-bit hex immediate value.
void Decoder::PrintXImm26(Instruction* instr) {
- uint32_t imm = instr->Imm26Value() << kImmFieldShift;
- out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
+ uint32_t target = static_cast<uint32_t>(instr->Imm26Value())
+ << kImmFieldShift;
+ target = (reinterpret_cast<uint32_t>(instr) & ~0xfffffff) | target;
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", target);
+}
+
+
+// Print 26-bit signed immediate value.
+void Decoder::PrintSImm26(Instruction* instr) {
+ int32_t imm26 = instr->Imm26Value();
+ // set sign
+ imm26 <<= (32 - kImm26Bits);
+ imm26 >>= (32 - kImm26Bits);
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm26);
+}
+
+
+// Print absoulte address for 26-bit offset or immediate value.
+// The absolute address is calculated according following expression:
+// PC + delta_pc + (offset << n_bits)
+void Decoder::PrintPCImm26(Instruction* instr, int delta_pc, int n_bits) {
+ int32_t imm26 = instr->Imm26Value();
+ // set sign
+ imm26 <<= (32 - kImm26Bits);
+ imm26 >>= (32 - kImm26Bits);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
+ converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
+ delta_pc + (imm26 << n_bits)));
+}
+
+
+// Print absoulte address for 26-bit offset or immediate value.
+// The absolute address is calculated according following expression:
+// PC[GPRLEN-1 .. 28] || instr_index26 || 00
+void Decoder::PrintPCImm26(Instruction* instr) {
+ int32_t imm26 = instr->Imm26Value();
+ uint32_t pc_mask = ~0xfffffff;
+ uint32_t pc = ((uint32_t)(instr + 1) & pc_mask) | (imm26 << 2);
+ out_buffer_pos_ +=
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
+ converter_.NameOfAddress((reinterpret_cast<byte*>(pc))));
}
@@ -289,6 +442,29 @@
}
+void Decoder::PrintFormat(Instruction* instr) {
+ char formatLetter = ' ';
+ switch (instr->RsFieldRaw()) {
+ case S:
+ formatLetter = 's';
+ break;
+ case D:
+ formatLetter = 'd';
+ break;
+ case W:
+ formatLetter = 'w';
+ break;
+ case L:
+ formatLetter = 'l';
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ PrintChar(formatLetter);
+}
+
+
// Printing of instruction name.
void Decoder::PrintInstructionName(Instruction* instr) {
}
@@ -320,22 +496,42 @@
// complexity of FormatOption.
int Decoder::FormatFPURegister(Instruction* instr, const char* format) {
DCHECK(format[0] == 'f');
- if (format[1] == 's') { // 'fs: fs register.
- int reg = instr->FsValue();
- PrintFPURegister(reg);
- return 2;
- } else if (format[1] == 't') { // 'ft: ft register.
- int reg = instr->FtValue();
- PrintFPURegister(reg);
- return 2;
- } else if (format[1] == 'd') { // 'fd: fd register.
- int reg = instr->FdValue();
- PrintFPURegister(reg);
- return 2;
- } else if (format[1] == 'r') { // 'fr: fr register.
- int reg = instr->FrValue();
- PrintFPURegister(reg);
- return 2;
+ if ((CTC1 == instr->RsFieldRaw()) || (CFC1 == instr->RsFieldRaw())) {
+ if (format[1] == 's') { // 'fs: fs register.
+ int reg = instr->FsValue();
+ PrintFPUStatusRegister(reg);
+ return 2;
+ } else if (format[1] == 't') { // 'ft: ft register.
+ int reg = instr->FtValue();
+ PrintFPUStatusRegister(reg);
+ return 2;
+ } else if (format[1] == 'd') { // 'fd: fd register.
+ int reg = instr->FdValue();
+ PrintFPUStatusRegister(reg);
+ return 2;
+ } else if (format[1] == 'r') { // 'fr: fr register.
+ int reg = instr->FrValue();
+ PrintFPUStatusRegister(reg);
+ return 2;
+ }
+ } else {
+ if (format[1] == 's') { // 'fs: fs register.
+ int reg = instr->FsValue();
+ PrintFPURegister(reg);
+ return 2;
+ } else if (format[1] == 't') { // 'ft: ft register.
+ int reg = instr->FtValue();
+ PrintFPURegister(reg);
+ return 2;
+ } else if (format[1] == 'd') { // 'fd: fd register.
+ int reg = instr->FdValue();
+ PrintFPURegister(reg);
+ return 2;
+ } else if (format[1] == 'r') { // 'fr: fr register.
+ int reg = instr->FrValue();
+ PrintFPURegister(reg);
+ return 2;
+ }
}
UNREACHABLE();
return -1;
@@ -356,25 +552,134 @@
}
case 'i': { // 'imm16u or 'imm26.
if (format[3] == '1') {
- DCHECK(STRING_STARTS_WITH(format, "imm16"));
- if (format[5] == 's') {
- DCHECK(STRING_STARTS_WITH(format, "imm16s"));
- PrintSImm16(instr);
- } else if (format[5] == 'u') {
- DCHECK(STRING_STARTS_WITH(format, "imm16u"));
- PrintSImm16(instr);
- } else {
- DCHECK(STRING_STARTS_WITH(format, "imm16x"));
- PrintXImm16(instr);
+ if (format[4] == '6') {
+ DCHECK(STRING_STARTS_WITH(format, "imm16"));
+ switch (format[5]) {
+ case 's':
+ DCHECK(STRING_STARTS_WITH(format, "imm16s"));
+ PrintSImm16(instr);
+ break;
+ case 'u':
+ DCHECK(STRING_STARTS_WITH(format, "imm16u"));
+ PrintSImm16(instr);
+ break;
+ case 'x':
+ DCHECK(STRING_STARTS_WITH(format, "imm16x"));
+ PrintXImm16(instr);
+ break;
+ case 'p': { // The PC relative address.
+ DCHECK(STRING_STARTS_WITH(format, "imm16p"));
+ int delta_pc = 0;
+ int n_bits = 0;
+ switch (format[6]) {
+ case '4': {
+ DCHECK(STRING_STARTS_WITH(format, "imm16p4"));
+ delta_pc = 4;
+ switch (format[8]) {
+ case '2':
+ DCHECK(STRING_STARTS_WITH(format, "imm16p4s2"));
+ n_bits = 2;
+ PrintPCImm16(instr, delta_pc, n_bits);
+ return 9;
+ }
+ }
+ }
+ }
+ }
+ return 6;
+ } else if (format[4] == '8') {
+ DCHECK(STRING_STARTS_WITH(format, "imm18"));
+ switch (format[5]) {
+ case 's':
+ DCHECK(STRING_STARTS_WITH(format, "imm18s"));
+ PrintSImm18(instr);
+ break;
+ case 'x':
+ DCHECK(STRING_STARTS_WITH(format, "imm18x"));
+ PrintXImm18(instr);
+ break;
+ }
+ return 6;
+ } else if (format[4] == '9') {
+ DCHECK(STRING_STARTS_WITH(format, "imm19"));
+ switch (format[5]) {
+ case 's':
+ DCHECK(STRING_STARTS_WITH(format, "imm19s"));
+ PrintSImm19(instr);
+ break;
+ case 'x':
+ DCHECK(STRING_STARTS_WITH(format, "imm19x"));
+ PrintXImm19(instr);
+ break;
+ }
+ return 6;
+ }
+ } else if (format[3] == '2' && format[4] == '1') {
+ DCHECK(STRING_STARTS_WITH(format, "imm21"));
+ switch (format[5]) {
+ case 's':
+ DCHECK(STRING_STARTS_WITH(format, "imm21s"));
+ PrintSImm21(instr);
+ break;
+ case 'x':
+ DCHECK(STRING_STARTS_WITH(format, "imm21x"));
+ PrintXImm21(instr);
+ break;
+ case 'p': { // The PC relative address.
+ DCHECK(STRING_STARTS_WITH(format, "imm21p"));
+ int delta_pc = 0;
+ int n_bits = 0;
+ switch (format[6]) {
+ case '4': {
+ DCHECK(STRING_STARTS_WITH(format, "imm21p4"));
+ delta_pc = 4;
+ switch (format[8]) {
+ case '2':
+ DCHECK(STRING_STARTS_WITH(format, "imm21p4s2"));
+ n_bits = 2;
+ PrintPCImm21(instr, delta_pc, n_bits);
+ return 9;
+ }
+ }
+ }
+ }
}
return 6;
- } else if (format[3] == '2' && format[4] == '1') {
- DCHECK(STRING_STARTS_WITH(format, "imm21x"));
- PrintXImm21(instr);
- return 6;
} else if (format[3] == '2' && format[4] == '6') {
- DCHECK(STRING_STARTS_WITH(format, "imm26x"));
- PrintXImm26(instr);
+ DCHECK(STRING_STARTS_WITH(format, "imm26"));
+ switch (format[5]) {
+ case 's':
+ DCHECK(STRING_STARTS_WITH(format, "imm26s"));
+ PrintSImm26(instr);
+ break;
+ case 'x':
+ DCHECK(STRING_STARTS_WITH(format, "imm26x"));
+ PrintXImm26(instr);
+ break;
+ case 'p': { // The PC relative address.
+ DCHECK(STRING_STARTS_WITH(format, "imm26p"));
+ int delta_pc = 0;
+ int n_bits = 0;
+ switch (format[6]) {
+ case '4': {
+ DCHECK(STRING_STARTS_WITH(format, "imm26p4"));
+ delta_pc = 4;
+ switch (format[8]) {
+ case '2':
+ DCHECK(STRING_STARTS_WITH(format, "imm26p4s2"));
+ n_bits = 2;
+ PrintPCImm26(instr, delta_pc, n_bits);
+ return 9;
+ }
+ }
+ }
+ }
+ case 'j': { // Absolute address for jump instructions.
+ DCHECK(STRING_STARTS_WITH(format, "imm26j"));
+ PrintPCImm26(instr);
+ break;
+ }
+ }
return 6;
}
}
@@ -386,11 +691,17 @@
}
case 's': { // 'sa.
switch (format[1]) {
- case 'a': {
- DCHECK(STRING_STARTS_WITH(format, "sa"));
- PrintSa(instr);
- return 2;
- }
+ case 'a':
+ if (format[2] == '2') {
+ DCHECK(STRING_STARTS_WITH(format, "sa2")); // 'sa2
+ PrintLsaSa(instr);
+ return 3;
+ } else {
+ DCHECK(STRING_STARTS_WITH(format, "sa"));
+ PrintSa(instr);
+ return 2;
+ }
+ break;
case 'd': {
DCHECK(STRING_STARTS_WITH(format, "sd"));
PrintSd(instr);
@@ -409,16 +720,32 @@
}
}
}
- case 'b': { // 'bc - Special for bc1 cc field.
- DCHECK(STRING_STARTS_WITH(format, "bc"));
- PrintBc(instr);
- return 2;
+ case 'b': {
+ switch (format[1]) {
+ case 'c': { // 'bc - Special for bc1 cc field.
+ DCHECK(STRING_STARTS_WITH(format, "bc"));
+ PrintBc(instr);
+ return 2;
+ }
+ case 'p': {
+ switch (format[2]) {
+ case '2': { // 'bp2
+ DCHECK(STRING_STARTS_WITH(format, "bp2"));
+ PrintBp2(instr);
+ return 3;
+ }
+ }
+ }
+ }
}
case 'C': { // 'Cc - Special for c.xx.d cc field.
DCHECK(STRING_STARTS_WITH(format, "Cc"));
PrintCc(instr);
return 2;
}
+ case 't':
+ PrintFormat(instr);
+ return 1;
}
UNREACHABLE();
return -1;
@@ -449,6 +776,521 @@
}
+bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case RINT:
+ Format(instr, "rint.'t 'fd, 'fs");
+ break;
+ case MIN:
+ Format(instr, "min.'t 'fd, 'fs, 'ft");
+ break;
+ case MAX:
+ Format(instr, "max.'t 'fd, 'fs, 'ft");
+ break;
+ case MINA:
+ Format(instr, "mina.'t 'fd, 'fs, 'ft");
+ break;
+ case MAXA:
+ Format(instr, "maxa.'t 'fd, 'fs, 'ft");
+ break;
+ case SEL:
+ Format(instr, "sel.'t 'fd, 'fs, 'ft");
+ break;
+ case SELEQZ_C:
+ Format(instr, "seleqz.'t 'fd, 'fs, 'ft");
+ break;
+ case SELNEZ_C:
+ Format(instr, "selnez.'t 'fd, 'fs, 'ft");
+ break;
+ case MOVZ_C:
+ Format(instr, "movz.'t 'fd, 'fs, 'rt");
+ break;
+ case MOVN_C:
+ Format(instr, "movn.'t 'fd, 'fs, 'rt");
+ break;
+ case MOVF:
+ if (instr->Bit(16)) {
+ Format(instr, "movt.'t 'fd, 'fs, 'Cc");
+ } else {
+ Format(instr, "movf.'t 'fd, 'fs, 'Cc");
+ }
+ break;
+ case ADD_D:
+ Format(instr, "add.'t 'fd, 'fs, 'ft");
+ break;
+ case SUB_D:
+ Format(instr, "sub.'t 'fd, 'fs, 'ft");
+ break;
+ case MUL_D:
+ Format(instr, "mul.'t 'fd, 'fs, 'ft");
+ break;
+ case DIV_D:
+ Format(instr, "div.'t 'fd, 'fs, 'ft");
+ break;
+ case ABS_D:
+ Format(instr, "abs.'t 'fd, 'fs");
+ break;
+ case MOV_D:
+ Format(instr, "mov.'t 'fd, 'fs");
+ break;
+ case NEG_D:
+ Format(instr, "neg.'t 'fd, 'fs");
+ break;
+ case SQRT_D:
+ Format(instr, "sqrt.'t 'fd, 'fs");
+ break;
+ case RECIP_D:
+ Format(instr, "recip.'t 'fd, 'fs");
+ break;
+ case RSQRT_D:
+ Format(instr, "rsqrt.'t 'fd, 'fs");
+ break;
+ case CVT_W_D:
+ Format(instr, "cvt.w.'t 'fd, 'fs");
+ break;
+ case CVT_L_D:
+ Format(instr, "cvt.l.'t 'fd, 'fs");
+ break;
+ case TRUNC_W_D:
+ Format(instr, "trunc.w.'t 'fd, 'fs");
+ break;
+ case TRUNC_L_D:
+ Format(instr, "trunc.l.'t 'fd, 'fs");
+ break;
+ case ROUND_W_D:
+ Format(instr, "round.w.'t 'fd, 'fs");
+ break;
+ case ROUND_L_D:
+ Format(instr, "round.l.'t 'fd, 'fs");
+ break;
+ case FLOOR_W_D:
+ Format(instr, "floor.w.'t 'fd, 'fs");
+ break;
+ case FLOOR_L_D:
+ Format(instr, "floor.l.'t 'fd, 'fs");
+ break;
+ case CEIL_W_D:
+ Format(instr, "ceil.w.'t 'fd, 'fs");
+ break;
+ case CLASS_D:
+ Format(instr, "class.'t 'fd, 'fs");
+ break;
+ case CEIL_L_D:
+ Format(instr, "ceil.l.'t 'fd, 'fs");
+ break;
+ case CVT_S_D:
+ Format(instr, "cvt.s.'t 'fd, 'fs");
+ break;
+ case C_F_D:
+ Format(instr, "c.f.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_UN_D:
+ Format(instr, "c.un.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_EQ_D:
+ Format(instr, "c.eq.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_UEQ_D:
+ Format(instr, "c.ueq.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_OLT_D:
+ Format(instr, "c.olt.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_ULT_D:
+ Format(instr, "c.ult.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_OLE_D:
+ Format(instr, "c.ole.'t 'fs, 'ft, 'Cc");
+ break;
+ case C_ULE_D:
+ Format(instr, "c.ule.'t 'fs, 'ft, 'Cc");
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) {
+ if (!DecodeTypeRegisterRsType(instr)) {
+ switch (instr->FunctionFieldRaw()) {
+ case CVT_D_S:
+ Format(instr, "cvt.d.'t 'fd, 'fs");
+ break;
+ default:
+ Format(instr, "unknown.cop1.'t");
+ break;
+ }
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) {
+ if (!DecodeTypeRegisterRsType(instr)) {
+ Format(instr, "unknown.cop1.'t");
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case CVT_D_L:
+ Format(instr, "cvt.d.l 'fd, 'fs");
+ break;
+ case CVT_S_L:
+ Format(instr, "cvt.s.l 'fd, 'fs");
+ break;
+ case CMP_AF:
+ Format(instr, "cmp.af.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_UN:
+ Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_EQ:
+ Format(instr, "cmp.eq.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_UEQ:
+ Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_LT:
+ Format(instr, "cmp.lt.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_ULT:
+ Format(instr, "cmp.ult.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_LE:
+ Format(instr, "cmp.le.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_ULE:
+ Format(instr, "cmp.ule.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_OR:
+ Format(instr, "cmp.or.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_UNE:
+ Format(instr, "cmp.une.d 'fd, 'fs, 'ft");
+ break;
+ case CMP_NE:
+ Format(instr, "cmp.ne.d 'fd, 'fs, 'ft");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) {
+ switch (instr->FunctionValue()) {
+ case CVT_S_W: // Convert word to float (single).
+ Format(instr, "cvt.s.w 'fd, 'fs");
+ break;
+ case CVT_D_W: // Convert word to double.
+ Format(instr, "cvt.d.w 'fd, 'fs");
+ break;
+ case CMP_AF:
+ Format(instr, "cmp.af.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_UN:
+ Format(instr, "cmp.un.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_EQ:
+ Format(instr, "cmp.eq.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_UEQ:
+ Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_LT:
+ Format(instr, "cmp.lt.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_ULT:
+ Format(instr, "cmp.ult.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_LE:
+ Format(instr, "cmp.le.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_ULE:
+ Format(instr, "cmp.ule.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_OR:
+ Format(instr, "cmp.or.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_UNE:
+ Format(instr, "cmp.une.s 'fd, 'fs, 'ft");
+ break;
+ case CMP_NE:
+ Format(instr, "cmp.ne.s 'fd, 'fs, 'ft");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case JR:
+ Format(instr, "jr 'rs");
+ break;
+ case JALR:
+ Format(instr, "jalr 'rs, 'rd");
+ break;
+ case SLL:
+ if (0x0 == static_cast<int>(instr->InstructionBits()))
+ Format(instr, "nop");
+ else
+ Format(instr, "sll 'rd, 'rt, 'sa");
+ break;
+ case SRL:
+ if (instr->RsValue() == 0) {
+ Format(instr, "srl 'rd, 'rt, 'sa");
+ } else {
+ if (IsMipsArchVariant(kMips32r2)) {
+ Format(instr, "rotr 'rd, 'rt, 'sa");
+ } else {
+ Unknown(instr);
+ }
+ }
+ break;
+ case SRA:
+ Format(instr, "sra 'rd, 'rt, 'sa");
+ break;
+ case SLLV:
+ Format(instr, "sllv 'rd, 'rt, 'rs");
+ break;
+ case SRLV:
+ if (instr->SaValue() == 0) {
+ Format(instr, "srlv 'rd, 'rt, 'rs");
+ } else {
+ if (IsMipsArchVariant(kMips32r2)) {
+ Format(instr, "rotrv 'rd, 'rt, 'rs");
+ } else {
+ Unknown(instr);
+ }
+ }
+ break;
+ case SRAV:
+ Format(instr, "srav 'rd, 'rt, 'rs");
+ break;
+ case LSA:
+ Format(instr, "lsa 'rd, 'rt, 'rs, 'sa2");
+ break;
+ case MFHI:
+ if (instr->Bits(25, 16) == 0) {
+ Format(instr, "mfhi 'rd");
+ } else {
+ if ((instr->FunctionFieldRaw() == CLZ_R6) && (instr->FdValue() == 1)) {
+ Format(instr, "clz 'rd, 'rs");
+ } else if ((instr->FunctionFieldRaw() == CLO_R6) &&
+ (instr->FdValue() == 1)) {
+ Format(instr, "clo 'rd, 'rs");
+ }
+ }
+ break;
+ case MFLO:
+ Format(instr, "mflo 'rd");
+ break;
+ case MULT: // @Mips32r6 == MUL_MUH.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "mult 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == MUL_OP) {
+ Format(instr, "mul 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "muh 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case MULTU: // @Mips32r6 == MUL_MUH_U.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "multu 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == MUL_OP) {
+ Format(instr, "mulu 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "muhu 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case DIV: // @Mips32r6 == DIV_MOD.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "div 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == DIV_OP) {
+ Format(instr, "div 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "mod 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case DIVU: // @Mips32r6 == DIV_MOD_U.
+ if (!IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "divu 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == DIV_OP) {
+ Format(instr, "divu 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "modu 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case ADD:
+ Format(instr, "add 'rd, 'rs, 'rt");
+ break;
+ case ADDU:
+ Format(instr, "addu 'rd, 'rs, 'rt");
+ break;
+ case SUB:
+ Format(instr, "sub 'rd, 'rs, 'rt");
+ break;
+ case SUBU:
+ Format(instr, "subu 'rd, 'rs, 'rt");
+ break;
+ case AND:
+ Format(instr, "and 'rd, 'rs, 'rt");
+ break;
+ case OR:
+ if (0 == instr->RsValue()) {
+ Format(instr, "mov 'rd, 'rt");
+ } else if (0 == instr->RtValue()) {
+ Format(instr, "mov 'rd, 'rs");
+ } else {
+ Format(instr, "or 'rd, 'rs, 'rt");
+ }
+ break;
+ case XOR:
+ Format(instr, "xor 'rd, 'rs, 'rt");
+ break;
+ case NOR:
+ Format(instr, "nor 'rd, 'rs, 'rt");
+ break;
+ case SLT:
+ Format(instr, "slt 'rd, 'rs, 'rt");
+ break;
+ case SLTU:
+ Format(instr, "sltu 'rd, 'rs, 'rt");
+ break;
+ case BREAK:
+ Format(instr, "break, code: 'code");
+ break;
+ case TGE:
+ Format(instr, "tge 'rs, 'rt, code: 'code");
+ break;
+ case TGEU:
+ Format(instr, "tgeu 'rs, 'rt, code: 'code");
+ break;
+ case TLT:
+ Format(instr, "tlt 'rs, 'rt, code: 'code");
+ break;
+ case TLTU:
+ Format(instr, "tltu 'rs, 'rt, code: 'code");
+ break;
+ case TEQ:
+ Format(instr, "teq 'rs, 'rt, code: 'code");
+ break;
+ case TNE:
+ Format(instr, "tne 'rs, 'rt, code: 'code");
+ break;
+ case MOVZ:
+ Format(instr, "movz 'rd, 'rs, 'rt");
+ break;
+ case MOVN:
+ Format(instr, "movn 'rd, 'rs, 'rt");
+ break;
+ case MOVCI:
+ if (instr->Bit(16)) {
+ Format(instr, "movt 'rd, 'rs, 'bc");
+ } else {
+ Format(instr, "movf 'rd, 'rs, 'bc");
+ }
+ break;
+ case SELEQZ_S:
+ Format(instr, "seleqz 'rd, 'rs, 'rt");
+ break;
+ case SELNEZ_S:
+ Format(instr, "selnez 'rd, 'rs, 'rt");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case MUL:
+ Format(instr, "mul 'rd, 'rs, 'rt");
+ break;
+ case CLZ:
+ if (!IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "clz 'rd, 'rs");
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case INS: {
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
+ case EXT: {
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
+ case BSHFL: {
+ int sa = instr->SaFieldRaw() >> kSaShift;
+ switch (sa) {
+ case BITSWAP: {
+ if (IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "bitswap 'rd, 'rt");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
+ case SEB:
+ case SEH:
+ case WSBH:
+ UNREACHABLE();
+ break;
+ default: {
+ sa >>= kBp2Bits;
+ switch (sa) {
+ case ALIGN: {
+ if (IsMipsArchVariant(kMips32r6)) {
+ Format(instr, "align 'rd, 'rs, 'rt, 'bp2");
+ } else {
+ Unknown(instr);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
void Decoder::DecodeTypeRegister(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
case COP1: // Coprocessor instructions.
@@ -475,147 +1317,17 @@
case MTHC1:
Format(instr, "mthc1 'rt, 'fs");
break;
- case D:
- switch (instr->FunctionFieldRaw()) {
- case ADD_D:
- Format(instr, "add.d 'fd, 'fs, 'ft");
- break;
- case SUB_D:
- Format(instr, "sub.d 'fd, 'fs, 'ft");
- break;
- case MUL_D:
- Format(instr, "mul.d 'fd, 'fs, 'ft");
- break;
- case DIV_D:
- Format(instr, "div.d 'fd, 'fs, 'ft");
- break;
- case ABS_D:
- Format(instr, "abs.d 'fd, 'fs");
- break;
- case MOV_D:
- Format(instr, "mov.d 'fd, 'fs");
- break;
- case NEG_D:
- Format(instr, "neg.d 'fd, 'fs");
- break;
- case SQRT_D:
- Format(instr, "sqrt.d 'fd, 'fs");
- break;
- case CVT_W_D:
- Format(instr, "cvt.w.d 'fd, 'fs");
- break;
- 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:
- Format(instr, "trunc.l.d 'fd, 'fs");
- break;
- case ROUND_W_D:
- Format(instr, "round.w.d 'fd, 'fs");
- break;
- case FLOOR_W_D:
- Format(instr, "floor.w.d 'fd, 'fs");
- break;
- case CEIL_W_D:
- Format(instr, "ceil.w.d 'fd, 'fs");
- break;
- case CVT_S_D:
- Format(instr, "cvt.s.d 'fd, 'fs");
- break;
- case C_F_D:
- Format(instr, "c.f.d 'fs, 'ft, 'Cc");
- break;
- case C_UN_D:
- Format(instr, "c.un.d 'fs, 'ft, 'Cc");
- break;
- case C_EQ_D:
- Format(instr, "c.eq.d 'fs, 'ft, 'Cc");
- break;
- case C_UEQ_D:
- Format(instr, "c.ueq.d 'fs, 'ft, 'Cc");
- break;
- case C_OLT_D:
- Format(instr, "c.olt.d 'fs, 'ft, 'Cc");
- break;
- case C_ULT_D:
- Format(instr, "c.ult.d 'fs, 'ft, 'Cc");
- break;
- case C_OLE_D:
- Format(instr, "c.ole.d 'fs, 'ft, 'Cc");
- break;
- case C_ULE_D:
- Format(instr, "c.ule.d 'fs, 'ft, 'Cc");
- break;
- default:
- Format(instr, "unknown.cop1.d");
- break;
- }
- break;
case S:
- switch (instr->FunctionFieldRaw()) {
- case CVT_D_S:
- Format(instr, "cvt.d.s 'fd, 'fs");
- break;
- default:
- UNIMPLEMENTED_MIPS();
- }
+ DecodeTypeRegisterSRsType(instr);
break;
- case W:
- switch (instr->FunctionFieldRaw()) {
- case CVT_S_W: // Convert word to float (single).
- Format(instr, "cvt.s.w 'fd, 'fs");
- break;
- case CVT_D_W: // Convert word to double.
- Format(instr, "cvt.d.w 'fd, 'fs");
- break;
- default:
- UNREACHABLE();
- }
+ case D:
+ DecodeTypeRegisterDRsType(instr);
break;
case L:
- switch (instr->FunctionFieldRaw()) {
- case CVT_D_L:
- Format(instr, "cvt.d.l 'fd, 'fs");
- break;
- case CVT_S_L:
- Format(instr, "cvt.s.l 'fd, 'fs");
- break;
- case CMP_UN:
- Format(instr, "cmp.un.d 'fd, 'fs, 'ft");
- break;
- case CMP_EQ:
- Format(instr, "cmp.eq.d 'fd, 'fs, 'ft");
- break;
- case CMP_UEQ:
- Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft");
- break;
- case CMP_LT:
- Format(instr, "cmp.lt.d 'fd, 'fs, 'ft");
- break;
- case CMP_ULT:
- Format(instr, "cmp.ult.d 'fd, 'fs, 'ft");
- break;
- case CMP_LE:
- Format(instr, "cmp.le.d 'fd, 'fs, 'ft");
- break;
- case CMP_ULE:
- Format(instr, "cmp.ule.d 'fd, 'fs, 'ft");
- break;
- case CMP_OR:
- Format(instr, "cmp.or.d 'fd, 'fs, 'ft");
- break;
- case CMP_UNE:
- Format(instr, "cmp.une.d 'fd, 'fs, 'ft");
- break;
- case CMP_NE:
- Format(instr, "cmp.ne.d 'fd, 'fs, 'ft");
- break;
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterLRsType(instr);
+ break;
+ case W:
+ DecodeTypeRegisterWRsType(instr);
break;
case PS:
UNIMPLEMENTED_MIPS();
@@ -634,225 +1346,13 @@
}
break;
case SPECIAL:
- switch (instr->FunctionFieldRaw()) {
- case JR:
- Format(instr, "jr 'rs");
- break;
- case JALR:
- Format(instr, "jalr 'rs");
- break;
- case SLL:
- if ( 0x0 == static_cast<int>(instr->InstructionBits()))
- Format(instr, "nop");
- else
- Format(instr, "sll 'rd, 'rt, 'sa");
- break;
- case SRL:
- if (instr->RsValue() == 0) {
- Format(instr, "srl 'rd, 'rt, 'sa");
- } else {
- if (IsMipsArchVariant(kMips32r2)) {
- Format(instr, "rotr 'rd, 'rt, 'sa");
- } else {
- Unknown(instr);
- }
- }
- break;
- case SRA:
- Format(instr, "sra 'rd, 'rt, 'sa");
- break;
- case SLLV:
- Format(instr, "sllv 'rd, 'rt, 'rs");
- break;
- case SRLV:
- if (instr->SaValue() == 0) {
- Format(instr, "srlv 'rd, 'rt, 'rs");
- } else {
- if (IsMipsArchVariant(kMips32r2)) {
- Format(instr, "rotrv 'rd, 'rt, 'rs");
- } else {
- Unknown(instr);
- }
- }
- break;
- case SRAV:
- Format(instr, "srav 'rd, 'rt, 'rs");
- break;
- case MFHI:
- if (instr->Bits(25, 16) == 0) {
- Format(instr, "mfhi 'rd");
- } else {
- if ((instr->FunctionFieldRaw() == CLZ_R6)
- && (instr->FdValue() == 1)) {
- Format(instr, "clz 'rd, 'rs");
- } else if ((instr->FunctionFieldRaw() == CLO_R6)
- && (instr->FdValue() == 1)) {
- Format(instr, "clo 'rd, 'rs");
- }
- }
- break;
- case MFLO:
- Format(instr, "mflo 'rd");
- break;
- case MULT: // @Mips32r6 == MUL_MUH.
- if (!IsMipsArchVariant(kMips32r6)) {
- Format(instr, "mult 'rs, 'rt");
- } else {
- if (instr->SaValue() == MUL_OP) {
- Format(instr, "mul 'rd, 'rs, 'rt");
- } else {
- Format(instr, "muh 'rd, 'rs, 'rt");
- }
- }
- break;
- case MULTU: // @Mips32r6 == MUL_MUH_U.
- if (!IsMipsArchVariant(kMips32r6)) {
- Format(instr, "multu 'rs, 'rt");
- } else {
- if (instr->SaValue() == MUL_OP) {
- Format(instr, "mulu 'rd, 'rs, 'rt");
- } else {
- Format(instr, "muhu 'rd, 'rs, 'rt");
- }
- }
- break;
- case DIV: // @Mips32r6 == DIV_MOD.
- if (!IsMipsArchVariant(kMips32r6)) {
- Format(instr, "div 'rs, 'rt");
- } else {
- if (instr->SaValue() == DIV_OP) {
- Format(instr, "div 'rd, 'rs, 'rt");
- } else {
- Format(instr, "mod 'rd, 'rs, 'rt");
- }
- }
- break;
- case DIVU: // @Mips32r6 == DIV_MOD_U.
- if (!IsMipsArchVariant(kMips32r6)) {
- Format(instr, "divu 'rs, 'rt");
- } else {
- if (instr->SaValue() == DIV_OP) {
- Format(instr, "divu 'rd, 'rs, 'rt");
- } else {
- Format(instr, "modu 'rd, 'rs, 'rt");
- }
- }
- break;
- case ADD:
- Format(instr, "add 'rd, 'rs, 'rt");
- break;
- case ADDU:
- Format(instr, "addu 'rd, 'rs, 'rt");
- break;
- case SUB:
- Format(instr, "sub 'rd, 'rs, 'rt");
- break;
- case SUBU:
- Format(instr, "subu 'rd, 'rs, 'rt");
- break;
- case AND:
- Format(instr, "and 'rd, 'rs, 'rt");
- break;
- case OR:
- if (0 == instr->RsValue()) {
- Format(instr, "mov 'rd, 'rt");
- } else if (0 == instr->RtValue()) {
- Format(instr, "mov 'rd, 'rs");
- } else {
- Format(instr, "or 'rd, 'rs, 'rt");
- }
- break;
- case XOR:
- Format(instr, "xor 'rd, 'rs, 'rt");
- break;
- case NOR:
- Format(instr, "nor 'rd, 'rs, 'rt");
- break;
- case SLT:
- Format(instr, "slt 'rd, 'rs, 'rt");
- break;
- case SLTU:
- Format(instr, "sltu 'rd, 'rs, 'rt");
- break;
- case BREAK:
- Format(instr, "break, code: 'code");
- break;
- case TGE:
- Format(instr, "tge 'rs, 'rt, code: 'code");
- break;
- case TGEU:
- Format(instr, "tgeu 'rs, 'rt, code: 'code");
- break;
- case TLT:
- Format(instr, "tlt 'rs, 'rt, code: 'code");
- break;
- case TLTU:
- Format(instr, "tltu 'rs, 'rt, code: 'code");
- break;
- case TEQ:
- Format(instr, "teq 'rs, 'rt, code: 'code");
- break;
- case TNE:
- Format(instr, "tne 'rs, 'rt, code: 'code");
- break;
- case MOVZ:
- Format(instr, "movz 'rd, 'rs, 'rt");
- break;
- case MOVN:
- Format(instr, "movn 'rd, 'rs, 'rt");
- break;
- case MOVCI:
- if (instr->Bit(16)) {
- Format(instr, "movt 'rd, 'rs, 'bc");
- } else {
- Format(instr, "movf 'rd, 'rs, 'bc");
- }
- break;
- case SELEQZ_S:
- Format(instr, "seleqz 'rd, 'rs, 'rt");
- break;
- case SELNEZ_S:
- Format(instr, "selnez 'rd, 'rs, 'rt");
- break;
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterSPECIAL(instr);
break;
case SPECIAL2:
- switch (instr->FunctionFieldRaw()) {
- case MUL:
- Format(instr, "mul 'rd, 'rs, 'rt");
- break;
- case CLZ:
- if (!IsMipsArchVariant(kMips32r6)) {
- Format(instr, "clz 'rd, 'rs");
- }
- break;
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterSPECIAL2(instr);
break;
case SPECIAL3:
- switch (instr->FunctionFieldRaw()) {
- case INS: {
- if (IsMipsArchVariant(kMips32r2)) {
- Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
- } else {
- Unknown(instr);
- }
- break;
- }
- case EXT: {
- if (IsMipsArchVariant(kMips32r2)) {
- Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
- } else {
- Unknown(instr);
- }
- break;
- }
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterSPECIAL3(instr);
break;
default:
UNREACHABLE();
@@ -866,148 +1366,16 @@
switch (instr->RsFieldRaw()) {
case BC1:
if (instr->FBtrueValue()) {
- Format(instr, "bc1t 'bc, 'imm16u");
+ Format(instr, "bc1t 'bc, 'imm16u -> 'imm16p4s2");
} else {
- Format(instr, "bc1f 'bc, 'imm16u");
+ Format(instr, "bc1f 'bc, 'imm16u -> 'imm16p4s2");
}
break;
case BC1EQZ:
- Format(instr, "bc1eqz 'ft, 'imm16u");
+ Format(instr, "bc1eqz 'ft, 'imm16u -> 'imm16p4s2");
break;
case BC1NEZ:
- Format(instr, "bc1nez 'ft, 'imm16u");
- break;
- case W: // CMP.S instruction.
- switch (instr->FunctionValue()) {
- case CMP_AF:
- Format(instr, "cmp.af.S 'ft, 'fs, 'fd");
- break;
- case CMP_UN:
- Format(instr, "cmp.un.S 'ft, 'fs, 'fd");
- break;
- case CMP_EQ:
- Format(instr, "cmp.eq.S 'ft, 'fs, 'fd");
- break;
- case CMP_UEQ:
- Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd");
- break;
- case CMP_LT:
- Format(instr, "cmp.lt.S 'ft, 'fs, 'fd");
- break;
- case CMP_ULT:
- Format(instr, "cmp.ult.S 'ft, 'fs, 'fd");
- break;
- case CMP_LE:
- Format(instr, "cmp.le.S 'ft, 'fs, 'fd");
- break;
- case CMP_ULE:
- Format(instr, "cmp.ule.S 'ft, 'fs, 'fd");
- break;
- case CMP_OR:
- Format(instr, "cmp.or.S 'ft, 'fs, 'fd");
- break;
- case CMP_UNE:
- Format(instr, "cmp.une.S 'ft, 'fs, 'fd");
- break;
- case CMP_NE:
- Format(instr, "cmp.ne.S 'ft, 'fs, 'fd");
- break;
- default:
- UNREACHABLE();
- }
- break;
- case L: // CMP.D instruction.
- switch (instr->FunctionValue()) {
- case CMP_AF:
- Format(instr, "cmp.af.D 'ft, 'fs, 'fd");
- break;
- case CMP_UN:
- Format(instr, "cmp.un.D 'ft, 'fs, 'fd");
- break;
- case CMP_EQ:
- Format(instr, "cmp.eq.D 'ft, 'fs, 'fd");
- break;
- case CMP_UEQ:
- Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd");
- break;
- case CMP_LT:
- Format(instr, "cmp.lt.D 'ft, 'fs, 'fd");
- break;
- case CMP_ULT:
- Format(instr, "cmp.ult.D 'ft, 'fs, 'fd");
- break;
- case CMP_LE:
- Format(instr, "cmp.le.D 'ft, 'fs, 'fd");
- break;
- case CMP_ULE:
- Format(instr, "cmp.ule.D 'ft, 'fs, 'fd");
- break;
- case CMP_OR:
- Format(instr, "cmp.or.D 'ft, 'fs, 'fd");
- break;
- case CMP_UNE:
- Format(instr, "cmp.une.D 'ft, 'fs, 'fd");
- break;
- case CMP_NE:
- Format(instr, "cmp.ne.D 'ft, 'fs, 'fd");
- break;
- default:
- UNREACHABLE();
- }
- break;
- case S:
- switch (instr->FunctionValue()) {
- case SEL:
- Format(instr, "sel.S 'ft, 'fs, 'fd");
- break;
- case SELEQZ_C:
- Format(instr, "seleqz.S 'ft, 'fs, 'fd");
- break;
- case SELNEZ_C:
- Format(instr, "selnez.S 'ft, 'fs, 'fd");
- break;
- case MIN:
- Format(instr, "min.S 'ft, 'fs, 'fd");
- break;
- case MINA:
- Format(instr, "mina.S 'ft, 'fs, 'fd");
- break;
- case MAX:
- Format(instr, "max.S 'ft, 'fs, 'fd");
- break;
- case MAXA:
- Format(instr, "maxa.S 'ft, 'fs, 'fd");
- break;
- default:
- UNREACHABLE();
- }
- break;
- case D:
- switch (instr->FunctionValue()) {
- case SEL:
- Format(instr, "sel.D 'ft, 'fs, 'fd");
- break;
- case SELEQZ_C:
- Format(instr, "seleqz.D 'ft, 'fs, 'fd");
- break;
- case SELNEZ_C:
- Format(instr, "selnez.D 'ft, 'fs, 'fd");
- break;
- case MIN:
- Format(instr, "min.D 'ft, 'fs, 'fd");
- break;
- case MINA:
- Format(instr, "mina.D 'ft, 'fs, 'fd");
- break;
- case MAX:
- Format(instr, "max.D 'ft, 'fs, 'fd");
- break;
- case MAXA:
- Format(instr, "maxa.D 'ft, 'fs, 'fd");
- break;
- default:
- UNREACHABLE();
- }
+ Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
break;
default:
UNREACHABLE();
@@ -1018,19 +1386,23 @@
case REGIMM:
switch (instr->RtFieldRaw()) {
case BLTZ:
- Format(instr, "bltz 'rs, 'imm16u");
+ Format(instr, "bltz 'rs, 'imm16u -> 'imm16p4s2");
break;
case BLTZAL:
- Format(instr, "bltzal 'rs, 'imm16u");
+ Format(instr, "bltzal 'rs, 'imm16u -> 'imm16p4s2");
break;
case BGEZ:
- Format(instr, "bgez 'rs, 'imm16u");
+ Format(instr, "bgez 'rs, 'imm16u -> 'imm16p4s2");
break;
- case BGEZAL:
- Format(instr, "bgezal 'rs, 'imm16u");
+ case BGEZAL: {
+ if (instr->RsValue() == 0)
+ Format(instr, "bal 'imm16s -> 'imm16p4s2");
+ else
+ Format(instr, "bgezal 'rs, 'imm16u -> 'imm16p4s2");
break;
+ }
case BGEZALL:
- Format(instr, "bgezall 'rs, 'imm16u");
+ Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
break;
default:
UNREACHABLE();
@@ -1038,81 +1410,83 @@
break; // Case REGIMM.
// ------------- Branch instructions.
case BEQ:
- Format(instr, "beq 'rs, 'rt, 'imm16u");
+ Format(instr, "beq 'rs, 'rt, 'imm16u -> 'imm16p4s2");
+ break;
+ case BC:
+ Format(instr, "bc 'imm26s -> 'imm26p4s2");
+ break;
+ case BALC:
+ Format(instr, "balc 'imm26s -> 'imm26p4s2");
break;
case BNE:
- Format(instr, "bne 'rs, 'rt, 'imm16u");
+ Format(instr, "bne 'rs, 'rt, 'imm16u -> 'imm16p4s2");
break;
case BLEZ:
- if ((instr->RtFieldRaw() == 0)
- && (instr->RsFieldRaw() != 0)) {
- Format(instr, "blez 'rs, 'imm16u");
- } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
- && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgeuc 'rs, 'rt, 'imm16u");
- } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgezalc 'rs, 'imm16u");
- } else if ((instr->RsFieldRaw() == 0)
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "blezalc 'rs, 'imm16u");
+ if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
+ Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() != instr->RsValue()) &&
+ (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() == instr->RsValue()) &&
+ (instr->RtValue() != 0)) {
+ Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
+ Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
} else {
UNREACHABLE();
}
break;
case BGTZ:
- if ((instr->RtFieldRaw() == 0)
- && (instr->RsFieldRaw() != 0)) {
- Format(instr, "bgtz 'rs, 'imm16u");
- } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
- && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bltuc 'rs, 'rt, 'imm16u");
- } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bltzalc 'rt, 'imm16u");
- } else if ((instr->RsFieldRaw() == 0)
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgtzalc 'rt, 'imm16u");
+ if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
+ Format(instr, "bgtz 'rs, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() != instr->RsValue()) &&
+ (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bltuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() == instr->RsValue()) &&
+ (instr->RtValue() != 0)) {
+ Format(instr, "bltzalc 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bgtzalc 'rt, 'imm16u -> 'imm16p4s2");
} else {
UNREACHABLE();
}
break;
case BLEZL:
- if ((instr->RtFieldRaw() == instr->RsFieldRaw())
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgezc 'rt, 'imm16u");
- } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
- && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgec 'rs, 'rt, 'imm16u");
- } else if ((instr->RsFieldRaw() == 0)
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "blezc 'rt, 'imm16u");
+ if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
+ Format(instr, "bgezc 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() != instr->RsValue()) &&
+ (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bgec 'rs, 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
+ Format(instr, "blezc 'rt, 'imm16u -> 'imm16p4s2");
} else {
UNREACHABLE();
}
break;
case BGTZL:
- if ((instr->RtFieldRaw() == instr->RsFieldRaw())
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bltzc 'rt, 'imm16u");
- } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
- && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bltc 'rs, 'rt, 'imm16u");
- } else if ((instr->RsFieldRaw() == 0)
- && (instr->RtFieldRaw() != 0)) {
- Format(instr, "bgtzc 'rt, 'imm16u");
+ if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
+ Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RtValue() != instr->RsValue()) &&
+ (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
+ } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
+ Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
} else {
UNREACHABLE();
}
break;
- case BEQZC:
- if (instr->RsFieldRaw() != 0) {
- Format(instr, "beqzc 'rs, 'imm21x");
+ case POP66:
+ if (instr->RsValue() == JIC) {
+ Format(instr, "jic 'rt, 'imm16s");
+ } else {
+ Format(instr, "beqzc 'rs, 'imm21s -> 'imm21p4s2");
}
break;
- case BNEZC:
- if (instr->RsFieldRaw() != 0) {
- Format(instr, "bnezc 'rs, 'imm21x");
+ case POP76:
+ if (instr->RsValue() == JIALC) {
+ Format(instr, "jialc 'rt, 'imm16s");
+ } else {
+ Format(instr, "bnezc 'rs, 'imm21s -> 'imm21p4s2");
}
break;
// ------------- Arithmetic instructions.
@@ -1120,25 +1494,33 @@
if (!IsMipsArchVariant(kMips32r6)) {
Format(instr, "addi 'rt, 'rs, 'imm16s");
} else {
- // Check if BOVC or BEQC instruction.
- if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
- Format(instr, "bovc 'rs, 'rt, 'imm16s");
- } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
- Format(instr, "beqc 'rs, 'rt, 'imm16s");
+ int rs_reg = instr->RsValue();
+ int rt_reg = instr->RtValue();
+ // Check if BOVC, BEQZALC or BEQC instruction.
+ if (rs_reg >= rt_reg) {
+ Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else {
- UNREACHABLE();
+ if (rs_reg == 0) {
+ Format(instr, "beqzalc 'rt, 'imm16s -> 'imm16p4s2");
+ } else {
+ Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
+ }
}
}
break;
case DADDI:
if (IsMipsArchVariant(kMips32r6)) {
- // Check if BNVC or BNEC instruction.
- if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
- Format(instr, "bnvc 'rs, 'rt, 'imm16s");
- } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
- Format(instr, "bnec 'rs, 'rt, 'imm16s");
+ int rs_reg = instr->RsValue();
+ int rt_reg = instr->RtValue();
+ // Check if BNVC, BNEZALC or BNEC instruction.
+ if (rs_reg >= rt_reg) {
+ Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
} else {
- UNREACHABLE();
+ if (rs_reg == 0) {
+ Format(instr, "bnezalc 'rt, 'imm16s -> 'imm16p4s2");
+ } else {
+ Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
+ }
}
}
break;
@@ -1165,7 +1547,7 @@
Format(instr, "lui 'rt, 'imm16x");
} else {
if (instr->RsValue() != 0) {
- Format(instr, "aui 'rt, 'imm16x");
+ Format(instr, "aui 'rt, 'rs, 'imm16x");
} else {
Format(instr, "lui 'rt, 'imm16x");
}
@@ -1223,6 +1605,35 @@
case SDC1:
Format(instr, "sdc1 'ft, 'imm16s('rs)");
break;
+ case PCREL: {
+ int32_t imm21 = instr->Imm21Value();
+ // rt field: 5-bits checking
+ uint8_t rt = (imm21 >> kImm16Bits);
+ switch (rt) {
+ case ALUIPC:
+ Format(instr, "aluipc 'rs, 'imm16s");
+ break;
+ case AUIPC:
+ Format(instr, "auipc 'rs, 'imm16s");
+ break;
+ default: {
+ // rt field: checking of the most significant 2-bits
+ rt = (imm21 >> kImm19Bits);
+ switch (rt) {
+ case LWPC:
+ Format(instr, "lwpc 'rs, 'imm19s");
+ break;
+ case ADDIUPC:
+ Format(instr, "addiupc 'rs, 'imm19s");
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+ break;
+ }
default:
printf("a 0x%x \n", instr->OpcodeFieldRaw());
UNREACHABLE();
@@ -1234,10 +1645,10 @@
void Decoder::DecodeTypeJump(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
case J:
- Format(instr, "j 'imm26x");
+ Format(instr, "j 'imm26x -> 'imm26j");
break;
case JAL:
- Format(instr, "jal 'imm26x");
+ Format(instr, "jal 'imm26x -> 'imm26j");
break;
default:
UNREACHABLE();
@@ -1252,7 +1663,7 @@
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
"%08x ",
instr->InstructionBits());
- switch (instr->InstructionType()) {
+ switch (instr->InstructionType(Instruction::EXTRA)) {
case Instruction::kRegisterType: {
DecodeTypeRegister(instr);
break;
@@ -1274,8 +1685,8 @@
}
-} } // namespace v8::internal
-
+} // namespace internal
+} // namespace v8
//------------------------------------------------------------------------------