1*1da177e4SLinus Torvalds 2*1da177e4SLinus Torvalds/* 3*1da177e4SLinus Torvalds=============================================================================== 4*1da177e4SLinus Torvalds 5*1da177e4SLinus TorvaldsThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 6*1da177e4SLinus TorvaldsArithmetic Package, Release 2. 7*1da177e4SLinus Torvalds 8*1da177e4SLinus TorvaldsWritten by John R. Hauser. This work was made possible in part by the 9*1da177e4SLinus TorvaldsInternational Computer Science Institute, located at Suite 600, 1947 Center 10*1da177e4SLinus TorvaldsStreet, Berkeley, California 94704. Funding was partially provided by the 11*1da177e4SLinus TorvaldsNational Science Foundation under grant MIP-9311980. The original version 12*1da177e4SLinus Torvaldsof this code was written as part of a project to build a fixed-point vector 13*1da177e4SLinus Torvaldsprocessor in collaboration with the University of California at Berkeley, 14*1da177e4SLinus Torvaldsoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 15*1da177e4SLinus Torvaldsis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 16*1da177e4SLinus Torvaldsarithmetic/softfloat.html'. 17*1da177e4SLinus Torvalds 18*1da177e4SLinus TorvaldsTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 19*1da177e4SLinus Torvaldshas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 20*1da177e4SLinus TorvaldsTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 21*1da177e4SLinus TorvaldsPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 22*1da177e4SLinus TorvaldsAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 23*1da177e4SLinus Torvalds 24*1da177e4SLinus TorvaldsDerivative works are acceptable, even for commercial purposes, so long as 25*1da177e4SLinus Torvalds(1) they include prominent notice that the work is derivative, and (2) they 26*1da177e4SLinus Torvaldsinclude prominent notice akin to these three paragraphs for those parts of 27*1da177e4SLinus Torvaldsthis code that are retained. 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds=============================================================================== 30*1da177e4SLinus Torvalds*/ 31*1da177e4SLinus Torvalds 32*1da177e4SLinus Torvalds/* 33*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 34*1da177e4SLinus TorvaldsUnderflow tininess-detection mode, statically initialized to default value. 35*1da177e4SLinus Torvalds(The declaration in `softfloat.h' must match the `int8' type here.) 36*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 37*1da177e4SLinus Torvalds*/ 38*1da177e4SLinus Torvaldsint8 float_detect_tininess = float_tininess_after_rounding; 39*1da177e4SLinus Torvalds 40*1da177e4SLinus Torvalds/* 41*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 42*1da177e4SLinus TorvaldsRaises the exceptions specified by `flags'. Floating-point traps can be 43*1da177e4SLinus Torvaldsdefined here if desired. It is currently not possible for such a trap to 44*1da177e4SLinus Torvaldssubstitute a result value. If traps are not implemented, this routine 45*1da177e4SLinus Torvaldsshould be simply `float_exception_flags |= flags;'. 46*1da177e4SLinus Torvalds 47*1da177e4SLinus TorvaldsScottB: November 4, 1998 48*1da177e4SLinus TorvaldsMoved this function out of softfloat-specialize into fpmodule.c. 49*1da177e4SLinus TorvaldsThis effectively isolates all the changes required for integrating with the 50*1da177e4SLinus TorvaldsLinux kernel into fpmodule.c. Porting to NetBSD should only require modifying 51*1da177e4SLinus Torvaldsfpmodule.c to integrate with the NetBSD kernel (I hope!). 52*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 53*1da177e4SLinus Torvaldsvoid float_raise( int8 flags ) 54*1da177e4SLinus Torvalds{ 55*1da177e4SLinus Torvalds float_exception_flags |= flags; 56*1da177e4SLinus Torvalds} 57*1da177e4SLinus Torvalds*/ 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds/* 60*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 61*1da177e4SLinus TorvaldsInternal canonical NaN format. 62*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 63*1da177e4SLinus Torvalds*/ 64*1da177e4SLinus Torvaldstypedef struct { 65*1da177e4SLinus Torvalds flag sign; 66*1da177e4SLinus Torvalds bits64 high, low; 67*1da177e4SLinus Torvalds} commonNaNT; 68*1da177e4SLinus Torvalds 69*1da177e4SLinus Torvalds/* 70*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 71*1da177e4SLinus TorvaldsThe pattern for a default generated single-precision NaN. 72*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 73*1da177e4SLinus Torvalds*/ 74*1da177e4SLinus Torvalds#define float32_default_nan 0xFFFFFFFF 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds/* 77*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 78*1da177e4SLinus TorvaldsReturns 1 if the single-precision floating-point value `a' is a NaN; 79*1da177e4SLinus Torvaldsotherwise returns 0. 80*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 81*1da177e4SLinus Torvalds*/ 82*1da177e4SLinus Torvaldsflag float32_is_nan( float32 a ) 83*1da177e4SLinus Torvalds{ 84*1da177e4SLinus Torvalds 85*1da177e4SLinus Torvalds return ( 0xFF000000 < (bits32) ( a<<1 ) ); 86*1da177e4SLinus Torvalds 87*1da177e4SLinus Torvalds} 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds/* 90*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 91*1da177e4SLinus TorvaldsReturns 1 if the single-precision floating-point value `a' is a signaling 92*1da177e4SLinus TorvaldsNaN; otherwise returns 0. 93*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 94*1da177e4SLinus Torvalds*/ 95*1da177e4SLinus Torvaldsflag float32_is_signaling_nan( float32 a ) 96*1da177e4SLinus Torvalds{ 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds} 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds/* 103*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 104*1da177e4SLinus TorvaldsReturns the result of converting the single-precision floating-point NaN 105*1da177e4SLinus Torvalds`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 106*1da177e4SLinus Torvaldsexception is raised. 107*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 108*1da177e4SLinus Torvalds*/ 109*1da177e4SLinus Torvaldsstatic commonNaNT float32ToCommonNaN( float32 a ) 110*1da177e4SLinus Torvalds{ 111*1da177e4SLinus Torvalds commonNaNT z; 112*1da177e4SLinus Torvalds 113*1da177e4SLinus Torvalds if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 114*1da177e4SLinus Torvalds z.sign = a>>31; 115*1da177e4SLinus Torvalds z.low = 0; 116*1da177e4SLinus Torvalds z.high = ( (bits64) a )<<41; 117*1da177e4SLinus Torvalds return z; 118*1da177e4SLinus Torvalds 119*1da177e4SLinus Torvalds} 120*1da177e4SLinus Torvalds 121*1da177e4SLinus Torvalds/* 122*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 123*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the single- 124*1da177e4SLinus Torvaldsprecision floating-point format. 125*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 126*1da177e4SLinus Torvalds*/ 127*1da177e4SLinus Torvaldsstatic float32 commonNaNToFloat32( commonNaNT a ) 128*1da177e4SLinus Torvalds{ 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 131*1da177e4SLinus Torvalds 132*1da177e4SLinus Torvalds} 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds/* 135*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 136*1da177e4SLinus TorvaldsTakes two single-precision floating-point values `a' and `b', one of which 137*1da177e4SLinus Torvaldsis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 138*1da177e4SLinus Torvaldssignaling NaN, the invalid exception is raised. 139*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 140*1da177e4SLinus Torvalds*/ 141*1da177e4SLinus Torvaldsstatic float32 propagateFloat32NaN( float32 a, float32 b ) 142*1da177e4SLinus Torvalds{ 143*1da177e4SLinus Torvalds flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds aIsNaN = float32_is_nan( a ); 146*1da177e4SLinus Torvalds aIsSignalingNaN = float32_is_signaling_nan( a ); 147*1da177e4SLinus Torvalds bIsNaN = float32_is_nan( b ); 148*1da177e4SLinus Torvalds bIsSignalingNaN = float32_is_signaling_nan( b ); 149*1da177e4SLinus Torvalds a |= 0x00400000; 150*1da177e4SLinus Torvalds b |= 0x00400000; 151*1da177e4SLinus Torvalds if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 152*1da177e4SLinus Torvalds if ( aIsNaN ) { 153*1da177e4SLinus Torvalds return ( aIsSignalingNaN & bIsNaN ) ? b : a; 154*1da177e4SLinus Torvalds } 155*1da177e4SLinus Torvalds else { 156*1da177e4SLinus Torvalds return b; 157*1da177e4SLinus Torvalds } 158*1da177e4SLinus Torvalds 159*1da177e4SLinus Torvalds} 160*1da177e4SLinus Torvalds 161*1da177e4SLinus Torvalds/* 162*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 163*1da177e4SLinus TorvaldsThe pattern for a default generated double-precision NaN. 164*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 165*1da177e4SLinus Torvalds*/ 166*1da177e4SLinus Torvalds#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds/* 169*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 170*1da177e4SLinus TorvaldsReturns 1 if the double-precision floating-point value `a' is a NaN; 171*1da177e4SLinus Torvaldsotherwise returns 0. 172*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 173*1da177e4SLinus Torvalds*/ 174*1da177e4SLinus Torvaldsflag float64_is_nan( float64 a ) 175*1da177e4SLinus Torvalds{ 176*1da177e4SLinus Torvalds 177*1da177e4SLinus Torvalds return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 178*1da177e4SLinus Torvalds 179*1da177e4SLinus Torvalds} 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds/* 182*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 183*1da177e4SLinus TorvaldsReturns 1 if the double-precision floating-point value `a' is a signaling 184*1da177e4SLinus TorvaldsNaN; otherwise returns 0. 185*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 186*1da177e4SLinus Torvalds*/ 187*1da177e4SLinus Torvaldsflag float64_is_signaling_nan( float64 a ) 188*1da177e4SLinus Torvalds{ 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds return 191*1da177e4SLinus Torvalds ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 192*1da177e4SLinus Torvalds && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds} 195*1da177e4SLinus Torvalds 196*1da177e4SLinus Torvalds/* 197*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 198*1da177e4SLinus TorvaldsReturns the result of converting the double-precision floating-point NaN 199*1da177e4SLinus Torvalds`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 200*1da177e4SLinus Torvaldsexception is raised. 201*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 202*1da177e4SLinus Torvalds*/ 203*1da177e4SLinus Torvaldsstatic commonNaNT float64ToCommonNaN( float64 a ) 204*1da177e4SLinus Torvalds{ 205*1da177e4SLinus Torvalds commonNaNT z; 206*1da177e4SLinus Torvalds 207*1da177e4SLinus Torvalds if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 208*1da177e4SLinus Torvalds z.sign = a>>63; 209*1da177e4SLinus Torvalds z.low = 0; 210*1da177e4SLinus Torvalds z.high = a<<12; 211*1da177e4SLinus Torvalds return z; 212*1da177e4SLinus Torvalds 213*1da177e4SLinus Torvalds} 214*1da177e4SLinus Torvalds 215*1da177e4SLinus Torvalds/* 216*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 217*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the double- 218*1da177e4SLinus Torvaldsprecision floating-point format. 219*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 220*1da177e4SLinus Torvalds*/ 221*1da177e4SLinus Torvaldsstatic float64 commonNaNToFloat64( commonNaNT a ) 222*1da177e4SLinus Torvalds{ 223*1da177e4SLinus Torvalds 224*1da177e4SLinus Torvalds return 225*1da177e4SLinus Torvalds ( ( (bits64) a.sign )<<63 ) 226*1da177e4SLinus Torvalds | LIT64( 0x7FF8000000000000 ) 227*1da177e4SLinus Torvalds | ( a.high>>12 ); 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds} 230*1da177e4SLinus Torvalds 231*1da177e4SLinus Torvalds/* 232*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 233*1da177e4SLinus TorvaldsTakes two double-precision floating-point values `a' and `b', one of which 234*1da177e4SLinus Torvaldsis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 235*1da177e4SLinus Torvaldssignaling NaN, the invalid exception is raised. 236*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 237*1da177e4SLinus Torvalds*/ 238*1da177e4SLinus Torvaldsstatic float64 propagateFloat64NaN( float64 a, float64 b ) 239*1da177e4SLinus Torvalds{ 240*1da177e4SLinus Torvalds flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds aIsNaN = float64_is_nan( a ); 243*1da177e4SLinus Torvalds aIsSignalingNaN = float64_is_signaling_nan( a ); 244*1da177e4SLinus Torvalds bIsNaN = float64_is_nan( b ); 245*1da177e4SLinus Torvalds bIsSignalingNaN = float64_is_signaling_nan( b ); 246*1da177e4SLinus Torvalds a |= LIT64( 0x0008000000000000 ); 247*1da177e4SLinus Torvalds b |= LIT64( 0x0008000000000000 ); 248*1da177e4SLinus Torvalds if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 249*1da177e4SLinus Torvalds if ( aIsNaN ) { 250*1da177e4SLinus Torvalds return ( aIsSignalingNaN & bIsNaN ) ? b : a; 251*1da177e4SLinus Torvalds } 252*1da177e4SLinus Torvalds else { 253*1da177e4SLinus Torvalds return b; 254*1da177e4SLinus Torvalds } 255*1da177e4SLinus Torvalds 256*1da177e4SLinus Torvalds} 257*1da177e4SLinus Torvalds 258*1da177e4SLinus Torvalds#ifdef FLOATX80 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds/* 261*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 262*1da177e4SLinus TorvaldsThe pattern for a default generated extended double-precision NaN. The 263*1da177e4SLinus Torvalds`high' and `low' values hold the most- and least-significant bits, 264*1da177e4SLinus Torvaldsrespectively. 265*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 266*1da177e4SLinus Torvalds*/ 267*1da177e4SLinus Torvalds#define floatx80_default_nan_high 0xFFFF 268*1da177e4SLinus Torvalds#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 269*1da177e4SLinus Torvalds 270*1da177e4SLinus Torvalds/* 271*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 272*1da177e4SLinus TorvaldsReturns 1 if the extended double-precision floating-point value `a' is a 273*1da177e4SLinus TorvaldsNaN; otherwise returns 0. 274*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 275*1da177e4SLinus Torvalds*/ 276*1da177e4SLinus Torvaldsflag floatx80_is_nan( floatx80 a ) 277*1da177e4SLinus Torvalds{ 278*1da177e4SLinus Torvalds 279*1da177e4SLinus Torvalds return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds} 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds/* 284*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 285*1da177e4SLinus TorvaldsReturns 1 if the extended double-precision floating-point value `a' is a 286*1da177e4SLinus Torvaldssignaling NaN; otherwise returns 0. 287*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 288*1da177e4SLinus Torvalds*/ 289*1da177e4SLinus Torvaldsflag floatx80_is_signaling_nan( floatx80 a ) 290*1da177e4SLinus Torvalds{ 291*1da177e4SLinus Torvalds //register int lr; 292*1da177e4SLinus Torvalds bits64 aLow; 293*1da177e4SLinus Torvalds 294*1da177e4SLinus Torvalds //__asm__("mov %0, lr" : : "g" (lr)); 295*1da177e4SLinus Torvalds //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr); 296*1da177e4SLinus Torvalds aLow = a.low & ~ LIT64( 0x4000000000000000 ); 297*1da177e4SLinus Torvalds return 298*1da177e4SLinus Torvalds ( ( a.high & 0x7FFF ) == 0x7FFF ) 299*1da177e4SLinus Torvalds && (bits64) ( aLow<<1 ) 300*1da177e4SLinus Torvalds && ( a.low == aLow ); 301*1da177e4SLinus Torvalds 302*1da177e4SLinus Torvalds} 303*1da177e4SLinus Torvalds 304*1da177e4SLinus Torvalds/* 305*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 306*1da177e4SLinus TorvaldsReturns the result of converting the extended double-precision floating- 307*1da177e4SLinus Torvaldspoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 308*1da177e4SLinus Torvaldsinvalid exception is raised. 309*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 310*1da177e4SLinus Torvalds*/ 311*1da177e4SLinus Torvaldsstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 312*1da177e4SLinus Torvalds{ 313*1da177e4SLinus Torvalds commonNaNT z; 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 316*1da177e4SLinus Torvalds z.sign = a.high>>15; 317*1da177e4SLinus Torvalds z.low = 0; 318*1da177e4SLinus Torvalds z.high = a.low<<1; 319*1da177e4SLinus Torvalds return z; 320*1da177e4SLinus Torvalds 321*1da177e4SLinus Torvalds} 322*1da177e4SLinus Torvalds 323*1da177e4SLinus Torvalds/* 324*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 325*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the extended 326*1da177e4SLinus Torvaldsdouble-precision floating-point format. 327*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 328*1da177e4SLinus Torvalds*/ 329*1da177e4SLinus Torvaldsstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 330*1da177e4SLinus Torvalds{ 331*1da177e4SLinus Torvalds floatx80 z; 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 334*1da177e4SLinus Torvalds z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 335*1da177e4SLinus Torvalds return z; 336*1da177e4SLinus Torvalds 337*1da177e4SLinus Torvalds} 338*1da177e4SLinus Torvalds 339*1da177e4SLinus Torvalds/* 340*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 341*1da177e4SLinus TorvaldsTakes two extended double-precision floating-point values `a' and `b', one 342*1da177e4SLinus Torvaldsof which is a NaN, and returns the appropriate NaN result. If either `a' or 343*1da177e4SLinus Torvalds`b' is a signaling NaN, the invalid exception is raised. 344*1da177e4SLinus Torvalds------------------------------------------------------------------------------- 345*1da177e4SLinus Torvalds*/ 346*1da177e4SLinus Torvaldsstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 347*1da177e4SLinus Torvalds{ 348*1da177e4SLinus Torvalds flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 349*1da177e4SLinus Torvalds 350*1da177e4SLinus Torvalds aIsNaN = floatx80_is_nan( a ); 351*1da177e4SLinus Torvalds aIsSignalingNaN = floatx80_is_signaling_nan( a ); 352*1da177e4SLinus Torvalds bIsNaN = floatx80_is_nan( b ); 353*1da177e4SLinus Torvalds bIsSignalingNaN = floatx80_is_signaling_nan( b ); 354*1da177e4SLinus Torvalds a.low |= LIT64( 0xC000000000000000 ); 355*1da177e4SLinus Torvalds b.low |= LIT64( 0xC000000000000000 ); 356*1da177e4SLinus Torvalds if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 357*1da177e4SLinus Torvalds if ( aIsNaN ) { 358*1da177e4SLinus Torvalds return ( aIsSignalingNaN & bIsNaN ) ? b : a; 359*1da177e4SLinus Torvalds } 360*1da177e4SLinus Torvalds else { 361*1da177e4SLinus Torvalds return b; 362*1da177e4SLinus Torvalds } 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds} 365*1da177e4SLinus Torvalds 366*1da177e4SLinus Torvalds#endif 367