aboutsummaryrefslogtreecommitdiff
path: root/fpu
diff options
context:
space:
mode:
Diffstat (limited to 'fpu')
-rw-r--r--fpu/softfloat-native.c6
-rw-r--r--fpu/softfloat-native.h6
-rw-r--r--fpu/softfloat-specialize.h374
-rw-r--r--fpu/softfloat.c104
-rw-r--r--fpu/softfloat.h43
5 files changed, 399 insertions, 134 deletions
diff --git a/fpu/softfloat-native.c b/fpu/softfloat-native.c
index 049c8300f5..008bb53cec 100644
--- a/fpu/softfloat-native.c
+++ b/fpu/softfloat-native.c
@@ -254,7 +254,7 @@ int float32_is_signaling_nan( float32 a1)
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
-int float32_is_nan( float32 a1 )
+int float32_is_quiet_nan( float32 a1 )
{
float32u u;
uint64_t a;
@@ -411,7 +411,7 @@ int float64_is_signaling_nan( float64 a1)
}
-int float64_is_nan( float64 a1 )
+int float64_is_quiet_nan( float64 a1 )
{
float64u u;
uint64_t a;
@@ -504,7 +504,7 @@ int floatx80_is_signaling_nan( floatx80 a1)
&& ( u.i.low == aLow );
}
-int floatx80_is_nan( floatx80 a1 )
+int floatx80_is_quiet_nan( floatx80 a1 )
{
floatx80u u;
u.f = a1;
diff --git a/fpu/softfloat-native.h b/fpu/softfloat-native.h
index 6da0bcbbea..80b5f288e3 100644
--- a/fpu/softfloat-native.h
+++ b/fpu/softfloat-native.h
@@ -242,7 +242,7 @@ INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
-int float32_is_nan( float32 );
+int float32_is_quiet_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
@@ -351,7 +351,7 @@ INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
-int float64_is_nan( float64 );
+int float64_is_quiet_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
@@ -455,7 +455,7 @@ INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
-int floatx80_is_nan( floatx80 );
+int floatx80_is_quiet_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 07468786f9..f293f24356 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
-#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
+#if defined(TARGET_MIPS)
#define SNAN_BIT_IS_ONE 1
#else
#define SNAN_BIT_IS_ONE 0
@@ -61,10 +61,8 @@ typedef struct {
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
#define float32_default_nan make_float32(0x7FFFFFFF)
-#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#define float32_default_nan make_float32(0x7FC00000)
-#elif defined(TARGET_HPPA)
-#define float32_default_nan make_float32(0x7FA00000)
#elif SNAN_BIT_IS_ONE
#define float32_default_nan make_float32(0x7FBFFFFF)
#else
@@ -76,7 +74,7 @@ typedef struct {
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float32_is_nan( float32 a_ )
+int float32_is_quiet_nan( float32 a_ )
{
uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE
@@ -109,13 +107,17 @@ int float32_is_signaling_nan( float32 a_ )
float32 float32_maybe_silence_nan( float32 a_ )
{
if (float32_is_signaling_nan(a_)) {
- uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE
- a &= ~(1 << 22);
+# if defined(TARGET_MIPS)
+ return float32_default_nan;
+# else
+# error Rules for silencing a signaling NaN are target-specific
+# endif
#else
+ bits32 a = float32_val(a_);
a |= (1 << 22);
-#endif
return make_float32(a);
+#endif
}
return a_;
}
@@ -153,6 +155,118 @@ static float32 commonNaNToFloat32( commonNaNT a )
}
/*----------------------------------------------------------------------------
+| Select which NaN to propagate for a two-input operation.
+| IEEE754 doesn't specify all the details of this, so the
+| algorithm is target-specific.
+| The routine is passed various bits of information about the
+| two NaNs and should return 0 to select NaN a and 1 for NaN b.
+| Note that signalling NaNs are always squashed to quiet NaNs
+| by the caller, by calling floatXX_maybe_silence_nan() before
+| returning them.
+|
+| aIsLargerSignificand is only valid if both a and b are NaNs
+| of some kind, and is true if a has the larger significand,
+| or if both a and b have the same significand but a is
+| positive but b is negative. It is only needed for the x87
+| tie-break rule.
+*----------------------------------------------------------------------------*/
+
+#if defined(TARGET_ARM)
+static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+ flag aIsLargerSignificand)
+{
+ /* ARM mandated NaN propagation rules: take the first of:
+ * 1. A if it is signaling
+ * 2. B if it is signaling
+ * 3. A (quiet)
+ * 4. B (quiet)
+ * A signaling NaN is always quietened before returning it.
+ */
+ if (aIsSNaN) {
+ return 0;
+ } else if (bIsSNaN) {
+ return 1;
+ } else if (aIsQNaN) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#elif defined(TARGET_MIPS)
+static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+ flag aIsLargerSignificand)
+{
+ /* According to MIPS specifications, if one of the two operands is
+ * a sNaN, a new qNaN has to be generated. This is done in
+ * floatXX_maybe_silence_nan(). For qNaN inputs the specifications
+ * says: "When possible, this QNaN result is one of the operand QNaN
+ * values." In practice it seems that most implementations choose
+ * the first operand if both operands are qNaN. In short this gives
+ * the following rules:
+ * 1. A if it is signaling
+ * 2. B if it is signaling
+ * 3. A (quiet)
+ * 4. B (quiet)
+ * A signaling NaN is always silenced before returning it.
+ */
+ if (aIsSNaN) {
+ return 0;
+ } else if (bIsSNaN) {
+ return 1;
+ } else if (aIsQNaN) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#elif defined(TARGET_PPC)
+static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+ flag aIsLargerSignificand)
+{
+ /* PowerPC propagation rules:
+ * 1. A if it sNaN or qNaN
+ * 2. B if it sNaN or qNaN
+ * A signaling NaN is always silenced before returning it.
+ */
+ if (aIsSNaN || aIsQNaN) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#else
+static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+ flag aIsLargerSignificand)
+{
+ /* This implements x87 NaN propagation rules:
+ * SNaN + QNaN => return the QNaN
+ * two SNaNs => return the one with the larger significand, silenced
+ * two QNaNs => return the one with the larger significand
+ * SNaN and a non-NaN => return the SNaN, silenced
+ * QNaN and a non-NaN => return the QNaN
+ *
+ * If we get down to comparing significands and they are the same,
+ * return the NaN with the positive sign bit (if any).
+ */
+ if (aIsSNaN) {
+ if (bIsSNaN) {
+ return aIsLargerSignificand ? 0 : 1;
+ }
+ return bIsQNaN ? 1 : 0;
+ }
+ else if (aIsQNaN) {
+ if (bIsSNaN || !bIsQNaN)
+ return 0;
+ else {
+ return aIsLargerSignificand ? 0 : 1;
+ }
+ } else {
+ return 1;
+ }
+}
+#endif
+
+/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
@@ -160,47 +274,36 @@ static float32 commonNaNToFloat32( commonNaNT a )
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{
- flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
- bits32 av, bv, res;
+ flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
+ flag aIsLargerSignificand;
+ bits32 av, bv;
if ( STATUS(default_nan_mode) )
return float32_default_nan;
- aIsNaN = float32_is_nan( a );
+ aIsQuietNaN = float32_is_quiet_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
- bIsNaN = float32_is_nan( b );
+ bIsQuietNaN = float32_is_quiet_nan( b );
bIsSignalingNaN = float32_is_signaling_nan( b );
av = float32_val(a);
bv = float32_val(b);
-#if SNAN_BIT_IS_ONE
- av &= ~0x00400000;
- bv &= ~0x00400000;
-#else
- av |= 0x00400000;
- bv |= 0x00400000;
-#endif
+
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
- if ( aIsSignalingNaN ) {
- if ( bIsSignalingNaN ) goto returnLargerSignificand;
- res = bIsNaN ? bv : av;
- }
- else if ( aIsNaN ) {
- if ( bIsSignalingNaN || ! bIsNaN )
- res = av;
- else {
- returnLargerSignificand:
- if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
- res = bv;
- else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
- res = av;
- else
- res = ( av < bv ) ? av : bv;
- }
+
+ if ((bits32)(av<<1) < (bits32)(bv<<1)) {
+ aIsLargerSignificand = 0;
+ } else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
+ aIsLargerSignificand = 1;
+ } else {
+ aIsLargerSignificand = (av < bv) ? 1 : 0;
}
- else {
- res = bv;
+
+ if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
+ aIsLargerSignificand)) {
+ return float32_maybe_silence_nan(b);
+ } else {
+ return float32_maybe_silence_nan(a);
}
- return make_float32(res);
}
/*----------------------------------------------------------------------------
@@ -208,10 +311,8 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
-#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
+#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
-#elif defined(TARGET_HPPA)
-#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
#elif SNAN_BIT_IS_ONE
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
#else
@@ -223,7 +324,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float64_is_nan( float64 a_ )
+int float64_is_quiet_nan( float64 a_ )
{
bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE
@@ -260,13 +361,17 @@ int float64_is_signaling_nan( float64 a_ )
float64 float64_maybe_silence_nan( float64 a_ )
{
if (float64_is_signaling_nan(a_)) {
- bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE
- a &= ~LIT64( 0x0008000000000000 );
+# if defined(TARGET_MIPS)
+ return float64_default_nan;
+# else
+# error Rules for silencing a signaling NaN are target-specific
+# endif
#else
+ bits64 a = float64_val(a_);
a |= LIT64( 0x0008000000000000 );
-#endif
return make_float64(a);
+#endif
}
return a_;
}
@@ -314,47 +419,36 @@ static float64 commonNaNToFloat64( commonNaNT a )
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{
- flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
- bits64 av, bv, res;
+ flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
+ flag aIsLargerSignificand;
+ bits64 av, bv;
if ( STATUS(default_nan_mode) )
return float64_default_nan;
- aIsNaN = float64_is_nan( a );
+ aIsQuietNaN = float64_is_quiet_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
- bIsNaN = float64_is_nan( b );
+ bIsQuietNaN = float64_is_quiet_nan( b );
bIsSignalingNaN = float64_is_signaling_nan( b );
av = float64_val(a);
bv = float64_val(b);
-#if SNAN_BIT_IS_ONE
- av &= ~LIT64( 0x0008000000000000 );
- bv &= ~LIT64( 0x0008000000000000 );
-#else
- av |= LIT64( 0x0008000000000000 );
- bv |= LIT64( 0x0008000000000000 );
-#endif
+
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
- if ( aIsSignalingNaN ) {
- if ( bIsSignalingNaN ) goto returnLargerSignificand;
- res = bIsNaN ? bv : av;
- }
- else if ( aIsNaN ) {
- if ( bIsSignalingNaN || ! bIsNaN )
- res = av;
- else {
- returnLargerSignificand:
- if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
- res = bv;
- else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
- res = av;
- else
- res = ( av < bv ) ? av : bv;
- }
+
+ if ((bits64)(av<<1) < (bits64)(bv<<1)) {
+ aIsLargerSignificand = 0;
+ } else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
+ aIsLargerSignificand = 1;
+ } else {
+ aIsLargerSignificand = (av < bv) ? 1 : 0;
}
- else {
- res = bv;
+
+ if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
+ aIsLargerSignificand)) {
+ return float64_maybe_silence_nan(b);
+ } else {
+ return float64_maybe_silence_nan(a);
}
- return make_float64(res);
}
#ifdef FLOATX80
@@ -377,7 +471,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
| quiet NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int floatx80_is_nan( floatx80 a )
+int floatx80_is_quiet_nan( floatx80 a )
{
#if SNAN_BIT_IS_ONE
bits64 aLow;
@@ -413,6 +507,29 @@ int floatx80_is_signaling_nan( floatx80 a )
}
/*----------------------------------------------------------------------------
+| Returns a quiet NaN if the extended double-precision floating point value
+| `a' is a signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+
+floatx80 floatx80_maybe_silence_nan( floatx80 a )
+{
+ if (floatx80_is_signaling_nan(a)) {
+#if SNAN_BIT_IS_ONE
+# if defined(TARGET_MIPS)
+ a.low = floatx80_default_nan_low;
+ a.high = floatx80_default_nan_high;
+# else
+# error Rules for silencing a signaling NaN are target-specific
+# endif
+#else
+ a.low |= LIT64( 0xC000000000000000 );
+ return a;
+#endif
+ }
+ return a;
+}
+
+/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
| invalid exception is raised.
@@ -454,7 +571,8 @@ static floatx80 commonNaNToFloatx80( commonNaNT a )
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
{
- flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+ flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
+ flag aIsLargerSignificand;
if ( STATUS(default_nan_mode) ) {
a.low = floatx80_default_nan_low;
@@ -462,31 +580,26 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
return a;
}
- aIsNaN = floatx80_is_nan( a );
+ aIsQuietNaN = floatx80_is_quiet_nan( a );
aIsSignalingNaN = floatx80_is_signaling_nan( a );
- bIsNaN = floatx80_is_nan( b );
+ bIsQuietNaN = floatx80_is_quiet_nan( b );
bIsSignalingNaN = floatx80_is_signaling_nan( b );
-#if SNAN_BIT_IS_ONE
- a.low &= ~LIT64( 0xC000000000000000 );
- b.low &= ~LIT64( 0xC000000000000000 );
-#else
- a.low |= LIT64( 0xC000000000000000 );
- b.low |= LIT64( 0xC000000000000000 );
-#endif
+
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
- if ( aIsSignalingNaN ) {
- if ( bIsSignalingNaN ) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if ( aIsNaN ) {
- if ( bIsSignalingNaN || ! bIsNaN ) return a;
- returnLargerSignificand:
- if ( a.low < b.low ) return b;
- if ( b.low < a.low ) return a;
- return ( a.high < b.high ) ? a : b;
+
+ if (a.low < b.low) {
+ aIsLargerSignificand = 0;
+ } else if (b.low < a.low) {
+ aIsLargerSignificand = 1;
+ } else {
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
- else {
- return b;
+
+ if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
+ aIsLargerSignificand)) {
+ return floatx80_maybe_silence_nan(b);
+ } else {
+ return floatx80_maybe_silence_nan(a);
}
}
@@ -511,7 +624,7 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
-int float128_is_nan( float128 a )
+int float128_is_quiet_nan( float128 a )
{
#if SNAN_BIT_IS_ONE
return
@@ -543,6 +656,29 @@ int float128_is_signaling_nan( float128 a )
}
/*----------------------------------------------------------------------------
+| Returns a quiet NaN if the quadruple-precision floating point value `a' is
+| a signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+
+float128 float128_maybe_silence_nan( float128 a )
+{
+ if (float128_is_signaling_nan(a)) {
+#if SNAN_BIT_IS_ONE
+# if defined(TARGET_MIPS)
+ a.low = float128_default_nan_low;
+ a.high = float128_default_nan_high;
+# else
+# error Rules for silencing a signaling NaN are target-specific
+# endif
+#else
+ a.high |= LIT64( 0x0000800000000000 );
+ return a;
+#endif
+ }
+ return a;
+}
+
+/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
@@ -580,7 +716,8 @@ static float128 commonNaNToFloat128( commonNaNT a )
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
{
- flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+ flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
+ flag aIsLargerSignificand;
if ( STATUS(default_nan_mode) ) {
a.low = float128_default_nan_low;
@@ -588,31 +725,26 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
return a;
}
- aIsNaN = float128_is_nan( a );
+ aIsQuietNaN = float128_is_quiet_nan( a );
aIsSignalingNaN = float128_is_signaling_nan( a );
- bIsNaN = float128_is_nan( b );
+ bIsQuietNaN = float128_is_quiet_nan( b );
bIsSignalingNaN = float128_is_signaling_nan( b );
-#if SNAN_BIT_IS_ONE
- a.high &= ~LIT64( 0x0000800000000000 );
- b.high &= ~LIT64( 0x0000800000000000 );
-#else
- a.high |= LIT64( 0x0000800000000000 );
- b.high |= LIT64( 0x0000800000000000 );
-#endif
+
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
- if ( aIsSignalingNaN ) {
- if ( bIsSignalingNaN ) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if ( aIsNaN ) {
- if ( bIsSignalingNaN || ! bIsNaN ) return a;
- returnLargerSignificand:
- if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
- if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
- return ( a.high < b.high ) ? a : b;
+
+ if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
+ aIsLargerSignificand = 0;
+ } else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
+ aIsLargerSignificand = 1;
+ } else {
+ aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
- else {
- return b;
+
+ if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
+ aIsLargerSignificand)) {
+ return float128_maybe_silence_nan(b);
+ } else {
+ return float128_maybe_silence_nan(a);
}
}
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 6f5b05d5fe..17842f43da 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -30,8 +30,6 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
-/* FIXME: Flush-To-Zero only effects results. Denormal inputs should also
- be flushed to zero. */
#include "softfloat.h"
/*----------------------------------------------------------------------------
@@ -204,6 +202,21 @@ INLINE flag extractFloat32Sign( float32 a )
}
/*----------------------------------------------------------------------------
+| If `a' is denormal and we are in flush-to-zero mode then set the
+| input-denormal exception and return zero. Otherwise just return the value.
+*----------------------------------------------------------------------------*/
+static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
+{
+ if (STATUS(flush_inputs_to_zero)) {
+ if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
+ float_raise(float_flag_input_denormal STATUS_VAR);
+ return make_float32(float32_val(a) & 0x80000000);
+ }
+ }
+ return a;
+}
+
+/*----------------------------------------------------------------------------
| Normalizes the subnormal single-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
@@ -368,6 +381,21 @@ INLINE flag extractFloat64Sign( float64 a )
}
/*----------------------------------------------------------------------------
+| If `a' is denormal and we are in flush-to-zero mode then set the
+| input-denormal exception and return zero. Otherwise just return the value.
+*----------------------------------------------------------------------------*/
+static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
+{
+ if (STATUS(flush_inputs_to_zero)) {
+ if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
+ float_raise(float_flag_input_denormal STATUS_VAR);
+ return make_float64(float64_val(a) & (1ULL << 63));
+ }
+ }
+ return a;
+}
+
+/*----------------------------------------------------------------------------
| Normalizes the subnormal double-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
@@ -1298,6 +1326,7 @@ int32 float32_to_int32( float32 a STATUS_PARAM )
bits32 aSig;
bits64 aSig64;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -1327,6 +1356,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
int16 aExp, shiftCount;
bits32 aSig;
int32 z;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1418,6 +1448,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
int16 aExp, shiftCount;
bits32 aSig;
bits64 aSig64, aSigExtra;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1455,6 +1486,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
bits32 aSig;
bits64 aSig64;
int64 z;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1496,6 +1528,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
flag aSign;
int16 aExp;
bits32 aSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1528,6 +1561,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -1561,6 +1595,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -1593,6 +1628,7 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
bits32 lastBitMask, roundBitsMask;
int8 roundingMode;
bits32 z;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aExp = extractFloat32Exp( a );
if ( 0x96 <= aExp ) {
@@ -1796,6 +1832,8 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
float32 float32_add( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
@@ -1817,6 +1855,8 @@ float32 float32_add( float32 a, float32 b STATUS_PARAM )
float32 float32_sub( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
@@ -1843,6 +1883,9 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
bits64 zSig64;
bits32 zSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
+
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -1900,6 +1943,8 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
bits32 aSig, bSig, zSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -1966,6 +2011,8 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
bits64 aSig64, bSig64, q64;
bits32 alternateASig;
sbits32 sigMean;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -2062,6 +2109,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
int16 aExp, zExp;
bits32 aSig, zSig;
bits64 rem, term;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -2148,6 +2196,7 @@ float32 float32_exp2( float32 a STATUS_PARAM )
bits32 aSig;
float64 r, x, xn;
int i;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -2194,6 +2243,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig, zSig, i;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -2238,6 +2288,8 @@ float32 float32_log2( float32 a STATUS_PARAM )
int float32_eq( float32 a, float32 b STATUS_PARAM )
{
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2263,6 +2315,8 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2289,6 +2343,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2315,6 +2371,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
{
bits32 av, bv;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2339,6 +2397,8 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2368,6 +2428,8 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
+ a = float32_squash_input_denormal(a STATUS_VAR);
+ b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@@ -2401,6 +2463,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM )
flag aSign;
int16 aExp, shiftCount;
bits64 aSig;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -2429,6 +2492,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
int16 aExp, shiftCount;
bits64 aSig, savedASig;
int32 z;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -2525,6 +2589,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
flag aSign;
int16 aExp, shiftCount;
bits64 aSig, aSigExtra;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -2568,6 +2633,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
int16 aExp, shiftCount;
bits64 aSig;
int64 z;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -2617,6 +2683,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig;
bits32 zSig;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -2694,6 +2761,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
bits32 mask;
bits32 increment;
int8 roundingMode;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@@ -2788,6 +2856,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@@ -2822,6 +2891,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig, zSig0, zSig1;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@@ -2855,6 +2925,7 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
bits64 lastBitMask, roundBitsMask;
int8 roundingMode;
bits64 z;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aExp = extractFloat64Exp( a );
if ( 0x433 <= aExp ) {
@@ -3071,6 +3142,8 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
float64 float64_add( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
@@ -3092,6 +3165,8 @@ float64 float64_add( float64 a, float64 b STATUS_PARAM )
float64 float64_sub( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
@@ -3116,6 +3191,9 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
int16 aExp, bExp, zExp;
bits64 aSig, bSig, zSig0, zSig1;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
+
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@@ -3175,6 +3253,8 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
bits64 aSig, bSig, zSig;
bits64 rem0, rem1;
bits64 term0, term1;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -3246,6 +3326,8 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
bits64 q, alternateASig;
sbits64 sigMean;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@@ -3328,6 +3410,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
int16 aExp, zExp;
bits64 aSig, zSig, doubleZSig;
bits64 rem0, rem1, term0, term1;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -3377,6 +3460,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
flag aSign, zSign;
int16 aExp;
bits64 aSig, aSig0, aSig1, zSig, i;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@@ -3422,6 +3506,8 @@ float64 float64_log2( float64 a STATUS_PARAM )
int float64_eq( float64 a, float64 b STATUS_PARAM )
{
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3448,6 +3534,8 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3475,6 +3563,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
flag aSign, bSign;
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
) {
@@ -3500,6 +3590,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
{
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3524,6 +3616,8 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -3553,6 +3647,8 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
+ a = float64_squash_input_denormal(a STATUS_VAR);
+ b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@@ -5833,6 +5929,8 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \
{ \
flag aSign, bSign; \
bits ## s av, bv; \
+ a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
+ b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
\
if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
extractFloat ## s ## Frac( a ) ) || \
@@ -5929,6 +6027,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
int16 aExp;
bits32 aSig;
+ a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@@ -5952,6 +6051,7 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
int16 aExp;
bits64 aSig;
+ a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 1c1004de97..a6d0f16b42 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -180,7 +180,8 @@ enum {
float_flag_divbyzero = 4,
float_flag_overflow = 8,
float_flag_underflow = 16,
- float_flag_inexact = 32
+ float_flag_inexact = 32,
+ float_flag_input_denormal = 64
};
typedef struct float_status {
@@ -190,7 +191,10 @@ typedef struct float_status {
#ifdef FLOATX80
signed char floatx80_rounding_precision;
#endif
+ /* should denormalised results go to zero and set the inexact flag? */
flag flush_to_zero;
+ /* should denormalised inputs go to zero and set the input_denormal flag? */
+ flag flush_inputs_to_zero;
flag default_nan_mode;
} float_status;
@@ -200,6 +204,10 @@ INLINE void set_flush_to_zero(flag val STATUS_PARAM)
{
STATUS(flush_to_zero) = val;
}
+INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM)
+{
+ STATUS(flush_inputs_to_zero) = val;
+}
INLINE void set_default_nan_mode(flag val STATUS_PARAM)
{
STATUS(default_nan_mode) = val;
@@ -287,18 +295,24 @@ int float32_le_quiet( float32, float32 STATUS_PARAM );
int float32_lt_quiet( float32, float32 STATUS_PARAM );
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
-int float32_is_nan( float32 );
+int float32_is_quiet_nan( float32 );
int float32_is_signaling_nan( float32 );
float32 float32_maybe_silence_nan( float32 );
float32 float32_scalbn( float32, int STATUS_PARAM );
INLINE float32 float32_abs(float32 a)
{
+ /* Note that abs does *not* handle NaN specially, nor does
+ * it flush denormal inputs to zero.
+ */
return make_float32(float32_val(a) & 0x7fffffff);
}
INLINE float32 float32_chs(float32 a)
{
+ /* Note that chs does *not* handle NaN specially, nor does
+ * it flush denormal inputs to zero.
+ */
return make_float32(float32_val(a) ^ 0x80000000);
}
@@ -367,18 +381,24 @@ int float64_le_quiet( float64, float64 STATUS_PARAM );
int float64_lt_quiet( float64, float64 STATUS_PARAM );
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
-int float64_is_nan( float64 a );
+int float64_is_quiet_nan( float64 a );
int float64_is_signaling_nan( float64 );
float64 float64_maybe_silence_nan( float64 );
float64 float64_scalbn( float64, int STATUS_PARAM );
INLINE float64 float64_abs(float64 a)
{
+ /* Note that abs does *not* handle NaN specially, nor does
+ * it flush denormal inputs to zero.
+ */
return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
}
INLINE float64 float64_chs(float64 a)
{
+ /* Note that chs does *not* handle NaN specially, nor does
+ * it flush denormal inputs to zero.
+ */
return make_float64(float64_val(a) ^ 0x8000000000000000LL);
}
@@ -437,8 +457,9 @@ int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
-int floatx80_is_nan( floatx80 );
+int floatx80_is_quiet_nan( floatx80 );
int floatx80_is_signaling_nan( floatx80 );
+floatx80 floatx80_maybe_silence_nan( floatx80 );
floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
INLINE floatx80 floatx80_abs(floatx80 a)
@@ -468,6 +489,11 @@ INLINE int floatx80_is_zero(floatx80 a)
return (a.high & 0x7fff) == 0 && a.low == 0;
}
+INLINE int floatx80_is_any_nan(floatx80 a)
+{
+ return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
+}
+
#endif
#ifdef FLOAT128
@@ -503,8 +529,9 @@ int float128_le_quiet( float128, float128 STATUS_PARAM );
int float128_lt_quiet( float128, float128 STATUS_PARAM );
int float128_compare( float128, float128 STATUS_PARAM );
int float128_compare_quiet( float128, float128 STATUS_PARAM );
-int float128_is_nan( float128 );
+int float128_is_quiet_nan( float128 );
int float128_is_signaling_nan( float128 );
+float128 float128_maybe_silence_nan( float128 );
float128 float128_scalbn( float128, int STATUS_PARAM );
INLINE float128 float128_abs(float128 a)
@@ -534,6 +561,12 @@ INLINE int float128_is_zero(float128 a)
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
}
+INLINE int float128_is_any_nan(float128 a)
+{
+ return ((a.high >> 48) & 0x7fff) == 0x7fff &&
+ ((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
+}
+
#endif
#else /* CONFIG_SOFTFLOAT */