Hi There are issues with m68k softfloat (fpgnulib.c) not perserving NaNs and Inf when converting from (long) double and float types.
This issue has been documented in a NetBSD PR: http://gnats.netbsd.org/59616 Addressed by the attached patch which sets the value correctly for NaN and +/- Infinity when converting between different types. Best regards, Nat
diff -r 5ad0dfe2fd93 external/gpl3/gcc/dist/libgcc/config/m68k/fpgnulib.c --- a/external/gpl3/gcc/dist/libgcc/config/m68k/fpgnulib.c Sun Aug 24 21:39:00 2025 +0000 +++ b/external/gpl3/gcc/dist/libgcc/config/m68k/fpgnulib.c Sat Aug 30 12:42:51 2025 +1000 @@ -63,7 +63,7 @@ #define HIDDEND (1L << 20L) #define EXPDBITS 11 #define EXPDMASK 0x7FFL -#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL) +#define EXPD(fp) (((fp.l.upper) >> 20L) & EXPDMASK) #define SIGND(fp) ((fp.l.upper) & SIGNBIT) #define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ (fp.l.lower >> 22)) @@ -78,6 +78,9 @@ #define SIGNX(fp) ((fp.l.upper) & SIGNBIT) #define MANTXMASK 0x7FFFFFFFL /* mask of upper part */ +#define QUIET_NaN 0xFFFFFFFF +#define POSS_INF_or_NaN 0x7FFFFFFF + union double_long { double d; @@ -242,6 +245,23 @@ double fl1.f = a1; dl.l.upper = SIGN (fl1.l); + + /* special case for inf. */ + if ((fl1.l & POSS_INF_or_NaN) == 0x7F800000) + { + dl.l.upper |= 0x7FF00000; + dl.l.lower = 0; + return dl.d; + } + + /* expand the right value for nan */ + if ((fl1.l & QUIET_NaN) == QUIET_NaN) + { + dl.l.upper = QUIET_NaN; + dl.l.lower = QUIET_NaN; + return dl.d; + } + if ((fl1.l & ~SIGNBIT) == 0) { dl.l.lower = 0; @@ -282,6 +302,20 @@ float dl1.d = a1; + /* special case for inf. */ + if ((dl1.l.upper & POSS_INF_or_NaN) == 0x7FF00000 && dl1.l.lower == 0) + { + fl.l = 0x7F800000 | SIGND(dl1); + return fl.f; + } + + /* special case for nan. */ + if ((dl1.l.upper & QUIET_NaN) == QUIET_NaN && dl1.l.lower == QUIET_NaN) + { + fl.l = QUIET_NaN; + return fl.f; + } + if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower) { fl.l = SIGND(dl1); @@ -425,6 +459,25 @@ long double /*printf ("dfxf in: %g\n", d);*/ ldl.l.upper = SIGND (dl); + + /* special case for inf. */ + if ((dl.l.upper & POSS_INF_or_NaN) == 0x7FF00000 && dl.l.lower == 0) + { + ldl.l.upper |= 0x7FFF0000; + ldl.l.middle = 0; + ldl.l.lower = 0; + return ldl.ld; + } + + /* special case for nan */ + if ((dl.l.upper & QUIET_NaN) == QUIET_NaN && dl.l.lower == QUIET_NaN) + { + ldl.l.upper = 0xFFFF0000; + ldl.l.middle = QUIET_NaN; + ldl.l.lower = QUIET_NaN; + return ldl.ld; + } + if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower) { ldl.l.middle = 0; @@ -458,6 +511,25 @@ double /*printf ("xfdf in: %s\n", dumpxf (ld));*/ dl.l.upper = SIGNX (ldl); + + /* special case for inf. */ + if ((ldl.l.upper & 0x7FFF0000) == 0x7FFF0000 && + (ldl.l.middle | ldl.l.lower) == 0) + { + dl.l.upper |= 0x7FF00000; + dl.l.lower = 0; + return dl.d; + } + + /* special case for nan */ + if ((ldl.l.upper & 0xFFFF0000) == 0xFFFF0000 && ldl.l.middle == QUIET_NaN && + ldl.l.lower == QUIET_NaN) + { + dl.l.upper = QUIET_NaN; + dl.l.lower = QUIET_NaN; + return dl.d; + } + if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower) { dl.l.lower = 0;