softfloat-specialize revision 129203
1189251Ssam/* $FreeBSD: head/lib/libc/softfloat/templates/softfloat-specialize 129203 2004-05-14 12:13:06Z cognet $ */ 2189251Ssam 3189251Ssam/* 4189251Ssam=============================================================================== 5252726Srpaulo 6252726SrpauloThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point 7189251SsamArithmetic Package, Release 2a. 8189251Ssam 9189251SsamWritten by John R. Hauser. This work was made possible in part by the 10189251SsamInternational Computer Science Institute, located at Suite 600, 1947 Center 11189251SsamStreet, Berkeley, California 94704. Funding was partially provided by the 12189251SsamNational Science Foundation under grant MIP-9311980. The original version 13189251Ssamof this code was written as part of a project to build a fixed-point vector 14189251Ssamprocessor in collaboration with the University of California at Berkeley, 15189251Ssamoverseen by Profs. Nelson Morgan and John Wawrzynek. More information 16189251Ssamis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 17189251Ssamarithmetic/SoftFloat.html'. 18189251Ssam 19189251SsamTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 20189251Ssamhas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 21189251SsamTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 22189251SsamPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 23189251SsamAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 24189251Ssam 25189251SsamDerivative works are acceptable, even for commercial purposes, so long as 26189251Ssam(1) they include prominent notice that the work is derivative, and (2) they 27189251Ssaminclude prominent notice akin to these four paragraphs for those parts of 28189251Ssamthis code that are retained. 29189251Ssam 30189251Ssam=============================================================================== 31189251Ssam*/ 32189251Ssam 33189251Ssam/* 34189251Ssam------------------------------------------------------------------------------- 35189251SsamUnderflow tininess-detection mode, statically initialized to default value. 36189251Ssam(The declaration in `softfloat.h' must match the `int8' type here.) 37189251Ssam------------------------------------------------------------------------------- 38189251Ssam*/ 39189251Ssamint8 float_detect_tininess = float_tininess_after_rounding; 40189251Ssam 41189251Ssam/* 42189251Ssam------------------------------------------------------------------------------- 43189251SsamRaises the exceptions specified by `flags'. Floating-point traps can be 44189251Ssamdefined here if desired. It is currently not possible for such a trap to 45189251Ssamsubstitute a result value. If traps are not implemented, this routine 46189251Ssamshould be simply `float_exception_flags |= flags;'. 47189251Ssam------------------------------------------------------------------------------- 48189251Ssam*/ 49189251Ssamvoid float_raise( int8 flags ) 50189251Ssam{ 51189251Ssam 52189251Ssam float_exception_flags |= flags; 53189251Ssam 54189251Ssam} 55189251Ssam 56189251Ssam/* 57189251Ssam------------------------------------------------------------------------------- 58189251SsamInternal canonical NaN format. 59189251Ssam------------------------------------------------------------------------------- 60189251Ssam*/ 61189251Ssamtypedef struct { 62189251Ssam flag sign; 63189251Ssam bits64 high, low; 64189251Ssam} commonNaNT; 65189251Ssam 66189251Ssam/* 67189251Ssam------------------------------------------------------------------------------- 68189251SsamThe pattern for a default generated single-precision NaN. 69189251Ssam------------------------------------------------------------------------------- 70189251Ssam*/ 71189251Ssam#define float32_default_nan 0xFFFFFFFF 72189251Ssam 73189251Ssam/* 74189251Ssam------------------------------------------------------------------------------- 75189251SsamReturns 1 if the single-precision floating-point value `a' is a NaN; 76189251Ssamotherwise returns 0. 77189251Ssam------------------------------------------------------------------------------- 78189251Ssam*/ 79189251Ssamflag float32_is_nan( float32 a ) 80189251Ssam{ 81189251Ssam 82189251Ssam return ( 0xFF000000 < (bits32) ( a<<1 ) ); 83189251Ssam 84189251Ssam} 85189251Ssam 86189251Ssam/* 87189251Ssam------------------------------------------------------------------------------- 88189251SsamReturns 1 if the single-precision floating-point value `a' is a signaling 89189251SsamNaN; otherwise returns 0. 90189251Ssam------------------------------------------------------------------------------- 91189251Ssam*/ 92189251Ssamflag float32_is_signaling_nan( float32 a ) 93189251Ssam{ 94189251Ssam 95189251Ssam return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 96189251Ssam 97189251Ssam} 98189251Ssam 99189251Ssam/* 100189251Ssam------------------------------------------------------------------------------- 101189251SsamReturns the result of converting the single-precision floating-point NaN 102189251Ssam`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 103189251Ssamexception is raised. 104189251Ssam------------------------------------------------------------------------------- 105189251Ssam*/ 106189251Ssamstatic commonNaNT float32ToCommonNaN( float32 a ) 107189251Ssam{ 108189251Ssam commonNaNT z; 109189251Ssam 110189251Ssam if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 111189251Ssam z.sign = a>>31; 112189251Ssam z.low = 0; 113189251Ssam z.high = ( (bits64) a )<<41; 114189251Ssam return z; 115189251Ssam 116189251Ssam} 117189251Ssam 118189251Ssam/* 119189251Ssam------------------------------------------------------------------------------- 120189251SsamReturns the result of converting the canonical NaN `a' to the single- 121189251Ssamprecision floating-point format. 122189251Ssam------------------------------------------------------------------------------- 123189251Ssam*/ 124189251Ssamstatic float32 commonNaNToFloat32( commonNaNT a ) 125189251Ssam{ 126189251Ssam 127 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 128 129} 130 131/* 132------------------------------------------------------------------------------- 133Takes two single-precision floating-point values `a' and `b', one of which 134is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 135signaling NaN, the invalid exception is raised. 136------------------------------------------------------------------------------- 137*/ 138static float32 propagateFloat32NaN( float32 a, float32 b ) 139{ 140 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 141 142 aIsNaN = float32_is_nan( a ); 143 aIsSignalingNaN = float32_is_signaling_nan( a ); 144 bIsNaN = float32_is_nan( b ); 145 bIsSignalingNaN = float32_is_signaling_nan( b ); 146 a |= 0x00400000; 147 b |= 0x00400000; 148 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 149 if ( aIsNaN ) { 150 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 151 } 152 else { 153 return b; 154 } 155 156} 157 158/* 159------------------------------------------------------------------------------- 160The pattern for a default generated double-precision NaN. 161------------------------------------------------------------------------------- 162*/ 163#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 164 165/* 166------------------------------------------------------------------------------- 167Returns 1 if the double-precision floating-point value `a' is a NaN; 168otherwise returns 0. 169------------------------------------------------------------------------------- 170*/ 171flag float64_is_nan( float64 a ) 172{ 173 174 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 175 176} 177 178/* 179------------------------------------------------------------------------------- 180Returns 1 if the double-precision floating-point value `a' is a signaling 181NaN; otherwise returns 0. 182------------------------------------------------------------------------------- 183*/ 184flag float64_is_signaling_nan( float64 a ) 185{ 186 187 return 188 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 189 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 190 191} 192 193/* 194------------------------------------------------------------------------------- 195Returns the result of converting the double-precision floating-point NaN 196`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 197exception is raised. 198------------------------------------------------------------------------------- 199*/ 200static commonNaNT float64ToCommonNaN( float64 a ) 201{ 202 commonNaNT z; 203 204 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 205 z.sign = a>>63; 206 z.low = 0; 207 z.high = a<<12; 208 return z; 209 210} 211 212/* 213------------------------------------------------------------------------------- 214Returns the result of converting the canonical NaN `a' to the double- 215precision floating-point format. 216------------------------------------------------------------------------------- 217*/ 218static float64 commonNaNToFloat64( commonNaNT a ) 219{ 220 221 return 222 ( ( (bits64) a.sign )<<63 ) 223 | LIT64( 0x7FF8000000000000 ) 224 | ( a.high>>12 ); 225 226} 227 228/* 229------------------------------------------------------------------------------- 230Takes two double-precision floating-point values `a' and `b', one of which 231is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 232signaling NaN, the invalid exception is raised. 233------------------------------------------------------------------------------- 234*/ 235static float64 propagateFloat64NaN( float64 a, float64 b ) 236{ 237 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 238 239 aIsNaN = float64_is_nan( a ); 240 aIsSignalingNaN = float64_is_signaling_nan( a ); 241 bIsNaN = float64_is_nan( b ); 242 bIsSignalingNaN = float64_is_signaling_nan( b ); 243 a |= LIT64( 0x0008000000000000 ); 244 b |= LIT64( 0x0008000000000000 ); 245 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 246 if ( aIsNaN ) { 247 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 248 } 249 else { 250 return b; 251 } 252 253} 254 255#ifdef FLOATX80 256 257/* 258------------------------------------------------------------------------------- 259The pattern for a default generated extended double-precision NaN. The 260`high' and `low' values hold the most- and least-significant bits, 261respectively. 262------------------------------------------------------------------------------- 263*/ 264#define floatx80_default_nan_high 0xFFFF 265#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 266 267/* 268------------------------------------------------------------------------------- 269Returns 1 if the extended double-precision floating-point value `a' is a 270NaN; otherwise returns 0. 271------------------------------------------------------------------------------- 272*/ 273flag floatx80_is_nan( floatx80 a ) 274{ 275 276 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 277 278} 279 280/* 281------------------------------------------------------------------------------- 282Returns 1 if the extended double-precision floating-point value `a' is a 283signaling NaN; otherwise returns 0. 284------------------------------------------------------------------------------- 285*/ 286flag floatx80_is_signaling_nan( floatx80 a ) 287{ 288 bits64 aLow; 289 290 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 291 return 292 ( ( a.high & 0x7FFF ) == 0x7FFF ) 293 && (bits64) ( aLow<<1 ) 294 && ( a.low == aLow ); 295 296} 297 298/* 299------------------------------------------------------------------------------- 300Returns the result of converting the extended double-precision floating- 301point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 302invalid exception is raised. 303------------------------------------------------------------------------------- 304*/ 305static commonNaNT floatx80ToCommonNaN( floatx80 a ) 306{ 307 commonNaNT z; 308 309 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 310 z.sign = a.high>>15; 311 z.low = 0; 312 z.high = a.low<<1; 313 return z; 314 315} 316 317/* 318------------------------------------------------------------------------------- 319Returns the result of converting the canonical NaN `a' to the extended 320double-precision floating-point format. 321------------------------------------------------------------------------------- 322*/ 323static floatx80 commonNaNToFloatx80( commonNaNT a ) 324{ 325 floatx80 z; 326 327 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 328 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 329 return z; 330 331} 332 333/* 334------------------------------------------------------------------------------- 335Takes two extended double-precision floating-point values `a' and `b', one 336of which is a NaN, and returns the appropriate NaN result. If either `a' or 337`b' is a signaling NaN, the invalid exception is raised. 338------------------------------------------------------------------------------- 339*/ 340static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 341{ 342 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 343 344 aIsNaN = floatx80_is_nan( a ); 345 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 346 bIsNaN = floatx80_is_nan( b ); 347 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 348 a.low |= LIT64( 0xC000000000000000 ); 349 b.low |= LIT64( 0xC000000000000000 ); 350 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 351 if ( aIsNaN ) { 352 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 353 } 354 else { 355 return b; 356 } 357 358} 359 360#endif 361 362#ifdef FLOAT128 363 364/* 365------------------------------------------------------------------------------- 366The pattern for a default generated quadruple-precision NaN. The `high' and 367`low' values hold the most- and least-significant bits, respectively. 368------------------------------------------------------------------------------- 369*/ 370#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 371#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 372 373/* 374------------------------------------------------------------------------------- 375Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 376otherwise returns 0. 377------------------------------------------------------------------------------- 378*/ 379flag float128_is_nan( float128 a ) 380{ 381 382 return 383 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 384 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 385 386} 387 388/* 389------------------------------------------------------------------------------- 390Returns 1 if the quadruple-precision floating-point value `a' is a 391signaling NaN; otherwise returns 0. 392------------------------------------------------------------------------------- 393*/ 394flag float128_is_signaling_nan( float128 a ) 395{ 396 397 return 398 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 399 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 400 401} 402 403/* 404------------------------------------------------------------------------------- 405Returns the result of converting the quadruple-precision floating-point NaN 406`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 407exception is raised. 408------------------------------------------------------------------------------- 409*/ 410static commonNaNT float128ToCommonNaN( float128 a ) 411{ 412 commonNaNT z; 413 414 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 415 z.sign = a.high>>63; 416 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 417 return z; 418 419} 420 421/* 422------------------------------------------------------------------------------- 423Returns the result of converting the canonical NaN `a' to the quadruple- 424precision floating-point format. 425------------------------------------------------------------------------------- 426*/ 427static float128 commonNaNToFloat128( commonNaNT a ) 428{ 429 float128 z; 430 431 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 432 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 433 return z; 434 435} 436 437/* 438------------------------------------------------------------------------------- 439Takes two quadruple-precision floating-point values `a' and `b', one of 440which is a NaN, and returns the appropriate NaN result. If either `a' or 441`b' is a signaling NaN, the invalid exception is raised. 442------------------------------------------------------------------------------- 443*/ 444static float128 propagateFloat128NaN( float128 a, float128 b ) 445{ 446 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 447 448 aIsNaN = float128_is_nan( a ); 449 aIsSignalingNaN = float128_is_signaling_nan( a ); 450 bIsNaN = float128_is_nan( b ); 451 bIsSignalingNaN = float128_is_signaling_nan( b ); 452 a.high |= LIT64( 0x0000800000000000 ); 453 b.high |= LIT64( 0x0000800000000000 ); 454 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 455 if ( aIsNaN ) { 456 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 457 } 458 else { 459 return b; 460 } 461 462} 463 464#endif 465 466