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