Index: src/mips/simulator-mips.cc |
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc |
index 7ff3d144e7a019ff35ccc427ebc8788789e03557..58191a8bddcc032a3ae51cdefc30a670a91527b8 100644 |
--- a/src/mips/simulator-mips.cc |
+++ b/src/mips/simulator-mips.cc |
@@ -1129,9 +1129,16 @@ double Simulator::get_double_from_register_pair(int reg) { |
int64_t Simulator::get_fpu_register(int fpureg) const { |
- DCHECK(IsFp64Mode()); |
- DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
- return FPUregisters_[fpureg]; |
+ if (IsFp64Mode()) { |
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
+ return FPUregisters_[fpureg]; |
+ } else { |
+ DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
+ uint64_t i64; |
+ i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg)); |
+ i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32; |
+ return static_cast<int64_t>(i64); |
+ } |
} |
@@ -1688,18 +1695,77 @@ int32_t Simulator::get_pc() const { |
// executed in the simulator. Since the host is typically IA32 we will not |
// get the correct MIPS-like behaviour on unaligned accesses. |
-void Simulator::TraceRegWr(int32_t value) { |
+void Simulator::TraceRegWr(int32_t value, TraceType t) { |
if (::v8::internal::FLAG_trace_sim) { |
- SNPrintF(trace_buf_, "%08x", value); |
+ union { |
+ int32_t fmt_int32; |
+ float fmt_float; |
+ } v; |
+ v.fmt_int32 = value; |
+ |
+ switch (t) { |
+ case WORD: |
+ SNPrintF(trace_buf_, "%08" PRIx32 " (%" PRIu64 ") int32:%" PRId32 |
+ " uint32:%" PRIu32, |
+ value, icount_, value, value); |
+ break; |
+ case FLOAT: |
+ SNPrintF(trace_buf_, "%08" PRIx32 " (%" PRIu64 ") flt:%e", |
+ v.fmt_int32, icount_, v.fmt_float); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
} |
} |
+void Simulator::TraceRegWr(int64_t value, TraceType t) { |
+ if (::v8::internal::FLAG_trace_sim) { |
+ union { |
+ int64_t fmt_int64; |
+ double fmt_double; |
+ } v; |
+ v.fmt_int64 = value; |
+ |
+ switch (t) { |
+ case DWORD: |
+ SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") int64:%" PRId64 |
+ " uint64:%" PRIu64, |
+ value, icount_, value, value); |
+ break; |
+ case DOUBLE: |
+ SNPrintF(trace_buf_, "%016" PRIx64 " (%" PRIu64 ") dbl:%e", |
+ v.fmt_int64, icount_, v.fmt_double); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+} |
// TODO(plind): consider making icount_ printing a flag option. |
-void Simulator::TraceMemRd(int32_t addr, int32_t value) { |
+void Simulator::TraceMemRd(int32_t addr, int32_t value, TraceType t) { |
if (::v8::internal::FLAG_trace_sim) { |
- SNPrintF(trace_buf_, "%08x <-- [%08x] (%" PRIu64 ")", value, addr, |
- icount_); |
+ union { |
+ int32_t fmt_int32; |
+ float fmt_float; |
+ } v; |
+ v.fmt_int32 = value; |
+ |
+ switch (t) { |
+ case WORD: |
+ SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 |
+ ") int32:%" PRId32 " uint32:%" PRIu32, |
+ value, addr, icount_, value, value); |
+ break; |
+ case FLOAT: |
+ SNPrintF(trace_buf_, |
+ "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 ") flt:%e", |
+ v.fmt_int32, addr, icount_, v.fmt_float); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
} |
} |
@@ -1708,22 +1774,73 @@ void Simulator::TraceMemWr(int32_t addr, int32_t value, TraceType t) { |
if (::v8::internal::FLAG_trace_sim) { |
switch (t) { |
case BYTE: |
- SNPrintF(trace_buf_, " %02x --> [%08x]", |
- static_cast<int8_t>(value), addr); |
+ SNPrintF(trace_buf_, |
+ " %02" PRIx8 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
+ static_cast<uint8_t>(value), addr, icount_); |
break; |
case HALF: |
- SNPrintF(trace_buf_, " %04x --> [%08x]", static_cast<int16_t>(value), |
- addr); |
+ SNPrintF(trace_buf_, |
+ " %04" PRIx16 " --> [%08" PRIx32 "] (%" PRIu64 ")", |
+ static_cast<uint16_t>(value), addr, icount_); |
break; |
case WORD: |
- SNPrintF(trace_buf_, "%08x --> [%08x]", value, addr); |
+ SNPrintF(trace_buf_, |
+ "%08" PRIx32 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, |
+ addr, icount_); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+} |
+ |
+void Simulator::TraceMemRd(int32_t addr, int64_t value, TraceType t) { |
+ if (::v8::internal::FLAG_trace_sim) { |
+ union { |
+ int64_t fmt_int64; |
+ int32_t fmt_int32[2]; |
+ float fmt_float[2]; |
+ double fmt_double; |
+ } v; |
+ v.fmt_int64 = value; |
+ |
+ switch (t) { |
+ case DWORD: |
+ SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 |
+ ") int64:%" PRId64 " uint64:%" PRIu64, |
+ v.fmt_int64, addr, icount_, v.fmt_int64, v.fmt_int64); |
+ break; |
+ case DOUBLE: |
+ SNPrintF(trace_buf_, "%016" PRIx64 " <-- [%08" PRIx32 "] (%" PRIu64 |
+ ") dbl:%e", |
+ v.fmt_int64, addr, icount_, v.fmt_double); |
+ break; |
+ case FLOAT_DOUBLE: |
+ SNPrintF(trace_buf_, "%08" PRIx32 " <-- [%08" PRIx32 "] (%" PRIu64 |
+ ") flt:%e dbl:%e", |
+ v.fmt_int32[1], addr, icount_, v.fmt_float[1], v.fmt_double); |
break; |
+ default: |
+ UNREACHABLE(); |
} |
} |
} |
+void Simulator::TraceMemWr(int32_t addr, int64_t value, TraceType t) { |
+ if (::v8::internal::FLAG_trace_sim) { |
+ switch (t) { |
+ case DWORD: |
+ SNPrintF(trace_buf_, |
+ "%016" PRIx64 " --> [%08" PRIx32 "] (%" PRIu64 ")", value, |
+ addr, icount_); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ } |
+} |
-int Simulator::ReadW(int32_t addr, Instruction* instr) { |
+int Simulator::ReadW(int32_t addr, Instruction* instr, TraceType t) { |
if (addr >=0 && addr < 0x400) { |
// This has to be a NULL-dereference, drop into debugger. |
PrintF("Memory read from bad address: 0x%08x, pc=0x%08" PRIxPTR "\n", addr, |
@@ -1733,7 +1850,16 @@ int Simulator::ReadW(int32_t addr, Instruction* instr) { |
} |
if ((addr & kPointerAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
- TraceMemRd(addr, static_cast<int32_t>(*ptr)); |
+ switch (t) { |
+ case WORD: |
+ TraceMemRd(addr, static_cast<int32_t>(*ptr), t); |
+ break; |
+ case FLOAT: |
+ // This TraceType is allowed but tracing for this value will be omitted. |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
return *ptr; |
} |
PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
@@ -1744,7 +1870,6 @@ int Simulator::ReadW(int32_t addr, Instruction* instr) { |
return 0; |
} |
- |
void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { |
if (addr >= 0 && addr < 0x400) { |
// This has to be a NULL-dereference, drop into debugger. |
@@ -1766,7 +1891,6 @@ void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { |
dbg.Debug(); |
} |
- |
double Simulator::ReadD(int32_t addr, Instruction* instr) { |
if ((addr & kDoubleAlignmentMask) == 0 || IsMipsArchVariant(kMips32r6)) { |
double* ptr = reinterpret_cast<double*>(addr); |
@@ -2460,7 +2584,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
result = lower; |
break; |
} |
- set_fpu_register_double(fd_reg(), result); |
+ SetFPUDoubleResult(fd_reg(), result); |
if (result != fs) { |
set_fcsr_bit(kFCSRInexactFlagBit, true); |
} |
@@ -2468,20 +2592,20 @@ void Simulator::DecodeTypeRegisterDRsType() { |
} |
case SEL: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
+ SetFPUDoubleResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
break; |
case SELEQZ_C: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
+ SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
break; |
case SELNEZ_C: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
+ SetFPUDoubleResult(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
break; |
case MOVZ_C: { |
DCHECK(IsMipsArchVariant(kMips32r2)); |
if (rt() == 0) { |
- set_fpu_register_double(fd_reg(), fs); |
+ SetFPUDoubleResult(fd_reg(), fs); |
} |
break; |
} |
@@ -2490,7 +2614,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
int32_t rt_reg = instr_.RtValue(); |
int32_t rt = get_register(rt_reg); |
if (rt != 0) { |
- set_fpu_register_double(fd_reg(), fs); |
+ SetFPUDoubleResult(fd_reg(), fs); |
} |
break; |
} |
@@ -2500,115 +2624,121 @@ void Simulator::DecodeTypeRegisterDRsType() { |
ft_cc = get_fcsr_condition_bit(ft_cc); |
if (instr_.Bit(16)) { // Read Tf bit. |
// MOVT.D |
- if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
+ if (test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
} else { |
// MOVF.D |
- if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
+ if (!test_fcsr_bit(ft_cc)) SetFPUDoubleResult(fd_reg(), fs); |
} |
break; |
} |
case MIN: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
+ SetFPUDoubleResult(fd_reg(), FPUMin(ft, fs)); |
break; |
case MAX: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
+ SetFPUDoubleResult(fd_reg(), FPUMax(ft, fs)); |
break; |
case MINA: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
+ SetFPUDoubleResult(fd_reg(), FPUMinA(ft, fs)); |
break; |
case MAXA: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
+ SetFPUDoubleResult(fd_reg(), FPUMaxA(ft, fs)); |
break; |
case ADD_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation( |
[](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
break; |
case SUB_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation( |
[](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
break; |
case MADDF_D: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); |
+ SetFPUDoubleResult(fd_reg(), std::fma(fs, ft, fd)); |
break; |
case MSUBF_D: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); |
+ SetFPUDoubleResult(fd_reg(), std::fma(-fs, ft, fd)); |
break; |
case MUL_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation( |
[](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
break; |
case DIV_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation( |
[](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
break; |
case ABS_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
break; |
case MOV_D: |
- set_fpu_register_double(fd_reg(), fs); |
+ SetFPUDoubleResult(fd_reg(), fs); |
break; |
case NEG_D: |
- set_fpu_register_double( |
- fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
- KeepSign::yes, fs)); |
+ SetFPUDoubleResult(fd_reg(), |
+ FPUCanonalizeOperation([](double src) { return -src; }, |
+ KeepSign::yes, fs)); |
break; |
case SQRT_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), |
FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
break; |
case RSQRT_D: |
- set_fpu_register_double( |
+ SetFPUDoubleResult( |
fd_reg(), FPUCanonalizeOperation( |
[](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
break; |
case RECIP_D: |
- set_fpu_register_double( |
- fd_reg(), |
- FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
+ SetFPUDoubleResult(fd_reg(), FPUCanonalizeOperation( |
+ [](double fs) { return 1.0 / fs; }, fs)); |
break; |
case C_UN_D: |
set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_EQ_D: |
set_fcsr_bit(fcsr_cc, (fs == ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_UEQ_D: |
set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_OLT_D: |
set_fcsr_bit(fcsr_cc, (fs < ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_ULT_D: |
set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_OLE_D: |
set_fcsr_bit(fcsr_cc, (fs <= ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_ULE_D: |
set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case CVT_W_D: { // Convert double to word. |
double rounded; |
int32_t result; |
round_according_to_fcsr(fs, rounded, result, fs); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -2622,7 +2752,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
// round to the even one. |
result--; |
} |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -2631,7 +2761,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
{ |
double rounded = trunc(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -2640,7 +2770,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
{ |
double rounded = std::floor(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -2649,20 +2779,20 @@ void Simulator::DecodeTypeRegisterDRsType() { |
{ |
double rounded = std::ceil(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
} break; |
case CVT_S_D: // Convert double to float (single). |
- set_fpu_register_float(fd_reg(), static_cast<float>(fs)); |
+ SetFPUFloatResult(fd_reg(), static_cast<float>(fs)); |
break; |
case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
if (IsFp64Mode()) { |
int64_t result; |
double rounded; |
round64_according_to_fcsr(fs, rounded, result, fs); |
- set_fpu_register(fd_reg(), result); |
+ SetFPUResult(fd_reg(), result); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -2677,7 +2807,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
double rounded = trunc(fs); |
i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -2697,7 +2827,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
} |
int64_t i64 = static_cast<int64_t>(result); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -2711,7 +2841,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
double rounded = std::floor(fs); |
int64_t i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -2725,7 +2855,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
double rounded = std::ceil(fs); |
int64_t i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -2795,12 +2925,13 @@ void Simulator::DecodeTypeRegisterDRsType() { |
DCHECK(result != 0); |
dResult = bit_cast<double>(result); |
- set_fpu_register_double(fd_reg(), dResult); |
+ SetFPUDoubleResult(fd_reg(), dResult); |
break; |
} |
case C_F_D: { |
set_fcsr_bit(fcsr_cc, false); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
} |
default: |
@@ -2816,83 +2947,83 @@ void Simulator::DecodeTypeRegisterWRsType() { |
switch (instr_.FunctionFieldRaw()) { |
case CVT_S_W: // Convert word to float (single). |
alu_out = get_fpu_register_signed_word(fs_reg()); |
- set_fpu_register_float(fd_reg(), static_cast<float>(alu_out)); |
+ SetFPUFloatResult(fd_reg(), static_cast<float>(alu_out)); |
break; |
case CVT_D_W: // Convert word to double. |
alu_out = get_fpu_register_signed_word(fs_reg()); |
- set_fpu_register_double(fd_reg(), static_cast<double>(alu_out)); |
+ SetFPUDoubleResult(fd_reg(), static_cast<double>(alu_out)); |
break; |
case CMP_AF: |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
break; |
case CMP_UN: |
if (std::isnan(fs) || std::isnan(ft)) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_EQ: |
if (fs == ft) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_UEQ: |
if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_LT: |
if (fs < ft) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_ULT: |
if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_LE: |
if (fs <= ft) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_ULE: |
if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_OR: |
if (!std::isnan(fs) && !std::isnan(ft)) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_UNE: |
if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
case CMP_NE: |
if (fs != ft) { |
- set_fpu_register_word(fd_reg(), -1); |
+ SetFPUWordResult(fd_reg(), -1); |
} else { |
- set_fpu_register_word(fd_reg(), 0); |
+ SetFPUWordResult(fd_reg(), 0); |
} |
break; |
default: |
@@ -2944,102 +3075,108 @@ void Simulator::DecodeTypeRegisterSRsType() { |
result = lower; |
break; |
} |
- set_fpu_register_float(fd_reg(), result); |
+ SetFPUFloatResult(fd_reg(), result); |
if (result != fs) { |
set_fcsr_bit(kFCSRInexactFlagBit, true); |
} |
break; |
} |
case ADD_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), |
FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
fs, ft)); |
break; |
case SUB_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), |
FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
fs, ft)); |
break; |
case MADDF_S: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); |
+ SetFPUFloatResult(fd_reg(), std::fma(fs, ft, fd)); |
break; |
case MSUBF_S: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); |
+ SetFPUFloatResult(fd_reg(), std::fma(-fs, ft, fd)); |
break; |
case MUL_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), |
FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
fs, ft)); |
break; |
case DIV_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), |
FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
fs, ft)); |
break; |
case ABS_S: |
- set_fpu_register_float( |
- fd_reg(), |
- FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
+ [](float fs) { return FPAbs(fs); }, fs)); |
break; |
case MOV_S: |
- set_fpu_register_float(fd_reg(), fs); |
+ SetFPUFloatResult(fd_reg(), fs); |
break; |
case NEG_S: |
- set_fpu_register_float( |
- fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
- KeepSign::yes, fs)); |
+ SetFPUFloatResult(fd_reg(), |
+ FPUCanonalizeOperation([](float src) { return -src; }, |
+ KeepSign::yes, fs)); |
break; |
case SQRT_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), |
FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
break; |
case RSQRT_S: |
- set_fpu_register_float( |
+ SetFPUFloatResult( |
fd_reg(), FPUCanonalizeOperation( |
[](float src) { return 1.0 / std::sqrt(src); }, fs)); |
break; |
case RECIP_S: |
- set_fpu_register_float( |
- fd_reg(), |
- FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUCanonalizeOperation( |
+ [](float src) { return 1.0 / src; }, fs)); |
break; |
case C_F_D: |
set_fcsr_bit(fcsr_cc, false); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_UN_D: |
set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_EQ_D: |
set_fcsr_bit(fcsr_cc, (fs == ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_UEQ_D: |
set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_OLT_D: |
set_fcsr_bit(fcsr_cc, (fs < ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_ULT_D: |
set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_OLE_D: |
set_fcsr_bit(fcsr_cc, (fs <= ft)); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case C_ULE_D: |
set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
+ TraceRegWr(test_fcsr_bit(fcsr_cc)); |
break; |
case CVT_D_S: |
- set_fpu_register_double(fd_reg(), static_cast<double>(fs)); |
+ SetFPUDoubleResult(fd_reg(), static_cast<double>(fs)); |
break; |
case SEL: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
+ SetFPUFloatResult(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
break; |
case CLASS_S: { // Mips32r6 instruction |
// Convert float input to uint32_t for easier bit manipulation |
@@ -3103,33 +3240,33 @@ void Simulator::DecodeTypeRegisterSRsType() { |
DCHECK(result != 0); |
fResult = bit_cast<float>(result); |
- set_fpu_register_float(fd_reg(), fResult); |
+ SetFPUFloatResult(fd_reg(), fResult); |
break; |
} |
case SELEQZ_C: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 |
- ? get_fpu_register_float(fs_reg()) |
- : 0.0); |
+ SetFPUFloatResult( |
+ fd_reg(), |
+ (ft_int & 0x1) == 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
break; |
case SELNEZ_C: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), (ft_int & 0x1) != 0 |
- ? get_fpu_register_float(fs_reg()) |
- : 0.0); |
+ SetFPUFloatResult( |
+ fd_reg(), |
+ (ft_int & 0x1) != 0 ? get_fpu_register_float(fs_reg()) : 0.0); |
break; |
case MOVZ_C: { |
DCHECK(IsMipsArchVariant(kMips32r2)); |
if (rt() == 0) { |
- set_fpu_register_float(fd_reg(), fs); |
+ SetFPUFloatResult(fd_reg(), fs); |
} |
break; |
} |
case MOVN_C: { |
DCHECK(IsMipsArchVariant(kMips32r2)); |
if (rt() != 0) { |
- set_fpu_register_float(fd_reg(), fs); |
+ SetFPUFloatResult(fd_reg(), fs); |
} |
break; |
} |
@@ -3140,17 +3277,17 @@ void Simulator::DecodeTypeRegisterSRsType() { |
if (instr_.Bit(16)) { // Read Tf bit. |
// MOVT.D |
- if (test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
+ if (test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
} else { |
// MOVF.D |
- if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
+ if (!test_fcsr_bit(ft_cc)) SetFPUFloatResult(fd_reg(), fs); |
} |
break; |
} |
case TRUNC_W_S: { // Truncate single to word (round towards 0). |
float rounded = trunc(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -3160,7 +3297,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
float rounded = trunc(fs); |
int64_t i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -3173,7 +3310,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
{ |
float rounded = std::floor(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -3183,7 +3320,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
float rounded = std::floor(fs); |
int64_t i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -3200,7 +3337,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
// round to the even one. |
result--; |
} |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -3217,7 +3354,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
} |
int64_t i64 = static_cast<int64_t>(result); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -3230,7 +3367,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
{ |
float rounded = std::ceil(fs); |
int32_t result = static_cast<int32_t>(rounded); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -3240,7 +3377,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
float rounded = std::ceil(fs); |
int64_t i64 = static_cast<int64_t>(rounded); |
if (IsFp64Mode()) { |
- set_fpu_register(fd_reg(), i64); |
+ SetFPUResult(fd_reg(), i64); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -3251,26 +3388,26 @@ void Simulator::DecodeTypeRegisterSRsType() { |
} |
case MIN: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUMin(ft, fs)); |
break; |
case MAX: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUMax(ft, fs)); |
break; |
case MINA: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUMinA(ft, fs)); |
break; |
case MAXA: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
+ SetFPUFloatResult(fd_reg(), FPUMaxA(ft, fs)); |
break; |
case CVT_L_S: { |
if (IsFp64Mode()) { |
int64_t result; |
float rounded; |
round64_according_to_fcsr(fs, rounded, result, fs); |
- set_fpu_register(fd_reg(), result); |
+ SetFPUResult(fd_reg(), result); |
if (set_fcsr_round64_error(fs, rounded)) { |
set_fpu_register_invalid_result64(fs, rounded); |
} |
@@ -3283,7 +3420,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
float rounded; |
int32_t result; |
round_according_to_fcsr(fs, rounded, result, fs); |
- set_fpu_register_word(fd_reg(), result); |
+ SetFPUWordResult(fd_reg(), result); |
if (set_fcsr_round_error(fs, rounded)) { |
set_fpu_register_word_invalid_result(fs, rounded); |
} |
@@ -3311,7 +3448,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); |
i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
} |
- set_fpu_register_double(fd_reg(), static_cast<double>(i64)); |
+ SetFPUDoubleResult(fd_reg(), static_cast<double>(i64)); |
break; |
case CVT_S_L: |
if (IsFp64Mode()) { |
@@ -3320,79 +3457,79 @@ void Simulator::DecodeTypeRegisterLRsType() { |
i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg())); |
i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
} |
- set_fpu_register_float(fd_reg(), static_cast<float>(i64)); |
+ SetFPUFloatResult(fd_reg(), static_cast<float>(i64)); |
break; |
case CMP_AF: // Mips64r6 CMP.D instructions. |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
break; |
case CMP_UN: |
if (std::isnan(fs) || std::isnan(ft)) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_EQ: |
if (fs == ft) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_UEQ: |
if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_LT: |
if (fs < ft) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_ULT: |
if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_LE: |
if (fs <= ft) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_ULE: |
if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_OR: |
if (!std::isnan(fs) && !std::isnan(ft)) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_UNE: |
if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
case CMP_NE: |
if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
- set_fpu_register(fd_reg(), -1); |
+ SetFPUResult(fd_reg(), -1); |
} else { |
- set_fpu_register(fd_reg(), 0); |
+ SetFPUResult(fd_reg(), 0); |
} |
break; |
default: |
@@ -3406,16 +3543,16 @@ void Simulator::DecodeTypeRegisterCOP1() { |
case CFC1: |
// At the moment only FCSR is supported. |
DCHECK(fs_reg() == kFCSRRegister); |
- set_register(rt_reg(), FCSR_); |
+ SetResult(rt_reg(), FCSR_); |
break; |
case MFC1: |
- set_register(rt_reg(), get_fpu_register_word(fs_reg())); |
+ SetResult(rt_reg(), get_fpu_register_word(fs_reg())); |
break; |
case MFHC1: |
if (IsFp64Mode()) { |
- set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
+ SetResult(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
} else { |
- set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
+ SetResult(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
} |
break; |
case CTC1: { |
@@ -3428,18 +3565,26 @@ void Simulator::DecodeTypeRegisterCOP1() { |
DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
} |
+ TraceRegWr(static_cast<int32_t>(FCSR_)); |
break; |
} |
case MTC1: |
// Hardware writes upper 32-bits to zero on mtc1. |
set_fpu_register_hi_word(fs_reg(), 0); |
set_fpu_register_word(fs_reg(), registers_[rt_reg()]); |
+ TraceRegWr(get_fpu_register_word(fs_reg()), FLOAT); |
break; |
case MTHC1: |
if (IsFp64Mode()) { |
set_fpu_register_hi_word(fs_reg(), registers_[rt_reg()]); |
+ TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); |
} else { |
set_fpu_register_word(fs_reg() + 1, registers_[rt_reg()]); |
+ if (fs_reg() % 2) { |
+ TraceRegWr(get_fpu_register_word(fs_reg() + 1), FLOAT); |
+ } else { |
+ TraceRegWr(get_fpu_register(fs_reg()), DOUBLE); |
+ } |
} |
break; |
case S: { |
@@ -3472,7 +3617,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
fr = get_fpu_register_float(fr_reg()); |
fs = get_fpu_register_float(fs_reg()); |
ft = get_fpu_register_float(ft_reg()); |
- set_fpu_register_float(fd_reg(), fs * ft + fr); |
+ SetFPUFloatResult(fd_reg(), fs * ft + fr); |
break; |
} |
case MSUB_S: { |
@@ -3481,7 +3626,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
fr = get_fpu_register_float(fr_reg()); |
fs = get_fpu_register_float(fs_reg()); |
ft = get_fpu_register_float(ft_reg()); |
- set_fpu_register_float(fd_reg(), fs * ft - fr); |
+ SetFPUFloatResult(fd_reg(), fs * ft - fr); |
break; |
} |
case MADD_D: { |
@@ -3490,7 +3635,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
fr = get_fpu_register_double(fr_reg()); |
fs = get_fpu_register_double(fs_reg()); |
ft = get_fpu_register_double(ft_reg()); |
- set_fpu_register_double(fd_reg(), fs * ft + fr); |
+ SetFPUDoubleResult(fd_reg(), fs * ft + fr); |
break; |
} |
case MSUB_D: { |
@@ -3499,7 +3644,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
fr = get_fpu_register_double(fr_reg()); |
fs = get_fpu_register_double(fs_reg()); |
ft = get_fpu_register_double(ft_reg()); |
- set_fpu_register_double(fd_reg(), fs * ft - fr); |
+ SetFPUDoubleResult(fd_reg(), fs * ft - fr); |
break; |
} |
default: |
@@ -3517,11 +3662,11 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
switch (instr_.FunctionFieldRaw()) { |
case SELEQZ_S: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_register(rd_reg(), rt() == 0 ? rs() : 0); |
+ SetResult(rd_reg(), rt() == 0 ? rs() : 0); |
break; |
case SELNEZ_S: |
DCHECK(IsMipsArchVariant(kMips32r6)); |
- set_register(rd_reg(), rt() != 0 ? rs() : 0); |
+ SetResult(rd_reg(), rt() != 0 ? rs() : 0); |
break; |
case JR: { |
int32_t next_pc = rs(); |
@@ -3622,10 +3767,10 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
} else { |
switch (sa()) { |
case MUL_OP: |
- set_register(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); |
+ SetResult(rd_reg(), static_cast<int32_t>(i64hilo & 0xffffffff)); |
break; |
case MUH_OP: |
- set_register(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); |
+ SetResult(rd_reg(), static_cast<int32_t>(i64hilo >> 32)); |
break; |
default: |
UNIMPLEMENTED_MIPS(); |
@@ -3641,10 +3786,10 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
} else { |
switch (sa()) { |
case MUL_OP: |
- set_register(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); |
+ SetResult(rd_reg(), static_cast<int32_t>(u64hilo & 0xffffffff)); |
break; |
case MUH_OP: |
- set_register(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
+ SetResult(rd_reg(), static_cast<int32_t>(u64hilo >> 32)); |
break; |
default: |
UNIMPLEMENTED_MIPS(); |
@@ -3657,16 +3802,16 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
switch (sa()) { |
case DIV_OP: |
if (rs() == INT_MIN && rt() == -1) { |
- set_register(rd_reg(), INT_MIN); |
+ SetResult(rd_reg(), INT_MIN); |
} else if (rt() != 0) { |
- set_register(rd_reg(), rs() / rt()); |
+ SetResult(rd_reg(), rs() / rt()); |
} |
break; |
case MOD_OP: |
if (rs() == INT_MIN && rt() == -1) { |
- set_register(rd_reg(), 0); |
+ SetResult(rd_reg(), 0); |
} else if (rt() != 0) { |
- set_register(rd_reg(), rs() % rt()); |
+ SetResult(rd_reg(), rs() % rt()); |
} |
break; |
default: |
@@ -3692,12 +3837,12 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
switch (sa()) { |
case DIV_OP: |
if (rt_u() != 0) { |
- set_register(rd_reg(), rs_u() / rt_u()); |
+ SetResult(rd_reg(), rs_u() / rt_u()); |
} |
break; |
case MOD_OP: |
if (rt_u() != 0) { |
- set_register(rd_reg(), rs_u() % rt_u()); |
+ SetResult(rd_reg(), rs_u() % rt_u()); |
} |
break; |
default: |
@@ -3791,8 +3936,7 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
// Conditional moves. |
case MOVN: |
if (rt()) { |
- set_register(rd_reg(), rs()); |
- TraceRegWr(rs()); |
+ SetResult(rd_reg(), rs()); |
} |
break; |
case MOVCI: { |
@@ -3807,8 +3951,7 @@ void Simulator::DecodeTypeRegisterSPECIAL() { |
} |
case MOVZ: |
if (!rt()) { |
- set_register(rd_reg(), rs()); |
- TraceRegWr(rs()); |
+ SetResult(rd_reg(), rs()); |
} |
break; |
default: |
@@ -4372,16 +4515,25 @@ void Simulator::DecodeTypeImmediate() { |
} |
case LWC1: |
set_fpu_register_hi_word(ft_reg, 0); |
- set_fpu_register_word(ft_reg, ReadW(rs + se_imm16, instr_.instr())); |
+ set_fpu_register_word(ft_reg, |
+ ReadW(rs + se_imm16, instr_.instr(), FLOAT)); |
+ if (ft_reg % 2) { |
+ TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg - 1), FLOAT_DOUBLE); |
+ } else { |
+ TraceMemRd(rs + se_imm16, get_fpu_register_word(ft_reg), FLOAT); |
+ } |
break; |
case LDC1: |
set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr_.instr())); |
+ TraceMemRd(rs + se_imm16, get_fpu_register(ft_reg), DOUBLE); |
break; |
case SWC1: |
WriteW(rs + se_imm16, get_fpu_register_word(ft_reg), instr_.instr()); |
+ TraceMemWr(rs + se_imm16, get_fpu_register_word(ft_reg)); |
break; |
case SDC1: |
WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr_.instr()); |
+ TraceMemWr(rs + se_imm16, get_fpu_register(ft_reg)); |
break; |
// ------------- PC-Relative instructions. |
case PCREL: { |
@@ -4422,7 +4574,7 @@ void Simulator::DecodeTypeImmediate() { |
} |
} |
} |
- set_register(rs_reg, alu_out); |
+ SetResult(rs_reg, alu_out); |
break; |
} |
default: |