Index: src/mips64/disasm-mips64.cc |
diff --git a/src/mips64/disasm-mips64.cc b/src/mips64/disasm-mips64.cc |
index 3f0642db2c02d691fcd5fcba8d8b96c50410e62e..fc83955fe350ded4f5dbf8b95bc90aaee6411cc5 100644 |
--- a/src/mips64/disasm-mips64.cc |
+++ b/src/mips64/disasm-mips64.cc |
@@ -101,8 +101,23 @@ class Decoder { |
int DecodeBreakInstr(Instruction* instr); |
// Each of these functions decodes one particular instruction type. |
+ void DecodeTypeRegisterDRsType(Instruction* instr); |
+ void DecodeTypeRegisterLRsType(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 DecodeTypeImmediateCOP1W(Instruction* instr); |
+ void DecodeTypeImmediateCOP1L(Instruction* instr); |
+ void DecodeTypeImmediateCOP1S(Instruction* instr); |
+ void DecodeTypeImmediateCOP1D(Instruction* instr); |
+ void DecodeTypeImmediateCOP1(Instruction* instr); |
+ void DecodeTypeImmediateREGIMM(Instruction* instr); |
void DecodeTypeImmediate(Instruction* instr); |
+ |
void DecodeTypeJump(Instruction* instr); |
const disasm::NameConverter& converter_; |
@@ -474,503 +489,547 @@ int Decoder::DecodeBreakInstr(Instruction* instr) { |
} |
-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(); |
- } |
+void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { |
+ switch (instr->FunctionFieldRaw()) { |
+ case SELEQZ_C: |
+ Format(instr, "seleqz.D 'ft, 'fs, 'fd"); |
break; |
- case COP1X: |
+ case SELNEZ_C: |
+ Format(instr, "selnez.D 'ft, 'fs, 'fd"); |
+ break; |
+ 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; |
+ } |
+} |
+ |
+ |
+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::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 D: |
+ DecodeTypeRegisterDRsType(instr); |
+ break; |
+ case W: |
switch (instr->FunctionFieldRaw()) { |
- case MADD_D: |
- Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); |
+ case CVT_D_W: // Convert word to double. |
+ Format(instr, "cvt.d.w 'fd, 'fs"); |
break; |
default: |
UNREACHABLE(); |
} |
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"); |
- } |
- } |
+ case L: |
+ DecodeTypeRegisterLRsType(instr); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
- 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(); |
+ |
+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 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(); |
+ 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 SPECIAL3: |
- switch (instr->FunctionFieldRaw()) { |
- case INS: { |
- Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
- 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); |
} |
- case EXT: { |
- Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
- break; |
+ } |
+ 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); |
} |
- case DEXT: { |
- Format(instr, "dext 'rt, 'rs, 'sa, 'ss1"); |
- break; |
+ } |
+ 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 'rs, 'rt, 'rd"); |
+ break; |
+ case SELNEZ_S: |
+ Format(instr, "selnez 'rs, 'rt, 'rd"); |
+ 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. |
+ DecodeTypeRegisterCOP1(instr); |
+ break; |
+ case COP1X: |
+ DecodeTypeRegisterCOP1X(instr); |
+ break; |
+ case SPECIAL: |
+ switch (instr->FunctionFieldRaw()) { |
+ case BREAK: |
+ return DecodeBreakInstr(instr); |
default: |
- UNREACHABLE(); |
+ DecodeTypeRegisterSPECIAL(instr); |
+ break; |
} |
break; |
+ case SPECIAL2: |
+ DecodeTypeRegisterSPECIAL2(instr); |
+ break; |
+ case SPECIAL3: |
+ DecodeTypeRegisterSPECIAL3(instr); |
+ break; |
default: |
UNREACHABLE(); |
} |
@@ -978,187 +1037,216 @@ int Decoder::DecodeTypeRegister(Instruction* instr) { |
} |
+void Decoder::DecodeTypeImmediateCOP1D(Instruction* instr) { |
+ 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(); |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeTypeImmediateCOP1L(Instruction* instr) { |
+ 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(); |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeTypeImmediateCOP1S(Instruction* instr) { |
+ 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(); |
+ } |
+} |
+ |
+ |
+void Decoder::DecodeTypeImmediateCOP1W(Instruction* instr) { |
+ 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(); |
+ } |
+} |
+ |
+ |
+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; |
+ case W: // CMP.S instruction. |
+ DecodeTypeImmediateCOP1W(instr); |
+ break; |
+ case L: // CMP.D instruction. |
+ DecodeTypeImmediateCOP1L(instr); |
+ break; |
+ case S: |
+ DecodeTypeImmediateCOP1S(instr); |
+ break; |
+ case D: |
+ DecodeTypeImmediateCOP1D(instr); |
+ 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: |