Commit 6886f2ce authored by Dusan Simicic's avatar Dusan Simicic Committed by Commit Bot

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: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Cr-Commit-Position: refs/heads/master@{#46410}
parent b2644df7
......@@ -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.
......
This diff is collapsed.
This diff is collapsed.
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