MIPS[64]: Implement MSA 2R instructions in simulator
Add support for pcnt.df, nlzc.df, nloc.df MSA instructions in mips32 and mips64 simulator. Bug: Change-Id: I15c2e832c317ff81ce3615b7bd269e039c978e93 Reviewed-on: https://chromium-review.googlesource.com/538654 Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com> Reviewed-by: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com> Cr-Commit-Position: refs/heads/master@{#46410}
This commit is contained in:
parent
b2644df70f
commit
6886f2ceed
@ -4772,7 +4772,7 @@ void Simulator::DecodeTypeMsa2R() {
|
||||
DCHECK(IsMipsArchVariant(kMips32r6));
|
||||
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
|
||||
uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
|
||||
msa_reg_t wd;
|
||||
msa_reg_t wd, ws;
|
||||
switch (opcode) {
|
||||
case FILL:
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
@ -4808,9 +4808,93 @@ void Simulator::DecodeTypeMsa2R() {
|
||||
}
|
||||
break;
|
||||
case PCNT:
|
||||
#define PCNT_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
|
||||
wd.elem[i] = base::bits::CountPopulation64(u64elem); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
PCNT_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
PCNT_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
PCNT_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
PCNT_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef PCNT_DF
|
||||
break;
|
||||
case NLOC:
|
||||
#define NLOC_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
const uint64_t mask = (num_of_lanes == kMSALanesDword) \
|
||||
? UINT64_MAX \
|
||||
: (1ULL << (kMSARegSize / num_of_lanes)) - 1; \
|
||||
uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \
|
||||
wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
|
||||
(64 - kMSARegSize / num_of_lanes); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
NLOC_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
NLOC_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
NLOC_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
NLOC_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef NLOC_DF
|
||||
break;
|
||||
case NLZC:
|
||||
UNIMPLEMENTED();
|
||||
#define NLZC_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
|
||||
wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
|
||||
(64 - kMSARegSize / num_of_lanes); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
NLZC_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
NLZC_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
NLZC_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
NLZC_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef NLZC_DF
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -338,9 +338,13 @@ class Simulator {
|
||||
enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD };
|
||||
typedef union {
|
||||
int8_t b[kMSALanesByte];
|
||||
uint8_t ub[kMSALanesByte];
|
||||
int16_t h[kMSALanesHalf];
|
||||
uint16_t uh[kMSALanesHalf];
|
||||
int32_t w[kMSALanesWord];
|
||||
uint32_t uw[kMSALanesWord];
|
||||
int64_t d[kMSALanesDword];
|
||||
uint64_t ud[kMSALanesDword];
|
||||
} msa_reg_t;
|
||||
|
||||
// Read and write memory.
|
||||
|
@ -4997,7 +4997,7 @@ void Simulator::DecodeTypeMsa2R() {
|
||||
DCHECK(kArchVariant == kMips64r6);
|
||||
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
|
||||
uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
|
||||
msa_reg_t wd;
|
||||
msa_reg_t wd, ws;
|
||||
switch (opcode) {
|
||||
case FILL:
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
@ -5040,9 +5040,93 @@ void Simulator::DecodeTypeMsa2R() {
|
||||
}
|
||||
break;
|
||||
case PCNT:
|
||||
#define PCNT_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
|
||||
wd.elem[i] = base::bits::CountPopulation64(u64elem); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
PCNT_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
PCNT_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
PCNT_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
PCNT_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef PCNT_DF
|
||||
break;
|
||||
case NLOC:
|
||||
#define NLOC_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
const uint64_t mask = (num_of_lanes == kMSALanesDword) \
|
||||
? UINT64_MAX \
|
||||
: (1ULL << (kMSARegSize / num_of_lanes)) - 1; \
|
||||
uint64_t u64elem = static_cast<uint64_t>(~ws.elem[i]) & mask; \
|
||||
wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
|
||||
(64 - kMSARegSize / num_of_lanes); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
NLOC_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
NLOC_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
NLOC_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
NLOC_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef NLOC_DF
|
||||
break;
|
||||
case NLZC:
|
||||
UNIMPLEMENTED();
|
||||
#define NLZC_DF(elem, num_of_lanes) \
|
||||
get_msa_register(instr_.WsValue(), ws.elem); \
|
||||
for (int i = 0; i < num_of_lanes; i++) { \
|
||||
uint64_t u64elem = static_cast<uint64_t>(ws.elem[i]); \
|
||||
wd.elem[i] = base::bits::CountLeadingZeros64(u64elem) - \
|
||||
(64 - kMSARegSize / num_of_lanes); \
|
||||
} \
|
||||
set_msa_register(instr_.WdValue(), wd.elem); \
|
||||
TraceMSARegWr(wd.elem)
|
||||
|
||||
switch (DecodeMsaDataFormat()) {
|
||||
case MSA_BYTE:
|
||||
NLZC_DF(ub, kMSALanesByte);
|
||||
break;
|
||||
case MSA_HALF:
|
||||
NLZC_DF(uh, kMSALanesHalf);
|
||||
break;
|
||||
case MSA_WORD:
|
||||
NLZC_DF(uw, kMSALanesWord);
|
||||
break;
|
||||
case MSA_DWORD:
|
||||
NLZC_DF(ud, kMSALanesDword);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
#undef NLZC_DF
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -356,9 +356,13 @@ class Simulator {
|
||||
enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD };
|
||||
typedef union {
|
||||
int8_t b[kMSALanesByte];
|
||||
uint8_t ub[kMSALanesByte];
|
||||
int16_t h[kMSALanesHalf];
|
||||
uint16_t uh[kMSALanesHalf];
|
||||
int32_t w[kMSALanesWord];
|
||||
uint32_t uw[kMSALanesWord];
|
||||
int64_t d[kMSALanesDword];
|
||||
uint64_t ud[kMSALanesDword];
|
||||
} msa_reg_t;
|
||||
|
||||
// Read and write memory.
|
||||
|
@ -6624,4 +6624,223 @@ TEST(MSA_ceqi_clti_clei) {
|
||||
#undef CEQI_CLTI_CLEI_U_DF
|
||||
}
|
||||
|
||||
struct TestCaseMsa2R {
|
||||
uint64_t ws_lo;
|
||||
uint64_t ws_hi;
|
||||
uint64_t exp_res_lo;
|
||||
uint64_t exp_res_hi;
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
void run_msa_2r(struct TestCaseMsa2R* input, Func Generate2RInstructionFunc) {
|
||||
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;
|
||||
|
||||
__ li(t0, static_cast<uint32_t>(input->ws_lo & 0xffffffff));
|
||||
__ li(t1, static_cast<uint32_t>((input->ws_lo >> 32) & 0xffffffff));
|
||||
__ insert_w(w0, 0, t0);
|
||||
__ insert_w(w0, 1, t1);
|
||||
__ li(t0, static_cast<uint32_t>(input->ws_hi & 0xffffffff));
|
||||
__ li(t1, static_cast<uint32_t>((input->ws_hi >> 32) & 0xffffffff));
|
||||
__ insert_w(w0, 2, t0);
|
||||
__ insert_w(w0, 3, t1);
|
||||
|
||||
Generate2RInstructionFunc(assm);
|
||||
|
||||
__ copy_u_w(t2, w2, 0);
|
||||
__ sw(t2, MemOperand(a0, 0));
|
||||
__ copy_u_w(t2, w2, 1);
|
||||
__ sw(t2, MemOperand(a0, 4));
|
||||
__ copy_u_w(t2, w2, 2);
|
||||
__ sw(t2, MemOperand(a0, 8));
|
||||
__ copy_u_w(t2, w2, 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(input->exp_res_lo, res.d[0]);
|
||||
CHECK_EQ(input->exp_res_hi, res.d[1]);
|
||||
}
|
||||
|
||||
TEST(MSA_pcnt) {
|
||||
if (!IsMipsArchVariant(kMips32r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x0204050405050504, 0x0704030503070304},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0404040303040207, 0x0403010504060403},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0603030405030503, 0x0502080605070504}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x00060009000a0009, 0x000b0008000a0007},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0008000700070009, 0x00070006000a0007},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0009000700080008, 0x0007000e000c0009}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x0000000f00000013, 0x0000001300000011},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0000000f00000010, 0x0000000d00000011},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0000001000000010, 0x0000001500000015}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0x40, 0x40},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c, 0x22, 0x24},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8, 0x1f, 0x1e},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0x20, 0x2a}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ pcnt_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ pcnt_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ pcnt_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ pcnt_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSA_nlzc) {
|
||||
if (!IsMipsArchVariant(kMips32r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x1169350b07030100, 0x7f011402381f0a6c,
|
||||
0x0301020405060708, 0x0107030602030401},
|
||||
{0x010806003478121f, 0x03013016073f7b08,
|
||||
0x0704050802010303, 0x0607020305020104},
|
||||
{0x0168321100083803, 0x07113f03013f1676,
|
||||
0x0701020308040206, 0x0503020607020301}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x00010007000a003c, 0x37a5001e00010002,
|
||||
0x000f000d000c000a, 0x0002000b000f000e},
|
||||
{0x0026066200780edf, 0x003d0003000f00c8,
|
||||
0x000a000500090004, 0x000a000e000c0008},
|
||||
{0x335807e100480030, 0x01410fde12bf5636,
|
||||
0x000200050009000a, 0x0007000400030001}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x00000005000007c3, 0x000014ae00006a9c,
|
||||
0x0000001d00000015, 0x0000001300000011},
|
||||
{0x00009362000112df, 0x000380d6003f8bc8,
|
||||
0x000000100000000f, 0x0000000e0000000a},
|
||||
{0x135862e17e38f8b0, 0x0061ffde03bfe636,
|
||||
0x0000000300000001, 0x0000000900000006}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0x40, 0x40},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x000000000000014e, 0x00000000000176da, 0x37, 0x2f},
|
||||
{0x00000062c4e812df, 0x000065d68b3f8bc8, 0x19, 0x11},
|
||||
{0x00000000e338f8b0, 0x0754534acab32654, 0x20, 0x5}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ nlzc_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ nlzc_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ nlzc_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ nlzc_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSA_nloc) {
|
||||
if (!IsMipsArchVariant(kMips32r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xEE96CAF4F8FCFEFF, 0x80FEEBFDC7E0F593,
|
||||
0x0301020405060708, 0x0107030602030401},
|
||||
{0xFEF7F9FFCB87EDE0, 0xFCFECFE9F8C084F7,
|
||||
0x0704050802010303, 0x0607020305020104},
|
||||
{0xFE97CDEEFFF7C7FC, 0xF8EEC0FCFEC0E989,
|
||||
0x0701020308040206, 0x0503020607020301}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFEFFF8FFF5FFC3, 0xC85AFFE1FFFEFFFD,
|
||||
0x000f000d000c000a, 0x0002000b000f000e},
|
||||
{0xFFD9F99DFF87F120, 0xFFC2FFFCFFF0FF37,
|
||||
0x000a000500090004, 0x000a000e000c0008},
|
||||
{0xCCA7F81EFFB7FFCF, 0xFEBEF021ED40A9C9,
|
||||
0x000200050009000a, 0x0007000400030001}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFFFFFAFFFFF83C, 0xFFFFEB51FFFF9563,
|
||||
0x0000001d00000015, 0x0000001300000011},
|
||||
{0xFFFF6C9DFFFEED20, 0xFFFC7F29FFC07437,
|
||||
0x000000100000000f, 0x0000000e0000000a},
|
||||
{0xECA79D1E81C7074F, 0xFF9E0021FC4019C9,
|
||||
0x0000000300000001, 0x0000000900000006}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0x40, 0x40},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFFFFFFFFFFFEB1, 0xFFFFFFFFFFFE8925, 0x37, 0x2f},
|
||||
{0xFFFFFF9D3B17ED20, 0xFFFF9A2974C07437, 0x19, 0x11},
|
||||
{0xFFFFFFFF1CC7074F, 0xF8ABACB5354CD9AB, 0x20, 0x5}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ nloc_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ nloc_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ nloc_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ nloc_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
@ -7426,4 +7426,219 @@ TEST(MSA_ceqi_clti_clei) {
|
||||
#undef CEQI_CLTI_CLEI_U_DF
|
||||
}
|
||||
|
||||
struct TestCaseMsa2R {
|
||||
uint64_t ws_lo;
|
||||
uint64_t ws_hi;
|
||||
uint64_t exp_res_lo;
|
||||
uint64_t exp_res_hi;
|
||||
};
|
||||
|
||||
template <typename Func>
|
||||
void run_msa_2r(struct TestCaseMsa2R* input, Func Generate2RInstructionFunc) {
|
||||
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;
|
||||
|
||||
__ li(t0, input->ws_lo);
|
||||
__ li(t1, input->ws_hi);
|
||||
__ insert_d(w0, 0, t0);
|
||||
__ insert_d(w0, 1, t1);
|
||||
|
||||
Generate2RInstructionFunc(assm);
|
||||
|
||||
__ copy_u_w(t2, w2, 0);
|
||||
__ sw(t2, MemOperand(a0, 0));
|
||||
__ copy_u_w(t2, w2, 1);
|
||||
__ sw(t2, MemOperand(a0, 4));
|
||||
__ copy_u_w(t2, w2, 2);
|
||||
__ sw(t2, MemOperand(a0, 8));
|
||||
__ copy_u_w(t2, w2, 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(input->exp_res_lo, res.d[0]);
|
||||
CHECK_EQ(input->exp_res_hi, res.d[1]);
|
||||
}
|
||||
|
||||
TEST(MSA_pcnt) {
|
||||
if ((kArchVariant != kMips64r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x0204050405050504, 0x0704030503070304},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0404040303040207, 0x0403010504060403},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0603030405030503, 0x0502080605070504}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x00060009000a0009, 0x000b0008000a0007},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0008000700070009, 0x00070006000a0007},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0009000700080008, 0x0007000e000c0009}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c,
|
||||
0x0000000f00000013, 0x0000001300000011},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8,
|
||||
0x0000000f00000010, 0x0000000d00000011},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636,
|
||||
0x0000001000000010, 0x0000001500000015}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0x40, 0x40},
|
||||
{0x1169751bb9a7d9c3, 0xf7a594aec8ef8a9c, 0x22, 0x24},
|
||||
{0x2b665362c4e812df, 0x3a0d80d68b3f8bc8, 0x1f, 0x1e},
|
||||
{0xf35862e13e38f8b0, 0x4f41ffdef2bfe636, 0x20, 0x2a}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ pcnt_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ pcnt_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ pcnt_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ pcnt_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSA_nlzc) {
|
||||
if ((kArchVariant != kMips64r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x1169350b07030100, 0x7f011402381f0a6c,
|
||||
0x0301020405060708, 0x0107030602030401},
|
||||
{0x010806003478121f, 0x03013016073f7b08,
|
||||
0x0704050802010303, 0x0607020305020104},
|
||||
{0x0168321100083803, 0x07113f03013f1676,
|
||||
0x0701020308040206, 0x0503020607020301}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x00010007000a003c, 0x37a5001e00010002,
|
||||
0x000f000d000c000a, 0x0002000b000f000e},
|
||||
{0x0026066200780edf, 0x003d0003000f00c8,
|
||||
0x000a000500090004, 0x000a000e000c0008},
|
||||
{0x335807e100480030, 0x01410fde12bf5636,
|
||||
0x000200050009000a, 0x0007000400030001}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x00000005000007c3, 0x000014ae00006a9c,
|
||||
0x0000001d00000015, 0x0000001300000011},
|
||||
{0x00009362000112df, 0x000380d6003f8bc8,
|
||||
0x000000100000000f, 0x0000000e0000000a},
|
||||
{0x135862e17e38f8b0, 0x0061ffde03bfe636,
|
||||
0x0000000300000001, 0x0000000900000006}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0x0000000000000000, 0x0000000000000000, 0x40, 0x40},
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0, 0},
|
||||
{0x000000000000014e, 0x00000000000176da, 0x37, 0x2f},
|
||||
{0x00000062c4e812df, 0x000065d68b3f8bc8, 0x19, 0x11},
|
||||
{0x00000000e338f8b0, 0x0754534acab32654, 0x20, 0x5}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ nlzc_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ nlzc_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ nlzc_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ nlzc_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MSA_nloc) {
|
||||
if ((kArchVariant != kMips64r6) || !CpuFeatures::IsSupported(MIPS_SIMD))
|
||||
return;
|
||||
|
||||
CcTest::InitializeVM();
|
||||
|
||||
struct TestCaseMsa2R tc_b[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0808080808080808, 0x0808080808080808},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xEE96CAF4F8FCFEFF, 0x80FEEBFDC7E0F593,
|
||||
0x0301020405060708, 0x0107030602030401},
|
||||
{0xFEF7F9FFCB87EDE0, 0xFCFECFE9F8C084F7,
|
||||
0x0704050802010303, 0x0607020305020104},
|
||||
{0xFE97CDEEFFF7C7FC, 0xF8EEC0FCFEC0E989,
|
||||
0x0701020308040206, 0x0503020607020301}};
|
||||
|
||||
struct TestCaseMsa2R tc_h[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0010001000100010, 0x0010001000100010},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFEFFF8FFF5FFC3, 0xC85AFFE1FFFEFFFD,
|
||||
0x000f000d000c000a, 0x0002000b000f000e},
|
||||
{0xFFD9F99DFF87F120, 0xFFC2FFFCFFF0FF37,
|
||||
0x000a000500090004, 0x000a000e000c0008},
|
||||
{0xCCA7F81EFFB7FFCF, 0xFEBEF021ED40A9C9,
|
||||
0x000200050009000a, 0x0007000400030001}};
|
||||
|
||||
struct TestCaseMsa2R tc_w[] = {// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff,
|
||||
0x0000002000000020, 0x0000002000000020},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFFFFFAFFFFF83C, 0xFFFFEB51FFFF9563,
|
||||
0x0000001d00000015, 0x0000001300000011},
|
||||
{0xFFFF6C9DFFFEED20, 0xFFFC7F29FFC07437,
|
||||
0x000000100000000f, 0x0000000e0000000a},
|
||||
{0xECA79D1E81C7074F, 0xFF9E0021FC4019C9,
|
||||
0x0000000300000001, 0x0000000900000006}};
|
||||
|
||||
struct TestCaseMsa2R tc_d[] = {
|
||||
// ws_lo, ws_hi, exp_res_lo, exp_res_hi
|
||||
{0xffffffffffffffff, 0xffffffffffffffff, 0x40, 0x40},
|
||||
{0x0000000000000000, 0x0000000000000000, 0, 0},
|
||||
{0xFFFFFFFFFFFFFEB1, 0xFFFFFFFFFFFE8925, 0x37, 0x2f},
|
||||
{0xFFFFFF9D3B17ED20, 0xFFFF9A2974C07437, 0x19, 0x11},
|
||||
{0xFFFFFFFF1CC7074F, 0xF8ABACB5354CD9AB, 0x20, 0x5}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(tc_b) / sizeof(TestCaseMsa2R); ++i) {
|
||||
run_msa_2r(&tc_b[i], [](MacroAssembler& assm) { __ nloc_b(w2, w0); });
|
||||
run_msa_2r(&tc_h[i], [](MacroAssembler& assm) { __ nloc_h(w2, w0); });
|
||||
run_msa_2r(&tc_w[i], [](MacroAssembler& assm) { __ nloc_w(w2, w0); });
|
||||
run_msa_2r(&tc_d[i], [](MacroAssembler& assm) { __ nloc_d(w2, w0); });
|
||||
}
|
||||
}
|
||||
|
||||
#undef __
|
||||
|
Loading…
Reference in New Issue
Block a user