Home | History | Annotate | Line # | Download | only in softfloat
softfloat-specialize revision 1.4
      1     /*	$NetBSD: softfloat-specialize,v 1.4 2004/09/26 21:13:27 jmmv 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         !defined(SOFTFLOAT_M68K_FOR_GCC)
    108     static
    109     #endif
    110     flag float32_is_signaling_nan( float32 a )
    111     {
    112     
    113         return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
    114     
    115     }
    116     
    117     /*
    118     -------------------------------------------------------------------------------
    119     Returns the result of converting the single-precision floating-point NaN
    120     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    121     exception is raised.
    122     -------------------------------------------------------------------------------
    123     */
    124     static commonNaNT float32ToCommonNaN( float32 a )
    125     {
    126         commonNaNT z;
    127     
    128         if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    129         z.sign = a>>31;
    130         z.low = 0;
    131         z.high = ( (bits64) a )<<41;
    132         return z;
    133     
    134     }
    135     
    136     /*
    137     -------------------------------------------------------------------------------
    138     Returns the result of converting the canonical NaN `a' to the single-
    139     precision floating-point format.
    140     -------------------------------------------------------------------------------
    141     */
    142     static float32 commonNaNToFloat32( commonNaNT a )
    143     {
    144     
    145         return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    146     
    147     }
    148     
    149     /*
    150     -------------------------------------------------------------------------------
    151     Takes two single-precision floating-point values `a' and `b', one of which
    152     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    153     signaling NaN, the invalid exception is raised.
    154     -------------------------------------------------------------------------------
    155     */
    156     static float32 propagateFloat32NaN( float32 a, float32 b )
    157     {
    158         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    159     
    160         aIsNaN = float32_is_nan( a );
    161         aIsSignalingNaN = float32_is_signaling_nan( a );
    162         bIsNaN = float32_is_nan( b );
    163         bIsSignalingNaN = float32_is_signaling_nan( b );
    164         a |= 0x00400000;
    165         b |= 0x00400000;
    166         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    167         if ( aIsNaN ) {
    168             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    169         }
    170         else {
    171             return b;
    172         }
    173     
    174     }
    175     
    176     /*
    177     -------------------------------------------------------------------------------
    178     The pattern for a default generated double-precision NaN.
    179     -------------------------------------------------------------------------------
    180     */
    181     #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
    182     
    183     /*
    184     -------------------------------------------------------------------------------
    185     Returns 1 if the double-precision floating-point value `a' is a NaN;
    186     otherwise returns 0.
    187     -------------------------------------------------------------------------------
    188     */
    189     #ifdef SOFTFLOAT_FOR_GCC
    190     static
    191     #endif
    192     flag float64_is_nan( float64 a )
    193     {
    194     
    195         return ( LIT64( 0xFFE0000000000000 ) <
    196     	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
    197     
    198     }
    199     
    200     /*
    201     -------------------------------------------------------------------------------
    202     Returns 1 if the double-precision floating-point value `a' is a signaling
    203     NaN; otherwise returns 0.
    204     -------------------------------------------------------------------------------
    205     */
    206     #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
    207         !defined(SOFTFLOATM68K_FOR_GCC)
    208     static
    209     #endif
    210     flag float64_is_signaling_nan( float64 a )
    211     {
    212     
    213         return
    214                ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
    215             && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
    216     
    217     }
    218     
    219     /*
    220     -------------------------------------------------------------------------------
    221     Returns the result of converting the double-precision floating-point NaN
    222     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    223     exception is raised.
    224     -------------------------------------------------------------------------------
    225     */
    226     static commonNaNT float64ToCommonNaN( float64 a )
    227     {
    228         commonNaNT z;
    229     
    230         if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    231         z.sign = FLOAT64_DEMANGLE(a)>>63;
    232         z.low = 0;
    233         z.high = FLOAT64_DEMANGLE(a)<<12;
    234         return z;
    235     
    236     }
    237     
    238     /*
    239     -------------------------------------------------------------------------------
    240     Returns the result of converting the canonical NaN `a' to the double-
    241     precision floating-point format.
    242     -------------------------------------------------------------------------------
    243     */
    244     static float64 commonNaNToFloat64( commonNaNT a )
    245     {
    246     
    247         return FLOAT64_MANGLE(
    248     	( ( (bits64) a.sign )<<63 )
    249             | LIT64( 0x7FF8000000000000 )
    250             | ( a.high>>12 ) );
    251     
    252     }
    253     
    254     /*
    255     -------------------------------------------------------------------------------
    256     Takes two double-precision floating-point values `a' and `b', one of which
    257     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    258     signaling NaN, the invalid exception is raised.
    259     -------------------------------------------------------------------------------
    260     */
    261     static float64 propagateFloat64NaN( float64 a, float64 b )
    262     {
    263         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    264     
    265         aIsNaN = float64_is_nan( a );
    266         aIsSignalingNaN = float64_is_signaling_nan( a );
    267         bIsNaN = float64_is_nan( b );
    268         bIsSignalingNaN = float64_is_signaling_nan( b );
    269         a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    270         b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    271         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    272         if ( aIsNaN ) {
    273             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    274         }
    275         else {
    276             return b;
    277         }
    278     
    279     }
    280     
    281     #ifdef FLOATX80
    282     
    283     /*
    284     -------------------------------------------------------------------------------
    285     The pattern for a default generated extended double-precision NaN.  The
    286     `high' and `low' values hold the most- and least-significant bits,
    287     respectively.
    288     -------------------------------------------------------------------------------
    289     */
    290     #define floatx80_default_nan_high 0xFFFF
    291     #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    292     
    293     /*
    294     -------------------------------------------------------------------------------
    295     Returns 1 if the extended double-precision floating-point value `a' is a
    296     NaN; otherwise returns 0.
    297     -------------------------------------------------------------------------------
    298     */
    299     flag floatx80_is_nan( floatx80 a )
    300     {
    301     
    302         return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    303     
    304     }
    305     
    306     /*
    307     -------------------------------------------------------------------------------
    308     Returns 1 if the extended double-precision floating-point value `a' is a
    309     signaling NaN; otherwise returns 0.
    310     -------------------------------------------------------------------------------
    311     */
    312     flag floatx80_is_signaling_nan( floatx80 a )
    313     {
    314         bits64 aLow;
    315     
    316         aLow = a.low & ~ LIT64( 0x4000000000000000 );
    317         return
    318                ( ( a.high & 0x7FFF ) == 0x7FFF )
    319             && (bits64) ( aLow<<1 )
    320             && ( a.low == aLow );
    321     
    322     }
    323     
    324     /*
    325     -------------------------------------------------------------------------------
    326     Returns the result of converting the extended double-precision floating-
    327     point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    328     invalid exception is raised.
    329     -------------------------------------------------------------------------------
    330     */
    331     static commonNaNT floatx80ToCommonNaN( floatx80 a )
    332     {
    333         commonNaNT z;
    334     
    335         if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    336         z.sign = a.high>>15;
    337         z.low = 0;
    338         z.high = a.low<<1;
    339         return z;
    340     
    341     }
    342     
    343     /*
    344     -------------------------------------------------------------------------------
    345     Returns the result of converting the canonical NaN `a' to the extended
    346     double-precision floating-point format.
    347     -------------------------------------------------------------------------------
    348     */
    349     static floatx80 commonNaNToFloatx80( commonNaNT a )
    350     {
    351         floatx80 z;
    352     
    353         z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    354         z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    355         return z;
    356     
    357     }
    358     
    359     /*
    360     -------------------------------------------------------------------------------
    361     Takes two extended double-precision floating-point values `a' and `b', one
    362     of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    363     `b' is a signaling NaN, the invalid exception is raised.
    364     -------------------------------------------------------------------------------
    365     */
    366     static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    367     {
    368         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    369     
    370         aIsNaN = floatx80_is_nan( a );
    371         aIsSignalingNaN = floatx80_is_signaling_nan( a );
    372         bIsNaN = floatx80_is_nan( b );
    373         bIsSignalingNaN = floatx80_is_signaling_nan( b );
    374         a.low |= LIT64( 0xC000000000000000 );
    375         b.low |= LIT64( 0xC000000000000000 );
    376         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    377         if ( aIsNaN ) {
    378             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    379         }
    380         else {
    381             return b;
    382         }
    383     
    384     }
    385     
    386     #endif
    387     
    388     #ifdef FLOAT128
    389     
    390     /*
    391     -------------------------------------------------------------------------------
    392     The pattern for a default generated quadruple-precision NaN.  The `high' and
    393     `low' values hold the most- and least-significant bits, respectively.
    394     -------------------------------------------------------------------------------
    395     */
    396     #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
    397     #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    398     
    399     /*
    400     -------------------------------------------------------------------------------
    401     Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    402     otherwise returns 0.
    403     -------------------------------------------------------------------------------
    404     */
    405     flag float128_is_nan( float128 a )
    406     {
    407     
    408         return
    409                ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    410             && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    411     
    412     }
    413     
    414     /*
    415     -------------------------------------------------------------------------------
    416     Returns 1 if the quadruple-precision floating-point value `a' is a
    417     signaling NaN; otherwise returns 0.
    418     -------------------------------------------------------------------------------
    419     */
    420     flag float128_is_signaling_nan( float128 a )
    421     {
    422     
    423         return
    424                ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    425             && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    426     
    427     }
    428     
    429     /*
    430     -------------------------------------------------------------------------------
    431     Returns the result of converting the quadruple-precision floating-point NaN
    432     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    433     exception is raised.
    434     -------------------------------------------------------------------------------
    435     */
    436     static commonNaNT float128ToCommonNaN( float128 a )
    437     {
    438         commonNaNT z;
    439     
    440         if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    441         z.sign = a.high>>63;
    442         shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    443         return z;
    444     
    445     }
    446     
    447     /*
    448     -------------------------------------------------------------------------------
    449     Returns the result of converting the canonical NaN `a' to the quadruple-
    450     precision floating-point format.
    451     -------------------------------------------------------------------------------
    452     */
    453     static float128 commonNaNToFloat128( commonNaNT a )
    454     {
    455         float128 z;
    456     
    457         shift128Right( a.high, a.low, 16, &z.high, &z.low );
    458         z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    459         return z;
    460     
    461     }
    462     
    463     /*
    464     -------------------------------------------------------------------------------
    465     Takes two quadruple-precision floating-point values `a' and `b', one of
    466     which is a NaN, and returns the appropriate NaN result.  If either `a' or
    467     `b' is a signaling NaN, the invalid exception is raised.
    468     -------------------------------------------------------------------------------
    469     */
    470     static float128 propagateFloat128NaN( float128 a, float128 b )
    471     {
    472         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    473     
    474         aIsNaN = float128_is_nan( a );
    475         aIsSignalingNaN = float128_is_signaling_nan( a );
    476         bIsNaN = float128_is_nan( b );
    477         bIsSignalingNaN = float128_is_signaling_nan( b );
    478         a.high |= LIT64( 0x0000800000000000 );
    479         b.high |= LIT64( 0x0000800000000000 );
    480         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    481         if ( aIsNaN ) {
    482             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    483         }
    484         else {
    485             return b;
    486         }
    487     
    488     }
    489     
    490     #endif
    491     
    492