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