1/* $NetBSD: softfloat-specialize,v 1.6 2011/03/06 10:27:37 martin Exp $ */ 2 3/* This is a derivative work. */ 4 5/* 6=============================================================================== 7 8This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 9Arithmetic Package, Release 2a. 10 11Written by John R. Hauser. This work was made possible in part by the 12International Computer Science Institute, located at Suite 600, 1947 Center 13Street, Berkeley, California 94704. Funding was partially provided by the 14National Science Foundation under grant MIP-9311980. The original version 15of this code was written as part of a project to build a fixed-point vector 16processor in collaboration with the University of California at Berkeley, 17overseen by Profs. Nelson Morgan and John Wawrzynek. More information 18is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 19arithmetic/SoftFloat.html'. 20 21THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 22has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 23TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 24PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 25AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 26 27Derivative works are acceptable, even for commercial purposes, so long as 28(1) they include prominent notice that the work is derivative, and (2) they 29include prominent notice akin to these four paragraphs for those parts of 30this code that are retained. 31 32=============================================================================== 33*/ 34 35#include <signal.h> 36#include <string.h> 37#include <unistd.h> 38 39/* 40------------------------------------------------------------------------------- 41Underflow tininess-detection mode, statically initialized to default value. 42(The declaration in `softfloat.h' must match the `int8' type here.) 43------------------------------------------------------------------------------- 44*/ 45#ifdef SOFTFLOAT_FOR_GCC 46static 47#endif 48#ifdef __sparc64__ 49int8 float_detect_tininess = float_tininess_before_rounding; 50#else 51int8 float_detect_tininess = float_tininess_after_rounding; 52#endif 53 54/* 55------------------------------------------------------------------------------- 56Raises the exceptions specified by `flags'. Floating-point traps can be 57defined here if desired. It is currently not possible for such a trap to 58substitute a result value. If traps are not implemented, this routine 59should be simply `float_exception_flags |= flags;'. 60------------------------------------------------------------------------------- 61*/ 62#ifdef SOFTFLOAT_FOR_GCC 63#define float_exception_mask __softfloat_float_exception_mask 64#endif 65int float_exception_mask = 0; 66void float_raise( int flags ) 67{ 68 69 float_exception_flags |= flags; 70 71 if ( flags & float_exception_mask ) { 72#if 0 73 siginfo_t info; 74 memset(&info, 0, sizeof info); 75 info.si_signo = SIGFPE; 76 info.si_pid = getpid(); 77 info.si_uid = geteuid(); 78 if (flags & float_flag_underflow) 79 info.si_code = FPE_FLTUND; 80 else if (flags & float_flag_overflow) 81 info.si_code = FPE_FLTOVF; 82 else if (flags & float_flag_divbyzero) 83 info.si_code = FPE_FLTDIV; 84 else if (flags & float_flag_invalid) 85 info.si_code = FPE_FLTINV; 86 else if (flags & float_flag_inexact) 87 info.si_code = FPE_FLTRES; 88 sigqueueinfo(getpid(), &info); 89#else 90 raise( SIGFPE ); 91#endif 92 } 93} 94#undef float_exception_mask 95 96/* 97------------------------------------------------------------------------------- 98Internal canonical NaN format. 99------------------------------------------------------------------------------- 100*/ 101typedef struct { 102 flag sign; 103 bits64 high, low; 104} commonNaNT; 105 106/* 107------------------------------------------------------------------------------- 108The pattern for a default generated single-precision NaN. 109------------------------------------------------------------------------------- 110*/ 111#define float32_default_nan 0xFFFFFFFF 112 113/* 114------------------------------------------------------------------------------- 115Returns 1 if the single-precision floating-point value `a' is a NaN; 116otherwise returns 0. 117------------------------------------------------------------------------------- 118*/ 119#ifdef SOFTFLOAT_FOR_GCC 120static 121#endif 122flag float32_is_nan( float32 a ) 123{ 124 125 return ( 0xFF000000 < (bits32) ( a<<1 ) ); 126 127} 128 129/* 130------------------------------------------------------------------------------- 131Returns 1 if the single-precision floating-point value `a' is a signaling 132NaN; otherwise returns 0. 133------------------------------------------------------------------------------- 134*/ 135#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 136 !defined(SOFTFLOAT_M68K_FOR_GCC) 137static 138#endif 139flag float32_is_signaling_nan( float32 a ) 140{ 141 142 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 143 144} 145 146/* 147------------------------------------------------------------------------------- 148Returns the result of converting the single-precision floating-point NaN 149`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 150exception is raised. 151------------------------------------------------------------------------------- 152*/ 153static commonNaNT float32ToCommonNaN( float32 a ) 154{ 155 commonNaNT z; 156 157 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 158 z.sign = a>>31; 159 z.low = 0; 160 z.high = ( (bits64) a )<<41; 161 return z; 162 163} 164 165/* 166------------------------------------------------------------------------------- 167Returns the result of converting the canonical NaN `a' to the single- 168precision floating-point format. 169------------------------------------------------------------------------------- 170*/ 171static float32 commonNaNToFloat32( commonNaNT a ) 172{ 173 174 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 175 176} 177 178/* 179------------------------------------------------------------------------------- 180Takes two single-precision floating-point values `a' and `b', one of which 181is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 182signaling NaN, the invalid exception is raised. 183------------------------------------------------------------------------------- 184*/ 185static float32 propagateFloat32NaN( float32 a, float32 b ) 186{ 187 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 188 189 aIsNaN = float32_is_nan( a ); 190 aIsSignalingNaN = float32_is_signaling_nan( a ); 191 bIsNaN = float32_is_nan( b ); 192 bIsSignalingNaN = float32_is_signaling_nan( b ); 193 a |= 0x00400000; 194 b |= 0x00400000; 195 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 196 if ( aIsNaN ) { 197 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 198 } 199 else { 200 return b; 201 } 202 203} 204 205/* 206------------------------------------------------------------------------------- 207The pattern for a default generated double-precision NaN. 208------------------------------------------------------------------------------- 209*/ 210#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 211 212/* 213------------------------------------------------------------------------------- 214Returns 1 if the double-precision floating-point value `a' is a NaN; 215otherwise returns 0. 216------------------------------------------------------------------------------- 217*/ 218#ifdef SOFTFLOAT_FOR_GCC 219static 220#endif 221flag float64_is_nan( float64 a ) 222{ 223 224 return ( LIT64( 0xFFE0000000000000 ) < 225 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 226 227} 228 229/* 230------------------------------------------------------------------------------- 231Returns 1 if the double-precision floating-point value `a' is a signaling 232NaN; otherwise returns 0. 233------------------------------------------------------------------------------- 234*/ 235#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 236 !defined(SOFTFLOATM68K_FOR_GCC) 237static 238#endif 239flag float64_is_signaling_nan( float64 a ) 240{ 241 242 return 243 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 244 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 245 246} 247 248/* 249------------------------------------------------------------------------------- 250Returns the result of converting the double-precision floating-point NaN 251`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 252exception is raised. 253------------------------------------------------------------------------------- 254*/ 255static commonNaNT float64ToCommonNaN( float64 a ) 256{ 257 commonNaNT z; 258 259 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 260 z.sign = FLOAT64_DEMANGLE(a)>>63; 261 z.low = 0; 262 z.high = FLOAT64_DEMANGLE(a)<<12; 263 return z; 264 265} 266 267/* 268------------------------------------------------------------------------------- 269Returns the result of converting the canonical NaN `a' to the double- 270precision floating-point format. 271------------------------------------------------------------------------------- 272*/ 273static float64 commonNaNToFloat64( commonNaNT a ) 274{ 275 276 return FLOAT64_MANGLE( 277 ( ( (bits64) a.sign )<<63 ) 278 | LIT64( 0x7FF8000000000000 ) 279 | ( a.high>>12 ) ); 280 281} 282 283/* 284------------------------------------------------------------------------------- 285Takes two double-precision floating-point values `a' and `b', one of which 286is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 287signaling NaN, the invalid exception is raised. 288------------------------------------------------------------------------------- 289*/ 290static float64 propagateFloat64NaN( float64 a, float64 b ) 291{ 292 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 293 294 aIsNaN = float64_is_nan( a ); 295 aIsSignalingNaN = float64_is_signaling_nan( a ); 296 bIsNaN = float64_is_nan( b ); 297 bIsSignalingNaN = float64_is_signaling_nan( b ); 298 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 299 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 300 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 301 if ( aIsNaN ) { 302 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 303 } 304 else { 305 return b; 306 } 307 308} 309 310#ifdef FLOATX80 311 312/* 313------------------------------------------------------------------------------- 314The pattern for a default generated extended double-precision NaN. The 315`high' and `low' values hold the most- and least-significant bits, 316respectively. 317------------------------------------------------------------------------------- 318*/ 319#define floatx80_default_nan_high 0xFFFF 320#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 321 322/* 323------------------------------------------------------------------------------- 324Returns 1 if the extended double-precision floating-point value `a' is a 325NaN; otherwise returns 0. 326------------------------------------------------------------------------------- 327*/ 328flag floatx80_is_nan( floatx80 a ) 329{ 330 331 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 332 333} 334 335/* 336------------------------------------------------------------------------------- 337Returns 1 if the extended double-precision floating-point value `a' is a 338signaling NaN; otherwise returns 0. 339------------------------------------------------------------------------------- 340*/ 341flag floatx80_is_signaling_nan( floatx80 a ) 342{ 343 bits64 aLow; 344 345 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 346 return 347 ( ( a.high & 0x7FFF ) == 0x7FFF ) 348 && (bits64) ( aLow<<1 ) 349 && ( a.low == aLow ); 350 351} 352 353/* 354------------------------------------------------------------------------------- 355Returns the result of converting the extended double-precision floating- 356point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 357invalid exception is raised. 358------------------------------------------------------------------------------- 359*/ 360static commonNaNT floatx80ToCommonNaN( floatx80 a ) 361{ 362 commonNaNT z; 363 364 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 365 z.sign = a.high>>15; 366 z.low = 0; 367 z.high = a.low<<1; 368 return z; 369 370} 371 372/* 373------------------------------------------------------------------------------- 374Returns the result of converting the canonical NaN `a' to the extended 375double-precision floating-point format. 376------------------------------------------------------------------------------- 377*/ 378static floatx80 commonNaNToFloatx80( commonNaNT a ) 379{ 380 floatx80 z; 381 382 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 383 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 384 return z; 385 386} 387 388/* 389------------------------------------------------------------------------------- 390Takes two extended double-precision floating-point values `a' and `b', one 391of which is a NaN, and returns the appropriate NaN result. If either `a' or 392`b' is a signaling NaN, the invalid exception is raised. 393------------------------------------------------------------------------------- 394*/ 395static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 396{ 397 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 398 399 aIsNaN = floatx80_is_nan( a ); 400 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 401 bIsNaN = floatx80_is_nan( b ); 402 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 403 a.low |= LIT64( 0xC000000000000000 ); 404 b.low |= LIT64( 0xC000000000000000 ); 405 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 406 if ( aIsNaN ) { 407 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 408 } 409 else { 410 return b; 411 } 412 413} 414 415#endif 416 417#ifdef FLOAT128 418 419/* 420------------------------------------------------------------------------------- 421The pattern for a default generated quadruple-precision NaN. The `high' and 422`low' values hold the most- and least-significant bits, respectively. 423------------------------------------------------------------------------------- 424*/ 425#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 426#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 427 428/* 429------------------------------------------------------------------------------- 430Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 431otherwise returns 0. 432------------------------------------------------------------------------------- 433*/ 434flag float128_is_nan( float128 a ) 435{ 436 437 return 438 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 439 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 440 441} 442 443/* 444------------------------------------------------------------------------------- 445Returns 1 if the quadruple-precision floating-point value `a' is a 446signaling NaN; otherwise returns 0. 447------------------------------------------------------------------------------- 448*/ 449flag float128_is_signaling_nan( float128 a ) 450{ 451 452 return 453 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 454 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 455 456} 457 458/* 459------------------------------------------------------------------------------- 460Returns the result of converting the quadruple-precision floating-point NaN 461`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 462exception is raised. 463------------------------------------------------------------------------------- 464*/ 465static commonNaNT float128ToCommonNaN( float128 a ) 466{ 467 commonNaNT z; 468 469 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 470 z.sign = a.high>>63; 471 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 472 return z; 473 474} 475 476/* 477------------------------------------------------------------------------------- 478Returns the result of converting the canonical NaN `a' to the quadruple- 479precision floating-point format. 480------------------------------------------------------------------------------- 481*/ 482static float128 commonNaNToFloat128( commonNaNT a ) 483{ 484 float128 z; 485 486 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 487 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 488 return z; 489 490} 491 492/* 493------------------------------------------------------------------------------- 494Takes two quadruple-precision floating-point values `a' and `b', one of 495which is a NaN, and returns the appropriate NaN result. If either `a' or 496`b' is a signaling NaN, the invalid exception is raised. 497------------------------------------------------------------------------------- 498*/ 499static float128 propagateFloat128NaN( float128 a, float128 b ) 500{ 501 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 502 503 aIsNaN = float128_is_nan( a ); 504 aIsSignalingNaN = float128_is_signaling_nan( a ); 505 bIsNaN = float128_is_nan( b ); 506 bIsSignalingNaN = float128_is_signaling_nan( b ); 507 a.high |= LIT64( 0x0000800000000000 ); 508 b.high |= LIT64( 0x0000800000000000 ); 509 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 510 if ( aIsNaN ) { 511 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 512 } 513 else { 514 return b; 515 } 516 517} 518 519#endif 520 521