Chromium Code Reviews| Index: src/mips/simulator-mips.cc |
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc |
| index 7ff3d144e7a019ff35ccc427ebc8788789e03557..c41934bf27a69964b08c04847825f6a965babdd5 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)); |
| + int64_t i64; |
| + i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg)); |
| + i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32; |
|
ivica.bogosavljevic
2017/01/23 13:22:38
According to strict C/C++, bitwise operation shoul
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
|
| + return i64; |
| + } |
| } |
| @@ -1688,18 +1695,75 @@ 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); |
| + default: |
| + break; |
|
ivica.bogosavljevic
2017/01/23 13:22:38
this should be UNREACHABLE, right?
Ilija.Pavlovic1
2017/01/27 09:09:16
Yes, this should be UNREACHABLE(). Also, missing "
|
| + } |
| } |
| } |
| +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); |
| + default: |
| + break; |
|
ivica.bogosavljevic
2017/01/23 13:22:38
UNREACHABLE!
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
|
| + } |
| + } |
| +} |
| // 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: |
| + break; |
|
ivica.bogosavljevic
2017/01/23 13:22:38
ibid here and all places bellow!
Ilija.Pavlovic1
2017/01/27 09:09:16
Done.
|
| + } |
| } |
| } |
| @@ -1708,22 +1772,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: |
| + break; |
| + } |
| + } |
| +} |
| + |
| +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: |
| break; |
| } |
| } |
| } |
| +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: |
| + break; |
| + } |
| + } |
| +} |
| -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 +1848,9 @@ 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)); |
| + if (t == WORD) { |
| + TraceMemRd(addr, static_cast<int32_t>(*ptr), t); |
|
ivica.bogosavljevic
2017/01/23 13:22:38
What happens if t != WORD? Should it be unreachabl
Ilija.Pavlovic1
2017/01/27 09:09:16
For WORD, the trace should be visible.
For FLOAT,
|
| + } |
| return *ptr; |
| } |
| PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n", |
| @@ -1744,7 +1861,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 +1882,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); |
| @@ -2464,25 +2579,30 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (result != fs) { |
| set_fcsr_bit(kFCSRInexactFlagBit, true); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case SEL: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case SELEQZ_C: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), (ft_int & 0x1) == 0 ? fs : 0.0); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case SELNEZ_C: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), (ft_int & 0x1) != 0 ? fs : 0.0); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MOVZ_C: { |
| DCHECK(IsMipsArchVariant(kMips32r2)); |
| if (rt() == 0) { |
| set_fpu_register_double(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case MOVN_C: { |
| @@ -2492,6 +2612,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (rt != 0) { |
| set_fpu_register_double(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case MOVF: { |
| @@ -2505,104 +2626,128 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| // MOVF.D |
| if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case MIN: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MAX: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MINA: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MAXA: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case ADD_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation( |
| [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case SUB_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation( |
| [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MADDF_D: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), std::fma(fs, ft, fd)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MSUBF_D: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_double(fd_reg(), std::fma(-fs, ft, fd)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MUL_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation( |
| [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case DIV_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation( |
| [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case ABS_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case MOV_D: |
| set_fpu_register_double(fd_reg(), fs); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case NEG_D: |
| set_fpu_register_double( |
| fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
| KeepSign::yes, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case SQRT_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case RSQRT_D: |
| set_fpu_register_double( |
| fd_reg(), FPUCanonalizeOperation( |
| [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case RECIP_D: |
| set_fpu_register_double( |
| fd_reg(), |
| FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| 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; |
| @@ -2612,6 +2757,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case ROUND_W_D: // Round double to word (round half to even). |
| { |
| @@ -2626,6 +2772,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case TRUNC_W_D: // Truncate double to word (round towards 0). |
| { |
| @@ -2635,6 +2782,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case FLOOR_W_D: // Round double to word towards negative infinity. |
| { |
| @@ -2644,6 +2792,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case CEIL_W_D: // Round double to word towards positive infinity. |
| { |
| @@ -2653,9 +2802,11 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case CVT_S_D: // Convert double to float (single). |
| set_fpu_register_float(fd_reg(), static_cast<float>(fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
| if (IsFp64Mode()) { |
| @@ -2666,6 +2817,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -2681,6 +2833,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -2701,6 +2854,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -2715,6 +2869,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -2729,6 +2884,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -2796,11 +2952,13 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| dResult = bit_cast<double>(result); |
| set_fpu_register_double(fd_reg(), dResult); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case C_F_D: { |
| set_fcsr_bit(fcsr_cc, false); |
| + TraceRegWr(test_fcsr_bit(fcsr_cc)); |
| break; |
| } |
| default: |
| @@ -2817,13 +2975,16 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| 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)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| 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)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case CMP_AF: |
| set_fpu_register_word(fd_reg(), 0); |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_UN: |
| if (std::isnan(fs) || std::isnan(ft)) { |
| @@ -2831,6 +2992,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_EQ: |
| if (fs == ft) { |
| @@ -2838,6 +3000,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_UEQ: |
| if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -2845,6 +3008,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_LT: |
| if (fs < ft) { |
| @@ -2852,6 +3016,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_ULT: |
| if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -2859,6 +3024,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_LE: |
| if (fs <= ft) { |
| @@ -2866,6 +3032,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_ULE: |
| if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -2873,6 +3040,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_OR: |
| if (!std::isnan(fs) && !std::isnan(ft)) { |
| @@ -2880,6 +3048,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_UNE: |
| if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -2887,6 +3056,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| case CMP_NE: |
| if (fs != ft) { |
| @@ -2894,6 +3064,7 @@ void Simulator::DecodeTypeRegisterWRsType() { |
| } else { |
| set_fpu_register_word(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -2948,6 +3119,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (result != fs) { |
| set_fcsr_bit(kFCSRInexactFlagBit, true); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case ADD_S: |
| @@ -2955,91 +3127,113 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| fd_reg(), |
| FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| fs, ft)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case SUB_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| fs, ft)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MADDF_S: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), std::fma(fs, ft, fd)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MSUBF_S: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), std::fma(-fs, ft, fd)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MUL_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| fs, ft)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case DIV_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| fs, ft)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case ABS_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MOV_S: |
| set_fpu_register_float(fd_reg(), fs); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case NEG_S: |
| set_fpu_register_float( |
| fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
| KeepSign::yes, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case SQRT_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case RSQRT_S: |
| set_fpu_register_float( |
| fd_reg(), FPUCanonalizeOperation( |
| [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case RECIP_S: |
| set_fpu_register_float( |
| fd_reg(), |
| FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| 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)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case SEL: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case CLASS_S: { // Mips32r6 instruction |
| // Convert float input to uint32_t for easier bit manipulation |
| @@ -3104,6 +3298,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| fResult = bit_cast<float>(result); |
| set_fpu_register_float(fd_reg(), fResult); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| @@ -3112,18 +3307,21 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 |
| ? get_fpu_register_float(fs_reg()) |
| : 0.0); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| 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); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MOVZ_C: { |
| DCHECK(IsMipsArchVariant(kMips32r2)); |
| if (rt() == 0) { |
| set_fpu_register_float(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case MOVN_C: { |
| @@ -3131,6 +3329,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (rt() != 0) { |
| set_fpu_register_float(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case MOVF: { |
| @@ -3145,6 +3344,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| // MOVF.D |
| if (!test_fcsr_bit(ft_cc)) set_fpu_register_float(fd_reg(), fs); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case TRUNC_W_S: { // Truncate single to word (round towards 0). |
| @@ -3154,6 +3354,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case TRUNC_L_S: { // Mips32r2 instruction. |
| DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| @@ -3164,6 +3365,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -3177,6 +3379,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case FLOOR_L_S: { // Mips32r2 instruction. |
| DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| @@ -3187,6 +3390,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -3204,6 +3408,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| } |
| case ROUND_L_S: { // Mips32r2 instruction. |
| @@ -3221,6 +3426,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -3234,6 +3440,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| } break; |
| case CEIL_L_S: { // Mips32r2 instruction. |
| DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); |
| @@ -3244,6 +3451,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -3252,18 +3460,22 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| case MIN: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MAX: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MINA: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case MAXA: |
| DCHECK(IsMipsArchVariant(kMips32r6)); |
| set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case CVT_L_S: { |
| if (IsFp64Mode()) { |
| @@ -3274,6 +3486,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round64_error(fs, rounded)) { |
| set_fpu_register_invalid_result64(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| } else { |
| UNSUPPORTED(); |
| } |
| @@ -3287,6 +3500,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (set_fcsr_round_error(fs, rounded)) { |
| set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| + TraceRegWr(get_fpu_register_word(fd_reg())); |
| break; |
| } |
| default: |
| @@ -3312,6 +3526,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| } |
| set_fpu_register_double(fd_reg(), static_cast<double>(i64)); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| case CVT_S_L: |
| if (IsFp64Mode()) { |
| @@ -3321,9 +3536,11 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| i64 |= static_cast<int64_t>(get_fpu_register_word(fs_reg() + 1)) << 32; |
| } |
| set_fpu_register_float(fd_reg(), static_cast<float>(i64)); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| case CMP_AF: // Mips64r6 CMP.D instructions. |
| set_fpu_register(fd_reg(), 0); |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_UN: |
| if (std::isnan(fs) || std::isnan(ft)) { |
| @@ -3331,6 +3548,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_EQ: |
| if (fs == ft) { |
| @@ -3338,6 +3556,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_UEQ: |
| if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -3345,6 +3564,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_LT: |
| if (fs < ft) { |
| @@ -3352,6 +3572,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_ULT: |
| if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -3359,6 +3580,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_LE: |
| if (fs <= ft) { |
| @@ -3366,6 +3588,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_ULE: |
| if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -3373,6 +3596,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_OR: |
| if (!std::isnan(fs) && !std::isnan(ft)) { |
| @@ -3380,6 +3604,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_UNE: |
| if ((fs != ft) || (std::isnan(fs) || std::isnan(ft))) { |
| @@ -3387,6 +3612,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| case CMP_NE: |
| if (fs != ft && (!std::isnan(fs) && !std::isnan(ft))) { |
| @@ -3394,6 +3620,7 @@ void Simulator::DecodeTypeRegisterLRsType() { |
| } else { |
| set_fpu_register(fd_reg(), 0); |
| } |
| + TraceRegWr(get_fpu_register(fd_reg())); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -3407,9 +3634,11 @@ void Simulator::DecodeTypeRegisterCOP1() { |
| // At the moment only FCSR is supported. |
| DCHECK(fs_reg() == kFCSRRegister); |
| set_register(rt_reg(), FCSR_); |
| + TraceRegWr(get_register(rt_reg())); |
| break; |
| case MFC1: |
| set_register(rt_reg(), get_fpu_register_word(fs_reg())); |
| + TraceRegWr(get_register(rt_reg())); |
| break; |
| case MFHC1: |
| if (IsFp64Mode()) { |
| @@ -3417,6 +3646,7 @@ void Simulator::DecodeTypeRegisterCOP1() { |
| } else { |
| set_register(rt_reg(), get_fpu_register_word(fs_reg() + 1)); |
| } |
| + TraceRegWr(get_register(rt_reg())); |
| break; |
| case CTC1: { |
| // At the moment only FCSR is supported. |
| @@ -3428,18 +3658,26 @@ void Simulator::DecodeTypeRegisterCOP1() { |
| DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
| FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| } |
| + TraceRegWr(static_cast<int32_t>(FCSR_), FLOAT); |
| 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: { |
| @@ -3473,6 +3711,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
| fs = get_fpu_register_float(fs_reg()); |
| ft = get_fpu_register_float(ft_reg()); |
| set_fpu_register_float(fd_reg(), fs * ft + fr); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case MSUB_S: { |
| @@ -3482,6 +3721,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
| fs = get_fpu_register_float(fs_reg()); |
| ft = get_fpu_register_float(ft_reg()); |
| set_fpu_register_float(fd_reg(), fs * ft - fr); |
| + TraceRegWr(get_fpu_register_word(fd_reg()), FLOAT); |
| break; |
| } |
| case MADD_D: { |
| @@ -3491,6 +3731,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
| fs = get_fpu_register_double(fs_reg()); |
| ft = get_fpu_register_double(ft_reg()); |
| set_fpu_register_double(fd_reg(), fs * ft + fr); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| case MSUB_D: { |
| @@ -3500,6 +3741,7 @@ void Simulator::DecodeTypeRegisterCOP1X() { |
| fs = get_fpu_register_double(fs_reg()); |
| ft = get_fpu_register_double(ft_reg()); |
| set_fpu_register_double(fd_reg(), fs * ft - fr); |
| + TraceRegWr(get_fpu_register(fd_reg()), DOUBLE); |
| break; |
| } |
| default: |
| @@ -4372,16 +4614,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: { |