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