summaryrefslogtreecommitdiff
path: root/deps/v8/src/mips64/disasm-mips64.cc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2015-06-19 13:23:56 +0200
committerRod Vagg <rod@vagg.org>2015-08-04 11:56:14 -0700
commit70d1f32f5605465a1a630a64f6f0d35f96c7709d (patch)
tree0a349040a686eafcb0a09943ebc733477dce2781 /deps/v8/src/mips64/disasm-mips64.cc
parent4643b8b6671607a7aff60cbbd0b384dcf2f6959e (diff)
downloadnode-new-70d1f32f5605465a1a630a64f6f0d35f96c7709d.tar.gz
deps: update v8 to 4.4.63.9
Upgrade the bundled V8 and update code in src/ and lib/ to the new API. Notable backwards incompatible changes are the removal of the smalloc module and dropped support for CESU-8 decoding. CESU-8 support can be brought back if necessary by doing UTF-8 decoding ourselves. This commit includes https://codereview.chromium.org/1192973004 to fix a build error on python 2.6 systems. The original commit log follows: Use optparse in js2c.py for python compatibility Without this change, V8 won't build on RHEL/CentOS 6 because the distro python is too old to know about the argparse module. PR-URL: https://github.com/nodejs/io.js/pull/2022 Reviewed-By: Rod Vagg <rod@vagg.org> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Diffstat (limited to 'deps/v8/src/mips64/disasm-mips64.cc')
-rw-r--r--deps/v8/src/mips64/disasm-mips64.cc1354
1 files changed, 698 insertions, 656 deletions
diff --git a/deps/v8/src/mips64/disasm-mips64.cc b/deps/v8/src/mips64/disasm-mips64.cc
index 3f0642db2c..dc43769fea 100644
--- a/deps/v8/src/mips64/disasm-mips64.cc
+++ b/deps/v8/src/mips64/disasm-mips64.cc
@@ -89,6 +89,7 @@ class Decoder {
void PrintXImm21(Instruction* instr);
void PrintXImm26(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);
@@ -101,8 +102,22 @@ class Decoder {
int DecodeBreakInstr(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 DecodeTypeRegisterCOP1(Instruction* instr);
+ void DecodeTypeRegisterCOP1X(Instruction* instr);
int DecodeTypeRegister(Instruction* instr);
+
+ void DecodeTypeImmediateCOP1(Instruction* instr);
+ void DecodeTypeImmediateREGIMM(Instruction* instr);
void DecodeTypeImmediate(Instruction* instr);
+
void DecodeTypeJump(Instruction* instr);
const disasm::NameConverter& converter_;
@@ -290,6 +305,29 @@ void Decoder::PrintCode(Instruction* instr) {
}
+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) {
}
@@ -420,6 +458,9 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
PrintCc(instr);
return 2;
}
+ case 't':
+ PrintFormat(instr);
+ return 1;
}
UNREACHABLE();
return -1;
@@ -474,502 +515,626 @@ int Decoder::DecodeBreakInstr(Instruction* instr) {
}
+bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case RINT:
+ Format(instr, "rint.'t 'fd, 'fs");
+ break;
+ case SELEQZ_C:
+ Format(instr, "seleqz.'t 'fd, 'fs, 'ft");
+ break;
+ case SELNEZ_C:
+ Format(instr, "selnez.'t 'fd, 'fs, 'ft");
+ 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 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 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 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_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::DecodeTypeRegisterCOP1(Instruction* instr) {
+ switch (instr->RsFieldRaw()) {
+ 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");
+ break;
+ case CFC1:
+ Format(instr, "cfc1 'rt, 'fs");
+ break;
+ case MTHC1:
+ Format(instr, "mthc1 'rt, 'fs");
+ break;
+ case S:
+ DecodeTypeRegisterSRsType(instr);
+ break;
+ case D:
+ DecodeTypeRegisterDRsType(instr);
+ break;
+ case W:
+ DecodeTypeRegisterWRsType(instr);
+ break;
+ case L:
+ DecodeTypeRegisterLRsType(instr);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case MADD_D:
+ Format(instr, "madd.d 'fd, 'fr, '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");
+ break;
+ case SLL:
+ if (0x0 == static_cast<int>(instr->InstructionBits()))
+ Format(instr, "nop");
+ else
+ Format(instr, "sll 'rd, 'rt, 'sa");
+ break;
+ case DSLL:
+ Format(instr, "dsll 'rd, 'rt, 'sa");
+ break;
+ case D_MUL_MUH: // Equals to DMUL.
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "dmult 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == MUL_OP) {
+ Format(instr, "dmul 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "dmuh 'rd, 'rs, 'rt");
+ }
+ }
+ 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 == 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 == 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:
+ 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 D_MUL_MUH_U: // Equals to DMULTU.
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "dmultu 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == MUL_OP) {
+ Format(instr, "dmulu 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "dmuhu 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case MULT: // @Mips64r6 == MUL_MUH.
+ if (kArchVariant != kMips64r6) {
+ 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: // @Mips64r6 == MUL_MUH_U.
+ if (kArchVariant != kMips64r6) {
+ 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: // @Mips64r6 == DIV_MOD.
+ if (kArchVariant != kMips64r6) {
+ 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 DDIV: // @Mips64r6 == D_DIV_MOD.
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "ddiv 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == DIV_OP) {
+ Format(instr, "ddiv 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "dmod 'rd, 'rs, 'rt");
+ }
+ }
+ break;
+ case DIVU: // @Mips64r6 == DIV_MOD_U.
+ if (kArchVariant != kMips64r6) {
+ 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 DDIVU: // @Mips64r6 == D_DIV_MOD_U.
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "ddivu 'rs, 'rt");
+ } else {
+ if (instr->SaValue() == DIV_OP) {
+ Format(instr, "ddivu 'rd, 'rs, 'rt");
+ } else {
+ Format(instr, "dmodu 'rd, '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;
+ 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 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 (kArchVariant != kMips64r6) {
+ Format(instr, "clz 'rd, 'rs");
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) {
+ switch (instr->FunctionFieldRaw()) {
+ case INS: {
+ Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
+ break;
+ }
+ case EXT: {
+ Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
+ break;
+ }
+ case DEXT: {
+ Format(instr, "dext 'rt, 'rs, 'sa, 'ss1");
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
int Decoder::DecodeTypeRegister(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
- case COP1: // Coprocessor instructions.
- switch (instr->RsFieldRaw()) {
- 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");
- break;
- case CFC1:
- Format(instr, "cfc1 'rt, 'fs");
- break;
- 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 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;
- 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 W:
- switch (instr->FunctionFieldRaw()) {
- case CVT_D_W: // Convert word to double.
- Format(instr, "cvt.d.w 'fd, 'fs");
- break;
- default:
- UNREACHABLE();
- }
- 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();
- }
- break;
- default:
- UNREACHABLE();
- }
+ case COP1: // Coprocessor instructions.
+ DecodeTypeRegisterCOP1(instr);
break;
case COP1X:
- switch (instr->FunctionFieldRaw()) {
- case MADD_D:
- Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft");
- break;
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterCOP1X(instr);
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 DSLL:
- Format(instr, "dsll 'rd, 'rt, 'sa");
- break;
- case D_MUL_MUH: // Equals to DMUL.
- if (kArchVariant != kMips64r6) {
- Format(instr, "dmult 'rs, 'rt");
- } else {
- if (instr->SaValue() == MUL_OP) {
- Format(instr, "dmul 'rd, 'rs, 'rt");
- } else {
- Format(instr, "dmuh 'rd, 'rs, 'rt");
- }
- }
- 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 == 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 == 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:
- 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 D_MUL_MUH_U: // Equals to DMULTU.
- if (kArchVariant != kMips64r6) {
- Format(instr, "dmultu 'rs, 'rt");
- } else {
- if (instr->SaValue() == MUL_OP) {
- Format(instr, "dmulu 'rd, 'rs, 'rt");
- } else {
- Format(instr, "dmuhu 'rd, 'rs, 'rt");
- }
- }
- break;
- case MULT: // @Mips64r6 == MUL_MUH.
- if (kArchVariant != kMips64r6) {
- 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: // @Mips64r6 == MUL_MUH_U.
- if (kArchVariant != kMips64r6) {
- 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: // @Mips64r6 == DIV_MOD.
- if (kArchVariant != kMips64r6) {
- 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 DDIV: // @Mips64r6 == D_DIV_MOD.
- if (kArchVariant != kMips64r6) {
- Format(instr, "ddiv 'rs, 'rt");
- } else {
- if (instr->SaValue() == DIV_OP) {
- Format(instr, "ddiv 'rd, 'rs, 'rt");
- } else {
- Format(instr, "dmod 'rd, 'rs, 'rt");
- }
- }
- break;
- case DIVU: // @Mips64r6 == DIV_MOD_U.
- if (kArchVariant != kMips64r6) {
- 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 DDIVU: // @Mips64r6 == D_DIV_MOD_U.
- if (kArchVariant != kMips64r6) {
- Format(instr, "ddivu 'rs, 'rt");
- } else {
- if (instr->SaValue() == DIV_OP) {
- Format(instr, "ddivu 'rd, 'rs, 'rt");
- } else {
- Format(instr, "dmodu 'rd, '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;
- 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:
return DecodeBreakInstr(instr);
- 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;
}
break;
case SPECIAL2:
- switch (instr->FunctionFieldRaw()) {
- case MUL:
- Format(instr, "mul 'rd, 'rs, 'rt");
- break;
- case CLZ:
- if (kArchVariant != kMips64r6) {
- Format(instr, "clz 'rd, 'rs");
- }
- break;
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterSPECIAL2(instr);
break;
case SPECIAL3:
- switch (instr->FunctionFieldRaw()) {
- case INS: {
- Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
- break;
- }
- case EXT: {
- Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
- break;
- }
- case DEXT: {
- Format(instr, "dext 'rt, 'rs, 'sa, 'ss1");
- break;
- }
- default:
- UNREACHABLE();
- }
+ DecodeTypeRegisterSPECIAL3(instr);
break;
default:
UNREACHABLE();
@@ -978,187 +1143,64 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
}
+void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
+ switch (instr->RsFieldRaw()) {
+ case BC1:
+ if (instr->FBtrueValue()) {
+ Format(instr, "bc1t 'bc, 'imm16u");
+ } else {
+ Format(instr, "bc1f 'bc, 'imm16u");
+ }
+ break;
+ case BC1EQZ:
+ Format(instr, "bc1eqz 'ft, 'imm16u");
+ break;
+ case BC1NEZ:
+ Format(instr, "bc1nez 'ft, 'imm16u");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
+ switch (instr->RtFieldRaw()) {
+ case BLTZ:
+ Format(instr, "bltz 'rs, 'imm16u");
+ break;
+ case BLTZAL:
+ Format(instr, "bltzal 'rs, 'imm16u");
+ break;
+ case BGEZ:
+ Format(instr, "bgez 'rs, 'imm16u");
+ break;
+ case BGEZAL:
+ Format(instr, "bgezal 'rs, 'imm16u");
+ break;
+ case BGEZALL:
+ Format(instr, "bgezall 'rs, 'imm16u");
+ break;
+ case DAHI:
+ Format(instr, "dahi 'rs, 'imm16u");
+ break;
+ case DATI:
+ Format(instr, "dati 'rs, 'imm16u");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
void Decoder::DecodeTypeImmediate(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
case COP1:
- switch (instr->RsFieldRaw()) {
- case BC1:
- if (instr->FBtrueValue()) {
- Format(instr, "bc1t 'bc, 'imm16u");
- } else {
- Format(instr, "bc1f 'bc, 'imm16u");
- }
- break;
- case BC1EQZ:
- Format(instr, "bc1eqz 'ft, 'imm16u");
- 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();
- }
- break;
- default:
- UNREACHABLE();
- }
-
+ DecodeTypeImmediateCOP1(instr);
break; // Case COP1.
// ------------- REGIMM class.
case REGIMM:
- switch (instr->RtFieldRaw()) {
- case BLTZ:
- Format(instr, "bltz 'rs, 'imm16u");
- break;
- case BLTZAL:
- Format(instr, "bltzal 'rs, 'imm16u");
- break;
- case BGEZ:
- Format(instr, "bgez 'rs, 'imm16u");
- break;
- case BGEZAL:
- Format(instr, "bgezal 'rs, 'imm16u");
- break;
- case BGEZALL:
- Format(instr, "bgezall 'rs, 'imm16u");
- break;
- case DAHI:
- Format(instr, "dahi 'rs, 'imm16u");
- break;
- case DATI:
- Format(instr, "dati 'rs, 'imm16u");
- break;
- default:
- UNREACHABLE();
- }
+
break; // Case REGIMM.
// ------------- Branch instructions.
case BEQ: