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