diff --git a/options/ansi/musl-generic-math/__fpclassifyl.c b/options/ansi/musl-generic-math/__fpclassifyl.c index 481c0b9499..fb62dd9fc4 100644 --- a/options/ansi/musl-generic-math/__fpclassifyl.c +++ b/options/ansi/musl-generic-math/__fpclassifyl.c @@ -13,10 +13,18 @@ int __fpclassifyl(long double x) int msb = u.i.m>>63; if (!e && !msb) return u.i.m ? FP_SUBNORMAL : FP_ZERO; + if (e == 0x7fff) { + /* The x86 variant of 80-bit extended precision only admits + * one representation of each infinity, with the mantissa msb + * necessarily set. The version with it clear is invalid/nan. + * The m68k variant, however, allows either, and tooling uses + * the version with it clear. */ + if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && !msb) + return FP_NAN; + return u.i.m << 1 ? FP_NAN : FP_INFINITE; + } if (!msb) return FP_NAN; - if (e == 0x7fff) - return u.i.m << 1 ? FP_NAN : FP_INFINITE; return FP_NORMAL; } #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 diff --git a/options/ansi/musl-generic-math/libm.h b/options/ansi/musl-generic-math/libm.h index 8120292ea8..2022cc5054 100644 --- a/options/ansi/musl-generic-math/libm.h +++ b/options/ansi/musl-generic-math/libm.h @@ -18,7 +18,7 @@ #include #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ union ldshape { long double f; struct { @@ -26,7 +26,18 @@ union ldshape { uint16_t se; } i; }; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +/* This is the m68k variant of 80-bit long double, and this definition only works + * on archs where the alignment requirement of uint64_t is <= 4. */ +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t pad; + uint64_t m; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ union ldshape { long double f; struct { @@ -40,7 +51,7 @@ union ldshape { uint64_t hi; } i2; }; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ union ldshape { long double f; struct {