Index: src/mips/disasm-mips.cc |
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc |
index 381e2f14474e951aa49576f42ab048af8b63ecd2..73169ca00f732d9489384067ccdf5de87a4ac3b1 100644 |
--- a/src/mips/disasm-mips.cc |
+++ b/src/mips/disasm-mips.cc |
@@ -81,13 +81,20 @@ class Decoder { |
void PrintSs2(Instruction* instr); |
void PrintBc(Instruction* instr); |
void PrintCc(Instruction* instr); |
+ void PrintBp2(Instruction* instr); |
void PrintFunction(Instruction* instr); |
void PrintSecondaryField(Instruction* instr); |
void PrintUImm16(Instruction* instr); |
void PrintSImm16(Instruction* instr); |
void PrintXImm16(Instruction* instr); |
+ void PrintXImm18(Instruction* instr); |
+ void PrintSImm18(Instruction* instr); |
+ void PrintXImm19(Instruction* instr); |
+ void PrintSImm19(Instruction* instr); |
void PrintXImm21(Instruction* instr); |
+ void PrintSImm21(Instruction* instr); |
void PrintXImm26(Instruction* instr); |
+ void PrintSImm26(Instruction* instr); |
void PrintCode(Instruction* instr); // For break and trap instructions. |
void PrintFormat(Instruction* instr); // For floating format postfix. |
// Printing of instruction name. |
@@ -236,6 +243,12 @@ void Decoder::PrintCc(Instruction* instr) { |
} |
+void Decoder::PrintBp2(Instruction* instr) { |
+ int bp2 = instr->Bp2Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp2); |
+} |
+ |
+ |
// Print 16-bit unsigned immediate value. |
void Decoder::PrintUImm16(Instruction* instr) { |
int32_t imm = instr->Imm16Value(); |
@@ -257,6 +270,38 @@ void Decoder::PrintXImm16(Instruction* instr) { |
} |
+// Print 18-bit signed immediate value. |
+void Decoder::PrintSImm18(Instruction* instr) { |
+ int32_t imm = |
+ ((instr->Imm18Value()) << (32 - kImm18Bits)) >> (32 - kImm18Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); |
+} |
+ |
+ |
+// Print 18-bit hexa immediate value. |
+void Decoder::PrintXImm18(Instruction* instr) { |
+ int32_t imm = instr->Imm18Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
+} |
+ |
+ |
+// Print 19-bit hexa immediate value. |
+void Decoder::PrintXImm19(Instruction* instr) { |
+ int32_t imm = instr->Imm19Value(); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
+} |
+ |
+ |
+// Print 19-bit signed immediate value. |
+void Decoder::PrintSImm19(Instruction* instr) { |
+ int32_t imm19 = instr->Imm19Value(); |
+ // set sign |
+ imm19 <<= (32 - kImm19Bits); |
+ imm19 >>= (32 - kImm19Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm19); |
+} |
+ |
+ |
// Print 21-bit immediate value. |
void Decoder::PrintXImm21(Instruction* instr) { |
uint32_t imm = instr->Imm21Value(); |
@@ -264,13 +309,33 @@ void Decoder::PrintXImm21(Instruction* instr) { |
} |
-// Print 26-bit immediate value. |
+// Print 21-bit signed immediate value. |
+void Decoder::PrintSImm21(Instruction* instr) { |
+ int32_t imm21 = instr->Imm21Value(); |
+ // set sign |
+ imm21 <<= (32 - kImm21Bits); |
+ imm21 >>= (32 - kImm21Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm21); |
+} |
+ |
+ |
+// Print 26-bit hex immediate value. |
void Decoder::PrintXImm26(Instruction* instr) { |
uint32_t imm = instr->Imm26Value() << kImmFieldShift; |
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
} |
+// Print 26-bit signed immediate value. |
+void Decoder::PrintSImm26(Instruction* instr) { |
+ int32_t imm26 = instr->Imm26Value(); |
+ // set sign |
+ imm26 <<= (32 - kImm26Bits); |
+ imm26 >>= (32 - kImm26Bits); |
+ out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm26); |
+} |
+ |
+ |
// Print 26-bit immediate value. |
void Decoder::PrintCode(Instruction* instr) { |
if (instr->OpcodeFieldRaw() != SPECIAL) |
@@ -389,25 +454,75 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
} |
case 'i': { // 'imm16u or 'imm26. |
if (format[3] == '1') { |
- DCHECK(STRING_STARTS_WITH(format, "imm16")); |
- if (format[5] == 's') { |
- DCHECK(STRING_STARTS_WITH(format, "imm16s")); |
- PrintSImm16(instr); |
- } else if (format[5] == 'u') { |
- DCHECK(STRING_STARTS_WITH(format, "imm16u")); |
- PrintSImm16(instr); |
- } else { |
- DCHECK(STRING_STARTS_WITH(format, "imm16x")); |
- PrintXImm16(instr); |
+ if (format[4] == '6') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm16")); |
+ switch (format[5]) { |
+ case 's': |
+ DCHECK(STRING_STARTS_WITH(format, "imm16s")); |
+ PrintSImm16(instr); |
+ break; |
+ case 'u': |
+ DCHECK(STRING_STARTS_WITH(format, "imm16u")); |
+ PrintSImm16(instr); |
+ break; |
+ case 'x': |
+ DCHECK(STRING_STARTS_WITH(format, "imm16x")); |
+ PrintXImm16(instr); |
+ break; |
+ } |
+ return 6; |
+ } else if (format[4] == '8') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm18")); |
+ switch (format[5]) { |
+ case 's': |
+ DCHECK(STRING_STARTS_WITH(format, "imm18s")); |
+ PrintSImm18(instr); |
+ break; |
+ case 'x': |
+ DCHECK(STRING_STARTS_WITH(format, "imm18x")); |
+ PrintXImm18(instr); |
+ break; |
+ } |
+ return 6; |
+ } else if (format[4] == '9') { |
+ DCHECK(STRING_STARTS_WITH(format, "imm19")); |
+ switch (format[5]) { |
+ case 's': |
+ DCHECK(STRING_STARTS_WITH(format, "imm19s")); |
+ PrintSImm19(instr); |
+ break; |
+ case 'x': |
+ DCHECK(STRING_STARTS_WITH(format, "imm19x")); |
+ PrintXImm19(instr); |
+ break; |
+ } |
+ return 6; |
} |
- return 6; |
} else if (format[3] == '2' && format[4] == '1') { |
- DCHECK(STRING_STARTS_WITH(format, "imm21x")); |
- PrintXImm21(instr); |
+ DCHECK(STRING_STARTS_WITH(format, "imm21")); |
+ switch (format[5]) { |
+ case 's': |
+ DCHECK(STRING_STARTS_WITH(format, "imm21s")); |
+ PrintSImm21(instr); |
+ break; |
+ case 'x': |
+ DCHECK(STRING_STARTS_WITH(format, "imm21x")); |
+ PrintXImm21(instr); |
+ break; |
+ } |
return 6; |
} else if (format[3] == '2' && format[4] == '6') { |
- DCHECK(STRING_STARTS_WITH(format, "imm26x")); |
- PrintXImm26(instr); |
+ DCHECK(STRING_STARTS_WITH(format, "imm26")); |
+ switch (format[5]) { |
+ case 's': |
+ DCHECK(STRING_STARTS_WITH(format, "imm26s")); |
+ PrintSImm26(instr); |
+ break; |
+ case 'x': |
+ DCHECK(STRING_STARTS_WITH(format, "imm26x")); |
+ PrintXImm26(instr); |
+ break; |
+ } |
return 6; |
} |
} |
@@ -442,10 +557,23 @@ int Decoder::FormatOption(Instruction* instr, const char* format) { |
} |
} |
} |
- case 'b': { // 'bc - Special for bc1 cc field. |
- DCHECK(STRING_STARTS_WITH(format, "bc")); |
- PrintBc(instr); |
- return 2; |
+ case 'b': { |
+ switch (format[1]) { |
+ case 'c': { // 'bc - Special for bc1 cc field. |
+ DCHECK(STRING_STARTS_WITH(format, "bc")); |
+ PrintBc(instr); |
+ return 2; |
+ } |
+ case 'p': { |
+ switch (format[2]) { |
+ case '2': { // 'bp2 |
+ DCHECK(STRING_STARTS_WITH(format, "bp2")); |
+ PrintBp2(instr); |
+ return 3; |
+ } |
+ } |
+ } |
+ } |
} |
case 'C': { // 'Cc - Special for c.xx.d cc field. |
DCHECK(STRING_STARTS_WITH(format, "Cc")); |
@@ -941,7 +1069,7 @@ void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { |
void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { |
switch (instr->FunctionFieldRaw()) { |
case INS: { |
- if (IsMipsArchVariant(kMips32r2)) { |
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { |
Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
} else { |
Unknown(instr); |
@@ -949,18 +1077,45 @@ void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { |
break; |
} |
case EXT: { |
- if (IsMipsArchVariant(kMips32r2)) { |
+ if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { |
Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
} else { |
Unknown(instr); |
} |
break; |
} |
- case BITSWAP: { |
- if (IsMipsArchVariant(kMips32r6)) { |
- Format(instr, "bitswap 'rd, 'rt"); |
- } else { |
- Unknown(instr); |
+ case BSHFL: { |
+ int sa = instr->SaFieldRaw() >> kSaShift; |
+ switch (sa) { |
+ case BITSWAP: { |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ Format(instr, "bitswap 'rd, 'rt"); |
+ } else { |
+ Unknown(instr); |
+ } |
+ break; |
+ } |
+ case SEB: |
+ case SEH: |
+ case WSBH: |
+ UNREACHABLE(); |
+ break; |
+ default: { |
+ sa >>= kBp2Bits; |
+ switch (sa) { |
+ case ALIGN: { |
+ if (IsMipsArchVariant(kMips32r6)) { |
+ Format(instr, "align 'rd, 'rs, 'rt, 'bp2"); |
+ } else { |
+ Unknown(instr); |
+ } |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
} |
break; |
} |
@@ -1087,6 +1242,12 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { |
case BEQ: |
Format(instr, "beq 'rs, 'rt, 'imm16u"); |
break; |
+ case BC: |
+ Format(instr, "bc 'imm26s"); |
+ break; |
+ case BALC: |
+ Format(instr, "balc 'imm26s"); |
+ break; |
case BNE: |
Format(instr, "bne 'rs, 'rt, 'imm16u"); |
break; |
@@ -1152,13 +1313,17 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { |
UNREACHABLE(); |
} |
break; |
- case BEQZC: |
- if (instr->RsFieldRaw() != 0) { |
- Format(instr, "beqzc 'rs, 'imm21x"); |
+ case POP66: |
+ if (instr->RsValue() == JIC) { |
+ Format(instr, "jic 'rt, 'imm16s"); |
+ } else { |
+ Format(instr, "beqzc 'rs, 'imm21s"); |
} |
break; |
- case BNEZC: |
- if (instr->RsFieldRaw() != 0) { |
+ case POP76: |
+ if (instr->RsValue() == JIALC) { |
+ Format(instr, "jialc 'rt, 'imm16x"); |
+ } else { |
Format(instr, "bnezc 'rs, 'imm21x"); |
} |
break; |
@@ -1270,6 +1435,35 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { |
case SDC1: |
Format(instr, "sdc1 'ft, 'imm16s('rs)"); |
break; |
+ case PCREL: { |
+ int32_t imm21 = instr->Imm21Value(); |
+ // rt field: 5-bits checking |
+ uint8_t rt = (imm21 >> kImm16Bits); |
+ switch (rt) { |
+ case ALUIPC: |
+ Format(instr, "aluipc 'rs, 'imm16s"); |
+ break; |
+ case AUIPC: |
+ Format(instr, "auipc 'rs, 'imm16s"); |
+ break; |
+ default: { |
+ // rt field: checking of the most significant 2-bits |
+ rt = (imm21 >> kImm19Bits); |
+ switch (rt) { |
+ case LWPC: |
+ Format(instr, "lwpc 'rs, 'imm19s"); |
+ break; |
+ case ADDIUPC: |
+ Format(instr, "addiupc 'rs, 'imm19s"); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
+ } |
+ break; |
+ } |
default: |
printf("a 0x%x \n", instr->OpcodeFieldRaw()); |
UNREACHABLE(); |