xref: /minix3/lib/libc/softfloat/softfloat-specialize (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc/*	$NetBSD: softfloat-specialize,v 1.9 2014/08/10 05:57:31 matt Exp $	*/
22fe8fb19SBen Gras
32fe8fb19SBen Gras/* This is a derivative work. */
42fe8fb19SBen Gras
52fe8fb19SBen Gras/*
62fe8fb19SBen Gras===============================================================================
72fe8fb19SBen Gras
82fe8fb19SBen GrasThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
92fe8fb19SBen GrasArithmetic Package, Release 2a.
102fe8fb19SBen Gras
112fe8fb19SBen GrasWritten by John R. Hauser.  This work was made possible in part by the
122fe8fb19SBen GrasInternational Computer Science Institute, located at Suite 600, 1947 Center
132fe8fb19SBen GrasStreet, Berkeley, California 94704.  Funding was partially provided by the
142fe8fb19SBen GrasNational Science Foundation under grant MIP-9311980.  The original version
152fe8fb19SBen Grasof this code was written as part of a project to build a fixed-point vector
162fe8fb19SBen Grasprocessor in collaboration with the University of California at Berkeley,
172fe8fb19SBen Grasoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
182fe8fb19SBen Grasis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
192fe8fb19SBen Grasarithmetic/SoftFloat.html'.
202fe8fb19SBen Gras
212fe8fb19SBen GrasTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
222fe8fb19SBen Grashas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
232fe8fb19SBen GrasTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
242fe8fb19SBen GrasPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
252fe8fb19SBen GrasAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
262fe8fb19SBen Gras
272fe8fb19SBen GrasDerivative works are acceptable, even for commercial purposes, so long as
282fe8fb19SBen Gras(1) they include prominent notice that the work is derivative, and (2) they
292fe8fb19SBen Grasinclude prominent notice akin to these four paragraphs for those parts of
302fe8fb19SBen Grasthis code that are retained.
312fe8fb19SBen Gras
322fe8fb19SBen Gras===============================================================================
332fe8fb19SBen Gras*/
342fe8fb19SBen Gras
352fe8fb19SBen Gras#include <signal.h>
36f14fb602SLionel Sambuc#include <string.h>
37f14fb602SLionel Sambuc#include <unistd.h>
382fe8fb19SBen Gras
392fe8fb19SBen Gras/*
402fe8fb19SBen Gras-------------------------------------------------------------------------------
412fe8fb19SBen GrasUnderflow tininess-detection mode, statically initialized to default value.
422fe8fb19SBen Gras(The declaration in `softfloat.h' must match the `int8' type here.)
432fe8fb19SBen Gras-------------------------------------------------------------------------------
442fe8fb19SBen Gras*/
452fe8fb19SBen Gras#ifdef SOFTFLOAT_FOR_GCC
462fe8fb19SBen Grasstatic
472fe8fb19SBen Gras#endif
482fe8fb19SBen Grasint8 float_detect_tininess = float_tininess_after_rounding;
492fe8fb19SBen Gras
502fe8fb19SBen Gras/*
512fe8fb19SBen Gras-------------------------------------------------------------------------------
522fe8fb19SBen GrasRaises the exceptions specified by `flags'.  Floating-point traps can be
532fe8fb19SBen Grasdefined here if desired.  It is currently not possible for such a trap to
542fe8fb19SBen Grassubstitute a result value.  If traps are not implemented, this routine
552fe8fb19SBen Grasshould be simply `float_exception_flags |= flags;'.
562fe8fb19SBen Gras-------------------------------------------------------------------------------
572fe8fb19SBen Gras*/
58f14fb602SLionel Sambuc#ifdef SOFTFLOAT_FOR_GCC
5984d9c625SLionel Sambuc#ifndef set_float_exception_mask
60f14fb602SLionel Sambuc#define float_exception_mask	_softfloat_float_exception_mask
61f14fb602SLionel Sambuc#endif
6284d9c625SLionel Sambuc#endif
6384d9c625SLionel Sambuc#ifndef set_float_exception_mask
642fe8fb19SBen Grasfp_except float_exception_mask = 0;
6584d9c625SLionel Sambuc#endif
6684d9c625SLionel Sambucvoid
6784d9c625SLionel Sambucfloat_raise( fp_except flags )
682fe8fb19SBen Gras{
69f14fb602SLionel Sambuc    siginfo_t info;
7084d9c625SLionel Sambuc    fp_except mask = float_exception_mask;
712fe8fb19SBen Gras
7284d9c625SLionel Sambuc#ifdef set_float_exception_mask
7384d9c625SLionel Sambuc    flags |= set_float_exception_flags(flags, 0);
7484d9c625SLionel Sambuc#else
752fe8fb19SBen Gras    float_exception_flags |= flags;
7684d9c625SLionel Sambuc    flags = float_exception_flags;
7784d9c625SLionel Sambuc#endif
782fe8fb19SBen Gras
7984d9c625SLionel Sambuc    flags &= mask;
8084d9c625SLionel Sambuc    if ( flags ) {
81f14fb602SLionel Sambuc	memset(&info, 0, sizeof info);
82f14fb602SLionel Sambuc	info.si_signo = SIGFPE;
83f14fb602SLionel Sambuc	info.si_pid = getpid();
84f14fb602SLionel Sambuc	info.si_uid = geteuid();
85f14fb602SLionel Sambuc	if (flags & float_flag_underflow)
86f14fb602SLionel Sambuc	    info.si_code = FPE_FLTUND;
87f14fb602SLionel Sambuc	else if (flags & float_flag_overflow)
88f14fb602SLionel Sambuc	    info.si_code = FPE_FLTOVF;
89f14fb602SLionel Sambuc	else if (flags & float_flag_divbyzero)
90f14fb602SLionel Sambuc	    info.si_code = FPE_FLTDIV;
91f14fb602SLionel Sambuc	else if (flags & float_flag_invalid)
92f14fb602SLionel Sambuc	    info.si_code = FPE_FLTINV;
93f14fb602SLionel Sambuc	else if (flags & float_flag_inexact)
94f14fb602SLionel Sambuc	    info.si_code = FPE_FLTRES;
95b1c4ba4aSLionel Sambuc#if !defined(__minix)
96b1c4ba4aSLionel Sambuc/* LSC FIXME: This kind of remove any interest to the function. We should
97b1c4ba4aSLionel Sambuc               be using the minix equivalent, or do something appropriate. */
98f14fb602SLionel Sambuc	sigqueueinfo(getpid(), &info);
99b1c4ba4aSLionel Sambuc#endif /* !defined(__minix) */
1002fe8fb19SBen Gras    }
1012fe8fb19SBen Gras}
102f14fb602SLionel Sambuc#undef float_exception_mask
1032fe8fb19SBen Gras
1042fe8fb19SBen Gras/*
1052fe8fb19SBen Gras-------------------------------------------------------------------------------
1062fe8fb19SBen GrasInternal canonical NaN format.
1072fe8fb19SBen Gras-------------------------------------------------------------------------------
1082fe8fb19SBen Gras*/
1092fe8fb19SBen Grastypedef struct {
1102fe8fb19SBen Gras    flag sign;
1112fe8fb19SBen Gras    bits64 high, low;
1122fe8fb19SBen Gras} commonNaNT;
1132fe8fb19SBen Gras
1142fe8fb19SBen Gras/*
1152fe8fb19SBen Gras-------------------------------------------------------------------------------
1162fe8fb19SBen GrasThe pattern for a default generated single-precision NaN.
1172fe8fb19SBen Gras-------------------------------------------------------------------------------
1182fe8fb19SBen Gras*/
1192fe8fb19SBen Gras#define float32_default_nan 0xFFFFFFFF
1202fe8fb19SBen Gras
1212fe8fb19SBen Gras/*
1222fe8fb19SBen Gras-------------------------------------------------------------------------------
1232fe8fb19SBen GrasReturns 1 if the single-precision floating-point value `a' is a NaN;
1242fe8fb19SBen Grasotherwise returns 0.
1252fe8fb19SBen Gras-------------------------------------------------------------------------------
1262fe8fb19SBen Gras*/
1272fe8fb19SBen Gras#ifdef SOFTFLOAT_FOR_GCC
1282fe8fb19SBen Grasstatic
1292fe8fb19SBen Gras#endif
1302fe8fb19SBen Grasflag float32_is_nan( float32 a )
1312fe8fb19SBen Gras{
1322fe8fb19SBen Gras
133f14fb602SLionel Sambuc    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
1342fe8fb19SBen Gras
1352fe8fb19SBen Gras}
1362fe8fb19SBen Gras
1372fe8fb19SBen Gras/*
1382fe8fb19SBen Gras-------------------------------------------------------------------------------
1392fe8fb19SBen GrasReturns 1 if the single-precision floating-point value `a' is a signaling
1402fe8fb19SBen GrasNaN; otherwise returns 0.
1412fe8fb19SBen Gras-------------------------------------------------------------------------------
1422fe8fb19SBen Gras*/
143*0a6a1f1dSLionel Sambuc#if defined(SOFTFLOAT_FOR_GCC) \
144*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
145*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
146*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATM68K_FOR_GCC)
1472fe8fb19SBen Grasstatic
1482fe8fb19SBen Gras#endif
1492fe8fb19SBen Grasflag float32_is_signaling_nan( float32 a )
1502fe8fb19SBen Gras{
1512fe8fb19SBen Gras
1522fe8fb19SBen Gras    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
1532fe8fb19SBen Gras
1542fe8fb19SBen Gras}
1552fe8fb19SBen Gras
1562fe8fb19SBen Gras/*
1572fe8fb19SBen Gras-------------------------------------------------------------------------------
1582fe8fb19SBen GrasReturns the result of converting the single-precision floating-point NaN
1592fe8fb19SBen Gras`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
1602fe8fb19SBen Grasexception is raised.
1612fe8fb19SBen Gras-------------------------------------------------------------------------------
1622fe8fb19SBen Gras*/
1632fe8fb19SBen Grasstatic commonNaNT float32ToCommonNaN( float32 a )
1642fe8fb19SBen Gras{
1652fe8fb19SBen Gras    commonNaNT z;
1662fe8fb19SBen Gras
1672fe8fb19SBen Gras    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
1682fe8fb19SBen Gras    z.sign = a>>31;
1692fe8fb19SBen Gras    z.low = 0;
1702fe8fb19SBen Gras    z.high = ( (bits64) a )<<41;
1712fe8fb19SBen Gras    return z;
1722fe8fb19SBen Gras
1732fe8fb19SBen Gras}
1742fe8fb19SBen Gras
1752fe8fb19SBen Gras/*
1762fe8fb19SBen Gras-------------------------------------------------------------------------------
1772fe8fb19SBen GrasReturns the result of converting the canonical NaN `a' to the single-
1782fe8fb19SBen Grasprecision floating-point format.
1792fe8fb19SBen Gras-------------------------------------------------------------------------------
1802fe8fb19SBen Gras*/
1812fe8fb19SBen Grasstatic float32 commonNaNToFloat32( commonNaNT a )
1822fe8fb19SBen Gras{
1832fe8fb19SBen Gras
184f14fb602SLionel Sambuc    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
1852fe8fb19SBen Gras
1862fe8fb19SBen Gras}
1872fe8fb19SBen Gras
1882fe8fb19SBen Gras/*
1892fe8fb19SBen Gras-------------------------------------------------------------------------------
1902fe8fb19SBen GrasTakes two single-precision floating-point values `a' and `b', one of which
1912fe8fb19SBen Grasis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
1922fe8fb19SBen Grassignaling NaN, the invalid exception is raised.
1932fe8fb19SBen Gras-------------------------------------------------------------------------------
1942fe8fb19SBen Gras*/
1952fe8fb19SBen Grasstatic float32 propagateFloat32NaN( float32 a, float32 b )
1962fe8fb19SBen Gras{
1972fe8fb19SBen Gras    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
1982fe8fb19SBen Gras
1992fe8fb19SBen Gras    aIsNaN = float32_is_nan( a );
2002fe8fb19SBen Gras    aIsSignalingNaN = float32_is_signaling_nan( a );
2012fe8fb19SBen Gras    bIsNaN = float32_is_nan( b );
2022fe8fb19SBen Gras    bIsSignalingNaN = float32_is_signaling_nan( b );
2032fe8fb19SBen Gras    a |= 0x00400000;
2042fe8fb19SBen Gras    b |= 0x00400000;
2052fe8fb19SBen Gras    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
2062fe8fb19SBen Gras    if ( aIsNaN ) {
2072fe8fb19SBen Gras        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
2082fe8fb19SBen Gras    }
2092fe8fb19SBen Gras    else {
2102fe8fb19SBen Gras        return b;
2112fe8fb19SBen Gras    }
2122fe8fb19SBen Gras
2132fe8fb19SBen Gras}
2142fe8fb19SBen Gras
2152fe8fb19SBen Gras/*
2162fe8fb19SBen Gras-------------------------------------------------------------------------------
2172fe8fb19SBen GrasThe pattern for a default generated double-precision NaN.
2182fe8fb19SBen Gras-------------------------------------------------------------------------------
2192fe8fb19SBen Gras*/
2202fe8fb19SBen Gras#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
2212fe8fb19SBen Gras
2222fe8fb19SBen Gras/*
2232fe8fb19SBen Gras-------------------------------------------------------------------------------
2242fe8fb19SBen GrasReturns 1 if the double-precision floating-point value `a' is a NaN;
2252fe8fb19SBen Grasotherwise returns 0.
2262fe8fb19SBen Gras-------------------------------------------------------------------------------
2272fe8fb19SBen Gras*/
2282fe8fb19SBen Gras#ifdef SOFTFLOAT_FOR_GCC
2292fe8fb19SBen Grasstatic
2302fe8fb19SBen Gras#endif
2312fe8fb19SBen Grasflag float64_is_nan( float64 a )
2322fe8fb19SBen Gras{
2332fe8fb19SBen Gras
234f14fb602SLionel Sambuc    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
2352fe8fb19SBen Gras	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
2362fe8fb19SBen Gras
2372fe8fb19SBen Gras}
2382fe8fb19SBen Gras
2392fe8fb19SBen Gras/*
2402fe8fb19SBen Gras-------------------------------------------------------------------------------
2412fe8fb19SBen GrasReturns 1 if the double-precision floating-point value `a' is a signaling
2422fe8fb19SBen GrasNaN; otherwise returns 0.
2432fe8fb19SBen Gras-------------------------------------------------------------------------------
2442fe8fb19SBen Gras*/
245*0a6a1f1dSLionel Sambuc#if defined(SOFTFLOAT_FOR_GCC) \
246*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
247*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
248*0a6a1f1dSLionel Sambuc    && !defined(SOFTFLOATM68K_FOR_GCC)
2492fe8fb19SBen Grasstatic
2502fe8fb19SBen Gras#endif
2512fe8fb19SBen Grasflag float64_is_signaling_nan( float64 a )
2522fe8fb19SBen Gras{
2532fe8fb19SBen Gras
2542fe8fb19SBen Gras    return
2552fe8fb19SBen Gras           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
2562fe8fb19SBen Gras        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
2572fe8fb19SBen Gras
2582fe8fb19SBen Gras}
2592fe8fb19SBen Gras
2602fe8fb19SBen Gras/*
2612fe8fb19SBen Gras-------------------------------------------------------------------------------
2622fe8fb19SBen GrasReturns the result of converting the double-precision floating-point NaN
2632fe8fb19SBen Gras`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
2642fe8fb19SBen Grasexception is raised.
2652fe8fb19SBen Gras-------------------------------------------------------------------------------
2662fe8fb19SBen Gras*/
2672fe8fb19SBen Grasstatic commonNaNT float64ToCommonNaN( float64 a )
2682fe8fb19SBen Gras{
2692fe8fb19SBen Gras    commonNaNT z;
2702fe8fb19SBen Gras
2712fe8fb19SBen Gras    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
272f14fb602SLionel Sambuc    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
2732fe8fb19SBen Gras    z.low = 0;
2742fe8fb19SBen Gras    z.high = FLOAT64_DEMANGLE(a)<<12;
2752fe8fb19SBen Gras    return z;
2762fe8fb19SBen Gras
2772fe8fb19SBen Gras}
2782fe8fb19SBen Gras
2792fe8fb19SBen Gras/*
2802fe8fb19SBen Gras-------------------------------------------------------------------------------
2812fe8fb19SBen GrasReturns the result of converting the canonical NaN `a' to the double-
2822fe8fb19SBen Grasprecision floating-point format.
2832fe8fb19SBen Gras-------------------------------------------------------------------------------
2842fe8fb19SBen Gras*/
2852fe8fb19SBen Grasstatic float64 commonNaNToFloat64( commonNaNT a )
2862fe8fb19SBen Gras{
2872fe8fb19SBen Gras
2882fe8fb19SBen Gras    return FLOAT64_MANGLE(
2892fe8fb19SBen Gras	( ( (bits64) a.sign )<<63 )
2902fe8fb19SBen Gras        | LIT64( 0x7FF8000000000000 )
2912fe8fb19SBen Gras        | ( a.high>>12 ) );
2922fe8fb19SBen Gras
2932fe8fb19SBen Gras}
2942fe8fb19SBen Gras
2952fe8fb19SBen Gras/*
2962fe8fb19SBen Gras-------------------------------------------------------------------------------
2972fe8fb19SBen GrasTakes two double-precision floating-point values `a' and `b', one of which
2982fe8fb19SBen Grasis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
2992fe8fb19SBen Grassignaling NaN, the invalid exception is raised.
3002fe8fb19SBen Gras-------------------------------------------------------------------------------
3012fe8fb19SBen Gras*/
3022fe8fb19SBen Grasstatic float64 propagateFloat64NaN( float64 a, float64 b )
3032fe8fb19SBen Gras{
3042fe8fb19SBen Gras    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
3052fe8fb19SBen Gras
3062fe8fb19SBen Gras    aIsNaN = float64_is_nan( a );
3072fe8fb19SBen Gras    aIsSignalingNaN = float64_is_signaling_nan( a );
3082fe8fb19SBen Gras    bIsNaN = float64_is_nan( b );
3092fe8fb19SBen Gras    bIsSignalingNaN = float64_is_signaling_nan( b );
3102fe8fb19SBen Gras    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
3112fe8fb19SBen Gras    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
3122fe8fb19SBen Gras    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
3132fe8fb19SBen Gras    if ( aIsNaN ) {
3142fe8fb19SBen Gras        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
3152fe8fb19SBen Gras    }
3162fe8fb19SBen Gras    else {
3172fe8fb19SBen Gras        return b;
3182fe8fb19SBen Gras    }
3192fe8fb19SBen Gras
3202fe8fb19SBen Gras}
3212fe8fb19SBen Gras
3222fe8fb19SBen Gras#ifdef FLOATX80
3232fe8fb19SBen Gras
3242fe8fb19SBen Gras/*
3252fe8fb19SBen Gras-------------------------------------------------------------------------------
3262fe8fb19SBen GrasThe pattern for a default generated extended double-precision NaN.  The
3272fe8fb19SBen Gras`high' and `low' values hold the most- and least-significant bits,
3282fe8fb19SBen Grasrespectively.
3292fe8fb19SBen Gras-------------------------------------------------------------------------------
3302fe8fb19SBen Gras*/
3312fe8fb19SBen Gras#define floatx80_default_nan_high 0xFFFF
3322fe8fb19SBen Gras#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
3332fe8fb19SBen Gras
3342fe8fb19SBen Gras/*
3352fe8fb19SBen Gras-------------------------------------------------------------------------------
3362fe8fb19SBen GrasReturns 1 if the extended double-precision floating-point value `a' is a
3372fe8fb19SBen GrasNaN; otherwise returns 0.
3382fe8fb19SBen Gras-------------------------------------------------------------------------------
3392fe8fb19SBen Gras*/
3402fe8fb19SBen Grasflag floatx80_is_nan( floatx80 a )
3412fe8fb19SBen Gras{
3422fe8fb19SBen Gras
3432fe8fb19SBen Gras    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
3442fe8fb19SBen Gras
3452fe8fb19SBen Gras}
3462fe8fb19SBen Gras
3472fe8fb19SBen Gras/*
3482fe8fb19SBen Gras-------------------------------------------------------------------------------
3492fe8fb19SBen GrasReturns 1 if the extended double-precision floating-point value `a' is a
3502fe8fb19SBen Grassignaling NaN; otherwise returns 0.
3512fe8fb19SBen Gras-------------------------------------------------------------------------------
3522fe8fb19SBen Gras*/
3532fe8fb19SBen Grasflag floatx80_is_signaling_nan( floatx80 a )
3542fe8fb19SBen Gras{
3552fe8fb19SBen Gras    bits64 aLow;
3562fe8fb19SBen Gras
3572fe8fb19SBen Gras    aLow = a.low & ~ LIT64( 0x4000000000000000 );
3582fe8fb19SBen Gras    return
3592fe8fb19SBen Gras           ( ( a.high & 0x7FFF ) == 0x7FFF )
3602fe8fb19SBen Gras        && (bits64) ( aLow<<1 )
3612fe8fb19SBen Gras        && ( a.low == aLow );
3622fe8fb19SBen Gras
3632fe8fb19SBen Gras}
3642fe8fb19SBen Gras
3652fe8fb19SBen Gras/*
3662fe8fb19SBen Gras-------------------------------------------------------------------------------
3672fe8fb19SBen GrasReturns the result of converting the extended double-precision floating-
3682fe8fb19SBen Graspoint NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
3692fe8fb19SBen Grasinvalid exception is raised.
3702fe8fb19SBen Gras-------------------------------------------------------------------------------
3712fe8fb19SBen Gras*/
3722fe8fb19SBen Grasstatic commonNaNT floatx80ToCommonNaN( floatx80 a )
3732fe8fb19SBen Gras{
3742fe8fb19SBen Gras    commonNaNT z;
3752fe8fb19SBen Gras
3762fe8fb19SBen Gras    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
3772fe8fb19SBen Gras    z.sign = a.high>>15;
3782fe8fb19SBen Gras    z.low = 0;
3792fe8fb19SBen Gras    z.high = a.low<<1;
3802fe8fb19SBen Gras    return z;
3812fe8fb19SBen Gras
3822fe8fb19SBen Gras}
3832fe8fb19SBen Gras
3842fe8fb19SBen Gras/*
3852fe8fb19SBen Gras-------------------------------------------------------------------------------
3862fe8fb19SBen GrasReturns the result of converting the canonical NaN `a' to the extended
3872fe8fb19SBen Grasdouble-precision floating-point format.
3882fe8fb19SBen Gras-------------------------------------------------------------------------------
3892fe8fb19SBen Gras*/
3902fe8fb19SBen Grasstatic floatx80 commonNaNToFloatx80( commonNaNT a )
3912fe8fb19SBen Gras{
3922fe8fb19SBen Gras    floatx80 z;
3932fe8fb19SBen Gras
3942fe8fb19SBen Gras    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
3952fe8fb19SBen Gras    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
3962fe8fb19SBen Gras    return z;
3972fe8fb19SBen Gras
3982fe8fb19SBen Gras}
3992fe8fb19SBen Gras
4002fe8fb19SBen Gras/*
4012fe8fb19SBen Gras-------------------------------------------------------------------------------
4022fe8fb19SBen GrasTakes two extended double-precision floating-point values `a' and `b', one
4032fe8fb19SBen Grasof which is a NaN, and returns the appropriate NaN result.  If either `a' or
4042fe8fb19SBen Gras`b' is a signaling NaN, the invalid exception is raised.
4052fe8fb19SBen Gras-------------------------------------------------------------------------------
4062fe8fb19SBen Gras*/
4072fe8fb19SBen Grasstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
4082fe8fb19SBen Gras{
4092fe8fb19SBen Gras    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
4102fe8fb19SBen Gras
4112fe8fb19SBen Gras    aIsNaN = floatx80_is_nan( a );
4122fe8fb19SBen Gras    aIsSignalingNaN = floatx80_is_signaling_nan( a );
4132fe8fb19SBen Gras    bIsNaN = floatx80_is_nan( b );
4142fe8fb19SBen Gras    bIsSignalingNaN = floatx80_is_signaling_nan( b );
4152fe8fb19SBen Gras    a.low |= LIT64( 0xC000000000000000 );
4162fe8fb19SBen Gras    b.low |= LIT64( 0xC000000000000000 );
4172fe8fb19SBen Gras    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
4182fe8fb19SBen Gras    if ( aIsNaN ) {
4192fe8fb19SBen Gras        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
4202fe8fb19SBen Gras    }
4212fe8fb19SBen Gras    else {
4222fe8fb19SBen Gras        return b;
4232fe8fb19SBen Gras    }
4242fe8fb19SBen Gras
4252fe8fb19SBen Gras}
4262fe8fb19SBen Gras
4272fe8fb19SBen Gras#endif
4282fe8fb19SBen Gras
4292fe8fb19SBen Gras#ifdef FLOAT128
4302fe8fb19SBen Gras
4312fe8fb19SBen Gras/*
4322fe8fb19SBen Gras-------------------------------------------------------------------------------
4332fe8fb19SBen GrasThe pattern for a default generated quadruple-precision NaN.  The `high' and
4342fe8fb19SBen Gras`low' values hold the most- and least-significant bits, respectively.
4352fe8fb19SBen Gras-------------------------------------------------------------------------------
4362fe8fb19SBen Gras*/
4372fe8fb19SBen Gras#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
4382fe8fb19SBen Gras#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
4392fe8fb19SBen Gras
4402fe8fb19SBen Gras/*
4412fe8fb19SBen Gras-------------------------------------------------------------------------------
4422fe8fb19SBen GrasReturns 1 if the quadruple-precision floating-point value `a' is a NaN;
4432fe8fb19SBen Grasotherwise returns 0.
4442fe8fb19SBen Gras-------------------------------------------------------------------------------
4452fe8fb19SBen Gras*/
4462fe8fb19SBen Grasflag float128_is_nan( float128 a )
4472fe8fb19SBen Gras{
4482fe8fb19SBen Gras
4492fe8fb19SBen Gras    return
450f14fb602SLionel Sambuc           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
4512fe8fb19SBen Gras        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
4522fe8fb19SBen Gras
4532fe8fb19SBen Gras}
4542fe8fb19SBen Gras
4552fe8fb19SBen Gras/*
4562fe8fb19SBen Gras-------------------------------------------------------------------------------
4572fe8fb19SBen GrasReturns 1 if the quadruple-precision floating-point value `a' is a
4582fe8fb19SBen Grassignaling NaN; otherwise returns 0.
4592fe8fb19SBen Gras-------------------------------------------------------------------------------
4602fe8fb19SBen Gras*/
4612fe8fb19SBen Grasflag float128_is_signaling_nan( float128 a )
4622fe8fb19SBen Gras{
4632fe8fb19SBen Gras
4642fe8fb19SBen Gras    return
4652fe8fb19SBen Gras           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
4662fe8fb19SBen Gras        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
4672fe8fb19SBen Gras
4682fe8fb19SBen Gras}
4692fe8fb19SBen Gras
4702fe8fb19SBen Gras/*
4712fe8fb19SBen Gras-------------------------------------------------------------------------------
4722fe8fb19SBen GrasReturns the result of converting the quadruple-precision floating-point NaN
4732fe8fb19SBen Gras`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
4742fe8fb19SBen Grasexception is raised.
4752fe8fb19SBen Gras-------------------------------------------------------------------------------
4762fe8fb19SBen Gras*/
4772fe8fb19SBen Grasstatic commonNaNT float128ToCommonNaN( float128 a )
4782fe8fb19SBen Gras{
4792fe8fb19SBen Gras    commonNaNT z;
4802fe8fb19SBen Gras
4812fe8fb19SBen Gras    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
482f14fb602SLionel Sambuc    z.sign = (flag)(a.high>>63);
4832fe8fb19SBen Gras    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
4842fe8fb19SBen Gras    return z;
4852fe8fb19SBen Gras
4862fe8fb19SBen Gras}
4872fe8fb19SBen Gras
4882fe8fb19SBen Gras/*
4892fe8fb19SBen Gras-------------------------------------------------------------------------------
4902fe8fb19SBen GrasReturns the result of converting the canonical NaN `a' to the quadruple-
4912fe8fb19SBen Grasprecision floating-point format.
4922fe8fb19SBen Gras-------------------------------------------------------------------------------
4932fe8fb19SBen Gras*/
4942fe8fb19SBen Grasstatic float128 commonNaNToFloat128( commonNaNT a )
4952fe8fb19SBen Gras{
4962fe8fb19SBen Gras    float128 z;
4972fe8fb19SBen Gras
4982fe8fb19SBen Gras    shift128Right( a.high, a.low, 16, &z.high, &z.low );
4992fe8fb19SBen Gras    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
5002fe8fb19SBen Gras    return z;
5012fe8fb19SBen Gras
5022fe8fb19SBen Gras}
5032fe8fb19SBen Gras
5042fe8fb19SBen Gras/*
5052fe8fb19SBen Gras-------------------------------------------------------------------------------
5062fe8fb19SBen GrasTakes two quadruple-precision floating-point values `a' and `b', one of
5072fe8fb19SBen Graswhich is a NaN, and returns the appropriate NaN result.  If either `a' or
5082fe8fb19SBen Gras`b' is a signaling NaN, the invalid exception is raised.
5092fe8fb19SBen Gras-------------------------------------------------------------------------------
5102fe8fb19SBen Gras*/
5112fe8fb19SBen Grasstatic float128 propagateFloat128NaN( float128 a, float128 b )
5122fe8fb19SBen Gras{
5132fe8fb19SBen Gras    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
5142fe8fb19SBen Gras
5152fe8fb19SBen Gras    aIsNaN = float128_is_nan( a );
5162fe8fb19SBen Gras    aIsSignalingNaN = float128_is_signaling_nan( a );
5172fe8fb19SBen Gras    bIsNaN = float128_is_nan( b );
5182fe8fb19SBen Gras    bIsSignalingNaN = float128_is_signaling_nan( b );
5192fe8fb19SBen Gras    a.high |= LIT64( 0x0000800000000000 );
5202fe8fb19SBen Gras    b.high |= LIT64( 0x0000800000000000 );
5212fe8fb19SBen Gras    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
5222fe8fb19SBen Gras    if ( aIsNaN ) {
5232fe8fb19SBen Gras        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
5242fe8fb19SBen Gras    }
5252fe8fb19SBen Gras    else {
5262fe8fb19SBen Gras        return b;
5272fe8fb19SBen Gras    }
5282fe8fb19SBen Gras
5292fe8fb19SBen Gras}
5302fe8fb19SBen Gras
5312fe8fb19SBen Gras#endif
5322fe8fb19SBen Gras
533