| Index: src/mips64/simulator-mips64.cc | 
| diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc | 
| index d1d65ac7113539beed08ce140be71933a5e97d5c..185dbf117e76a83c619a468a98a482d2b000ac6a 100644 | 
| --- a/src/mips64/simulator-mips64.cc | 
| +++ b/src/mips64/simulator-mips64.cc | 
| @@ -898,7 +898,12 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { | 
| for (int i = 0; i < kNumFPURegisters; i++) { | 
| FPUregisters_[i] = 0; | 
| } | 
| -  FCSR_ = 0; | 
| + | 
| +  if (kArchVariant == kMips64r6) { | 
| +    FCSR_ = kFCSRNaN2008FlagMask; | 
| +  } else { | 
| +    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 | 
| @@ -1315,6 +1320,124 @@ bool Simulator::set_fcsr_round_error(float original, float rounded) { | 
| return ret; | 
| } | 
|  | 
| +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. | 
| @@ -2371,7 +2494,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); | 
| } | 
| break; | 
| } | 
| @@ -2381,7 +2504,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; | 
| } | 
| @@ -2390,7 +2513,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: {  // Mips64r2 instruction. | 
| @@ -2398,7 +2521,7 @@ void Simulator::DecodeTypeRegisterSRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2412,7 +2535,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; | 
| } | 
| @@ -2427,7 +2550,7 @@ void Simulator::DecodeTypeRegisterSRsType() { | 
| int64_t i64 = static_cast<int64_t>(result); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2436,7 +2559,7 @@ void Simulator::DecodeTypeRegisterSRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2446,7 +2569,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_W_S:  // Round double to word towards positive infinity. | 
| @@ -2455,7 +2578,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(fd_reg(), kFPUInvalidResult); | 
| +        set_fpu_register_invalid_result(fs, rounded); | 
| } | 
| } break; | 
| case CEIL_L_S: {  // Mips64r2 instruction. | 
| @@ -2463,7 +2586,7 @@ void Simulator::DecodeTypeRegisterSRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2807,7 +2930,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; | 
| } | 
| @@ -2822,7 +2945,7 @@ void Simulator::DecodeTypeRegisterDRsType() { | 
| } | 
| set_fpu_register_word(fd_reg(), result); | 
| if (set_fcsr_round_error(fs, rounded)) { | 
| -        set_fpu_register(fd_reg(), kFPUInvalidResult); | 
| +        set_fpu_register_invalid_result(fs, rounded); | 
| } | 
| } break; | 
| case TRUNC_W_D:  // Truncate double to word (round towards 0). | 
| @@ -2831,7 +2954,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(fd_reg(), kFPUInvalidResult); | 
| +        set_fpu_register_invalid_result(fs, rounded); | 
| } | 
| } break; | 
| case FLOOR_W_D:  // Round double to word towards negative infinity. | 
| @@ -2840,7 +2963,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(fd_reg(), kFPUInvalidResult); | 
| +        set_fpu_register_invalid_result(fs, rounded); | 
| } | 
| } break; | 
| case CEIL_W_D:  // Round double to word towards positive infinity. | 
| @@ -2849,7 +2972,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(fd_reg(), kFPUInvalidResult); | 
| +        set_fpu_register_invalid_result(fs, rounded); | 
| } | 
| } break; | 
| case CVT_S_D:  // Convert double to float (single). | 
| @@ -2861,7 +2984,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); | 
| } | 
| break; | 
| } | 
| @@ -2876,7 +2999,7 @@ void Simulator::DecodeTypeRegisterDRsType() { | 
| int64_t i64 = static_cast<int64_t>(result); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2885,7 +3008,7 @@ void Simulator::DecodeTypeRegisterDRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2894,7 +3017,7 @@ void Simulator::DecodeTypeRegisterDRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -2903,7 +3026,7 @@ void Simulator::DecodeTypeRegisterDRsType() { | 
| int64_t result = static_cast<int64_t>(rounded); | 
| 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); | 
| } | 
| break; | 
| } | 
| @@ -3188,11 +3311,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_ = static_cast<uint32_t>(rt()); | 
| +      uint32_t reg = static_cast<uint32_t>(rt()); | 
| +      if (kArchVariant == kMips64r6) { | 
| +        FCSR_ = reg | kFCSRNaN2008FlagMask; | 
| +      } else { | 
| +        DCHECK(kArchVariant == kMips64r2); | 
| +        FCSR_ = reg & ~kFCSRNaN2008FlagMask; | 
| +      } | 
| break; | 
| +    } | 
| case MTC1: | 
| // Hardware writes upper 32-bits to zero on mtc1. | 
| set_fpu_register_hi_word(fs_reg(), 0); | 
|  |