1230363Sdas/* $NetBSD: softfloat-specialize,v 1.6 2011/03/06 10:27:37 martin Exp $ */ 2129203Scognet/* $FreeBSD$ */ 3129203Scognet 4129203Scognet/* This is a derivative work. */ 5129203Scognet 6129203Scognet/* 7129203Scognet=============================================================================== 8129203Scognet 9129203ScognetThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 10129203ScognetArithmetic Package, Release 2a. 11129203Scognet 12129203ScognetWritten by John R. Hauser. This work was made possible in part by the 13129203ScognetInternational Computer Science Institute, located at Suite 600, 1947 Center 14129203ScognetStreet, Berkeley, California 94704. Funding was partially provided by the 15129203ScognetNational Science Foundation under grant MIP-9311980. The original version 16129203Scognetof this code was written as part of a project to build a fixed-point vector 17129203Scognetprocessor in collaboration with the University of California at Berkeley, 18129203Scognetoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 19129203Scognetis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 20129203Scognetarithmetic/SoftFloat.html'. 21129203Scognet 22129203ScognetTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 23129203Scognethas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 24129203ScognetTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 25129203ScognetPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 26129203ScognetAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 27129203Scognet 28129203ScognetDerivative works are acceptable, even for commercial purposes, so long as 29129203Scognet(1) they include prominent notice that the work is derivative, and (2) they 30129203Scognetinclude prominent notice akin to these four paragraphs for those parts of 31129203Scognetthis code that are retained. 32129203Scognet 33129203Scognet=============================================================================== 34129203Scognet*/ 35129203Scognet 36129203Scognet#include <signal.h> 37230363Sdas#include <string.h> 38230363Sdas#include <unistd.h> 39129203Scognet 40129203Scognet/* 41129203Scognet------------------------------------------------------------------------------- 42129203ScognetUnderflow tininess-detection mode, statically initialized to default value. 43129203Scognet(The declaration in `softfloat.h' must match the `int8' type here.) 44129203Scognet------------------------------------------------------------------------------- 45129203Scognet*/ 46129203Scognet#ifdef SOFTFLOAT_FOR_GCC 47129203Scognetstatic 48129203Scognet#endif 49206490Smarius#ifdef __sparc64__ 50206490Smariusint8 float_detect_tininess = float_tininess_before_rounding; 51206490Smarius#else 52129203Scognetint8 float_detect_tininess = float_tininess_after_rounding; 53206492Smarius#endif 54129203Scognet 55129203Scognet/* 56129203Scognet------------------------------------------------------------------------------- 57129203ScognetRaises the exceptions specified by `flags'. Floating-point traps can be 58129203Scognetdefined here if desired. It is currently not possible for such a trap to 59129203Scognetsubstitute a result value. If traps are not implemented, this routine 60129203Scognetshould be simply `float_exception_flags |= flags;'. 61129203Scognet------------------------------------------------------------------------------- 62129203Scognet*/ 63230363Sdas#ifdef SOFTFLOAT_FOR_GCC 64230363Sdas#define float_exception_mask __softfloat_float_exception_mask 65230363Sdas#endif 66230189Sdasint float_exception_mask = 0; 67230189Sdasvoid float_raise( int flags ) 68129203Scognet{ 69129203Scognet 70129203Scognet float_exception_flags |= flags; 71129203Scognet 72129203Scognet if ( flags & float_exception_mask ) { 73230363Sdas#if 0 74230363Sdas siginfo_t info; 75230363Sdas memset(&info, 0, sizeof info); 76230363Sdas info.si_signo = SIGFPE; 77230363Sdas info.si_pid = getpid(); 78230363Sdas info.si_uid = geteuid(); 79230363Sdas if (flags & float_flag_underflow) 80230363Sdas info.si_code = FPE_FLTUND; 81230363Sdas else if (flags & float_flag_overflow) 82230363Sdas info.si_code = FPE_FLTOVF; 83230363Sdas else if (flags & float_flag_divbyzero) 84230363Sdas info.si_code = FPE_FLTDIV; 85230363Sdas else if (flags & float_flag_invalid) 86230363Sdas info.si_code = FPE_FLTINV; 87230363Sdas else if (flags & float_flag_inexact) 88230363Sdas info.si_code = FPE_FLTRES; 89230363Sdas sigqueueinfo(getpid(), &info); 90230363Sdas#else 91129203Scognet raise( SIGFPE ); 92230363Sdas#endif 93129203Scognet } 94129203Scognet} 95230363Sdas#undef float_exception_mask 96129203Scognet 97129203Scognet/* 98129203Scognet------------------------------------------------------------------------------- 99129203ScognetInternal canonical NaN format. 100129203Scognet------------------------------------------------------------------------------- 101129203Scognet*/ 102129203Scognettypedef struct { 103129203Scognet flag sign; 104129203Scognet bits64 high, low; 105129203Scognet} commonNaNT; 106129203Scognet 107129203Scognet/* 108129203Scognet------------------------------------------------------------------------------- 109129203ScognetThe pattern for a default generated single-precision NaN. 110129203Scognet------------------------------------------------------------------------------- 111129203Scognet*/ 112129203Scognet#define float32_default_nan 0xFFFFFFFF 113129203Scognet 114129203Scognet/* 115129203Scognet------------------------------------------------------------------------------- 116129203ScognetReturns 1 if the single-precision floating-point value `a' is a NaN; 117129203Scognetotherwise returns 0. 118129203Scognet------------------------------------------------------------------------------- 119129203Scognet*/ 120129203Scognet#ifdef SOFTFLOAT_FOR_GCC 121129203Scognetstatic 122129203Scognet#endif 123129203Scognetflag float32_is_nan( float32 a ) 124129203Scognet{ 125129203Scognet 126129203Scognet return ( 0xFF000000 < (bits32) ( a<<1 ) ); 127129203Scognet 128129203Scognet} 129129203Scognet 130129203Scognet/* 131129203Scognet------------------------------------------------------------------------------- 132129203ScognetReturns 1 if the single-precision floating-point value `a' is a signaling 133129203ScognetNaN; otherwise returns 0. 134129203Scognet------------------------------------------------------------------------------- 135129203Scognet*/ 136230363Sdas#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 137230363Sdas !defined(SOFTFLOAT_M68K_FOR_GCC) 138129203Scognetstatic 139129203Scognet#endif 140129203Scognetflag float32_is_signaling_nan( float32 a ) 141129203Scognet{ 142129203Scognet 143129203Scognet return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 144129203Scognet 145129203Scognet} 146129203Scognet 147129203Scognet/* 148129203Scognet------------------------------------------------------------------------------- 149129203ScognetReturns the result of converting the single-precision floating-point NaN 150129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 151129203Scognetexception is raised. 152129203Scognet------------------------------------------------------------------------------- 153129203Scognet*/ 154129203Scognetstatic commonNaNT float32ToCommonNaN( float32 a ) 155129203Scognet{ 156129203Scognet commonNaNT z; 157129203Scognet 158129203Scognet if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 159129203Scognet z.sign = a>>31; 160129203Scognet z.low = 0; 161129203Scognet z.high = ( (bits64) a )<<41; 162129203Scognet return z; 163129203Scognet 164129203Scognet} 165129203Scognet 166129203Scognet/* 167129203Scognet------------------------------------------------------------------------------- 168129203ScognetReturns the result of converting the canonical NaN `a' to the single- 169129203Scognetprecision floating-point format. 170129203Scognet------------------------------------------------------------------------------- 171129203Scognet*/ 172129203Scognetstatic float32 commonNaNToFloat32( commonNaNT a ) 173129203Scognet{ 174129203Scognet 175129203Scognet return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 176129203Scognet 177129203Scognet} 178129203Scognet 179129203Scognet/* 180129203Scognet------------------------------------------------------------------------------- 181129203ScognetTakes two single-precision floating-point values `a' and `b', one of which 182129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 183129203Scognetsignaling NaN, the invalid exception is raised. 184129203Scognet------------------------------------------------------------------------------- 185129203Scognet*/ 186129203Scognetstatic float32 propagateFloat32NaN( float32 a, float32 b ) 187129203Scognet{ 188129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 189129203Scognet 190129203Scognet aIsNaN = float32_is_nan( a ); 191129203Scognet aIsSignalingNaN = float32_is_signaling_nan( a ); 192129203Scognet bIsNaN = float32_is_nan( b ); 193129203Scognet bIsSignalingNaN = float32_is_signaling_nan( b ); 194129203Scognet a |= 0x00400000; 195129203Scognet b |= 0x00400000; 196129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 197129203Scognet if ( aIsNaN ) { 198129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 199129203Scognet } 200129203Scognet else { 201129203Scognet return b; 202129203Scognet } 203129203Scognet 204129203Scognet} 205129203Scognet 206129203Scognet/* 207129203Scognet------------------------------------------------------------------------------- 208129203ScognetThe pattern for a default generated double-precision NaN. 209129203Scognet------------------------------------------------------------------------------- 210129203Scognet*/ 211129203Scognet#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 212129203Scognet 213129203Scognet/* 214129203Scognet------------------------------------------------------------------------------- 215129203ScognetReturns 1 if the double-precision floating-point value `a' is a NaN; 216129203Scognetotherwise returns 0. 217129203Scognet------------------------------------------------------------------------------- 218129203Scognet*/ 219129203Scognet#ifdef SOFTFLOAT_FOR_GCC 220129203Scognetstatic 221129203Scognet#endif 222129203Scognetflag float64_is_nan( float64 a ) 223129203Scognet{ 224129203Scognet 225129203Scognet return ( LIT64( 0xFFE0000000000000 ) < 226129203Scognet (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 227129203Scognet 228129203Scognet} 229129203Scognet 230129203Scognet/* 231129203Scognet------------------------------------------------------------------------------- 232129203ScognetReturns 1 if the double-precision floating-point value `a' is a signaling 233129203ScognetNaN; otherwise returns 0. 234129203Scognet------------------------------------------------------------------------------- 235129203Scognet*/ 236230363Sdas#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 237230363Sdas !defined(SOFTFLOATM68K_FOR_GCC) 238129203Scognetstatic 239129203Scognet#endif 240129203Scognetflag float64_is_signaling_nan( float64 a ) 241129203Scognet{ 242129203Scognet 243129203Scognet return 244129203Scognet ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 245129203Scognet && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 246129203Scognet 247129203Scognet} 248129203Scognet 249129203Scognet/* 250129203Scognet------------------------------------------------------------------------------- 251129203ScognetReturns the result of converting the double-precision floating-point NaN 252129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 253129203Scognetexception is raised. 254129203Scognet------------------------------------------------------------------------------- 255129203Scognet*/ 256129203Scognetstatic commonNaNT float64ToCommonNaN( float64 a ) 257129203Scognet{ 258129203Scognet commonNaNT z; 259129203Scognet 260129203Scognet if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 261129203Scognet z.sign = FLOAT64_DEMANGLE(a)>>63; 262129203Scognet z.low = 0; 263129203Scognet z.high = FLOAT64_DEMANGLE(a)<<12; 264129203Scognet return z; 265129203Scognet 266129203Scognet} 267129203Scognet 268129203Scognet/* 269129203Scognet------------------------------------------------------------------------------- 270129203ScognetReturns the result of converting the canonical NaN `a' to the double- 271129203Scognetprecision floating-point format. 272129203Scognet------------------------------------------------------------------------------- 273129203Scognet*/ 274129203Scognetstatic float64 commonNaNToFloat64( commonNaNT a ) 275129203Scognet{ 276129203Scognet 277129203Scognet return FLOAT64_MANGLE( 278129203Scognet ( ( (bits64) a.sign )<<63 ) 279129203Scognet | LIT64( 0x7FF8000000000000 ) 280129203Scognet | ( a.high>>12 ) ); 281129203Scognet 282129203Scognet} 283129203Scognet 284129203Scognet/* 285129203Scognet------------------------------------------------------------------------------- 286129203ScognetTakes two double-precision floating-point values `a' and `b', one of which 287129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 288129203Scognetsignaling NaN, the invalid exception is raised. 289129203Scognet------------------------------------------------------------------------------- 290129203Scognet*/ 291129203Scognetstatic float64 propagateFloat64NaN( float64 a, float64 b ) 292129203Scognet{ 293129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 294129203Scognet 295129203Scognet aIsNaN = float64_is_nan( a ); 296129203Scognet aIsSignalingNaN = float64_is_signaling_nan( a ); 297129203Scognet bIsNaN = float64_is_nan( b ); 298129203Scognet bIsSignalingNaN = float64_is_signaling_nan( b ); 299129203Scognet a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 300129203Scognet b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 301129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 302129203Scognet if ( aIsNaN ) { 303129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 304129203Scognet } 305129203Scognet else { 306129203Scognet return b; 307129203Scognet } 308129203Scognet 309129203Scognet} 310129203Scognet 311129203Scognet#ifdef FLOATX80 312129203Scognet 313129203Scognet/* 314129203Scognet------------------------------------------------------------------------------- 315129203ScognetThe pattern for a default generated extended double-precision NaN. The 316129203Scognet`high' and `low' values hold the most- and least-significant bits, 317129203Scognetrespectively. 318129203Scognet------------------------------------------------------------------------------- 319129203Scognet*/ 320129203Scognet#define floatx80_default_nan_high 0xFFFF 321129203Scognet#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 322129203Scognet 323129203Scognet/* 324129203Scognet------------------------------------------------------------------------------- 325129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 326129203ScognetNaN; otherwise returns 0. 327129203Scognet------------------------------------------------------------------------------- 328129203Scognet*/ 329129203Scognetflag floatx80_is_nan( floatx80 a ) 330129203Scognet{ 331129203Scognet 332129203Scognet return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 333129203Scognet 334129203Scognet} 335129203Scognet 336129203Scognet/* 337129203Scognet------------------------------------------------------------------------------- 338129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 339129203Scognetsignaling NaN; otherwise returns 0. 340129203Scognet------------------------------------------------------------------------------- 341129203Scognet*/ 342129203Scognetflag floatx80_is_signaling_nan( floatx80 a ) 343129203Scognet{ 344129203Scognet bits64 aLow; 345129203Scognet 346129203Scognet aLow = a.low & ~ LIT64( 0x4000000000000000 ); 347129203Scognet return 348129203Scognet ( ( a.high & 0x7FFF ) == 0x7FFF ) 349129203Scognet && (bits64) ( aLow<<1 ) 350129203Scognet && ( a.low == aLow ); 351129203Scognet 352129203Scognet} 353129203Scognet 354129203Scognet/* 355129203Scognet------------------------------------------------------------------------------- 356129203ScognetReturns the result of converting the extended double-precision floating- 357129203Scognetpoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 358129203Scognetinvalid exception is raised. 359129203Scognet------------------------------------------------------------------------------- 360129203Scognet*/ 361129203Scognetstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 362129203Scognet{ 363129203Scognet commonNaNT z; 364129203Scognet 365129203Scognet if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 366129203Scognet z.sign = a.high>>15; 367129203Scognet z.low = 0; 368129203Scognet z.high = a.low<<1; 369129203Scognet return z; 370129203Scognet 371129203Scognet} 372129203Scognet 373129203Scognet/* 374129203Scognet------------------------------------------------------------------------------- 375129203ScognetReturns the result of converting the canonical NaN `a' to the extended 376129203Scognetdouble-precision floating-point format. 377129203Scognet------------------------------------------------------------------------------- 378129203Scognet*/ 379129203Scognetstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 380129203Scognet{ 381129203Scognet floatx80 z; 382129203Scognet 383129203Scognet z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 384129203Scognet z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 385129203Scognet return z; 386129203Scognet 387129203Scognet} 388129203Scognet 389129203Scognet/* 390129203Scognet------------------------------------------------------------------------------- 391129203ScognetTakes two extended double-precision floating-point values `a' and `b', one 392129203Scognetof which is a NaN, and returns the appropriate NaN result. If either `a' or 393129203Scognet`b' is a signaling NaN, the invalid exception is raised. 394129203Scognet------------------------------------------------------------------------------- 395129203Scognet*/ 396129203Scognetstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 397129203Scognet{ 398129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 399129203Scognet 400129203Scognet aIsNaN = floatx80_is_nan( a ); 401129203Scognet aIsSignalingNaN = floatx80_is_signaling_nan( a ); 402129203Scognet bIsNaN = floatx80_is_nan( b ); 403129203Scognet bIsSignalingNaN = floatx80_is_signaling_nan( b ); 404129203Scognet a.low |= LIT64( 0xC000000000000000 ); 405129203Scognet b.low |= LIT64( 0xC000000000000000 ); 406129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 407129203Scognet if ( aIsNaN ) { 408129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 409129203Scognet } 410129203Scognet else { 411129203Scognet return b; 412129203Scognet } 413129203Scognet 414129203Scognet} 415129203Scognet 416129203Scognet#endif 417129203Scognet 418129203Scognet#ifdef FLOAT128 419129203Scognet 420129203Scognet/* 421129203Scognet------------------------------------------------------------------------------- 422129203ScognetThe pattern for a default generated quadruple-precision NaN. The `high' and 423129203Scognet`low' values hold the most- and least-significant bits, respectively. 424129203Scognet------------------------------------------------------------------------------- 425129203Scognet*/ 426129203Scognet#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 427129203Scognet#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 428129203Scognet 429129203Scognet/* 430129203Scognet------------------------------------------------------------------------------- 431129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 432129203Scognetotherwise returns 0. 433129203Scognet------------------------------------------------------------------------------- 434129203Scognet*/ 435129203Scognetflag float128_is_nan( float128 a ) 436129203Scognet{ 437129203Scognet 438129203Scognet return 439129203Scognet ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 440129203Scognet && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 441129203Scognet 442129203Scognet} 443129203Scognet 444129203Scognet/* 445129203Scognet------------------------------------------------------------------------------- 446129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a 447129203Scognetsignaling NaN; otherwise returns 0. 448129203Scognet------------------------------------------------------------------------------- 449129203Scognet*/ 450129203Scognetflag float128_is_signaling_nan( float128 a ) 451129203Scognet{ 452129203Scognet 453129203Scognet return 454129203Scognet ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 455129203Scognet && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 456129203Scognet 457129203Scognet} 458129203Scognet 459129203Scognet/* 460129203Scognet------------------------------------------------------------------------------- 461129203ScognetReturns the result of converting the quadruple-precision floating-point NaN 462129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 463129203Scognetexception is raised. 464129203Scognet------------------------------------------------------------------------------- 465129203Scognet*/ 466129203Scognetstatic commonNaNT float128ToCommonNaN( float128 a ) 467129203Scognet{ 468129203Scognet commonNaNT z; 469129203Scognet 470129203Scognet if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 471129203Scognet z.sign = a.high>>63; 472129203Scognet shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 473129203Scognet return z; 474129203Scognet 475129203Scognet} 476129203Scognet 477129203Scognet/* 478129203Scognet------------------------------------------------------------------------------- 479129203ScognetReturns the result of converting the canonical NaN `a' to the quadruple- 480129203Scognetprecision floating-point format. 481129203Scognet------------------------------------------------------------------------------- 482129203Scognet*/ 483129203Scognetstatic float128 commonNaNToFloat128( commonNaNT a ) 484129203Scognet{ 485129203Scognet float128 z; 486129203Scognet 487129203Scognet shift128Right( a.high, a.low, 16, &z.high, &z.low ); 488129203Scognet z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 489129203Scognet return z; 490129203Scognet 491129203Scognet} 492129203Scognet 493129203Scognet/* 494129203Scognet------------------------------------------------------------------------------- 495129203ScognetTakes two quadruple-precision floating-point values `a' and `b', one of 496129203Scognetwhich is a NaN, and returns the appropriate NaN result. If either `a' or 497129203Scognet`b' is a signaling NaN, the invalid exception is raised. 498129203Scognet------------------------------------------------------------------------------- 499129203Scognet*/ 500129203Scognetstatic float128 propagateFloat128NaN( float128 a, float128 b ) 501129203Scognet{ 502129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 503129203Scognet 504129203Scognet aIsNaN = float128_is_nan( a ); 505129203Scognet aIsSignalingNaN = float128_is_signaling_nan( a ); 506129203Scognet bIsNaN = float128_is_nan( b ); 507129203Scognet bIsSignalingNaN = float128_is_signaling_nan( b ); 508129203Scognet a.high |= LIT64( 0x0000800000000000 ); 509129203Scognet b.high |= LIT64( 0x0000800000000000 ); 510129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 511129203Scognet if ( aIsNaN ) { 512129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 513129203Scognet } 514129203Scognet else { 515129203Scognet return b; 516129203Scognet } 517129203Scognet 518129203Scognet} 519129203Scognet 520129203Scognet#endif 521129203Scognet 522