| 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()) {
|
|
|