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