| Index: src/mips/simulator-mips.cc
|
| diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
|
| index e52b3833b4856fcfd599b40a0348c87ca955c9f2..4de2d5abf06332b503a5a34ecfaa7a503fa4653c 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) {
|
| @@ -2415,7 +2539,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 +2553,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 +2562,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 +2571,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 +2580,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 +2593,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 +2608,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 +2628,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 +2642,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 +2656,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 +3059,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 +3069,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 +3082,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 +3092,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 +3109,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 +3126,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 +3139,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 +3149,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 +3231,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 +3244,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 +3373,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);
|
|
|