Commit f87271cc authored by dusan.simicic's avatar dusan.simicic Committed by Commit Bot

MIPS[64]: Implement insert.df and I8 instructions in simulator

Add support for insert.df, andi.b, ori.b, nori.b, xori.b,
bmnzi.b, bmzi.b, bseli.b, shf.df MSA instructions in mips32
and mips64 simulator.

BUG=

Review-Url: https://codereview.chromium.org/2908753002
Cr-Commit-Position: refs/heads/master@{#45620}
parent 69aa868b
...@@ -161,6 +161,11 @@ const int kInvalidMSARegister = -1; ...@@ -161,6 +161,11 @@ const int kInvalidMSARegister = -1;
const int kInvalidMSAControlRegister = -1; const int kInvalidMSAControlRegister = -1;
const int kMSAIRRegister = 0; const int kMSAIRRegister = 0;
const int kMSACSRRegister = 1; const int kMSACSRRegister = 1;
const int kMSARegSize = 128;
const int kMSALanesByte = kMSARegSize / 8;
const int kMSALanesHalf = kMSARegSize / 16;
const int kMSALanesWord = kMSARegSize / 32;
const int kMSALanesDword = kMSARegSize / 64;
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented. // FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
const int kFCSRRegister = 31; const int kFCSRRegister = 31;
......
...@@ -1810,6 +1810,43 @@ void Simulator::TraceMSARegWr(T* value, TraceType t) { ...@@ -1810,6 +1810,43 @@ void Simulator::TraceMSARegWr(T* value, TraceType t) {
} }
} }
template <typename T>
void Simulator::TraceMSARegWr(T* value) {
if (::v8::internal::FLAG_trace_sim) {
union {
uint8_t b[kMSALanesByte];
uint16_t h[kMSALanesHalf];
uint32_t w[kMSALanesWord];
uint64_t d[kMSALanesDword];
float f[kMSALanesWord];
double df[kMSALanesDword];
} v;
memcpy(v.b, value, kMSALanesByte);
if (std::is_same<T, int32_t>::value) {
SNPrintF(trace_buf_,
"LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
") int32[0..3]:%" PRId32 " %" PRId32 " %" PRId32
" %" PRId32,
v.d[0], v.d[1], icount_, v.w[0], v.w[1], v.w[2], v.w[3]);
} else if (std::is_same<T, float>::value) {
SNPrintF(trace_buf_,
"LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
") flt[0..3]:%e %e %e %e",
v.d[0], v.d[1], icount_, v.f[0], v.f[1], v.f[2], v.f[3]);
} else if (std::is_same<T, double>::value) {
SNPrintF(trace_buf_,
"LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64
") dbl[0..1]:%e %e",
v.d[0], v.d[1], icount_, v.df[0], v.df[1]);
} else {
SNPrintF(trace_buf_,
"LO: %016" PRIx64 " HI: %016" PRIx64 " (%" PRIu64 ")",
v.d[0], v.d[1], icount_);
}
}
}
// TODO(plind): consider making icount_ printing a flag option. // TODO(plind): consider making icount_ printing a flag option.
void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) { void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) {
if (::v8::internal::FLAG_trace_sim) { if (::v8::internal::FLAG_trace_sim) {
...@@ -4263,19 +4300,97 @@ void Simulator::DecodeTypeMsaI8() { ...@@ -4263,19 +4300,97 @@ void Simulator::DecodeTypeMsaI8() {
DCHECK(IsMipsArchVariant(kMips32r6)); DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD)); DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask; uint32_t opcode = instr_.InstructionBits() & kMsaI8Mask;
int8_t i8 = instr_.MsaImm8Value();
msa_reg_t ws, wd;
switch (opcode) { switch (opcode) {
case ANDI_B: case ANDI_B:
get_msa_register(instr_.WsValue(), ws.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = ws.b[i] & i8;
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case ORI_B: case ORI_B:
get_msa_register(instr_.WsValue(), ws.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = ws.b[i] | i8;
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case NORI_B: case NORI_B:
get_msa_register(instr_.WsValue(), ws.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = ~(ws.b[i] | i8);
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case XORI_B: case XORI_B:
get_msa_register(instr_.WsValue(), ws.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = ws.b[i] ^ i8;
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case BMNZI_B: case BMNZI_B:
get_msa_register(instr_.WsValue(), ws.b);
get_msa_register(instr_.WdValue(), wd.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = (ws.b[i] & i8) | (wd.b[i] & ~i8);
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case BMZI_B: case BMZI_B:
get_msa_register(instr_.WsValue(), ws.b);
get_msa_register(instr_.WdValue(), wd.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = (ws.b[i] & ~i8) | (wd.b[i] & i8);
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case BSELI_B: case BSELI_B:
get_msa_register(instr_.WsValue(), ws.b);
get_msa_register(instr_.WdValue(), wd.b);
for (int i = 0; i < kMSALanesByte; i++) {
wd.b[i] = (ws.b[i] & ~wd.b[i]) | (wd.b[i] & i8);
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case SHF_B: case SHF_B:
get_msa_register(instr_.WsValue(), ws.b);
for (int i = 0; i < kMSALanesByte; i++) {
int j = i % 4;
int k = (i8 >> (2 * j)) & 0x3;
wd.b[i] = ws.b[i - j + k];
}
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
case SHF_H: case SHF_H:
get_msa_register(instr_.WsValue(), ws.h);
for (int i = 0; i < kMSALanesHalf; i++) {
int j = i % 4;
int k = (i8 >> (2 * j)) & 0x3;
wd.h[i] = ws.h[i - j + k];
}
set_msa_register(instr_.WdValue(), wd.h);
TraceMSARegWr(wd.h);
break;
case SHF_W: case SHF_W:
UNIMPLEMENTED(); get_msa_register(instr_.WsValue(), ws.w);
for (int i = 0; i < kMSALanesWord; i++) {
int j = (i8 >> (2 * i)) & 0x3;
wd.w[i] = ws.w[j];
}
set_msa_register(instr_.WdValue(), wd.w);
TraceMSARegWr(wd.w);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -4325,39 +4440,70 @@ void Simulator::DecodeTypeMsaELM() { ...@@ -4325,39 +4440,70 @@ void Simulator::DecodeTypeMsaELM() {
int32_t alu_out; int32_t alu_out;
switch (opcode) { switch (opcode) {
case COPY_S: case COPY_S:
case COPY_U: case COPY_U: {
msa_reg_t ws;
switch (DecodeMsaDataFormat()) { switch (DecodeMsaDataFormat()) {
case MSA_BYTE: { case MSA_BYTE: {
DCHECK(n < 16); DCHECK(n < kMSALanesByte);
int8_t ws[16]; get_msa_register(instr_.WsValue(), ws.b);
get_msa_register(instr_.WsValue(), ws); alu_out = static_cast<int32_t>(ws.b[n]);
alu_out = static_cast<int32_t>(ws[n]);
SetResult(wd_reg(), (opcode == COPY_U) ? alu_out & 0xFFu : alu_out); SetResult(wd_reg(), (opcode == COPY_U) ? alu_out & 0xFFu : alu_out);
break; break;
} }
case MSA_HALF: { case MSA_HALF: {
DCHECK(n < 8); DCHECK(n < kMSALanesHalf);
int16_t ws[8]; get_msa_register(instr_.WsValue(), ws.h);
get_msa_register(instr_.WsValue(), ws); alu_out = static_cast<int32_t>(ws.h[n]);
alu_out = static_cast<int32_t>(ws[n]);
SetResult(wd_reg(), (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out); SetResult(wd_reg(), (opcode == COPY_U) ? alu_out & 0xFFFFu : alu_out);
break; break;
} }
case MSA_WORD: { case MSA_WORD: {
DCHECK(n < 4); DCHECK(n < kMSALanesWord);
int32_t ws[4]; get_msa_register(instr_.WsValue(), ws.w);
get_msa_register(instr_.WsValue(), ws); alu_out = static_cast<int32_t>(ws.w[n]);
alu_out = static_cast<int32_t>(ws[n]);
SetResult(wd_reg(), alu_out); SetResult(wd_reg(), alu_out);
break; break;
} }
default: default:
UNREACHABLE(); UNREACHABLE();
} }
break; } break;
case INSERT: {
msa_reg_t wd;
switch (DecodeMsaDataFormat()) {
case MSA_BYTE: {
DCHECK(n < kMSALanesByte);
int32_t rs = get_register(instr_.WsValue());
get_msa_register(instr_.WdValue(), wd.b);
wd.b[n] = rs & 0xFFu;
set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd.b);
break;
}
case MSA_HALF: {
DCHECK(n < kMSALanesHalf);
int32_t rs = get_register(instr_.WsValue());
get_msa_register(instr_.WdValue(), wd.h);
wd.h[n] = rs & 0xFFFFu;
set_msa_register(instr_.WdValue(), wd.h);
TraceMSARegWr(wd.h);
break;
}
case MSA_WORD: {
DCHECK(n < kMSALanesWord);
int32_t rs = get_register(instr_.WsValue());
get_msa_register(instr_.WdValue(), wd.w);
wd.w[n] = rs;
set_msa_register(instr_.WdValue(), wd.w);
TraceMSARegWr(wd.w);
break;
}
default:
UNREACHABLE();
}
} break;
case SLDI: case SLDI:
case SPLATI: case SPLATI:
case INSERT:
case INSVE: case INSVE:
UNIMPLEMENTED(); UNIMPLEMENTED();
break; break;
...@@ -4555,37 +4701,35 @@ void Simulator::DecodeTypeMsa2R() { ...@@ -4555,37 +4701,35 @@ void Simulator::DecodeTypeMsa2R() {
DCHECK(IsMipsArchVariant(kMips32r6)); DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(CpuFeatures::IsSupported(MIPS_SIMD)); DCHECK(CpuFeatures::IsSupported(MIPS_SIMD));
uint32_t opcode = instr_.InstructionBits() & kMsa2RMask; uint32_t opcode = instr_.InstructionBits() & kMsa2RMask;
msa_reg_t wd;
switch (opcode) { switch (opcode) {
case FILL: case FILL:
switch (DecodeMsaDataFormat()) { switch (DecodeMsaDataFormat()) {
case MSA_BYTE: { case MSA_BYTE: {
int8_t wd[16];
int32_t rs = get_register(instr_.WsValue()); int32_t rs = get_register(instr_.WsValue());
for (int i = 0; i < 16; i++) { for (int i = 0; i < kMSALanesByte; i++) {
wd[i] = rs & 0xFFu; wd.b[i] = rs & 0xFFu;
} }
set_msa_register(instr_.WdValue(), wd); set_msa_register(instr_.WdValue(), wd.b);
TraceMSARegWr(wd, BYTE); TraceMSARegWr(wd.b);
break; break;
} }
case MSA_HALF: { case MSA_HALF: {
int16_t wd[8];
int32_t rs = get_register(instr_.WsValue()); int32_t rs = get_register(instr_.WsValue());
for (int i = 0; i < 8; i++) { for (int i = 0; i < kMSALanesHalf; i++) {
wd[i] = rs & 0xFFFFu; wd.h[i] = rs & 0xFFFFu;
} }
set_msa_register(instr_.WdValue(), wd); set_msa_register(instr_.WdValue(), wd.h);
TraceMSARegWr(wd, HALF); TraceMSARegWr(wd.h);
break; break;
} }
case MSA_WORD: { case MSA_WORD: {
int32_t wd[4];
int32_t rs = get_register(instr_.WsValue()); int32_t rs = get_register(instr_.WsValue());
for (int i = 0; i < 4; i++) { for (int i = 0; i < kMSALanesWord; i++) {
wd[i] = rs; wd.w[i] = rs;
} }
set_msa_register(instr_.WdValue(), wd); set_msa_register(instr_.WdValue(), wd.w);
TraceMSARegWr(wd, WORD); TraceMSARegWr(wd.w);
break; break;
} }
default: default:
......
...@@ -336,6 +336,12 @@ class Simulator { ...@@ -336,6 +336,12 @@ class Simulator {
// MSA Data Format // MSA Data Format
enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD }; enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD };
typedef union {
int8_t b[kMSALanesByte];
int16_t h[kMSALanesHalf];
int32_t w[kMSALanesWord];
int64_t d[kMSALanesDword];
} msa_reg_t;
// Read and write memory. // Read and write memory.
inline uint32_t ReadBU(int32_t addr); inline uint32_t ReadBU(int32_t addr);
...@@ -359,6 +365,8 @@ class Simulator { ...@@ -359,6 +365,8 @@ class Simulator {
void TraceRegWr(int64_t value, TraceType t = DWORD); void TraceRegWr(int64_t value, TraceType t = DWORD);
template <typename T> template <typename T>
void TraceMSARegWr(T* value, TraceType t); void TraceMSARegWr(T* value, TraceType t);
template <typename T>
void TraceMSARegWr(T* value);
void TraceMemWr(int32_t addr, int32_t value, TraceType t = WORD); void TraceMemWr(int32_t addr, int32_t value, TraceType t = WORD);
void TraceMemRd(int32_t addr, int32_t value, TraceType t = WORD); void TraceMemRd(int32_t addr, int32_t value, TraceType t = WORD);
void TraceMemWr(int32_t addr, int64_t value, TraceType t = DWORD); void TraceMemWr(int32_t addr, int64_t value, TraceType t = DWORD);
......
...@@ -122,6 +122,11 @@ const int kInvalidMSARegister = -1; ...@@ -122,6 +122,11 @@ const int kInvalidMSARegister = -1;
const int kInvalidMSAControlRegister = -1; const int kInvalidMSAControlRegister = -1;
const int kMSAIRRegister = 0; const int kMSAIRRegister = 0;
const int kMSACSRRegister = 1; const int kMSACSRRegister = 1;
const int kMSARegSize = 128;
const int kMSALanesByte = kMSARegSize / 8;
const int kMSALanesHalf = kMSARegSize / 16;
const int kMSALanesWord = kMSARegSize / 32;
const int kMSALanesDword = kMSARegSize / 64;
// FPU (coprocessor 1) control registers. Currently only FCSR is implemented. // FPU (coprocessor 1) control registers. Currently only FCSR is implemented.
const int kFCSRRegister = 31; const int kFCSRRegister = 31;
......
This diff is collapsed.
...@@ -354,6 +354,12 @@ class Simulator { ...@@ -354,6 +354,12 @@ class Simulator {
// MSA Data Format // MSA Data Format
enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD }; enum MSADataFormat { MSA_VECT = 0, MSA_BYTE, MSA_HALF, MSA_WORD, MSA_DWORD };
typedef union {
int8_t b[kMSALanesByte];
int16_t h[kMSALanesHalf];
int32_t w[kMSALanesWord];
int64_t d[kMSALanesDword];
} msa_reg_t;
// Read and write memory. // Read and write memory.
inline uint32_t ReadBU(int64_t addr); inline uint32_t ReadBU(int64_t addr);
...@@ -382,6 +388,8 @@ class Simulator { ...@@ -382,6 +388,8 @@ class Simulator {
void TraceRegWr(int64_t value, TraceType t = DWORD); void TraceRegWr(int64_t value, TraceType t = DWORD);
template <typename T> template <typename T>
void TraceMSARegWr(T* value, TraceType t); void TraceMSARegWr(T* value, TraceType t);
template <typename T>
void TraceMSARegWr(T* value);
void TraceMemWr(int64_t addr, int64_t value, TraceType t); void TraceMemWr(int64_t addr, int64_t value, TraceType t);
void TraceMemRd(int64_t addr, int64_t value, TraceType t = DWORD); void TraceMemRd(int64_t addr, int64_t value, TraceType t = DWORD);
......
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