Chromium Code Reviews| Index: src/mips/simulator-mips.cc |
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc |
| index e52b3833b4856fcfd599b40a0348c87ca955c9f2..4be07d468ce3c126705438dbfb3936d47e3165d7 100644 |
| --- a/src/mips/simulator-mips.cc |
| +++ b/src/mips/simulator-mips.cc |
| @@ -968,7 +968,12 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { |
| for (int i = 0; i < kNumFPURegisters; i++) { |
| FPUregisters_[i] = 0; |
| } |
| - FCSR_ = 0; |
| + if (IsMipsArchVariant(kMips32r6)) { |
| + FCSR_ = kFCSRNaN2008FlagMask; |
| + } else { |
| + DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
| + FCSR_ = 0; |
| + } |
| // The sp is initialized to point to the bottom (high address) of the |
| // allocated stack area. To be safe in potential stack underflows we leave |
| @@ -1296,6 +1301,125 @@ unsigned int Simulator::get_fcsr_rounding_mode() { |
| } |
| +void Simulator::set_fpu_register_word_invalid_result(float original, |
| + float rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int32 = std::numeric_limits<int32_t>::max(); |
| + double min_int32 = std::numeric_limits<int32_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register_word(fd_reg(), 0); |
| + } else if (rounded > max_int32) { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + } else if (rounded < min_int32) { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + } |
| +} |
| + |
| + |
| +void Simulator::set_fpu_register_invalid_result(float original, float rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int32 = std::numeric_limits<int32_t>::max(); |
| + double min_int32 = std::numeric_limits<int32_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register(fd_reg(), 0); |
| + } else if (rounded > max_int32) { |
| + set_fpu_register(fd_reg(), kFPUInvalidResult); |
| + } else if (rounded < min_int32) { |
| + set_fpu_register(fd_reg(), kFPUInvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register(fd_reg(), kFPUInvalidResult); |
| + } |
| +} |
| + |
| + |
| +void Simulator::set_fpu_register_invalid_result64(float original, |
| + float rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int64 = std::numeric_limits<int64_t>::max(); |
| + double min_int64 = std::numeric_limits<int64_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register(fd_reg(), 0); |
| + } else if (rounded > max_int64) { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + } else if (rounded < min_int64) { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + } |
| +} |
| + |
| + |
| +void Simulator::set_fpu_register_word_invalid_result(double original, |
| + double rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int32 = std::numeric_limits<int32_t>::max(); |
| + double min_int32 = std::numeric_limits<int32_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register_word(fd_reg(), 0); |
| + } else if (rounded > max_int32) { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + } else if (rounded < min_int32) { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + } |
| +} |
| + |
| + |
| +void Simulator::set_fpu_register_invalid_result(double original, |
| + double rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int32 = std::numeric_limits<int32_t>::max(); |
| + double min_int32 = std::numeric_limits<int32_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register(fd_reg(), 0); |
| + } else if (rounded > max_int32) { |
| + set_fpu_register(fd_reg(), kFPUInvalidResult); |
| + } else if (rounded < min_int32) { |
| + set_fpu_register(fd_reg(), kFPUInvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register(fd_reg(), kFPUInvalidResult); |
| + } |
| +} |
| + |
| + |
| +void Simulator::set_fpu_register_invalid_result64(double original, |
| + double rounded) { |
| + if (FCSR_ & kFCSRNaN2008FlagMask) { |
| + double max_int64 = std::numeric_limits<int64_t>::max(); |
| + double min_int64 = std::numeric_limits<int64_t>::min(); |
| + if (std::isnan(original)) { |
| + set_fpu_register(fd_reg(), 0); |
| + } else if (rounded > max_int64) { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + } else if (rounded < min_int64) { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); |
| + } else { |
| + UNREACHABLE(); |
| + } |
| + } else { |
| + set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + } |
| +} |
| + |
| + |
| // Sets the rounding error codes in FCSR based on the result of the rounding. |
| // Returns true if the operation was invalid. |
| bool Simulator::set_fcsr_round_error(double original, double rounded) { |
| @@ -1450,8 +1574,10 @@ void Simulator::round_according_to_fcsr(double toRound, double& rounded, |
| } |
| break; |
| case kRoundToZero: |
| + printf("kRoundToZero"); |
| rounded = trunc(fs); |
| rounded_int = static_cast<int32_t>(rounded); |
| + printf("Rounded int = %d\n", rounded_int); |
|
paul.l...
2015/12/02 02:49:51
Leftover debugging prints? Please remove, here and
|
| break; |
| case kRoundToPlusInf: |
| rounded = std::ceil(fs); |
| @@ -2415,7 +2541,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| round_according_to_fcsr(fs, rounded, result, fs); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case ROUND_W_D: // Round double to word (round half to even). |
| @@ -2429,7 +2555,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| } |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case TRUNC_W_D: // Truncate double to word (round towards 0). |
| @@ -2438,7 +2564,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case FLOOR_W_D: // Round double to word towards negative infinity. |
| @@ -2447,7 +2573,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case CEIL_W_D: // Round double to word towards positive infinity. |
| @@ -2456,7 +2582,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case CVT_S_D: // Convert double to float (single). |
| @@ -2469,7 +2595,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| round64_according_to_fcsr(fs, rounded, result, fs); |
| set_fpu_register(fd_reg(), result); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2484,7 +2610,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2504,7 +2630,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2518,7 +2644,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2532,7 +2658,7 @@ void Simulator::DecodeTypeRegisterDRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2935,7 +3061,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case TRUNC_L_S: { // Mips32r2 instruction. |
| @@ -2945,7 +3071,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2958,7 +3084,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case FLOOR_L_S: { // Mips32r2 instruction. |
| @@ -2968,7 +3094,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -2985,7 +3111,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| } |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| break; |
| } |
| @@ -3002,7 +3128,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -3015,7 +3141,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| int32_t result = static_cast<int32_t>(rounded); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| } break; |
| case CEIL_L_S: { // Mips32r2 instruction. |
| @@ -3025,7 +3151,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| if (IsFp64Mode()) { |
| set_fpu_register(fd_reg(), i64); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -3107,7 +3233,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| round64_according_to_fcsr(fs, rounded, result, fs); |
| set_fpu_register(fd_reg(), result); |
| if (set_fcsr_round64_error(fs, rounded)) { |
| - set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| + set_fpu_register_invalid_result64(fs, rounded); |
| } |
| } else { |
| UNSUPPORTED(); |
| @@ -3120,7 +3246,7 @@ void Simulator::DecodeTypeRegisterSRsType() { |
| round_according_to_fcsr(fs, rounded, result, fs); |
| set_fpu_register_word(fd_reg(), result); |
| if (set_fcsr_round_error(fs, rounded)) { |
| - set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| + set_fpu_register_word_invalid_result(fs, rounded); |
| } |
| break; |
| } |
| @@ -3249,11 +3375,18 @@ void Simulator::DecodeTypeRegisterCOP1() { |
| case MFHC1: |
| set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
| break; |
| - case CTC1: |
| + case CTC1: { |
| // At the moment only FCSR is supported. |
| DCHECK(fs_reg() == kFCSRRegister); |
| - FCSR_ = registers_[rt_reg()]; |
| + int32_t reg = registers_[rt_reg()]; |
| + if (IsMipsArchVariant(kMips32r6)) { |
| + FCSR_ = reg | kFCSRNaN2008FlagMask; |
| + } else { |
| + DCHECK(IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kMips32r2)); |
| + FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| + } |
| break; |
| + } |
| case MTC1: |
| // Hardware writes upper 32-bits to zero on mtc1. |
| set_fpu_register_hi_word(fs_reg(), 0); |