| Index: src/mips/simulator-mips.cc
 | 
| ===================================================================
 | 
| --- src/mips/simulator-mips.cc	(revision 8174)
 | 
| +++ src/mips/simulator-mips.cc	(working copy)
 | 
| @@ -1159,15 +1159,30 @@
 | 
|  // 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) {
 | 
| -  if (!isfinite(original) ||
 | 
| -      rounded > LONG_MAX ||
 | 
| -      rounded < LONG_MIN) {
 | 
| -    set_fcsr_bit(6, true);  // Invalid operation.
 | 
| -    return true;
 | 
| -  } else if (original != static_cast<double>(rounded)) {
 | 
| -    set_fcsr_bit(2, true);  // Inexact.
 | 
| +  bool ret = false;
 | 
| +
 | 
| +  if (!isfinite(original) || !isfinite(rounded)) {
 | 
| +    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
 | 
| +    ret = true;
 | 
|    }
 | 
| -  return false;
 | 
| +
 | 
| +  if (original != rounded) {
 | 
| +    set_fcsr_bit(kFCSRInexactFlagBit, true);
 | 
| +  }
 | 
| +
 | 
| +  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
 | 
| +    set_fcsr_bit(kFCSRUnderflowFlagBit, true);
 | 
| +    ret = true;
 | 
| +  }
 | 
| +
 | 
| +  if (rounded > INT_MAX || rounded < INT_MIN) {
 | 
| +    set_fcsr_bit(kFCSROverflowFlagBit, true);
 | 
| +    // The reference is not really clear but it seems this is required:
 | 
| +    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
 | 
| +    ret = true;
 | 
| +  }
 | 
| +
 | 
| +  return ret;
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2054,9 +2069,10 @@
 | 
|                break;
 | 
|              case TRUNC_W_D:  // Truncate double to word (round towards 0).
 | 
|                {
 | 
| -                int32_t result = static_cast<int32_t>(fs);
 | 
| +                double rounded = trunc(fs);
 | 
| +                int32_t result = static_cast<int32_t>(rounded);
 | 
|                  set_fpu_register(fd_reg, result);
 | 
| -                if (set_fcsr_round_error(fs, static_cast<double>(result))) {
 | 
| +                if (set_fcsr_round_error(fs, rounded)) {
 | 
|                    set_fpu_register(fd_reg, kFPUInvalidResult);
 | 
|                  }
 | 
|                }
 | 
| @@ -2084,16 +2100,20 @@
 | 
|              case CVT_S_D:  // Convert double to float (single).
 | 
|                set_fpu_register_float(fd_reg, static_cast<float>(fs));
 | 
|                break;
 | 
| -            case CVT_L_D:  // Mips32r2: Truncate double to 64-bit long-word.
 | 
| -              i64 = static_cast<int64_t>(fs);
 | 
| +            case CVT_L_D: {  // Mips32r2: Truncate double to 64-bit long-word.
 | 
| +              double rounded = trunc(fs);
 | 
| +              i64 = static_cast<int64_t>(rounded);
 | 
|                set_fpu_register(fd_reg, i64 & 0xffffffff);
 | 
|                set_fpu_register(fd_reg + 1, i64 >> 32);
 | 
|                break;
 | 
| -            case TRUNC_L_D:  // Mips32r2 instruction.
 | 
| -              i64 = static_cast<int64_t>(fs);
 | 
| +            }
 | 
| +            case TRUNC_L_D: {  // Mips32r2 instruction.
 | 
| +              double rounded = trunc(fs);
 | 
| +              i64 = static_cast<int64_t>(rounded);
 | 
|                set_fpu_register(fd_reg, i64 & 0xffffffff);
 | 
|                set_fpu_register(fd_reg + 1, i64 >> 32);
 | 
|                break;
 | 
| +            }
 | 
|              case ROUND_L_D: {  // Mips32r2 instruction.
 | 
|                double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
 | 
|                i64 = static_cast<int64_t>(rounded);
 | 
| 
 |