softfloat-specialize revision 1.9
11.9Smatt/* $NetBSD: softfloat-specialize,v 1.9 2014/08/10 05:57:31 matt 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.1Sbjh21/* 401.1Sbjh21------------------------------------------------------------------------------- 411.1Sbjh21Underflow tininess-detection mode, statically initialized to default value. 421.1Sbjh21(The declaration in `softfloat.h' must match the `int8' type here.) 431.1Sbjh21------------------------------------------------------------------------------- 441.1Sbjh21*/ 451.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC 461.1Sbjh21static 471.1Sbjh21#endif 481.1Sbjh21int8 float_detect_tininess = float_tininess_after_rounding; 491.1Sbjh21 501.1Sbjh21/* 511.1Sbjh21------------------------------------------------------------------------------- 521.1Sbjh21Raises the exceptions specified by `flags'. Floating-point traps can be 531.1Sbjh21defined here if desired. It is currently not possible for such a trap to 541.1Sbjh21substitute a result value. If traps are not implemented, this routine 551.1Sbjh21should be simply `float_exception_flags |= flags;'. 561.1Sbjh21------------------------------------------------------------------------------- 571.1Sbjh21*/ 581.6Smartin#ifdef SOFTFLOAT_FOR_GCC 591.8Smatt#ifndef set_float_exception_mask 601.6Smartin#define float_exception_mask _softfloat_float_exception_mask 611.6Smartin#endif 621.8Smatt#endif 631.8Smatt#ifndef set_float_exception_mask 641.3Sbjh21fp_except float_exception_mask = 0; 651.8Smatt#endif 661.8Smattvoid 671.8Smattfloat_raise( fp_except flags ) 681.1Sbjh21{ 691.5Smartin siginfo_t info; 701.8Smatt fp_except mask = float_exception_mask; 711.1Sbjh21 721.8Smatt#ifdef set_float_exception_mask 731.8Smatt flags |= set_float_exception_flags(flags, 0); 741.8Smatt#else 751.1Sbjh21 float_exception_flags |= flags; 761.8Smatt flags = float_exception_flags; 771.8Smatt#endif 781.1Sbjh21 791.8Smatt flags &= mask; 801.8Smatt if ( flags ) { 811.5Smartin memset(&info, 0, sizeof info); 821.5Smartin info.si_signo = SIGFPE; 831.5Smartin info.si_pid = getpid(); 841.5Smartin info.si_uid = geteuid(); 851.5Smartin if (flags & float_flag_underflow) 861.5Smartin info.si_code = FPE_FLTUND; 871.5Smartin else if (flags & float_flag_overflow) 881.5Smartin info.si_code = FPE_FLTOVF; 891.5Smartin else if (flags & float_flag_divbyzero) 901.5Smartin info.si_code = FPE_FLTDIV; 911.5Smartin else if (flags & float_flag_invalid) 921.5Smartin info.si_code = FPE_FLTINV; 931.5Smartin else if (flags & float_flag_inexact) 941.5Smartin info.si_code = FPE_FLTRES; 951.5Smartin sigqueueinfo(getpid(), &info); 961.3Sbjh21 } 971.1Sbjh21} 981.6Smartin#undef float_exception_mask 991.1Sbjh21 1001.1Sbjh21/* 1011.1Sbjh21------------------------------------------------------------------------------- 1021.1Sbjh21Internal canonical NaN format. 1031.1Sbjh21------------------------------------------------------------------------------- 1041.1Sbjh21*/ 1051.1Sbjh21typedef struct { 1061.1Sbjh21 flag sign; 1071.1Sbjh21 bits64 high, low; 1081.1Sbjh21} commonNaNT; 1091.1Sbjh21 1101.1Sbjh21/* 1111.1Sbjh21------------------------------------------------------------------------------- 1121.1Sbjh21The pattern for a default generated single-precision NaN. 1131.1Sbjh21------------------------------------------------------------------------------- 1141.1Sbjh21*/ 1151.1Sbjh21#define float32_default_nan 0xFFFFFFFF 1161.1Sbjh21 1171.1Sbjh21/* 1181.1Sbjh21------------------------------------------------------------------------------- 1191.1Sbjh21Returns 1 if the single-precision floating-point value `a' is a NaN; 1201.1Sbjh21otherwise returns 0. 1211.1Sbjh21------------------------------------------------------------------------------- 1221.1Sbjh21*/ 1231.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC 1241.1Sbjh21static 1251.1Sbjh21#endif 1261.1Sbjh21flag float32_is_nan( float32 a ) 1271.1Sbjh21{ 1281.1Sbjh21 1291.7Schristos return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) ); 1301.1Sbjh21 1311.1Sbjh21} 1321.1Sbjh21 1331.1Sbjh21/* 1341.1Sbjh21------------------------------------------------------------------------------- 1351.1Sbjh21Returns 1 if the single-precision floating-point value `a' is a signaling 1361.1Sbjh21NaN; otherwise returns 0. 1371.1Sbjh21------------------------------------------------------------------------------- 1381.1Sbjh21*/ 1391.9Smatt#if defined(SOFTFLOAT_FOR_GCC) \ 1401.9Smatt && !defined(SOFTFLOATAARCH64_FOR_GCC) \ 1411.9Smatt && !defined(SOFTFLOATSPARC64_FOR_GCC) \ 1421.9Smatt && !defined(SOFTFLOATM68K_FOR_GCC) 1431.1Sbjh21static 1441.1Sbjh21#endif 1451.1Sbjh21flag float32_is_signaling_nan( float32 a ) 1461.1Sbjh21{ 1471.1Sbjh21 1481.1Sbjh21 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 1491.1Sbjh21 1501.1Sbjh21} 1511.1Sbjh21 1521.1Sbjh21/* 1531.1Sbjh21------------------------------------------------------------------------------- 1541.1Sbjh21Returns the result of converting the single-precision floating-point NaN 1551.1Sbjh21`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 1561.1Sbjh21exception is raised. 1571.1Sbjh21------------------------------------------------------------------------------- 1581.1Sbjh21*/ 1591.1Sbjh21static commonNaNT float32ToCommonNaN( float32 a ) 1601.1Sbjh21{ 1611.1Sbjh21 commonNaNT z; 1621.1Sbjh21 1631.1Sbjh21 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 1641.1Sbjh21 z.sign = a>>31; 1651.1Sbjh21 z.low = 0; 1661.1Sbjh21 z.high = ( (bits64) a )<<41; 1671.1Sbjh21 return z; 1681.1Sbjh21 1691.1Sbjh21} 1701.1Sbjh21 1711.1Sbjh21/* 1721.1Sbjh21------------------------------------------------------------------------------- 1731.1Sbjh21Returns the result of converting the canonical NaN `a' to the single- 1741.1Sbjh21precision floating-point format. 1751.1Sbjh21------------------------------------------------------------------------------- 1761.1Sbjh21*/ 1771.1Sbjh21static float32 commonNaNToFloat32( commonNaNT a ) 1781.1Sbjh21{ 1791.1Sbjh21 1801.7Schristos return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 ); 1811.1Sbjh21 1821.1Sbjh21} 1831.1Sbjh21 1841.1Sbjh21/* 1851.1Sbjh21------------------------------------------------------------------------------- 1861.1Sbjh21Takes two single-precision floating-point values `a' and `b', one of which 1871.1Sbjh21is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 1881.1Sbjh21signaling NaN, the invalid exception is raised. 1891.1Sbjh21------------------------------------------------------------------------------- 1901.1Sbjh21*/ 1911.1Sbjh21static float32 propagateFloat32NaN( float32 a, float32 b ) 1921.1Sbjh21{ 1931.1Sbjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 1941.1Sbjh21 1951.1Sbjh21 aIsNaN = float32_is_nan( a ); 1961.1Sbjh21 aIsSignalingNaN = float32_is_signaling_nan( a ); 1971.1Sbjh21 bIsNaN = float32_is_nan( b ); 1981.1Sbjh21 bIsSignalingNaN = float32_is_signaling_nan( b ); 1991.1Sbjh21 a |= 0x00400000; 2001.1Sbjh21 b |= 0x00400000; 2011.1Sbjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 2021.1Sbjh21 if ( aIsNaN ) { 2031.1Sbjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 2041.1Sbjh21 } 2051.1Sbjh21 else { 2061.1Sbjh21 return b; 2071.1Sbjh21 } 2081.1Sbjh21 2091.1Sbjh21} 2101.1Sbjh21 2111.1Sbjh21/* 2121.1Sbjh21------------------------------------------------------------------------------- 2131.1Sbjh21The pattern for a default generated double-precision NaN. 2141.1Sbjh21------------------------------------------------------------------------------- 2151.1Sbjh21*/ 2161.1Sbjh21#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 2171.1Sbjh21 2181.1Sbjh21/* 2191.1Sbjh21------------------------------------------------------------------------------- 2201.1Sbjh21Returns 1 if the double-precision floating-point value `a' is a NaN; 2211.1Sbjh21otherwise returns 0. 2221.1Sbjh21------------------------------------------------------------------------------- 2231.1Sbjh21*/ 2241.1Sbjh21#ifdef SOFTFLOAT_FOR_GCC 2251.1Sbjh21static 2261.1Sbjh21#endif 2271.1Sbjh21flag float64_is_nan( float64 a ) 2281.1Sbjh21{ 2291.1Sbjh21 2301.7Schristos return ( (bits64)LIT64( 0xFFE0000000000000 ) < 2311.1Sbjh21 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 2321.1Sbjh21 2331.1Sbjh21} 2341.1Sbjh21 2351.1Sbjh21/* 2361.1Sbjh21------------------------------------------------------------------------------- 2371.1Sbjh21Returns 1 if the double-precision floating-point value `a' is a signaling 2381.1Sbjh21NaN; otherwise returns 0. 2391.1Sbjh21------------------------------------------------------------------------------- 2401.1Sbjh21*/ 2411.9Smatt#if defined(SOFTFLOAT_FOR_GCC) \ 2421.9Smatt && !defined(SOFTFLOATAARCH64_FOR_GCC) \ 2431.9Smatt && !defined(SOFTFLOATSPARC64_FOR_GCC) \ 2441.9Smatt && !defined(SOFTFLOATM68K_FOR_GCC) 2451.1Sbjh21static 2461.1Sbjh21#endif 2471.1Sbjh21flag float64_is_signaling_nan( float64 a ) 2481.1Sbjh21{ 2491.1Sbjh21 2501.1Sbjh21 return 2511.1Sbjh21 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 2521.1Sbjh21 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 2531.1Sbjh21 2541.1Sbjh21} 2551.1Sbjh21 2561.1Sbjh21/* 2571.1Sbjh21------------------------------------------------------------------------------- 2581.1Sbjh21Returns the result of converting the double-precision floating-point NaN 2591.1Sbjh21`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 2601.1Sbjh21exception is raised. 2611.1Sbjh21------------------------------------------------------------------------------- 2621.1Sbjh21*/ 2631.1Sbjh21static commonNaNT float64ToCommonNaN( float64 a ) 2641.1Sbjh21{ 2651.1Sbjh21 commonNaNT z; 2661.1Sbjh21 2671.1Sbjh21 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 2681.7Schristos z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63); 2691.1Sbjh21 z.low = 0; 2701.1Sbjh21 z.high = FLOAT64_DEMANGLE(a)<<12; 2711.1Sbjh21 return z; 2721.1Sbjh21 2731.1Sbjh21} 2741.1Sbjh21 2751.1Sbjh21/* 2761.1Sbjh21------------------------------------------------------------------------------- 2771.1Sbjh21Returns the result of converting the canonical NaN `a' to the double- 2781.1Sbjh21precision floating-point format. 2791.1Sbjh21------------------------------------------------------------------------------- 2801.1Sbjh21*/ 2811.1Sbjh21static float64 commonNaNToFloat64( commonNaNT a ) 2821.1Sbjh21{ 2831.1Sbjh21 2841.1Sbjh21 return FLOAT64_MANGLE( 2851.1Sbjh21 ( ( (bits64) a.sign )<<63 ) 2861.1Sbjh21 | LIT64( 0x7FF8000000000000 ) 2871.1Sbjh21 | ( a.high>>12 ) ); 2881.1Sbjh21 2891.1Sbjh21} 2901.1Sbjh21 2911.1Sbjh21/* 2921.1Sbjh21------------------------------------------------------------------------------- 2931.1Sbjh21Takes two double-precision floating-point values `a' and `b', one of which 2941.1Sbjh21is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 2951.1Sbjh21signaling NaN, the invalid exception is raised. 2961.1Sbjh21------------------------------------------------------------------------------- 2971.1Sbjh21*/ 2981.1Sbjh21static float64 propagateFloat64NaN( float64 a, float64 b ) 2991.1Sbjh21{ 3001.1Sbjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 3011.1Sbjh21 3021.1Sbjh21 aIsNaN = float64_is_nan( a ); 3031.1Sbjh21 aIsSignalingNaN = float64_is_signaling_nan( a ); 3041.1Sbjh21 bIsNaN = float64_is_nan( b ); 3051.1Sbjh21 bIsSignalingNaN = float64_is_signaling_nan( b ); 3061.1Sbjh21 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 3071.1Sbjh21 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 3081.1Sbjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 3091.1Sbjh21 if ( aIsNaN ) { 3101.1Sbjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 3111.1Sbjh21 } 3121.1Sbjh21 else { 3131.1Sbjh21 return b; 3141.1Sbjh21 } 3151.1Sbjh21 3161.1Sbjh21} 3171.1Sbjh21 3181.1Sbjh21#ifdef FLOATX80 3191.1Sbjh21 3201.1Sbjh21/* 3211.1Sbjh21------------------------------------------------------------------------------- 3221.1Sbjh21The pattern for a default generated extended double-precision NaN. The 3231.1Sbjh21`high' and `low' values hold the most- and least-significant bits, 3241.1Sbjh21respectively. 3251.1Sbjh21------------------------------------------------------------------------------- 3261.1Sbjh21*/ 3271.1Sbjh21#define floatx80_default_nan_high 0xFFFF 3281.1Sbjh21#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 3291.1Sbjh21 3301.1Sbjh21/* 3311.1Sbjh21------------------------------------------------------------------------------- 3321.1Sbjh21Returns 1 if the extended double-precision floating-point value `a' is a 3331.1Sbjh21NaN; otherwise returns 0. 3341.1Sbjh21------------------------------------------------------------------------------- 3351.1Sbjh21*/ 3361.1Sbjh21flag floatx80_is_nan( floatx80 a ) 3371.1Sbjh21{ 3381.1Sbjh21 3391.1Sbjh21 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 3401.1Sbjh21 3411.1Sbjh21} 3421.1Sbjh21 3431.1Sbjh21/* 3441.1Sbjh21------------------------------------------------------------------------------- 3451.1Sbjh21Returns 1 if the extended double-precision floating-point value `a' is a 3461.1Sbjh21signaling NaN; otherwise returns 0. 3471.1Sbjh21------------------------------------------------------------------------------- 3481.1Sbjh21*/ 3491.1Sbjh21flag floatx80_is_signaling_nan( floatx80 a ) 3501.1Sbjh21{ 3511.1Sbjh21 bits64 aLow; 3521.1Sbjh21 3531.1Sbjh21 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 3541.1Sbjh21 return 3551.1Sbjh21 ( ( a.high & 0x7FFF ) == 0x7FFF ) 3561.1Sbjh21 && (bits64) ( aLow<<1 ) 3571.1Sbjh21 && ( a.low == aLow ); 3581.1Sbjh21 3591.1Sbjh21} 3601.1Sbjh21 3611.1Sbjh21/* 3621.1Sbjh21------------------------------------------------------------------------------- 3631.1Sbjh21Returns the result of converting the extended double-precision floating- 3641.1Sbjh21point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 3651.1Sbjh21invalid exception is raised. 3661.1Sbjh21------------------------------------------------------------------------------- 3671.1Sbjh21*/ 3681.1Sbjh21static commonNaNT floatx80ToCommonNaN( floatx80 a ) 3691.1Sbjh21{ 3701.1Sbjh21 commonNaNT z; 3711.1Sbjh21 3721.1Sbjh21 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 3731.1Sbjh21 z.sign = a.high>>15; 3741.1Sbjh21 z.low = 0; 3751.1Sbjh21 z.high = a.low<<1; 3761.1Sbjh21 return z; 3771.1Sbjh21 3781.1Sbjh21} 3791.1Sbjh21 3801.1Sbjh21/* 3811.1Sbjh21------------------------------------------------------------------------------- 3821.1Sbjh21Returns the result of converting the canonical NaN `a' to the extended 3831.1Sbjh21double-precision floating-point format. 3841.1Sbjh21------------------------------------------------------------------------------- 3851.1Sbjh21*/ 3861.1Sbjh21static floatx80 commonNaNToFloatx80( commonNaNT a ) 3871.1Sbjh21{ 3881.1Sbjh21 floatx80 z; 3891.1Sbjh21 3901.1Sbjh21 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 3911.1Sbjh21 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 3921.1Sbjh21 return z; 3931.1Sbjh21 3941.1Sbjh21} 3951.1Sbjh21 3961.1Sbjh21/* 3971.1Sbjh21------------------------------------------------------------------------------- 3981.1Sbjh21Takes two extended double-precision floating-point values `a' and `b', one 3991.1Sbjh21of which is a NaN, and returns the appropriate NaN result. If either `a' or 4001.1Sbjh21`b' is a signaling NaN, the invalid exception is raised. 4011.1Sbjh21------------------------------------------------------------------------------- 4021.1Sbjh21*/ 4031.1Sbjh21static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 4041.1Sbjh21{ 4051.1Sbjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 4061.1Sbjh21 4071.1Sbjh21 aIsNaN = floatx80_is_nan( a ); 4081.1Sbjh21 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 4091.1Sbjh21 bIsNaN = floatx80_is_nan( b ); 4101.1Sbjh21 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 4111.1Sbjh21 a.low |= LIT64( 0xC000000000000000 ); 4121.1Sbjh21 b.low |= LIT64( 0xC000000000000000 ); 4131.1Sbjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 4141.1Sbjh21 if ( aIsNaN ) { 4151.1Sbjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 4161.1Sbjh21 } 4171.1Sbjh21 else { 4181.1Sbjh21 return b; 4191.1Sbjh21 } 4201.1Sbjh21 4211.1Sbjh21} 4221.1Sbjh21 4231.1Sbjh21#endif 4241.1Sbjh21 4251.1Sbjh21#ifdef FLOAT128 4261.1Sbjh21 4271.1Sbjh21/* 4281.1Sbjh21------------------------------------------------------------------------------- 4291.1Sbjh21The pattern for a default generated quadruple-precision NaN. The `high' and 4301.1Sbjh21`low' values hold the most- and least-significant bits, respectively. 4311.1Sbjh21------------------------------------------------------------------------------- 4321.1Sbjh21*/ 4331.1Sbjh21#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 4341.1Sbjh21#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 4351.1Sbjh21 4361.1Sbjh21/* 4371.1Sbjh21------------------------------------------------------------------------------- 4381.1Sbjh21Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 4391.1Sbjh21otherwise returns 0. 4401.1Sbjh21------------------------------------------------------------------------------- 4411.1Sbjh21*/ 4421.1Sbjh21flag float128_is_nan( float128 a ) 4431.1Sbjh21{ 4441.1Sbjh21 4451.1Sbjh21 return 4461.7Schristos ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 4471.1Sbjh21 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 4481.1Sbjh21 4491.1Sbjh21} 4501.1Sbjh21 4511.1Sbjh21/* 4521.1Sbjh21------------------------------------------------------------------------------- 4531.1Sbjh21Returns 1 if the quadruple-precision floating-point value `a' is a 4541.1Sbjh21signaling NaN; otherwise returns 0. 4551.1Sbjh21------------------------------------------------------------------------------- 4561.1Sbjh21*/ 4571.1Sbjh21flag float128_is_signaling_nan( float128 a ) 4581.1Sbjh21{ 4591.1Sbjh21 4601.1Sbjh21 return 4611.1Sbjh21 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 4621.1Sbjh21 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 4631.1Sbjh21 4641.1Sbjh21} 4651.1Sbjh21 4661.1Sbjh21/* 4671.1Sbjh21------------------------------------------------------------------------------- 4681.1Sbjh21Returns the result of converting the quadruple-precision floating-point NaN 4691.1Sbjh21`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 4701.1Sbjh21exception is raised. 4711.1Sbjh21------------------------------------------------------------------------------- 4721.1Sbjh21*/ 4731.1Sbjh21static commonNaNT float128ToCommonNaN( float128 a ) 4741.1Sbjh21{ 4751.1Sbjh21 commonNaNT z; 4761.1Sbjh21 4771.1Sbjh21 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 4781.7Schristos z.sign = (flag)(a.high>>63); 4791.1Sbjh21 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 4801.1Sbjh21 return z; 4811.1Sbjh21 4821.1Sbjh21} 4831.1Sbjh21 4841.1Sbjh21/* 4851.1Sbjh21------------------------------------------------------------------------------- 4861.1Sbjh21Returns the result of converting the canonical NaN `a' to the quadruple- 4871.1Sbjh21precision floating-point format. 4881.1Sbjh21------------------------------------------------------------------------------- 4891.1Sbjh21*/ 4901.1Sbjh21static float128 commonNaNToFloat128( commonNaNT a ) 4911.1Sbjh21{ 4921.1Sbjh21 float128 z; 4931.1Sbjh21 4941.1Sbjh21 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 4951.1Sbjh21 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 4961.1Sbjh21 return z; 4971.1Sbjh21 4981.1Sbjh21} 4991.1Sbjh21 5001.1Sbjh21/* 5011.1Sbjh21------------------------------------------------------------------------------- 5021.1Sbjh21Takes two quadruple-precision floating-point values `a' and `b', one of 5031.1Sbjh21which is a NaN, and returns the appropriate NaN result. If either `a' or 5041.1Sbjh21`b' is a signaling NaN, the invalid exception is raised. 5051.1Sbjh21------------------------------------------------------------------------------- 5061.1Sbjh21*/ 5071.1Sbjh21static float128 propagateFloat128NaN( float128 a, float128 b ) 5081.1Sbjh21{ 5091.1Sbjh21 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 5101.1Sbjh21 5111.1Sbjh21 aIsNaN = float128_is_nan( a ); 5121.1Sbjh21 aIsSignalingNaN = float128_is_signaling_nan( a ); 5131.1Sbjh21 bIsNaN = float128_is_nan( b ); 5141.1Sbjh21 bIsSignalingNaN = float128_is_signaling_nan( b ); 5151.1Sbjh21 a.high |= LIT64( 0x0000800000000000 ); 5161.1Sbjh21 b.high |= LIT64( 0x0000800000000000 ); 5171.1Sbjh21 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 5181.1Sbjh21 if ( aIsNaN ) { 5191.1Sbjh21 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 5201.1Sbjh21 } 5211.1Sbjh21 else { 5221.1Sbjh21 return b; 5231.1Sbjh21 } 5241.1Sbjh21 5251.1Sbjh21} 5261.1Sbjh21 5271.1Sbjh21#endif 5281.1Sbjh21 529