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: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com> Cr-Commit-Position: refs/heads/master@{#46474}
This commit is contained in:
parent
08688b3953
commit
c16a39f23e
@ -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 __
|
||||
|
Loading…
Reference in New Issue
Block a user