Home | History | Annotate | Line # | Download | only in libkern
softfloat-specialize.h revision 1.1.2.2
      1 /* $NetBSD: softfloat-specialize.h,v 1.1.2.2 2001/06/21 20:07:18 nathanw Exp $ */
      2 
      3 /* This is a derivative work. */
      4 
      5 /*-
      6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      7  * All rights reserved.
      8  *
      9  * This code is derived from software contributed to The NetBSD Foundation
     10  * by Ross Harvey.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. All advertising materials mentioning features or use of this software
     21  *    must display the following acknowledgement:
     22  *        This product includes software developed by the NetBSD
     23  *        Foundation, Inc. and its contributors.
     24  * 4. Neither the name of The NetBSD Foundation nor the names of its
     25  *    contributors may be used to endorse or promote products derived
     26  *    from this software without specific prior written permission.
     27  *
     28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     38  * POSSIBILITY OF SUCH DAMAGE.
     39  */
     40 
     41 /*
     42 ===============================================================================
     43 
     44 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
     45 Arithmetic Package, Release 2a.
     46 
     47 Written by John R. Hauser.  This work was made possible in part by the
     48 International Computer Science Institute, located at Suite 600, 1947 Center
     49 Street, Berkeley, California 94704.  Funding was partially provided by the
     50 National Science Foundation under grant MIP-9311980.  The original version
     51 of this code was written as part of a project to build a fixed-point vector
     52 processor in collaboration with the University of California at Berkeley,
     53 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
     54 is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
     55 arithmetic/SoftFloat.html'.
     56 
     57 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
     58 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
     59 TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
     60 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
     61 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
     62 
     63 Derivative works are acceptable, even for commercial purposes, so long as
     64 (1) they include prominent notice that the work is derivative, and (2) they
     65 include prominent notice akin to these four paragraphs for those parts of
     66 this code that are retained.
     67 
     68 ===============================================================================
     69 */
     70 
     71 /*
     72 -------------------------------------------------------------------------------
     73 Underflow tininess-detection mode, statically initialized to default value.
     74 -------------------------------------------------------------------------------
     75 */
     76 
     77 /* [ MP safe, does not change dynamically ] */
     78 int float_detect_tininess = float_tininess_after_rounding;
     79 
     80 /*
     81 -------------------------------------------------------------------------------
     82 Internal canonical NaN format.
     83 -------------------------------------------------------------------------------
     84 */
     85 typedef struct {
     86     flag sign;
     87     bits64 high, low;
     88 } commonNaNT;
     89 
     90 /*
     91 -------------------------------------------------------------------------------
     92 The pattern for a default generated single-precision NaN.
     93 -------------------------------------------------------------------------------
     94 */
     95 #define float32_default_nan 0xFFC00000
     96 
     97 /*
     98 -------------------------------------------------------------------------------
     99 Returns 1 if the single-precision floating-point value `a' is a NaN;
    100 otherwise returns 0.
    101 -------------------------------------------------------------------------------
    102 */
    103 static flag float32_is_nan( float32 a )
    104 {
    105 
    106     return ( 0xFF000000 < (bits32) ( a<<1 ) );
    107 
    108 }
    109 
    110 /*
    111 -------------------------------------------------------------------------------
    112 Returns 1 if the single-precision floating-point value `a' is a signaling
    113 NaN; otherwise returns 0.
    114 -------------------------------------------------------------------------------
    115 */
    116 flag float32_is_signaling_nan( float32 a )
    117 {
    118 
    119     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
    120 
    121 }
    122 
    123 /*
    124 -------------------------------------------------------------------------------
    125 Returns the result of converting the single-precision floating-point NaN
    126 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    127 exception is raised.
    128 -------------------------------------------------------------------------------
    129 */
    130 static commonNaNT float32ToCommonNaN( float32 a )
    131 {
    132     commonNaNT z;
    133 
    134     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    135     z.sign = a>>31;
    136     z.low = 0;
    137     z.high = ( (bits64) a )<<41;
    138     return z;
    139 
    140 }
    141 
    142 /*
    143 -------------------------------------------------------------------------------
    144 Returns the result of converting the canonical NaN `a' to the single-
    145 precision floating-point format.
    146 -------------------------------------------------------------------------------
    147 */
    148 static float32 commonNaNToFloat32( commonNaNT a )
    149 {
    150 
    151     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    152 
    153 }
    154 
    155 /*
    156 -------------------------------------------------------------------------------
    157 Takes two single-precision floating-point values `a' and `b', one of which
    158 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    159 signaling NaN, the invalid exception is raised.
    160 -------------------------------------------------------------------------------
    161 */
    162 static float32 propagateFloat32NaN( float32 a, float32 b )
    163 {
    164     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    165 
    166     aIsNaN = float32_is_nan( a );
    167     aIsSignalingNaN = float32_is_signaling_nan( a );
    168     bIsNaN = float32_is_nan( b );
    169     bIsSignalingNaN = float32_is_signaling_nan( b );
    170     a |= 0x00400000;
    171     b |= 0x00400000;
    172     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    173     if ( aIsSignalingNaN ) {
    174         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    175         return bIsNaN ? b : a;
    176     }
    177     else if ( aIsNaN ) {
    178         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    179  returnLargerSignificand:
    180         if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
    181         if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
    182         return ( a < b ) ? a : b;
    183     }
    184     else {
    185         return b;
    186     }
    187 
    188 }
    189 
    190 
    191 /*
    192 -------------------------------------------------------------------------------
    193 Returns the result of converting the double-precision floating-point NaN
    194 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    195 exception is raised.
    196 -------------------------------------------------------------------------------
    197 */
    198 static commonNaNT float64ToCommonNaN( float64 a )
    199 {
    200     commonNaNT z;
    201 
    202     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    203     z.sign = a>>63;
    204     z.low = 0;
    205     z.high = a<<12;
    206     return z;
    207 
    208 }
    209 
    210 /*
    211 -------------------------------------------------------------------------------
    212 Returns the result of converting the canonical NaN `a' to the double-
    213 precision floating-point format.
    214 -------------------------------------------------------------------------------
    215 */
    216 static float64 commonNaNToFloat64( commonNaNT a )
    217 {
    218 
    219     return
    220           ( ( (bits64) a.sign )<<63 )
    221         | LIT64( 0x7FF8000000000000 )
    222         | ( a.high>>12 );
    223 
    224 }
    225 
    226 /*
    227 -------------------------------------------------------------------------------
    228 Takes two double-precision floating-point values `a' and `b', one of which
    229 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    230 signaling NaN, the invalid exception is raised.
    231 -------------------------------------------------------------------------------
    232 */
    233 static float64 propagateFloat64NaN( float64 a, float64 b )
    234 {
    235     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    236 
    237     aIsNaN = float64_is_nan( a );
    238     aIsSignalingNaN = float64_is_signaling_nan( a );
    239     bIsNaN = float64_is_nan( b );
    240     bIsSignalingNaN = float64_is_signaling_nan( b );
    241     a |= LIT64( 0x0008000000000000 );
    242     b |= LIT64( 0x0008000000000000 );
    243     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    244     if ( aIsSignalingNaN ) {
    245         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    246         return bIsNaN ? b : a;
    247     }
    248     else if ( aIsNaN ) {
    249         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    250  returnLargerSignificand:
    251         if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
    252         if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
    253         return ( a < b ) ? a : b;
    254     }
    255     else {
    256         return b;
    257     }
    258 
    259 }
    260 
    261 #ifdef FLOATX80
    262 
    263 /*
    264 -------------------------------------------------------------------------------
    265 The pattern for a default generated extended double-precision NaN.  The
    266 `high' and `low' values hold the most- and least-significant bits,
    267 respectively.
    268 -------------------------------------------------------------------------------
    269 */
    270 #define floatx80_default_nan_high 0xFFFF
    271 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
    272 
    273 /*
    274 -------------------------------------------------------------------------------
    275 Returns 1 if the extended double-precision floating-point value `a' is a
    276 NaN; otherwise returns 0.
    277 -------------------------------------------------------------------------------
    278 */
    279 static flag floatx80_is_nan( floatx80 a )
    280 {
    281 
    282     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    283 
    284 }
    285 
    286 /*
    287 -------------------------------------------------------------------------------
    288 Returns 1 if the extended double-precision floating-point value `a' is a
    289 signaling NaN; otherwise returns 0.
    290 -------------------------------------------------------------------------------
    291 */
    292 flag floatx80_is_signaling_nan( floatx80 a )
    293 {
    294     bits64 aLow;
    295 
    296     aLow = a.low & ~ LIT64( 0x4000000000000000 );
    297     return
    298            ( ( a.high & 0x7FFF ) == 0x7FFF )
    299         && (bits64) ( aLow<<1 )
    300         && ( a.low == aLow );
    301 
    302 }
    303 
    304 /*
    305 -------------------------------------------------------------------------------
    306 Returns the result of converting the extended double-precision floating-
    307 point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    308 invalid exception is raised.
    309 -------------------------------------------------------------------------------
    310 */
    311 static commonNaNT floatx80ToCommonNaN( floatx80 a )
    312 {
    313     commonNaNT z;
    314 
    315     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    316     z.sign = a.high>>15;
    317     z.low = 0;
    318     z.high = a.low<<1;
    319     return z;
    320 
    321 }
    322 
    323 /*
    324 -------------------------------------------------------------------------------
    325 Returns the result of converting the canonical NaN `a' to the extended
    326 double-precision floating-point format.
    327 -------------------------------------------------------------------------------
    328 */
    329 static floatx80 commonNaNToFloatx80( commonNaNT a )
    330 {
    331     floatx80 z;
    332 
    333     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    334     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    335     return z;
    336 
    337 }
    338 
    339 /*
    340 -------------------------------------------------------------------------------
    341 Takes two extended double-precision floating-point values `a' and `b', one
    342 of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    343 `b' is a signaling NaN, the invalid exception is raised.
    344 -------------------------------------------------------------------------------
    345 */
    346 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    347 {
    348     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    349 
    350     aIsNaN = floatx80_is_nan( a );
    351     aIsSignalingNaN = floatx80_is_signaling_nan( a );
    352     bIsNaN = floatx80_is_nan( b );
    353     bIsSignalingNaN = floatx80_is_signaling_nan( b );
    354     a.low |= LIT64( 0xC000000000000000 );
    355     b.low |= LIT64( 0xC000000000000000 );
    356     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    357     if ( aIsSignalingNaN ) {
    358         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    359         return bIsNaN ? b : a;
    360     }
    361     else if ( aIsNaN ) {
    362         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    363  returnLargerSignificand:
    364         if ( a.low < b.low ) return b;
    365         if ( b.low < a.low ) return a;
    366         return ( a.high < b.high ) ? a : b;
    367     }
    368     else {
    369         return b;
    370     }
    371 
    372 }
    373 
    374 #endif
    375 
    376 #ifdef FLOAT128
    377 
    378 /*
    379 -------------------------------------------------------------------------------
    380 The pattern for a default generated quadruple-precision NaN.  The `high' and
    381 `low' values hold the most- and least-significant bits, respectively.
    382 -------------------------------------------------------------------------------
    383 */
    384 #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
    385 #define float128_default_nan_low  LIT64( 0x0000000000000000 )
    386 
    387 /*
    388 -------------------------------------------------------------------------------
    389 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    390 otherwise returns 0.
    391 -------------------------------------------------------------------------------
    392 */
    393 flag float128_is_nan( float128 a )
    394 {
    395 
    396     return
    397            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    398         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    399 
    400 }
    401 
    402 /*
    403 -------------------------------------------------------------------------------
    404 Returns 1 if the quadruple-precision floating-point value `a' is a
    405 signaling NaN; otherwise returns 0.
    406 -------------------------------------------------------------------------------
    407 */
    408 flag float128_is_signaling_nan( float128 a )
    409 {
    410 
    411     return
    412            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    413         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    414 
    415 }
    416 
    417 /*
    418 -------------------------------------------------------------------------------
    419 Returns the result of converting the quadruple-precision floating-point NaN
    420 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    421 exception is raised.
    422 -------------------------------------------------------------------------------
    423 */
    424 static commonNaNT float128ToCommonNaN( float128 a )
    425 {
    426     commonNaNT z;
    427 
    428     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    429     z.sign = a.high>>63;
    430     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    431     return z;
    432 
    433 }
    434 
    435 /*
    436 -------------------------------------------------------------------------------
    437 Returns the result of converting the canonical NaN `a' to the quadruple-
    438 precision floating-point format.
    439 -------------------------------------------------------------------------------
    440 */
    441 static float128 commonNaNToFloat128( commonNaNT a )
    442 {
    443     float128 z;
    444 
    445     shift128Right( a.high, a.low, 16, &z.high, &z.low );
    446     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    447     return z;
    448 
    449 }
    450 
    451 /*
    452 -------------------------------------------------------------------------------
    453 Takes two quadruple-precision floating-point values `a' and `b', one of
    454 which is a NaN, and returns the appropriate NaN result.  If either `a' or
    455 `b' is a signaling NaN, the invalid exception is raised.
    456 -------------------------------------------------------------------------------
    457 */
    458 static float128 propagateFloat128NaN( float128 a, float128 b )
    459 {
    460     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    461 
    462     aIsNaN = float128_is_nan( a );
    463     aIsSignalingNaN = float128_is_signaling_nan( a );
    464     bIsNaN = float128_is_nan( b );
    465     bIsSignalingNaN = float128_is_signaling_nan( b );
    466     a.high |= LIT64( 0x0000800000000000 );
    467     b.high |= LIT64( 0x0000800000000000 );
    468     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    469     if ( aIsSignalingNaN ) {
    470         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    471         return bIsNaN ? b : a;
    472     }
    473     else if ( aIsNaN ) {
    474         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    475  returnLargerSignificand:
    476         if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
    477         if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
    478         return ( a.high < b.high ) ? a : b;
    479     }
    480     else {
    481         return b;
    482     }
    483 
    484 }
    485 
    486 #endif
    487 
    488