Commit c16a39f2 authored by Dusan Simicic's avatar Dusan Simicic Committed by Commit Bot

MIPS[64]: Implement vector MSA instructions in simulator

Add support for and.v, or.v, nor.v, xor.v, bmnz.v, bmz.v, bsel.v MSA
instructions in mips32 and mips64 simulator.

Bug: 
Change-Id: Idf092a1c211959a096694485268fff379b612b77
Reviewed-on: https://chromium-review.googlesource.com/533075
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Cr-Commit-Position: refs/heads/master@{#46474}
parent 08688b39
......@@ -4753,19 +4753,43 @@ void Simulator::DecodeTypeMsaVec() {
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
switch (opcode) {
case AND_V:
case OR_V:
case NOR_V:
case XOR_V:
case BMNZ_V:
case BMZ_V:
case BSEL_V:
UNIMPLEMENTED();
break;
default:
UNREACHABLE();
msa_reg_t wd, ws, wt;
get_msa_register(instr_.WsValue(), ws.w);
get_msa_register(instr_.WtValue(), wt.w);
if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
get_msa_register(instr_.WdValue(), wd.w);
}
for (int i = 0; i < kMSALanesWord; i++) {
switch (opcode) {
case AND_V:
wd.w[i] = ws.w[i] & wt.w[i];
break;
case OR_V:
wd.w[i] = ws.w[i] | wt.w[i];
break;
case NOR_V:
wd.w[i] = ~(ws.w[i] | wt.w[i]);
break;
case XOR_V:
wd.w[i] = ws.w[i] ^ wt.w[i];
break;
case BMNZ_V:
wd.w[i] = (wt.w[i] & ws.w[i]) | (~wt.w[i] & wd.w[i]);
break;
case BMZ_V:
wd.w[i] = (~wt.w[i] & ws.w[i]) | (wt.w[i] & wd.w[i]);
break;
case BSEL_V:
wd.w[i] = (~wd.w[i] & ws.w[i]) | (wd.w[i] & wt.w[i]);
break;
default:
UNREACHABLE();
}
}
set_msa_register(instr_.WdValue(), wd.w);
TraceMSARegWr(wd.d);
}
void Simulator::DecodeTypeMsa2R() {
......
......@@ -4978,19 +4978,43 @@ void Simulator::DecodeTypeMsaVec() {
DCHECK(kArchVariant == kMips64r6);
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
uint32_t opcode = instr_.InstructionBits() & kMsaVECMask;
switch (opcode) {
case AND_V:
case OR_V:
case NOR_V:
case XOR_V:
case BMNZ_V:
case BMZ_V:
case BSEL_V:
UNIMPLEMENTED();
break;
default:
UNREACHABLE();
msa_reg_t wd, ws, wt;
get_msa_register(instr_.WsValue(), ws.d);
get_msa_register(instr_.WtValue(), wt.d);
if (opcode == BMNZ_V || opcode == BMZ_V || opcode == BSEL_V) {
get_msa_register(instr_.WdValue(), wd.d);
}
for (int i = 0; i < kMSALanesDword; i++) {
switch (opcode) {
case AND_V:
wd.d[i] = ws.d[i] & wt.d[i];
break;
case OR_V:
wd.d[i] = ws.d[i] | wt.d[i];
break;
case NOR_V:
wd.d[i] = ~(ws.d[i] | wt.d[i]);
break;
case XOR_V:
wd.d[i] = ws.d[i] ^ wt.d[i];
break;
case BMNZ_V:
wd.d[i] = (wt.d[i] & ws.d[i]) | (~wt.d[i] & wd.d[i]);
break;
case BMZ_V:
wd.d[i] = (~wt.d[i] & ws.d[i]) | (wt.d[i] & wd.d[i]);
break;
case BSEL_V:
wd.d[i] = (~wd.d[i] & ws.d[i]) | (wd.d[i] & wt.d[i]);
break;
default:
UNREACHABLE();
}
}
set_msa_register(instr_.WdValue(), wd.d);
TraceMSARegWr(wd.d);
}
void Simulator::DecodeTypeMsa2R() {
......
......@@ -6888,4 +6888,113 @@ TEST(MSA_nloc) {
}
}
struct TestCaseMsaVector {
uint64_t wd_lo;
uint64_t wd_hi;
uint64_t ws_lo;
uint64_t ws_hi;
uint64_t wt_lo;
uint64_t wt_hi;
};
template <typename InstFunc, typename OperFunc>
void run_msa_vector(struct TestCaseMsaVector* input,
InstFunc GenerateVectorInstructionFunc,
OperFunc GenerateOperationFunc) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
CpuFeatureScope fscope(&assm, MIPS_SIMD);
msa_reg_t res;
#define LOAD_W_REG(lo, hi, w_reg) \
__ li(t0, static_cast<uint32_t>(lo & 0xffffffff)); \
__ li(t1, static_cast<uint32_t>((lo >> 32) & 0xffffffff)); \
__ insert_w(w_reg, 0, t0); \
__ insert_w(w_reg, 1, t1); \
__ li(t0, static_cast<uint32_t>(hi & 0xffffffff)); \
__ li(t1, static_cast<uint32_t>((hi >> 32) & 0xffffffff)); \
__ insert_w(w_reg, 2, t0); \
__ insert_w(w_reg, 3, t1)
LOAD_W_REG(input->ws_lo, input->ws_hi, w0);
LOAD_W_REG(input->wt_lo, input->wt_hi, w2);
LOAD_W_REG(input->wd_lo, input->wd_hi, w4);
#undef LOAD_W_REG
GenerateVectorInstructionFunc(assm);
__ copy_u_w(t2, w4, 0);
__ sw(t2, MemOperand(a0, 0));
__ copy_u_w(t2, w4, 1);
__ sw(t2, MemOperand(a0, 4));
__ copy_u_w(t2, w4, 2);
__ sw(t2, MemOperand(a0, 8));
__ copy_u_w(t2, w4, 3);
__ sw(t2, MemOperand(a0, 12));
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(isolate, &desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
code->Print(std::cout);
#endif
F3 f = FUNCTION_CAST<F3>(code->entry());
(CALL_GENERATED_CODE(isolate, f, &res, 0, 0, 0, 0));
CHECK_EQ(GenerateOperationFunc(input->wd_lo, input->ws_lo, input->wt_lo),
res.d[0]);
CHECK_EQ(GenerateOperationFunc(input->wd_hi, input->ws_hi, input->wt_hi),
res.d[1]);
}
TEST(MSA_vector) {
if (!IsMipsArchVariant(kMips32r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
return;
CcTest::InitializeVM();
struct TestCaseMsaVector tc[] = {
// wd_lo, wd_hi, ws_lo, ws_hi, wt_lo, wt_hi
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0xdcd39d91f9057627,
0x64be4f6dbe9caa51, 0x6b23de1a687d9cb9, 0x49547aad691da4ca},
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0x401614523d830549,
0xd7c46d613f50eddd, 0x52284cbc60a1562b, 0x1756ed510d8849cd},
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0xd6e2d2ebcb40d72f,
0x13a619afce67b079, 0x36cce284343e40f9, 0xb4e8f44fd148bf7f}};
for (size_t i = 0; i < sizeof(tc) / sizeof(TestCaseMsaVector); ++i) {
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ and_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws & wt; });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ or_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws | wt; });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ nor_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ~(ws | wt); });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ xor_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws ^ wt; });
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bmnz_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & wt) | (wd & ~wt);
});
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bmz_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & ~wt) | (wd & wt);
});
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bsel_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & ~wd) | (wt & wd);
});
}
}
#undef __
......@@ -7757,4 +7757,109 @@ TEST(MSA_nloc) {
}
}
struct TestCaseMsaVector {
uint64_t wd_lo;
uint64_t wd_hi;
uint64_t ws_lo;
uint64_t ws_hi;
uint64_t wt_lo;
uint64_t wt_hi;
};
template <typename InstFunc, typename OperFunc>
void run_msa_vector(struct TestCaseMsaVector* input,
InstFunc GenerateVectorInstructionFunc,
OperFunc GenerateOperationFunc) {
Isolate* isolate = CcTest::i_isolate();
HandleScope scope(isolate);
MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes);
CpuFeatureScope fscope(&assm, MIPS_SIMD);
msa_reg_t res;
#define LOAD_W_REG(lo, hi, w_reg) \
__ li(t0, lo); \
__ li(t1, hi); \
__ insert_d(w_reg, 0, t0); \
__ insert_d(w_reg, 1, t1)
LOAD_W_REG(input->ws_lo, input->ws_hi, w0);
LOAD_W_REG(input->wt_lo, input->wt_hi, w2);
LOAD_W_REG(input->wd_lo, input->wd_hi, w4);
#undef LOAD_W_REG
GenerateVectorInstructionFunc(assm);
__ copy_u_w(t2, w4, 0);
__ sw(t2, MemOperand(a0, 0));
__ copy_u_w(t2, w4, 1);
__ sw(t2, MemOperand(a0, 4));
__ copy_u_w(t2, w4, 2);
__ sw(t2, MemOperand(a0, 8));
__ copy_u_w(t2, w4, 3);
__ sw(t2, MemOperand(a0, 12));
__ jr(ra);
__ nop();
CodeDesc desc;
assm.GetCode(isolate, &desc);
Handle<Code> code = isolate->factory()->NewCode(
desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
#ifdef OBJECT_PRINT
code->Print(std::cout);
#endif
F3 f = FUNCTION_CAST<F3>(code->entry());
(CALL_GENERATED_CODE(isolate, f, &res, 0, 0, 0, 0));
CHECK_EQ(GenerateOperationFunc(input->wd_lo, input->ws_lo, input->wt_lo),
res.d[0]);
CHECK_EQ(GenerateOperationFunc(input->wd_hi, input->ws_hi, input->wt_hi),
res.d[1]);
}
TEST(MSA_vector) {
if ((kArchVariant != kMips64r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
return;
CcTest::InitializeVM();
struct TestCaseMsaVector tc[] = {
// wd_lo, wd_hi, ws_lo, ws_hi, wt_lo, wt_hi
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0xdcd39d91f9057627,
0x64be4f6dbe9caa51, 0x6b23de1a687d9cb9, 0x49547aad691da4ca},
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0x401614523d830549,
0xd7c46d613f50eddd, 0x52284cbc60a1562b, 0x1756ed510d8849cd},
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0xd6e2d2ebcb40d72f,
0x13a619afce67b079, 0x36cce284343e40f9, 0xb4e8f44fd148bf7f}};
for (size_t i = 0; i < sizeof(tc) / sizeof(TestCaseMsaVector); ++i) {
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ and_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws & wt; });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ or_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws | wt; });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ nor_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ~(ws | wt); });
run_msa_vector(
&tc[i], [](MacroAssembler& assm) { __ xor_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) { return ws ^ wt; });
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bmnz_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & wt) | (wd & ~wt);
});
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bmz_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & ~wt) | (wd & wt);
});
run_msa_vector(&tc[i], [](MacroAssembler& assm) { __ bsel_v(w4, w0, w2); },
[](uint64_t wd, uint64_t ws, uint64_t wt) {
return (ws & ~wd) | (wt & wd);
});
}
}
#undef __
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