Annotation of hatari/src/cpu/softfloat/softfloat-specialize.h, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.