1/* $NetBSD: softfloat-specialize,v 1.8 2013/01/10 08:16:10 matt 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 48int8 float_detect_tininess = float_tininess_after_rounding; 49 50/* 51------------------------------------------------------------------------------- 52Raises the exceptions specified by `flags'. Floating-point traps can be 53defined here if desired. It is currently not possible for such a trap to 54substitute a result value. If traps are not implemented, this routine 55should be simply `float_exception_flags |= flags;'. 56------------------------------------------------------------------------------- 57*/ 58#ifdef SOFTFLOAT_FOR_GCC 59#ifndef set_float_exception_mask 60#define float_exception_mask _softfloat_float_exception_mask 61#endif 62#endif 63#ifndef set_float_exception_mask 64fp_except float_exception_mask = 0; 65#endif 66void 67float_raise( fp_except flags ) 68{ 69 siginfo_t info; 70 fp_except mask = float_exception_mask; 71 72#ifdef set_float_exception_mask 73 flags |= set_float_exception_flags(flags, 0); 74#else 75 float_exception_flags |= flags; 76 flags = float_exception_flags; 77#endif 78 79 flags &= mask; 80 if ( flags ) { 81 memset(&info, 0, sizeof info); 82 info.si_signo = SIGFPE; 83 info.si_pid = getpid(); 84 info.si_uid = geteuid(); 85 if (flags & float_flag_underflow) 86 info.si_code = FPE_FLTUND; 87 else if (flags & float_flag_overflow) 88 info.si_code = FPE_FLTOVF; 89 else if (flags & float_flag_divbyzero) 90 info.si_code = FPE_FLTDIV; 91 else if (flags & float_flag_invalid) 92 info.si_code = FPE_FLTINV; 93 else if (flags & float_flag_inexact) 94 info.si_code = FPE_FLTRES; 95 sigqueueinfo(getpid(), &info); 96 } 97} 98#undef float_exception_mask 99 100/* 101------------------------------------------------------------------------------- 102Internal canonical NaN format. 103------------------------------------------------------------------------------- 104*/ 105typedef struct { 106 flag sign; 107 bits64 high, low; 108} commonNaNT; 109 110/* 111------------------------------------------------------------------------------- 112The pattern for a default generated single-precision NaN. 113------------------------------------------------------------------------------- 114*/ 115#define float32_default_nan 0xFFFFFFFF 116 117/* 118------------------------------------------------------------------------------- 119Returns 1 if the single-precision floating-point value `a' is a NaN; 120otherwise returns 0. 121------------------------------------------------------------------------------- 122*/ 123#ifdef SOFTFLOAT_FOR_GCC 124static 125#endif 126flag float32_is_nan( float32 a ) 127{ 128 129 return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) ); 130 131} 132 133/* 134------------------------------------------------------------------------------- 135Returns 1 if the single-precision floating-point value `a' is a signaling 136NaN; otherwise returns 0. 137------------------------------------------------------------------------------- 138*/ 139#if defined(SOFTFLOAT_FOR_GCC) \ 140 && !defined(SOFTFLOATAARCH64_FOR_GCC) \ 141 && !defined(SOFTFLOATSPARC64_FOR_GCC) \ 142 && !defined(SOFTFLOATM68K_FOR_GCC) 143static 144#endif 145flag float32_is_signaling_nan( float32 a ) 146{ 147 148 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 149 150} 151 152/* 153------------------------------------------------------------------------------- 154Returns the result of converting the single-precision floating-point NaN 155`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 156exception is raised. 157------------------------------------------------------------------------------- 158*/ 159static commonNaNT float32ToCommonNaN( float32 a ) 160{ 161 commonNaNT z; 162 163 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 164 z.sign = a>>31; 165 z.low = 0; 166 z.high = ( (bits64) a )<<41; 167 return z; 168 169} 170 171/* 172------------------------------------------------------------------------------- 173Returns the result of converting the canonical NaN `a' to the single- 174precision floating-point format. 175------------------------------------------------------------------------------- 176*/ 177static float32 commonNaNToFloat32( commonNaNT a ) 178{ 179 180 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 ); 181 182} 183 184/* 185------------------------------------------------------------------------------- 186Takes two single-precision floating-point values `a' and `b', one of which 187is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 188signaling NaN, the invalid exception is raised. 189------------------------------------------------------------------------------- 190*/ 191static float32 propagateFloat32NaN( float32 a, float32 b ) 192{ 193 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 194 195 aIsNaN = float32_is_nan( a ); 196 aIsSignalingNaN = float32_is_signaling_nan( a ); 197 bIsNaN = float32_is_nan( b ); 198 bIsSignalingNaN = float32_is_signaling_nan( b ); 199 a |= 0x00400000; 200 b |= 0x00400000; 201 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 202 if ( aIsNaN ) { 203 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 204 } 205 else { 206 return b; 207 } 208 209} 210 211/* 212------------------------------------------------------------------------------- 213The pattern for a default generated double-precision NaN. 214------------------------------------------------------------------------------- 215*/ 216#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 217 218/* 219------------------------------------------------------------------------------- 220Returns 1 if the double-precision floating-point value `a' is a NaN; 221otherwise returns 0. 222------------------------------------------------------------------------------- 223*/ 224#ifdef SOFTFLOAT_FOR_GCC 225static 226#endif 227flag float64_is_nan( float64 a ) 228{ 229 230 return ( (bits64)LIT64( 0xFFE0000000000000 ) < 231 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 232 233} 234 235/* 236------------------------------------------------------------------------------- 237Returns 1 if the double-precision floating-point value `a' is a signaling 238NaN; otherwise returns 0. 239------------------------------------------------------------------------------- 240*/ 241#if defined(SOFTFLOAT_FOR_GCC) \ 242 && !defined(SOFTFLOATAARCH64_FOR_GCC) \ 243 && !defined(SOFTFLOATSPARC64_FOR_GCC) \ 244 && !defined(SOFTFLOATM68K_FOR_GCC) 245static 246#endif 247flag float64_is_signaling_nan( float64 a ) 248{ 249 250 return 251 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 252 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 253 254} 255 256/* 257------------------------------------------------------------------------------- 258Returns the result of converting the double-precision floating-point NaN 259`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 260exception is raised. 261------------------------------------------------------------------------------- 262*/ 263static commonNaNT float64ToCommonNaN( float64 a ) 264{ 265 commonNaNT z; 266 267 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 268 z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63); 269 z.low = 0; 270 z.high = FLOAT64_DEMANGLE(a)<<12; 271 return z; 272 273} 274 275/* 276------------------------------------------------------------------------------- 277Returns the result of converting the canonical NaN `a' to the double- 278precision floating-point format. 279------------------------------------------------------------------------------- 280*/ 281static float64 commonNaNToFloat64( commonNaNT a ) 282{ 283 284 return FLOAT64_MANGLE( 285 ( ( (bits64) a.sign )<<63 ) 286 | LIT64( 0x7FF8000000000000 ) 287 | ( a.high>>12 ) ); 288 289} 290 291/* 292------------------------------------------------------------------------------- 293Takes two double-precision floating-point values `a' and `b', one of which 294is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 295signaling NaN, the invalid exception is raised. 296------------------------------------------------------------------------------- 297*/ 298static float64 propagateFloat64NaN( float64 a, float64 b ) 299{ 300 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 301 302 aIsNaN = float64_is_nan( a ); 303 aIsSignalingNaN = float64_is_signaling_nan( a ); 304 bIsNaN = float64_is_nan( b ); 305 bIsSignalingNaN = float64_is_signaling_nan( b ); 306 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 307 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 308 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 309 if ( aIsNaN ) { 310 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 311 } 312 else { 313 return b; 314 } 315 316} 317 318#ifdef FLOATX80 319 320/* 321------------------------------------------------------------------------------- 322The pattern for a default generated extended double-precision NaN. The 323`high' and `low' values hold the most- and least-significant bits, 324respectively. 325------------------------------------------------------------------------------- 326*/ 327#define floatx80_default_nan_high 0xFFFF 328#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 329 330/* 331------------------------------------------------------------------------------- 332Returns 1 if the extended double-precision floating-point value `a' is a 333NaN; otherwise returns 0. 334------------------------------------------------------------------------------- 335*/ 336flag floatx80_is_nan( floatx80 a ) 337{ 338 339 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 340 341} 342 343/* 344------------------------------------------------------------------------------- 345Returns 1 if the extended double-precision floating-point value `a' is a 346signaling NaN; otherwise returns 0. 347------------------------------------------------------------------------------- 348*/ 349flag floatx80_is_signaling_nan( floatx80 a ) 350{ 351 bits64 aLow; 352 353 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 354 return 355 ( ( a.high & 0x7FFF ) == 0x7FFF ) 356 && (bits64) ( aLow<<1 ) 357 && ( a.low == aLow ); 358 359} 360 361/* 362------------------------------------------------------------------------------- 363Returns the result of converting the extended double-precision floating- 364point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 365invalid exception is raised. 366------------------------------------------------------------------------------- 367*/ 368static commonNaNT floatx80ToCommonNaN( floatx80 a ) 369{ 370 commonNaNT z; 371 372 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 373 z.sign = a.high>>15; 374 z.low = 0; 375 z.high = a.low<<1; 376 return z; 377 378} 379 380/* 381------------------------------------------------------------------------------- 382Returns the result of converting the canonical NaN `a' to the extended 383double-precision floating-point format. 384------------------------------------------------------------------------------- 385*/ 386static floatx80 commonNaNToFloatx80( commonNaNT a ) 387{ 388 floatx80 z; 389 390 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 391 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 392 return z; 393 394} 395 396/* 397------------------------------------------------------------------------------- 398Takes two extended double-precision floating-point values `a' and `b', one 399of which is a NaN, and returns the appropriate NaN result. If either `a' or 400`b' is a signaling NaN, the invalid exception is raised. 401------------------------------------------------------------------------------- 402*/ 403static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 404{ 405 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 406 407 aIsNaN = floatx80_is_nan( a ); 408 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 409 bIsNaN = floatx80_is_nan( b ); 410 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 411 a.low |= LIT64( 0xC000000000000000 ); 412 b.low |= LIT64( 0xC000000000000000 ); 413 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 414 if ( aIsNaN ) { 415 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 416 } 417 else { 418 return b; 419 } 420 421} 422 423#endif 424 425#ifdef FLOAT128 426 427/* 428------------------------------------------------------------------------------- 429The pattern for a default generated quadruple-precision NaN. The `high' and 430`low' values hold the most- and least-significant bits, respectively. 431------------------------------------------------------------------------------- 432*/ 433#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 434#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 435 436/* 437------------------------------------------------------------------------------- 438Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 439otherwise returns 0. 440------------------------------------------------------------------------------- 441*/ 442flag float128_is_nan( float128 a ) 443{ 444 445 return 446 ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 447 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 448 449} 450 451/* 452------------------------------------------------------------------------------- 453Returns 1 if the quadruple-precision floating-point value `a' is a 454signaling NaN; otherwise returns 0. 455------------------------------------------------------------------------------- 456*/ 457flag float128_is_signaling_nan( float128 a ) 458{ 459 460 return 461 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 462 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 463 464} 465 466/* 467------------------------------------------------------------------------------- 468Returns the result of converting the quadruple-precision floating-point NaN 469`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 470exception is raised. 471------------------------------------------------------------------------------- 472*/ 473static commonNaNT float128ToCommonNaN( float128 a ) 474{ 475 commonNaNT z; 476 477 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 478 z.sign = (flag)(a.high>>63); 479 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 480 return z; 481 482} 483 484/* 485------------------------------------------------------------------------------- 486Returns the result of converting the canonical NaN `a' to the quadruple- 487precision floating-point format. 488------------------------------------------------------------------------------- 489*/ 490static float128 commonNaNToFloat128( commonNaNT a ) 491{ 492 float128 z; 493 494 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 495 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 496 return z; 497 498} 499 500/* 501------------------------------------------------------------------------------- 502Takes two quadruple-precision floating-point values `a' and `b', one of 503which is a NaN, and returns the appropriate NaN result. If either `a' or 504`b' is a signaling NaN, the invalid exception is raised. 505------------------------------------------------------------------------------- 506*/ 507static float128 propagateFloat128NaN( float128 a, float128 b ) 508{ 509 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 510 511 aIsNaN = float128_is_nan( a ); 512 aIsSignalingNaN = float128_is_signaling_nan( a ); 513 bIsNaN = float128_is_nan( b ); 514 bIsSignalingNaN = float128_is_signaling_nan( b ); 515 a.high |= LIT64( 0x0000800000000000 ); 516 b.high |= LIT64( 0x0000800000000000 ); 517 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 518 if ( aIsNaN ) { 519 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 520 } 521 else { 522 return b; 523 } 524 525} 526 527#endif 528 529