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