diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2015-06-19 13:23:56 +0200 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-08-04 11:56:14 -0700 |
commit | 70d1f32f5605465a1a630a64f6f0d35f96c7709d (patch) | |
tree | 0a349040a686eafcb0a09943ebc733477dce2781 /deps/v8/src/mips64/disasm-mips64.cc | |
parent | 4643b8b6671607a7aff60cbbd0b384dcf2f6959e (diff) | |
download | node-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.cc | 1354 |
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: |