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