softfloat-specialize revision 1.11
11.11Sriastrad/*	$NetBSD: softfloat-specialize,v 1.11 2025/05/06 23:18:27 riastradh Exp $	*/
21.3Sbjh21
31.3Sbjh21/* This is a derivative work. */
41.1Sbjh21
51.1Sbjh21/*
61.1Sbjh21===============================================================================
71.1Sbjh21
81.1Sbjh21This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
91.1Sbjh21Arithmetic Package, Release 2a.
101.1Sbjh21
111.1Sbjh21Written by John R. Hauser.  This work was made possible in part by the
121.1Sbjh21International Computer Science Institute, located at Suite 600, 1947 Center
131.1Sbjh21Street, Berkeley, California 94704.  Funding was partially provided by the
141.1Sbjh21National Science Foundation under grant MIP-9311980.  The original version
151.1Sbjh21of this code was written as part of a project to build a fixed-point vector
161.1Sbjh21processor in collaboration with the University of California at Berkeley,
171.1Sbjh21overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
181.1Sbjh21is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
191.1Sbjh21arithmetic/SoftFloat.html'.
201.1Sbjh21
211.1Sbjh21THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
221.1Sbjh21has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
231.1Sbjh21TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
241.1Sbjh21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
251.1Sbjh21AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
261.1Sbjh21
271.1Sbjh21Derivative works are acceptable, even for commercial purposes, so long as
281.1Sbjh21(1) they include prominent notice that the work is derivative, and (2) they
291.1Sbjh21include prominent notice akin to these four paragraphs for those parts of
301.1Sbjh21this code that are retained.
311.1Sbjh21
321.1Sbjh21===============================================================================
331.1Sbjh21*/
341.1Sbjh21
351.3Sbjh21#include <signal.h>
361.5Smartin#include <string.h>
371.5Smartin#include <unistd.h>
381.3Sbjh21
391.10Sriastrad#include "reentrant.h"
401.10Sriastrad
411.1Sbjh21/*
421.1Sbjh21-------------------------------------------------------------------------------
431.1Sbjh21Underflow tininess-detection mode, statically initialized to default value.
441.1Sbjh21(The declaration in `softfloat.h' must match the `int8' type here.)
451.1Sbjh21-------------------------------------------------------------------------------
461.1Sbjh21*/
471.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC
481.1Sbjh21static
491.1Sbjh21#endif
501.1Sbjh21int8 float_detect_tininess = float_tininess_after_rounding;
511.1Sbjh21
521.1Sbjh21/*
531.1Sbjh21-------------------------------------------------------------------------------
541.1Sbjh21Raises the exceptions specified by `flags'.  Floating-point traps can be
551.1Sbjh21defined here if desired.  It is currently not possible for such a trap to
561.1Sbjh21substitute a result value.  If traps are not implemented, this routine
571.1Sbjh21should be simply `float_exception_flags |= flags;'.
581.1Sbjh21-------------------------------------------------------------------------------
591.1Sbjh21*/
601.6Smartin#ifdef SOFTFLOAT_FOR_GCC
611.8Smatt#ifndef set_float_exception_mask
621.6Smartin#define float_exception_mask	_softfloat_float_exception_mask
631.6Smartin#endif
641.8Smatt#endif
651.8Smatt#ifndef set_float_exception_mask
661.3Sbjh21fp_except float_exception_mask = 0;
671.8Smatt#endif
681.8Smattvoid
691.10Sriastradfloat_raise( fp_except newflags )
701.1Sbjh21{
711.5Smartin    siginfo_t info;
721.10Sriastrad    struct sigaction sa;
731.10Sriastrad    sigset_t sigmask, osigmask;
741.10Sriastrad    fp_except flags;
751.1Sbjh21
761.10Sriastrad    for (;;) {
771.8Smatt#ifdef set_float_exception_mask
781.10Sriastrad	flags = newflags | set_float_exception_flags(newflags, 0);
791.8Smatt#else
801.10Sriastrad	float_exception_flags |= newflags;
811.10Sriastrad	flags = float_exception_flags;
821.8Smatt#endif
831.1Sbjh21
841.10Sriastrad	/*
851.10Sriastrad	 * If none of the sticky flags are trapped (i.e., enabled in
861.10Sriastrad	 * float_exception_mask), we're done.  Trapping is unusual and
871.10Sriastrad	 * costly anyway, so take the non-trapping path as the fast
881.10Sriastrad	 * path.
891.10Sriastrad	 */
901.10Sriastrad	flags &= float_exception_mask;
911.10Sriastrad	if (__predict_true(flags == 0))
921.10Sriastrad	    break;
931.10Sriastrad
941.10Sriastrad	/*
951.10Sriastrad	 * Block all signals while we figure out how to deliver a
961.10Sriastrad	 * non-maskable (as a signal), non-ignorable SIGFPE, and obtain
971.10Sriastrad	 * the current signal mask.
981.10Sriastrad	 */
991.10Sriastrad	sigfillset(&sigmask);
1001.11Sriastrad#ifdef _REENTRANT	/* XXX PR lib/59401 */
1011.10Sriastrad	thr_sigsetmask(SIG_BLOCK, &sigmask, &osigmask);
1021.11Sriastrad#else
1031.11Sriastrad	sigprocmask(SIG_BLOCK, &sigmask, &osigmask);
1041.11Sriastrad#endif
1051.10Sriastrad
1061.10Sriastrad	/*
1071.10Sriastrad	 * Find the current signal disposition of SIGFPE.
1081.10Sriastrad	 */
1091.10Sriastrad	sigaction(SIGFPE, NULL, &sa);
1101.10Sriastrad
1111.10Sriastrad	/*
1121.10Sriastrad	 * If SIGFPE is masked or ignored, unmask it and reset it to
1131.10Sriastrad	 * the default disposition to deliver the signal.
1141.10Sriastrad	 */
1151.10Sriastrad	if (sigismember(&osigmask, SIGFPE) ||
1161.10Sriastrad	    ((sa.sa_flags & SA_SIGINFO) == 0 &&
1171.10Sriastrad		sa.sa_handler == SIG_IGN)) {
1181.10Sriastrad		/*
1191.10Sriastrad		 * Prepare to unmask SIGFPE.  This will take effect
1201.10Sriastrad		 * when we use thr_sigsetmask(SIG_SETMASK, ...) below,
1211.10Sriastrad		 * once the signal has been queued, so that it happens
1221.10Sriastrad		 * atomically with respect to other signal delivery.
1231.10Sriastrad		 */
1241.10Sriastrad		sigdelset(&osigmask, SIGFPE);
1251.10Sriastrad
1261.10Sriastrad		/*
1271.10Sriastrad		 * Reset SIGFPE to the default disposition, which is to
1281.10Sriastrad		 * terminate the process.
1291.10Sriastrad		 */
1301.10Sriastrad		memset(&sa, 0, sizeof(sa));
1311.10Sriastrad		sa.sa_handler = SIG_DFL;
1321.10Sriastrad		sigemptyset(&sa.sa_mask);
1331.10Sriastrad		sa.sa_flags = 0;
1341.10Sriastrad		sigaction(SIGFPE, &sa, NULL);
1351.10Sriastrad	}
1361.10Sriastrad
1371.10Sriastrad	/*
1381.10Sriastrad	 * Queue the signal for delivery.  It won't trigger the signal
1391.10Sriastrad	 * handler yet, because it's still masked, but as soon as we
1401.10Sriastrad	 * unmask it either the process will terminate or the signal
1411.10Sriastrad	 * handler will be called.
1421.10Sriastrad	 */
1431.5Smartin	memset(&info, 0, sizeof info);
1441.5Smartin	info.si_signo = SIGFPE;
1451.5Smartin	info.si_pid = getpid();
1461.5Smartin	info.si_uid = geteuid();
1471.5Smartin	if (flags & float_flag_underflow)
1481.5Smartin	    info.si_code = FPE_FLTUND;
1491.5Smartin	else if (flags & float_flag_overflow)
1501.5Smartin	    info.si_code = FPE_FLTOVF;
1511.5Smartin	else if (flags & float_flag_divbyzero)
1521.5Smartin	    info.si_code = FPE_FLTDIV;
1531.5Smartin	else if (flags & float_flag_invalid)
1541.5Smartin	    info.si_code = FPE_FLTINV;
1551.5Smartin	else if (flags & float_flag_inexact)
1561.5Smartin	    info.si_code = FPE_FLTRES;
1571.5Smartin	sigqueueinfo(getpid(), &info);
1581.10Sriastrad
1591.10Sriastrad	/*
1601.10Sriastrad	 * Restore the old signal mask, except with SIGFPE unmasked
1611.10Sriastrad	 * even if it was masked before.
1621.10Sriastrad	 *
1631.10Sriastrad	 * At this point, either the process will terminate (if SIGFPE
1641.10Sriastrad	 * had or now has the default disposition) or the signal
1651.10Sriastrad	 * handler will be called (if SIGFPE had a non-default,
1661.10Sriastrad	 * non-ignored disposition).
1671.10Sriastrad	 *
1681.10Sriastrad	 * If the signal handler returns, it can't change the set of
1691.10Sriastrad	 * exceptions raised by this floating-point operation -- but it
1701.10Sriastrad	 * can change the sticky set from previous operations, and it
1711.10Sriastrad	 * can change the set of exceptions that are trapped, so loop
1721.10Sriastrad	 * around; next time we might make progress instead of calling
1731.10Sriastrad	 * the signal handler again.
1741.10Sriastrad	 */
1751.11Sriastrad#ifdef _REENTRANT	/* XXX PR lib/59401 */
1761.10Sriastrad	thr_sigsetmask(SIG_SETMASK, &osigmask, NULL);
1771.11Sriastrad#else
1781.11Sriastrad	sigprocmask(SIG_SETMASK, &osigmask, NULL);
1791.11Sriastrad#endif
1801.3Sbjh21    }
1811.1Sbjh21}
1821.6Smartin#undef float_exception_mask
1831.1Sbjh21
1841.1Sbjh21/*
1851.1Sbjh21-------------------------------------------------------------------------------
1861.1Sbjh21Internal canonical NaN format.
1871.1Sbjh21-------------------------------------------------------------------------------
1881.1Sbjh21*/
1891.1Sbjh21typedef struct {
1901.1Sbjh21    flag sign;
1911.1Sbjh21    bits64 high, low;
1921.1Sbjh21} commonNaNT;
1931.1Sbjh21
1941.1Sbjh21/*
1951.1Sbjh21-------------------------------------------------------------------------------
1961.1Sbjh21The pattern for a default generated single-precision NaN.
1971.1Sbjh21-------------------------------------------------------------------------------
1981.1Sbjh21*/
1991.1Sbjh21#define float32_default_nan 0xFFFFFFFF
2001.1Sbjh21
2011.1Sbjh21/*
2021.1Sbjh21-------------------------------------------------------------------------------
2031.1Sbjh21Returns 1 if the single-precision floating-point value `a' is a NaN;
2041.1Sbjh21otherwise returns 0.
2051.1Sbjh21-------------------------------------------------------------------------------
2061.1Sbjh21*/
2071.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC
2081.1Sbjh21static
2091.1Sbjh21#endif
2101.1Sbjh21flag float32_is_nan( float32 a )
2111.1Sbjh21{
2121.1Sbjh21
2131.7Schristos    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
2141.1Sbjh21
2151.1Sbjh21}
2161.1Sbjh21
2171.1Sbjh21/*
2181.1Sbjh21-------------------------------------------------------------------------------
2191.1Sbjh21Returns 1 if the single-precision floating-point value `a' is a signaling
2201.1Sbjh21NaN; otherwise returns 0.
2211.1Sbjh21-------------------------------------------------------------------------------
2221.1Sbjh21*/
2231.9Smatt#if defined(SOFTFLOAT_FOR_GCC) \
2241.9Smatt    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
2251.9Smatt    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
2261.9Smatt    && !defined(SOFTFLOATM68K_FOR_GCC)
2271.1Sbjh21static
2281.1Sbjh21#endif
2291.1Sbjh21flag float32_is_signaling_nan( float32 a )
2301.1Sbjh21{
2311.1Sbjh21
2321.1Sbjh21    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
2331.1Sbjh21
2341.1Sbjh21}
2351.1Sbjh21
2361.1Sbjh21/*
2371.1Sbjh21-------------------------------------------------------------------------------
2381.1Sbjh21Returns the result of converting the single-precision floating-point NaN
2391.1Sbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
2401.1Sbjh21exception is raised.
2411.1Sbjh21-------------------------------------------------------------------------------
2421.1Sbjh21*/
2431.1Sbjh21static commonNaNT float32ToCommonNaN( float32 a )
2441.1Sbjh21{
2451.1Sbjh21    commonNaNT z;
2461.1Sbjh21
2471.1Sbjh21    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
2481.1Sbjh21    z.sign = a>>31;
2491.1Sbjh21    z.low = 0;
2501.1Sbjh21    z.high = ( (bits64) a )<<41;
2511.1Sbjh21    return z;
2521.1Sbjh21
2531.1Sbjh21}
2541.1Sbjh21
2551.1Sbjh21/*
2561.1Sbjh21-------------------------------------------------------------------------------
2571.1Sbjh21Returns the result of converting the canonical NaN `a' to the single-
2581.1Sbjh21precision floating-point format.
2591.1Sbjh21-------------------------------------------------------------------------------
2601.1Sbjh21*/
2611.1Sbjh21static float32 commonNaNToFloat32( commonNaNT a )
2621.1Sbjh21{
2631.1Sbjh21
2641.7Schristos    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
2651.1Sbjh21
2661.1Sbjh21}
2671.1Sbjh21
2681.1Sbjh21/*
2691.1Sbjh21-------------------------------------------------------------------------------
2701.1Sbjh21Takes two single-precision floating-point values `a' and `b', one of which
2711.1Sbjh21is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
2721.1Sbjh21signaling NaN, the invalid exception is raised.
2731.1Sbjh21-------------------------------------------------------------------------------
2741.1Sbjh21*/
2751.1Sbjh21static float32 propagateFloat32NaN( float32 a, float32 b )
2761.1Sbjh21{
2771.1Sbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
2781.1Sbjh21
2791.1Sbjh21    aIsNaN = float32_is_nan( a );
2801.1Sbjh21    aIsSignalingNaN = float32_is_signaling_nan( a );
2811.1Sbjh21    bIsNaN = float32_is_nan( b );
2821.1Sbjh21    bIsSignalingNaN = float32_is_signaling_nan( b );
2831.1Sbjh21    a |= 0x00400000;
2841.1Sbjh21    b |= 0x00400000;
2851.1Sbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
2861.1Sbjh21    if ( aIsNaN ) {
2871.1Sbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
2881.1Sbjh21    }
2891.1Sbjh21    else {
2901.1Sbjh21        return b;
2911.1Sbjh21    }
2921.1Sbjh21
2931.1Sbjh21}
2941.1Sbjh21
2951.1Sbjh21/*
2961.1Sbjh21-------------------------------------------------------------------------------
2971.1Sbjh21The pattern for a default generated double-precision NaN.
2981.1Sbjh21-------------------------------------------------------------------------------
2991.1Sbjh21*/
3001.1Sbjh21#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
3011.1Sbjh21
3021.1Sbjh21/*
3031.1Sbjh21-------------------------------------------------------------------------------
3041.1Sbjh21Returns 1 if the double-precision floating-point value `a' is a NaN;
3051.1Sbjh21otherwise returns 0.
3061.1Sbjh21-------------------------------------------------------------------------------
3071.1Sbjh21*/
3081.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC
3091.1Sbjh21static
3101.1Sbjh21#endif
3111.1Sbjh21flag float64_is_nan( float64 a )
3121.1Sbjh21{
3131.1Sbjh21
3141.7Schristos    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
3151.1Sbjh21	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
3161.1Sbjh21
3171.1Sbjh21}
3181.1Sbjh21
3191.1Sbjh21/*
3201.1Sbjh21-------------------------------------------------------------------------------
3211.1Sbjh21Returns 1 if the double-precision floating-point value `a' is a signaling
3221.1Sbjh21NaN; otherwise returns 0.
3231.1Sbjh21-------------------------------------------------------------------------------
3241.1Sbjh21*/
3251.9Smatt#if defined(SOFTFLOAT_FOR_GCC) \
3261.9Smatt    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
3271.9Smatt    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
3281.9Smatt    && !defined(SOFTFLOATM68K_FOR_GCC)
3291.1Sbjh21static
3301.1Sbjh21#endif
3311.1Sbjh21flag float64_is_signaling_nan( float64 a )
3321.1Sbjh21{
3331.1Sbjh21
3341.1Sbjh21    return
3351.1Sbjh21           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
3361.1Sbjh21        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
3371.1Sbjh21
3381.1Sbjh21}
3391.1Sbjh21
3401.1Sbjh21/*
3411.1Sbjh21-------------------------------------------------------------------------------
3421.1Sbjh21Returns the result of converting the double-precision floating-point NaN
3431.1Sbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
3441.1Sbjh21exception is raised.
3451.1Sbjh21-------------------------------------------------------------------------------
3461.1Sbjh21*/
3471.1Sbjh21static commonNaNT float64ToCommonNaN( float64 a )
3481.1Sbjh21{
3491.1Sbjh21    commonNaNT z;
3501.1Sbjh21
3511.1Sbjh21    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
3521.7Schristos    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
3531.1Sbjh21    z.low = 0;
3541.1Sbjh21    z.high = FLOAT64_DEMANGLE(a)<<12;
3551.1Sbjh21    return z;
3561.1Sbjh21
3571.1Sbjh21}
3581.1Sbjh21
3591.1Sbjh21/*
3601.1Sbjh21-------------------------------------------------------------------------------
3611.1Sbjh21Returns the result of converting the canonical NaN `a' to the double-
3621.1Sbjh21precision floating-point format.
3631.1Sbjh21-------------------------------------------------------------------------------
3641.1Sbjh21*/
3651.1Sbjh21static float64 commonNaNToFloat64( commonNaNT a )
3661.1Sbjh21{
3671.1Sbjh21
3681.1Sbjh21    return FLOAT64_MANGLE(
3691.1Sbjh21	( ( (bits64) a.sign )<<63 )
3701.1Sbjh21        | LIT64( 0x7FF8000000000000 )
3711.1Sbjh21        | ( a.high>>12 ) );
3721.1Sbjh21
3731.1Sbjh21}
3741.1Sbjh21
3751.1Sbjh21/*
3761.1Sbjh21-------------------------------------------------------------------------------
3771.1Sbjh21Takes two double-precision floating-point values `a' and `b', one of which
3781.1Sbjh21is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
3791.1Sbjh21signaling NaN, the invalid exception is raised.
3801.1Sbjh21-------------------------------------------------------------------------------
3811.1Sbjh21*/
3821.1Sbjh21static float64 propagateFloat64NaN( float64 a, float64 b )
3831.1Sbjh21{
3841.1Sbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
3851.1Sbjh21
3861.1Sbjh21    aIsNaN = float64_is_nan( a );
3871.1Sbjh21    aIsSignalingNaN = float64_is_signaling_nan( a );
3881.1Sbjh21    bIsNaN = float64_is_nan( b );
3891.1Sbjh21    bIsSignalingNaN = float64_is_signaling_nan( b );
3901.1Sbjh21    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
3911.1Sbjh21    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
3921.1Sbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
3931.1Sbjh21    if ( aIsNaN ) {
3941.1Sbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
3951.1Sbjh21    }
3961.1Sbjh21    else {
3971.1Sbjh21        return b;
3981.1Sbjh21    }
3991.1Sbjh21
4001.1Sbjh21}
4011.1Sbjh21
4021.1Sbjh21#ifdef FLOATX80
4031.1Sbjh21
4041.1Sbjh21/*
4051.1Sbjh21-------------------------------------------------------------------------------
4061.1Sbjh21The pattern for a default generated extended double-precision NaN.  The
4071.1Sbjh21`high' and `low' values hold the most- and least-significant bits,
4081.1Sbjh21respectively.
4091.1Sbjh21-------------------------------------------------------------------------------
4101.1Sbjh21*/
4111.1Sbjh21#define floatx80_default_nan_high 0xFFFF
4121.1Sbjh21#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
4131.1Sbjh21
4141.1Sbjh21/*
4151.1Sbjh21-------------------------------------------------------------------------------
4161.1Sbjh21Returns 1 if the extended double-precision floating-point value `a' is a
4171.1Sbjh21NaN; otherwise returns 0.
4181.1Sbjh21-------------------------------------------------------------------------------
4191.1Sbjh21*/
4201.1Sbjh21flag floatx80_is_nan( floatx80 a )
4211.1Sbjh21{
4221.1Sbjh21
4231.1Sbjh21    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
4241.1Sbjh21
4251.1Sbjh21}
4261.1Sbjh21
4271.1Sbjh21/*
4281.1Sbjh21-------------------------------------------------------------------------------
4291.1Sbjh21Returns 1 if the extended double-precision floating-point value `a' is a
4301.1Sbjh21signaling NaN; otherwise returns 0.
4311.1Sbjh21-------------------------------------------------------------------------------
4321.1Sbjh21*/
4331.1Sbjh21flag floatx80_is_signaling_nan( floatx80 a )
4341.1Sbjh21{
4351.1Sbjh21    bits64 aLow;
4361.1Sbjh21
4371.1Sbjh21    aLow = a.low & ~ LIT64( 0x4000000000000000 );
4381.1Sbjh21    return
4391.1Sbjh21           ( ( a.high & 0x7FFF ) == 0x7FFF )
4401.1Sbjh21        && (bits64) ( aLow<<1 )
4411.1Sbjh21        && ( a.low == aLow );
4421.1Sbjh21
4431.1Sbjh21}
4441.1Sbjh21
4451.1Sbjh21/*
4461.1Sbjh21-------------------------------------------------------------------------------
4471.1Sbjh21Returns the result of converting the extended double-precision floating-
4481.1Sbjh21point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
4491.1Sbjh21invalid exception is raised.
4501.1Sbjh21-------------------------------------------------------------------------------
4511.1Sbjh21*/
4521.1Sbjh21static commonNaNT floatx80ToCommonNaN( floatx80 a )
4531.1Sbjh21{
4541.1Sbjh21    commonNaNT z;
4551.1Sbjh21
4561.1Sbjh21    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
4571.1Sbjh21    z.sign = a.high>>15;
4581.1Sbjh21    z.low = 0;
4591.1Sbjh21    z.high = a.low<<1;
4601.1Sbjh21    return z;
4611.1Sbjh21
4621.1Sbjh21}
4631.1Sbjh21
4641.1Sbjh21/*
4651.1Sbjh21-------------------------------------------------------------------------------
4661.1Sbjh21Returns the result of converting the canonical NaN `a' to the extended
4671.1Sbjh21double-precision floating-point format.
4681.1Sbjh21-------------------------------------------------------------------------------
4691.1Sbjh21*/
4701.1Sbjh21static floatx80 commonNaNToFloatx80( commonNaNT a )
4711.1Sbjh21{
4721.1Sbjh21    floatx80 z;
4731.1Sbjh21
4741.1Sbjh21    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
4751.1Sbjh21    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
4761.1Sbjh21    return z;
4771.1Sbjh21
4781.1Sbjh21}
4791.1Sbjh21
4801.1Sbjh21/*
4811.1Sbjh21-------------------------------------------------------------------------------
4821.1Sbjh21Takes two extended double-precision floating-point values `a' and `b', one
4831.1Sbjh21of which is a NaN, and returns the appropriate NaN result.  If either `a' or
4841.1Sbjh21`b' is a signaling NaN, the invalid exception is raised.
4851.1Sbjh21-------------------------------------------------------------------------------
4861.1Sbjh21*/
4871.1Sbjh21static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
4881.1Sbjh21{
4891.1Sbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
4901.1Sbjh21
4911.1Sbjh21    aIsNaN = floatx80_is_nan( a );
4921.1Sbjh21    aIsSignalingNaN = floatx80_is_signaling_nan( a );
4931.1Sbjh21    bIsNaN = floatx80_is_nan( b );
4941.1Sbjh21    bIsSignalingNaN = floatx80_is_signaling_nan( b );
4951.1Sbjh21    a.low |= LIT64( 0xC000000000000000 );
4961.1Sbjh21    b.low |= LIT64( 0xC000000000000000 );
4971.1Sbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
4981.1Sbjh21    if ( aIsNaN ) {
4991.1Sbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
5001.1Sbjh21    }
5011.1Sbjh21    else {
5021.1Sbjh21        return b;
5031.1Sbjh21    }
5041.1Sbjh21
5051.1Sbjh21}
5061.1Sbjh21
5071.1Sbjh21#endif
5081.1Sbjh21
5091.1Sbjh21#ifdef FLOAT128
5101.1Sbjh21
5111.1Sbjh21/*
5121.1Sbjh21-------------------------------------------------------------------------------
5131.1Sbjh21The pattern for a default generated quadruple-precision NaN.  The `high' and
5141.1Sbjh21`low' values hold the most- and least-significant bits, respectively.
5151.1Sbjh21-------------------------------------------------------------------------------
5161.1Sbjh21*/
5171.1Sbjh21#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
5181.1Sbjh21#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
5191.1Sbjh21
5201.1Sbjh21/*
5211.1Sbjh21-------------------------------------------------------------------------------
5221.1Sbjh21Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
5231.1Sbjh21otherwise returns 0.
5241.1Sbjh21-------------------------------------------------------------------------------
5251.1Sbjh21*/
5261.1Sbjh21flag float128_is_nan( float128 a )
5271.1Sbjh21{
5281.1Sbjh21
5291.1Sbjh21    return
5301.7Schristos           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
5311.1Sbjh21        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
5321.1Sbjh21
5331.1Sbjh21}
5341.1Sbjh21
5351.1Sbjh21/*
5361.1Sbjh21-------------------------------------------------------------------------------
5371.1Sbjh21Returns 1 if the quadruple-precision floating-point value `a' is a
5381.1Sbjh21signaling NaN; otherwise returns 0.
5391.1Sbjh21-------------------------------------------------------------------------------
5401.1Sbjh21*/
5411.1Sbjh21flag float128_is_signaling_nan( float128 a )
5421.1Sbjh21{
5431.1Sbjh21
5441.1Sbjh21    return
5451.1Sbjh21           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
5461.1Sbjh21        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
5471.1Sbjh21
5481.1Sbjh21}
5491.1Sbjh21
5501.1Sbjh21/*
5511.1Sbjh21-------------------------------------------------------------------------------
5521.1Sbjh21Returns the result of converting the quadruple-precision floating-point NaN
5531.1Sbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
5541.1Sbjh21exception is raised.
5551.1Sbjh21-------------------------------------------------------------------------------
5561.1Sbjh21*/
5571.1Sbjh21static commonNaNT float128ToCommonNaN( float128 a )
5581.1Sbjh21{
5591.1Sbjh21    commonNaNT z;
5601.1Sbjh21
5611.1Sbjh21    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
5621.7Schristos    z.sign = (flag)(a.high>>63);
5631.1Sbjh21    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
5641.1Sbjh21    return z;
5651.1Sbjh21
5661.1Sbjh21}
5671.1Sbjh21
5681.1Sbjh21/*
5691.1Sbjh21-------------------------------------------------------------------------------
5701.1Sbjh21Returns the result of converting the canonical NaN `a' to the quadruple-
5711.1Sbjh21precision floating-point format.
5721.1Sbjh21-------------------------------------------------------------------------------
5731.1Sbjh21*/
5741.1Sbjh21static float128 commonNaNToFloat128( commonNaNT a )
5751.1Sbjh21{
5761.1Sbjh21    float128 z;
5771.1Sbjh21
5781.1Sbjh21    shift128Right( a.high, a.low, 16, &z.high, &z.low );
5791.1Sbjh21    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
5801.1Sbjh21    return z;
5811.1Sbjh21
5821.1Sbjh21}
5831.1Sbjh21
5841.1Sbjh21/*
5851.1Sbjh21-------------------------------------------------------------------------------
5861.1Sbjh21Takes two quadruple-precision floating-point values `a' and `b', one of
5871.1Sbjh21which is a NaN, and returns the appropriate NaN result.  If either `a' or
5881.1Sbjh21`b' is a signaling NaN, the invalid exception is raised.
5891.1Sbjh21-------------------------------------------------------------------------------
5901.1Sbjh21*/
5911.1Sbjh21static float128 propagateFloat128NaN( float128 a, float128 b )
5921.1Sbjh21{
5931.1Sbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
5941.1Sbjh21
5951.1Sbjh21    aIsNaN = float128_is_nan( a );
5961.1Sbjh21    aIsSignalingNaN = float128_is_signaling_nan( a );
5971.1Sbjh21    bIsNaN = float128_is_nan( b );
5981.1Sbjh21    bIsSignalingNaN = float128_is_signaling_nan( b );
5991.1Sbjh21    a.high |= LIT64( 0x0000800000000000 );
6001.1Sbjh21    b.high |= LIT64( 0x0000800000000000 );
6011.1Sbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
6021.1Sbjh21    if ( aIsNaN ) {
6031.1Sbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
6041.1Sbjh21    }
6051.1Sbjh21    else {
6061.1Sbjh21        return b;
6071.1Sbjh21    }
6081.1Sbjh21
6091.1Sbjh21}
6101.1Sbjh21
6111.1Sbjh21#endif
6121.1Sbjh21
613