Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Unified Diff: src/mips64/disasm-mips64.cc

Issue 426863006: MIPS64: Add support for architecture revision 6. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips64/constants-mips64.cc ('k') | src/mips64/full-codegen-mips64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips64/disasm-mips64.cc
diff --git a/src/mips64/disasm-mips64.cc b/src/mips64/disasm-mips64.cc
index 9b9cd348f754bfa9d63b5d0824b18ebab5098528..f2aaa58befe66013d661d17a336dbd8f275dddca 100644
--- a/src/mips64/disasm-mips64.cc
+++ b/src/mips64/disasm-mips64.cc
@@ -86,6 +86,7 @@ class Decoder {
void PrintUImm16(Instruction* instr);
void PrintSImm16(Instruction* instr);
void PrintXImm16(Instruction* instr);
+ void PrintXImm21(Instruction* instr);
void PrintXImm26(Instruction* instr);
void PrintCode(Instruction* instr); // For break and trap instructions.
// Printing of instruction name.
@@ -247,6 +248,13 @@ void Decoder::PrintXImm16(Instruction* instr) {
}
+// Print 21-bit immediate value.
+void Decoder::PrintXImm21(Instruction* instr) {
+ uint32_t imm = instr->Imm21Value();
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm);
+}
+
+
// Print 26-bit immediate value.
void Decoder::PrintXImm26(Instruction* instr) {
uint32_t imm = instr->Imm26Value() << kImmFieldShift;
@@ -361,7 +369,11 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
PrintXImm16(instr);
}
return 6;
- } else {
+ } else if (format[3] == '2' && format[4] == '1') {
+ ASSERT(STRING_STARTS_WITH(format, "imm21x"));
+ PrintXImm21(instr);
+ return 6;
+ } else if (format[3] == '2' && format[4] == '6') {
ASSERT(STRING_STARTS_WITH(format, "imm26x"));
PrintXImm26(instr);
return 6;
@@ -466,9 +478,6 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
case COP1: // Coprocessor instructions.
switch (instr->RsFieldRaw()) {
- case BC1: // bc1 handled in DecodeTypeImmediate.
- UNREACHABLE();
- break;
case MFC1:
Format(instr, "mfc1 'rt, 'fs");
break;
@@ -582,14 +591,8 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
break;
}
break;
- case S:
- UNIMPLEMENTED_MIPS();
- break;
case W:
switch (instr->FunctionFieldRaw()) {
- case CVT_S_W: // Convert word to float (single).
- Format(instr, "cvt.s.w 'fd, 'fs");
- break;
case CVT_D_W: // Convert word to double.
Format(instr, "cvt.d.w 'fd, 'fs");
break;
@@ -605,13 +608,40 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
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;
- case PS:
- UNIMPLEMENTED_MIPS();
- break;
default:
UNREACHABLE();
}
@@ -634,13 +664,24 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
Format(instr, "jalr 'rs");
break;
case SLL:
- if ( 0x0 == static_cast<int>(instr->InstructionBits()))
+ 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");
+ 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");
@@ -714,34 +755,98 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
Format(instr, "dsrav 'rd, 'rt, 'rs");
break;
case MFHI:
- Format(instr, "mfhi 'rd");
+ if (instr->Bits(25, 16) == 0) {
+ Format(instr, "mfhi 'rd");
+ } else {
+ if ((instr->FunctionFieldRaw() == CLZ_R6)
+ && (instr->FdValue() == 1)) {
+ Format(instr, "clz 'rd, 'rs");
+ } else if ((instr->FunctionFieldRaw() == CLO_R6)
+ && (instr->FdValue() == 1)) {
+ Format(instr, "clo 'rd, 'rs");
+ }
+ }
break;
case MFLO:
Format(instr, "mflo 'rd");
break;
- case MULT:
- Format(instr, "mult 'rs, 'rt");
- break;
- case DMULT:
- Format(instr, "dmult 'rs, 'rt");
+ 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 MULTU:
- Format(instr, "multu 'rs, 'rt");
+ 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 DMULTU:
- Format(instr, "dmultu 'rs, 'rt");
+ 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:
- Format(instr, "div 'rs, 'rt");
+ 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:
- Format(instr, "ddiv 'rs, 'rt");
+ 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:
- Format(instr, "divu 'rs, 'rt");
+ 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:
- Format(instr, "ddivu 'rs, 'rt");
+ 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");
@@ -824,6 +929,12 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
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();
}
@@ -834,7 +945,9 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
Format(instr, "mul 'rd, 'rs, 'rt");
break;
case CLZ:
- Format(instr, "clz 'rd, 'rs");
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "clz 'rd, 'rs");
+ }
break;
default:
UNREACHABLE();
@@ -843,19 +956,11 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
case SPECIAL3:
switch (instr->FunctionFieldRaw()) {
case INS: {
- if (kArchVariant == kMips64r2) {
- Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
- } else {
- Unknown(instr);
- }
+ Format(instr, "ins 'rt, 'rs, 'sa, 'ss2");
break;
}
case EXT: {
- if (kArchVariant == kMips64r2) {
- Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
- } else {
- Unknown(instr);
- }
+ Format(instr, "ext 'rt, 'rs, 'sa, 'ss1");
break;
}
default:
@@ -871,7 +976,6 @@ int Decoder::DecodeTypeRegister(Instruction* instr) {
void Decoder::DecodeTypeImmediate(Instruction* instr) {
switch (instr->OpcodeFieldRaw()) {
- // ------------- REGIMM class.
case COP1:
switch (instr->RsFieldRaw()) {
case BC1:
@@ -881,10 +985,150 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
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();
}
+
break; // Case COP1.
+ // ------------- REGIMM class.
case REGIMM:
switch (instr->RtFieldRaw()) {
case BLTZ:
@@ -899,6 +1143,15 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
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();
}
@@ -911,17 +1164,105 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "bne 'rs, 'rt, 'imm16u");
break;
case BLEZ:
- Format(instr, "blez 'rs, 'imm16u");
+ if ((instr->RtFieldRaw() == 0)
+ && (instr->RsFieldRaw() != 0)) {
+ Format(instr, "blez 'rs, 'imm16u");
+ } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
+ && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgeuc 'rs, 'rt, 'imm16u");
+ } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgezalc 'rs, 'imm16u");
+ } else if ((instr->RsFieldRaw() == 0)
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "blezalc 'rs, 'imm16u");
+ } else {
+ UNREACHABLE();
+ }
break;
case BGTZ:
- Format(instr, "bgtz 'rs, 'imm16u");
+ if ((instr->RtFieldRaw() == 0)
+ && (instr->RsFieldRaw() != 0)) {
+ Format(instr, "bgtz 'rs, 'imm16u");
+ } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
+ && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bltuc 'rs, 'rt, 'imm16u");
+ } else if ((instr->RtFieldRaw() == instr->RsFieldRaw())
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bltzalc 'rt, 'imm16u");
+ } else if ((instr->RsFieldRaw() == 0)
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgtzalc 'rt, 'imm16u");
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case BLEZL:
+ if ((instr->RtFieldRaw() == instr->RsFieldRaw())
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgezc 'rt, 'imm16u");
+ } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
+ && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgec 'rs, 'rt, 'imm16u");
+ } else if ((instr->RsFieldRaw() == 0)
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "blezc 'rt, 'imm16u");
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case BGTZL:
+ if ((instr->RtFieldRaw() == instr->RsFieldRaw())
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bltzc 'rt, 'imm16u");
+ } else if ((instr->RtFieldRaw() != instr->RsFieldRaw())
+ && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bltc 'rs, 'rt, 'imm16u");
+ } else if ((instr->RsFieldRaw() == 0)
+ && (instr->RtFieldRaw() != 0)) {
+ Format(instr, "bgtzc 'rt, 'imm16u");
+ } else {
+ UNREACHABLE();
+ }
+ break;
+ case BEQZC:
+ if (instr->RsFieldRaw() != 0) {
+ Format(instr, "beqzc 'rs, 'imm21x");
+ }
+ break;
+ case BNEZC:
+ if (instr->RsFieldRaw() != 0) {
+ Format(instr, "bnezc 'rs, 'imm21x");
+ }
break;
// ------------- Arithmetic instructions.
case ADDI:
- Format(instr, "addi 'rt, 'rs, 'imm16s");
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "addi 'rt, 'rs, 'imm16s");
+ } else {
+ // Check if BOVC or BEQC instruction.
+ if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
+ Format(instr, "bovc 'rs, 'rt, 'imm16s");
+ } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
+ Format(instr, "beqc 'rs, 'rt, 'imm16s");
+ } else {
+ UNREACHABLE();
+ }
+ }
break;
case DADDI:
- Format(instr, "daddi 'rt, 'rs, 'imm16s");
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "daddi 'rt, 'rs, 'imm16s");
+ } else {
+ // Check if BNVC or BNEC instruction.
+ if (instr->RsFieldRaw() >= instr->RtFieldRaw()) {
+ Format(instr, "bnvc 'rs, 'rt, 'imm16s");
+ } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) {
+ Format(instr, "bnec 'rs, 'rt, 'imm16s");
+ } else {
+ UNREACHABLE();
+ }
+ }
break;
case ADDIU:
Format(instr, "addiu 'rt, 'rs, 'imm16s");
@@ -945,7 +1286,18 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "xori 'rt, 'rs, 'imm16x");
break;
case LUI:
- Format(instr, "lui 'rt, 'imm16x");
+ if (kArchVariant != kMips64r6) {
+ Format(instr, "lui 'rt, 'imm16x");
+ } else {
+ if (instr->RsValue() != 0) {
+ Format(instr, "aui 'rt, 'imm16x");
+ } else {
+ Format(instr, "lui 'rt, 'imm16x");
+ }
+ }
+ break;
+ case DAUI:
+ Format(instr, "daui 'rt, 'imm16x");
break;
// ------------- Memory instructions.
case LB:
« no previous file with comments | « src/mips64/constants-mips64.cc ('k') | src/mips64/full-codegen-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698