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