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