| Index: src/mips64/disasm-mips64.cc
|
| diff --git a/src/mips64/disasm-mips64.cc b/src/mips64/disasm-mips64.cc
|
| index 3ce2b45380ce7dcd6da4c90a67dec96dfdae34d3..ee624db2f8cab4d92fb4df9d02e74baaeb11c558 100644
|
| --- a/src/mips64/disasm-mips64.cc
|
| +++ b/src/mips64/disasm-mips64.cc
|
| @@ -86,13 +86,18 @@ class Decoder {
|
| void PrintUImm16(Instruction* instr);
|
| void PrintSImm16(Instruction* instr);
|
| void PrintXImm16(Instruction* instr);
|
| + void PrintPCImm16(Instruction* instr, int delta_pc, int n_bits);
|
| void PrintXImm18(Instruction* instr);
|
| void PrintSImm18(Instruction* instr);
|
| void PrintXImm19(Instruction* instr);
|
| void PrintSImm19(Instruction* instr);
|
| void PrintXImm21(Instruction* instr);
|
| +
|
| + void PrintPCImm21(Instruction* instr, int delta_pc, int n_bits);
|
| void PrintXImm26(Instruction* instr);
|
| void PrintSImm26(Instruction* instr);
|
| + void PrintPCImm26(Instruction* instr, int delta_pc, int n_bits);
|
| + void PrintPCImm26(Instruction* instr);
|
| void PrintCode(Instruction* instr); // For break and trap instructions.
|
| void PrintFormat(Instruction* instr); // For floating format postfix.
|
| void PrintBp2(Instruction* instr);
|
| @@ -271,6 +276,18 @@ void Decoder::PrintXImm16(Instruction* instr) {
|
| }
|
|
|
|
|
| +// Print absoulte address for 16-bit offset or immediate value.
|
| +// The absolute address is calculated according following expression:
|
| +// PC + delta_pc + (offset << n_bits)
|
| +void Decoder::PrintPCImm16(Instruction* instr, int delta_pc, int n_bits) {
|
| + int16_t offset = instr->Imm16Value();
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
|
| + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
|
| + delta_pc + (offset << n_bits)));
|
| +}
|
| +
|
| +
|
| // Print 18-bit signed immediate value.
|
| void Decoder::PrintSImm18(Instruction* instr) {
|
| int32_t imm =
|
| @@ -310,6 +327,21 @@ void Decoder::PrintXImm21(Instruction* instr) {
|
| }
|
|
|
|
|
| +// Print absoulte address for 21-bit offset or immediate value.
|
| +// The absolute address is calculated according following expression:
|
| +// PC + delta_pc + (offset << n_bits)
|
| +void Decoder::PrintPCImm21(Instruction* instr, int delta_pc, int n_bits) {
|
| + int32_t imm21 = instr->Imm21Value();
|
| + // set sign
|
| + imm21 <<= (32 - kImm21Bits);
|
| + imm21 >>= (32 - kImm21Bits);
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
|
| + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
|
| + delta_pc + (imm21 << n_bits)));
|
| +}
|
| +
|
| +
|
| // Print 26-bit hex immediate value.
|
| void Decoder::PrintXImm26(Instruction* instr) {
|
| uint32_t imm = static_cast<uint32_t>(instr->Imm26Value()) << kImmFieldShift;
|
| @@ -327,6 +359,34 @@ void Decoder::PrintSImm26(Instruction* instr) {
|
| }
|
|
|
|
|
| +// Print absoulte address for 26-bit offset or immediate value.
|
| +// The absolute address is calculated according following expression:
|
| +// PC + delta_pc + (offset << n_bits)
|
| +void Decoder::PrintPCImm26(Instruction* instr, int delta_pc, int n_bits) {
|
| + int32_t imm26 = instr->Imm26Value();
|
| + // set sign
|
| + imm26 <<= (32 - kImm26Bits);
|
| + imm26 >>= (32 - kImm26Bits);
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
|
| + converter_.NameOfAddress(reinterpret_cast<byte*>(instr) +
|
| + delta_pc + (imm26 << n_bits)));
|
| +}
|
| +
|
| +
|
| +// Print absoulte address for 26-bit offset or immediate value.
|
| +// The absolute address is calculated according following expression:
|
| +// PC[GPRLEN-1 .. 28] || instr_index26 || 00
|
| +void Decoder::PrintPCImm26(Instruction* instr) {
|
| + int32_t imm26 = instr->Imm26Value();
|
| + uint64_t pc_mask = ~0xfffffff;
|
| + uint64_t pc = ((uint64_t)(instr + 1) & pc_mask) | (imm26 << 2);
|
| + out_buffer_pos_ +=
|
| + SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
|
| + converter_.NameOfAddress((reinterpret_cast<byte*>(pc))));
|
| +}
|
| +
|
| +
|
| void Decoder::PrintBp2(Instruction* instr) {
|
| int bp2 = instr->Bp2Value();
|
| out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", bp2);
|
| @@ -472,6 +532,24 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
|
| DCHECK(STRING_STARTS_WITH(format, "imm16x"));
|
| PrintXImm16(instr);
|
| break;
|
| + case 'p': { // The PC relative address.
|
| + DCHECK(STRING_STARTS_WITH(format, "imm16p"));
|
| + int delta_pc = 0;
|
| + int n_bits = 0;
|
| + switch (format[6]) {
|
| + case '4': {
|
| + DCHECK(STRING_STARTS_WITH(format, "imm16p4"));
|
| + delta_pc = 4;
|
| + switch (format[8]) {
|
| + case '2':
|
| + DCHECK(STRING_STARTS_WITH(format, "imm16p4s2"));
|
| + n_bits = 2;
|
| + PrintPCImm16(instr, delta_pc, n_bits);
|
| + return 9;
|
| + }
|
| + }
|
| + }
|
| + }
|
| }
|
| return 6;
|
| } else if (format[4] == '8') {
|
| @@ -502,8 +580,31 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
|
| 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 'x':
|
| + DCHECK(STRING_STARTS_WITH(format, "imm21x"));
|
| + PrintXImm21(instr);
|
| + break;
|
| + case 'p': { // The PC relative address.
|
| + DCHECK(STRING_STARTS_WITH(format, "imm21p"));
|
| + int delta_pc = 0;
|
| + int n_bits = 0;
|
| + switch (format[6]) {
|
| + case '4': {
|
| + DCHECK(STRING_STARTS_WITH(format, "imm21p4"));
|
| + delta_pc = 4;
|
| + switch (format[8]) {
|
| + case '2':
|
| + DCHECK(STRING_STARTS_WITH(format, "imm21p4s2"));
|
| + n_bits = 2;
|
| + PrintPCImm21(instr, delta_pc, n_bits);
|
| + return 9;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| return 6;
|
| } else if (format[3] == '2' && format[4] == '6') {
|
| DCHECK(STRING_STARTS_WITH(format, "imm26"));
|
| @@ -516,6 +617,29 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
|
| DCHECK(STRING_STARTS_WITH(format, "imm26x"));
|
| PrintXImm26(instr);
|
| break;
|
| + case 'p': { // The PC relative address.
|
| + DCHECK(STRING_STARTS_WITH(format, "imm26p"));
|
| + int delta_pc = 0;
|
| + int n_bits = 0;
|
| + switch (format[6]) {
|
| + case '4': {
|
| + DCHECK(STRING_STARTS_WITH(format, "imm26p4"));
|
| + delta_pc = 4;
|
| + switch (format[8]) {
|
| + case '2':
|
| + DCHECK(STRING_STARTS_WITH(format, "imm26p4s2"));
|
| + n_bits = 2;
|
| + PrintPCImm26(instr, delta_pc, n_bits);
|
| + return 9;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + case 'j': { // Absolute address for jump instructions.
|
| + DCHECK(STRING_STARTS_WITH(format, "imm26j"));
|
| + PrintPCImm26(instr);
|
| + break;
|
| + }
|
| }
|
| return 6;
|
| }
|
| @@ -1358,16 +1482,16 @@ void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
|
| switch (instr->RsFieldRaw()) {
|
| case BC1:
|
| if (instr->FBtrueValue()) {
|
| - Format(instr, "bc1t 'bc, 'imm16u");
|
| + Format(instr, "bc1t 'bc, 'imm16u -> 'imm16p4s2");
|
| } else {
|
| - Format(instr, "bc1f 'bc, 'imm16u");
|
| + Format(instr, "bc1f 'bc, 'imm16u -> 'imm16p4s2");
|
| }
|
| break;
|
| case BC1EQZ:
|
| - Format(instr, "bc1eqz 'ft, 'imm16u");
|
| + Format(instr, "bc1eqz 'ft, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BC1NEZ:
|
| - Format(instr, "bc1nez 'ft, 'imm16u");
|
| + Format(instr, "bc1nez 'ft, 'imm16u -> 'imm16p4s2");
|
| break;
|
| default:
|
| UNREACHABLE();
|
| @@ -1378,19 +1502,19 @@ void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) {
|
| void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
|
| switch (instr->RtFieldRaw()) {
|
| case BLTZ:
|
| - Format(instr, "bltz 'rs, 'imm16u");
|
| + Format(instr, "bltz 'rs, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BLTZAL:
|
| - Format(instr, "bltzal 'rs, 'imm16u");
|
| + Format(instr, "bltzal 'rs, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BGEZ:
|
| - Format(instr, "bgez 'rs, 'imm16u");
|
| + Format(instr, "bgez 'rs, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BGEZAL:
|
| - Format(instr, "bgezal 'rs, 'imm16u");
|
| + Format(instr, "bgezal 'rs, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BGEZALL:
|
| - Format(instr, "bgezall 'rs, 'imm16u");
|
| + Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case DAHI:
|
| Format(instr, "dahi 'rs, 'imm16u");
|
| @@ -1411,79 +1535,71 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| break; // Case COP1.
|
| // ------------- REGIMM class.
|
| case REGIMM:
|
| -
|
| - break; // Case REGIMM.
|
| + DecodeTypeImmediateREGIMM(instr);
|
| + break; // Case REGIMM.
|
| // ------------- Branch instructions.
|
| case BEQ:
|
| - Format(instr, "beq 'rs, 'rt, 'imm16u");
|
| + Format(instr, "beq 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BC:
|
| - Format(instr, "bc 'imm26s");
|
| + Format(instr, "bc 'imm26s -> 'imm26p4s2");
|
| break;
|
| case BALC:
|
| - Format(instr, "balc 'imm26s");
|
| + Format(instr, "balc 'imm26s -> 'imm26p4s2");
|
| break;
|
| case BNE:
|
| - Format(instr, "bne 'rs, 'rt, 'imm16u");
|
| + Format(instr, "bne 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| break;
|
| case BLEZ:
|
| - 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");
|
| + if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
|
| + Format(instr, "blez 'rs, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() != instr->RsValue()) &&
|
| + (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bgeuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() == instr->RsValue()) &&
|
| + (instr->RtValue() != 0)) {
|
| + Format(instr, "bgezalc 'rs, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "blezalc 'rt, 'imm16u -> 'imm16p4s2");
|
| } else {
|
| UNREACHABLE();
|
| }
|
| break;
|
| case BGTZ:
|
| - 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");
|
| + if ((instr->RtValue() == 0) && (instr->RsValue() != 0)) {
|
| + Format(instr, "bgtz 'rs, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() != instr->RsValue()) &&
|
| + (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bltuc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() == instr->RsValue()) &&
|
| + (instr->RtValue() != 0)) {
|
| + Format(instr, "bltzalc 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bgtzalc 'rt, 'imm16u -> 'imm16p4s2");
|
| } 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");
|
| + if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bgezc 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() != instr->RsValue()) &&
|
| + (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bgec 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "blezc 'rt, 'imm16u -> 'imm16p4s2");
|
| } 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");
|
| + if ((instr->RtValue() == instr->RsValue()) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bltzc 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RtValue() != instr->RsValue()) &&
|
| + (instr->RsValue() != 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bltc 'rs, 'rt, 'imm16u -> 'imm16p4s2");
|
| + } else if ((instr->RsValue() == 0) && (instr->RtValue() != 0)) {
|
| + Format(instr, "bgtzc 'rt, 'imm16u -> 'imm16p4s2");
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -1492,14 +1608,14 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| if (instr->RsValue() == JIC) {
|
| Format(instr, "jic 'rt, 'imm16s");
|
| } else {
|
| - Format(instr, "beqzc 'rs, 'imm21x");
|
| + Format(instr, "beqzc 'rs, 'imm21x -> 'imm21p4s2");
|
| }
|
| break;
|
| case POP76:
|
| if (instr->RsValue() == JIALC) {
|
| Format(instr, "jialc 'rt, 'imm16x");
|
| } else {
|
| - Format(instr, "bnezc 'rs, 'imm21x");
|
| + Format(instr, "bnezc 'rs, 'imm21x -> 'imm21p4s2");
|
| }
|
| break;
|
| // ------------- Arithmetic instructions.
|
| @@ -1508,10 +1624,10 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| 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");
|
| + if (instr->RsValue() >= instr->RtValue()) {
|
| + Format(instr, "bovc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
|
| + } else if (instr->RsValue() < instr->RtValue()) {
|
| + Format(instr, "beqc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -1522,10 +1638,10 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| 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");
|
| + if (instr->RsValue() >= instr->RtValue()) {
|
| + Format(instr, "bnvc 'rs, 'rt, 'imm16s -> 'imm16p4s2");
|
| + } else if (instr->RsValue() < instr->RtValue()) {
|
| + Format(instr, "bnec 'rs, 'rt, 'imm16s -> 'imm16p4s2");
|
| } else {
|
| UNREACHABLE();
|
| }
|
| @@ -1687,10 +1803,10 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
|
| void Decoder::DecodeTypeJump(Instruction* instr) {
|
| switch (instr->OpcodeFieldRaw()) {
|
| case J:
|
| - Format(instr, "j 'imm26x");
|
| + Format(instr, "j 'imm26x -> 'imm26j");
|
| break;
|
| case JAL:
|
| - Format(instr, "jal 'imm26x");
|
| + Format(instr, "jal 'imm26x -> 'imm26j");
|
| break;
|
| default:
|
| UNREACHABLE();
|
|
|