Home | History | Annotate | Line # | Download | only in libkern
      1 /* $NetBSD: softfloat-specialize.h,v 1.3 2020/09/02 03:41:56 thorpej 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  *
     21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 /*============================================================================
     35 
     36 This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
     37 Arithmetic Package, Release 2c, by John R. Hauser.
     38 
     39 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
     40 been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
     41 RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
     42 AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
     43 PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
     44 THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
     45 INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
     46 (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
     47 PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
     48 INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
     49 SOFTWARE.
     50 
     51 Derivative works require also that (1) the source code for the derivative work
     52 includes prominent notice that the work is derivative, and (2) the source code
     53 includes prominent notice of these three paragraphs for those parts of this
     54 code that are retained.
     55 
     56 =============================================================================*/
     57 
     58 /*----------------------------------------------------------------------------
     59 | Underflow tininess-detection mode, statically initialized to default value.
     60 | (The declaration in `softfloat.h' must match the `int8' type here.)
     61 *----------------------------------------------------------------------------*/
     62 /* [ MP safe, does not change dynamically ] */
     63 int float_detect_tininess = float_tininess_after_rounding;
     64 
     65 /*----------------------------------------------------------------------------
     66 | Internal canonical NaN format.
     67 *----------------------------------------------------------------------------*/
     68 typedef struct {
     69     flag sign;
     70     bits64 high, low;
     71 } commonNaNT;
     72 
     73 /*----------------------------------------------------------------------------
     74 | The pattern for a default generated single-precision NaN.
     75 *----------------------------------------------------------------------------*/
     76 #define float32_default_nan 0xFFC00000
     77 
     78 /*----------------------------------------------------------------------------
     79 | Returns 1 if the single-precision floating-point value `a' is a NaN;
     80 | otherwise returns 0.
     81 *----------------------------------------------------------------------------*/
     82 
     83 static flag float32_is_nan( float32 a )
     84 {
     85 
     86     return ( 0xFF000000 < (bits32) ( a<<1 ) );
     87 
     88 }
     89 
     90 /*----------------------------------------------------------------------------
     91 | Returns 1 if the single-precision floating-point value `a' is a signaling
     92 | NaN; otherwise returns 0.
     93 *----------------------------------------------------------------------------*/
     94 
     95 flag float32_is_signaling_nan( float32 a )
     96 {
     97 
     98     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
     99 
    100 }
    101 
    102 /*----------------------------------------------------------------------------
    103 | Returns the result of converting the single-precision floating-point NaN
    104 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    105 | exception is raised.
    106 *----------------------------------------------------------------------------*/
    107 
    108 static commonNaNT float32ToCommonNaN( float32 a )
    109 {
    110     commonNaNT z;
    111 
    112     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    113     z.sign = a>>31;
    114     z.low = 0;
    115     z.high = ( (bits64) a )<<41;
    116     return z;
    117 
    118 }
    119 
    120 /*----------------------------------------------------------------------------
    121 | Returns the result of converting the canonical NaN `a' to the single-
    122 | precision floating-point format.
    123 *----------------------------------------------------------------------------*/
    124 
    125 static float32 commonNaNToFloat32( commonNaNT a )
    126 {
    127 
    128     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
    129 
    130 }
    131 
    132 /*----------------------------------------------------------------------------
    133 | Takes two single-precision floating-point values `a' and `b', one of which
    134 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    135 | signaling NaN, the invalid exception is raised.
    136 *----------------------------------------------------------------------------*/
    137 
    138 static float32 propagateFloat32NaN( float32 a, float32 b )
    139 {
    140     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    141 
    142     aIsNaN = float32_is_nan( a );
    143     aIsSignalingNaN = float32_is_signaling_nan( a );
    144     bIsNaN = float32_is_nan( b );
    145     bIsSignalingNaN = float32_is_signaling_nan( b );
    146     a |= 0x00400000;
    147     b |= 0x00400000;
    148     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    149     if ( aIsSignalingNaN ) {
    150         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    151         return bIsNaN ? b : a;
    152     }
    153     else if ( aIsNaN ) {
    154         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    155  returnLargerSignificand:
    156         if ( (bits32) ( a<<1 ) < (bits32) ( b<<1 ) ) return b;
    157         if ( (bits32) ( b<<1 ) < (bits32) ( a<<1 ) ) return a;
    158         return ( a < b ) ? a : b;
    159     }
    160     else {
    161         return b;
    162     }
    163 
    164 }
    165 
    166 /*
    167  * float64_default_nan, float64_is_nan(), float64_is_signaling_nan()
    168  * have moved to softfloat.h.
    169  */
    170 
    171 /*----------------------------------------------------------------------------
    172 | Returns the result of converting the double-precision floating-point NaN
    173 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    174 | exception is raised.
    175 *----------------------------------------------------------------------------*/
    176 
    177 static commonNaNT float64ToCommonNaN( float64 a )
    178 {
    179     commonNaNT z;
    180 
    181     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    182     z.sign = a>>63;
    183     z.low = 0;
    184     z.high = a<<12;
    185     return z;
    186 
    187 }
    188 
    189 /*----------------------------------------------------------------------------
    190 | Returns the result of converting the canonical NaN `a' to the double-
    191 | precision floating-point format.
    192 *----------------------------------------------------------------------------*/
    193 
    194 static float64 commonNaNToFloat64( commonNaNT a )
    195 {
    196 
    197     return
    198           ( ( (bits64) a.sign )<<63 )
    199         | LIT64( 0x7FF8000000000000 )
    200         | ( a.high>>12 );
    201 
    202 }
    203 
    204 /*----------------------------------------------------------------------------
    205 | Takes two double-precision floating-point values `a' and `b', one of which
    206 | is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
    207 | signaling NaN, the invalid exception is raised.
    208 *----------------------------------------------------------------------------*/
    209 
    210 static float64 propagateFloat64NaN( float64 a, float64 b )
    211 {
    212     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    213 
    214     aIsNaN = float64_is_nan( a );
    215     aIsSignalingNaN = float64_is_signaling_nan( a );
    216     bIsNaN = float64_is_nan( b );
    217     bIsSignalingNaN = float64_is_signaling_nan( b );
    218     a |= LIT64( 0x0008000000000000 );
    219     b |= LIT64( 0x0008000000000000 );
    220     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    221     if ( aIsSignalingNaN ) {
    222         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    223         return bIsNaN ? b : a;
    224     }
    225     else if ( aIsNaN ) {
    226         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    227  returnLargerSignificand:
    228         if ( (bits64) ( a<<1 ) < (bits64) ( b<<1 ) ) return b;
    229         if ( (bits64) ( b<<1 ) < (bits64) ( a<<1 ) ) return a;
    230         return ( a < b ) ? a : b;
    231     }
    232     else {
    233         return b;
    234     }
    235 
    236 }
    237 
    238 #ifdef FLOATX80
    239 
    240 /*----------------------------------------------------------------------------
    241 | The pattern for a default generated double-extended-precision NaN.
    242 | The `high' and `low' values hold the most- and least-significant bits,
    243 | respectively.
    244 *----------------------------------------------------------------------------*/
    245 #define floatx80_default_nan_high 0xFFFF
    246 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
    247 
    248 /*----------------------------------------------------------------------------
    249 | Returns 1 if the double-extended-precision floating-point value `a' is a
    250 | NaN; otherwise returns 0.
    251 *----------------------------------------------------------------------------*/
    252 
    253 static flag floatx80_is_nan( floatx80 a )
    254 {
    255 
    256     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
    257 
    258 }
    259 
    260 /*----------------------------------------------------------------------------
    261 | Returns 1 if the double-extended-precision floating-point value `a' is a
    262 | signaling NaN; otherwise returns 0.
    263 *----------------------------------------------------------------------------*/
    264 
    265 flag floatx80_is_signaling_nan( floatx80 a )
    266 {
    267     bits64 aLow;
    268 
    269     aLow = a.low & ~ LIT64( 0x4000000000000000 );
    270     return
    271            ( ( a.high & 0x7FFF ) == 0x7FFF )
    272         && (bits64) ( aLow<<1 )
    273         && ( a.low == aLow );
    274 
    275 }
    276 
    277 /*----------------------------------------------------------------------------
    278 | Returns the result of converting the double-extended-precision floating-
    279 | point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
    280 | invalid exception is raised.
    281 *----------------------------------------------------------------------------*/
    282 
    283 static commonNaNT floatx80ToCommonNaN( floatx80 a )
    284 {
    285     commonNaNT z;
    286 
    287     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    288     z.sign = a.high>>15;
    289     z.low = 0;
    290     z.high = a.low<<1;
    291     return z;
    292 
    293 }
    294 
    295 /*----------------------------------------------------------------------------
    296 | Returns the result of converting the canonical NaN `a' to the double-
    297 | extended-precision floating-point format.
    298 *----------------------------------------------------------------------------*/
    299 
    300 static floatx80 commonNaNToFloatx80( commonNaNT a )
    301 {
    302     floatx80 z;
    303 
    304     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
    305     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
    306     return z;
    307 
    308 }
    309 
    310 /*----------------------------------------------------------------------------
    311 | Takes two double-extended-precision floating-point values `a' and `b', one
    312 | of which is a NaN, and returns the appropriate NaN result.  If either `a' or
    313 | `b' is a signaling NaN, the invalid exception is raised.
    314 *----------------------------------------------------------------------------*/
    315 
    316 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
    317 {
    318     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    319 
    320     aIsNaN = floatx80_is_nan( a );
    321     aIsSignalingNaN = floatx80_is_signaling_nan( a );
    322     bIsNaN = floatx80_is_nan( b );
    323     bIsSignalingNaN = floatx80_is_signaling_nan( b );
    324     a.low |= LIT64( 0xC000000000000000 );
    325     b.low |= LIT64( 0xC000000000000000 );
    326     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    327     if ( aIsSignalingNaN ) {
    328         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    329         return bIsNaN ? b : a;
    330     }
    331     else if ( aIsNaN ) {
    332         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    333  returnLargerSignificand:
    334         if ( a.low < b.low ) return b;
    335         if ( b.low < a.low ) return a;
    336         return ( a.high < b.high ) ? a : b;
    337     }
    338     else {
    339         return b;
    340     }
    341 
    342 }
    343 
    344 #endif
    345 
    346 #ifdef FLOAT128
    347 
    348 /*----------------------------------------------------------------------------
    349 | The pattern for a default generated quadruple-precision NaN.  The `high' and
    350 | `low' values hold the most- and least-significant bits, respectively.
    351 *----------------------------------------------------------------------------*/
    352 #define float128_default_nan_high LIT64( 0xFFFF800000000000 )
    353 #define float128_default_nan_low  LIT64( 0x0000000000000000 )
    354 
    355 /*----------------------------------------------------------------------------
    356 | Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
    357 | otherwise returns 0.
    358 *----------------------------------------------------------------------------*/
    359 
    360 flag float128_is_nan( float128 a )
    361 {
    362 
    363     return
    364            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
    365         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
    366 
    367 }
    368 
    369 /*----------------------------------------------------------------------------
    370 | Returns 1 if the quadruple-precision floating-point value `a' is a
    371 | signaling NaN; otherwise returns 0.
    372 *----------------------------------------------------------------------------*/
    373 
    374 flag float128_is_signaling_nan( float128 a )
    375 {
    376 
    377     return
    378            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
    379         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
    380 
    381 }
    382 
    383 /*----------------------------------------------------------------------------
    384 | Returns the result of converting the quadruple-precision floating-point NaN
    385 | `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
    386 | exception is raised.
    387 *----------------------------------------------------------------------------*/
    388 
    389 static commonNaNT float128ToCommonNaN( float128 a )
    390 {
    391     commonNaNT z;
    392 
    393     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
    394     z.sign = a.high>>63;
    395     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
    396     return z;
    397 
    398 }
    399 
    400 /*----------------------------------------------------------------------------
    401 | Returns the result of converting the canonical NaN `a' to the quadruple-
    402 | precision floating-point format.
    403 *----------------------------------------------------------------------------*/
    404 
    405 static float128 commonNaNToFloat128( commonNaNT a )
    406 {
    407     float128 z;
    408 
    409     shift128Right( a.high, a.low, 16, &z.high, &z.low );
    410     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
    411     return z;
    412 
    413 }
    414 
    415 /*----------------------------------------------------------------------------
    416 | Takes two quadruple-precision floating-point values `a' and `b', one of
    417 | which is a NaN, and returns the appropriate NaN result.  If either `a' or
    418 | `b' is a signaling NaN, the invalid exception is raised.
    419 *----------------------------------------------------------------------------*/
    420 
    421 static float128 propagateFloat128NaN( float128 a, float128 b )
    422 {
    423     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
    424 
    425     aIsNaN = float128_is_nan( a );
    426     aIsSignalingNaN = float128_is_signaling_nan( a );
    427     bIsNaN = float128_is_nan( b );
    428     bIsSignalingNaN = float128_is_signaling_nan( b );
    429     a.high |= LIT64( 0x0000800000000000 );
    430     b.high |= LIT64( 0x0000800000000000 );
    431     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
    432     if ( aIsSignalingNaN ) {
    433         if ( bIsSignalingNaN ) goto returnLargerSignificand;
    434         return bIsNaN ? b : a;
    435     }
    436     else if ( aIsNaN ) {
    437         if ( bIsSignalingNaN | ! bIsNaN ) return a;
    438  returnLargerSignificand:
    439         if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
    440         if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
    441         return ( a.high < b.high ) ? a : b;
    442     }
    443     else {
    444         return b;
    445     }
    446 
    447 }
    448 
    449 #endif
    450 
    451