1 /* $NetBSD: softfloat-specialize.h,v 1.3 2020/09/02 03:41:56 thorpej 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 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /*============================================================================ 35 36 This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point 37 Arithmetic Package, Release 2c, by John R. Hauser. 38 39 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 40 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 41 RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 42 AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER 43 PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR 44 THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY 45 INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE 46 (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER 47 PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR 48 INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE 49 SOFTWARE. 50 51 Derivative works require also that (1) the source code for the derivative work 52 includes prominent notice that the work is derivative, and (2) the source code 53 includes prominent notice of these three paragraphs for those parts of this 54 code that are retained. 55 56 =============================================================================*/ 57 58 /*---------------------------------------------------------------------------- 59 | Underflow tininess-detection mode, statically initialized to default value. 60 | (The declaration in `softfloat.h' must match the `int8' type here.) 61 *----------------------------------------------------------------------------*/ 62 /* [ MP safe, does not change dynamically ] */ 63 int float_detect_tininess = float_tininess_after_rounding; 64 65 /*---------------------------------------------------------------------------- 66 | Internal canonical NaN format. 67 *----------------------------------------------------------------------------*/ 68 typedef struct { 69 flag sign; 70 bits64 high, low; 71 } commonNaNT; 72 73 /*---------------------------------------------------------------------------- 74 | The pattern for a default generated single-precision NaN. 75 *----------------------------------------------------------------------------*/ 76 #define float32_default_nan 0xFFC00000 77 78 /*---------------------------------------------------------------------------- 79 | Returns 1 if the single-precision floating-point value `a' is a NaN; 80 | otherwise returns 0. 81 *----------------------------------------------------------------------------*/ 82 83 static flag float32_is_nan( float32 a ) 84 { 85 86 return ( 0xFF000000 < (bits32) ( a<<1 ) ); 87 88 } 89 90 /*---------------------------------------------------------------------------- 91 | Returns 1 if the single-precision floating-point value `a' is a signaling 92 | NaN; otherwise returns 0. 93 *----------------------------------------------------------------------------*/ 94 95 flag float32_is_signaling_nan( float32 a ) 96 { 97 98 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 99 100 } 101 102 /*---------------------------------------------------------------------------- 103 | Returns the result of converting the single-precision floating-point NaN 104 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 105 | exception is raised. 106 *----------------------------------------------------------------------------*/ 107 108 static commonNaNT float32ToCommonNaN( float32 a ) 109 { 110 commonNaNT z; 111 112 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 113 z.sign = a>>31; 114 z.low = 0; 115 z.high = ( (bits64) a )<<41; 116 return z; 117 118 } 119 120 /*---------------------------------------------------------------------------- 121 | Returns the result of converting the canonical NaN `a' to the single- 122 | precision floating-point format. 123 *----------------------------------------------------------------------------*/ 124 125 static float32 commonNaNToFloat32( commonNaNT a ) 126 { 127 128 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 129 130 } 131 132 /*---------------------------------------------------------------------------- 133 | Takes two single-precision floating-point values `a' and `b', one of which 134 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 135 | signaling NaN, the invalid exception is raised. 136 *----------------------------------------------------------------------------*/ 137 138 static float32 propagateFloat32NaN( float32 a, float32 b ) 139 { 140 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 141 142 aIsNaN = float32_is_nan( a ); 143 aIsSignalingNaN = float32_is_signaling_nan( a ); 144 bIsNaN = float32_is_nan( b ); 145 bIsSignalingNaN = float32_is_signaling_nan( b ); 146 a |= 0x00400000; 147 b |= 0x00400000; 148 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 149 if ( aIsSignalingNaN ) { 150 if ( bIsSignalingNaN ) goto returnLargerSignificand; 151 return bIsNaN ? b : a; 152 } 153 else if ( aIsNaN ) { 154 if ( bIsSignalingNaN | ! bIsNaN ) return a; 155 returnLargerSignificand: 156 if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b; 157 if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a; 158 return ( a < b ) ? a : b; 159 } 160 else { 161 return b; 162 } 163 164 } 165 166 /* 167 * float64_default_nan, float64_is_nan(), float64_is_signaling_nan() 168 * have moved to softfloat.h. 169 */ 170 171 /*---------------------------------------------------------------------------- 172 | Returns the result of converting the double-precision floating-point NaN 173 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 174 | exception is raised. 175 *----------------------------------------------------------------------------*/ 176 177 static commonNaNT float64ToCommonNaN( float64 a ) 178 { 179 commonNaNT z; 180 181 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 182 z.sign = a>>63; 183 z.low = 0; 184 z.high = a<<12; 185 return z; 186 187 } 188 189 /*---------------------------------------------------------------------------- 190 | Returns the result of converting the canonical NaN `a' to the double- 191 | precision floating-point format. 192 *----------------------------------------------------------------------------*/ 193 194 static float64 commonNaNToFloat64( commonNaNT a ) 195 { 196 197 return 198 ( ( (bits64) a.sign )<<63 ) 199 | LIT64( 0x7FF8000000000000 ) 200 | ( a.high>>12 ); 201 202 } 203 204 /*---------------------------------------------------------------------------- 205 | Takes two double-precision floating-point values `a' and `b', one of which 206 | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 207 | signaling NaN, the invalid exception is raised. 208 *----------------------------------------------------------------------------*/ 209 210 static float64 propagateFloat64NaN( float64 a, float64 b ) 211 { 212 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 213 214 aIsNaN = float64_is_nan( a ); 215 aIsSignalingNaN = float64_is_signaling_nan( a ); 216 bIsNaN = float64_is_nan( b ); 217 bIsSignalingNaN = float64_is_signaling_nan( b ); 218 a |= LIT64( 0x0008000000000000 ); 219 b |= LIT64( 0x0008000000000000 ); 220 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 221 if ( aIsSignalingNaN ) { 222 if ( bIsSignalingNaN ) goto returnLargerSignificand; 223 return bIsNaN ? b : a; 224 } 225 else if ( aIsNaN ) { 226 if ( bIsSignalingNaN | ! bIsNaN ) return a; 227 returnLargerSignificand: 228 if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b; 229 if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a; 230 return ( a < b ) ? a : b; 231 } 232 else { 233 return b; 234 } 235 236 } 237 238 #ifdef FLOATX80 239 240 /*---------------------------------------------------------------------------- 241 | The pattern for a default generated double-extended-precision NaN. 242 | The `high' and `low' values hold the most- and least-significant bits, 243 | respectively. 244 *----------------------------------------------------------------------------*/ 245 #define floatx80_default_nan_high 0xFFFF 246 #define floatx80_default_nan_low LIT64( 0xC000000000000000 ) 247 248 /*---------------------------------------------------------------------------- 249 | Returns 1 if the double-extended-precision floating-point value `a' is a 250 | NaN; otherwise returns 0. 251 *----------------------------------------------------------------------------*/ 252 253 static flag floatx80_is_nan( floatx80 a ) 254 { 255 256 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 257 258 } 259 260 /*---------------------------------------------------------------------------- 261 | Returns 1 if the double-extended-precision floating-point value `a' is a 262 | signaling NaN; otherwise returns 0. 263 *----------------------------------------------------------------------------*/ 264 265 flag floatx80_is_signaling_nan( floatx80 a ) 266 { 267 bits64 aLow; 268 269 aLow = a.low & ~ LIT64( 0x4000000000000000 ); 270 return 271 ( ( a.high & 0x7FFF ) == 0x7FFF ) 272 && (bits64) ( aLow<<1 ) 273 && ( a.low == aLow ); 274 275 } 276 277 /*---------------------------------------------------------------------------- 278 | Returns the result of converting the double-extended-precision floating- 279 | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 280 | invalid exception is raised. 281 *----------------------------------------------------------------------------*/ 282 283 static commonNaNT floatx80ToCommonNaN( floatx80 a ) 284 { 285 commonNaNT z; 286 287 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 288 z.sign = a.high>>15; 289 z.low = 0; 290 z.high = a.low<<1; 291 return z; 292 293 } 294 295 /*---------------------------------------------------------------------------- 296 | Returns the result of converting the canonical NaN `a' to the double- 297 | extended-precision floating-point format. 298 *----------------------------------------------------------------------------*/ 299 300 static floatx80 commonNaNToFloatx80( commonNaNT a ) 301 { 302 floatx80 z; 303 304 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 305 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 306 return z; 307 308 } 309 310 /*---------------------------------------------------------------------------- 311 | Takes two double-extended-precision floating-point values `a' and `b', one 312 | of which is a NaN, and returns the appropriate NaN result. If either `a' or 313 | `b' is a signaling NaN, the invalid exception is raised. 314 *----------------------------------------------------------------------------*/ 315 316 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 317 { 318 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 319 320 aIsNaN = floatx80_is_nan( a ); 321 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 322 bIsNaN = floatx80_is_nan( b ); 323 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 324 a.low |= LIT64( 0xC000000000000000 ); 325 b.low |= LIT64( 0xC000000000000000 ); 326 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 327 if ( aIsSignalingNaN ) { 328 if ( bIsSignalingNaN ) goto returnLargerSignificand; 329 return bIsNaN ? b : a; 330 } 331 else if ( aIsNaN ) { 332 if ( bIsSignalingNaN | ! bIsNaN ) return a; 333 returnLargerSignificand: 334 if ( a.low < b.low ) return b; 335 if ( b.low < a.low ) return a; 336 return ( a.high < b.high ) ? a : b; 337 } 338 else { 339 return b; 340 } 341 342 } 343 344 #endif 345 346 #ifdef FLOAT128 347 348 /*---------------------------------------------------------------------------- 349 | The pattern for a default generated quadruple-precision NaN. The `high' and 350 | `low' values hold the most- and least-significant bits, respectively. 351 *----------------------------------------------------------------------------*/ 352 #define float128_default_nan_high LIT64( 0xFFFF800000000000 ) 353 #define float128_default_nan_low LIT64( 0x0000000000000000 ) 354 355 /*---------------------------------------------------------------------------- 356 | Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 357 | otherwise returns 0. 358 *----------------------------------------------------------------------------*/ 359 360 flag float128_is_nan( float128 a ) 361 { 362 363 return 364 ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 365 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 366 367 } 368 369 /*---------------------------------------------------------------------------- 370 | Returns 1 if the quadruple-precision floating-point value `a' is a 371 | signaling NaN; otherwise returns 0. 372 *----------------------------------------------------------------------------*/ 373 374 flag float128_is_signaling_nan( float128 a ) 375 { 376 377 return 378 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 379 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 380 381 } 382 383 /*---------------------------------------------------------------------------- 384 | Returns the result of converting the quadruple-precision floating-point NaN 385 | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 386 | exception is raised. 387 *----------------------------------------------------------------------------*/ 388 389 static commonNaNT float128ToCommonNaN( float128 a ) 390 { 391 commonNaNT z; 392 393 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 394 z.sign = a.high>>63; 395 shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 396 return z; 397 398 } 399 400 /*---------------------------------------------------------------------------- 401 | Returns the result of converting the canonical NaN `a' to the quadruple- 402 | precision floating-point format. 403 *----------------------------------------------------------------------------*/ 404 405 static float128 commonNaNToFloat128( commonNaNT a ) 406 { 407 float128 z; 408 409 shift128Right( a.high, a.low, 16, &z.high, &z.low ); 410 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 411 return z; 412 413 } 414 415 /*---------------------------------------------------------------------------- 416 | Takes two quadruple-precision floating-point values `a' and `b', one of 417 | which is a NaN, and returns the appropriate NaN result. If either `a' or 418 | `b' is a signaling NaN, the invalid exception is raised. 419 *----------------------------------------------------------------------------*/ 420 421 static float128 propagateFloat128NaN( float128 a, float128 b ) 422 { 423 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 424 425 aIsNaN = float128_is_nan( a ); 426 aIsSignalingNaN = float128_is_signaling_nan( a ); 427 bIsNaN = float128_is_nan( b ); 428 bIsSignalingNaN = float128_is_signaling_nan( b ); 429 a.high |= LIT64( 0x0000800000000000 ); 430 b.high |= LIT64( 0x0000800000000000 ); 431 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 432 if ( aIsSignalingNaN ) { 433 if ( bIsSignalingNaN ) goto returnLargerSignificand; 434 return bIsNaN ? b : a; 435 } 436 else if ( aIsNaN ) { 437 if ( bIsSignalingNaN | ! bIsNaN ) return a; 438 returnLargerSignificand: 439 if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b; 440 if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a; 441 return ( a.high < b.high ) ? a : b; 442 } 443 else { 444 return b; 445 } 446 447 } 448 449 #endif 450 451