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) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 140 !defined(SOFTFLOAT_M68K_FOR_GCC) 141static 142#endif 143flag float32_is_signaling_nan( float32 a ) 144{ 145 146 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 147 148} 149 150/* 151------------------------------------------------------------------------------- 152Returns the result of converting the single-precision floating-point NaN 153`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 154exception is raised. 155------------------------------------------------------------------------------- 156*/ 157static commonNaNT float32ToCommonNaN( float32 a ) 158{ 159 commonNaNT z; 160 161 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 162 z.sign = a>>31; 163 z.low = 0; 164 z.high = ( (bits64) a )<<41; 165 return z; 166 167} 168 169/* 170------------------------------------------------------------------------------- 171Returns the result of converting the canonical NaN `a' to the single- 172precision floating-point format. 173------------------------------------------------------------------------------- 174*/ 175static float32 commonNaNToFloat32( commonNaNT a ) 176{ 177 178 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 ); 179 180} 181 182/* 183------------------------------------------------------------------------------- 184Takes two single-precision floating-point values `a' and `b', one of which 185is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 186signaling NaN, the invalid exception is raised. 187------------------------------------------------------------------------------- 188*/ 189static float32 propagateFloat32NaN( float32 a, float32 b ) 190{ 191 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 192 193 aIsNaN = float32_is_nan( a ); 194 aIsSignalingNaN = float32_is_signaling_nan( a ); 195 bIsNaN = float32_is_nan( b ); 196 bIsSignalingNaN = float32_is_signaling_nan( b ); 197 a |= 0x00400000; 198 b |= 0x00400000; 199 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 200 if ( aIsNaN ) { 201 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 202 } 203 else { 204 return b; 205 } 206 207} 208 209/* 210------------------------------------------------------------------------------- 211The pattern for a default generated double-precision NaN. 212------------------------------------------------------------------------------- 213*/ 214#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 215 216/* 217------------------------------------------------------------------------------- 218Returns 1 if the double-precision floating-point value `a' is a NaN; 219otherwise returns 0. 220------------------------------------------------------------------------------- 221*/ 222#ifdef SOFTFLOAT_FOR_GCC 223static 224#endif 225flag float64_is_nan( float64 a ) 226{ 227 228 return ( (bits64)LIT64( 0xFFE0000000000000 ) < 229 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) ); 230 231} 232 233/* 234------------------------------------------------------------------------------- 235Returns 1 if the double-precision floating-point value `a' is a signaling 236NaN; otherwise returns 0. 237------------------------------------------------------------------------------- 238*/ 239#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \ 240 !defined(SOFTFLOATM68K_FOR_GCC) 241static 242#endif 243flag float64_is_signaling_nan( float64 a ) 244{ 245 246 return 247 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE ) 248 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) ); 249 250} 251 252/* 253------------------------------------------------------------------------------- 254Returns the result of converting the double-precision floating-point NaN 255`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 256exception is raised. 257------------------------------------------------------------------------------- 258*/ 259static commonNaNT float64ToCommonNaN( float64 a ) 260{ 261 commonNaNT z; 262 263 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 264 z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63); 265 z.low = 0; 266 z.high = FLOAT64_DEMANGLE(a)<<12; 267 return z; 268 269} 270 271/* 272------------------------------------------------------------------------------- 273Returns the result of converting the canonical NaN `a' to the double- 274precision floating-point format. 275------------------------------------------------------------------------------- 276*/ 277static float64 commonNaNToFloat64( commonNaNT a ) 278{ 279 280 return FLOAT64_MANGLE( 281 ( ( (bits64) a.sign )<<63 ) 282 | LIT64( 0x7FF8000000000000 ) 283 | ( a.high>>12 ) ); 284 285} 286 287/* 288------------------------------------------------------------------------------- 289Takes two double-precision floating-point values `a' and `b', one of which 290is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 291signaling NaN, the invalid exception is raised. 292------------------------------------------------------------------------------- 293*/ 294static float64 propagateFloat64NaN( float64 a, float64 b ) 295{ 296 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 297 298 aIsNaN = float64_is_nan( a ); 299 aIsSignalingNaN = float64_is_signaling_nan( a ); 300 bIsNaN = float64_is_nan( b ); 301 bIsSignalingNaN = float64_is_signaling_nan( b ); 302 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 303 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 )); 304 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 305 if ( aIsNaN ) { 306 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 307 } 308 else { 309 return b; 310 } 311 312} 313 314#ifdef FLOATX80 315 316/* 317------------------------------------------------------------------------------- 318The pattern for a default generated extended double-precision NaN. The 319`high' and `low' values hold the most- and least-significant bits, 320respectively. 321------------------------------------------------------------------------------- 322*/ 323#define floatx80_default_nan_high 0xFFFF 324#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 325 326/* 327------------------------------------------------------------------------------- 328Returns 1 if the extended double-precision floating-point value `a' is a 329NaN; otherwise returns 0. 330------------------------------------------------------------------------------- 331*/ 332flag floatx80_is_nan( floatx80 a ) 333{ 334 335 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 336 337} 338 339/* 340------------------------------------------------------------------------------- 341Returns 1 if the extended double-precision floating-point value `a' is a 342signaling NaN; otherwise returns 0. 343------------------------------------------------------------------------------- 344*/ 345flag floatx80_is_signaling_nan( floatx80 a ) 346{ 347 bits64 aLow; 348 349 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 350 return 351 ( ( a.high & 0x7FFF ) == 0x7FFF ) 352 && (bits64) ( aLow<<1 ) 353 && ( a.low == aLow ); 354 355} 356 357/* 358------------------------------------------------------------------------------- 359Returns the result of converting the extended double-precision floating- 360point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 361invalid exception is raised. 362------------------------------------------------------------------------------- 363*/ 364static commonNaNT floatx80ToCommonNaN( floatx80 a ) 365{ 366 commonNaNT z; 367 368 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 369 z.sign = a.high>>15; 370 z.low = 0; 371 z.high = a.low<<1; 372 return z; 373 374} 375 376/* 377------------------------------------------------------------------------------- 378Returns the result of converting the canonical NaN `a' to the extended 379double-precision floating-point format. 380------------------------------------------------------------------------------- 381*/ 382static floatx80 commonNaNToFloatx80( commonNaNT a ) 383{ 384 floatx80 z; 385 386 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 387 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 388 return z; 389 390} 391 392/* 393------------------------------------------------------------------------------- 394Takes two extended double-precision floating-point values `a' and `b', one 395of which is a NaN, and returns the appropriate NaN result. If either `a' or 396`b' is a signaling NaN, the invalid exception is raised. 397------------------------------------------------------------------------------- 398*/ 399static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 400{ 401 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 402 403 aIsNaN = floatx80_is_nan( a ); 404 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 405 bIsNaN = floatx80_is_nan( b ); 406 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 407 a.low |= LIT64( 0xC000000000000000 ); 408 b.low |= LIT64( 0xC000000000000000 ); 409 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 410 if ( aIsNaN ) { 411 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 412 } 413 else { 414 return b; 415 } 416 417} 418 419#endif 420 421#ifdef FLOAT128 422 423/* 424------------------------------------------------------------------------------- 425The pattern for a default generated quadruple-precision NaN. The `high' and 426`low' values hold the most- and least-significant bits, respectively. 427------------------------------------------------------------------------------- 428*/ 429#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 430#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 431 432/* 433------------------------------------------------------------------------------- 434Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 435otherwise returns 0. 436------------------------------------------------------------------------------- 437*/ 438flag float128_is_nan( float128 a ) 439{ 440 441 return 442 ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 443 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 444 445} 446 447/* 448------------------------------------------------------------------------------- 449Returns 1 if the quadruple-precision floating-point value `a' is a 450signaling NaN; otherwise returns 0. 451------------------------------------------------------------------------------- 452*/ 453flag float128_is_signaling_nan( float128 a ) 454{ 455 456 return 457 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 458 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 459 460} 461 462/* 463------------------------------------------------------------------------------- 464Returns the result of converting the quadruple-precision floating-point NaN 465`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 466exception is raised. 467------------------------------------------------------------------------------- 468*/ 469static commonNaNT float128ToCommonNaN( float128 a ) 470{ 471 commonNaNT z; 472 473 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 474 z.sign = (flag)(a.high>>63); 475 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 476 return z; 477 478} 479 480/* 481------------------------------------------------------------------------------- 482Returns the result of converting the canonical NaN `a' to the quadruple- 483precision floating-point format. 484------------------------------------------------------------------------------- 485*/ 486static float128 commonNaNToFloat128( commonNaNT a ) 487{ 488 float128 z; 489 490 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 491 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 492 return z; 493 494} 495 496/* 497------------------------------------------------------------------------------- 498Takes two quadruple-precision floating-point values `a' and `b', one of 499which is a NaN, and returns the appropriate NaN result. If either `a' or 500`b' is a signaling NaN, the invalid exception is raised. 501------------------------------------------------------------------------------- 502*/ 503static float128 propagateFloat128NaN( float128 a, float128 b ) 504{ 505 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 506 507 aIsNaN = float128_is_nan( a ); 508 aIsSignalingNaN = float128_is_signaling_nan( a ); 509 bIsNaN = float128_is_nan( b ); 510 bIsSignalingNaN = float128_is_signaling_nan( b ); 511 a.high |= LIT64( 0x0000800000000000 ); 512 b.high |= LIT64( 0x0000800000000000 ); 513 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 514 if ( aIsNaN ) { 515 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 516 } 517 else { 518 return b; 519 } 520 521} 522 523#endif 524 525