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

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

Issue 1668143002: MIPS: Fix FPU min, max, mina, maxa in simulator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 10 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 | « src/mips/simulator-mips.h ('k') | src/mips64/simulator-mips64.h » ('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 f0d55d938f65552e69fa107f79a78c69f00eb4f5..9fab5aefd597d40ea1027b9cafb33fc4f869ecf0 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -2347,6 +2347,89 @@ void Simulator::SignalException(Exception e) {
static_cast<int>(e));
}
+template <typename T>
+T FPAbs(T a);
+
+template <>
+double FPAbs<double>(double a) {
+ return fabs(a);
+}
+
+template <>
+float FPAbs<float>(float a) {
+ return fabsf(a);
+}
+
+template <typename T>
+bool Simulator::FPUProcessNaNsAndZeros(T a, T b, IsMin min, T& result) {
+ if (std::isnan(a) && std::isnan(b)) {
+ result = a;
+ } else if (std::isnan(a)) {
+ result = b;
+ } else if (std::isnan(b)) {
+ result = a;
+ } else if (b == a) {
+ // Handle -0.0 == 0.0 case.
+ // std::signbit() returns int 0 or 1 so substracting IsMin::kMax negates the
+ // result.
+ result = std::signbit(b) - static_cast<int>(min) ? b : a;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+template <typename T>
+T Simulator::FPUMin(T a, T b) {
+ T result;
+ if (FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) {
+ return result;
+ } else {
+ return b < a ? b : a;
+ }
+}
+
+template <typename T>
+T Simulator::FPUMax(T a, T b) {
+ T result;
+ if (FPUProcessNaNsAndZeros(a, b, IsMin::kMax, result)) {
+ return result;
+ } else {
+ return b > a ? b : a;
+ }
+}
+
+template <typename T>
+T Simulator::FPUMinA(T a, T b) {
+ T result;
+ if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) {
+ if (FPAbs(a) < FPAbs(b)) {
+ result = a;
+ } else if (FPAbs(b) < FPAbs(a)) {
+ result = b;
+ } else {
+ result = a < b ? a : b;
+ }
+ }
+ return result;
+}
+
+template <typename T>
+T Simulator::FPUMaxA(T a, T b) {
+ T result;
+ if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) {
+ if (FPAbs(a) > FPAbs(b)) {
+ result = a;
+ } else if (FPAbs(b) > FPAbs(a)) {
+ result = b;
+ } else {
+ result = a > b ? a : b;
+ }
+ }
+ return result;
+}
+
+// Handle execution based on instruction types.
void Simulator::DecodeTypeRegisterDRsType() {
double ft, fs, fd;
@@ -2442,72 +2525,19 @@ void Simulator::DecodeTypeRegisterDRsType() {
}
case MIN:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else {
- set_fpu_register_double(fd_reg(), (fs >= ft) ? ft : fs);
- }
+ set_fpu_register_double(fd_reg(), FPUMin(ft, fs));
break;
- case MINA:
+ case MAX:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else {
- double result;
- if (fabs(fs) > fabs(ft)) {
- result = ft;
- } else if (fabs(fs) < fabs(ft)) {
- result = fs;
- } else {
- result = (fs < ft ? fs : ft);
- }
- set_fpu_register_double(fd_reg(), result);
- }
+ set_fpu_register_double(fd_reg(), FPUMax(ft, fs));
break;
- case MAXA:
+ case MINA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else {
- double result;
- if (fabs(fs) < fabs(ft)) {
- result = ft;
- } else if (fabs(fs) > fabs(ft)) {
- result = fs;
- } else {
- result = (fs > ft ? fs : ft);
- }
- set_fpu_register_double(fd_reg(), result);
- }
+ set_fpu_register_double(fd_reg(), FPUMinA(ft, fs));
break;
- case MAX:
+ case MAXA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_double(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_double(fd_reg(), fs);
- } else {
- set_fpu_register_double(fd_reg(), (fs <= ft) ? ft : fs);
- }
- break;
+ set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs));
break;
case ADD_D:
set_fpu_register_double(fd_reg(), fs + ft);
@@ -3193,71 +3223,19 @@ void Simulator::DecodeTypeRegisterSRsType() {
}
case MIN:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else {
- set_fpu_register_float(fd_reg(), (fs >= ft) ? ft : fs);
- }
+ set_fpu_register_float(fd_reg(), FPUMin(ft, fs));
break;
case MAX:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else {
- set_fpu_register_float(fd_reg(), (fs <= ft) ? ft : fs);
- }
+ set_fpu_register_float(fd_reg(), FPUMax(ft, fs));
break;
case MINA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else {
- float result;
- if (fabs(fs) > fabs(ft)) {
- result = ft;
- } else if (fabs(fs) < fabs(ft)) {
- result = fs;
- } else {
- result = (fs < ft ? fs : ft);
- }
- set_fpu_register_float(fd_reg(), result);
- }
+ set_fpu_register_float(fd_reg(), FPUMinA(ft, fs));
break;
case MAXA:
DCHECK(IsMipsArchVariant(kMips32r6));
- fs = get_fpu_register_float(fs_reg());
- if (std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else if (std::isnan(fs) && !std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), ft);
- } else if (!std::isnan(fs) && std::isnan(ft)) {
- set_fpu_register_float(fd_reg(), fs);
- } else {
- float result;
- if (fabs(fs) < fabs(ft)) {
- result = ft;
- } else if (fabs(fs) > fabs(ft)) {
- result = fs;
- } else {
- result = (fs > ft ? fs : ft);
- }
- set_fpu_register_float(fd_reg(), result);
- }
+ set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs));
break;
case CVT_L_S: {
if (IsFp64Mode()) {
« no previous file with comments | « src/mips/simulator-mips.h ('k') | src/mips64/simulator-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698