Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Unified Diff: src/mips/simulator-mips.cc

Issue 1488613007: MIPS: Correct handling of Nan values on MIPS R6 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);

Powered by Google App Engine
This is Rietveld 408576698