* version 2 or later. See the COPYING file in the top-level directory.
*/
-#if defined(TARGET_XTENSA)
/* Define for architectures which deviate from IEEE in not supporting
* signaling NaNs (so all NaNs are treated as quiet).
*/
+#if defined(TARGET_XTENSA)
#define NO_SIGNALING_NANS 1
#endif
+/* Define how the architecture discriminates signaling NaNs.
+ * This done with the most significant bit of the fraction.
+ * In IEEE 754-1985 this was implementation defined, but in IEEE 754-2008
+ * the msb must be zero. MIPS is (so far) unique in supporting both the
+ * 2008 revision and backward compatibility with their original choice.
+ * Thus for MIPS we must make the choice at runtime.
+ */
+static inline flag snan_bit_is_one(float_status *status)
+{
+#if defined(TARGET_MIPS)
+ return status->snan_bit_is_one;
+#elif defined(TARGET_HPPA) || defined(TARGET_UNICORE32) || defined(TARGET_SH4)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
/*----------------------------------------------------------------------------
| For the deconstructed floating-point with fraction FRAC, return true
| if the fraction represents a signalling NaN; otherwise false.
return false;
#else
flag msb = extract64(frac, DECOMPOSED_BINARY_POINT - 1, 1);
- return msb == status->snan_bit_is_one;
+ return msb == snan_bit_is_one(status);
#endif
}
uint64_t frac;
#if defined(TARGET_SPARC) || defined(TARGET_M68K)
+ /* !snan_bit_is_one, set all bits */
frac = (1ULL << DECOMPOSED_BINARY_POINT) - 1;
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
- defined(TARGET_S390X) || defined(TARGET_RISCV)
+#elif defined(TARGET_I386) || defined(TARGET_X86_64) \
+ || defined(TARGET_MICROBLAZE)
+ /* !snan_bit_is_one, set sign and msb */
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
+ sign = 1;
#elif defined(TARGET_HPPA)
+ /* snan_bit_is_one, set msb-1. */
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 2);
#else
- if (status->snan_bit_is_one) {
+ /* This case is true for Alpha, ARM, MIPS, OpenRISC, PPC, RISC-V,
+ * S390, SH4, TriCore, and Xtensa. I cannot find documentation
+ * for Unicore32; the choice from the original commit is unchanged.
+ * Our other supported targets, CRIS, LM32, Moxie, Nios2, and Tile,
+ * do not have floating-point.
+ */
+ if (snan_bit_is_one(status)) {
+ /* set all bits other than msb */
frac = (1ULL << (DECOMPOSED_BINARY_POINT - 1)) - 1;
} else {
-#if defined(TARGET_MIPS)
- frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
-#else
+ /* set msb */
frac = 1ULL << (DECOMPOSED_BINARY_POINT - 1);
- sign = 1;
-#endif
}
#endif
a.frac &= ~(1ULL << (DECOMPOSED_BINARY_POINT - 1));
a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 2);
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return parts_default_nan(status);
} else {
a.frac |= 1ULL << (DECOMPOSED_BINARY_POINT - 1);
return a;
}
-/*----------------------------------------------------------------------------
-| The pattern for a default generated half-precision NaN.
-*----------------------------------------------------------------------------*/
-float16 float16_default_nan(float_status *status)
-{
-#if defined(TARGET_ARM)
- return const_float16(0x7E00);
-#else
- if (status->snan_bit_is_one) {
- return const_float16(0x7DFF);
- } else {
-#if defined(TARGET_MIPS)
- return const_float16(0x7E00);
-#else
- return const_float16(0xFE00);
-#endif
- }
-#endif
-}
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated single-precision NaN.
-*----------------------------------------------------------------------------*/
-float32 float32_default_nan(float_status *status)
-{
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
- return const_float32(0x7FFFFFFF);
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
- defined(TARGET_XTENSA) || defined(TARGET_S390X) || \
- defined(TARGET_TRICORE) || defined(TARGET_RISCV)
- return const_float32(0x7FC00000);
-#elif defined(TARGET_HPPA)
- return const_float32(0x7FA00000);
-#else
- if (status->snan_bit_is_one) {
- return const_float32(0x7FBFFFFF);
- } else {
-#if defined(TARGET_MIPS)
- return const_float32(0x7FC00000);
-#else
- return const_float32(0xFFC00000);
-#endif
- }
-#endif
-}
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated double-precision NaN.
-*----------------------------------------------------------------------------*/
-float64 float64_default_nan(float_status *status)
-{
-#if defined(TARGET_SPARC) || defined(TARGET_M68K)
- return const_float64(LIT64(0x7FFFFFFFFFFFFFFF));
-#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA) || \
- defined(TARGET_S390X) || defined(TARGET_RISCV)
- return const_float64(LIT64(0x7FF8000000000000));
-#elif defined(TARGET_HPPA)
- return const_float64(LIT64(0x7FF4000000000000));
-#else
- if (status->snan_bit_is_one) {
- return const_float64(LIT64(0x7FF7FFFFFFFFFFFF));
- } else {
-#if defined(TARGET_MIPS)
- return const_float64(LIT64(0x7FF8000000000000));
-#else
- return const_float64(LIT64(0xFFF8000000000000));
-#endif
- }
-#endif
-}
-
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
floatx80 floatx80_default_nan(float_status *status)
{
floatx80 r;
+
+ /* None of the targets that have snan_bit_is_one use floatx80. */
+ assert(!snan_bit_is_one(status));
#if defined(TARGET_M68K)
r.low = LIT64(0xFFFFFFFFFFFFFFFF);
r.high = 0x7FFF;
#else
- if (status->snan_bit_is_one) {
- r.low = LIT64(0xBFFFFFFFFFFFFFFF);
- r.high = 0x7FFF;
- } else {
- r.low = LIT64(0xC000000000000000);
- r.high = 0xFFFF;
- }
+ /* X86 */
+ r.low = LIT64(0xC000000000000000);
+ r.high = 0xFFFF;
#endif
return r;
}
const floatx80 floatx80_infinity
= make_floatx80_init(floatx80_infinity_high, floatx80_infinity_low);
-/*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.
-*----------------------------------------------------------------------------*/
-float128 float128_default_nan(float_status *status)
-{
- float128 r;
-
- if (status->snan_bit_is_one) {
- r.low = LIT64(0xFFFFFFFFFFFFFFFF);
- r.high = LIT64(0x7FFF7FFFFFFFFFFF);
- } else {
- r.low = LIT64(0x0000000000000000);
-#if defined(TARGET_S390X) || defined(TARGET_PPC) || defined(TARGET_RISCV)
- r.high = LIT64(0x7FFF800000000000);
-#else
- r.high = LIT64(0xFFFF800000000000);
-#endif
- }
- return r;
-}
-
/*----------------------------------------------------------------------------
| Raises the exceptions specified by `flags'. Floating-point traps can be
| defined here if desired. It is currently not possible for such a trap
return float16_is_any_nan(a_);
#else
uint16_t a = float16_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
} else {
return ((a & ~0x8000) >= 0x7C80);
return 0;
#else
uint16_t a = float16_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return ((a & ~0x8000) >= 0x7C80);
} else {
return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
#endif
}
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN from a signalling NaN for the half-precision
-| floating point value `a'.
-*----------------------------------------------------------------------------*/
-
-float16 float16_silence_nan(float16 a, float_status *status)
-{
-#ifdef NO_SIGNALING_NANS
- g_assert_not_reached();
-#else
- if (status->snan_bit_is_one) {
- return float16_default_nan(status);
- } else {
- return a | (1 << 9);
- }
-#endif
-}
-
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a quiet
| NaN; otherwise returns 0.
return float32_is_any_nan(a_);
#else
uint32_t a = float32_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
} else {
return ((uint32_t)(a << 1) >= 0xFF800000);
return 0;
#else
uint32_t a = float32_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return ((uint32_t)(a << 1) >= 0xFF800000);
} else {
return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
#endif
}
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN from a signalling NaN for the single-precision
-| floating point value `a'.
-*----------------------------------------------------------------------------*/
-
-float32 float32_silence_nan(float32 a, float_status *status)
-{
-#ifdef NO_SIGNALING_NANS
- g_assert_not_reached();
-#else
- if (status->snan_bit_is_one) {
-# ifdef TARGET_HPPA
- a &= ~0x00400000;
- a |= 0x00200000;
- return a;
-# else
- return float32_default_nan(status);
-# endif
- } else {
- return a | (1 << 22);
- }
-#endif
-}
-
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| tie-break rule.
*----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
+static int pickNaN(FloatClass a_cls, FloatClass b_cls,
flag aIsLargerSignificand)
{
+#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_HPPA)
/* ARM mandated NaN propagation rules (see FPProcessNaNs()), take
* the first of:
* 1. A if it is signaling
* 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) || defined(TARGET_HPPA)
-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_silence_nan(). For qNaN inputs the specifications
* 4. B (quiet)
* A signaling NaN is always silenced before returning it.
*/
- if (aIsSNaN) {
+ if (is_snan(a_cls)) {
return 0;
- } else if (bIsSNaN) {
+ } else if (is_snan(b_cls)) {
return 1;
- } else if (aIsQNaN) {
+ } else if (is_qnan(a_cls)) {
return 0;
} else {
return 1;
}
-}
-#elif defined(TARGET_PPC) || defined(TARGET_XTENSA)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag aIsLargerSignificand)
-{
+#elif defined(TARGET_PPC) || defined(TARGET_XTENSA) || defined(TARGET_M68K)
/* 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;
- }
-}
-#elif defined(TARGET_M68K)
-static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag aIsLargerSignificand)
-{
/* M68000 FAMILY PROGRAMMER'S REFERENCE MANUAL
* 3.4 FLOATING-POINT INSTRUCTION DETAILS
* If either operand, but not both operands, of an operation is a
* a nonsignaling NaN. The operation then continues as described in the
* preceding paragraph for nonsignaling NaNs.
*/
- if (aIsQNaN || aIsSNaN) { /* a is the destination operand */
- return 0; /* return the destination operand */
+ if (is_nan(a_cls)) {
+ return 0;
} else {
- return 1; /* return b */
+ 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
* 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) {
+ if (is_snan(a_cls)) {
+ if (is_snan(b_cls)) {
return aIsLargerSignificand ? 0 : 1;
}
- return bIsQNaN ? 1 : 0;
- } else if (aIsQNaN) {
- if (bIsSNaN || !bIsQNaN) {
+ return is_qnan(b_cls) ? 1 : 0;
+ } else if (is_qnan(a_cls)) {
+ if (is_snan(b_cls) || !is_qnan(b_cls)) {
return 0;
} else {
return aIsLargerSignificand ? 0 : 1;
} else {
return 1;
}
-}
#endif
+}
/*----------------------------------------------------------------------------
| Select which NaN to propagate for a three-input operation.
| information.
| Return values : 0 : a; 1 : b; 2 : c; 3 : default-NaN
*----------------------------------------------------------------------------*/
-#if defined(TARGET_ARM)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
+static int pickNaNMulAdd(FloatClass a_cls, FloatClass b_cls, FloatClass c_cls,
+ bool infzero, float_status *status)
{
+#if defined(TARGET_ARM)
/* For ARM, the (inf,zero,qnan) case sets InvalidOp and returns
* the default NaN
*/
- if (infzero && cIsQNaN) {
+ if (infzero && is_qnan(c_cls)) {
float_raise(float_flag_invalid, status);
return 3;
}
/* This looks different from the ARM ARM pseudocode, because the ARM ARM
* puts the operands to a fused mac operation (a*b)+c in the order c,a,b.
*/
- if (cIsSNaN) {
+ if (is_snan(c_cls)) {
return 2;
- } else if (aIsSNaN) {
+ } else if (is_snan(a_cls)) {
return 0;
- } else if (bIsSNaN) {
+ } else if (is_snan(b_cls)) {
return 1;
- } else if (cIsQNaN) {
+ } else if (is_qnan(c_cls)) {
return 2;
- } else if (aIsQNaN) {
+ } else if (is_qnan(a_cls)) {
return 0;
} else {
return 1;
}
-}
#elif defined(TARGET_MIPS)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
- /* For MIPS, the (inf,zero,qnan) case sets InvalidOp and returns
- * the default NaN
- */
- if (infzero) {
- float_raise(float_flag_invalid, status);
- return 3;
- }
-
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
+ /*
+ * For MIPS systems that conform to IEEE754-1985, the (inf,zero,nan)
+ * case sets InvalidOp and returns the default NaN
+ */
+ if (infzero) {
+ float_raise(float_flag_invalid, status);
+ return 3;
+ }
/* Prefer sNaN over qNaN, in the a, b, c order. */
- if (aIsSNaN) {
+ if (is_snan(a_cls)) {
return 0;
- } else if (bIsSNaN) {
+ } else if (is_snan(b_cls)) {
return 1;
- } else if (cIsSNaN) {
+ } else if (is_snan(c_cls)) {
return 2;
- } else if (aIsQNaN) {
+ } else if (is_qnan(a_cls)) {
return 0;
- } else if (bIsQNaN) {
+ } else if (is_qnan(b_cls)) {
return 1;
} else {
return 2;
}
} else {
+ /*
+ * For MIPS systems that conform to IEEE754-2008, the (inf,zero,nan)
+ * case sets InvalidOp and returns the input value 'c'
+ */
+ if (infzero) {
+ float_raise(float_flag_invalid, status);
+ return 2;
+ }
/* Prefer sNaN over qNaN, in the c, a, b order. */
- if (cIsSNaN) {
+ if (is_snan(c_cls)) {
return 2;
- } else if (aIsSNaN) {
+ } else if (is_snan(a_cls)) {
return 0;
- } else if (bIsSNaN) {
+ } else if (is_snan(b_cls)) {
return 1;
- } else if (cIsQNaN) {
+ } else if (is_qnan(c_cls)) {
return 2;
- } else if (aIsQNaN) {
+ } else if (is_qnan(a_cls)) {
return 0;
} else {
return 1;
}
}
-}
#elif defined(TARGET_PPC)
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
/* For PPC, the (inf,zero,qnan) case sets InvalidOp, but we prefer
* to return an input NaN if we have one (ie c) rather than generating
* a default NaN
/* If fRA is a NaN return it; otherwise if fRB is a NaN return it;
* otherwise return fRC. Note that muladd on PPC is (fRA * fRC) + frB
*/
- if (aIsSNaN || aIsQNaN) {
+ if (is_nan(a_cls)) {
return 0;
- } else if (cIsSNaN || cIsQNaN) {
+ } else if (is_nan(c_cls)) {
return 2;
} else {
return 1;
}
-}
#else
-/* A default implementation: prefer a to b to c.
- * This is unlikely to actually match any real implementation.
- */
-static int pickNaNMulAdd(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
- flag cIsQNaN, flag cIsSNaN, flag infzero,
- float_status *status)
-{
- if (aIsSNaN || aIsQNaN) {
+ /* A default implementation: prefer a to b to c.
+ * This is unlikely to actually match any real implementation.
+ */
+ if (is_nan(a_cls)) {
return 0;
- } else if (bIsSNaN || bIsQNaN) {
+ } else if (is_nan(b_cls)) {
return 1;
} else {
return 2;
}
-}
#endif
+}
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
static float32 propagateFloat32NaN(float32 a, float32 b, float_status *status)
{
- flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
uint32_t av, bv;
+ FloatClass a_cls, b_cls;
+
+ /* This is not complete, but is good enough for pickNaN. */
+ a_cls = (!float32_is_any_nan(a)
+ ? float_class_normal
+ : float32_is_signaling_nan(a, status)
+ ? float_class_snan
+ : float_class_qnan);
+ b_cls = (!float32_is_any_nan(b)
+ ? float_class_normal
+ : float32_is_signaling_nan(b, status)
+ ? float_class_snan
+ : float_class_qnan);
- aIsQuietNaN = float32_is_quiet_nan(a, status);
- aIsSignalingNaN = float32_is_signaling_nan(a, status);
- bIsQuietNaN = float32_is_quiet_nan(b, status);
- bIsSignalingNaN = float32_is_signaling_nan(b, status);
av = float32_val(a);
bv = float32_val(b);
- if (aIsSignalingNaN | bIsSignalingNaN) {
+ if (is_snan(a_cls) || is_snan(b_cls)) {
float_raise(float_flag_invalid, status);
}
aIsLargerSignificand = (av < bv) ? 1 : 0;
}
- if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
- aIsLargerSignificand)) {
- if (bIsSignalingNaN) {
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+ if (is_snan(b_cls)) {
return float32_silence_nan(b, status);
}
return b;
} else {
- if (aIsSignalingNaN) {
+ if (is_snan(a_cls)) {
return float32_silence_nan(a, status);
}
return a;
return float64_is_any_nan(a_);
#else
uint64_t a = float64_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return (((a >> 51) & 0xFFF) == 0xFFE)
&& (a & 0x0007FFFFFFFFFFFFULL);
} else {
return 0;
#else
uint64_t a = float64_val(a_);
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return ((a << 1) >= 0xFFF0000000000000ULL);
} else {
return (((a >> 51) & 0xFFF) == 0xFFE)
#endif
}
-/*----------------------------------------------------------------------------
-| Returns a quiet NaN from a signalling NaN for the double-precision
-| floating point value `a'.
-*----------------------------------------------------------------------------*/
-
-float64 float64_silence_nan(float64 a, float_status *status)
-{
-#ifdef NO_SIGNALING_NANS
- g_assert_not_reached();
-#else
- if (status->snan_bit_is_one) {
-# ifdef TARGET_HPPA
- a &= ~0x0008000000000000ULL;
- a |= 0x0004000000000000ULL;
- return a;
-# else
- return float64_default_nan(status);
-# endif
- } else {
- return a | LIT64(0x0008000000000000);
- }
-#endif
-}
-
-
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
static float64 propagateFloat64NaN(float64 a, float64 b, float_status *status)
{
- flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
uint64_t av, bv;
+ FloatClass a_cls, b_cls;
+
+ /* This is not complete, but is good enough for pickNaN. */
+ a_cls = (!float64_is_any_nan(a)
+ ? float_class_normal
+ : float64_is_signaling_nan(a, status)
+ ? float_class_snan
+ : float_class_qnan);
+ b_cls = (!float64_is_any_nan(b)
+ ? float_class_normal
+ : float64_is_signaling_nan(b, status)
+ ? float_class_snan
+ : float_class_qnan);
- aIsQuietNaN = float64_is_quiet_nan(a, status);
- aIsSignalingNaN = float64_is_signaling_nan(a, status);
- bIsQuietNaN = float64_is_quiet_nan(b, status);
- bIsSignalingNaN = float64_is_signaling_nan(b, status);
av = float64_val(a);
bv = float64_val(b);
- if (aIsSignalingNaN | bIsSignalingNaN) {
+ if (is_snan(a_cls) || is_snan(b_cls)) {
float_raise(float_flag_invalid, status);
}
aIsLargerSignificand = (av < bv) ? 1 : 0;
}
- if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
- aIsLargerSignificand)) {
- if (bIsSignalingNaN) {
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+ if (is_snan(b_cls)) {
return float64_silence_nan(b, status);
}
return b;
} else {
- if (aIsSignalingNaN) {
+ if (is_snan(a_cls)) {
return float64_silence_nan(a, status);
}
return a;
#ifdef NO_SIGNALING_NANS
return floatx80_is_any_nan(a);
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
uint64_t aLow;
aLow = a.low & ~0x4000000000000000ULL;
#ifdef NO_SIGNALING_NANS
return 0;
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return ((a.high & 0x7FFF) == 0x7FFF)
&& ((a.low << 1) >= 0x8000000000000000ULL);
} else {
floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
{
-#ifdef NO_SIGNALING_NANS
- g_assert_not_reached();
-#else
- if (status->snan_bit_is_one) {
- return floatx80_default_nan(status);
- } else {
- a.low |= LIT64(0xC000000000000000);
- return a;
- }
-#endif
+ /* None of the targets that have snan_bit_is_one use floatx80. */
+ assert(!snan_bit_is_one(status));
+ a.low |= LIT64(0xC000000000000000);
+ return a;
}
/*----------------------------------------------------------------------------
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, float_status *status)
{
- flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
-
- aIsQuietNaN = floatx80_is_quiet_nan(a, status);
- aIsSignalingNaN = floatx80_is_signaling_nan(a, status);
- bIsQuietNaN = floatx80_is_quiet_nan(b, status);
- bIsSignalingNaN = floatx80_is_signaling_nan(b, status);
-
- if (aIsSignalingNaN | bIsSignalingNaN) {
+ FloatClass a_cls, b_cls;
+
+ /* This is not complete, but is good enough for pickNaN. */
+ a_cls = (!floatx80_is_any_nan(a)
+ ? float_class_normal
+ : floatx80_is_signaling_nan(a, status)
+ ? float_class_snan
+ : float_class_qnan);
+ b_cls = (!floatx80_is_any_nan(b)
+ ? float_class_normal
+ : floatx80_is_signaling_nan(b, status)
+ ? float_class_snan
+ : float_class_qnan);
+
+ if (is_snan(a_cls) || is_snan(b_cls)) {
float_raise(float_flag_invalid, status);
}
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
- if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
- aIsLargerSignificand)) {
- if (bIsSignalingNaN) {
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+ if (is_snan(b_cls)) {
return floatx80_silence_nan(b, status);
}
return b;
} else {
- if (aIsSignalingNaN) {
+ if (is_snan(a_cls)) {
return floatx80_silence_nan(a, status);
}
return a;
#ifdef NO_SIGNALING_NANS
return float128_is_any_nan(a);
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
&& (a.low || (a.high & 0x00007FFFFFFFFFFFULL));
} else {
#ifdef NO_SIGNALING_NANS
return 0;
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return ((a.high << 1) >= 0xFFFF000000000000ULL)
&& (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
} else {
#ifdef NO_SIGNALING_NANS
g_assert_not_reached();
#else
- if (status->snan_bit_is_one) {
+ if (snan_bit_is_one(status)) {
return float128_default_nan(status);
} else {
a.high |= LIT64(0x0000800000000000);
static float128 propagateFloat128NaN(float128 a, float128 b,
float_status *status)
{
- flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
-
- aIsQuietNaN = float128_is_quiet_nan(a, status);
- aIsSignalingNaN = float128_is_signaling_nan(a, status);
- bIsQuietNaN = float128_is_quiet_nan(b, status);
- bIsSignalingNaN = float128_is_signaling_nan(b, status);
-
- if (aIsSignalingNaN | bIsSignalingNaN) {
+ FloatClass a_cls, b_cls;
+
+ /* This is not complete, but is good enough for pickNaN. */
+ a_cls = (!float128_is_any_nan(a)
+ ? float_class_normal
+ : float128_is_signaling_nan(a, status)
+ ? float_class_snan
+ : float_class_qnan);
+ b_cls = (!float128_is_any_nan(b)
+ ? float_class_normal
+ : float128_is_signaling_nan(b, status)
+ ? float_class_snan
+ : float_class_qnan);
+
+ if (is_snan(a_cls) || is_snan(b_cls)) {
float_raise(float_flag_invalid, status);
}
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
- if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
- aIsLargerSignificand)) {
- if (bIsSignalingNaN) {
+ if (pickNaN(a_cls, b_cls, aIsLargerSignificand)) {
+ if (is_snan(b_cls)) {
return float128_silence_nan(b, status);
}
return b;
} else {
- if (aIsSignalingNaN) {
+ if (is_snan(a_cls)) {
return float128_silence_nan(a, status);
}
return a;