Commit 75e67175 authored by Ilija.Pavlovic's avatar Ilija.Pavlovic Committed by Commit bot

MIPS: Disassembler enhancement. Disassembled branch instruction displays...

MIPS: Disassembler enhancement. Disassembled branch instruction displays branch target absolute address.

TEST=cctest/test-disasm-mips[64]
BUG=

Review URL: https://codereview.chromium.org/1213553004

Cr-Commit-Position: refs/heads/master@{#29462}
parent 84f0a33c
......@@ -87,14 +87,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 PrintSImm21(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.
// Printing of instruction name.
......@@ -270,6 +274,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 =
......@@ -319,6 +335,21 @@ void Decoder::PrintSImm21(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 = instr->Imm26Value() << kImmFieldShift;
......@@ -336,6 +367,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();
uint32_t pc_mask = ~0xfffffff;
uint32_t pc = ((uint32_t)(instr + 1) & pc_mask) | (imm26 << 2);
out_buffer_pos_ +=
SNPrintF(out_buffer_ + out_buffer_pos_, "%s",
converter_.NameOfAddress((reinterpret_cast<byte*>(pc))));
}
// Print 26-bit immediate value.
void Decoder::PrintCode(Instruction* instr) {
if (instr->OpcodeFieldRaw() != SPECIAL)
......@@ -469,6 +528,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') {
......@@ -509,6 +586,24 @@ int Decoder::FormatOption(Instruction* instr, const char* format) {
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') {
......@@ -522,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;
}
......@@ -1200,16 +1318,16 @@ void Decoder::DecodeTypeImmediate(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();
......@@ -1220,19 +1338,19 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
case REGIMM:
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;
default:
UNREACHABLE();
......@@ -1240,75 +1358,67 @@ void Decoder::DecodeTypeImmediate(Instruction* 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();
}
......@@ -1317,14 +1427,14 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
if (instr->RsValue() == JIC) {
Format(instr, "jic 'rt, 'imm16s");
} else {
Format(instr, "beqzc 'rs, 'imm21s");
Format(instr, "beqzc 'rs, 'imm21s -> '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.
......@@ -1333,10 +1443,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();
}
......@@ -1345,10 +1455,10 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
case DADDI:
if (IsMipsArchVariant(kMips32r6)) {
// 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();
}
......@@ -1475,10 +1585,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();
......
......@@ -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();
......
......@@ -92,6 +92,45 @@ if (failure) { \
}
#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, progcounter + 4 + (offset << 2)); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_REL(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, progcounter + (offset << 2)); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_JUMP(asm_, compare_string, target) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
int instr_index = target >> 2; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, reinterpret_cast<byte *>( \
((uint32_t)(progcounter + 1) & ~0xfffffff) | \
(instr_index << 2))); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
TEST(Type0) {
SET_UP();
......@@ -199,50 +238,241 @@ TEST(Type0) {
COMPARE(modu(v0, v1, a0),
"006410db modu v0, v1, a0");
COMPARE(bovc(a0, a0, static_cast<int16_t>(0)),
"20840000 bovc a0, a0, 0");
COMPARE(bovc(a1, a0, static_cast<int16_t>(0)),
"20a40000 bovc a1, a0, 0");
COMPARE(bovc(a1, a0, 32767),
"20a47fff bovc a1, a0, 32767");
COMPARE(bovc(a1, a0, -32768),
"20a48000 bovc a1, a0, -32768");
COMPARE(bnvc(a0, a0, static_cast<int16_t>(0)),
"60840000 bnvc a0, a0, 0");
COMPARE(bnvc(a1, a0, static_cast<int16_t>(0)),
"60a40000 bnvc a1, a0, 0");
COMPARE(bnvc(a1, a0, 32767),
"60a47fff bnvc a1, a0, 32767");
COMPARE(bnvc(a1, a0, -32768),
"60a48000 bnvc a1, a0, -32768");
COMPARE(beqzc(a0, -1048576), "d8900000 beqzc a0, -1048576");
COMPARE(beqzc(a0, -1), "d89fffff beqzc a0, -1");
COMPARE(beqzc(a0, 0), "d8800000 beqzc a0, 0");
COMPARE(beqzc(a0, 1), "d8800001 beqzc a0, 1");
COMPARE(beqzc(a0, 1048575), "d88fffff beqzc a0, 1048575");
COMPARE(bnezc(a0, 0),
"f8800000 bnezc a0, 0x0");
COMPARE(bnezc(a0, 0xfffff), // 0x0fffff == 1048575.
"f88fffff bnezc a0, 0xfffff");
COMPARE(bnezc(a0, 0x100000), // 0x100000 == -1048576.
"f8900000 bnezc a0, 0x100000");
COMPARE(bc(-33554432), "ca000000 bc -33554432");
COMPARE(bc(-1), "cbffffff bc -1");
COMPARE(bc(0), "c8000000 bc 0");
COMPARE(bc(1), "c8000001 bc 1");
COMPARE(bc(33554431), "c9ffffff bc 33554431");
COMPARE(balc(-33554432), "ea000000 balc -33554432");
COMPARE(balc(-1), "ebffffff balc -1");
COMPARE(balc(0), "e8000000 balc 0");
COMPARE(balc(1), "e8000001 balc 1");
COMPARE(balc(33554431), "e9ffffff balc 33554431");
COMPARE_PC_REL_COMPACT(bovc(a0, a0, static_cast<int16_t>(0)),
"20840000 bovc a0, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, static_cast<int16_t>(0)),
"20a40000 bovc a1, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, 32767),
"20a47fff bovc a1, a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, -32768),
"20a48000 bovc a1, a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bnvc(a0, a0, static_cast<int16_t>(0)),
"60840000 bnvc a0, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, static_cast<int16_t>(0)),
"60a40000 bnvc a1, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, 32767),
"60a47fff bnvc a1, a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, -32768),
"60a48000 bnvc a1, a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(beqzc(a0, -1048576),
"d8900000 beqzc a0, -1048576", -1048576);
COMPARE_PC_REL_COMPACT(beqzc(a0, -1), "d89fffff beqzc a0, -1", -1);
COMPARE_PC_REL_COMPACT(beqzc(a0, 0), "d8800000 beqzc a0, 0", 0);
COMPARE_PC_REL_COMPACT(beqzc(a0, 1), "d8800001 beqzc a0, 1", 1);
COMPARE_PC_REL_COMPACT(beqzc(a0, 1048575),
"d88fffff beqzc a0, 1048575", 1048575);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0), "f8800000 bnezc a0, 0x0", 0);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0xfffff), // 0x0fffff == 1048575.
"f88fffff bnezc a0, 0xfffff", 1048575);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0x100000), // 0x100000 == -1048576.
"f8900000 bnezc a0, 0x100000", -1048576);
COMPARE_PC_REL_COMPACT(bc(-33554432), "ca000000 bc -33554432",
-33554432);
COMPARE_PC_REL_COMPACT(bc(-1), "cbffffff bc -1", -1);
COMPARE_PC_REL_COMPACT(bc(0), "c8000000 bc 0", 0);
COMPARE_PC_REL_COMPACT(bc(1), "c8000001 bc 1", 1);
COMPARE_PC_REL_COMPACT(bc(33554431), "c9ffffff bc 33554431",
33554431);
COMPARE_PC_REL_COMPACT(balc(-33554432), "ea000000 balc -33554432",
-33554432);
COMPARE_PC_REL_COMPACT(balc(-1), "ebffffff balc -1", -1);
COMPARE_PC_REL_COMPACT(balc(0), "e8000000 balc 0", 0);
COMPARE_PC_REL_COMPACT(balc(1), "e8000001 balc 1", 1);
COMPARE_PC_REL_COMPACT(balc(33554431), "e9ffffff balc 33554431",
33554431);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -32768),
"18858000 bgeuc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -1),
"1885ffff bgeuc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 1),
"18850001 bgeuc a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 32767),
"18857fff bgeuc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgezalc(a0, -32768),
"18848000 bgezalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgezalc(a0, -1), "1884ffff bgezalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bgezalc(a0, 1), "18840001 bgezalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgezalc(a0, 32767),
"18847fff bgezalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(blezalc(a0, -32768),
"18048000 blezalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(blezalc(a0, -1), "1804ffff blezalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(blezalc(a0, 1), "18040001 blezalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(blezalc(a0, 32767),
"18047fff blezalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -32768),
"1c858000 bltuc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -1),
"1c85ffff bltuc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 1), "1c850001 bltuc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 32767),
"1c857fff bltuc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltzalc(a0, -32768),
"1c848000 bltzalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltzalc(a0, -1), "1c84ffff bltzalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bltzalc(a0, 1), "1c840001 bltzalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltzalc(a0, 32767),
"1c847fff bltzalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, -32768),
"1c048000 bgtzalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, -1), "1c04ffff bgtzalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, 1), "1c040001 bgtzalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, 32767),
"1c047fff bgtzalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgezc(a0, -32768),
"58848000 bgezc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgezc(a0, -1), "5884ffff bgezc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgezc(a0, 1), "58840001 bgezc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgezc(a0, 32767),
"58847fff bgezc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, -32768),
"58858000 bgec a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, -1),
"5885ffff bgec a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, 1), "58850001 bgec a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, 32767),
"58857fff bgec a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(blezc(a0, -32768),
"58048000 blezc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(blezc(a0, -1), "5804ffff blezc a0, -1", -1);
COMPARE_PC_REL_COMPACT(blezc(a0, 1), "58040001 blezc a0, 1", 1);
COMPARE_PC_REL_COMPACT(blezc(a0, 32767),
"58047fff blezc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltzc(a0, -32768),
"5c848000 bltzc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltzc(a0, -1), "5c84ffff bltzc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bltzc(a0, 1), "5c840001 bltzc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltzc(a0, 32767),
"5c847fff bltzc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, -32768),
"5c858000 bltc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, -1),
"5c85ffff bltc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, 1), "5c850001 bltc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, 32767),
"5c857fff bltc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgtzc(a0, -32768),
"5c048000 bgtzc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgtzc(a0, -1), "5c04ffff bgtzc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgtzc(a0, 1), "5c040001 bgtzc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtzc(a0, 32767),
"5c047fff bgtzc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bc1eqz(-32768, f1),
"45218000 bc1eqz f1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bc1eqz(-1, f1), "4521ffff bc1eqz f1, -1",
-1);
COMPARE_PC_REL_COMPACT(bc1eqz(1, f1), "45210001 bc1eqz f1, 1", 1);
COMPARE_PC_REL_COMPACT(bc1eqz(32767, f1),
"45217fff bc1eqz f1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bc1nez(-32768, f1),
"45a18000 bc1nez f1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bc1nez(-1, f1), "45a1ffff bc1nez f1, -1",
-1);
COMPARE_PC_REL_COMPACT(bc1nez(1, f1), "45a10001 bc1nez f1, 1", 1);
COMPARE_PC_REL_COMPACT(bc1nez(32767, f1),
"45a17fff bc1nez f1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, -1), "20a4ffff bovc a1, a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bovc(a0, a0, 1), "20840001 bovc a0, a0, 1",
1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, -32768),
"20858000 beqc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, -1), "2085ffff beqc a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, 1), "20850001 beqc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, 32767),
"20857fff beqc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, -32768),
"60858000 bnec a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, -1), "6085ffff bnec a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, 1), "60850001 bnec a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, 32767),
"60857fff bnec a0, a1, 32767", 32767);
}
COMPARE_PC_REL_COMPACT(bne(a0, a1, -32768),
"14858000 bne a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bne(a0, a1, -1), "1485ffff bne a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(bne(a0, a1, 1), "14850001 bne a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(bne(a0, a1, 32767),
"14857fff bne a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(beq(a0, a1, -32768),
"10858000 beq a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(beq(a0, a1, -1), "1085ffff beq a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(beq(a0, a1, 1), "10850001 beq a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(beq(a0, a1, 32767),
"10857fff beq a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltz(a0, -32768), "04808000 bltz a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bltz(a0, -1), "0480ffff bltz a0, -1", -1);
COMPARE_PC_REL_COMPACT(bltz(a0, 1), "04800001 bltz a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltz(a0, 32767), "04807fff bltz a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(bgez(a0, -32768), "04818000 bgez a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bgez(a0, -1), "0481ffff bgez a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgez(a0, 1), "04810001 bgez a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgez(a0, 32767), "04817fff bgez a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(blez(a0, -32768), "18808000 blez a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(blez(a0, -1), "1880ffff blez a0, -1", -1);
COMPARE_PC_REL_COMPACT(blez(a0, 1), "18800001 blez a0, 1", 1);
COMPARE_PC_REL_COMPACT(blez(a0, 32767), "18807fff blez a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(bgtz(a0, -32768), "1c808000 bgtz a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bgtz(a0, -1), "1c80ffff bgtz a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgtz(a0, 1), "1c800001 bgtz a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtz(a0, 32767), "1c807fff bgtz a0, 32767",
32767);
COMPARE_PC_JUMP(j(0x4), "08000001 j 0x4", 0x4);
COMPARE_PC_JUMP(j(0xffffffc), "0bffffff j 0xffffffc", 0xffffffc);
COMPARE_PC_JUMP(jal(0x4), "0c000001 jal 0x4", 0x4);
COMPARE_PC_JUMP(jal(0xffffffc), "0fffffff jal 0xffffffc",
0xffffffc);
COMPARE(addiu(a0, a1, 0x0),
"24a40000 addiu a0, a1, 0");
COMPARE(addiu(s0, s1, 32767),
......
......@@ -92,6 +92,45 @@ if (failure) { \
}
#define COMPARE_PC_REL_COMPACT(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, progcounter + 4 + (offset << 2)); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_REL(asm_, compare_string, offset) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, progcounter + (offset << 2)); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
#define COMPARE_PC_JUMP(asm_, compare_string, target) \
{ \
int pc_offset = assm.pc_offset(); \
byte *progcounter = &buffer[pc_offset]; \
char str_with_address[100]; \
int instr_index = target >> 2; \
snprintf(str_with_address, sizeof(str_with_address), "%s -> %p", \
compare_string, reinterpret_cast<byte *>( \
((uint64_t)(progcounter + 1) & ~0xfffffff) | \
(instr_index << 2))); \
assm.asm_; \
if (!DisassembleAndCompare(progcounter, str_with_address)) failure = true; \
}
TEST(Type0) {
SET_UP();
......@@ -279,50 +318,6 @@ TEST(Type0) {
"0064109f ddivu v0, v1, a0");
COMPARE(dmodu(v0, v1, a0),
"006410df dmodu v0, v1, a0");
COMPARE(bovc(a0, a0, static_cast<int16_t>(0)),
"20840000 bovc a0, a0, 0");
COMPARE(bovc(a1, a0, static_cast<int16_t>(0)),
"20a40000 bovc a1, a0, 0");
COMPARE(bovc(a1, a0, 32767),
"20a47fff bovc a1, a0, 32767");
COMPARE(bovc(a1, a0, -32768),
"20a48000 bovc a1, a0, -32768");
COMPARE(bnvc(a0, a0, static_cast<int16_t>(0)),
"60840000 bnvc a0, a0, 0");
COMPARE(bnvc(a1, a0, static_cast<int16_t>(0)),
"60a40000 bnvc a1, a0, 0");
COMPARE(bnvc(a1, a0, 32767),
"60a47fff bnvc a1, a0, 32767");
COMPARE(bnvc(a1, a0, -32768),
"60a48000 bnvc a1, a0, -32768");
COMPARE(beqzc(a0, 0),
"d8800000 beqzc a0, 0x0");
COMPARE(beqzc(a0, 0xfffff), // 0x0fffff == 1048575.
"d88fffff beqzc a0, 0xfffff");
COMPARE(beqzc(a0, 0x100000), // 0x100000 == -1048576.
"d8900000 beqzc a0, 0x100000");
COMPARE(bnezc(a0, 0),
"f8800000 bnezc a0, 0x0");
COMPARE(bnezc(a0, 0xfffff), // 0x0fffff == 1048575.
"f88fffff bnezc a0, 0xfffff");
COMPARE(bnezc(a0, 0x100000), // 0x100000 == -1048576.
"f8900000 bnezc a0, 0x100000");
COMPARE(bc(-33554432), "ca000000 bc -33554432");
COMPARE(bc(-1), "cbffffff bc -1");
COMPARE(bc(0), "c8000000 bc 0");
COMPARE(bc(1), "c8000001 bc 1");
COMPARE(bc(33554431), "c9ffffff bc 33554431");
COMPARE(balc(-33554432), "ea000000 balc -33554432");
COMPARE(balc(-1), "ebffffff balc -1");
COMPARE(balc(0), "e8000000 balc 0");
COMPARE(balc(1), "e8000001 balc 1");
COMPARE(balc(33554431), "e9ffffff balc 33554431");
}
COMPARE(addiu(a0, a1, 0x0),
......@@ -752,9 +747,11 @@ TEST(Type0) {
}
if (kArchVariant == kMips64r6) {
COMPARE(beqzc(a0, 16), "d8800010 beqzc a0, 0x10");
COMPARE(beqzc(a0, 4), "d8800004 beqzc a0, 0x4");
COMPARE(beqzc(a0, -32), "d89fffe0 beqzc a0, 0x1fffe0");
COMPARE_PC_REL_COMPACT(beqzc(a0, 16), "d8800010 beqzc a0, 0x10",
16);
COMPARE_PC_REL_COMPACT(beqzc(a0, 4), "d8800004 beqzc a0, 0x4", 4);
COMPARE_PC_REL_COMPACT(beqzc(a0, -32),
"d89fffe0 beqzc a0, 0x1fffe0", -32);
}
if (kArchVariant == kMips64r6) {
......@@ -887,6 +884,247 @@ TEST(Type2) {
}
TEST(Type3) {
SET_UP();
if (kArchVariant == kMips64r6) {
COMPARE_PC_REL_COMPACT(bovc(a0, a0, static_cast<int16_t>(0)),
"20840000 bovc a0, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, static_cast<int16_t>(0)),
"20a40000 bovc a1, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, 32767),
"20a47fff bovc a1, a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, -32768),
"20a48000 bovc a1, a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bnvc(a0, a0, static_cast<int16_t>(0)),
"60840000 bnvc a0, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, static_cast<int16_t>(0)),
"60a40000 bnvc a1, a0, 0", 0);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, 32767),
"60a47fff bnvc a1, a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bnvc(a1, a0, -32768),
"60a48000 bnvc a1, a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(beqzc(a0, 0), "d8800000 beqzc a0, 0x0", 0);
COMPARE_PC_REL_COMPACT(beqzc(a0, 0xfffff), // 0x0fffff == 1048575.
"d88fffff beqzc a0, 0xfffff", 1048575);
COMPARE_PC_REL_COMPACT(beqzc(a0, 0x100000), // 0x100000 == -1048576.
"d8900000 beqzc a0, 0x100000", -1048576);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0), "f8800000 bnezc a0, 0x0", 0);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0xfffff), // 0x0fffff == 1048575.
"f88fffff bnezc a0, 0xfffff", 1048575);
COMPARE_PC_REL_COMPACT(bnezc(a0, 0x100000), // 0x100000 == -1048576.
"f8900000 bnezc a0, 0x100000", -1048576);
COMPARE_PC_REL_COMPACT(bc(-33554432), "ca000000 bc -33554432",
-33554432);
COMPARE_PC_REL_COMPACT(bc(-1), "cbffffff bc -1", -1);
COMPARE_PC_REL_COMPACT(bc(0), "c8000000 bc 0", 0);
COMPARE_PC_REL_COMPACT(bc(1), "c8000001 bc 1", 1);
COMPARE_PC_REL_COMPACT(bc(33554431), "c9ffffff bc 33554431",
33554431);
COMPARE_PC_REL_COMPACT(balc(-33554432), "ea000000 balc -33554432",
-33554432);
COMPARE_PC_REL_COMPACT(balc(-1), "ebffffff balc -1", -1);
COMPARE_PC_REL_COMPACT(balc(0), "e8000000 balc 0", 0);
COMPARE_PC_REL_COMPACT(balc(1), "e8000001 balc 1", 1);
COMPARE_PC_REL_COMPACT(balc(33554431), "e9ffffff balc 33554431",
33554431);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -32768),
"18858000 bgeuc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, -1),
"1885ffff bgeuc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 1),
"18850001 bgeuc a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(bgeuc(a0, a1, 32767),
"18857fff bgeuc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgezalc(a0, -32768),
"18848000 bgezalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgezalc(a0, -1), "1884ffff bgezalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bgezalc(a0, 1), "18840001 bgezalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgezalc(a0, 32767),
"18847fff bgezalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(blezalc(a0, -32768),
"18048000 blezalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(blezalc(a0, -1), "1804ffff blezalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(blezalc(a0, 1), "18040001 blezalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(blezalc(a0, 32767),
"18047fff blezalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -32768),
"1c858000 bltuc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, -1),
"1c85ffff bltuc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 1), "1c850001 bltuc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bltuc(a0, a1, 32767),
"1c857fff bltuc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltzalc(a0, -32768),
"1c848000 bltzalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltzalc(a0, -1), "1c84ffff bltzalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bltzalc(a0, 1), "1c840001 bltzalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltzalc(a0, 32767),
"1c847fff bltzalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, -32768),
"1c048000 bgtzalc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, -1), "1c04ffff bgtzalc a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, 1), "1c040001 bgtzalc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtzalc(a0, 32767),
"1c047fff bgtzalc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgezc(a0, -32768),
"58848000 bgezc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgezc(a0, -1), "5884ffff bgezc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgezc(a0, 1), "58840001 bgezc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgezc(a0, 32767),
"58847fff bgezc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, -32768),
"58858000 bgec a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, -1),
"5885ffff bgec a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, 1), "58850001 bgec a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bgec(a0, a1, 32767),
"58857fff bgec a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(blezc(a0, -32768),
"58048000 blezc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(blezc(a0, -1), "5804ffff blezc a0, -1", -1);
COMPARE_PC_REL_COMPACT(blezc(a0, 1), "58040001 blezc a0, 1", 1);
COMPARE_PC_REL_COMPACT(blezc(a0, 32767),
"58047fff blezc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltzc(a0, -32768),
"5c848000 bltzc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltzc(a0, -1), "5c84ffff bltzc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bltzc(a0, 1), "5c840001 bltzc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltzc(a0, 32767),
"5c847fff bltzc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, -32768),
"5c858000 bltc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, -1),
"5c85ffff bltc a0, a1, -1", -1);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, 1), "5c850001 bltc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bltc(a0, a1, 32767),
"5c857fff bltc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bgtzc(a0, -32768),
"5c048000 bgtzc a0, -32768", -32768);
COMPARE_PC_REL_COMPACT(bgtzc(a0, -1), "5c04ffff bgtzc a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgtzc(a0, 1), "5c040001 bgtzc a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtzc(a0, 32767),
"5c047fff bgtzc a0, 32767", 32767);
COMPARE_PC_REL_COMPACT(bc1eqz(-32768, f1),
"45218000 bc1eqz f1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bc1eqz(-1, f1), "4521ffff bc1eqz f1, -1",
-1);
COMPARE_PC_REL_COMPACT(bc1eqz(1, f1), "45210001 bc1eqz f1, 1", 1);
COMPARE_PC_REL_COMPACT(bc1eqz(32767, f1),
"45217fff bc1eqz f1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bc1nez(-32768, f1),
"45a18000 bc1nez f1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bc1nez(-1, f1), "45a1ffff bc1nez f1, -1",
-1);
COMPARE_PC_REL_COMPACT(bc1nez(1, f1), "45a10001 bc1nez f1, 1", 1);
COMPARE_PC_REL_COMPACT(bc1nez(32767, f1),
"45a17fff bc1nez f1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bovc(a1, a0, -1), "20a4ffff bovc a1, a0, -1",
-1);
COMPARE_PC_REL_COMPACT(bovc(a0, a0, 1), "20840001 bovc a0, a0, 1",
1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, -32768),
"20858000 beqc a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, -1), "2085ffff beqc a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, 1), "20850001 beqc a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(beqc(a0, a1, 32767),
"20857fff beqc a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, -32768),
"60858000 bnec a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, -1), "6085ffff bnec a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, 1), "60850001 bnec a0, a1, 1",
1);
COMPARE_PC_REL_COMPACT(bnec(a0, a1, 32767),
"60857fff bnec a0, a1, 32767", 32767);
}
COMPARE_PC_REL_COMPACT(bne(a0, a1, -32768),
"14858000 bne a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(bne(a0, a1, -1), "1485ffff bne a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(bne(a0, a1, 1), "14850001 bne a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(bne(a0, a1, 32767),
"14857fff bne a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(beq(a0, a1, -32768),
"10858000 beq a0, a1, -32768", -32768);
COMPARE_PC_REL_COMPACT(beq(a0, a1, -1), "1085ffff beq a0, a1, -1",
-1);
COMPARE_PC_REL_COMPACT(beq(a0, a1, 1), "10850001 beq a0, a1, 1", 1);
COMPARE_PC_REL_COMPACT(beq(a0, a1, 32767),
"10857fff beq a0, a1, 32767", 32767);
COMPARE_PC_REL_COMPACT(bltz(a0, -32768), "04808000 bltz a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bltz(a0, -1), "0480ffff bltz a0, -1", -1);
COMPARE_PC_REL_COMPACT(bltz(a0, 1), "04800001 bltz a0, 1", 1);
COMPARE_PC_REL_COMPACT(bltz(a0, 32767), "04807fff bltz a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(bgez(a0, -32768), "04818000 bgez a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bgez(a0, -1), "0481ffff bgez a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgez(a0, 1), "04810001 bgez a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgez(a0, 32767), "04817fff bgez a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(blez(a0, -32768), "18808000 blez a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(blez(a0, -1), "1880ffff blez a0, -1", -1);
COMPARE_PC_REL_COMPACT(blez(a0, 1), "18800001 blez a0, 1", 1);
COMPARE_PC_REL_COMPACT(blez(a0, 32767), "18807fff blez a0, 32767",
32767);
COMPARE_PC_REL_COMPACT(bgtz(a0, -32768), "1c808000 bgtz a0, -32768",
-32768);
COMPARE_PC_REL_COMPACT(bgtz(a0, -1), "1c80ffff bgtz a0, -1", -1);
COMPARE_PC_REL_COMPACT(bgtz(a0, 1), "1c800001 bgtz a0, 1", 1);
COMPARE_PC_REL_COMPACT(bgtz(a0, 32767), "1c807fff bgtz a0, 32767",
32767);
COMPARE_PC_JUMP(j(0x4), "08000001 j 0x4", 0x4);
COMPARE_PC_JUMP(j(0xffffffc), "0bffffff j 0xffffffc", 0xffffffc);
COMPARE_PC_JUMP(jal(0x4), "0c000001 jal 0x4", 0x4);
COMPARE_PC_JUMP(jal(0xffffffc), "0fffffff jal 0xffffffc",
0xffffffc);
VERIFY_RUN();
}
TEST(C_FMT_DISASM) {
if (kArchVariant == kMips64r2) {
SET_UP();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment