Home | History | Annotate | Line # | Download | only in softfloat
softfloat-specialize revision 1.6
      1 /*	$NetBSD: softfloat-specialize,v 1.6 2011/03/06 10:27:37 martin 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 #include <string.h>
     37 #include <unistd.h>
     38 
     39 /*
     40 -------------------------------------------------------------------------------
     41 Underflow tininess-detection mode, statically initialized to default value.
     42 (The declaration in `softfloat.h' must match the `int8' type here.)
     43 -------------------------------------------------------------------------------
     44 */
     45 #ifdef SOFTFLOAT_FOR_GCC
     46 static
     47 #endif
     48 int8 float_detect_tininess = float_tininess_after_rounding;
     49 
     50 /*
     51 -------------------------------------------------------------------------------
     52 Raises the exceptions specified by `flags'.  Floating-point traps can be
     53 defined here if desired.  It is currently not possible for such a trap to
     54 substitute a result value.  If traps are not implemented, this routine
     55 should be simply `float_exception_flags |= flags;'.
     56 -------------------------------------------------------------------------------
     57 */
     58 #ifdef SOFTFLOAT_FOR_GCC
     59 #define float_exception_mask	_softfloat_float_exception_mask
     60 #endif
     61 fp_except float_exception_mask = 0;
     62 void float_raise( fp_except flags )
     63 {
     64     siginfo_t info;
     65 
     66     float_exception_flags |= flags;
     67 
     68     if ( flags & float_exception_mask ) {
     69 	memset(&info, 0, sizeof info);
     70 	info.si_signo = SIGFPE;
     71 	info.si_pid = getpid();
     72 	info.si_uid = geteuid();
     73 	if (flags & float_flag_underflow)
     74 	    info.si_code = FPE_FLTUND;
     75 	else if (flags & float_flag_overflow)
     76 	    info.si_code = FPE_FLTOVF;
     77 	else if (flags & float_flag_divbyzero)
     78 	    info.si_code = FPE_FLTDIV;
     79 	else if (flags & float_flag_invalid)
     80 	    info.si_code = FPE_FLTINV;
     81 	else if (flags & float_flag_inexact)
     82 	    info.si_code = FPE_FLTRES;
     83 	sigqueueinfo(getpid(), &info);
     84     }
     85 }
     86 #undef float_exception_mask
     87 
     88 /*
     89 -------------------------------------------------------------------------------
     90 Internal canonical NaN format.
     91 -------------------------------------------------------------------------------
     92 */
     93 typedef struct {
     94     flag sign;
     95     bits64 high, low;
     96 } commonNaNT;
     97 
     98 /*
     99 -------------------------------------------------------------------------------
    100 The pattern for a default generated single-precision NaN.
    101 -------------------------------------------------------------------------------
    102 */
    103 #define float32_default_nan 0xFFFFFFFF
    104 
    105 /*
    106 -------------------------------------------------------------------------------
    107 Returns 1 if the single-precision floating-point value `a' is a NaN;
    108 otherwise returns 0.
    109 -------------------------------------------------------------------------------
    110 */
    111 #ifdef SOFTFLOAT_FOR_GCC
    112 static
    113 #endif
    114 flag float32_is_nan( float32 a )
    115 {
    116 
    117     return ( 0xFF000000 < (bits32) ( a<<1 ) );
    118 
    119 }
    120 
    121 /*
    122 -------------------------------------------------------------------------------
    123 Returns 1 if the single-precision floating-point value `a' is a signaling
    124 NaN; otherwise returns 0.
    125 -------------------------------------------------------------------------------
    126 */
    127 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
    128     !defined(SOFTFLOAT_M68K_FOR_GCC)
    129 static
    130 #endif
    131 flag float32_is_signaling_nan( float32 a )
    132 {
    133 
    134     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
    135 
    136 }
    137 
    138 /*
    139 -------------------------------------------------------------------------------
    140 Returns the result of converting the single-precision floating-point NaN
    141 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    142 exception is raised.
    143 -------------------------------------------------------------------------------
    144 */
    145 static commonNaNT float32ToCommonNaN( float32 a )
    146 {
    147     commonNaNT z;
    148 
    149     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    150     z.sign = a>>31;
    151     z.low = 0;
    152     z.high = ( (bits64) a )<<41;
    153     return z;
    154 
    155 }
    156 
    157 /*
    158 -------------------------------------------------------------------------------
    159 Returns the result of converting the canonical NaN `a' to the single-
    160 precision floating-point format.
    161 -------------------------------------------------------------------------------
    162 */
    163 static float32 commonNaNToFloat32( commonNaNT a )
    164 {
    165 
    166     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    167 
    168 }
    169 
    170 /*
    171 -------------------------------------------------------------------------------
    172 Takes two single-precision floating-point values `a' and `b', one of which
    173 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    174 signaling NaN, the invalid exception is raised.
    175 -------------------------------------------------------------------------------
    176 */
    177 static float32 propagateFloat32NaN( float32 a, float32 b )
    178 {
    179     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    180 
    181     aIsNaN = float32_is_nan( a );
    182     aIsSignalingNaN = float32_is_signaling_nan( a );
    183     bIsNaN = float32_is_nan( b );
    184     bIsSignalingNaN = float32_is_signaling_nan( b );
    185     a |= 0x00400000;
    186     b |= 0x00400000;
    187     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    188     if ( aIsNaN ) {
    189         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    190     }
    191     else {
    192         return b;
    193     }
    194 
    195 }
    196 
    197 /*
    198 -------------------------------------------------------------------------------
    199 The pattern for a default generated double-precision NaN.
    200 -------------------------------------------------------------------------------
    201 */
    202 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
    203 
    204 /*
    205 -------------------------------------------------------------------------------
    206 Returns 1 if the double-precision floating-point value `a' is a NaN;
    207 otherwise returns 0.
    208 -------------------------------------------------------------------------------
    209 */
    210 #ifdef SOFTFLOAT_FOR_GCC
    211 static
    212 #endif
    213 flag float64_is_nan( float64 a )
    214 {
    215 
    216     return ( LIT64( 0xFFE0000000000000 ) <
    217 	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
    218 
    219 }
    220 
    221 /*
    222 -------------------------------------------------------------------------------
    223 Returns 1 if the double-precision floating-point value `a' is a signaling
    224 NaN; otherwise returns 0.
    225 -------------------------------------------------------------------------------
    226 */
    227 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
    228     !defined(SOFTFLOATM68K_FOR_GCC)
    229 static
    230 #endif
    231 flag float64_is_signaling_nan( float64 a )
    232 {
    233 
    234     return
    235            ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
    236         && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
    237 
    238 }
    239 
    240 /*
    241 -------------------------------------------------------------------------------
    242 Returns the result of converting the double-precision floating-point NaN
    243 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    244 exception is raised.
    245 -------------------------------------------------------------------------------
    246 */
    247 static commonNaNT float64ToCommonNaN( float64 a )
    248 {
    249     commonNaNT z;
    250 
    251     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    252     z.sign = FLOAT64_DEMANGLE(a)>>63;
    253     z.low = 0;
    254     z.high = FLOAT64_DEMANGLE(a)<<12;
    255     return z;
    256 
    257 }
    258 
    259 /*
    260 -------------------------------------------------------------------------------
    261 Returns the result of converting the canonical NaN `a' to the double-
    262 precision floating-point format.
    263 -------------------------------------------------------------------------------
    264 */
    265 static float64 commonNaNToFloat64( commonNaNT a )
    266 {
    267 
    268     return FLOAT64_MANGLE(
    269 	( ( (bits64) a.sign )<<63 )
    270         | LIT64( 0x7FF8000000000000 )
    271         | ( a.high>>12 ) );
    272 
    273 }
    274 
    275 /*
    276 -------------------------------------------------------------------------------
    277 Takes two double-precision floating-point values `a' and `b', one of which
    278 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    279 signaling NaN, the invalid exception is raised.
    280 -------------------------------------------------------------------------------
    281 */
    282 static float64 propagateFloat64NaN( float64 a, float64 b )
    283 {
    284     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    285 
    286     aIsNaN = float64_is_nan( a );
    287     aIsSignalingNaN = float64_is_signaling_nan( a );
    288     bIsNaN = float64_is_nan( b );
    289     bIsSignalingNaN = float64_is_signaling_nan( b );
    290     a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    291     b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
    292     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    293     if ( aIsNaN ) {
    294         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    295     }
    296     else {
    297         return b;
    298     }
    299 
    300 }
    301 
    302 #ifdef FLOATX80
    303 
    304 /*
    305 -------------------------------------------------------------------------------
    306 The pattern for a default generated extended double-precision NaN.  The
    307 `high' and `low' values hold the most- and least-significant bits,
    308 respectively.
    309 -------------------------------------------------------------------------------
    310 */
    311 #define floatx80_default_nan_high 0xFFFF
    312 #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    313 
    314 /*
    315 -------------------------------------------------------------------------------
    316 Returns 1 if the extended double-precision floating-point value `a' is a
    317 NaN; otherwise returns 0.
    318 -------------------------------------------------------------------------------
    319 */
    320 flag floatx80_is_nan( floatx80 a )
    321 {
    322 
    323     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    324 
    325 }
    326 
    327 /*
    328 -------------------------------------------------------------------------------
    329 Returns 1 if the extended double-precision floating-point value `a' is a
    330 signaling NaN; otherwise returns 0.
    331 -------------------------------------------------------------------------------
    332 */
    333 flag floatx80_is_signaling_nan( floatx80 a )
    334 {
    335     bits64 aLow;
    336 
    337     aLow = a.low & ~ LIT64( 0x4000000000000000 );
    338     return
    339            ( ( a.high & 0x7FFF ) == 0x7FFF )
    340         && (bits64) ( aLow<<1 )
    341         && ( a.low == aLow );
    342 
    343 }
    344 
    345 /*
    346 -------------------------------------------------------------------------------
    347 Returns the result of converting the extended double-precision floating-
    348 point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    349 invalid exception is raised.
    350 -------------------------------------------------------------------------------
    351 */
    352 static commonNaNT floatx80ToCommonNaN( floatx80 a )
    353 {
    354     commonNaNT z;
    355 
    356     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    357     z.sign = a.high>>15;
    358     z.low = 0;
    359     z.high = a.low<<1;
    360     return z;
    361 
    362 }
    363 
    364 /*
    365 -------------------------------------------------------------------------------
    366 Returns the result of converting the canonical NaN `a' to the extended
    367 double-precision floating-point format.
    368 -------------------------------------------------------------------------------
    369 */
    370 static floatx80 commonNaNToFloatx80( commonNaNT a )
    371 {
    372     floatx80 z;
    373 
    374     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    375     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    376     return z;
    377 
    378 }
    379 
    380 /*
    381 -------------------------------------------------------------------------------
    382 Takes two extended double-precision floating-point values `a' and `b', one
    383 of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    384 `b' is a signaling NaN, the invalid exception is raised.
    385 -------------------------------------------------------------------------------
    386 */
    387 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    388 {
    389     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    390 
    391     aIsNaN = floatx80_is_nan( a );
    392     aIsSignalingNaN = floatx80_is_signaling_nan( a );
    393     bIsNaN = floatx80_is_nan( b );
    394     bIsSignalingNaN = floatx80_is_signaling_nan( b );
    395     a.low |= LIT64( 0xC000000000000000 );
    396     b.low |= LIT64( 0xC000000000000000 );
    397     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    398     if ( aIsNaN ) {
    399         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    400     }
    401     else {
    402         return b;
    403     }
    404 
    405 }
    406 
    407 #endif
    408 
    409 #ifdef FLOAT128
    410 
    411 /*
    412 -------------------------------------------------------------------------------
    413 The pattern for a default generated quadruple-precision NaN.  The `high' and
    414 `low' values hold the most- and least-significant bits, respectively.
    415 -------------------------------------------------------------------------------
    416 */
    417 #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
    418 #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
    419 
    420 /*
    421 -------------------------------------------------------------------------------
    422 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    423 otherwise returns 0.
    424 -------------------------------------------------------------------------------
    425 */
    426 flag float128_is_nan( float128 a )
    427 {
    428 
    429     return
    430            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    431         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    432 
    433 }
    434 
    435 /*
    436 -------------------------------------------------------------------------------
    437 Returns 1 if the quadruple-precision floating-point value `a' is a
    438 signaling NaN; otherwise returns 0.
    439 -------------------------------------------------------------------------------
    440 */
    441 flag float128_is_signaling_nan( float128 a )
    442 {
    443 
    444     return
    445            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    446         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    447 
    448 }
    449 
    450 /*
    451 -------------------------------------------------------------------------------
    452 Returns the result of converting the quadruple-precision floating-point NaN
    453 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    454 exception is raised.
    455 -------------------------------------------------------------------------------
    456 */
    457 static commonNaNT float128ToCommonNaN( float128 a )
    458 {
    459     commonNaNT z;
    460 
    461     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    462     z.sign = a.high>>63;
    463     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    464     return z;
    465 
    466 }
    467 
    468 /*
    469 -------------------------------------------------------------------------------
    470 Returns the result of converting the canonical NaN `a' to the quadruple-
    471 precision floating-point format.
    472 -------------------------------------------------------------------------------
    473 */
    474 static float128 commonNaNToFloat128( commonNaNT a )
    475 {
    476     float128 z;
    477 
    478     shift128Right( a.high, a.low, 16, &z.high, &z.low );
    479     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    480     return z;
    481 
    482 }
    483 
    484 /*
    485 -------------------------------------------------------------------------------
    486 Takes two quadruple-precision floating-point values `a' and `b', one of
    487 which is a NaN, and returns the appropriate NaN result.  If either `a' or
    488 `b' is a signaling NaN, the invalid exception is raised.
    489 -------------------------------------------------------------------------------
    490 */
    491 static float128 propagateFloat128NaN( float128 a, float128 b )
    492 {
    493     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    494 
    495     aIsNaN = float128_is_nan( a );
    496     aIsSignalingNaN = float128_is_signaling_nan( a );
    497     bIsNaN = float128_is_nan( b );
    498     bIsSignalingNaN = float128_is_signaling_nan( b );
    499     a.high |= LIT64( 0x0000800000000000 );
    500     b.high |= LIT64( 0x0000800000000000 );
    501     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    502     if ( aIsNaN ) {
    503         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
    504     }
    505     else {
    506         return b;
    507     }
    508 
    509 }
    510 
    511 #endif
    512 
    513