зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset b9b555396153 (bug 1181063)
This commit is contained in:
Родитель
af7ad0b0ba
Коммит
3e0720d267
|
@ -28,16 +28,11 @@
|
||||||
|
|
||||||
#ifdef JS_SIMULATOR_ARM64
|
#ifdef JS_SIMULATOR_ARM64
|
||||||
|
|
||||||
#include "mozilla/FloatingPoint.h"
|
|
||||||
|
|
||||||
#include "jit/arm64/vixl/Simulator-vixl.h"
|
#include "jit/arm64/vixl/Simulator-vixl.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
using mozilla::IsInfinite;
|
|
||||||
using mozilla::IsNaN;
|
|
||||||
|
|
||||||
namespace vixl {
|
namespace vixl {
|
||||||
|
|
||||||
const Instruction* Simulator::kEndOfSimAddress = NULL;
|
const Instruction* Simulator::kEndOfSimAddress = NULL;
|
||||||
|
@ -369,7 +364,7 @@ void Simulator::FPCompare(double val0, double val1) {
|
||||||
|
|
||||||
// TODO: This assumes that the C++ implementation handles comparisons in the
|
// TODO: This assumes that the C++ implementation handles comparisons in the
|
||||||
// way that we expect (as per AssertSupportedFPCR()).
|
// way that we expect (as per AssertSupportedFPCR()).
|
||||||
if (IsNaN(val0) || IsNaN(val1)) {
|
if ((isnan(val0) != 0) || (isnan(val1) != 0)) {
|
||||||
nzcv().SetRawValue(FPUnorderedFlag);
|
nzcv().SetRawValue(FPUnorderedFlag);
|
||||||
} else if (val0 < val1) {
|
} else if (val0 < val1) {
|
||||||
nzcv().SetRawValue(FPLessThanFlag);
|
nzcv().SetRawValue(FPLessThanFlag);
|
||||||
|
@ -1772,7 +1767,7 @@ int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
|
||||||
} else if (value < kWMinInt) {
|
} else if (value < kWMinInt) {
|
||||||
return kWMinInt;
|
return kWMinInt;
|
||||||
}
|
}
|
||||||
return IsNaN(value) ? 0 : static_cast<int32_t>(value);
|
return isnan(value) ? 0 : static_cast<int32_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1783,7 +1778,7 @@ int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
|
||||||
} else if (value < kXMinInt) {
|
} else if (value < kXMinInt) {
|
||||||
return kXMinInt;
|
return kXMinInt;
|
||||||
}
|
}
|
||||||
return IsNaN(value) ? 0 : static_cast<int64_t>(value);
|
return isnan(value) ? 0 : static_cast<int64_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1794,7 +1789,7 @@ uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
|
||||||
} else if (value < 0.0) {
|
} else if (value < 0.0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return IsNaN(value) ? 0 : static_cast<uint32_t>(value);
|
return isnan(value) ? 0 : static_cast<uint32_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1805,7 +1800,7 @@ uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
|
||||||
} else if (value < 0.0) {
|
} else if (value < 0.0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return IsNaN(value) ? 0 : static_cast<uint64_t>(value);
|
return isnan(value) ? 0 : static_cast<uint64_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1899,14 +1894,14 @@ void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
|
||||||
float input = sreg(fn);
|
float input = sreg(fn);
|
||||||
float rounded = FPRoundInt(input, fpcr_rounding);
|
float rounded = FPRoundInt(input, fpcr_rounding);
|
||||||
set_sreg(fd, rounded);
|
set_sreg(fd, rounded);
|
||||||
if (!IsNaN(input) && (input != rounded)) FPProcessException();
|
if (!isnan(input) && (input != rounded)) FPProcessException();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FRINTX_d: {
|
case FRINTX_d: {
|
||||||
double input = dreg(fn);
|
double input = dreg(fn);
|
||||||
double rounded = FPRoundInt(input, fpcr_rounding);
|
double rounded = FPRoundInt(input, fpcr_rounding);
|
||||||
set_dreg(fd, rounded);
|
set_dreg(fd, rounded);
|
||||||
if (!IsNaN(input) && (input != rounded)) FPProcessException();
|
if (!isnan(input) && (input != rounded)) FPProcessException();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
|
case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
|
||||||
|
@ -2165,7 +2160,7 @@ double Simulator::FPRoundInt(double value, FPRounding round_mode) {
|
||||||
if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
|
if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
|
||||||
(value == kFP64NegativeInfinity)) {
|
(value == kFP64NegativeInfinity)) {
|
||||||
return value;
|
return value;
|
||||||
} else if (IsNaN(value)) {
|
} else if (isnan(value)) {
|
||||||
return FPProcessNaN(value);
|
return FPProcessNaN(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2397,9 +2392,9 @@ void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPAdd(T op1, T op2) {
|
T Simulator::FPAdd(T op1, T op2) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(op1) && !IsNaN(op2));
|
VIXL_ASSERT(!isnan(op1) && !isnan(op2));
|
||||||
|
|
||||||
if (IsInfinite(op1) && IsInfinite(op2) && (op1 != op2)) {
|
if (isinf(op1) && isinf(op2) && (op1 != op2)) {
|
||||||
// inf + -inf returns the default NaN.
|
// inf + -inf returns the default NaN.
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
return FPDefaultNaN<T>();
|
return FPDefaultNaN<T>();
|
||||||
|
@ -2413,9 +2408,9 @@ T Simulator::FPAdd(T op1, T op2) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPDiv(T op1, T op2) {
|
T Simulator::FPDiv(T op1, T op2) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(op1) && !IsNaN(op2));
|
VIXL_ASSERT(!isnan(op1) && !isnan(op2));
|
||||||
|
|
||||||
if ((IsInfinite(op1) && IsInfinite(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
|
if ((isinf(op1) && isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
|
||||||
// inf / inf and 0.0 / 0.0 return the default NaN.
|
// inf / inf and 0.0 / 0.0 return the default NaN.
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
return FPDefaultNaN<T>();
|
return FPDefaultNaN<T>();
|
||||||
|
@ -2431,7 +2426,7 @@ T Simulator::FPDiv(T op1, T op2) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPMax(T a, T b) {
|
T Simulator::FPMax(T a, T b) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(a) && !IsNaN(b));
|
VIXL_ASSERT(!isnan(a) && !isnan(b));
|
||||||
|
|
||||||
if ((a == 0.0) && (b == 0.0) &&
|
if ((a == 0.0) && (b == 0.0) &&
|
||||||
(copysign(1.0, a) != copysign(1.0, b))) {
|
(copysign(1.0, a) != copysign(1.0, b))) {
|
||||||
|
@ -2452,14 +2447,14 @@ T Simulator::FPMaxNM(T a, T b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
T result = FPProcessNaNs(a, b);
|
T result = FPProcessNaNs(a, b);
|
||||||
return IsNaN(result) ? result : FPMax(a, b);
|
return isnan(result) ? result : FPMax(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPMin(T a, T b) {
|
T Simulator::FPMin(T a, T b) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(a) && !IsNaN(b));
|
VIXL_ASSERT(!isnan(a) && !isnan(b));
|
||||||
|
|
||||||
if ((a == 0.0) && (b == 0.0) &&
|
if ((a == 0.0) && (b == 0.0) &&
|
||||||
(copysign(1.0, a) != copysign(1.0, b))) {
|
(copysign(1.0, a) != copysign(1.0, b))) {
|
||||||
|
@ -2480,16 +2475,16 @@ T Simulator::FPMinNM(T a, T b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
T result = FPProcessNaNs(a, b);
|
T result = FPProcessNaNs(a, b);
|
||||||
return IsNaN(result) ? result : FPMin(a, b);
|
return isnan(result) ? result : FPMin(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPMul(T op1, T op2) {
|
T Simulator::FPMul(T op1, T op2) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(op1) && !IsNaN(op2));
|
VIXL_ASSERT(!isnan(op1) && !isnan(op2));
|
||||||
|
|
||||||
if ((IsInfinite(op1) && (op2 == 0.0)) || (IsInfinite(op2) && (op1 == 0.0))) {
|
if ((isinf(op1) && (op2 == 0.0)) || (isinf(op2) && (op1 == 0.0))) {
|
||||||
// inf * 0.0 returns the default NaN.
|
// inf * 0.0 returns the default NaN.
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
return FPDefaultNaN<T>();
|
return FPDefaultNaN<T>();
|
||||||
|
@ -2506,13 +2501,13 @@ T Simulator::FPMulAdd(T a, T op1, T op2) {
|
||||||
|
|
||||||
T sign_a = copysign(1.0, a);
|
T sign_a = copysign(1.0, a);
|
||||||
T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
|
T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
|
||||||
bool isinf_prod = IsInfinite(op1) || IsInfinite(op2);
|
bool isinf_prod = isinf(op1) || isinf(op2);
|
||||||
bool operation_generates_nan =
|
bool operation_generates_nan =
|
||||||
(IsInfinite(op1) && (op2 == 0.0)) || // inf * 0.0
|
(isinf(op1) && (op2 == 0.0)) || // inf * 0.0
|
||||||
(IsInfinite(op2) && (op1 == 0.0)) || // 0.0 * inf
|
(isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
|
||||||
(IsInfinite(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
|
(isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
|
||||||
|
|
||||||
if (IsNaN(result)) {
|
if (isnan(result)) {
|
||||||
// Generated NaNs override quiet NaNs propagated from a.
|
// Generated NaNs override quiet NaNs propagated from a.
|
||||||
if (operation_generates_nan && IsQuietNaN(a)) {
|
if (operation_generates_nan && IsQuietNaN(a)) {
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
|
@ -2535,7 +2530,7 @@ T Simulator::FPMulAdd(T a, T op1, T op2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
result = FusedMultiplyAdd(op1, op2, a);
|
result = FusedMultiplyAdd(op1, op2, a);
|
||||||
VIXL_ASSERT(!IsNaN(result));
|
VIXL_ASSERT(!isnan(result));
|
||||||
|
|
||||||
// Work around broken fma implementations for rounded zero results: If a is
|
// Work around broken fma implementations for rounded zero results: If a is
|
||||||
// 0.0, the sign of the result is the sign of op1 * op2 before rounding.
|
// 0.0, the sign of the result is the sign of op1 * op2 before rounding.
|
||||||
|
@ -2550,9 +2545,9 @@ T Simulator::FPMulAdd(T a, T op1, T op2) {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPSub(T op1, T op2) {
|
T Simulator::FPSub(T op1, T op2) {
|
||||||
// NaNs should be handled elsewhere.
|
// NaNs should be handled elsewhere.
|
||||||
VIXL_ASSERT(!IsNaN(op1) && !IsNaN(op2));
|
VIXL_ASSERT(!isnan(op1) && !isnan(op2));
|
||||||
|
|
||||||
if (IsInfinite(op1) && IsInfinite(op2) && (op1 == op2)) {
|
if (isinf(op1) && isinf(op2) && (op1 == op2)) {
|
||||||
// inf - inf returns the default NaN.
|
// inf - inf returns the default NaN.
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
return FPDefaultNaN<T>();
|
return FPDefaultNaN<T>();
|
||||||
|
@ -2565,7 +2560,7 @@ T Simulator::FPSub(T op1, T op2) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPSqrt(T op) {
|
T Simulator::FPSqrt(T op) {
|
||||||
if (IsNaN(op)) {
|
if (isnan(op)) {
|
||||||
return FPProcessNaN(op);
|
return FPProcessNaN(op);
|
||||||
} else if (op < 0.0) {
|
} else if (op < 0.0) {
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
|
@ -2578,7 +2573,7 @@ T Simulator::FPSqrt(T op) {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T Simulator::FPProcessNaN(T op) {
|
T Simulator::FPProcessNaN(T op) {
|
||||||
VIXL_ASSERT(IsNaN(op));
|
VIXL_ASSERT(isnan(op));
|
||||||
if (IsSignallingNaN(op)) {
|
if (IsSignallingNaN(op)) {
|
||||||
FPProcessException();
|
FPProcessException();
|
||||||
}
|
}
|
||||||
|
@ -2592,10 +2587,10 @@ T Simulator::FPProcessNaNs(T op1, T op2) {
|
||||||
return FPProcessNaN(op1);
|
return FPProcessNaN(op1);
|
||||||
} else if (IsSignallingNaN(op2)) {
|
} else if (IsSignallingNaN(op2)) {
|
||||||
return FPProcessNaN(op2);
|
return FPProcessNaN(op2);
|
||||||
} else if (IsNaN(op1)) {
|
} else if (isnan(op1)) {
|
||||||
VIXL_ASSERT(IsQuietNaN(op1));
|
VIXL_ASSERT(IsQuietNaN(op1));
|
||||||
return FPProcessNaN(op1);
|
return FPProcessNaN(op1);
|
||||||
} else if (IsNaN(op2)) {
|
} else if (isnan(op2)) {
|
||||||
VIXL_ASSERT(IsQuietNaN(op2));
|
VIXL_ASSERT(IsQuietNaN(op2));
|
||||||
return FPProcessNaN(op2);
|
return FPProcessNaN(op2);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2612,13 +2607,13 @@ T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
|
||||||
return FPProcessNaN(op2);
|
return FPProcessNaN(op2);
|
||||||
} else if (IsSignallingNaN(op3)) {
|
} else if (IsSignallingNaN(op3)) {
|
||||||
return FPProcessNaN(op3);
|
return FPProcessNaN(op3);
|
||||||
} else if (IsNaN(op1)) {
|
} else if (isnan(op1)) {
|
||||||
VIXL_ASSERT(IsQuietNaN(op1));
|
VIXL_ASSERT(IsQuietNaN(op1));
|
||||||
return FPProcessNaN(op1);
|
return FPProcessNaN(op1);
|
||||||
} else if (IsNaN(op2)) {
|
} else if (isnan(op2)) {
|
||||||
VIXL_ASSERT(IsQuietNaN(op2));
|
VIXL_ASSERT(IsQuietNaN(op2));
|
||||||
return FPProcessNaN(op2);
|
return FPProcessNaN(op2);
|
||||||
} else if (IsNaN(op3)) {
|
} else if (isnan(op3)) {
|
||||||
VIXL_ASSERT(IsQuietNaN(op3));
|
VIXL_ASSERT(IsQuietNaN(op3));
|
||||||
return FPProcessNaN(op3);
|
return FPProcessNaN(op3);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2635,13 +2630,13 @@ bool Simulator::FPProcessNaNs(const Instruction* instr) {
|
||||||
|
|
||||||
if (instr->Mask(FP64) == FP64) {
|
if (instr->Mask(FP64) == FP64) {
|
||||||
double result = FPProcessNaNs(dreg(fn), dreg(fm));
|
double result = FPProcessNaNs(dreg(fn), dreg(fm));
|
||||||
if (IsNaN(result)) {
|
if (isnan(result)) {
|
||||||
set_dreg(fd, result);
|
set_dreg(fd, result);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
float result = FPProcessNaNs(sreg(fn), sreg(fm));
|
float result = FPProcessNaNs(sreg(fn), sreg(fm));
|
||||||
if (IsNaN(result)) {
|
if (isnan(result)) {
|
||||||
set_sreg(fd, result);
|
set_sreg(fd, result);
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче