cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

softfloat-specialize (12308B)


      1
      2/*
      3===============================================================================
      4
      5This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
      6Arithmetic Package, Release 2.
      7
      8Written by John R. Hauser.  This work was made possible in part by the
      9International Computer Science Institute, located at Suite 600, 1947 Center
     10Street, Berkeley, California 94704.  Funding was partially provided by the
     11National Science Foundation under grant MIP-9311980.  The original version
     12of this code was written as part of a project to build a fixed-point vector
     13processor in collaboration with the University of California at Berkeley,
     14overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
     15is available through the Web page
     16http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt
     17
     18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
     19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
     20TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
     21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
     22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
     23
     24Derivative works are acceptable, even for commercial purposes, so long as
     25(1) they include prominent notice that the work is derivative, and (2) they
     26include prominent notice akin to these three paragraphs for those parts of
     27this code that are retained.
     28
     29===============================================================================
     30*/
     31
     32/*
     33-------------------------------------------------------------------------------
     34Underflow tininess-detection mode, statically initialized to default value.
     35(The declaration in `softfloat.h' must match the `int8' type here.)
     36-------------------------------------------------------------------------------
     37*/
     38int8 float_detect_tininess = float_tininess_after_rounding;
     39
     40/*
     41-------------------------------------------------------------------------------
     42Raises the exceptions specified by `flags'.  Floating-point traps can be
     43defined here if desired.  It is currently not possible for such a trap to
     44substitute a result value.  If traps are not implemented, this routine
     45should be simply `float_exception_flags |= flags;'.
     46
     47ScottB:  November 4, 1998
     48Moved this function out of softfloat-specialize into fpmodule.c.
     49This effectively isolates all the changes required for integrating with the
     50Linux kernel into fpmodule.c.  Porting to NetBSD should only require modifying
     51fpmodule.c to integrate with the NetBSD kernel (I hope!).
     52-------------------------------------------------------------------------------
     53void float_raise( int8 flags )
     54{
     55    float_exception_flags |= flags;
     56}
     57*/
     58
     59/*
     60-------------------------------------------------------------------------------
     61Internal canonical NaN format.
     62-------------------------------------------------------------------------------
     63*/
     64typedef struct {
     65    flag sign;
     66    bits64 high, low;
     67} commonNaNT;
     68
     69/*
     70-------------------------------------------------------------------------------
     71The pattern for a default generated single-precision NaN.
     72-------------------------------------------------------------------------------
     73*/
     74#define float32_default_nan 0xFFFFFFFF
     75
     76/*
     77-------------------------------------------------------------------------------
     78Returns 1 if the single-precision floating-point value `a' is a NaN;
     79otherwise returns 0.
     80-------------------------------------------------------------------------------
     81*/
     82flag float32_is_nan( float32 a )
     83{
     84
     85    return ( 0xFF000000 < (bits32) ( a<<1 ) );
     86
     87}
     88
     89/*
     90-------------------------------------------------------------------------------
     91Returns 1 if the single-precision floating-point value `a' is a signaling
     92NaN; otherwise returns 0.
     93-------------------------------------------------------------------------------
     94*/
     95flag float32_is_signaling_nan( float32 a )
     96{
     97
     98    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
     99
    100}
    101
    102/*
    103-------------------------------------------------------------------------------
    104Returns the result of converting the single-precision floating-point NaN
    105`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    106exception is raised.
    107-------------------------------------------------------------------------------
    108*/
    109static commonNaNT float32ToCommonNaN( float32 a )
    110{
    111    commonNaNT z;
    112
    113    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    114    z.sign = a>>31;
    115    z.low = 0;
    116    z.high = ( (bits64) a )<<41;
    117    return z;
    118
    119}
    120
    121/*
    122-------------------------------------------------------------------------------
    123Returns the result of converting the canonical NaN `a' to the single-
    124precision floating-point format.
    125-------------------------------------------------------------------------------
    126*/
    127static float32 commonNaNToFloat32( commonNaNT a )
    128{
    129
    130    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    131
    132}
    133
    134/*
    135-------------------------------------------------------------------------------
    136Takes two single-precision floating-point values `a' and `b', one of which
    137is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    138signaling NaN, the invalid exception is raised.
    139-------------------------------------------------------------------------------
    140*/
    141static float32 propagateFloat32NaN( float32 a, float32 b )
    142{
    143    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    144
    145    aIsNaN = float32_is_nan( a );
    146    aIsSignalingNaN = float32_is_signaling_nan( a );
    147    bIsNaN = float32_is_nan( b );
    148    bIsSignalingNaN = float32_is_signaling_nan( b );
    149    a |= 0x00400000;
    150    b |= 0x00400000;
    151    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    152    if ( aIsNaN ) {
    153        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    154    }
    155    else {
    156        return b;
    157    }
    158
    159}
    160
    161/*
    162-------------------------------------------------------------------------------
    163The pattern for a default generated double-precision NaN.
    164-------------------------------------------------------------------------------
    165*/
    166#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
    167
    168/*
    169-------------------------------------------------------------------------------
    170Returns 1 if the double-precision floating-point value `a' is a NaN;
    171otherwise returns 0.
    172-------------------------------------------------------------------------------
    173*/
    174flag float64_is_nan( float64 a )
    175{
    176
    177    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
    178
    179}
    180
    181/*
    182-------------------------------------------------------------------------------
    183Returns 1 if the double-precision floating-point value `a' is a signaling
    184NaN; otherwise returns 0.
    185-------------------------------------------------------------------------------
    186*/
    187flag float64_is_signaling_nan( float64 a )
    188{
    189
    190    return
    191           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
    192        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
    193
    194}
    195
    196/*
    197-------------------------------------------------------------------------------
    198Returns the result of converting the double-precision floating-point NaN
    199`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    200exception is raised.
    201-------------------------------------------------------------------------------
    202*/
    203static commonNaNT float64ToCommonNaN( float64 a )
    204{
    205    commonNaNT z;
    206
    207    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    208    z.sign = a>>63;
    209    z.low = 0;
    210    z.high = a<<12;
    211    return z;
    212
    213}
    214
    215/*
    216-------------------------------------------------------------------------------
    217Returns the result of converting the canonical NaN `a' to the double-
    218precision floating-point format.
    219-------------------------------------------------------------------------------
    220*/
    221static float64 commonNaNToFloat64( commonNaNT a )
    222{
    223
    224    return
    225          ( ( (bits64) a.sign )<<63 )
    226        | LIT64( 0x7FF8000000000000 )
    227        | ( a.high>>12 );
    228
    229}
    230
    231/*
    232-------------------------------------------------------------------------------
    233Takes two double-precision floating-point values `a' and `b', one of which
    234is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    235signaling NaN, the invalid exception is raised.
    236-------------------------------------------------------------------------------
    237*/
    238static float64 propagateFloat64NaN( float64 a, float64 b )
    239{
    240    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    241
    242    aIsNaN = float64_is_nan( a );
    243    aIsSignalingNaN = float64_is_signaling_nan( a );
    244    bIsNaN = float64_is_nan( b );
    245    bIsSignalingNaN = float64_is_signaling_nan( b );
    246    a |= LIT64( 0x0008000000000000 );
    247    b |= LIT64( 0x0008000000000000 );
    248    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    249    if ( aIsNaN ) {
    250        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    251    }
    252    else {
    253        return b;
    254    }
    255
    256}
    257
    258#ifdef FLOATX80
    259
    260/*
    261-------------------------------------------------------------------------------
    262The pattern for a default generated extended double-precision NaN.  The
    263`high' and `low' values hold the most- and least-significant bits,
    264respectively.
    265-------------------------------------------------------------------------------
    266*/
    267#define floatx80_default_nan_high 0xFFFF
    268#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    269
    270/*
    271-------------------------------------------------------------------------------
    272Returns 1 if the extended double-precision floating-point value `a' is a
    273NaN; otherwise returns 0.
    274-------------------------------------------------------------------------------
    275*/
    276flag floatx80_is_nan( floatx80 a )
    277{
    278
    279    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    280
    281}
    282
    283/*
    284-------------------------------------------------------------------------------
    285Returns 1 if the extended double-precision floating-point value `a' is a
    286signaling NaN; otherwise returns 0.
    287-------------------------------------------------------------------------------
    288*/
    289flag floatx80_is_signaling_nan( floatx80 a )
    290{
    291    //register int lr;
    292    bits64 aLow;
    293
    294    //__asm__("mov %0, lr" : : "g" (lr));
    295    //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
    296    aLow = a.low & ~ LIT64( 0x4000000000000000 );
    297    return
    298           ( ( a.high & 0x7FFF ) == 0x7FFF )
    299        && (bits64) ( aLow<<1 )
    300        && ( a.low == aLow );
    301
    302}
    303
    304/*
    305-------------------------------------------------------------------------------
    306Returns the result of converting the extended double-precision floating-
    307point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    308invalid exception is raised.
    309-------------------------------------------------------------------------------
    310*/
    311static commonNaNT floatx80ToCommonNaN( floatx80 a )
    312{
    313    commonNaNT z;
    314
    315    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    316    z.sign = a.high>>15;
    317    z.low = 0;
    318    z.high = a.low<<1;
    319    return z;
    320
    321}
    322
    323/*
    324-------------------------------------------------------------------------------
    325Returns the result of converting the canonical NaN `a' to the extended
    326double-precision floating-point format.
    327-------------------------------------------------------------------------------
    328*/
    329static floatx80 commonNaNToFloatx80( commonNaNT a )
    330{
    331    floatx80 z;
    332
    333    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    334    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    335    z.__padding = 0;
    336    return z;
    337
    338}
    339
    340/*
    341-------------------------------------------------------------------------------
    342Takes two extended double-precision floating-point values `a' and `b', one
    343of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    344`b' is a signaling NaN, the invalid exception is raised.
    345-------------------------------------------------------------------------------
    346*/
    347static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    348{
    349    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    350
    351    aIsNaN = floatx80_is_nan( a );
    352    aIsSignalingNaN = floatx80_is_signaling_nan( a );
    353    bIsNaN = floatx80_is_nan( b );
    354    bIsSignalingNaN = floatx80_is_signaling_nan( b );
    355    a.low |= LIT64( 0xC000000000000000 );
    356    b.low |= LIT64( 0xC000000000000000 );
    357    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    358    if ( aIsNaN ) {
    359        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    360    }
    361    else {
    362        return b;
    363    }
    364
    365}
    366
    367#endif