| 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();
|
|
|