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