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