xref: /netbsd-src/lib/libc/softfloat/softfloat-specialize (revision 547b3a3b01258cc76b6903d55f3bbdd59e7003a6)
1*547b3a3bSmatt/*	$NetBSD: softfloat-specialize,v 1.9 2014/08/10 05:57:31 matt Exp $	*/
2010758bfSbjh21
3010758bfSbjh21/* This is a derivative work. */
425540ecaSbjh21
525540ecaSbjh21/*
625540ecaSbjh21===============================================================================
725540ecaSbjh21
825540ecaSbjh21This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
925540ecaSbjh21Arithmetic Package, Release 2a.
1025540ecaSbjh21
1125540ecaSbjh21Written by John R. Hauser.  This work was made possible in part by the
1225540ecaSbjh21International Computer Science Institute, located at Suite 600, 1947 Center
1325540ecaSbjh21Street, Berkeley, California 94704.  Funding was partially provided by the
1425540ecaSbjh21National Science Foundation under grant MIP-9311980.  The original version
1525540ecaSbjh21of this code was written as part of a project to build a fixed-point vector
1625540ecaSbjh21processor in collaboration with the University of California at Berkeley,
1725540ecaSbjh21overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
1825540ecaSbjh21is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
1925540ecaSbjh21arithmetic/SoftFloat.html'.
2025540ecaSbjh21
2125540ecaSbjh21THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
2225540ecaSbjh21has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
2325540ecaSbjh21TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
2425540ecaSbjh21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
2525540ecaSbjh21AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
2625540ecaSbjh21
2725540ecaSbjh21Derivative works are acceptable, even for commercial purposes, so long as
2825540ecaSbjh21(1) they include prominent notice that the work is derivative, and (2) they
2925540ecaSbjh21include prominent notice akin to these four paragraphs for those parts of
3025540ecaSbjh21this code that are retained.
3125540ecaSbjh21
3225540ecaSbjh21===============================================================================
3325540ecaSbjh21*/
3425540ecaSbjh21
35010758bfSbjh21#include <signal.h>
36a5ad4202Smartin#include <string.h>
37a5ad4202Smartin#include <unistd.h>
38010758bfSbjh21
3925540ecaSbjh21/*
4025540ecaSbjh21-------------------------------------------------------------------------------
4125540ecaSbjh21Underflow tininess-detection mode, statically initialized to default value.
4225540ecaSbjh21(The declaration in `softfloat.h' must match the `int8' type here.)
4325540ecaSbjh21-------------------------------------------------------------------------------
4425540ecaSbjh21*/
4525540ecaSbjh21#ifdef SOFTFLOAT_FOR_GCC
4625540ecaSbjh21static
4725540ecaSbjh21#endif
4825540ecaSbjh21int8 float_detect_tininess = float_tininess_after_rounding;
4925540ecaSbjh21
5025540ecaSbjh21/*
5125540ecaSbjh21-------------------------------------------------------------------------------
5225540ecaSbjh21Raises the exceptions specified by `flags'.  Floating-point traps can be
5325540ecaSbjh21defined here if desired.  It is currently not possible for such a trap to
5425540ecaSbjh21substitute a result value.  If traps are not implemented, this routine
5525540ecaSbjh21should be simply `float_exception_flags |= flags;'.
5625540ecaSbjh21-------------------------------------------------------------------------------
5725540ecaSbjh21*/
58598174ebSmartin#ifdef SOFTFLOAT_FOR_GCC
59536ad833Smatt#ifndef set_float_exception_mask
60598174ebSmartin#define float_exception_mask	_softfloat_float_exception_mask
61598174ebSmartin#endif
62536ad833Smatt#endif
63536ad833Smatt#ifndef set_float_exception_mask
64010758bfSbjh21fp_except float_exception_mask = 0;
65536ad833Smatt#endif
66536ad833Smattvoid
67536ad833Smattfloat_raise( fp_except flags )
6825540ecaSbjh21{
69a5ad4202Smartin    siginfo_t info;
70536ad833Smatt    fp_except mask = float_exception_mask;
7125540ecaSbjh21
72536ad833Smatt#ifdef set_float_exception_mask
73536ad833Smatt    flags |= set_float_exception_flags(flags, 0);
74536ad833Smatt#else
7525540ecaSbjh21    float_exception_flags |= flags;
76536ad833Smatt    flags = float_exception_flags;
77536ad833Smatt#endif
7825540ecaSbjh21
79536ad833Smatt    flags &= mask;
80536ad833Smatt    if ( flags ) {
81a5ad4202Smartin	memset(&info, 0, sizeof info);
82a5ad4202Smartin	info.si_signo = SIGFPE;
83a5ad4202Smartin	info.si_pid = getpid();
84a5ad4202Smartin	info.si_uid = geteuid();
85a5ad4202Smartin	if (flags & float_flag_underflow)
86a5ad4202Smartin	    info.si_code = FPE_FLTUND;
87a5ad4202Smartin	else if (flags & float_flag_overflow)
88a5ad4202Smartin	    info.si_code = FPE_FLTOVF;
89a5ad4202Smartin	else if (flags & float_flag_divbyzero)
90a5ad4202Smartin	    info.si_code = FPE_FLTDIV;
91a5ad4202Smartin	else if (flags & float_flag_invalid)
92a5ad4202Smartin	    info.si_code = FPE_FLTINV;
93a5ad4202Smartin	else if (flags & float_flag_inexact)
94a5ad4202Smartin	    info.si_code = FPE_FLTRES;
95a5ad4202Smartin	sigqueueinfo(getpid(), &info);
96010758bfSbjh21    }
9725540ecaSbjh21}
98598174ebSmartin#undef float_exception_mask
9925540ecaSbjh21
10025540ecaSbjh21/*
10125540ecaSbjh21-------------------------------------------------------------------------------
10225540ecaSbjh21Internal canonical NaN format.
10325540ecaSbjh21-------------------------------------------------------------------------------
10425540ecaSbjh21*/
10525540ecaSbjh21typedef struct {
10625540ecaSbjh21    flag sign;
10725540ecaSbjh21    bits64 high, low;
10825540ecaSbjh21} commonNaNT;
10925540ecaSbjh21
11025540ecaSbjh21/*
11125540ecaSbjh21-------------------------------------------------------------------------------
11225540ecaSbjh21The pattern for a default generated single-precision NaN.
11325540ecaSbjh21-------------------------------------------------------------------------------
11425540ecaSbjh21*/
11525540ecaSbjh21#define float32_default_nan 0xFFFFFFFF
11625540ecaSbjh21
11725540ecaSbjh21/*
11825540ecaSbjh21-------------------------------------------------------------------------------
11925540ecaSbjh21Returns 1 if the single-precision floating-point value `a' is a NaN;
12025540ecaSbjh21otherwise returns 0.
12125540ecaSbjh21-------------------------------------------------------------------------------
12225540ecaSbjh21*/
12325540ecaSbjh21#ifdef SOFTFLOAT_FOR_GCC
12425540ecaSbjh21static
12525540ecaSbjh21#endif
12625540ecaSbjh21flag float32_is_nan( float32 a )
12725540ecaSbjh21{
12825540ecaSbjh21
12939052f3bSchristos    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
13025540ecaSbjh21
13125540ecaSbjh21}
13225540ecaSbjh21
13325540ecaSbjh21/*
13425540ecaSbjh21-------------------------------------------------------------------------------
13525540ecaSbjh21Returns 1 if the single-precision floating-point value `a' is a signaling
13625540ecaSbjh21NaN; otherwise returns 0.
13725540ecaSbjh21-------------------------------------------------------------------------------
13825540ecaSbjh21*/
139*547b3a3bSmatt#if defined(SOFTFLOAT_FOR_GCC) \
140*547b3a3bSmatt    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
141*547b3a3bSmatt    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
142*547b3a3bSmatt    && !defined(SOFTFLOATM68K_FOR_GCC)
14325540ecaSbjh21static
14425540ecaSbjh21#endif
14525540ecaSbjh21flag float32_is_signaling_nan( float32 a )
14625540ecaSbjh21{
14725540ecaSbjh21
14825540ecaSbjh21    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
14925540ecaSbjh21
15025540ecaSbjh21}
15125540ecaSbjh21
15225540ecaSbjh21/*
15325540ecaSbjh21-------------------------------------------------------------------------------
15425540ecaSbjh21Returns the result of converting the single-precision floating-point NaN
15525540ecaSbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
15625540ecaSbjh21exception is raised.
15725540ecaSbjh21-------------------------------------------------------------------------------
15825540ecaSbjh21*/
15925540ecaSbjh21static commonNaNT float32ToCommonNaN( float32 a )
16025540ecaSbjh21{
16125540ecaSbjh21    commonNaNT z;
16225540ecaSbjh21
16325540ecaSbjh21    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
16425540ecaSbjh21    z.sign = a>>31;
16525540ecaSbjh21    z.low = 0;
16625540ecaSbjh21    z.high = ( (bits64) a )<<41;
16725540ecaSbjh21    return z;
16825540ecaSbjh21
16925540ecaSbjh21}
17025540ecaSbjh21
17125540ecaSbjh21/*
17225540ecaSbjh21-------------------------------------------------------------------------------
17325540ecaSbjh21Returns the result of converting the canonical NaN `a' to the single-
17425540ecaSbjh21precision floating-point format.
17525540ecaSbjh21-------------------------------------------------------------------------------
17625540ecaSbjh21*/
17725540ecaSbjh21static float32 commonNaNToFloat32( commonNaNT a )
17825540ecaSbjh21{
17925540ecaSbjh21
18039052f3bSchristos    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
18125540ecaSbjh21
18225540ecaSbjh21}
18325540ecaSbjh21
18425540ecaSbjh21/*
18525540ecaSbjh21-------------------------------------------------------------------------------
18625540ecaSbjh21Takes two single-precision floating-point values `a' and `b', one of which
18725540ecaSbjh21is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
18825540ecaSbjh21signaling NaN, the invalid exception is raised.
18925540ecaSbjh21-------------------------------------------------------------------------------
19025540ecaSbjh21*/
19125540ecaSbjh21static float32 propagateFloat32NaN( float32 a, float32 b )
19225540ecaSbjh21{
19325540ecaSbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
19425540ecaSbjh21
19525540ecaSbjh21    aIsNaN = float32_is_nan( a );
19625540ecaSbjh21    aIsSignalingNaN = float32_is_signaling_nan( a );
19725540ecaSbjh21    bIsNaN = float32_is_nan( b );
19825540ecaSbjh21    bIsSignalingNaN = float32_is_signaling_nan( b );
19925540ecaSbjh21    a |= 0x00400000;
20025540ecaSbjh21    b |= 0x00400000;
20125540ecaSbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
20225540ecaSbjh21    if ( aIsNaN ) {
20325540ecaSbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
20425540ecaSbjh21    }
20525540ecaSbjh21    else {
20625540ecaSbjh21        return b;
20725540ecaSbjh21    }
20825540ecaSbjh21
20925540ecaSbjh21}
21025540ecaSbjh21
21125540ecaSbjh21/*
21225540ecaSbjh21-------------------------------------------------------------------------------
21325540ecaSbjh21The pattern for a default generated double-precision NaN.
21425540ecaSbjh21-------------------------------------------------------------------------------
21525540ecaSbjh21*/
21625540ecaSbjh21#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
21725540ecaSbjh21
21825540ecaSbjh21/*
21925540ecaSbjh21-------------------------------------------------------------------------------
22025540ecaSbjh21Returns 1 if the double-precision floating-point value `a' is a NaN;
22125540ecaSbjh21otherwise returns 0.
22225540ecaSbjh21-------------------------------------------------------------------------------
22325540ecaSbjh21*/
22425540ecaSbjh21#ifdef SOFTFLOAT_FOR_GCC
22525540ecaSbjh21static
22625540ecaSbjh21#endif
22725540ecaSbjh21flag float64_is_nan( float64 a )
22825540ecaSbjh21{
22925540ecaSbjh21
23039052f3bSchristos    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
23125540ecaSbjh21	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
23225540ecaSbjh21
23325540ecaSbjh21}
23425540ecaSbjh21
23525540ecaSbjh21/*
23625540ecaSbjh21-------------------------------------------------------------------------------
23725540ecaSbjh21Returns 1 if the double-precision floating-point value `a' is a signaling
23825540ecaSbjh21NaN; otherwise returns 0.
23925540ecaSbjh21-------------------------------------------------------------------------------
24025540ecaSbjh21*/
241*547b3a3bSmatt#if defined(SOFTFLOAT_FOR_GCC) \
242*547b3a3bSmatt    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
243*547b3a3bSmatt    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
244*547b3a3bSmatt    && !defined(SOFTFLOATM68K_FOR_GCC)
24525540ecaSbjh21static
24625540ecaSbjh21#endif
24725540ecaSbjh21flag float64_is_signaling_nan( float64 a )
24825540ecaSbjh21{
24925540ecaSbjh21
25025540ecaSbjh21    return
25125540ecaSbjh21           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
25225540ecaSbjh21        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
25325540ecaSbjh21
25425540ecaSbjh21}
25525540ecaSbjh21
25625540ecaSbjh21/*
25725540ecaSbjh21-------------------------------------------------------------------------------
25825540ecaSbjh21Returns the result of converting the double-precision floating-point NaN
25925540ecaSbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
26025540ecaSbjh21exception is raised.
26125540ecaSbjh21-------------------------------------------------------------------------------
26225540ecaSbjh21*/
26325540ecaSbjh21static commonNaNT float64ToCommonNaN( float64 a )
26425540ecaSbjh21{
26525540ecaSbjh21    commonNaNT z;
26625540ecaSbjh21
26725540ecaSbjh21    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
26839052f3bSchristos    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
26925540ecaSbjh21    z.low = 0;
27025540ecaSbjh21    z.high = FLOAT64_DEMANGLE(a)<<12;
27125540ecaSbjh21    return z;
27225540ecaSbjh21
27325540ecaSbjh21}
27425540ecaSbjh21
27525540ecaSbjh21/*
27625540ecaSbjh21-------------------------------------------------------------------------------
27725540ecaSbjh21Returns the result of converting the canonical NaN `a' to the double-
27825540ecaSbjh21precision floating-point format.
27925540ecaSbjh21-------------------------------------------------------------------------------
28025540ecaSbjh21*/
28125540ecaSbjh21static float64 commonNaNToFloat64( commonNaNT a )
28225540ecaSbjh21{
28325540ecaSbjh21
28425540ecaSbjh21    return FLOAT64_MANGLE(
28525540ecaSbjh21	( ( (bits64) a.sign )<<63 )
28625540ecaSbjh21        | LIT64( 0x7FF8000000000000 )
28725540ecaSbjh21        | ( a.high>>12 ) );
28825540ecaSbjh21
28925540ecaSbjh21}
29025540ecaSbjh21
29125540ecaSbjh21/*
29225540ecaSbjh21-------------------------------------------------------------------------------
29325540ecaSbjh21Takes two double-precision floating-point values `a' and `b', one of which
29425540ecaSbjh21is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
29525540ecaSbjh21signaling NaN, the invalid exception is raised.
29625540ecaSbjh21-------------------------------------------------------------------------------
29725540ecaSbjh21*/
29825540ecaSbjh21static float64 propagateFloat64NaN( float64 a, float64 b )
29925540ecaSbjh21{
30025540ecaSbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
30125540ecaSbjh21
30225540ecaSbjh21    aIsNaN = float64_is_nan( a );
30325540ecaSbjh21    aIsSignalingNaN = float64_is_signaling_nan( a );
30425540ecaSbjh21    bIsNaN = float64_is_nan( b );
30525540ecaSbjh21    bIsSignalingNaN = float64_is_signaling_nan( b );
30625540ecaSbjh21    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
30725540ecaSbjh21    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
30825540ecaSbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
30925540ecaSbjh21    if ( aIsNaN ) {
31025540ecaSbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
31125540ecaSbjh21    }
31225540ecaSbjh21    else {
31325540ecaSbjh21        return b;
31425540ecaSbjh21    }
31525540ecaSbjh21
31625540ecaSbjh21}
31725540ecaSbjh21
31825540ecaSbjh21#ifdef FLOATX80
31925540ecaSbjh21
32025540ecaSbjh21/*
32125540ecaSbjh21-------------------------------------------------------------------------------
32225540ecaSbjh21The pattern for a default generated extended double-precision NaN.  The
32325540ecaSbjh21`high' and `low' values hold the most- and least-significant bits,
32425540ecaSbjh21respectively.
32525540ecaSbjh21-------------------------------------------------------------------------------
32625540ecaSbjh21*/
32725540ecaSbjh21#define floatx80_default_nan_high 0xFFFF
32825540ecaSbjh21#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
32925540ecaSbjh21
33025540ecaSbjh21/*
33125540ecaSbjh21-------------------------------------------------------------------------------
33225540ecaSbjh21Returns 1 if the extended double-precision floating-point value `a' is a
33325540ecaSbjh21NaN; otherwise returns 0.
33425540ecaSbjh21-------------------------------------------------------------------------------
33525540ecaSbjh21*/
33625540ecaSbjh21flag floatx80_is_nan( floatx80 a )
33725540ecaSbjh21{
33825540ecaSbjh21
33925540ecaSbjh21    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
34025540ecaSbjh21
34125540ecaSbjh21}
34225540ecaSbjh21
34325540ecaSbjh21/*
34425540ecaSbjh21-------------------------------------------------------------------------------
34525540ecaSbjh21Returns 1 if the extended double-precision floating-point value `a' is a
34625540ecaSbjh21signaling NaN; otherwise returns 0.
34725540ecaSbjh21-------------------------------------------------------------------------------
34825540ecaSbjh21*/
34925540ecaSbjh21flag floatx80_is_signaling_nan( floatx80 a )
35025540ecaSbjh21{
35125540ecaSbjh21    bits64 aLow;
35225540ecaSbjh21
35325540ecaSbjh21    aLow = a.low & ~ LIT64( 0x4000000000000000 );
35425540ecaSbjh21    return
35525540ecaSbjh21           ( ( a.high & 0x7FFF ) == 0x7FFF )
35625540ecaSbjh21        && (bits64) ( aLow<<1 )
35725540ecaSbjh21        && ( a.low == aLow );
35825540ecaSbjh21
35925540ecaSbjh21}
36025540ecaSbjh21
36125540ecaSbjh21/*
36225540ecaSbjh21-------------------------------------------------------------------------------
36325540ecaSbjh21Returns the result of converting the extended double-precision floating-
36425540ecaSbjh21point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
36525540ecaSbjh21invalid exception is raised.
36625540ecaSbjh21-------------------------------------------------------------------------------
36725540ecaSbjh21*/
36825540ecaSbjh21static commonNaNT floatx80ToCommonNaN( floatx80 a )
36925540ecaSbjh21{
37025540ecaSbjh21    commonNaNT z;
37125540ecaSbjh21
37225540ecaSbjh21    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
37325540ecaSbjh21    z.sign = a.high>>15;
37425540ecaSbjh21    z.low = 0;
37525540ecaSbjh21    z.high = a.low<<1;
37625540ecaSbjh21    return z;
37725540ecaSbjh21
37825540ecaSbjh21}
37925540ecaSbjh21
38025540ecaSbjh21/*
38125540ecaSbjh21-------------------------------------------------------------------------------
38225540ecaSbjh21Returns the result of converting the canonical NaN `a' to the extended
38325540ecaSbjh21double-precision floating-point format.
38425540ecaSbjh21-------------------------------------------------------------------------------
38525540ecaSbjh21*/
38625540ecaSbjh21static floatx80 commonNaNToFloatx80( commonNaNT a )
38725540ecaSbjh21{
38825540ecaSbjh21    floatx80 z;
38925540ecaSbjh21
39025540ecaSbjh21    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
39125540ecaSbjh21    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
39225540ecaSbjh21    return z;
39325540ecaSbjh21
39425540ecaSbjh21}
39525540ecaSbjh21
39625540ecaSbjh21/*
39725540ecaSbjh21-------------------------------------------------------------------------------
39825540ecaSbjh21Takes two extended double-precision floating-point values `a' and `b', one
39925540ecaSbjh21of which is a NaN, and returns the appropriate NaN result.  If either `a' or
40025540ecaSbjh21`b' is a signaling NaN, the invalid exception is raised.
40125540ecaSbjh21-------------------------------------------------------------------------------
40225540ecaSbjh21*/
40325540ecaSbjh21static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
40425540ecaSbjh21{
40525540ecaSbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
40625540ecaSbjh21
40725540ecaSbjh21    aIsNaN = floatx80_is_nan( a );
40825540ecaSbjh21    aIsSignalingNaN = floatx80_is_signaling_nan( a );
40925540ecaSbjh21    bIsNaN = floatx80_is_nan( b );
41025540ecaSbjh21    bIsSignalingNaN = floatx80_is_signaling_nan( b );
41125540ecaSbjh21    a.low |= LIT64( 0xC000000000000000 );
41225540ecaSbjh21    b.low |= LIT64( 0xC000000000000000 );
41325540ecaSbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
41425540ecaSbjh21    if ( aIsNaN ) {
41525540ecaSbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
41625540ecaSbjh21    }
41725540ecaSbjh21    else {
41825540ecaSbjh21        return b;
41925540ecaSbjh21    }
42025540ecaSbjh21
42125540ecaSbjh21}
42225540ecaSbjh21
42325540ecaSbjh21#endif
42425540ecaSbjh21
42525540ecaSbjh21#ifdef FLOAT128
42625540ecaSbjh21
42725540ecaSbjh21/*
42825540ecaSbjh21-------------------------------------------------------------------------------
42925540ecaSbjh21The pattern for a default generated quadruple-precision NaN.  The `high' and
43025540ecaSbjh21`low' values hold the most- and least-significant bits, respectively.
43125540ecaSbjh21-------------------------------------------------------------------------------
43225540ecaSbjh21*/
43325540ecaSbjh21#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
43425540ecaSbjh21#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
43525540ecaSbjh21
43625540ecaSbjh21/*
43725540ecaSbjh21-------------------------------------------------------------------------------
43825540ecaSbjh21Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
43925540ecaSbjh21otherwise returns 0.
44025540ecaSbjh21-------------------------------------------------------------------------------
44125540ecaSbjh21*/
44225540ecaSbjh21flag float128_is_nan( float128 a )
44325540ecaSbjh21{
44425540ecaSbjh21
44525540ecaSbjh21    return
44639052f3bSchristos           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
44725540ecaSbjh21        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
44825540ecaSbjh21
44925540ecaSbjh21}
45025540ecaSbjh21
45125540ecaSbjh21/*
45225540ecaSbjh21-------------------------------------------------------------------------------
45325540ecaSbjh21Returns 1 if the quadruple-precision floating-point value `a' is a
45425540ecaSbjh21signaling NaN; otherwise returns 0.
45525540ecaSbjh21-------------------------------------------------------------------------------
45625540ecaSbjh21*/
45725540ecaSbjh21flag float128_is_signaling_nan( float128 a )
45825540ecaSbjh21{
45925540ecaSbjh21
46025540ecaSbjh21    return
46125540ecaSbjh21           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
46225540ecaSbjh21        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
46325540ecaSbjh21
46425540ecaSbjh21}
46525540ecaSbjh21
46625540ecaSbjh21/*
46725540ecaSbjh21-------------------------------------------------------------------------------
46825540ecaSbjh21Returns the result of converting the quadruple-precision floating-point NaN
46925540ecaSbjh21`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
47025540ecaSbjh21exception is raised.
47125540ecaSbjh21-------------------------------------------------------------------------------
47225540ecaSbjh21*/
47325540ecaSbjh21static commonNaNT float128ToCommonNaN( float128 a )
47425540ecaSbjh21{
47525540ecaSbjh21    commonNaNT z;
47625540ecaSbjh21
47725540ecaSbjh21    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
47839052f3bSchristos    z.sign = (flag)(a.high>>63);
47925540ecaSbjh21    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
48025540ecaSbjh21    return z;
48125540ecaSbjh21
48225540ecaSbjh21}
48325540ecaSbjh21
48425540ecaSbjh21/*
48525540ecaSbjh21-------------------------------------------------------------------------------
48625540ecaSbjh21Returns the result of converting the canonical NaN `a' to the quadruple-
48725540ecaSbjh21precision floating-point format.
48825540ecaSbjh21-------------------------------------------------------------------------------
48925540ecaSbjh21*/
49025540ecaSbjh21static float128 commonNaNToFloat128( commonNaNT a )
49125540ecaSbjh21{
49225540ecaSbjh21    float128 z;
49325540ecaSbjh21
49425540ecaSbjh21    shift128Right( a.high, a.low, 16, &z.high, &z.low );
49525540ecaSbjh21    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
49625540ecaSbjh21    return z;
49725540ecaSbjh21
49825540ecaSbjh21}
49925540ecaSbjh21
50025540ecaSbjh21/*
50125540ecaSbjh21-------------------------------------------------------------------------------
50225540ecaSbjh21Takes two quadruple-precision floating-point values `a' and `b', one of
50325540ecaSbjh21which is a NaN, and returns the appropriate NaN result.  If either `a' or
50425540ecaSbjh21`b' is a signaling NaN, the invalid exception is raised.
50525540ecaSbjh21-------------------------------------------------------------------------------
50625540ecaSbjh21*/
50725540ecaSbjh21static float128 propagateFloat128NaN( float128 a, float128 b )
50825540ecaSbjh21{
50925540ecaSbjh21    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
51025540ecaSbjh21
51125540ecaSbjh21    aIsNaN = float128_is_nan( a );
51225540ecaSbjh21    aIsSignalingNaN = float128_is_signaling_nan( a );
51325540ecaSbjh21    bIsNaN = float128_is_nan( b );
51425540ecaSbjh21    bIsSignalingNaN = float128_is_signaling_nan( b );
51525540ecaSbjh21    a.high |= LIT64( 0x0000800000000000 );
51625540ecaSbjh21    b.high |= LIT64( 0x0000800000000000 );
51725540ecaSbjh21    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
51825540ecaSbjh21    if ( aIsNaN ) {
51925540ecaSbjh21        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
52025540ecaSbjh21    }
52125540ecaSbjh21    else {
52225540ecaSbjh21        return b;
52325540ecaSbjh21    }
52425540ecaSbjh21
52525540ecaSbjh21}
52625540ecaSbjh21
52725540ecaSbjh21#endif
52825540ecaSbjh21
529