Index: src/mips/disasm-mips.cc |
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc |
index f541e9143f5001e74a789cfca26f179301b399cd..8d50be1c0021f1c5d2358db38baa50b30c90352c 100644 |
--- a/src/mips/disasm-mips.cc |
+++ b/src/mips/disasm-mips.cc |
@@ -59,6 +59,17 @@ class Decoder { |
int InstructionDecode(byte* instruction); |
private: |
+ const uint32_t kMsaI8Mask = ((3U << 24) | ((1 << 6) - 1)); |
+ const uint32_t kMsaI5Mask = ((7U << 23) | ((1 << 6) - 1)); |
+ const uint32_t kMsaMI10Mask = (15U << 2); |
+ const uint32_t kMsaBITMask = ((7U << 23) | ((1 << 6) - 1)); |
+ const uint32_t kMsaELMMask = (15U << 22); |
+ const uint32_t kMsa3RMask = ((7U << 23) | ((1 << 6) - 1)); |
+ const uint32_t kMsa3RFMask = ((15U << 22) | ((1 << 6) - 1)); |
+ const uint32_t kMsaVECMask = (23U << 21); |
+ const uint32_t kMsa2RMask = (7U << 18); |
+ const uint32_t kMsa2RFMask = (15U << 17); |
+ |
// Bottleneck functions to print into the out_buffer. |
void PrintChar(const char ch); |
void Print(const char* str); |
@@ -66,7 +77,9 @@ class Decoder { |
// Printing of common values. |
void PrintRegister(int reg); |
void PrintFPURegister(int freg); |
+ void PrintMSARegister(int wreg); |
void PrintFPUStatusRegister(int freg); |
+ void PrintMSAControlRegister(int creg); |
void PrintRs(Instruction* instr); |
void PrintRt(Instruction* instr); |
void PrintRd(Instruction* instr); |
@@ -100,12 +113,22 @@ class Decoder { |
void PrintPCImm26(Instruction* instr); |
void PrintCode(Instruction* instr); // For break and trap instructions. |
void PrintFormat(Instruction* instr); // For floating format postfix. |
+ void PrintMsaDataFormat(Instruction* instr); |
+ void PrintMsaXImm8(Instruction* instr); |
+ void PrintMsaImm8(Instruction* instr); |
+ void PrintMsaImm5(Instruction* instr); |
+ void PrintMsaSImm5(Instruction* instr); |
+ void PrintMsaSImm10(Instruction* instr, bool is_mi10 = false); |
+ void PrintMsaImmBit(Instruction* instr); |
+ void PrintMsaImmElm(Instruction* instr); |
+ void PrintMsaCopy(Instruction* instr); |
// Printing of instruction name. |
void PrintInstructionName(Instruction* instr); |
// Handle formatting of instructions and their options. |
int FormatRegister(Instruction* instr, const char* option); |
int FormatFPURegister(Instruction* instr, const char* option); |
+ int FormatMSARegister(Instruction* instr, const char* option); |
int FormatOption(Instruction* instr, const char* option); |
void Format(Instruction* instr, const char* format); |
void Unknown(Instruction* instr); |
@@ -123,6 +146,17 @@ class Decoder { |
void DecodeTypeRegister(Instruction* instr); |
void DecodeTypeImmediate(Instruction* instr); |
void DecodeTypeJump(Instruction* instr); |
+ void DecodeTypeMsaI8(Instruction* instr); |
+ void DecodeTypeMsaI5(Instruction* instr); |
+ void DecodeTypeMsaI10(Instruction* instr); |
+ void DecodeTypeMsaELM(Instruction* instr); |
+ void DecodeTypeMsaBIT(Instruction* instr); |
+ void DecodeTypeMsaMI10(Instruction* instr); |
+ void DecodeTypeMsa3R(Instruction* instr); |
+ void DecodeTypeMsa3RF(Instruction* instr); |
+ void DecodeTypeMsaVec(Instruction* instr); |
+ void DecodeTypeMsa2R(Instruction* instr); |
+ void DecodeTypeMsa2RF(Instruction* instr); |
const disasm::NameConverter& converter_; |
v8::internal::Vector<char> out_buffer_; |
@@ -183,6 +217,7 @@ void Decoder::PrintFPURegister(int freg) { |
Print(converter_.NameOfXMMRegister(freg)); |
} |
+void Decoder::PrintMSARegister(int wreg) { Print(MSARegisters::Name(wreg)); } |
void Decoder::PrintFPUStatusRegister(int freg) { |
switch (freg) { |
@@ -194,6 +229,18 @@ void Decoder::PrintFPUStatusRegister(int freg) { |
} |
} |
+void Decoder::PrintMSAControlRegister(int creg) { |
+ switch (creg) { |
+ case kMSAIRRegister: |
+ Print("MSAIR"); |
+ break; |
+ case kMSACSRRegister: |
+ Print("MSACSR"); |
+ break; |
+ default: |
+ Print("no_msacreg"); |
+ } |
+} |
void Decoder::PrintFs(Instruction* instr) { |
int freg = instr->RsValue(); |
@@ -441,6 +488,53 @@ void Decoder::PrintCode(Instruction* instr) { |
} |
} |
+void Decoder::PrintMsaXImm8(Instruction* instr) { |
+ int32_t imm = instr->MsaImm8Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
+} |
+ |
+void Decoder::PrintMsaImm8(Instruction* instr) { |
+ int32_t imm = instr->MsaImm8Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm); |
+} |
+ |
+void Decoder::PrintMsaImm5(Instruction* instr) { |
+ int32_t imm = instr->MsaImm5Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm); |
+} |
+ |
+void Decoder::PrintMsaSImm5(Instruction* instr) { |
+ int32_t imm = instr->MsaImm5Value(); |
+ imm <<= (32 - kMsaImm5Bits); |
+ imm >>= (32 - kMsaImm5Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); |
+} |
+ |
+void Decoder::PrintMsaSImm10(Instruction* instr, bool is_mi10) { |
+ int32_t imm = is_mi10 ? instr->MsaImmMI10Value() : instr->MsaImm10Value(); |
+ imm <<= (32 - kMsaImm10Bits); |
+ imm >>= (32 - kMsaImm10Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); |
+} |
+ |
+void Decoder::PrintMsaImmBit(Instruction* instr) { |
+ int32_t m = instr->MsaBitMValue(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", m); |
+} |
+ |
+void Decoder::PrintMsaImmElm(Instruction* instr) { |
+ int32_t n = instr->MsaElmNValue(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", n); |
+} |
+ |
+void Decoder::PrintMsaCopy(Instruction* instr) { |
+ int32_t rd = instr->WdValue(); |
+ int32_t ws = instr->WsValue(); |
+ int32_t n = instr->MsaElmNValue(); |
+ out_buffer_pos_ += |
+ SNPrintF(out_buffer_ + out_buffer_pos_, "%s, %s[%u]", |
+ converter_.NameOfCPURegister(rd), MSARegisters::Name(ws), n); |
+} |
void Decoder::PrintFormat(Instruction* instr) { |
char formatLetter = ' '; |
@@ -464,6 +558,84 @@ void Decoder::PrintFormat(Instruction* instr) { |
PrintChar(formatLetter); |
} |
+void Decoder::PrintMsaDataFormat(Instruction* instr) { |
+ DCHECK(instr->IsMSAInstr()); |
+ char df = ' '; |
+ if (instr->IsMSABranchInstr()) { |
+ switch (instr->RsFieldRaw()) { |
+ case BZ_V: |
+ case BNZ_V: |
+ df = 'v'; |
+ break; |
+ case BZ_B: |
+ case BNZ_B: |
+ df = 'b'; |
+ break; |
+ case BZ_H: |
+ case BNZ_H: |
+ df = 'h'; |
+ break; |
+ case BZ_W: |
+ case BNZ_W: |
+ df = 'w'; |
+ break; |
+ case BZ_D: |
+ case BNZ_D: |
+ df = 'd'; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } else { |
+ char DF[] = {'b', 'h', 'w', 'd'}; |
+ switch (instr->MSAMinorOpcodeField()) { |
+ case kMsaMinorI5: |
+ case kMsaMinorI10: |
+ case kMsaMinor3R: |
+ df = DF[instr->Bits(22, 21)]; |
+ break; |
+ case kMsaMinorMI10: |
+ df = DF[instr->Bits(1, 0)]; |
+ break; |
+ case kMsaMinorBIT: |
+ df = DF[instr->MsaBitDf()]; |
+ break; |
+ case kMsaMinorELM: |
+ df = DF[instr->MsaElmDf()]; |
+ break; |
+ case kMsaMinor3RF: { |
+ uint32_t opcode = instr->InstructionBits() & kMsa3RFMask; |
+ switch (opcode) { |
+ case FEXDO: |
+ case FTQ: |
+ case MUL_Q: |
+ case MADD_Q: |
+ case MSUB_Q: |
+ case MULR_Q: |
+ case MADDR_Q: |
+ case MSUBR_Q: |
+ df = DF[1 + instr->Bit(21)]; |
+ break; |
+ default: |
+ df = DF[2 + instr->Bit(21)]; |
+ break; |
+ } |
+ } break; |
+ case kMsaMinor2R: |
+ df = DF[instr->Bits(17, 16)]; |
+ break; |
+ case kMsaMinor2RF: |
+ df = DF[2 + instr->Bit(16)]; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
+ |
+ PrintChar(df); |
+} |
// Printing of instruction name. |
void Decoder::PrintInstructionName(Instruction* instr) { |
@@ -537,6 +709,27 @@ int Decoder::FormatFPURegister(Instruction* instr, const char* format) { |
return -1; |
} |
+// Handle all MSARegister based formatting in this function to reduce the |
+// complexity of FormatOption. |
+int Decoder::FormatMSARegister(Instruction* instr, const char* format) { |
+ DCHECK(format[0] == 'w'); |
+ if (format[1] == 's') { |
+ int reg = instr->WsValue(); |
+ PrintMSARegister(reg); |
+ return 2; |
+ } else if (format[1] == 't') { |
+ int reg = instr->WtValue(); |
+ PrintMSARegister(reg); |
+ return 2; |
+ } else if (format[1] == 'd') { |
+ int reg = instr->WdValue(); |
+ PrintMSARegister(reg); |
+ return 2; |
+ } |
+ |
+ UNREACHABLE(); |
+ return -1; |
+} |
// FormatOption takes a formatting string and interprets it based on |
// the current instructions. The format string points to the first |
@@ -613,6 +806,16 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
break; |
} |
return 6; |
+ } else if (format[4] == '0' && format[5] == 's') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm10s")); |
+ if (format[6] == '1') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm10s1")); |
+ PrintMsaSImm10(instr, false); |
+ } else if (format[6] == '2') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm10s2")); |
+ PrintMsaSImm10(instr, true); |
+ } |
+ return 7; |
} |
} else if (format[3] == '2' && format[4] == '1') { |
DCHECK(STRING_STARTS_WITH(format, "imm21")); |
@@ -681,6 +884,28 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
} |
} |
return 6; |
+ } else if (format[3] == '5') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm5")); |
+ if (format[4] == 'u') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm5u")); |
+ PrintMsaImm5(instr); |
+ } else if (format[4] == 's') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm5s")); |
+ PrintMsaSImm5(instr); |
+ } |
+ return 5; |
+ } else if (format[3] == '8') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm8")); |
+ PrintMsaImm8(instr); |
+ return 4; |
+ } else if (format[3] == 'b') { |
+ DCHECK(STRING_STARTS_WITH(format, "immb")); |
+ PrintMsaImmBit(instr); |
+ return 4; |
+ } else if (format[3] == 'e') { |
+ DCHECK(STRING_STARTS_WITH(format, "imme")); |
+ PrintMsaImmElm(instr); |
+ return 4; |
} |
} |
case 'r': { // 'r: registers. |
@@ -689,6 +914,9 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
case 'f': { // 'f: FPUregisters. |
return FormatFPURegister(instr, format); |
} |
+ case 'w': { // 'w: MSA Register |
+ return FormatMSARegister(instr, format); |
+ } |
case 's': { // 'sa. |
switch (format[1]) { |
case 'a': |
@@ -744,7 +972,11 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
return 2; |
} |
case 't': |
- PrintFormat(instr); |
+ if (instr->IsMSAInstr()) { |
+ PrintMsaDataFormat(instr); |
+ } else { |
+ PrintFormat(instr); |
+ } |
return 1; |
} |
UNREACHABLE(); |
@@ -1401,6 +1633,27 @@ void Decoder::DecodeTypeRegister(Instruction* instr) { |
case SPECIAL3: |
DecodeTypeRegisterSPECIAL3(instr); |
break; |
+ case MSA: |
+ switch (instr->MSAMinorOpcodeField()) { |
+ case kMsaMinor3R: |
+ DecodeTypeMsa3R(instr); |
+ break; |
+ case kMsaMinor3RF: |
+ DecodeTypeMsa3RF(instr); |
+ break; |
+ case kMsaMinorVEC: |
+ DecodeTypeMsaVec(instr); |
+ break; |
+ case kMsaMinor2R: |
+ DecodeTypeMsa2R(instr); |
+ break; |
+ case kMsaMinor2RF: |
+ DecodeTypeMsa2RF(instr); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ break; |
default: |
UNREACHABLE(); |
} |
@@ -1424,6 +1677,20 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { |
case BC1NEZ: |
Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2"); |
break; |
+ case BZ_V: |
+ case BZ_B: |
+ case BZ_H: |
+ case BZ_W: |
+ case BZ_D: |
+ Format(instr, "bz.'t 'wt, 'imm16s -> 'imm16p4s2"); |
+ break; |
+ case BNZ_V: |
+ case BNZ_B: |
+ case BNZ_H: |
+ case BNZ_W: |
+ case BNZ_D: |
+ Format(instr, "bnz.'t 'wt, 'imm16s -> 'imm16p4s2"); |
+ break; |
default: |
UNREACHABLE(); |
} |
@@ -1683,6 +1950,31 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { |
} |
break; |
} |
+ case MSA: |
+ switch (instr->MSAMinorOpcodeField()) { |
+ case kMsaMinorI8: |
+ DecodeTypeMsaI8(instr); |
+ break; |
+ case kMsaMinorI5: |
+ DecodeTypeMsaI5(instr); |
+ break; |
+ case kMsaMinorI10: |
+ DecodeTypeMsaI10(instr); |
+ break; |
+ case kMsaMinorELM: |
+ DecodeTypeMsaELM(instr); |
+ break; |
+ case kMsaMinorBIT: |
+ DecodeTypeMsaBIT(instr); |
+ break; |
+ case kMsaMinorMI10: |
+ DecodeTypeMsaMI10(instr); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ break; |
default: |
printf("a 0x%x \n", instr->OpcodeFieldRaw()); |
UNREACHABLE(); |
@@ -1704,6 +1996,636 @@ void Decoder::DecodeTypeJump(Instruction* instr) { |
} |
} |
+void Decoder::DecodeTypeMsaI8(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaI8Mask; |
+ |
+ switch (opcode) { |
+ case ANDI_B: |
+ Format(instr, "andi.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case ORI_B: |
+ Format(instr, "ori.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case NORI_B: |
+ Format(instr, "nori.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case XORI_B: |
+ Format(instr, "xori.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case BMNZI_B: |
+ Format(instr, "bmnzi.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case BMZI_B: |
+ Format(instr, "bmzi.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case BSELI_B: |
+ Format(instr, "bseli.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case SHF_B: |
+ Format(instr, "shf.b 'wd, 'ws, 'imm8"); |
+ break; |
+ case SHF_H: |
+ Format(instr, "shf.h 'wd, 'ws, 'imm8"); |
+ break; |
+ case SHF_W: |
+ Format(instr, "shf.w 'wd, 'ws, 'imm8"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaI5(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaI5Mask; |
+ |
+ switch (opcode) { |
+ case ADDVI: |
+ Format(instr, "addvi.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ case SUBVI: |
+ Format(instr, "subvi.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ case MAXI_S: |
+ Format(instr, "maxi_s.'t 'wd, 'ws, 'imm5s"); |
+ break; |
+ case MAXI_U: |
+ Format(instr, "maxi_u.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ case MINI_S: |
+ Format(instr, "mini_s.'t 'wd, 'ws, 'imm5s"); |
+ break; |
+ case MINI_U: |
+ Format(instr, "mini_u.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ case CEQI: |
+ Format(instr, "ceqi.'t 'wd, 'ws, 'imm5s"); |
+ break; |
+ case CLTI_S: |
+ Format(instr, "clti_s.'t 'wd, 'ws, 'imm5s"); |
+ break; |
+ case CLTI_U: |
+ Format(instr, "clti_u.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ case CLEI_S: |
+ Format(instr, "clei_s.'t 'wd, 'ws, 'imm5s"); |
+ break; |
+ case CLEI_U: |
+ Format(instr, "clei_u.'t 'wd, 'ws, 'imm5u"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaI10(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaI5Mask; |
+ if (opcode == LDI) { |
+ Format(instr, "ldi.'t 'wd, 'imm10s1"); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaELM(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaELMMask; |
+ switch (opcode) { |
+ case SLDI: |
+ if (instr->Bits(21, 16) == 0x3E) { |
+ Format(instr, "ctcmsa "); |
+ PrintMSAControlRegister(instr->WdValue()); |
+ Print(", "); |
+ PrintRegister(instr->WsValue()); |
+ } else { |
+ Format(instr, "sldi.'t 'wd, 'ws['imme]"); |
+ } |
+ break; |
+ case SPLATI: |
+ if (instr->Bits(21, 16) == 0x3E) { |
+ Format(instr, "cfcmsa "); |
+ PrintRegister(instr->WdValue()); |
+ Print(", "); |
+ PrintMSAControlRegister(instr->WsValue()); |
+ } else { |
+ Format(instr, "splati.'t 'wd, 'ws['imme]"); |
+ } |
+ break; |
+ case COPY_S: |
+ if (instr->Bits(21, 16) == 0x3E) { |
+ Format(instr, "move.v 'wd, 'ws"); |
+ } else { |
+ Format(instr, "copy_s.'t "); |
+ PrintMsaCopy(instr); |
+ } |
+ break; |
+ case COPY_U: |
+ Format(instr, "copy_u.'t "); |
+ PrintMsaCopy(instr); |
+ break; |
+ case INSERT: |
+ Format(instr, "insert.'t 'wd['imme], "); |
+ PrintRegister(instr->WsValue()); |
+ break; |
+ case INSVE: |
+ Format(instr, "insve.'t 'wd['imme], 'ws[0]"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaBIT(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaBITMask; |
+ |
+ switch (opcode) { |
+ case SLLI: |
+ Format(instr, "slli.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SRAI: |
+ Format(instr, "srai.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SRLI: |
+ Format(instr, "srli.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case BCLRI: |
+ Format(instr, "bclri.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case BSETI: |
+ Format(instr, "bseti.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case BNEGI: |
+ Format(instr, "bnegi.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case BINSLI: |
+ Format(instr, "binsli.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case BINSRI: |
+ Format(instr, "binsri.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SAT_S: |
+ Format(instr, "sat_s.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SAT_U: |
+ Format(instr, "sat_u.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SRARI: |
+ Format(instr, "srari.'t 'wd, 'ws, 'immb"); |
+ break; |
+ case SRLRI: |
+ Format(instr, "srlri.'t 'wd, 'ws, 'immb"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaMI10(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaMI10Mask; |
+ if (opcode == MSA_LD) { |
+ Format(instr, "ld.'t 'wd, 'imm10s2("); |
+ PrintRegister(instr->WsValue()); |
+ Print(")"); |
+ } else if (opcode == MSA_ST) { |
+ Format(instr, "st.'t 'wd, 'imm10s2("); |
+ PrintRegister(instr->WsValue()); |
+ Print(")"); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsa3R(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsa3RMask; |
+ switch (opcode) { |
+ case SLL_MSA: |
+ Format(instr, "sll.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SRA_MSA: |
+ Format(instr, "sra.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SRL_MSA: |
+ Format(instr, "srl.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case BCLR: |
+ Format(instr, "bclr.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case BSET: |
+ Format(instr, "bset.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case BNEG: |
+ Format(instr, "bneg.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case BINSL: |
+ Format(instr, "binsl.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case BINSR: |
+ Format(instr, "binsr.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ADDV: |
+ Format(instr, "addv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SUBV: |
+ Format(instr, "subv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MAX_S: |
+ Format(instr, "max_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MAX_U: |
+ Format(instr, "max_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MIN_S: |
+ Format(instr, "min_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MIN_U: |
+ Format(instr, "min_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MAX_A: |
+ Format(instr, "max_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MIN_A: |
+ Format(instr, "min_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case CEQ: |
+ Format(instr, "ceq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case CLT_S: |
+ Format(instr, "clt_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case CLT_U: |
+ Format(instr, "clt_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case CLE_S: |
+ Format(instr, "cle_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case CLE_U: |
+ Format(instr, "cle_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ADD_A: |
+ Format(instr, "add_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ADDS_A: |
+ Format(instr, "adds_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ADDS_S: |
+ Format(instr, "adds_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ADDS_U: |
+ Format(instr, "adds_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case AVE_S: |
+ Format(instr, "ave_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case AVE_U: |
+ Format(instr, "ave_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case AVER_S: |
+ Format(instr, "aver_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case AVER_U: |
+ Format(instr, "aver_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SUBS_S: |
+ Format(instr, "subs_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SUBS_U: |
+ Format(instr, "subs_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SUBSUS_U: |
+ Format(instr, "subsus_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SUBSUU_S: |
+ Format(instr, "subsuu_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ASUB_S: |
+ Format(instr, "asub_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ASUB_U: |
+ Format(instr, "asub_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MULV: |
+ Format(instr, "mulv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MADDV: |
+ Format(instr, "maddv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MSUBV: |
+ Format(instr, "msubv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DIV_S_MSA: |
+ Format(instr, "div_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DIV_U: |
+ Format(instr, "div_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MOD_S: |
+ Format(instr, "mod_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MOD_U: |
+ Format(instr, "mod_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DOTP_S: |
+ Format(instr, "dotp_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DOTP_U: |
+ Format(instr, "dotp_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DPADD_S: |
+ Format(instr, "dpadd_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DPADD_U: |
+ Format(instr, "dpadd_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DPSUB_S: |
+ Format(instr, "dpsub_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case DPSUB_U: |
+ Format(instr, "dpsub_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SLD: |
+ Format(instr, "sld.'t 'wd, 'ws['rt]"); |
+ break; |
+ case SPLAT: |
+ Format(instr, "splat.'t 'wd, 'ws['rt]"); |
+ break; |
+ case PCKEV: |
+ Format(instr, "pckev.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case PCKOD: |
+ Format(instr, "pckod.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ILVL: |
+ Format(instr, "ilvl.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ILVR: |
+ Format(instr, "ilvr.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ILVEV: |
+ Format(instr, "ilvev.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case ILVOD: |
+ Format(instr, "ilvod.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case VSHF: |
+ Format(instr, "vshf.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SRAR: |
+ Format(instr, "srar.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case SRLR: |
+ Format(instr, "srlr.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case HADD_S: |
+ Format(instr, "hadd_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case HADD_U: |
+ Format(instr, "hadd_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case HSUB_S: |
+ Format(instr, "hsub_s.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case HSUB_U: |
+ Format(instr, "hsub_u.'t 'wd, 'ws, 'wt"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsa3RF(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsa3RFMask; |
+ switch (opcode) { |
+ case FCAF: |
+ Format(instr, "fcaf.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCUN: |
+ Format(instr, "fcun.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCEQ: |
+ Format(instr, "fceq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCUEQ: |
+ Format(instr, "fcueq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCLT: |
+ Format(instr, "fclt.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCULT: |
+ Format(instr, "fcult.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCLE: |
+ Format(instr, "fcle.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCULE: |
+ Format(instr, "fcule.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSAF: |
+ Format(instr, "fsaf.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSUN: |
+ Format(instr, "fsun.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSEQ: |
+ Format(instr, "fseq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSUEQ: |
+ Format(instr, "fsueq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSLT: |
+ Format(instr, "fslt.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSULT: |
+ Format(instr, "fsult.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSLE: |
+ Format(instr, "fsle.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSULE: |
+ Format(instr, "fsule.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FADD: |
+ Format(instr, "fadd.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSUB: |
+ Format(instr, "fsub.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMUL: |
+ Format(instr, "fmul.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FDIV: |
+ Format(instr, "fdiv.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMADD: |
+ Format(instr, "fmadd.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMSUB: |
+ Format(instr, "fmsub.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FEXP2: |
+ Format(instr, "fexp2.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FEXDO: |
+ Format(instr, "fexdo.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FTQ: |
+ Format(instr, "ftq.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMIN: |
+ Format(instr, "fmin.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMIN_A: |
+ Format(instr, "fmin_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMAX: |
+ Format(instr, "fmax.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FMAX_A: |
+ Format(instr, "fmax_a.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCOR: |
+ Format(instr, "fcor.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCUNE: |
+ Format(instr, "fcune.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FCNE: |
+ Format(instr, "fcne.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MUL_Q: |
+ Format(instr, "mul_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MADD_Q: |
+ Format(instr, "madd_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MSUB_Q: |
+ Format(instr, "msub_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSOR: |
+ Format(instr, "fsor.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSUNE: |
+ Format(instr, "fsune.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case FSNE: |
+ Format(instr, "fsne.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MULR_Q: |
+ Format(instr, "mulr_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MADDR_Q: |
+ Format(instr, "maddr_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ case MSUBR_Q: |
+ Format(instr, "msubr_q.'t 'wd, 'ws, 'wt"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsaVec(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsaVECMask; |
+ switch (opcode) { |
+ case AND_V: |
+ Format(instr, "and.v 'wd, 'ws, 'wt"); |
+ break; |
+ case OR_V: |
+ Format(instr, "or.v 'wd, 'ws, 'wt"); |
+ break; |
+ case NOR_V: |
+ Format(instr, "nor.v 'wd, 'ws, 'wt"); |
+ break; |
+ case XOR_V: |
+ Format(instr, "xor.v 'wd, 'ws, 'wt"); |
+ break; |
+ case BMNZ_V: |
+ Format(instr, "bmnz.v 'wd, 'ws, 'wt"); |
+ break; |
+ case BMZ_V: |
+ Format(instr, "bmz.v 'wd, 'ws, 'wt"); |
+ break; |
+ case BSEL_V: |
+ Format(instr, "bsel.v 'wd, 'ws, 'wt"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsa2R(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsa2RMask; |
+ switch (opcode) { |
+ case FILL: { |
+ Format(instr, "fill.'t 'wd, "); |
+ PrintRegister(instr->WsValue()); // rs value is in ws field |
+ } break; |
+ case PCNT: |
+ Format(instr, "pcnt.'t 'wd, 'ws"); |
+ break; |
+ case NLOC: |
+ Format(instr, "nloc.'t 'wd, 'ws"); |
+ break; |
+ case NLZC: |
+ Format(instr, "nlzc.'t 'wd, 'ws"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
+ |
+void Decoder::DecodeTypeMsa2RF(Instruction* instr) { |
+ uint32_t opcode = instr->InstructionBits() & kMsa2RFMask; |
+ switch (opcode) { |
+ case FCLASS: |
+ Format(instr, "fclass.'t 'wd, 'ws"); |
+ break; |
+ case FTRUNC_S: |
+ Format(instr, "ftrunc_s.'t 'wd, 'ws"); |
+ break; |
+ case FTRUNC_U: |
+ Format(instr, "ftrunc_u.'t 'wd, 'ws"); |
+ break; |
+ case FSQRT: |
+ Format(instr, "fsqrt.'t 'wd, 'ws"); |
+ break; |
+ case FRSQRT: |
+ Format(instr, "frsqrt.'t 'wd, 'ws"); |
+ break; |
+ case FRCP: |
+ Format(instr, "frcp.'t 'wd, 'ws"); |
+ break; |
+ case FRINT: |
+ Format(instr, "frint.'t 'wd, 'ws"); |
+ break; |
+ case FLOG2: |
+ Format(instr, "flog2.'t 'wd, 'ws"); |
+ break; |
+ case FEXUPL: |
+ Format(instr, "fexupl.'t 'wd, 'ws"); |
+ break; |
+ case FEXUPR: |
+ Format(instr, "fexupr.'t 'wd, 'ws"); |
+ break; |
+ case FFQL: |
+ Format(instr, "ffql.'t 'wd, 'ws"); |
+ break; |
+ case FFQR: |
+ Format(instr, "ffqr.'t 'wd, 'ws"); |
+ break; |
+ case FTINT_S: |
+ Format(instr, "ftint_s.'t 'wd, 'ws"); |
+ break; |
+ case FTINT_U: |
+ Format(instr, "ftint_u.'t 'wd, 'ws"); |
+ break; |
+ case FFINT_S: |
+ Format(instr, "ffint_s.'t 'wd, 'ws"); |
+ break; |
+ case FFINT_U: |
+ Format(instr, "ffint_u.'t 'wd, 'ws"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+} |
// Disassemble the instruction at *instr_ptr into the output buffer. |
int Decoder::InstructionDecode(byte* instr_ptr) { |