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