Annotation of hatari/src/cpu/softfloat/softfloat-specialize.h, revision 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.