| 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);
|
|
|