|
|
1.1 ! root 1: /* ! 2: * QEMU float support ! 3: * ! 4: * The code in this source file is derived from release 2a of the SoftFloat ! 5: * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and ! 6: * some later contributions) are provided under that license, as detailed below. ! 7: * It has subsequently been modified by contributors to the QEMU Project, ! 8: * so some portions are provided under: ! 9: * the SoftFloat-2a license ! 10: * the BSD license ! 11: * GPL-v2-or-later ! 12: * ! 13: * Any future contributions to this file after December 1st 2014 will be ! 14: * taken to be licensed under the Softfloat-2a license unless specifically ! 15: * indicated otherwise. ! 16: */ ! 17: ! 18: /* ! 19: =============================================================================== ! 20: This C source fragment is part of the SoftFloat IEC/IEEE Floating-point ! 21: Arithmetic Package, Release 2a. ! 22: ! 23: Written by John R. Hauser. This work was made possible in part by the ! 24: International Computer Science Institute, located at Suite 600, 1947 Center ! 25: Street, Berkeley, California 94704. Funding was partially provided by the ! 26: National Science Foundation under grant MIP-9311980. The original version ! 27: of this code was written as part of a project to build a fixed-point vector ! 28: processor in collaboration with the University of California at Berkeley, ! 29: overseen by Profs. Nelson Morgan and John Wawrzynek. More information ! 30: is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ ! 31: arithmetic/SoftFloat.html'. ! 32: ! 33: THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort ! 34: has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT ! 35: TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO ! 36: PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY ! 37: AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. ! 38: ! 39: Derivative works are acceptable, even for commercial purposes, so long as ! 40: (1) they include prominent notice that the work is derivative, and (2) they ! 41: include prominent notice akin to these four paragraphs for those parts of ! 42: this code that are retained. ! 43: ! 44: =============================================================================== ! 45: */ ! 46: ! 47: /* BSD licensing: ! 48: * Copyright (c) 2006, Fabrice Bellard ! 49: * All rights reserved. ! 50: * ! 51: * Redistribution and use in source and binary forms, with or without ! 52: * modification, are permitted provided that the following conditions are met: ! 53: * ! 54: * 1. Redistributions of source code must retain the above copyright notice, ! 55: * this list of conditions and the following disclaimer. ! 56: * ! 57: * 2. Redistributions in binary form must reproduce the above copyright notice, ! 58: * this list of conditions and the following disclaimer in the documentation ! 59: * and/or other materials provided with the distribution. ! 60: * ! 61: * 3. Neither the name of the copyright holder nor the names of its contributors ! 62: * may be used to endorse or promote products derived from this software without ! 63: * specific prior written permission. ! 64: * ! 65: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ! 66: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 67: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 68: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE ! 69: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ! 70: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ! 71: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ! 72: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ! 73: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ! 74: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF ! 75: * THE POSSIBILITY OF SUCH DAMAGE. ! 76: */ ! 77: ! 78: /* Portions of this work are licensed under the terms of the GNU GPL, ! 79: * version 2 or later. See the COPYING file in the top-level directory. ! 80: */ ! 81: ! 82: /*---------------------------------------------------------------------------- ! 83: | Returns 1 if the extended double-precision floating-point value `a' is a ! 84: | NaN; otherwise returns 0. ! 85: *----------------------------------------------------------------------------*/ ! 86: ! 87: static inline flag floatx80_is_nan( floatx80 a ) ! 88: { ! 89: ! 90: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( a.low<<1 ); ! 91: ! 92: } ! 93: ! 94: /*---------------------------------------------------------------------------- ! 95: | The pattern for a default generated extended double-precision NaN. ! 96: *----------------------------------------------------------------------------*/ ! 97: static inline floatx80 floatx80_default_nan(float_status *status) ! 98: { ! 99: floatx80 r; ! 100: r.high = 0x7FFF; ! 101: r.low = LIT64( 0xFFFFFFFFFFFFFFFF ); ! 102: return r; ! 103: } ! 104: ! 105: /*---------------------------------------------------------------------------- ! 106: | Raises the exceptions specified by `flags'. Floating-point traps can be ! 107: | defined here if desired. It is currently not possible for such a trap ! 108: | to substitute a result value. If traps are not implemented, this routine ! 109: | should be simply `float_exception_flags |= flags;'. ! 110: *----------------------------------------------------------------------------*/ ! 111: ! 112: static inline void float_raise(uint8_t flags, float_status *status) ! 113: { ! 114: status->float_exception_flags |= flags; ! 115: } ! 116: ! 117: /*---------------------------------------------------------------------------- ! 118: | Internal canonical NaN format. ! 119: *----------------------------------------------------------------------------*/ ! 120: typedef struct { ! 121: flag sign; ! 122: uint64_t high, low; ! 123: } commonNaNT; ! 124: ! 125: /*---------------------------------------------------------------------------- ! 126: | Returns 1 if the single-precision floating-point value `a' is a NaN; ! 127: | otherwise returns 0. ! 128: *----------------------------------------------------------------------------*/ ! 129: ! 130: static inline flag float32_is_nan( float32 a ) ! 131: { ! 132: ! 133: return ( 0xFF000000 < (uint32_t) ( a<<1 ) ); ! 134: ! 135: } ! 136: ! 137: /*---------------------------------------------------------------------------- ! 138: | Returns 1 if the single-precision floating-point value `a' is a signaling ! 139: | NaN; otherwise returns 0. ! 140: *----------------------------------------------------------------------------*/ ! 141: ! 142: static inline flag float32_is_signaling_nan( float32 a ) ! 143: { ! 144: ! 145: return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); ! 146: ! 147: } ! 148: ! 149: /*---------------------------------------------------------------------------- ! 150: | Returns the result of converting the single-precision floating-point NaN ! 151: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 152: | exception is raised. ! 153: *----------------------------------------------------------------------------*/ ! 154: ! 155: static inline commonNaNT float32ToCommonNaN( float32 a, float_status *status ) ! 156: { ! 157: commonNaNT z; ! 158: ! 159: if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_signaling, status ); ! 160: z.sign = a>>31; ! 161: z.low = 0; ! 162: z.high = ( (uint64_t) a )<<41; ! 163: return z; ! 164: ! 165: } ! 166: ! 167: /*---------------------------------------------------------------------------- ! 168: | Returns the result of converting the canonical NaN `a' to the single- ! 169: | precision floating-point format. ! 170: *----------------------------------------------------------------------------*/ ! 171: ! 172: static inline float32 commonNaNToFloat32( commonNaNT a ) ! 173: { ! 174: ! 175: return ( ( (uint32_t) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); ! 176: ! 177: } ! 178: ! 179: /*---------------------------------------------------------------------------- ! 180: | Takes two single-precision floating-point values `a' and `b', one of which ! 181: | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a ! 182: | signaling NaN, the invalid exception is raised. ! 183: *----------------------------------------------------------------------------*/ ! 184: ! 185: static inline float32 propagateFloat32NaN( float32 a, float32 b, float_status *status ) ! 186: { ! 187: flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; ! 188: ! 189: aIsNaN = float32_is_nan( a ); ! 190: aIsSignalingNaN = float32_is_signaling_nan( a ); ! 191: bIsNaN = float32_is_nan( b ); ! 192: bIsSignalingNaN = float32_is_signaling_nan( b ); ! 193: a |= 0x00400000; ! 194: b |= 0x00400000; ! 195: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status ); ! 196: if ( aIsNaN ) { ! 197: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 198: } ! 199: else { ! 200: return b; ! 201: } ! 202: ! 203: } ! 204: ! 205: /*---------------------------------------------------------------------------- ! 206: | Returns 1 if the double-precision floating-point value `a' is a NaN; ! 207: | otherwise returns 0. ! 208: *----------------------------------------------------------------------------*/ ! 209: ! 210: static inline flag float64_is_nan( float64 a ) ! 211: { ! 212: ! 213: return ( LIT64( 0xFFE0000000000000 ) < (uint64_t) ( a<<1 ) ); ! 214: ! 215: } ! 216: ! 217: /*---------------------------------------------------------------------------- ! 218: | Returns 1 if the double-precision floating-point value `a' is a signaling ! 219: | NaN; otherwise returns 0. ! 220: *----------------------------------------------------------------------------*/ ! 221: ! 222: static inline flag float64_is_signaling_nan( float64 a ) ! 223: { ! 224: ! 225: return ! 226: ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) ! 227: && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); ! 228: ! 229: } ! 230: ! 231: /*---------------------------------------------------------------------------- ! 232: | Returns the result of converting the double-precision floating-point NaN ! 233: | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid ! 234: | exception is raised. ! 235: *----------------------------------------------------------------------------*/ ! 236: ! 237: static inline commonNaNT float64ToCommonNaN(float64 a, float_status *status) ! 238: { ! 239: commonNaNT z; ! 240: ! 241: if (float64_is_signaling_nan(a)) { ! 242: float_raise(float_flag_invalid, status); ! 243: } ! 244: z.sign = float64_val(a) >> 63; ! 245: z.low = 0; ! 246: z.high = float64_val(a) << 12; ! 247: return z; ! 248: } ! 249: ! 250: /*---------------------------------------------------------------------------- ! 251: | Returns the result of converting the canonical NaN `a' to the double- ! 252: | precision floating-point format. ! 253: *----------------------------------------------------------------------------*/ ! 254: ! 255: static inline float64 commonNaNToFloat64(commonNaNT a, float_status *status) ! 256: { ! 257: return ! 258: ( ( (uint64_t) a.sign )<<63 ) ! 259: | LIT64( 0x7FF8000000000000 ) ! 260: | ( a.high>>12 ); ! 261: } ! 262: ! 263: /*---------------------------------------------------------------------------- ! 264: | Returns 1 if the extended double-precision floating-point value `a' is a ! 265: | signaling NaN; otherwise returns 0. ! 266: *----------------------------------------------------------------------------*/ ! 267: ! 268: static inline flag floatx80_is_signaling_nan( floatx80 a ) ! 269: { ! 270: uint64_t aLow; ! 271: ! 272: aLow = a.low & ~ LIT64( 0x4000000000000000 ); ! 273: return ! 274: ( ( a.high & 0x7FFF ) == 0x7FFF ) ! 275: && (uint64_t) ( aLow<<1 ) ! 276: && ( a.low == aLow ); ! 277: ! 278: } ! 279: ! 280: /*---------------------------------------------------------------------------- ! 281: | Returns the result of converting the extended double-precision floating- ! 282: | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the ! 283: | invalid exception is raised. ! 284: *----------------------------------------------------------------------------*/ ! 285: ! 286: static inline commonNaNT floatx80ToCommonNaN( floatx80 a, float_status *status ) ! 287: { ! 288: commonNaNT z; ! 289: ! 290: if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_signaling, status ); ! 291: z.sign = a.high>>15; ! 292: z.low = 0; ! 293: z.high = a.low<<1; ! 294: return z; ! 295: ! 296: } ! 297: ! 298: /*---------------------------------------------------------------------------- ! 299: | Returns the result of converting the canonical NaN `a' to the extended ! 300: | double-precision floating-point format. ! 301: *----------------------------------------------------------------------------*/ ! 302: ! 303: static inline floatx80 commonNaNToFloatx80(commonNaNT a, float_status *status) ! 304: { ! 305: floatx80 z; ! 306: #ifdef SOFTFLOAT_68K ! 307: z.low = LIT64( 0x4000000000000000 ) | ( a.high>>1 ); ! 308: #else ! 309: z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); ! 310: #endif ! 311: z.high = ( ( (int16_t) a.sign )<<15 ) | 0x7FFF; ! 312: return z; ! 313: } ! 314: ! 315: /*---------------------------------------------------------------------------- ! 316: | Takes two extended double-precision floating-point values `a' and `b', one ! 317: | of which is a NaN, and returns the appropriate NaN result. If either `a' or ! 318: | `b' is a signaling NaN, the invalid exception is raised. ! 319: *----------------------------------------------------------------------------*/ ! 320: ! 321: static inline floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b, float_status *status ) ! 322: { ! 323: flag aIsNaN, aIsSignalingNaN, bIsSignalingNaN; ! 324: #ifndef SOFTFLOAT_68K ! 325: flag bIsNaN; ! 326: #endif ! 327: ! 328: aIsNaN = floatx80_is_nan( a ); ! 329: aIsSignalingNaN = floatx80_is_signaling_nan( a ); ! 330: bIsSignalingNaN = floatx80_is_signaling_nan( b ); ! 331: #ifdef SOFTFLOAT_68K ! 332: a.low |= LIT64( 0x4000000000000000 ); ! 333: b.low |= LIT64( 0x4000000000000000 ); ! 334: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status ); ! 335: return aIsNaN ? a : b; ! 336: #else ! 337: bIsNaN = floatx80_is_nan( b ); ! 338: a.low |= LIT64( 0xC000000000000000 ); ! 339: b.low |= LIT64( 0xC000000000000000 ); ! 340: if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_signaling, status ); ! 341: if ( aIsNaN ) { ! 342: return ( aIsSignalingNaN & bIsNaN ) ? b : a; ! 343: } ! 344: else { ! 345: return b; ! 346: } ! 347: #endif ! 348: ! 349: } ! 350: ! 351: #ifdef SOFTFLOAT_68K ! 352: /*---------------------------------------------------------------------------- ! 353: | Takes extended double-precision floating-point NaN `a' and returns the ! 354: | appropriate NaN result. If `a' is a signaling NaN, the invalid exception ! 355: | is raised. ! 356: *----------------------------------------------------------------------------*/ ! 357: ! 358: static inline floatx80 propagateFloatx80NaNOneArg(floatx80 a, float_status *status) ! 359: { ! 360: if ( floatx80_is_signaling_nan( a ) ) ! 361: float_raise( float_flag_signaling, status ); ! 362: a.low |= LIT64( 0x4000000000000000 ); ! 363: ! 364: return a; ! 365: } ! 366: #endif ! 367: ! 368: // 28-12-2016: Added for Previous: ! 369: ! 370: /*---------------------------------------------------------------------------- ! 371: | Returns 1 if the extended double-precision floating-point value `a' is ! 372: | zero; otherwise returns 0. ! 373: *----------------------------------------------------------------------------*/ ! 374: ! 375: static inline flag floatx80_is_zero( floatx80 a ) ! 376: { ! 377: ! 378: return ( ( a.high & 0x7FFF ) < 0x7FFF ) && ( a.low == 0 ); ! 379: ! 380: } ! 381: ! 382: /*---------------------------------------------------------------------------- ! 383: | Returns 1 if the extended double-precision floating-point value `a' is ! 384: | infinity; otherwise returns 0. ! 385: *----------------------------------------------------------------------------*/ ! 386: ! 387: static inline flag floatx80_is_infinity( floatx80 a ) ! 388: { ! 389: ! 390: return ( ( a.high & 0x7FFF ) == 0x7FFF ) && ( (uint64_t) ( a.low<<1 ) == 0 ); ! 391: ! 392: } ! 393: ! 394: /*---------------------------------------------------------------------------- ! 395: | Returns 1 if the extended double-precision floating-point value `a' is ! 396: | negative; otherwise returns 0. ! 397: *----------------------------------------------------------------------------*/ ! 398: ! 399: static inline flag floatx80_is_negative( floatx80 a ) ! 400: { ! 401: ! 402: return ( ( a.high & 0x8000 ) == 0x8000 ); ! 403: ! 404: } ! 405: ! 406: /*---------------------------------------------------------------------------- ! 407: | Returns 1 if the extended double-precision floating-point value `a' is ! 408: | unnormal; otherwise returns 0. ! 409: *----------------------------------------------------------------------------*/ ! 410: static inline flag floatx80_is_unnormal( floatx80 a ) ! 411: { ! 412: return ! 413: ( ( a.high & 0x7FFF ) > 0 ) ! 414: && ( ( a.high & 0x7FFF ) < 0x7FFF) ! 415: && ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) ); ! 416: } ! 417: ! 418: /*---------------------------------------------------------------------------- ! 419: | Returns 1 if the extended double-precision floating-point value `a' is ! 420: | denormal; otherwise returns 0. ! 421: *----------------------------------------------------------------------------*/ ! 422: ! 423: static inline flag floatx80_is_denormal( floatx80 a ) ! 424: { ! 425: return ! 426: ( ( a.high & 0x7FFF ) == 0 ) ! 427: && ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x0000000000000000 ) ) ! 428: && (uint64_t) ( a.low<<1 ); ! 429: } ! 430: ! 431: /*---------------------------------------------------------------------------- ! 432: | Returns 1 if the extended double-precision floating-point value `a' is ! 433: | normal; otherwise returns 0. ! 434: *----------------------------------------------------------------------------*/ ! 435: ! 436: static inline flag floatx80_is_normal( floatx80 a ) ! 437: { ! 438: return ! 439: ( ( a.high & 0x7FFF ) < 0x7FFF ) ! 440: && ( (uint64_t) ( a.low & LIT64( 0x8000000000000000 ) ) == LIT64( 0x8000000000000000 ) ); ! 441: } ! 442: // End of addition for Previous ! 443:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.