| Index: src/mips64/simulator-mips64.cc
|
| diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc
|
| index 4702e7db44349783c955079b778d3c5b1ca70fde..beabc88e36adc3461de50a09f86768ca203617e3 100644
|
| --- a/src/mips64/simulator-mips64.cc
|
| +++ b/src/mips64/simulator-mips64.cc
|
| @@ -2332,6 +2332,87 @@ 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.
|
|
|
| @@ -2616,71 +2697,19 @@ void Simulator::DecodeTypeRegisterSRsType() {
|
| }
|
| case MINA:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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(kArchVariant == kMips64r6);
|
| - 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 MIN:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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(kArchVariant == kMips64r6);
|
| - 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 SEL:
|
| DCHECK(kArchVariant == kMips64r6);
|
| @@ -2825,71 +2854,19 @@ void Simulator::DecodeTypeRegisterDRsType() {
|
| }
|
| case MINA:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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 MAXA:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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(), FPUMaxA(ft, fs));
|
| break;
|
| case MIN:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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 MAX:
|
| DCHECK(kArchVariant == kMips64r6);
|
| - 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(), FPUMax(ft, fs));
|
| break;
|
| case ADD_D:
|
| set_fpu_register_double(fd_reg(), fs + ft);
|
|
|