softfloat.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,846 行 · 第 1/5 页

C
1,846
字号
float32 float32_sqrt( float32 a ){    flag aSign;    int16 aExp, zExp;    bits32 aSig, zSig, rem0, rem1, term0, term1;    aSig = extractFloat32Frac( a );    aExp = extractFloat32Exp( a );    aSign = extractFloat32Sign( a );    if ( aExp == 0xFF ) {        if ( aSig ) return propagateFloat32NaN( a, 0 );        if ( ! aSign ) return a;        float_raise( float_flag_invalid );        return float32_default_nan;    }    if ( aSign ) {        if ( ( aExp | aSig ) == 0 ) return a;        float_raise( float_flag_invalid );        return float32_default_nan;    }    if ( aExp == 0 ) {        if ( aSig == 0 ) return 0;        normalizeFloat32Subnormal( aSig, &aExp, &aSig );    }    zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;    aSig = ( aSig | 0x00800000 )<<8;    zSig = estimateSqrt32( aExp, aSig ) + 2;    if ( ( zSig & 0x7F ) <= 5 ) {        if ( zSig < 2 ) {            zSig = 0x7FFFFFFF;            goto roundAndPack;        }        else {            aSig >>= aExp & 1;            mul32To64( zSig, zSig, &term0, &term1 );            sub64( aSig, 0, term0, term1, &rem0, &rem1 );            while ( (sbits32) rem0 < 0 ) {                --zSig;                shortShift64Left( 0, zSig, 1, &term0, &term1 );                term1 |= 1;                add64( rem0, rem1, term0, term1, &rem0, &rem1 );            }            zSig |= ( ( rem0 | rem1 ) != 0 );        }    }    shift32RightJamming( zSig, 1, &zSig ); roundAndPack:    return roundAndPackFloat32( 0, zExp, zSig );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is equal to| the corresponding value `b', and 0 otherwise.  The comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*/flag float32_eq( float32 a, float32 b ){    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {            float_raise( float_flag_invalid );        }        return 0;    }    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is less than| or equal to the corresponding value `b', and 0 otherwise.  The comparison| is performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*/flag float32_le( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );    return ( a == b ) || ( aSign ^ ( a < b ) );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is less than| the corresponding value `b', and 0 otherwise.  The comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*/flag float32_lt( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );    return ( a != b ) && ( aSign ^ ( a < b ) );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is equal to| the corresponding value `b', and 0 otherwise.  The invalid exception is| raised if either operand is a NaN.  Otherwise, the comparison is performed| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*/flag float32_eq_signaling( float32 a, float32 b ){    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        float_raise( float_flag_invalid );        return 0;    }    return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is less than or| equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not| cause an exception.  Otherwise, the comparison is performed according to the| IEC/IEEE Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*/flag float32_le_quiet( float32 a, float32 b ){    flag aSign, bSign;    int16 aExp, bExp;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {            float_raise( float_flag_invalid );        }        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );    return ( a == b ) || ( aSign ^ ( a < b ) );}/*----------------------------------------------------------------------------| Returns 1 if the single-precision floating-point value `a' is less than| the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an| exception.  Otherwise, the comparison is performed according to the IEC/IEEE| Standard for Binary Floating-Point Arithmetic.*----------------------------------------------------------------------------*/flag float32_lt_quiet( float32 a, float32 b ){    flag aSign, bSign;    if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )         || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )       ) {        if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {            float_raise( float_flag_invalid );        }        return 0;    }    aSign = extractFloat32Sign( a );    bSign = extractFloat32Sign( b );    if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );    return ( a != b ) && ( aSign ^ ( a < b ) );}/*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the 32-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic---which means in particular that the conversion is rounded| according to the current rounding mode.  If `a' is a NaN, the largest| positive integer is returned.  Otherwise, if the conversion overflows, the| largest integer with the same sign as `a' is returned.*----------------------------------------------------------------------------*/int32 float64_to_int32( float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits32 aSig0, aSig1, absZ, aSigExtra;    int32 z;    int8 roundingMode;    aSig1 = extractFloat64Frac1( a );    aSig0 = extractFloat64Frac0( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    shiftCount = aExp - 0x413;    if ( 0 <= shiftCount ) {        if ( 0x41E < aExp ) {            if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;            goto invalid;        }        shortShift64Left(            aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );        if ( 0x80000000 < absZ ) goto invalid;    }    else {        aSig1 = ( aSig1 != 0 );        if ( aExp < 0x3FE ) {            aSigExtra = aExp | aSig0 | aSig1;            absZ = 0;        }        else {            aSig0 |= 0x00100000;            aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;            absZ = aSig0>>( - shiftCount );        }    }    roundingMode = float_rounding_mode;    if ( roundingMode == float_round_nearest_even ) {        if ( (sbits32) aSigExtra < 0 ) {            ++absZ;            if ( (bits32) ( aSigExtra<<1 ) == 0 ) absZ &= ~1;        }        z = aSign ? - absZ : absZ;    }    else {        aSigExtra = ( aSigExtra != 0 );        if ( aSign ) {            z = - (   absZ                    + ( ( roundingMode == float_round_down ) & aSigExtra ) );        }        else {            z = absZ + ( ( roundingMode == float_round_up ) & aSigExtra );        }    }    if ( ( aSign ^ ( z < 0 ) ) && z ) { invalid:        float_raise( float_flag_invalid );        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;    }    if ( aSigExtra ) float_exception_flags |= float_flag_inexact;    return z;}/*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the 32-bit two's complement integer format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic, except that the conversion is always rounded toward zero.| If `a' is a NaN, the largest positive integer is returned.  Otherwise, if| the conversion overflows, the largest integer with the same sign as `a' is| returned.*----------------------------------------------------------------------------*/int32 float64_to_int32_round_to_zero( float64 a ){    flag aSign;    int16 aExp, shiftCount;    bits32 aSig0, aSig1, absZ, aSigExtra;    int32 z;    aSig1 = extractFloat64Frac1( a );    aSig0 = extractFloat64Frac0( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    shiftCount = aExp - 0x413;    if ( 0 <= shiftCount ) {        if ( 0x41E < aExp ) {            if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;            goto invalid;        }        shortShift64Left(            aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );    }    else {        if ( aExp < 0x3FF ) {            if ( aExp | aSig0 | aSig1 ) {                float_exception_flags |= float_flag_inexact;            }            return 0;        }        aSig0 |= 0x00100000;        aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;        absZ = aSig0>>( - shiftCount );    }    z = aSign ? - absZ : absZ;    if ( ( aSign ^ ( z < 0 ) ) && z ) { invalid:        float_raise( float_flag_invalid );        return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;    }    if ( aSigExtra ) float_exception_flags |= float_flag_inexact;    return z;}/*----------------------------------------------------------------------------| Returns the result of converting the double-precision floating-point value| `a' to the single-precision floating-point format.  The conversion is| performed according to the IEC/IEEE Standard for Binary Floating-Point| Arithmetic.*----------------------------------------------------------------------------*/float32 float64_to_float32( float64 a ){    flag aSign;    int16 aExp;    bits32 aSig0, aSig1, zSig;    bits32 allZero;    aSig1 = extractFloat64Frac1( a );    aSig0 = extractFloat64Frac0( a );    aExp = extractFloat64Exp( a );    aSign = extractFloat64Sign( a );    if ( aExp == 0x7FF ) {        if ( aSig0 | aSig1 ) {            return commonNaNToFloat32( float64ToCommonNaN( a ) );        }        return packFloat32( aSign, 0xFF, 0 );    }    shift64RightJamming( aSig0, aSig1, 22, &allZero, &zSig );    if ( aExp ) zSig |= 0x40000000;    return roundAndPackFloat32( aSign, aExp - 0x381, zSig );}/*----------------------------------------------------------------------------| Rounds the double-precision floating-point value `a' to an integer,| and returns the result as a double-precision floating-point value.  The| operation is performed according to the IEC/IEEE Standard for Binary| Floating-Point Arithmetic.*----------------------------------------------------------------------------*/float64 float64_round_to_int( float64 a ){    flag aSign;    int16 aExp;    bits32 lastBitMask, roundBitsMask;    int8 roundingMode;    float64 z;    aExp = extractFloat64Exp( a );    if ( 0x413 <= aExp ) {        if ( 0x433 <= aExp ) {            if (    ( aExp == 0x7FF )                 && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) ) {                return propagateFloat64NaN( a, a );            }            return a;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?