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) {
}
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
// 'lui' has zero reg. for rs field.
DCHECK(!(rs.is(zero_reg)));
......
......@@ -1530,7 +1530,7 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "lui 'rt, 'imm16x");
} else {
if (instr->RsValue() != 0) {
Format(instr, "aui 'rt, 'imm16x");
Format(instr, "aui 'rt, 'rs, 'imm16x");
} else {
Format(instr, "lui 'rt, 'imm16x");
}
......
......@@ -4044,7 +4044,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
SetResult(rt_reg, rs ^ oe_imm16);
break;
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;
// ------------- Memory instructions.
case LB:
......
......@@ -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
// 'lui' has zero reg. for rs field.
DCHECK(!(rs.is(zero_reg)));
DCHECK(is_uint16(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(!rs.is(zero_reg));
GenInstrImmediate(DAUI, rs, rt, j);
}
......
......@@ -741,8 +741,8 @@ class Assembler : public AssemblerBase {
void ori(Register rd, Register rs, int32_t j);
void xori(Register rd, Register rs, int32_t j);
void lui(Register rd, int32_t j);
void aui(Register rs, Register rt, int32_t j);
void daui(Register rs, Register rt, int32_t j);
void aui(Register rt, Register rs, int32_t j);
void daui(Register rt, Register rs, int32_t j);
void dahi(Register rs, int32_t j);
void dati(Register rs, int32_t j);
......
......@@ -927,7 +927,7 @@ class Instruction {
OpcodeToBitNumber(SWR) | OpcodeToBitNumber(LWC1) |
OpcodeToBitNumber(LDC1) | OpcodeToBitNumber(SWC1) |
OpcodeToBitNumber(SDC1) | OpcodeToBitNumber(PCREL) |
OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
OpcodeToBitNumber(DAUI) | OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
#define FunctionFieldToBitNumber(function) (1ULL << function)
......
......@@ -1567,10 +1567,10 @@ void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) {
Format(instr, "bgezall 'rs, 'imm16u -> 'imm16p4s2");
break;
case DAHI:
Format(instr, "dahi 'rs, 'imm16u");
Format(instr, "dahi 'rs, 'imm16x");
break;
case DATI:
Format(instr, "dati 'rs, 'imm16u");
Format(instr, "dati 'rs, 'imm16x");
break;
default:
UNREACHABLE();
......@@ -1723,14 +1723,14 @@ void Decoder::DecodeTypeImmediate(Instruction* instr) {
Format(instr, "lui 'rt, 'imm16x");
} else {
if (instr->RsValue() != 0) {
Format(instr, "aui 'rt, 'imm16x");
Format(instr, "aui 'rt, 'rs, 'imm16x");
} else {
Format(instr, "lui 'rt, 'imm16x");
}
}
break;
case DAUI:
Format(instr, "daui 'rt, 'imm16x");
Format(instr, "daui 'rt, 'rs, 'imm16x");
break;
// ------------- Memory instructions.
case LB:
......
......@@ -4025,6 +4025,12 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case BGEZAL:
BranchAndLinkHelper(rs >= 0);
break;
case DAHI:
SetResult(rs_reg, rs + (se_imm16 << 32));
break;
case DATI:
SetResult(rs_reg, rs + (se_imm16 << 48));
break;
default:
UNREACHABLE();
}
......@@ -4111,12 +4117,24 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case XORI:
SetResult(rt_reg, rs ^ oe_imm16);
break;
case LUI: {
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));
case LUI:
if (rs_reg != 0) {
// AUI instruction.
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;
}
// ------------- Memory instructions.
case LB:
set_register(rt_reg, ReadB(rs + se_imm16));
......
......@@ -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) {
if (IsMipsArchVariant(kMips32r6)) {
CcTest::InitializeVM();
......
......@@ -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) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
......
......@@ -568,6 +568,11 @@ TEST(Type0) {
COMPARE(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),
"00052000 sll a0, a1, 0");
COMPARE(sll(s0, s1, 8),
......
......@@ -405,6 +405,20 @@ TEST(Type0) {
COMPARE(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),
"00052000 sll a0, a1, 0");
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