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