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

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

Issue 2184843002: MIPS: Add NaN handling to floating point operators in simulators. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix templates. Created 4 years, 3 months 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
« no previous file with comments | « no previous file | src/mips64/simulator-mips64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips/simulator-mips.cc
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index cd16f6aa07de596282d7c6df7c90ab9062e0e269..bfc854cad6c1247d3199fdc7fe989348b7a24f81 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -2366,6 +2366,49 @@ static T FPUMaxA(T a, T b) {
return result;
}
+enum class KeepSign : bool { no = false, yes };
+
+template <typename T, typename std::enable_if<std::is_floating_point<T>::value,
+ int>::type = 0>
+T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) {
+ DCHECK(std::isnan(arg));
+ T qNaN = std::numeric_limits<T>::quiet_NaN();
+ if (keepSign == KeepSign::yes) {
+ return std::copysign(qNaN, result);
+ }
+ return qNaN;
+}
+
+template <typename T>
+T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) {
+ if (std::isnan(first)) {
+ return FPUCanonalizeNaNArg(result, first, keepSign);
+ }
+ return result;
+}
+
+template <typename T, typename... Args>
+T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) {
+ if (std::isnan(first)) {
+ return FPUCanonalizeNaNArg(result, first, keepSign);
+ }
+ return FPUCanonalizeNaNArgs(result, keepSign, args...);
+}
+
+template <typename Func, typename T, typename... Args>
+T FPUCanonalizeOperation(Func f, T first, Args... args) {
+ return FPUCanonalizeOperation(f, KeepSign::no, first, args...);
+}
+
+template <typename Func, typename T, typename... Args>
+T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) {
+ T result = f(first, args...);
+ if (std::isnan(result)) {
+ result = FPUCanonalizeNaNArgs(result, keepSign, first, args...);
+ }
+ return result;
+}
+
// Handle execution based on instruction types.
void Simulator::DecodeTypeRegisterDRsType() {
@@ -2477,10 +2520,16 @@ void Simulator::DecodeTypeRegisterDRsType() {
set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs));
break;
case ADD_D:
- set_fpu_register_double(fd_reg(), fs + ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs + rhs; }, fs, ft));
break;
case SUB_D:
- set_fpu_register_double(fd_reg(), fs - ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs - rhs; }, fs, ft));
break;
case MADDF_D:
DCHECK(IsMipsArchVariant(kMips32r6));
@@ -2491,37 +2540,45 @@ void Simulator::DecodeTypeRegisterDRsType() {
set_fpu_register_double(fd_reg(), fd - (fs * ft));
break;
case MUL_D:
- set_fpu_register_double(fd_reg(), fs * ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs * rhs; }, fs, ft));
break;
case DIV_D:
- set_fpu_register_double(fd_reg(), fs / ft);
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation(
+ [](double lhs, double rhs) { return lhs / rhs; }, fs, ft));
break;
case ABS_D:
- set_fpu_register_double(fd_reg(), fabs(fs));
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs));
break;
case MOV_D:
set_fpu_register_double(fd_reg(), fs);
break;
case NEG_D:
- set_fpu_register_double(fd_reg(), -fs);
+ set_fpu_register_double(
+ fd_reg(), FPUCanonalizeOperation([](double src) { return -src; },
+ KeepSign::yes, fs));
break;
case SQRT_D:
- lazily_initialize_fast_sqrt(isolate_);
- set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_));
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs));
break;
- case RSQRT_D: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- lazily_initialize_fast_sqrt(isolate_);
- double result = 1.0 / fast_sqrt(fs, isolate_);
- set_fpu_register_double(fd_reg(), result);
+ case RSQRT_D:
+ set_fpu_register_double(
+ fd_reg(), FPUCanonalizeOperation(
+ [](double fs) { return 1.0 / std::sqrt(fs); }, fs));
break;
- }
- case RECIP_D: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- double result = 1.0 / fs;
- set_fpu_register_double(fd_reg(), result);
+ case RECIP_D:
+ set_fpu_register_double(
+ fd_reg(),
+ FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs));
break;
- }
case C_UN_D:
set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
break;
@@ -2890,10 +2947,16 @@ void Simulator::DecodeTypeRegisterSRsType() {
break;
}
case ADD_S:
- set_fpu_register_float(fd_reg(), fs + ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; },
+ fs, ft));
break;
case SUB_S:
- set_fpu_register_float(fd_reg(), fs - ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; },
+ fs, ft));
break;
case MADDF_S:
DCHECK(IsMipsArchVariant(kMips32r6));
@@ -2904,37 +2967,45 @@ void Simulator::DecodeTypeRegisterSRsType() {
set_fpu_register_float(fd_reg(), fd - (fs * ft));
break;
case MUL_S:
- set_fpu_register_float(fd_reg(), fs * ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; },
+ fs, ft));
break;
case DIV_S:
- set_fpu_register_float(fd_reg(), fs / ft);
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; },
+ fs, ft));
break;
case ABS_S:
- set_fpu_register_float(fd_reg(), fabs(fs));
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs));
break;
case MOV_S:
set_fpu_register_float(fd_reg(), fs);
break;
case NEG_S:
- set_fpu_register_float(fd_reg(), -fs);
+ set_fpu_register_float(
+ fd_reg(), FPUCanonalizeOperation([](float src) { return -src; },
+ KeepSign::yes, fs));
break;
case SQRT_S:
- lazily_initialize_fast_sqrt(isolate_);
- set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_));
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs));
break;
- case RSQRT_S: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- lazily_initialize_fast_sqrt(isolate_);
- float result = 1.0 / fast_sqrt(fs, isolate_);
- set_fpu_register_float(fd_reg(), result);
+ case RSQRT_S:
+ set_fpu_register_float(
+ fd_reg(), FPUCanonalizeOperation(
+ [](float src) { return 1.0 / std::sqrt(src); }, fs));
break;
- }
- case RECIP_S: {
- DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6));
- float result = 1.0 / fs;
- set_fpu_register_float(fd_reg(), result);
+ case RECIP_S:
+ set_fpu_register_float(
+ fd_reg(),
+ FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs));
break;
- }
case C_F_D:
set_fcsr_bit(fcsr_cc, false);
break;
« no previous file with comments | « no previous file | src/mips64/simulator-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698