1714 lines · 57.0 KB · C
RawDownload
/*============================================================================ This C source file is part of the SoftFloat IEEE Floating-Point ArithmeticPackage, Release 3e, by John R. Hauser. Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University ofCalifornia.  All rights reserved. Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:  1. Redistributions of source code must retain the above copyright notice,    this list of conditions, and the following disclaimer.  2. Redistributions in binary form must reproduce the above copyright notice,    this list of conditions, and the following disclaimer in the documentation    and/or other materials provided with the distribution.  3. Neither the name of the University nor the names of its contributors may    be used to endorse or promote products derived from this software without    specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANYEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AREDISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ANDON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. =============================================================================*/ #include "quakedef.h"#include "softfloat.h" #ifdef QUAKE_LITTLE_ENDIANstruct uint128 { u64int v0, v64; };struct uint64_extra { u64int extra, v; };#define wordIncr 1#define indexWord( total, n ) (n)#define indexWordHi( total ) ((total) - 1)#define indexWordLo( total ) 0#define indexMultiword( total, m, n ) (n)#define indexMultiwordHi( total, n ) ((total) - (n))#define indexMultiwordLo( total, n ) 0#define indexMultiwordHiBut( total, n ) (n)#define indexMultiwordLoBut( total, n ) 0#elsestruct uint128 { u64int v64, v0; };struct uint64_extra { u64int v, extra; };#define wordIncr -1#define indexWord( total, n ) ((total) - 1 - (n))#define indexWordHi( total ) 0#define indexWordLo( total ) ((total) - 1)#define indexMultiword( total, m, n ) ((total) - 1 - (m))#define indexMultiwordHi( total, n ) 0#define indexMultiwordLo( total, n ) ((total) - (n))#define indexMultiwordHiBut( total, n ) 0#define indexMultiwordLoBut( total, n ) (n)#endif /*----------------------------------------------------------------------------| Default value for 'softfloat_detectTininess'.*----------------------------------------------------------------------------*/#define init_detectTininess softfloat_tininess_afterRounding /*----------------------------------------------------------------------------| "Common NaN" structure, used to transfer NaN representations from one format| to another.*----------------------------------------------------------------------------*/struct commonNaN {    bool sign;#ifdef QUAKE_LITTLE_ENDIAN    u64int v0, v64;#else    u64int v64, v0;#endif}; union ui32_f32 { u32int ui; float32_t f; }; enum {    softfloat_mulAdd_subC    = 1,    softfloat_mulAdd_subProd = 2};  /*----------------------------------------------------------------------------| Software floating-point underflow tininess-detection mode.*----------------------------------------------------------------------------*/enum {    softfloat_tininess_beforeRounding = 0,    softfloat_tininess_afterRounding  = 1}; /*----------------------------------------------------------------------------| Software floating-point rounding mode.  (Mode "odd" is supported only if| SoftFloat is compiled with macro 'SOFTFLOAT_ROUND_ODD' defined.)*----------------------------------------------------------------------------*/enum {    softfloat_round_near_even   = 0,    softfloat_round_minMag      = 1,    softfloat_round_min         = 2,    softfloat_round_max         = 3,    softfloat_round_near_maxMag = 4,    softfloat_round_odd         = 6}; /*----------------------------------------------------------------------------| Software floating-point exception flags.*----------------------------------------------------------------------------*/typedef enum {    softfloat_flag_inexact   =  1,    softfloat_flag_underflow =  2,    softfloat_flag_overflow  =  4,    softfloat_flag_infinite  =  8,    softfloat_flag_invalid   = 16} exceptionFlag_t; /*----------------------------------------------------------------------------| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a| 32-bit floating-point signaling NaN.| Note:  This macro evaluates its argument more than once.*----------------------------------------------------------------------------*/#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) /*----------------------------------------------------------------------------| The bit pattern for a default generated 80-bit extended floating-point NaN.*----------------------------------------------------------------------------*/#define defaultNaNExtF80UI64 0xFFFF#define defaultNaNExtF80UI0  0xC000000000000000ULL /*----------------------------------------------------------------------------| Returns true when the 80-bit unsigned integer formed from concatenating| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended| floating-point signaling NaN.| Note:  This macro evaluates its arguments more than once.*----------------------------------------------------------------------------*/#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & 0x4000000000000000ULL ) && ((uiA0) & 0x3FFFFFFFFFFFFFFFULL )) #define signF32UI( a ) ((bool) ((u32int) (a)>>31))#define expF32UI( a ) ((s16int) ((a)>>23) & 0xFF)#define fracF32UI( a ) ((a) & 0x007FFFFF)#define packToF32UI( sign, exp, sig ) (((u32int) (sign)<<31) + ((u32int) (exp)<<23) + (sig)) #define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) struct exp16_sig32 { s16int exp; u32int sig; }; static struct exp16_sig32 softfloat_normSubnormalF32Sig( u32int );static float32_t softfloat_roundPackToF32( bool, s16int, u32int ); #define signExtF80UI64( a64 ) ((bool) ((u16int) (a64)>>15))#define expExtF80UI64( a64 ) ((a64) & 0x7FFF)#define packToExtF80UI64( sign, exp ) ((u16int) (sign)<<15 | (exp)) #define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & 0x7FFFFFFFFFFFFFFFULL )) struct exp32_sig64 { s32int exp; u64int sig; }; #define signF128UI64( a64 ) ((bool) ((u64int) (a64)>>63))#define expF128UI64( a64 ) ((s32int) ((a64)>>48) & 0x7FFF)#define fracF128UI64( a64 ) ((a64) & 0x0000FFFFFFFFFFFFULL )#define packToF128UI64( sign, exp, sig64 ) (((u64int) (sign)<<63) + ((u64int) (exp)<<48) + (sig64)) #define isNaNF128UI( a64, a0 ) (((~(a64) & 0x7FFF000000000000ULL ) == 0) && (a0 || ((a64) & 0x0000FFFFFFFFFFFFULL ))) struct exp32_sig128 { s32int exp; struct uint128 sig; }; /*----------------------------------------------------------------------------| Routine to raise any or all of the software floating-point exception flags.*----------------------------------------------------------------------------*/static void softfloat_raiseFlags( u8int ); u8int softfloat_roundingMode = softfloat_round_near_even;u8int softfloat_detectTininess = init_detectTininess;u8int softfloat_exceptionFlags = 0;u8int extF80_roundingPrecision = 80; static boolextF80M_isSignalingNaN( const extFloat80_t *aPtr ){    const struct extFloat80M *aSPtr;    u64int uiA0;     aSPtr = (const struct extFloat80M *) aPtr;    if ( (aSPtr->signExp & 0x7FFF) != 0x7FFF ) return false;    uiA0 = aSPtr->signif;    return        ! (uiA0 & 0x4000000000000000ULL )            && (uiA0 & 0x3FFFFFFFFFFFFFFFULL ); } /*----------------------------------------------------------------------------| Converts the common NaN pointed to by `aPtr' into an 80-bit extended| floating-point NaN, and stores this NaN at the location pointed to by| `zSPtr'.*----------------------------------------------------------------------------*/static voidsoftfloat_commonNaNToExtF80M(const struct commonNaN *aPtr, struct extFloat80M *zSPtr ){     zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );    zSPtr->signif = 0xC000000000000000ULL | aPtr->v64>>1; } /*----------------------------------------------------------------------------| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point| NaN, and returns the bit pattern of this value as an unsigned integer.*----------------------------------------------------------------------------*/static u32intsoftfloat_commonNaNToF32UI( const struct commonNaN *aPtr ){     return (u32int) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; } /*----------------------------------------------------------------------------| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is| a NaN, converts this NaN to the common NaN form, and stores the resulting| common NaN at the location pointed to by `zPtr'.  If the NaN is a signaling| NaN, the invalid exception is raised.*----------------------------------------------------------------------------*/static voidsoftfloat_extF80MToCommonNaN(const struct extFloat80M *aSPtr, struct commonNaN *zPtr ){     if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {        softfloat_raiseFlags( softfloat_flag_invalid );    }    zPtr->sign = signExtF80UI64( aSPtr->signExp );    zPtr->v64 = aSPtr->signif<<1;    zPtr->v0  = 0; } /*----------------------------------------------------------------------------| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts| this NaN to the common NaN form, and stores the resulting common NaN at the| location pointed to by `zPtr'.  If the NaN is a signaling NaN, the invalid| exception is raised.*----------------------------------------------------------------------------*/static voidsoftfloat_f32UIToCommonNaN( u32int uiA, struct commonNaN *zPtr ){     if ( softfloat_isSigNaNF32UI( uiA ) ) {        softfloat_raiseFlags( softfloat_flag_invalid );    }    zPtr->sign = uiA>>31;    zPtr->v64  = (u64int) uiA<<41;    zPtr->v0   = 0; } /*----------------------------------------------------------------------------| Assuming at least one of the two 80-bit extended floating-point values| pointed to by `aSPtr' and `bSPtr' is a NaN, stores the combined NaN result| at the location pointed to by `zSPtr'.  If either original floating-point| value is a signaling NaN, the invalid exception is raised.*----------------------------------------------------------------------------*/static voidsoftfloat_propagateNaNExtF80M(     const struct extFloat80M *aSPtr,     const struct extFloat80M *bSPtr,     struct extFloat80M *zSPtr ){    bool isSigNaNA;    const struct extFloat80M *sPtr;    bool isSigNaNB;    u16int uiB64;    u64int uiB0;    u16int uiA64;    u64int uiA0;    u16int uiMagA64, uiMagB64;     isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );    sPtr = aSPtr;    if ( ! bSPtr ) {        if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );        goto copy;    }    isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr );    if ( isSigNaNA | isSigNaNB ) {        softfloat_raiseFlags( softfloat_flag_invalid );        if ( isSigNaNA ) {            uiB64 = bSPtr->signExp;            if ( isSigNaNB ) goto returnLargerUIMag;            uiB0 = bSPtr->signif;            if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB;            goto copy;        } else {            uiA64 = aSPtr->signExp;            uiA0 = aSPtr->signif;            if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy;            goto copyB;        }    }    uiB64 = bSPtr->signExp; returnLargerUIMag:    uiA64 = aSPtr->signExp;    uiMagA64 = uiA64 & 0x7FFF;    uiMagB64 = uiB64 & 0x7FFF;    if ( uiMagA64 < uiMagB64 ) goto copyB;    if ( uiMagB64 < uiMagA64 ) goto copy;    uiA0 = aSPtr->signif;    uiB0 = bSPtr->signif;    if ( uiA0 < uiB0 ) goto copyB;    if ( uiB0 < uiA0 ) goto copy;    if ( uiA64 < uiB64 ) goto copy; copyB:    sPtr = bSPtr; copy:    zSPtr->signExp = sPtr->signExp;    zSPtr->signif = sPtr->signif | 0xC000000000000000ULL; } /*----------------------------------------------------------------------------| Interpreting the unsigned integer formed from concatenating 'uiA64' and| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another| 80-bit extended floating-point value, and assuming at least on of these| floating-point values is a NaN, returns the bit pattern of the combined NaN| result.  If either original floating-point value is a signaling NaN, the| invalid exception is raised.*----------------------------------------------------------------------------*/static struct uint128 softfloat_propagateNaNExtF80UI(     u16int uiA64,     u64int uiA0,     u16int uiB64,     u64int uiB0 ){    bool isSigNaNA, isSigNaNB;    u64int uiNonsigA0, uiNonsigB0;    u16int uiMagA64, uiMagB64;    struct uint128 uiZ;     /*------------------------------------------------------------------------    *------------------------------------------------------------------------*/    isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );    isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 );    /*------------------------------------------------------------------------    | Make NaNs non-signaling.    *------------------------------------------------------------------------*/    uiNonsigA0 = uiA0 | 0xC000000000000000ULL;    uiNonsigB0 = uiB0 | 0xC000000000000000ULL;    /*------------------------------------------------------------------------    *------------------------------------------------------------------------*/    if ( isSigNaNA | isSigNaNB ) {        softfloat_raiseFlags( softfloat_flag_invalid );        if ( isSigNaNA ) {            if ( isSigNaNB ) goto returnLargerMag;            if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB;            goto returnA;        } else {            if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA;            goto returnB;        }    } returnLargerMag:    uiMagA64 = uiA64 & 0x7FFF;    uiMagB64 = uiB64 & 0x7FFF;    if ( uiMagA64 < uiMagB64 ) goto returnB;    if ( uiMagB64 < uiMagA64 ) goto returnA;    if ( uiA0 < uiB0 ) goto returnB;    if ( uiB0 < uiA0 ) goto returnA;    if ( uiA64 < uiB64 ) goto returnA; returnB:    uiZ.v64 = uiB64;    uiZ.v0  = uiNonsigB0;    return uiZ; returnA:    uiZ.v64 = uiA64;    uiZ.v0  = uiNonsigA0;    return uiZ; } /*----------------------------------------------------------------------------| Raises the exceptions specified by `flags'.  Floating-point traps can be| defined here if desired.  It is currently not possible for such a trap| to substitute a result value.  If traps are not implemented, this routine| should be simply `softfloat_exceptionFlags |= flags;'.*----------------------------------------------------------------------------*/static voidsoftfloat_raiseFlags( u8int flags ){    softfloat_exceptionFlags |= flags;} static u64intsoftfloat_shortShiftRightJam64( u64int a, u8int dist ){    return a>>dist | ((a & (((u64int) 1<<dist) - 1)) != 0);} /*----------------------------------------------------------------------------| A constant table that translates an 8-bit unsigned integer (the array index)| into the number of leading 0 bits before the most-significant 1 of that| integer.  For integer zero (index 0), the corresponding table element is 8.*----------------------------------------------------------------------------*/static const u8int softfloat_countLeadingZeros8[256] = {    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static u8intsoftfloat_countLeadingZeros64( u64int a ){    u8int count;    u32int a32;     count = 0;    a32 = a>>32;    if ( ! a32 ) {        count = 32;        a32 = a;    }    /*------------------------------------------------------------------------    | From here, result is current count + count leading zeros of `a32'.    *------------------------------------------------------------------------*/    if ( a32 < 0x10000 ) {        count += 16;        a32 <<= 16;    }    if ( a32 < 0x1000000 ) {        count += 8;        a32 <<= 8;    }    count += softfloat_countLeadingZeros8[a32>>24];    return count; } static intsoftfloat_normExtF80SigM( u64int *sigPtr ){    u64int sig;    s8int shiftDist;     sig = *sigPtr;    shiftDist = softfloat_countLeadingZeros64( sig );    *sigPtr = sig<<shiftDist;    return -shiftDist; } static u8intsoftfloat_countLeadingZeros32( u32int a ){    u8int count;     count = 0;    if ( a < 0x10000 ) {        count = 16;        a <<= 16;    }    if ( a < 0x1000000 ) {        count += 8;        a <<= 8;    }    count += softfloat_countLeadingZeros8[a>>24];    return count; } static struct exp16_sig32softfloat_normSubnormalF32Sig( u32int sig ){    s8int shiftDist;    struct exp16_sig32 z;     shiftDist = softfloat_countLeadingZeros32( sig ) - 8;    z.exp = 1 - shiftDist;    z.sig = sig<<shiftDist;    return z;

Lines 1–500 of 1714.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t