Home | History | Annotate | Line # | Download | only in softfloat
softfloat-specialize revision 1.3
      1     /*	$NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $	*/
      2     
      3     /* This is a derivative work. */
      4     
      5     /*
      6     ===============================================================================
      7     
      8     This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
      9     Arithmetic Package, Release 2a.
     10     
     11     Written by John R. Hauser.  This work was made possible in part by the
     12     International Computer Science Institute, located at Suite 600, 1947 Center
     13     Street, Berkeley, California 94704.  Funding was partially provided by the
     14     National Science Foundation under grant MIP-9311980.  The original version
     15     of this code was written as part of a project to build a fixed-point vector
     16     processor in collaboration with the University of California at Berkeley,
     17     overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
     18     is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
     19     arithmetic/SoftFloat.html'.
     20     
     21     THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
     22     has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
     23     TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
     24     PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
     25     AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
     26     
     27     Derivative works are acceptable, even for commercial purposes, so long as
     28     (1) they include prominent notice that the work is derivative, and (2) they
     29     include prominent notice akin to these four paragraphs for those parts of
     30     this code that are retained.
     31     
     32     ===============================================================================
     33     */
     34     
     35     #include <signal.h>
     36     
     37     /*
     38     -------------------------------------------------------------------------------
     39     Underflow tininess-detection mode, statically initialized to default value.
     40     (The declaration in `softfloat.h' must match the `int8' type here.)
     41     -------------------------------------------------------------------------------
     42     */
     43     #ifdef SOFTFLOAT_FOR_GCC
     44     static
     45     #endif
     46     int8 float_detect_tininess = float_tininess_after_rounding;
     47     
     48     /*
     49     -------------------------------------------------------------------------------
     50     Raises the exceptions specified by `flags'.  Floating-point traps can be
     51     defined here if desired.  It is currently not possible for such a trap to
     52     substitute a result value.  If traps are not implemented, this routine
     53     should be simply `float_exception_flags |= flags;'.
     54     -------------------------------------------------------------------------------
     55     */
     56     fp_except float_exception_mask = 0;
     57     void float_raise( fp_except flags )
     58     {
     59     
     60         float_exception_flags |= flags;
     61     
     62         if ( flags & float_exception_mask ) {
     63     	raise( SIGFPE );
     64         }
     65     }
     66     
     67     /*
     68     -------------------------------------------------------------------------------
     69     Internal canonical NaN format.
     70     -------------------------------------------------------------------------------
     71     */
     72     typedef struct {
     73         flag sign;
     74         bits64 high, low;
     75     } commonNaNT;
     76     
     77     /*
     78     -------------------------------------------------------------------------------
     79     The pattern for a default generated single-precision NaN.
     80     -------------------------------------------------------------------------------
     81     */
     82     #define float32_default_nan 0xFFFFFFFF
     83     
     84     /*
     85     -------------------------------------------------------------------------------
     86     Returns 1 if the single-precision floating-point value `a' is a NaN;
     87     otherwise returns 0.
     88     -------------------------------------------------------------------------------
     89     */
     90     #ifdef SOFTFLOAT_FOR_GCC
     91     static
     92     #endif
     93     flag float32_is_nan( float32 a )
     94     {
     95     
     96         return ( 0xFF000000 < (bits32) ( a<<1 ) );
     97     
     98     }
     99     
    100     /*
    101     -------------------------------------------------------------------------------
    102     Returns 1 if the single-precision floating-point value `a' is a signaling
    103     NaN; otherwise returns 0.
    104     -------------------------------------------------------------------------------
    105     */
    106     #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
    107     static
    108     #endif
    109     flag float32_is_signaling_nan( float32 a )
    110     {
    111     
    112         return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
    113     
    114     }
    115     
    116     /*
    117     -------------------------------------------------------------------------------
    118     Returns the result of converting the single-precision floating-point NaN
    119     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    120     exception is raised.
    121     -------------------------------------------------------------------------------
    122     */
    123     static commonNaNT float32ToCommonNaN( float32 a )
    124     {
    125         commonNaNT z;
    126     
    127         if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    128         z.sign = a>>31;
    129         z.low = 0;
    130         z.high = ( (bits64) a )<<41;
    131         return z;
    132     
    133     }
    134     
    135     /*
    136     -------------------------------------------------------------------------------
    137     Returns the result of converting the canonical NaN `a' to the single-
    138     precision floating-point format.
    139     -------------------------------------------------------------------------------
    140     */
    141     static float32 commonNaNToFloat32( commonNaNT a )
    142     {
    143     
    144         return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    145     
    146     }
    147     
    148     /*
    149     -------------------------------------------------------------------------------
    150     Takes two single-precision floating-point values `a' and `b', one of which
    151     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    152     signaling NaN, the invalid exception is raised.
    153     -------------------------------------------------------------------------------
    154     */
    155     static float32 propagateFloat32NaN( float32 a, float32 b )
    156     {
    157         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    158     
    159         aIsNaN = float32_is_nan( a );
    160         aIsSignalingNaN = float32_is_signaling_nan( a );
    161         bIsNaN = float32_is_nan( b );
    162         bIsSignalingNaN = float32_is_signaling_nan( b );
    163         a |= 0x00400000;
    164         b |= 0x00400000;
    165         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    166         if ( aIsNaN ) {
    167             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    168         }
    169         else {
    170             return b;
    171         }
    172     
    173     }
    174     
    175     /*
    176     -------------------------------------------------------------------------------
    177     The pattern for a default generated double-precision NaN.
    178     -------------------------------------------------------------------------------
    179     */
    180     #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
    181     
    182     /*
    183     -------------------------------------------------------------------------------
    184     Returns 1 if the double-precision floating-point value `a' is a NaN;
    185     otherwise returns 0.
    186     -------------------------------------------------------------------------------
    187     */
    188     #ifdef SOFTFLOAT_FOR_GCC
    189     static
    190     #endif
    191     flag float64_is_nan( float64 a )
    192     {
    193     
    194         return ( LIT64( 0xFFE0000000000000 ) <
    195     	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
    196     
    197     }
    198     
    199     /*
    200     -------------------------------------------------------------------------------
    201     Returns 1 if the double-precision floating-point value `a' is a signaling
    202     NaN; otherwise returns 0.
    203     -------------------------------------------------------------------------------
    204     */
    205     #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
    206     static
    207     #endif
    208     flag float64_is_signaling_nan( float64 a )
    209     {
    210     
    211         return
    212                ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
    213             && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
    214     
    215     }
    216     
    217     /*
    218     -------------------------------------------------------------------------------
    219     Returns the result of converting the double-precision floating-point NaN
    220     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    221     exception is raised.
    222     -------------------------------------------------------------------------------
    223     */
    224     static commonNaNT float64ToCommonNaN( float64 a )
    225     {
    226         commonNaNT z;
    227     
    228         if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    229         z.sign = FLOAT64_DEMANGLE(a)>>63;
    230         z.low = 0;
    231         z.high = FLOAT64_DEMANGLE(a)<<12;
    232         return z;
    233     
    234     }
    235     
    236     /*
    237     -------------------------------------------------------------------------------
    238     Returns the result of converting the canonical NaN `a' to the double-
    239     precision floating-point format.
    240     -------------------------------------------------------------------------------
    241     */
    242     static float64 commonNaNToFloat64( commonNaNT a )
    243     {
    244     
    245         return FLOAT64_MANGLE(
    246     	( ( (bits64) a.sign )<<63 )
    247             | LIT64( 0x7FF8000000000000 )
    248             | ( a.high>>12 ) );
    249     
    250     }
    251     
    252     /*
    253     -------------------------------------------------------------------------------
    254     Takes two double-precision floating-point values `a' and `b', one of which
    255     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    256     signaling NaN, the invalid exception is raised.
    257     -------------------------------------------------------------------------------
    258     */
    259     static float64 propagateFloat64NaN( float64 a, float64 b )
    260     {
    261         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    262     
    263         aIsNaN = float64_is_nan( a );
    264         aIsSignalingNaN = float64_is_signaling_nan( a );
    265         bIsNaN = float64_is_nan( b );
    266         bIsSignalingNaN = float64_is_signaling_nan( b );
    267         a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    268         b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    269         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    270         if ( aIsNaN ) {
    271             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    272         }
    273         else {
    274             return b;
    275         }
    276     
    277     }
    278     
    279     #ifdef FLOATX80
    280     
    281     /*
    282     -------------------------------------------------------------------------------
    283     The pattern for a default generated extended double-precision NaN.  The
    284     `high' and `low' values hold the most- and least-significant bits,
    285     respectively.
    286     -------------------------------------------------------------------------------
    287     */
    288     #define floatx80_default_nan_high 0xFFFF
    289     #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    290     
    291     /*
    292     -------------------------------------------------------------------------------
    293     Returns 1 if the extended double-precision floating-point value `a' is a
    294     NaN; otherwise returns 0.
    295     -------------------------------------------------------------------------------
    296     */
    297     flag floatx80_is_nan( floatx80 a )
    298     {
    299     
    300         return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    301     
    302     }
    303     
    304     /*
    305     -------------------------------------------------------------------------------
    306     Returns 1 if the extended double-precision floating-point value `a' is a
    307     signaling NaN; otherwise returns 0.
    308     -------------------------------------------------------------------------------
    309     */
    310     flag floatx80_is_signaling_nan( floatx80 a )
    311     {
    312         bits64 aLow;
    313     
    314         aLow = a.low & ~ LIT64( 0x4000000000000000 );
    315         return
    316                ( ( a.high & 0x7FFF ) == 0x7FFF )
    317             && (bits64) ( aLow<<1 )
    318             && ( a.low == aLow );
    319     
    320     }
    321     
    322     /*
    323     -------------------------------------------------------------------------------
    324     Returns the result of converting the extended double-precision floating-
    325     point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    326     invalid exception is raised.
    327     -------------------------------------------------------------------------------
    328     */
    329     static commonNaNT floatx80ToCommonNaN( floatx80 a )
    330     {
    331         commonNaNT z;
    332     
    333         if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    334         z.sign = a.high>>15;
    335         z.low = 0;
    336         z.high = a.low<<1;
    337         return z;
    338     
    339     }
    340     
    341     /*
    342     -------------------------------------------------------------------------------
    343     Returns the result of converting the canonical NaN `a' to the extended
    344     double-precision floating-point format.
    345     -------------------------------------------------------------------------------
    346     */
    347     static floatx80 commonNaNToFloatx80( commonNaNT a )
    348     {
    349         floatx80 z;
    350     
    351         z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    352         z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    353         return z;
    354     
    355     }
    356     
    357     /*
    358     -------------------------------------------------------------------------------
    359     Takes two extended double-precision floating-point values `a' and `b', one
    360     of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    361     `b' is a signaling NaN, the invalid exception is raised.
    362     -------------------------------------------------------------------------------
    363     */
    364     static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    365     {
    366         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    367     
    368         aIsNaN = floatx80_is_nan( a );
    369         aIsSignalingNaN = floatx80_is_signaling_nan( a );
    370         bIsNaN = floatx80_is_nan( b );
    371         bIsSignalingNaN = floatx80_is_signaling_nan( b );
    372         a.low |= LIT64( 0xC000000000000000 );
    373         b.low |= LIT64( 0xC000000000000000 );
    374         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    375         if ( aIsNaN ) {
    376             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    377         }
    378         else {
    379             return b;
    380         }
    381     
    382     }
    383     
    384     #endif
    385     
    386     #ifdef FLOAT128
    387     
    388     /*
    389     -------------------------------------------------------------------------------
    390     The pattern for a default generated quadruple-precision NaN.  The `high' and
    391     `low' values hold the most- and least-significant bits, respectively.
    392     -------------------------------------------------------------------------------
    393     */
    394     #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
    395     #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    396     
    397     /*
    398     -------------------------------------------------------------------------------
    399     Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    400     otherwise returns 0.
    401     -------------------------------------------------------------------------------
    402     */
    403     flag float128_is_nan( float128 a )
    404     {
    405     
    406         return
    407                ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    408             && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    409     
    410     }
    411     
    412     /*
    413     -------------------------------------------------------------------------------
    414     Returns 1 if the quadruple-precision floating-point value `a' is a
    415     signaling NaN; otherwise returns 0.
    416     -------------------------------------------------------------------------------
    417     */
    418     flag float128_is_signaling_nan( float128 a )
    419     {
    420     
    421         return
    422                ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    423             && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    424     
    425     }
    426     
    427     /*
    428     -------------------------------------------------------------------------------
    429     Returns the result of converting the quadruple-precision floating-point NaN
    430     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    431     exception is raised.
    432     -------------------------------------------------------------------------------
    433     */
    434     static commonNaNT float128ToCommonNaN( float128 a )
    435     {
    436         commonNaNT z;
    437     
    438         if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    439         z.sign = a.high>>63;
    440         shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    441         return z;
    442     
    443     }
    444     
    445     /*
    446     -------------------------------------------------------------------------------
    447     Returns the result of converting the canonical NaN `a' to the quadruple-
    448     precision floating-point format.
    449     -------------------------------------------------------------------------------
    450     */
    451     static float128 commonNaNToFloat128( commonNaNT a )
    452     {
    453         float128 z;
    454     
    455         shift128Right( a.high, a.low, 16, &z.high, &z.low );
    456         z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    457         return z;
    458     
    459     }
    460     
    461     /*
    462     -------------------------------------------------------------------------------
    463     Takes two quadruple-precision floating-point values `a' and `b', one of
    464     which is a NaN, and returns the appropriate NaN result.  If either `a' or
    465     `b' is a signaling NaN, the invalid exception is raised.
    466     -------------------------------------------------------------------------------
    467     */
    468     static float128 propagateFloat128NaN( float128 a, float128 b )
    469     {
    470         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    471     
    472         aIsNaN = float128_is_nan( a );
    473         aIsSignalingNaN = float128_is_signaling_nan( a );
    474         bIsNaN = float128_is_nan( b );
    475         bIsSignalingNaN = float128_is_signaling_nan( b );
    476         a.high |= LIT64( 0x0000800000000000 );
    477         b.high |= LIT64( 0x0000800000000000 );
    478         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    479         if ( aIsNaN ) {
    480             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    481         }
    482         else {
    483             return b;
    484         }
    485     
    486     }
    487     
    488     #endif
    489     
    490