Commit cfd9beec authored by alan.li's avatar alan.li Committed by Commit bot

MIPS: Adding simulator support for AUI/DAUI/DAHI/DATI.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#32417}
parent 44d4131c
...@@ -1819,7 +1819,7 @@ void Assembler::lui(Register rd, int32_t j) { ...@@ -1819,7 +1819,7 @@ void Assembler::lui(Register rd, int32_t j) {
} }
void Assembler::aui(Register rs, Register rt, int32_t j) { void Assembler::aui(Register rt, Register rs, int32_t j) {
// This instruction uses same opcode as 'lui'. The difference in encoding is // This instruction uses same opcode as 'lui'. The difference in encoding is
// 'lui' has zero reg. for rs field. // 'lui' has zero reg. for rs field.
DCHECK(!(rs.is(zero_reg))); DCHECK(!(rs.is(zero_reg)));
......
...@@ -1530,7 +1530,7 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { ...@@ -1530,7 +1530,7 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "lui 'rt, 'imm16x"); Format(instr, "lui 'rt, 'imm16x");
} else { } else {
if (instr->RsValue() != 0) { if (instr->RsValue() != 0) {
Format(instr, "aui 'rt, 'imm16x"); Format(instr, "aui 'rt, 'rs, 'imm16x");
} else { } else {
Format(instr, "lui 'rt, 'imm16x"); Format(instr, "lui 'rt, 'imm16x");
} }
......
...@@ -4044,7 +4044,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { ...@@ -4044,7 +4044,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
SetResult(rt_reg, rs ^ oe_imm16); SetResult(rt_reg, rs ^ oe_imm16);
break; break;
case LUI: case LUI:
SetResult(rt_reg, oe_imm16 << 16); if (rs_reg != 0) {
// AUI
DCHECK(IsMipsArchVariant(kMips32r6));
SetResult(rt_reg, rs + (se_imm16 << 16));
} else {
// LUI
SetResult(rt_reg, oe_imm16 << 16);
}
break; break;
// ------------- Memory instructions. // ------------- Memory instructions.
case LB: case LB:
......
...@@ -1955,17 +1955,17 @@ void Assembler::lui(Register rd, int32_t j) { ...@@ -1955,17 +1955,17 @@ void Assembler::lui(Register rd, int32_t j) {
} }
void Assembler::aui(Register rs, Register rt, int32_t j) { void Assembler::aui(Register rt, Register rs, int32_t j) {
// This instruction uses same opcode as 'lui'. The difference in encoding is // This instruction uses same opcode as 'lui'. The difference in encoding is
// 'lui' has zero reg. for rs field. // 'lui' has zero reg. for rs field.
DCHECK(!(rs.is(zero_reg)));
DCHECK(is_uint16(j)); DCHECK(is_uint16(j));
GenInstrImmediate(LUI, rs, rt, j); GenInstrImmediate(LUI, rs, rt, j);
} }
void Assembler::daui(Register rs, Register rt, int32_t j) { void Assembler::daui(Register rt, Register rs, int32_t j) {
DCHECK(is_uint16(j)); DCHECK(is_uint16(j));
DCHECK(!rs.is(zero_reg));
GenInstrImmediate(DAUI, rs, rt, j); GenInstrImmediate(DAUI, rs, rt, j);
} }
......
...@@ -741,8 +741,8 @@ class Assembler : public AssemblerBase { ...@@ -741,8 +741,8 @@ class Assembler : public AssemblerBase {
void ori(Register rd, Register rs, int32_t j); void ori(Register rd, Register rs, int32_t j);
void xori(Register rd, Register rs, int32_t j); void xori(Register rd, Register rs, int32_t j);
void lui(Register rd, int32_t j); void lui(Register rd, int32_t j);
void aui(Register rs, Register rt, int32_t j); void aui(Register rt, Register rs, int32_t j);
void daui(Register rs, Register rt, int32_t j); void daui(Register rt, Register rs, int32_t j);
void dahi(Register rs, int32_t j); void dahi(Register rs, int32_t j);
void dati(Register rs, int32_t j); void dati(Register rs, int32_t j);
......
...@@ -927,7 +927,7 @@ class Instruction { ...@@ -927,7 +927,7 @@ class Instruction {
OpcodeToBitNumber(SWR) | OpcodeToBitNumber(LWC1) | OpcodeToBitNumber(SWR) | OpcodeToBitNumber(LWC1) |
OpcodeToBitNumber(LDC1) | OpcodeToBitNumber(SWC1) | OpcodeToBitNumber(LDC1) | OpcodeToBitNumber(SWC1) |
OpcodeToBitNumber(SDC1) | OpcodeToBitNumber(PCREL) | OpcodeToBitNumber(SDC1) | OpcodeToBitNumber(PCREL) |
OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC); OpcodeToBitNumber(DAUI) | OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
#define FunctionFieldToBitNumber(function) (1ULL << function) #define FunctionFieldToBitNumber(function) (1ULL << function)
......
...@@ -1567,10 +1567,10 @@ void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) { ...@@ -1567,10 +1567,10 @@ void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2"); Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
break; break;
case DAHI: case DAHI:
Format(instr, "dahi 'rs, 'imm16u"); Format(instr, "dahi 'rs, 'imm16x");
break; break;
case DATI: case DATI:
Format(instr, "dati 'rs, 'imm16u"); Format(instr, "dati 'rs, 'imm16x");
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -1723,14 +1723,14 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) { ...@@ -1723,14 +1723,14 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "lui 'rt, 'imm16x"); Format(instr, "lui 'rt, 'imm16x");
} else { } else {
if (instr->RsValue() != 0) { if (instr->RsValue() != 0) {
Format(instr, "aui 'rt, 'imm16x"); Format(instr, "aui 'rt, 'rs, 'imm16x");
} else { } else {
Format(instr, "lui 'rt, 'imm16x"); Format(instr, "lui 'rt, 'imm16x");
} }
} }
break; break;
case DAUI: case DAUI:
Format(instr, "daui 'rt, 'imm16x"); Format(instr, "daui 'rt, 'rs, 'imm16x");
break; break;
// ------------- Memory instructions. // ------------- Memory instructions.
case LB: case LB:
......
...@@ -4025,6 +4025,12 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { ...@@ -4025,6 +4025,12 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case BGEZAL: case BGEZAL:
BranchAndLinkHelper(rs >= 0); BranchAndLinkHelper(rs >= 0);
break; break;
case DAHI:
SetResult(rs_reg, rs + (se_imm16 << 32));
break;
case DATI:
SetResult(rs_reg, rs + (se_imm16 << 48));
break;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -4111,12 +4117,24 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { ...@@ -4111,12 +4117,24 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case XORI: case XORI:
SetResult(rt_reg, rs ^ oe_imm16); SetResult(rt_reg, rs ^ oe_imm16);
break; break;
case LUI: { case LUI:
int32_t alu32_out = static_cast<int32_t>(oe_imm16 << 16); if (rs_reg != 0) {
// Sign-extend result of 32bit operation into 64bit register. // AUI instruction.
SetResult(rt_reg, static_cast<int64_t>(alu32_out)); DCHECK(kArchVariant == kMips64r6);
int32_t alu32_out = static_cast<int32_t>(rs + (se_imm16 << 16));
SetResult(rt_reg, static_cast<int64_t>(alu32_out));
} else {
// LUI instruction.
int32_t alu32_out = static_cast<int32_t>(oe_imm16 << 16);
// Sign-extend result of 32bit operation into 64bit register.
SetResult(rt_reg, static_cast<int64_t>(alu32_out));
}
break;
case DAUI:
DCHECK(kArchVariant == kMips64r6);
DCHECK(rs_reg != 0);
SetResult(rt_reg, rs + (se_imm16 << 16));
break; break;
}
// ------------- Memory instructions. // ------------- Memory instructions.
case LB: case LB:
set_register(rt_reg, ReadB(rs + se_imm16)); set_register(rt_reg, ReadB(rs + se_imm16));
......
...@@ -5059,6 +5059,64 @@ int32_t run_balc(int32_t offset) { ...@@ -5059,6 +5059,64 @@ int32_t run_balc(int32_t offset) {
} }
uint32_t run_aui(uint32_t rs, uint16_t offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(t0, rs);
__ aui(v0, t0, offset);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint32_t res =
reinterpret_cast<uint32_t>
(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
TEST(r6_aui) {
if (IsMipsArchVariant(kMips32r6)) {
CcTest::InitializeVM();
struct TestCaseAui {
uint32_t rs;
uint16_t offset;
uint32_t ref_res;
};
struct TestCaseAui tc[] = {
// input, offset, result
{0xfffeffff, 1, 0xffffffff},
{0xffffffff, 0, 0xffffffff},
{0, 0xffff, 0xffff0000},
{0x0008ffff, 0xfff7, 0xffffffff},
{32767, 32767, 0x7fff7fff},
// overflow cases
{0xffffffff, 0x1, 0x0000ffff},
{0xffffffff, 0xffff, 0xfffeffff},
};
size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAui);
for (size_t i = 0; i < nr_test_cases; ++i) {
PC = 0;
uint32_t res = run_aui(tc[i].rs, tc[i].offset);
CHECK_EQ(tc[i].ref_res, res);
}
}
}
TEST(r6_balc) { TEST(r6_balc) {
if (IsMipsArchVariant(kMips32r6)) { if (IsMipsArchVariant(kMips32r6)) {
CcTest::InitializeVM(); CcTest::InitializeVM();
......
...@@ -4717,6 +4717,187 @@ TEST(r6_auipc) { ...@@ -4717,6 +4717,187 @@ TEST(r6_auipc) {
} }
uint64_t run_aui(uint64_t rs, uint16_t offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(t0, rs);
__ aui(v0, t0, offset);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint64_t res =
reinterpret_cast<uint64_t>
(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
uint64_t run_daui(uint64_t rs, uint16_t offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(t0, rs);
__ daui(v0, t0, offset);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint64_t res =
reinterpret_cast<uint64_t>
(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
uint64_t run_dahi(uint64_t rs, uint16_t offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(v0, rs);
__ dahi(v0, offset);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint64_t res =
reinterpret_cast<uint64_t>
(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
uint64_t run_dati(uint64_t rs, uint16_t offset) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
__ li(v0, rs);
__ dati(v0, offset);
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(&desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
F2 f = FUNCTION_CAST<F2>(code->entry());
uint64_t res =
reinterpret_cast<uint64_t>
(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
return res;
}
TEST(r6_aui_family) {
if (kArchVariant == kMips64r6) {
CcTest::InitializeVM();
struct TestCaseAui {
uint64_t rs;
uint16_t offset;
uint64_t ref_res;
};
// AUI test cases.
struct TestCaseAui aui_tc[] = {
{0xfffeffff, 0x1, 0xffffffffffffffff},
{0xffffffff, 0x0, 0xffffffffffffffff},
{0, 0xffff, 0xffffffffffff0000},
{0x0008ffff, 0xfff7, 0xffffffffffffffff},
{32767, 32767, 0x000000007fff7fff},
{0x00000000ffffffff, 0x1, 0x000000000000ffff},
{0xffffffff, 0xffff, 0xfffffffffffeffff},
};
size_t nr_test_cases = sizeof(aui_tc) / sizeof(TestCaseAui);
for (size_t i = 0; i < nr_test_cases; ++i) {
uint64_t res = run_aui(aui_tc[i].rs, aui_tc[i].offset);
CHECK_EQ(aui_tc[i].ref_res, res);
}
// DAUI test cases.
struct TestCaseAui daui_tc[] = {
{0xfffffffffffeffff, 0x1, 0xffffffffffffffff},
{0xffffffffffffffff, 0x0, 0xffffffffffffffff},
{0, 0xffff, 0xffffffffffff0000},
{0x0008ffff, 0xfff7, 0xffffffffffffffff},
{32767, 32767, 0x000000007fff7fff},
{0x00000000ffffffff, 0x1, 0x000000010000ffff},
{0xffffffff, 0xffff, 0x00000000fffeffff},
};
nr_test_cases = sizeof(daui_tc) / sizeof(TestCaseAui);
for (size_t i = 0; i < nr_test_cases; ++i) {
uint64_t res = run_daui(daui_tc[i].rs, daui_tc[i].offset);
CHECK_EQ(daui_tc[i].ref_res, res);
}
// DATI test cases.
struct TestCaseAui dati_tc[] = {
{0xfffffffffffeffff, 0x1, 0x0000fffffffeffff},
{0xffffffffffffffff, 0x0, 0xffffffffffffffff},
{0, 0xffff, 0xffff000000000000},
{0x0008ffff, 0xfff7, 0xfff700000008ffff},
{32767, 32767, 0x7fff000000007fff},
{0x00000000ffffffff, 0x1, 0x00010000ffffffff},
{0xffffffffffff, 0xffff, 0xffffffffffffffff},
};
nr_test_cases = sizeof(dati_tc) / sizeof(TestCaseAui);
for (size_t i = 0; i < nr_test_cases; ++i) {
uint64_t res = run_dati(dati_tc[i].rs, dati_tc[i].offset);
CHECK_EQ(dati_tc[i].ref_res, res);
}
// DAHI test cases.
struct TestCaseAui dahi_tc[] = {
{0xfffffffeffffffff, 0x1, 0xffffffffffffffff},
{0xffffffffffffffff, 0x0, 0xffffffffffffffff},
{0, 0xffff, 0xffffffff00000000},
};
nr_test_cases = sizeof(dahi_tc) / sizeof(TestCaseAui);
for (size_t i = 0; i < nr_test_cases; ++i) {
uint64_t res = run_dahi(dahi_tc[i].rs, dahi_tc[i].offset);
CHECK_EQ(dahi_tc[i].ref_res, res);
}
}
}
uint64_t run_lwpc(int offset) { uint64_t run_lwpc(int offset) {
Isolate* isolate = CcTest::i_isolate(); Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate); HandleScope scope(isolate);
......
...@@ -568,6 +568,11 @@ TEST(Type0) { ...@@ -568,6 +568,11 @@ TEST(Type0) {
COMPARE(lui(v0, 0xffff), COMPARE(lui(v0, 0xffff),
"3c02ffff lui v0, 0xffff"); "3c02ffff lui v0, 0xffff");
if (IsMipsArchVariant(kMips32r6)) {
COMPARE(aui(a0, a1, 0x1), "3ca40001 aui a0, a1, 0x1");
COMPARE(aui(v0, v1, 0xffff), "3c62ffff aui v0, v1, 0xffff");
}
COMPARE(sll(a0, a1, 0), COMPARE(sll(a0, a1, 0),
"00052000 sll a0, a1, 0"); "00052000 sll a0, a1, 0");
COMPARE(sll(s0, s1, 8), COMPARE(sll(s0, s1, 8),
......
...@@ -405,6 +405,20 @@ TEST(Type0) { ...@@ -405,6 +405,20 @@ TEST(Type0) {
COMPARE(lui(v0, 0xffff), COMPARE(lui(v0, 0xffff),
"3c02ffff lui v0, 0xffff"); "3c02ffff lui v0, 0xffff");
if (kArchVariant == (kMips64r6)) {
COMPARE(aui(a0, a1, 0x1), "3ca40001 aui a0, a1, 0x1");
COMPARE(aui(v0, v1, 0xffff), "3c62ffff aui v0, v1, 0xffff");
COMPARE(daui(a0, a1, 0x1), "74a40001 daui a0, a1, 0x1");
COMPARE(daui(v0, v1, 0xffff), "7462ffff daui v0, v1, 0xffff");
COMPARE(dahi(a0, 0x1), "04860001 dahi a0, 0x1");
COMPARE(dahi(v0, 0xffff), "0446ffff dahi v0, 0xffff");
COMPARE(dati(a0, 0x1), "049e0001 dati a0, 0x1");
COMPARE(dati(v0, 0xffff), "045effff dati v0, 0xffff");
}
COMPARE(sll(a0, a1, 0), COMPARE(sll(a0, a1, 0),
"00052000 sll a0, a1, 0"); "00052000 sll a0, a1, 0");
COMPARE(sll(s0, s1, 8), COMPARE(sll(s0, s1, 8),
......
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