softfloat-specialize revision 206490
1129203Scognet/* $NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $ */ 2129203Scognet/* $FreeBSD: head/lib/libc/softfloat/softfloat-specialize 206490 2010-04-11 20:08:54Z marius $ */ 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> 37129203Scognet 38129203Scognet/* 39129203Scognet------------------------------------------------------------------------------- 40129203ScognetUnderflow tininess-detection mode, statically initialized to default value. 41129203Scognet(The declaration in `softfloat.h' must match the `int8' type here.) 42129203Scognet------------------------------------------------------------------------------- 43129203Scognet*/ 44129203Scognet#ifdef SOFTFLOAT_FOR_GCC 45129203Scognetstatic 46129203Scognet#endif 47206490Smarius#ifdef __sparc64__ 48206490Smariusint8 float_detect_tininess = float_tininess_before_rounding; 49206490Smarius#else 50129203Scognetint8 float_detect_tininess = float_tininess_after_rounding; 51129203Scognet 52129203Scognet/* 53129203Scognet------------------------------------------------------------------------------- 54129203ScognetRaises the exceptions specified by `flags'. Floating-point traps can be 55129203Scognetdefined here if desired. It is currently not possible for such a trap to 56129203Scognetsubstitute a result value. If traps are not implemented, this routine 57129203Scognetshould be simply `float_exception_flags |= flags;'. 58129203Scognet------------------------------------------------------------------------------- 59129203Scognet*/ 60129203Scognetfp_except float_exception_mask = 0; 61129203Scognetvoid float_raise( fp_except flags ) 62129203Scognet{ 63129203Scognet 64129203Scognet float_exception_flags |= flags; 65129203Scognet 66129203Scognet if ( flags & float_exception_mask ) { 67129203Scognet raise( SIGFPE ); 68129203Scognet } 69129203Scognet} 70129203Scognet 71129203Scognet/* 72129203Scognet------------------------------------------------------------------------------- 73129203ScognetInternal canonical NaN format. 74129203Scognet------------------------------------------------------------------------------- 75129203Scognet*/ 76129203Scognettypedef struct { 77129203Scognet flag sign; 78129203Scognet bits64 high, low; 79129203Scognet} commonNaNT; 80129203Scognet 81129203Scognet/* 82129203Scognet------------------------------------------------------------------------------- 83129203ScognetThe pattern for a default generated single-precision NaN. 84129203Scognet------------------------------------------------------------------------------- 85129203Scognet*/ 86129203Scognet#define float32_default_nan 0xFFFFFFFF 87129203Scognet 88129203Scognet/* 89129203Scognet------------------------------------------------------------------------------- 90129203ScognetReturns 1 if the single-precision floating-point value `a' is a NaN; 91129203Scognetotherwise returns 0. 92129203Scognet------------------------------------------------------------------------------- 93129203Scognet*/ 94129203Scognet#ifdef SOFTFLOAT_FOR_GCC 95129203Scognetstatic 96129203Scognet#endif 97129203Scognetflag float32_is_nan( float32 a ) 98129203Scognet{ 99129203Scognet 100129203Scognet return ( 0xFF000000 < (bits32) ( a<<1 ) ); 101129203Scognet 102129203Scognet} 103129203Scognet 104129203Scognet/* 105129203Scognet------------------------------------------------------------------------------- 106129203ScognetReturns 1 if the single-precision floating-point value `a' is a signaling 107129203ScognetNaN; otherwise returns 0. 108129203Scognet------------------------------------------------------------------------------- 109129203Scognet*/ 110129203Scognet#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 111129203Scognetstatic 112129203Scognet#endif 113129203Scognetflag float32_is_signaling_nan( float32 a ) 114129203Scognet{ 115129203Scognet 116129203Scognet return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 117129203Scognet 118129203Scognet} 119129203Scognet 120129203Scognet/* 121129203Scognet------------------------------------------------------------------------------- 122129203ScognetReturns the result of converting the single-precision floating-point NaN 123129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 124129203Scognetexception is raised. 125129203Scognet------------------------------------------------------------------------------- 126129203Scognet*/ 127129203Scognetstatic commonNaNT float32ToCommonNaN( float32 a ) 128129203Scognet{ 129129203Scognet commonNaNT z; 130129203Scognet 131129203Scognet if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 132129203Scognet z.sign = a>>31; 133129203Scognet z.low = 0; 134129203Scognet z.high = ( (bits64) a )<<41; 135129203Scognet return z; 136129203Scognet 137129203Scognet} 138129203Scognet 139129203Scognet/* 140129203Scognet------------------------------------------------------------------------------- 141129203ScognetReturns the result of converting the canonical NaN `a' to the single- 142129203Scognetprecision floating-point format. 143129203Scognet------------------------------------------------------------------------------- 144129203Scognet*/ 145129203Scognetstatic float32 commonNaNToFloat32( commonNaNT a ) 146129203Scognet{ 147129203Scognet 148129203Scognet return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 149129203Scognet 150129203Scognet} 151129203Scognet 152129203Scognet/* 153129203Scognet------------------------------------------------------------------------------- 154129203ScognetTakes two single-precision floating-point values `a' and `b', one of which 155129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 156129203Scognetsignaling NaN, the invalid exception is raised. 157129203Scognet------------------------------------------------------------------------------- 158129203Scognet*/ 159129203Scognetstatic float32 propagateFloat32NaN( float32 a, float32 b ) 160129203Scognet{ 161129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 162129203Scognet 163129203Scognet aIsNaN = float32_is_nan( a ); 164129203Scognet aIsSignalingNaN = float32_is_signaling_nan( a ); 165129203Scognet bIsNaN = float32_is_nan( b ); 166129203Scognet bIsSignalingNaN = float32_is_signaling_nan( b ); 167129203Scognet a |= 0x00400000; 168129203Scognet b |= 0x00400000; 169129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 170129203Scognet if ( aIsNaN ) { 171129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 172129203Scognet } 173129203Scognet else { 174129203Scognet return b; 175129203Scognet } 176129203Scognet 177129203Scognet} 178129203Scognet 179129203Scognet/* 180129203Scognet------------------------------------------------------------------------------- 181129203ScognetThe pattern for a default generated double-precision NaN. 182129203Scognet------------------------------------------------------------------------------- 183129203Scognet*/ 184129203Scognet#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 185129203Scognet 186129203Scognet/* 187129203Scognet------------------------------------------------------------------------------- 188129203ScognetReturns 1 if the double-precision floating-point value `a' is a NaN; 189129203Scognetotherwise returns 0. 190129203Scognet------------------------------------------------------------------------------- 191129203Scognet*/ 192129203Scognet#ifdef SOFTFLOAT_FOR_GCC 193129203Scognetstatic 194129203Scognet#endif 195129203Scognetflag float64_is_nan( float64 a ) 196129203Scognet{ 197129203Scognet 198129203Scognet return ( LIT64( 0xFFE0000000000000 ) < 199129203Scognet (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 200129203Scognet 201129203Scognet} 202129203Scognet 203129203Scognet/* 204129203Scognet------------------------------------------------------------------------------- 205129203ScognetReturns 1 if the double-precision floating-point value `a' is a signaling 206129203ScognetNaN; otherwise returns 0. 207129203Scognet------------------------------------------------------------------------------- 208129203Scognet*/ 209129203Scognet#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) 210129203Scognetstatic 211129203Scognet#endif 212129203Scognetflag float64_is_signaling_nan( float64 a ) 213129203Scognet{ 214129203Scognet 215129203Scognet return 216129203Scognet ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 217129203Scognet && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 218129203Scognet 219129203Scognet} 220129203Scognet 221129203Scognet/* 222129203Scognet------------------------------------------------------------------------------- 223129203ScognetReturns the result of converting the double-precision floating-point NaN 224129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 225129203Scognetexception is raised. 226129203Scognet------------------------------------------------------------------------------- 227129203Scognet*/ 228129203Scognetstatic commonNaNT float64ToCommonNaN( float64 a ) 229129203Scognet{ 230129203Scognet commonNaNT z; 231129203Scognet 232129203Scognet if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 233129203Scognet z.sign = FLOAT64_DEMANGLE(a)>>63; 234129203Scognet z.low = 0; 235129203Scognet z.high = FLOAT64_DEMANGLE(a)<<12; 236129203Scognet return z; 237129203Scognet 238129203Scognet} 239129203Scognet 240129203Scognet/* 241129203Scognet------------------------------------------------------------------------------- 242129203ScognetReturns the result of converting the canonical NaN `a' to the double- 243129203Scognetprecision floating-point format. 244129203Scognet------------------------------------------------------------------------------- 245129203Scognet*/ 246129203Scognetstatic float64 commonNaNToFloat64( commonNaNT a ) 247129203Scognet{ 248129203Scognet 249129203Scognet return FLOAT64_MANGLE( 250129203Scognet ( ( (bits64) a.sign )<<63 ) 251129203Scognet | LIT64( 0x7FF8000000000000 ) 252129203Scognet | ( a.high>>12 ) ); 253129203Scognet 254129203Scognet} 255129203Scognet 256129203Scognet/* 257129203Scognet------------------------------------------------------------------------------- 258129203ScognetTakes two double-precision floating-point values `a' and `b', one of which 259129203Scognetis a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 260129203Scognetsignaling NaN, the invalid exception is raised. 261129203Scognet------------------------------------------------------------------------------- 262129203Scognet*/ 263129203Scognetstatic float64 propagateFloat64NaN( float64 a, float64 b ) 264129203Scognet{ 265129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 266129203Scognet 267129203Scognet aIsNaN = float64_is_nan( a ); 268129203Scognet aIsSignalingNaN = float64_is_signaling_nan( a ); 269129203Scognet bIsNaN = float64_is_nan( b ); 270129203Scognet bIsSignalingNaN = float64_is_signaling_nan( b ); 271129203Scognet a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 272129203Scognet b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 273129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 274129203Scognet if ( aIsNaN ) { 275129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 276129203Scognet } 277129203Scognet else { 278129203Scognet return b; 279129203Scognet } 280129203Scognet 281129203Scognet} 282129203Scognet 283129203Scognet#ifdef FLOATX80 284129203Scognet 285129203Scognet/* 286129203Scognet------------------------------------------------------------------------------- 287129203ScognetThe pattern for a default generated extended double-precision NaN. The 288129203Scognet`high' and `low' values hold the most- and least-significant bits, 289129203Scognetrespectively. 290129203Scognet------------------------------------------------------------------------------- 291129203Scognet*/ 292129203Scognet#define floatx80_default_nan_high 0xFFFF 293129203Scognet#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 294129203Scognet 295129203Scognet/* 296129203Scognet------------------------------------------------------------------------------- 297129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 298129203ScognetNaN; otherwise returns 0. 299129203Scognet------------------------------------------------------------------------------- 300129203Scognet*/ 301129203Scognetflag floatx80_is_nan( floatx80 a ) 302129203Scognet{ 303129203Scognet 304129203Scognet return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 305129203Scognet 306129203Scognet} 307129203Scognet 308129203Scognet/* 309129203Scognet------------------------------------------------------------------------------- 310129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a 311129203Scognetsignaling NaN; otherwise returns 0. 312129203Scognet------------------------------------------------------------------------------- 313129203Scognet*/ 314129203Scognetflag floatx80_is_signaling_nan( floatx80 a ) 315129203Scognet{ 316129203Scognet bits64 aLow; 317129203Scognet 318129203Scognet aLow = a.low & ~ LIT64( 0x4000000000000000 ); 319129203Scognet return 320129203Scognet ( ( a.high & 0x7FFF ) == 0x7FFF ) 321129203Scognet && (bits64) ( aLow<<1 ) 322129203Scognet && ( a.low == aLow ); 323129203Scognet 324129203Scognet} 325129203Scognet 326129203Scognet/* 327129203Scognet------------------------------------------------------------------------------- 328129203ScognetReturns the result of converting the extended double-precision floating- 329129203Scognetpoint NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 330129203Scognetinvalid exception is raised. 331129203Scognet------------------------------------------------------------------------------- 332129203Scognet*/ 333129203Scognetstatic commonNaNT floatx80ToCommonNaN( floatx80 a ) 334129203Scognet{ 335129203Scognet commonNaNT z; 336129203Scognet 337129203Scognet if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 338129203Scognet z.sign = a.high>>15; 339129203Scognet z.low = 0; 340129203Scognet z.high = a.low<<1; 341129203Scognet return z; 342129203Scognet 343129203Scognet} 344129203Scognet 345129203Scognet/* 346129203Scognet------------------------------------------------------------------------------- 347129203ScognetReturns the result of converting the canonical NaN `a' to the extended 348129203Scognetdouble-precision floating-point format. 349129203Scognet------------------------------------------------------------------------------- 350129203Scognet*/ 351129203Scognetstatic floatx80 commonNaNToFloatx80( commonNaNT a ) 352129203Scognet{ 353129203Scognet floatx80 z; 354129203Scognet 355129203Scognet z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 356129203Scognet z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 357129203Scognet return z; 358129203Scognet 359129203Scognet} 360129203Scognet 361129203Scognet/* 362129203Scognet------------------------------------------------------------------------------- 363129203ScognetTakes two extended double-precision floating-point values `a' and `b', one 364129203Scognetof which is a NaN, and returns the appropriate NaN result. If either `a' or 365129203Scognet`b' is a signaling NaN, the invalid exception is raised. 366129203Scognet------------------------------------------------------------------------------- 367129203Scognet*/ 368129203Scognetstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 369129203Scognet{ 370129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 371129203Scognet 372129203Scognet aIsNaN = floatx80_is_nan( a ); 373129203Scognet aIsSignalingNaN = floatx80_is_signaling_nan( a ); 374129203Scognet bIsNaN = floatx80_is_nan( b ); 375129203Scognet bIsSignalingNaN = floatx80_is_signaling_nan( b ); 376129203Scognet a.low |= LIT64( 0xC000000000000000 ); 377129203Scognet b.low |= LIT64( 0xC000000000000000 ); 378129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 379129203Scognet if ( aIsNaN ) { 380129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 381129203Scognet } 382129203Scognet else { 383129203Scognet return b; 384129203Scognet } 385129203Scognet 386129203Scognet} 387129203Scognet 388129203Scognet#endif 389129203Scognet 390129203Scognet#ifdef FLOAT128 391129203Scognet 392129203Scognet/* 393129203Scognet------------------------------------------------------------------------------- 394129203ScognetThe pattern for a default generated quadruple-precision NaN. The `high' and 395129203Scognet`low' values hold the most- and least-significant bits, respectively. 396129203Scognet------------------------------------------------------------------------------- 397129203Scognet*/ 398129203Scognet#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 399129203Scognet#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 400129203Scognet 401129203Scognet/* 402129203Scognet------------------------------------------------------------------------------- 403129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a NaN; 404129203Scognetotherwise returns 0. 405129203Scognet------------------------------------------------------------------------------- 406129203Scognet*/ 407129203Scognetflag float128_is_nan( float128 a ) 408129203Scognet{ 409129203Scognet 410129203Scognet return 411129203Scognet ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 412129203Scognet && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 413129203Scognet 414129203Scognet} 415129203Scognet 416129203Scognet/* 417129203Scognet------------------------------------------------------------------------------- 418129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a 419129203Scognetsignaling NaN; otherwise returns 0. 420129203Scognet------------------------------------------------------------------------------- 421129203Scognet*/ 422129203Scognetflag float128_is_signaling_nan( float128 a ) 423129203Scognet{ 424129203Scognet 425129203Scognet return 426129203Scognet ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 427129203Scognet && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 428129203Scognet 429129203Scognet} 430129203Scognet 431129203Scognet/* 432129203Scognet------------------------------------------------------------------------------- 433129203ScognetReturns the result of converting the quadruple-precision floating-point NaN 434129203Scognet`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 435129203Scognetexception is raised. 436129203Scognet------------------------------------------------------------------------------- 437129203Scognet*/ 438129203Scognetstatic commonNaNT float128ToCommonNaN( float128 a ) 439129203Scognet{ 440129203Scognet commonNaNT z; 441129203Scognet 442129203Scognet if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 443129203Scognet z.sign = a.high>>63; 444129203Scognet shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 445129203Scognet return z; 446129203Scognet 447129203Scognet} 448129203Scognet 449129203Scognet/* 450129203Scognet------------------------------------------------------------------------------- 451129203ScognetReturns the result of converting the canonical NaN `a' to the quadruple- 452129203Scognetprecision floating-point format. 453129203Scognet------------------------------------------------------------------------------- 454129203Scognet*/ 455129203Scognetstatic float128 commonNaNToFloat128( commonNaNT a ) 456129203Scognet{ 457129203Scognet float128 z; 458129203Scognet 459129203Scognet shift128Right( a.high, a.low, 16, &z.high, &z.low ); 460129203Scognet z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 461129203Scognet return z; 462129203Scognet 463129203Scognet} 464129203Scognet 465129203Scognet/* 466129203Scognet------------------------------------------------------------------------------- 467129203ScognetTakes two quadruple-precision floating-point values `a' and `b', one of 468129203Scognetwhich is a NaN, and returns the appropriate NaN result. If either `a' or 469129203Scognet`b' is a signaling NaN, the invalid exception is raised. 470129203Scognet------------------------------------------------------------------------------- 471129203Scognet*/ 472129203Scognetstatic float128 propagateFloat128NaN( float128 a, float128 b ) 473129203Scognet{ 474129203Scognet flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 475129203Scognet 476129203Scognet aIsNaN = float128_is_nan( a ); 477129203Scognet aIsSignalingNaN = float128_is_signaling_nan( a ); 478129203Scognet bIsNaN = float128_is_nan( b ); 479129203Scognet bIsSignalingNaN = float128_is_signaling_nan( b ); 480129203Scognet a.high |= LIT64( 0x0000800000000000 ); 481129203Scognet b.high |= LIT64( 0x0000800000000000 ); 482129203Scognet if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 483129203Scognet if ( aIsNaN ) { 484129203Scognet return ( aIsSignalingNaN & bIsNaN ) ? b : a; 485129203Scognet } 486129203Scognet else { 487129203Scognet return b; 488129203Scognet } 489129203Scognet 490129203Scognet} 491129203Scognet 492129203Scognet#endif 493129203Scognet 494