115144b0fSOlivier Houchard /* $NetBSD: softfloat.c,v 1.1 2002/05/21 23:51:07 bjh21 Exp $ */
215144b0fSOlivier Houchard 
315144b0fSOlivier Houchard /*
415144b0fSOlivier Houchard  * This version hacked for use with gcc -msoft-float by bjh21.
515144b0fSOlivier Houchard  * (Mostly a case of #ifdefing out things GCC doesn't need or provides
615144b0fSOlivier Houchard  *  itself).
715144b0fSOlivier Houchard  */
815144b0fSOlivier Houchard 
915144b0fSOlivier Houchard /*
1015144b0fSOlivier Houchard  * Things you may want to define:
1115144b0fSOlivier Houchard  *
1215144b0fSOlivier Houchard  * SOFTFLOAT_FOR_GCC - build only those functions necessary for GCC (with
1315144b0fSOlivier Houchard  *   -msoft-float) to work.  Include "softfloat-for-gcc.h" to get them
1415144b0fSOlivier Houchard  *   properly renamed.
1515144b0fSOlivier Houchard  */
1615144b0fSOlivier Houchard 
1715144b0fSOlivier Houchard /*
1815144b0fSOlivier Houchard  * This differs from the standard bits32/softfloat.c in that float64
1915144b0fSOlivier Houchard  * is defined to be a 64-bit integer rather than a structure.  The
2015144b0fSOlivier Houchard  * structure is float64s, with translation between the two going via
2115144b0fSOlivier Houchard  * float64u.
2215144b0fSOlivier Houchard  */
2315144b0fSOlivier Houchard 
2415144b0fSOlivier Houchard /*
2515144b0fSOlivier Houchard ===============================================================================
2615144b0fSOlivier Houchard 
2715144b0fSOlivier Houchard This C source file is part of the SoftFloat IEC/IEEE Floating-Point
2815144b0fSOlivier Houchard Arithmetic Package, Release 2a.
2915144b0fSOlivier Houchard 
3015144b0fSOlivier Houchard Written by John R. Hauser.  This work was made possible in part by the
3115144b0fSOlivier Houchard International Computer Science Institute, located at Suite 600, 1947 Center
3215144b0fSOlivier Houchard Street, Berkeley, California 94704.  Funding was partially provided by the
3315144b0fSOlivier Houchard National Science Foundation under grant MIP-9311980.  The original version
3415144b0fSOlivier Houchard of this code was written as part of a project to build a fixed-point vector
3515144b0fSOlivier Houchard processor in collaboration with the University of California at Berkeley,
3615144b0fSOlivier Houchard overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
3715144b0fSOlivier Houchard is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
3815144b0fSOlivier Houchard arithmetic/SoftFloat.html'.
3915144b0fSOlivier Houchard 
4015144b0fSOlivier Houchard THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
4115144b0fSOlivier Houchard has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
4215144b0fSOlivier Houchard TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
4315144b0fSOlivier Houchard PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
4415144b0fSOlivier Houchard AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
4515144b0fSOlivier Houchard 
4615144b0fSOlivier Houchard Derivative works are acceptable, even for commercial purposes, so long as
4715144b0fSOlivier Houchard (1) they include prominent notice that the work is derivative, and (2) they
4815144b0fSOlivier Houchard include prominent notice akin to these four paragraphs for those parts of
4915144b0fSOlivier Houchard this code that are retained.
5015144b0fSOlivier Houchard 
5115144b0fSOlivier Houchard ===============================================================================
5215144b0fSOlivier Houchard */
5315144b0fSOlivier Houchard 
5415144b0fSOlivier Houchard #include <sys/cdefs.h>
5515144b0fSOlivier Houchard __FBSDID("$FreeBSD$");
5615144b0fSOlivier Houchard 
5715144b0fSOlivier Houchard #ifdef SOFTFLOAT_FOR_GCC
5815144b0fSOlivier Houchard #include "softfloat-for-gcc.h"
5915144b0fSOlivier Houchard #endif
6015144b0fSOlivier Houchard 
6115144b0fSOlivier Houchard #include "milieu.h"
6215144b0fSOlivier Houchard #include "softfloat.h"
6315144b0fSOlivier Houchard 
6415144b0fSOlivier Houchard /*
6515144b0fSOlivier Houchard  * Conversions between floats as stored in memory and floats as
6615144b0fSOlivier Houchard  * SoftFloat uses them
6715144b0fSOlivier Houchard  */
6815144b0fSOlivier Houchard #ifndef FLOAT64_DEMANGLE
6915144b0fSOlivier Houchard #define FLOAT64_DEMANGLE(a)	(a)
7015144b0fSOlivier Houchard #endif
7115144b0fSOlivier Houchard #ifndef FLOAT64_MANGLE
7215144b0fSOlivier Houchard #define FLOAT64_MANGLE(a)	(a)
7315144b0fSOlivier Houchard #endif
7415144b0fSOlivier Houchard 
7515144b0fSOlivier Houchard /*
7615144b0fSOlivier Houchard -------------------------------------------------------------------------------
7715144b0fSOlivier Houchard Floating-point rounding mode and exception flags.
7815144b0fSOlivier Houchard -------------------------------------------------------------------------------
7915144b0fSOlivier Houchard */
80*b1d04644SDavid Schultz int float_rounding_mode = float_round_nearest_even;
81*b1d04644SDavid Schultz int float_exception_flags = 0;
8215144b0fSOlivier Houchard 
8315144b0fSOlivier Houchard /*
8415144b0fSOlivier Houchard -------------------------------------------------------------------------------
8515144b0fSOlivier Houchard Primitive arithmetic functions, including multi-word arithmetic, and
8615144b0fSOlivier Houchard division and square root approximations.  (Can be specialized to target if
8715144b0fSOlivier Houchard desired.)
8815144b0fSOlivier Houchard -------------------------------------------------------------------------------
8915144b0fSOlivier Houchard */
9015144b0fSOlivier Houchard #include "softfloat-macros"
9115144b0fSOlivier Houchard 
9215144b0fSOlivier Houchard /*
9315144b0fSOlivier Houchard -------------------------------------------------------------------------------
9415144b0fSOlivier Houchard Functions and definitions to determine:  (1) whether tininess for underflow
9515144b0fSOlivier Houchard is detected before or after rounding by default, (2) what (if anything)
9615144b0fSOlivier Houchard happens when exceptions are raised, (3) how signaling NaNs are distinguished
9715144b0fSOlivier Houchard from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
9815144b0fSOlivier Houchard are propagated from function inputs to output.  These details are target-
9915144b0fSOlivier Houchard specific.
10015144b0fSOlivier Houchard -------------------------------------------------------------------------------
10115144b0fSOlivier Houchard */
10215144b0fSOlivier Houchard #include "softfloat-specialize"
10315144b0fSOlivier Houchard 
10415144b0fSOlivier Houchard /*
10515144b0fSOlivier Houchard -------------------------------------------------------------------------------
10615144b0fSOlivier Houchard Returns the fraction bits of the single-precision floating-point value `a'.
10715144b0fSOlivier Houchard -------------------------------------------------------------------------------
10815144b0fSOlivier Houchard */
extractFloat32Frac(float32 a)10915144b0fSOlivier Houchard INLINE bits32 extractFloat32Frac( float32 a )
11015144b0fSOlivier Houchard {
11115144b0fSOlivier Houchard 
11215144b0fSOlivier Houchard     return a & 0x007FFFFF;
11315144b0fSOlivier Houchard 
11415144b0fSOlivier Houchard }
11515144b0fSOlivier Houchard 
11615144b0fSOlivier Houchard /*
11715144b0fSOlivier Houchard -------------------------------------------------------------------------------
11815144b0fSOlivier Houchard Returns the exponent bits of the single-precision floating-point value `a'.
11915144b0fSOlivier Houchard -------------------------------------------------------------------------------
12015144b0fSOlivier Houchard */
extractFloat32Exp(float32 a)12115144b0fSOlivier Houchard INLINE int16 extractFloat32Exp( float32 a )
12215144b0fSOlivier Houchard {
12315144b0fSOlivier Houchard 
12415144b0fSOlivier Houchard     return ( a>>23 ) & 0xFF;
12515144b0fSOlivier Houchard 
12615144b0fSOlivier Houchard }
12715144b0fSOlivier Houchard 
12815144b0fSOlivier Houchard /*
12915144b0fSOlivier Houchard -------------------------------------------------------------------------------
13015144b0fSOlivier Houchard Returns the sign bit of the single-precision floating-point value `a'.
13115144b0fSOlivier Houchard -------------------------------------------------------------------------------
13215144b0fSOlivier Houchard */
extractFloat32Sign(float32 a)13315144b0fSOlivier Houchard INLINE flag extractFloat32Sign( float32 a )
13415144b0fSOlivier Houchard {
13515144b0fSOlivier Houchard 
13615144b0fSOlivier Houchard     return a>>31;
13715144b0fSOlivier Houchard 
13815144b0fSOlivier Houchard }
13915144b0fSOlivier Houchard 
14015144b0fSOlivier Houchard /*
14115144b0fSOlivier Houchard -------------------------------------------------------------------------------
14215144b0fSOlivier Houchard Normalizes the subnormal single-precision floating-point value represented
14315144b0fSOlivier Houchard by the denormalized significand `aSig'.  The normalized exponent and
14415144b0fSOlivier Houchard significand are stored at the locations pointed to by `zExpPtr' and
14515144b0fSOlivier Houchard `zSigPtr', respectively.
14615144b0fSOlivier Houchard -------------------------------------------------------------------------------
14715144b0fSOlivier Houchard */
14815144b0fSOlivier Houchard static void
normalizeFloat32Subnormal(bits32 aSig,int16 * zExpPtr,bits32 * zSigPtr)14915144b0fSOlivier Houchard  normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
15015144b0fSOlivier Houchard {
15115144b0fSOlivier Houchard     int8 shiftCount;
15215144b0fSOlivier Houchard 
15315144b0fSOlivier Houchard     shiftCount = countLeadingZeros32( aSig ) - 8;
15415144b0fSOlivier Houchard     *zSigPtr = aSig<<shiftCount;
15515144b0fSOlivier Houchard     *zExpPtr = 1 - shiftCount;
15615144b0fSOlivier Houchard 
15715144b0fSOlivier Houchard }
15815144b0fSOlivier Houchard 
15915144b0fSOlivier Houchard /*
16015144b0fSOlivier Houchard -------------------------------------------------------------------------------
16115144b0fSOlivier Houchard Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
16215144b0fSOlivier Houchard single-precision floating-point value, returning the result.  After being
16315144b0fSOlivier Houchard shifted into the proper positions, the three fields are simply added
16415144b0fSOlivier Houchard together to form the result.  This means that any integer portion of `zSig'
16515144b0fSOlivier Houchard will be added into the exponent.  Since a properly normalized significand
16615144b0fSOlivier Houchard will have an integer portion equal to 1, the `zExp' input should be 1 less
16715144b0fSOlivier Houchard than the desired result exponent whenever `zSig' is a complete, normalized
16815144b0fSOlivier Houchard significand.
16915144b0fSOlivier Houchard -------------------------------------------------------------------------------
17015144b0fSOlivier Houchard */
packFloat32(flag zSign,int16 zExp,bits32 zSig)17115144b0fSOlivier Houchard INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
17215144b0fSOlivier Houchard {
17315144b0fSOlivier Houchard 
17415144b0fSOlivier Houchard     return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
17515144b0fSOlivier Houchard 
17615144b0fSOlivier Houchard }
17715144b0fSOlivier Houchard 
17815144b0fSOlivier Houchard /*
17915144b0fSOlivier Houchard -------------------------------------------------------------------------------
18015144b0fSOlivier Houchard Takes an abstract floating-point value having sign `zSign', exponent `zExp',
18115144b0fSOlivier Houchard and significand `zSig', and returns the proper single-precision floating-
18215144b0fSOlivier Houchard point value corresponding to the abstract input.  Ordinarily, the abstract
18315144b0fSOlivier Houchard value is simply rounded and packed into the single-precision format, with
18415144b0fSOlivier Houchard the inexact exception raised if the abstract input cannot be represented
18515144b0fSOlivier Houchard exactly.  However, if the abstract value is too large, the overflow and
18615144b0fSOlivier Houchard inexact exceptions are raised and an infinity or maximal finite value is
18715144b0fSOlivier Houchard returned.  If the abstract value is too small, the input value is rounded to
18815144b0fSOlivier Houchard a subnormal number, and the underflow and inexact exceptions are raised if
18915144b0fSOlivier Houchard the abstract input cannot be represented exactly as a subnormal single-
19015144b0fSOlivier Houchard precision floating-point number.
19115144b0fSOlivier Houchard     The input significand `zSig' has its binary point between bits 30
19215144b0fSOlivier Houchard and 29, which is 7 bits to the left of the usual location.  This shifted
19315144b0fSOlivier Houchard significand must be normalized or smaller.  If `zSig' is not normalized,
19415144b0fSOlivier Houchard `zExp' must be 0; in that case, the result returned is a subnormal number,
19515144b0fSOlivier Houchard and it must not require rounding.  In the usual case that `zSig' is
19615144b0fSOlivier Houchard normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
19715144b0fSOlivier Houchard The handling of underflow and overflow follows the IEC/IEEE Standard for
19815144b0fSOlivier Houchard Binary Floating-Point Arithmetic.
19915144b0fSOlivier Houchard -------------------------------------------------------------------------------
20015144b0fSOlivier Houchard */
roundAndPackFloat32(flag zSign,int16 zExp,bits32 zSig)20115144b0fSOlivier Houchard static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
20215144b0fSOlivier Houchard {
20315144b0fSOlivier Houchard     int8 roundingMode;
20415144b0fSOlivier Houchard     flag roundNearestEven;
20515144b0fSOlivier Houchard     int8 roundIncrement, roundBits;
20615144b0fSOlivier Houchard     flag isTiny;
20715144b0fSOlivier Houchard 
20815144b0fSOlivier Houchard     roundingMode = float_rounding_mode;
20915144b0fSOlivier Houchard     roundNearestEven = roundingMode == float_round_nearest_even;
21015144b0fSOlivier Houchard     roundIncrement = 0x40;
21115144b0fSOlivier Houchard     if ( ! roundNearestEven ) {
21215144b0fSOlivier Houchard         if ( roundingMode == float_round_to_zero ) {
21315144b0fSOlivier Houchard             roundIncrement = 0;
21415144b0fSOlivier Houchard         }
21515144b0fSOlivier Houchard         else {
21615144b0fSOlivier Houchard             roundIncrement = 0x7F;
21715144b0fSOlivier Houchard             if ( zSign ) {
21815144b0fSOlivier Houchard                 if ( roundingMode == float_round_up ) roundIncrement = 0;
21915144b0fSOlivier Houchard             }
22015144b0fSOlivier Houchard             else {
22115144b0fSOlivier Houchard                 if ( roundingMode == float_round_down ) roundIncrement = 0;
22215144b0fSOlivier Houchard             }
22315144b0fSOlivier Houchard         }
22415144b0fSOlivier Houchard     }
22515144b0fSOlivier Houchard     roundBits = zSig & 0x7F;
22615144b0fSOlivier Houchard     if ( 0xFD <= (bits16) zExp ) {
22715144b0fSOlivier Houchard         if (    ( 0xFD < zExp )
22815144b0fSOlivier Houchard              || (    ( zExp == 0xFD )
22915144b0fSOlivier Houchard                   && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
23015144b0fSOlivier Houchard            ) {
23115144b0fSOlivier Houchard             float_raise( float_flag_overflow | float_flag_inexact );
23215144b0fSOlivier Houchard             return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
23315144b0fSOlivier Houchard         }
23415144b0fSOlivier Houchard         if ( zExp < 0 ) {
23515144b0fSOlivier Houchard             isTiny =
23615144b0fSOlivier Houchard                    ( float_detect_tininess == float_tininess_before_rounding )
23715144b0fSOlivier Houchard                 || ( zExp < -1 )
23815144b0fSOlivier Houchard                 || ( zSig + roundIncrement < 0x80000000 );
23915144b0fSOlivier Houchard             shift32RightJamming( zSig, - zExp, &zSig );
24015144b0fSOlivier Houchard             zExp = 0;
24115144b0fSOlivier Houchard             roundBits = zSig & 0x7F;
24215144b0fSOlivier Houchard             if ( isTiny && roundBits ) float_raise( float_flag_underflow );
24315144b0fSOlivier Houchard         }
24415144b0fSOlivier Houchard     }
24515144b0fSOlivier Houchard     if ( roundBits ) float_exception_flags |= float_flag_inexact;
24615144b0fSOlivier Houchard     zSig = ( zSig + roundIncrement )>>7;
24715144b0fSOlivier Houchard     zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
24815144b0fSOlivier Houchard     if ( zSig == 0 ) zExp = 0;
24915144b0fSOlivier Houchard     return packFloat32( zSign, zExp, zSig );
25015144b0fSOlivier Houchard 
25115144b0fSOlivier Houchard }
25215144b0fSOlivier Houchard 
25315144b0fSOlivier Houchard /*
25415144b0fSOlivier Houchard -------------------------------------------------------------------------------
25515144b0fSOlivier Houchard Takes an abstract floating-point value having sign `zSign', exponent `zExp',
25615144b0fSOlivier Houchard and significand `zSig', and returns the proper single-precision floating-
25715144b0fSOlivier Houchard point value corresponding to the abstract input.  This routine is just like
25815144b0fSOlivier Houchard `roundAndPackFloat32' except that `zSig' does not have to be normalized.
25915144b0fSOlivier Houchard Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
26015144b0fSOlivier Houchard floating-point exponent.
26115144b0fSOlivier Houchard -------------------------------------------------------------------------------
26215144b0fSOlivier Houchard */
26315144b0fSOlivier Houchard static float32
normalizeRoundAndPackFloat32(flag zSign,int16 zExp,bits32 zSig)26415144b0fSOlivier Houchard  normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
26515144b0fSOlivier Houchard {
26615144b0fSOlivier Houchard     int8 shiftCount;
26715144b0fSOlivier Houchard 
26815144b0fSOlivier Houchard     shiftCount = countLeadingZeros32( zSig ) - 1;
26915144b0fSOlivier Houchard     return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
27015144b0fSOlivier Houchard 
27115144b0fSOlivier Houchard }
27215144b0fSOlivier Houchard 
27315144b0fSOlivier Houchard /*
27415144b0fSOlivier Houchard -------------------------------------------------------------------------------
27515144b0fSOlivier Houchard Returns the least-significant 32 fraction bits of the double-precision
27615144b0fSOlivier Houchard floating-point value `a'.
27715144b0fSOlivier Houchard -------------------------------------------------------------------------------
27815144b0fSOlivier Houchard */
extractFloat64Frac1(float64 a)27915144b0fSOlivier Houchard INLINE bits32 extractFloat64Frac1( float64 a )
28015144b0fSOlivier Houchard {
28115144b0fSOlivier Houchard 
28215144b0fSOlivier Houchard     return FLOAT64_DEMANGLE(a) & LIT64( 0x00000000FFFFFFFF );
28315144b0fSOlivier Houchard 
28415144b0fSOlivier Houchard }
28515144b0fSOlivier Houchard 
28615144b0fSOlivier Houchard /*
28715144b0fSOlivier Houchard -------------------------------------------------------------------------------
28815144b0fSOlivier Houchard Returns the most-significant 20 fraction bits of the double-precision
28915144b0fSOlivier Houchard floating-point value `a'.
29015144b0fSOlivier Houchard -------------------------------------------------------------------------------
29115144b0fSOlivier Houchard */
extractFloat64Frac0(float64 a)29215144b0fSOlivier Houchard INLINE bits32 extractFloat64Frac0( float64 a )
29315144b0fSOlivier Houchard {
29415144b0fSOlivier Houchard 
29515144b0fSOlivier Houchard     return ( FLOAT64_DEMANGLE(a)>>32 ) & 0x000FFFFF;
29615144b0fSOlivier Houchard 
29715144b0fSOlivier Houchard }
29815144b0fSOlivier Houchard 
29915144b0fSOlivier Houchard /*
30015144b0fSOlivier Houchard -------------------------------------------------------------------------------
30115144b0fSOlivier Houchard Returns the exponent bits of the double-precision floating-point value `a'.
30215144b0fSOlivier Houchard -------------------------------------------------------------------------------
30315144b0fSOlivier Houchard */
extractFloat64Exp(float64 a)30415144b0fSOlivier Houchard INLINE int16 extractFloat64Exp( float64 a )
30515144b0fSOlivier Houchard {
30615144b0fSOlivier Houchard 
30715144b0fSOlivier Houchard     return ( FLOAT64_DEMANGLE(a)>>52 ) & 0x7FF;
30815144b0fSOlivier Houchard 
30915144b0fSOlivier Houchard }
31015144b0fSOlivier Houchard 
31115144b0fSOlivier Houchard /*
31215144b0fSOlivier Houchard -------------------------------------------------------------------------------
31315144b0fSOlivier Houchard Returns the sign bit of the double-precision floating-point value `a'.
31415144b0fSOlivier Houchard -------------------------------------------------------------------------------
31515144b0fSOlivier Houchard */
extractFloat64Sign(float64 a)31615144b0fSOlivier Houchard INLINE flag extractFloat64Sign( float64 a )
31715144b0fSOlivier Houchard {
31815144b0fSOlivier Houchard 
31915144b0fSOlivier Houchard     return FLOAT64_DEMANGLE(a)>>63;
32015144b0fSOlivier Houchard 
32115144b0fSOlivier Houchard }
32215144b0fSOlivier Houchard 
32315144b0fSOlivier Houchard /*
32415144b0fSOlivier Houchard -------------------------------------------------------------------------------
32515144b0fSOlivier Houchard Normalizes the subnormal double-precision floating-point value represented
32615144b0fSOlivier Houchard by the denormalized significand formed by the concatenation of `aSig0' and
32715144b0fSOlivier Houchard `aSig1'.  The normalized exponent is stored at the location pointed to by
32815144b0fSOlivier Houchard `zExpPtr'.  The most significant 21 bits of the normalized significand are
32915144b0fSOlivier Houchard stored at the location pointed to by `zSig0Ptr', and the least significant
33015144b0fSOlivier Houchard 32 bits of the normalized significand are stored at the location pointed to
33115144b0fSOlivier Houchard by `zSig1Ptr'.
33215144b0fSOlivier Houchard -------------------------------------------------------------------------------
33315144b0fSOlivier Houchard */
33415144b0fSOlivier Houchard static void
normalizeFloat64Subnormal(bits32 aSig0,bits32 aSig1,int16 * zExpPtr,bits32 * zSig0Ptr,bits32 * zSig1Ptr)33515144b0fSOlivier Houchard  normalizeFloat64Subnormal(
33615144b0fSOlivier Houchard      bits32 aSig0,
33715144b0fSOlivier Houchard      bits32 aSig1,
33815144b0fSOlivier Houchard      int16 *zExpPtr,
33915144b0fSOlivier Houchard      bits32 *zSig0Ptr,
34015144b0fSOlivier Houchard      bits32 *zSig1Ptr
34115144b0fSOlivier Houchard  )
34215144b0fSOlivier Houchard {
34315144b0fSOlivier Houchard     int8 shiftCount;
34415144b0fSOlivier Houchard 
34515144b0fSOlivier Houchard     if ( aSig0 == 0 ) {
34615144b0fSOlivier Houchard         shiftCount = countLeadingZeros32( aSig1 ) - 11;
34715144b0fSOlivier Houchard         if ( shiftCount < 0 ) {
34815144b0fSOlivier Houchard             *zSig0Ptr = aSig1>>( - shiftCount );
34915144b0fSOlivier Houchard             *zSig1Ptr = aSig1<<( shiftCount & 31 );
35015144b0fSOlivier Houchard         }
35115144b0fSOlivier Houchard         else {
35215144b0fSOlivier Houchard             *zSig0Ptr = aSig1<<shiftCount;
35315144b0fSOlivier Houchard             *zSig1Ptr = 0;
35415144b0fSOlivier Houchard         }
35515144b0fSOlivier Houchard         *zExpPtr = - shiftCount - 31;
35615144b0fSOlivier Houchard     }
35715144b0fSOlivier Houchard     else {
35815144b0fSOlivier Houchard         shiftCount = countLeadingZeros32( aSig0 ) - 11;
35915144b0fSOlivier Houchard         shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
36015144b0fSOlivier Houchard         *zExpPtr = 1 - shiftCount;
36115144b0fSOlivier Houchard     }
36215144b0fSOlivier Houchard 
36315144b0fSOlivier Houchard }
36415144b0fSOlivier Houchard 
36515144b0fSOlivier Houchard /*
36615144b0fSOlivier Houchard -------------------------------------------------------------------------------
36715144b0fSOlivier Houchard Packs the sign `zSign', the exponent `zExp', and the significand formed by
36815144b0fSOlivier Houchard the concatenation of `zSig0' and `zSig1' into a double-precision floating-
36915144b0fSOlivier Houchard point value, returning the result.  After being shifted into the proper
37015144b0fSOlivier Houchard positions, the three fields `zSign', `zExp', and `zSig0' are simply added
37115144b0fSOlivier Houchard together to form the most significant 32 bits of the result.  This means
37215144b0fSOlivier Houchard that any integer portion of `zSig0' will be added into the exponent.  Since
37315144b0fSOlivier Houchard a properly normalized significand will have an integer portion equal to 1,
37415144b0fSOlivier Houchard the `zExp' input should be 1 less than the desired result exponent whenever
37515144b0fSOlivier Houchard `zSig0' and `zSig1' concatenated form a complete, normalized significand.
37615144b0fSOlivier Houchard -------------------------------------------------------------------------------
37715144b0fSOlivier Houchard */
37815144b0fSOlivier Houchard INLINE float64
packFloat64(flag zSign,int16 zExp,bits32 zSig0,bits32 zSig1)37915144b0fSOlivier Houchard  packFloat64( flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1 )
38015144b0fSOlivier Houchard {
38115144b0fSOlivier Houchard 
38215144b0fSOlivier Houchard     return FLOAT64_MANGLE( ( ( (bits64) zSign )<<63 ) +
38315144b0fSOlivier Houchard 			   ( ( (bits64) zExp )<<52 ) +
38415144b0fSOlivier Houchard 			   ( ( (bits64) zSig0 )<<32 ) + zSig1 );
38515144b0fSOlivier Houchard 
38615144b0fSOlivier Houchard 
38715144b0fSOlivier Houchard }
38815144b0fSOlivier Houchard 
38915144b0fSOlivier Houchard /*
39015144b0fSOlivier Houchard -------------------------------------------------------------------------------
39115144b0fSOlivier Houchard Takes an abstract floating-point value having sign `zSign', exponent `zExp',
39215144b0fSOlivier Houchard and extended significand formed by the concatenation of `zSig0', `zSig1',
39315144b0fSOlivier Houchard and `zSig2', and returns the proper double-precision floating-point value
39415144b0fSOlivier Houchard corresponding to the abstract input.  Ordinarily, the abstract value is
39515144b0fSOlivier Houchard simply rounded and packed into the double-precision format, with the inexact
39615144b0fSOlivier Houchard exception raised if the abstract input cannot be represented exactly.
39715144b0fSOlivier Houchard However, if the abstract value is too large, the overflow and inexact
39815144b0fSOlivier Houchard exceptions are raised and an infinity or maximal finite value is returned.
39915144b0fSOlivier Houchard If the abstract value is too small, the input value is rounded to a
40015144b0fSOlivier Houchard subnormal number, and the underflow and inexact exceptions are raised if the
40115144b0fSOlivier Houchard abstract input cannot be represented exactly as a subnormal double-precision
40215144b0fSOlivier Houchard floating-point number.
40315144b0fSOlivier Houchard     The input significand must be normalized or smaller.  If the input
40415144b0fSOlivier Houchard significand is not normalized, `zExp' must be 0; in that case, the result
40515144b0fSOlivier Houchard returned is a subnormal number, and it must not require rounding.  In the
40615144b0fSOlivier Houchard usual case that the input significand is normalized, `zExp' must be 1 less
40715144b0fSOlivier Houchard than the ``true'' floating-point exponent.  The handling of underflow and
40815144b0fSOlivier Houchard overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
40915144b0fSOlivier Houchard -------------------------------------------------------------------------------
41015144b0fSOlivier Houchard */
41115144b0fSOlivier Houchard static float64
roundAndPackFloat64(flag zSign,int16 zExp,bits32 zSig0,bits32 zSig1,bits32 zSig2)41215144b0fSOlivier Houchard  roundAndPackFloat64(
41315144b0fSOlivier Houchard      flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1, bits32 zSig2 )
41415144b0fSOlivier Houchard {
41515144b0fSOlivier Houchard     int8 roundingMode;
41615144b0fSOlivier Houchard     flag roundNearestEven, increment, isTiny;
41715144b0fSOlivier Houchard 
41815144b0fSOlivier Houchard     roundingMode = float_rounding_mode;
41915144b0fSOlivier Houchard     roundNearestEven = ( roundingMode == float_round_nearest_even );
42015144b0fSOlivier Houchard     increment = ( (sbits32) zSig2 < 0 );
42115144b0fSOlivier Houchard     if ( ! roundNearestEven ) {
42215144b0fSOlivier Houchard         if ( roundingMode == float_round_to_zero ) {
42315144b0fSOlivier Houchard             increment = 0;
42415144b0fSOlivier Houchard         }
42515144b0fSOlivier Houchard         else {
42615144b0fSOlivier Houchard             if ( zSign ) {
42715144b0fSOlivier Houchard                 increment = ( roundingMode == float_round_down ) && zSig2;
42815144b0fSOlivier Houchard             }
42915144b0fSOlivier Houchard             else {
43015144b0fSOlivier Houchard                 increment = ( roundingMode == float_round_up ) && zSig2;
43115144b0fSOlivier Houchard             }
43215144b0fSOlivier Houchard         }
43315144b0fSOlivier Houchard     }
43415144b0fSOlivier Houchard     if ( 0x7FD <= (bits16) zExp ) {
43515144b0fSOlivier Houchard         if (    ( 0x7FD < zExp )
43615144b0fSOlivier Houchard              || (    ( zExp == 0x7FD )
43715144b0fSOlivier Houchard                   && eq64( 0x001FFFFF, 0xFFFFFFFF, zSig0, zSig1 )
43815144b0fSOlivier Houchard                   && increment
43915144b0fSOlivier Houchard                 )
44015144b0fSOlivier Houchard            ) {
44115144b0fSOlivier Houchard             float_raise( float_flag_overflow | float_flag_inexact );
44215144b0fSOlivier Houchard             if (    ( roundingMode == float_round_to_zero )
44315144b0fSOlivier Houchard                  || ( zSign && ( roundingMode == float_round_up ) )
44415144b0fSOlivier Houchard                  || ( ! zSign && ( roundingMode == float_round_down ) )
44515144b0fSOlivier Houchard                ) {
44615144b0fSOlivier Houchard                 return packFloat64( zSign, 0x7FE, 0x000FFFFF, 0xFFFFFFFF );
44715144b0fSOlivier Houchard             }
44815144b0fSOlivier Houchard             return packFloat64( zSign, 0x7FF, 0, 0 );
44915144b0fSOlivier Houchard         }
45015144b0fSOlivier Houchard         if ( zExp < 0 ) {
45115144b0fSOlivier Houchard             isTiny =
45215144b0fSOlivier Houchard                    ( float_detect_tininess == float_tininess_before_rounding )
45315144b0fSOlivier Houchard                 || ( zExp < -1 )
45415144b0fSOlivier Houchard                 || ! increment
45515144b0fSOlivier Houchard                 || lt64( zSig0, zSig1, 0x001FFFFF, 0xFFFFFFFF );
45615144b0fSOlivier Houchard             shift64ExtraRightJamming(
45715144b0fSOlivier Houchard                 zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
45815144b0fSOlivier Houchard             zExp = 0;
45915144b0fSOlivier Houchard             if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
46015144b0fSOlivier Houchard             if ( roundNearestEven ) {
46115144b0fSOlivier Houchard                 increment = ( (sbits32) zSig2 < 0 );
46215144b0fSOlivier Houchard             }
46315144b0fSOlivier Houchard             else {
46415144b0fSOlivier Houchard                 if ( zSign ) {
46515144b0fSOlivier Houchard                     increment = ( roundingMode == float_round_down ) && zSig2;
46615144b0fSOlivier Houchard                 }
46715144b0fSOlivier Houchard                 else {
46815144b0fSOlivier Houchard                     increment = ( roundingMode == float_round_up ) && zSig2;
46915144b0fSOlivier Houchard                 }
47015144b0fSOlivier Houchard             }
47115144b0fSOlivier Houchard         }
47215144b0fSOlivier Houchard     }
47315144b0fSOlivier Houchard     if ( zSig2 ) float_exception_flags |= float_flag_inexact;
47415144b0fSOlivier Houchard     if ( increment ) {
47515144b0fSOlivier Houchard         add64( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
47615144b0fSOlivier Houchard         zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
47715144b0fSOlivier Houchard     }
47815144b0fSOlivier Houchard     else {
47915144b0fSOlivier Houchard         if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
48015144b0fSOlivier Houchard     }
48115144b0fSOlivier Houchard     return packFloat64( zSign, zExp, zSig0, zSig1 );
48215144b0fSOlivier Houchard 
48315144b0fSOlivier Houchard }
48415144b0fSOlivier Houchard 
48515144b0fSOlivier Houchard /*
48615144b0fSOlivier Houchard -------------------------------------------------------------------------------
48715144b0fSOlivier Houchard Takes an abstract floating-point value having sign `zSign', exponent `zExp',
48815144b0fSOlivier Houchard and significand formed by the concatenation of `zSig0' and `zSig1', and
48915144b0fSOlivier Houchard returns the proper double-precision floating-point value corresponding
49015144b0fSOlivier Houchard to the abstract input.  This routine is just like `roundAndPackFloat64'
49115144b0fSOlivier Houchard except that the input significand has fewer bits and does not have to be
49215144b0fSOlivier Houchard normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
49315144b0fSOlivier Houchard point exponent.
49415144b0fSOlivier Houchard -------------------------------------------------------------------------------
49515144b0fSOlivier Houchard */
49615144b0fSOlivier Houchard static float64
normalizeRoundAndPackFloat64(flag zSign,int16 zExp,bits32 zSig0,bits32 zSig1)49715144b0fSOlivier Houchard  normalizeRoundAndPackFloat64(
49815144b0fSOlivier Houchard      flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1 )
49915144b0fSOlivier Houchard {
50015144b0fSOlivier Houchard     int8 shiftCount;
50115144b0fSOlivier Houchard     bits32 zSig2;
50215144b0fSOlivier Houchard 
50315144b0fSOlivier Houchard     if ( zSig0 == 0 ) {
50415144b0fSOlivier Houchard         zSig0 = zSig1;
50515144b0fSOlivier Houchard         zSig1 = 0;
50615144b0fSOlivier Houchard         zExp -= 32;
50715144b0fSOlivier Houchard     }
50815144b0fSOlivier Houchard     shiftCount = countLeadingZeros32( zSig0 ) - 11;
50915144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
51015144b0fSOlivier Houchard         zSig2 = 0;
51115144b0fSOlivier Houchard         shortShift64Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
51215144b0fSOlivier Houchard     }
51315144b0fSOlivier Houchard     else {
51415144b0fSOlivier Houchard         shift64ExtraRightJamming(
51515144b0fSOlivier Houchard             zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
51615144b0fSOlivier Houchard     }
51715144b0fSOlivier Houchard     zExp -= shiftCount;
51815144b0fSOlivier Houchard     return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
51915144b0fSOlivier Houchard 
52015144b0fSOlivier Houchard }
52115144b0fSOlivier Houchard 
52215144b0fSOlivier Houchard /*
52315144b0fSOlivier Houchard -------------------------------------------------------------------------------
52415144b0fSOlivier Houchard Returns the result of converting the 32-bit two's complement integer `a' to
52515144b0fSOlivier Houchard the single-precision floating-point format.  The conversion is performed
52615144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
52715144b0fSOlivier Houchard -------------------------------------------------------------------------------
52815144b0fSOlivier Houchard */
int32_to_float32(int32 a)52915144b0fSOlivier Houchard float32 int32_to_float32( int32 a )
53015144b0fSOlivier Houchard {
53115144b0fSOlivier Houchard     flag zSign;
53215144b0fSOlivier Houchard 
53315144b0fSOlivier Houchard     if ( a == 0 ) return 0;
53415144b0fSOlivier Houchard     if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
53515144b0fSOlivier Houchard     zSign = ( a < 0 );
53615144b0fSOlivier Houchard     return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
53715144b0fSOlivier Houchard 
53815144b0fSOlivier Houchard }
53915144b0fSOlivier Houchard 
54015144b0fSOlivier Houchard /*
54115144b0fSOlivier Houchard -------------------------------------------------------------------------------
54215144b0fSOlivier Houchard Returns the result of converting the 32-bit two's complement integer `a' to
54315144b0fSOlivier Houchard the double-precision floating-point format.  The conversion is performed
54415144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
54515144b0fSOlivier Houchard -------------------------------------------------------------------------------
54615144b0fSOlivier Houchard */
int32_to_float64(int32 a)54715144b0fSOlivier Houchard float64 int32_to_float64( int32 a )
54815144b0fSOlivier Houchard {
54915144b0fSOlivier Houchard     flag zSign;
55015144b0fSOlivier Houchard     bits32 absA;
55115144b0fSOlivier Houchard     int8 shiftCount;
55215144b0fSOlivier Houchard     bits32 zSig0, zSig1;
55315144b0fSOlivier Houchard 
55415144b0fSOlivier Houchard     if ( a == 0 ) return packFloat64( 0, 0, 0, 0 );
55515144b0fSOlivier Houchard     zSign = ( a < 0 );
55615144b0fSOlivier Houchard     absA = zSign ? - a : a;
55715144b0fSOlivier Houchard     shiftCount = countLeadingZeros32( absA ) - 11;
55815144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
55915144b0fSOlivier Houchard         zSig0 = absA<<shiftCount;
56015144b0fSOlivier Houchard         zSig1 = 0;
56115144b0fSOlivier Houchard     }
56215144b0fSOlivier Houchard     else {
56315144b0fSOlivier Houchard         shift64Right( absA, 0, - shiftCount, &zSig0, &zSig1 );
56415144b0fSOlivier Houchard     }
56515144b0fSOlivier Houchard     return packFloat64( zSign, 0x412 - shiftCount, zSig0, zSig1 );
56615144b0fSOlivier Houchard 
56715144b0fSOlivier Houchard }
56815144b0fSOlivier Houchard 
56915144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
57015144b0fSOlivier Houchard /*
57115144b0fSOlivier Houchard -------------------------------------------------------------------------------
57215144b0fSOlivier Houchard Returns the result of converting the single-precision floating-point value
57315144b0fSOlivier Houchard `a' to the 32-bit two's complement integer format.  The conversion is
57415144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
57515144b0fSOlivier Houchard Arithmetic---which means in particular that the conversion is rounded
57615144b0fSOlivier Houchard according to the current rounding mode.  If `a' is a NaN, the largest
57715144b0fSOlivier Houchard positive integer is returned.  Otherwise, if the conversion overflows, the
57815144b0fSOlivier Houchard largest integer with the same sign as `a' is returned.
57915144b0fSOlivier Houchard -------------------------------------------------------------------------------
58015144b0fSOlivier Houchard */
float32_to_int32(float32 a)58115144b0fSOlivier Houchard int32 float32_to_int32( float32 a )
58215144b0fSOlivier Houchard {
58315144b0fSOlivier Houchard     flag aSign;
58415144b0fSOlivier Houchard     int16 aExp, shiftCount;
58515144b0fSOlivier Houchard     bits32 aSig, aSigExtra;
58615144b0fSOlivier Houchard     int32 z;
58715144b0fSOlivier Houchard     int8 roundingMode;
58815144b0fSOlivier Houchard 
58915144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
59015144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
59115144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
59215144b0fSOlivier Houchard     shiftCount = aExp - 0x96;
59315144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
59415144b0fSOlivier Houchard         if ( 0x9E <= aExp ) {
59515144b0fSOlivier Houchard             if ( a != 0xCF000000 ) {
59615144b0fSOlivier Houchard                 float_raise( float_flag_invalid );
59715144b0fSOlivier Houchard                 if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
59815144b0fSOlivier Houchard                     return 0x7FFFFFFF;
59915144b0fSOlivier Houchard                 }
60015144b0fSOlivier Houchard             }
60115144b0fSOlivier Houchard             return (sbits32) 0x80000000;
60215144b0fSOlivier Houchard         }
60315144b0fSOlivier Houchard         z = ( aSig | 0x00800000 )<<shiftCount;
60415144b0fSOlivier Houchard         if ( aSign ) z = - z;
60515144b0fSOlivier Houchard     }
60615144b0fSOlivier Houchard     else {
60715144b0fSOlivier Houchard         if ( aExp < 0x7E ) {
60815144b0fSOlivier Houchard             aSigExtra = aExp | aSig;
60915144b0fSOlivier Houchard             z = 0;
61015144b0fSOlivier Houchard         }
61115144b0fSOlivier Houchard         else {
61215144b0fSOlivier Houchard             aSig |= 0x00800000;
61315144b0fSOlivier Houchard             aSigExtra = aSig<<( shiftCount & 31 );
61415144b0fSOlivier Houchard             z = aSig>>( - shiftCount );
61515144b0fSOlivier Houchard         }
61615144b0fSOlivier Houchard         if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
61715144b0fSOlivier Houchard         roundingMode = float_rounding_mode;
61815144b0fSOlivier Houchard         if ( roundingMode == float_round_nearest_even ) {
61915144b0fSOlivier Houchard             if ( (sbits32) aSigExtra < 0 ) {
62015144b0fSOlivier Houchard                 ++z;
62115144b0fSOlivier Houchard                 if ( (bits32) ( aSigExtra<<1 ) == 0 ) z &= ~1;
62215144b0fSOlivier Houchard             }
62315144b0fSOlivier Houchard             if ( aSign ) z = - z;
62415144b0fSOlivier Houchard         }
62515144b0fSOlivier Houchard         else {
62615144b0fSOlivier Houchard             aSigExtra = ( aSigExtra != 0 );
62715144b0fSOlivier Houchard             if ( aSign ) {
62815144b0fSOlivier Houchard                 z += ( roundingMode == float_round_down ) & aSigExtra;
62915144b0fSOlivier Houchard                 z = - z;
63015144b0fSOlivier Houchard             }
63115144b0fSOlivier Houchard             else {
63215144b0fSOlivier Houchard                 z += ( roundingMode == float_round_up ) & aSigExtra;
63315144b0fSOlivier Houchard             }
63415144b0fSOlivier Houchard         }
63515144b0fSOlivier Houchard     }
63615144b0fSOlivier Houchard     return z;
63715144b0fSOlivier Houchard 
63815144b0fSOlivier Houchard }
63915144b0fSOlivier Houchard #endif
64015144b0fSOlivier Houchard 
64115144b0fSOlivier Houchard /*
64215144b0fSOlivier Houchard -------------------------------------------------------------------------------
64315144b0fSOlivier Houchard Returns the result of converting the single-precision floating-point value
64415144b0fSOlivier Houchard `a' to the 32-bit two's complement integer format.  The conversion is
64515144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
64615144b0fSOlivier Houchard Arithmetic, except that the conversion is always rounded toward zero.
64715144b0fSOlivier Houchard If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
64815144b0fSOlivier Houchard the conversion overflows, the largest integer with the same sign as `a' is
64915144b0fSOlivier Houchard returned.
65015144b0fSOlivier Houchard -------------------------------------------------------------------------------
65115144b0fSOlivier Houchard */
float32_to_int32_round_to_zero(float32 a)65215144b0fSOlivier Houchard int32 float32_to_int32_round_to_zero( float32 a )
65315144b0fSOlivier Houchard {
65415144b0fSOlivier Houchard     flag aSign;
65515144b0fSOlivier Houchard     int16 aExp, shiftCount;
65615144b0fSOlivier Houchard     bits32 aSig;
65715144b0fSOlivier Houchard     int32 z;
65815144b0fSOlivier Houchard 
65915144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
66015144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
66115144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
66215144b0fSOlivier Houchard     shiftCount = aExp - 0x9E;
66315144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
66415144b0fSOlivier Houchard         if ( a != 0xCF000000 ) {
66515144b0fSOlivier Houchard             float_raise( float_flag_invalid );
66615144b0fSOlivier Houchard             if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
66715144b0fSOlivier Houchard         }
66815144b0fSOlivier Houchard         return (sbits32) 0x80000000;
66915144b0fSOlivier Houchard     }
67015144b0fSOlivier Houchard     else if ( aExp <= 0x7E ) {
67115144b0fSOlivier Houchard         if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
67215144b0fSOlivier Houchard         return 0;
67315144b0fSOlivier Houchard     }
67415144b0fSOlivier Houchard     aSig = ( aSig | 0x00800000 )<<8;
67515144b0fSOlivier Houchard     z = aSig>>( - shiftCount );
67615144b0fSOlivier Houchard     if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
67715144b0fSOlivier Houchard         float_exception_flags |= float_flag_inexact;
67815144b0fSOlivier Houchard     }
67915144b0fSOlivier Houchard     if ( aSign ) z = - z;
68015144b0fSOlivier Houchard     return z;
68115144b0fSOlivier Houchard 
68215144b0fSOlivier Houchard }
68315144b0fSOlivier Houchard 
68415144b0fSOlivier Houchard /*
68515144b0fSOlivier Houchard -------------------------------------------------------------------------------
68615144b0fSOlivier Houchard Returns the result of converting the single-precision floating-point value
68715144b0fSOlivier Houchard `a' to the double-precision floating-point format.  The conversion is
68815144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
68915144b0fSOlivier Houchard Arithmetic.
69015144b0fSOlivier Houchard -------------------------------------------------------------------------------
69115144b0fSOlivier Houchard */
float32_to_float64(float32 a)69215144b0fSOlivier Houchard float64 float32_to_float64( float32 a )
69315144b0fSOlivier Houchard {
69415144b0fSOlivier Houchard     flag aSign;
69515144b0fSOlivier Houchard     int16 aExp;
69615144b0fSOlivier Houchard     bits32 aSig, zSig0, zSig1;
69715144b0fSOlivier Houchard 
69815144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
69915144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
70015144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
70115144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
70215144b0fSOlivier Houchard         if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
70315144b0fSOlivier Houchard         return packFloat64( aSign, 0x7FF, 0, 0 );
70415144b0fSOlivier Houchard     }
70515144b0fSOlivier Houchard     if ( aExp == 0 ) {
70615144b0fSOlivier Houchard         if ( aSig == 0 ) return packFloat64( aSign, 0, 0, 0 );
70715144b0fSOlivier Houchard         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
70815144b0fSOlivier Houchard         --aExp;
70915144b0fSOlivier Houchard     }
71015144b0fSOlivier Houchard     shift64Right( aSig, 0, 3, &zSig0, &zSig1 );
71115144b0fSOlivier Houchard     return packFloat64( aSign, aExp + 0x380, zSig0, zSig1 );
71215144b0fSOlivier Houchard 
71315144b0fSOlivier Houchard }
71415144b0fSOlivier Houchard 
71515144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
71615144b0fSOlivier Houchard /*
71715144b0fSOlivier Houchard -------------------------------------------------------------------------------
71815144b0fSOlivier Houchard Rounds the single-precision floating-point value `a' to an integer,
71915144b0fSOlivier Houchard and returns the result as a single-precision floating-point value.  The
72015144b0fSOlivier Houchard operation is performed according to the IEC/IEEE Standard for Binary
72115144b0fSOlivier Houchard Floating-Point Arithmetic.
72215144b0fSOlivier Houchard -------------------------------------------------------------------------------
72315144b0fSOlivier Houchard */
float32_round_to_int(float32 a)72415144b0fSOlivier Houchard float32 float32_round_to_int( float32 a )
72515144b0fSOlivier Houchard {
72615144b0fSOlivier Houchard     flag aSign;
72715144b0fSOlivier Houchard     int16 aExp;
72815144b0fSOlivier Houchard     bits32 lastBitMask, roundBitsMask;
72915144b0fSOlivier Houchard     int8 roundingMode;
73015144b0fSOlivier Houchard     float32 z;
73115144b0fSOlivier Houchard 
73215144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
73315144b0fSOlivier Houchard     if ( 0x96 <= aExp ) {
73415144b0fSOlivier Houchard         if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
73515144b0fSOlivier Houchard             return propagateFloat32NaN( a, a );
73615144b0fSOlivier Houchard         }
73715144b0fSOlivier Houchard         return a;
73815144b0fSOlivier Houchard     }
73915144b0fSOlivier Houchard     if ( aExp <= 0x7E ) {
74015144b0fSOlivier Houchard         if ( (bits32) ( a<<1 ) == 0 ) return a;
74115144b0fSOlivier Houchard         float_exception_flags |= float_flag_inexact;
74215144b0fSOlivier Houchard         aSign = extractFloat32Sign( a );
74315144b0fSOlivier Houchard         switch ( float_rounding_mode ) {
74415144b0fSOlivier Houchard          case float_round_nearest_even:
74515144b0fSOlivier Houchard             if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
74615144b0fSOlivier Houchard                 return packFloat32( aSign, 0x7F, 0 );
74715144b0fSOlivier Houchard             }
74815144b0fSOlivier Houchard             break;
74915144b0fSOlivier Houchard 	 case float_round_to_zero:
75015144b0fSOlivier Houchard 	    break;
75115144b0fSOlivier Houchard          case float_round_down:
75215144b0fSOlivier Houchard             return aSign ? 0xBF800000 : 0;
75315144b0fSOlivier Houchard          case float_round_up:
75415144b0fSOlivier Houchard             return aSign ? 0x80000000 : 0x3F800000;
75515144b0fSOlivier Houchard         }
75615144b0fSOlivier Houchard         return packFloat32( aSign, 0, 0 );
75715144b0fSOlivier Houchard     }
75815144b0fSOlivier Houchard     lastBitMask = 1;
75915144b0fSOlivier Houchard     lastBitMask <<= 0x96 - aExp;
76015144b0fSOlivier Houchard     roundBitsMask = lastBitMask - 1;
76115144b0fSOlivier Houchard     z = a;
76215144b0fSOlivier Houchard     roundingMode = float_rounding_mode;
76315144b0fSOlivier Houchard     if ( roundingMode == float_round_nearest_even ) {
76415144b0fSOlivier Houchard         z += lastBitMask>>1;
76515144b0fSOlivier Houchard         if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
76615144b0fSOlivier Houchard     }
76715144b0fSOlivier Houchard     else if ( roundingMode != float_round_to_zero ) {
76815144b0fSOlivier Houchard         if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
76915144b0fSOlivier Houchard             z += roundBitsMask;
77015144b0fSOlivier Houchard         }
77115144b0fSOlivier Houchard     }
77215144b0fSOlivier Houchard     z &= ~ roundBitsMask;
77315144b0fSOlivier Houchard     if ( z != a ) float_exception_flags |= float_flag_inexact;
77415144b0fSOlivier Houchard     return z;
77515144b0fSOlivier Houchard 
77615144b0fSOlivier Houchard }
77715144b0fSOlivier Houchard #endif
77815144b0fSOlivier Houchard 
77915144b0fSOlivier Houchard /*
78015144b0fSOlivier Houchard -------------------------------------------------------------------------------
78115144b0fSOlivier Houchard Returns the result of adding the absolute values of the single-precision
78215144b0fSOlivier Houchard floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
78315144b0fSOlivier Houchard before being returned.  `zSign' is ignored if the result is a NaN.
78415144b0fSOlivier Houchard The addition is performed according to the IEC/IEEE Standard for Binary
78515144b0fSOlivier Houchard Floating-Point Arithmetic.
78615144b0fSOlivier Houchard -------------------------------------------------------------------------------
78715144b0fSOlivier Houchard */
addFloat32Sigs(float32 a,float32 b,flag zSign)78815144b0fSOlivier Houchard static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
78915144b0fSOlivier Houchard {
79015144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
79115144b0fSOlivier Houchard     bits32 aSig, bSig, zSig;
79215144b0fSOlivier Houchard     int16 expDiff;
79315144b0fSOlivier Houchard 
79415144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
79515144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
79615144b0fSOlivier Houchard     bSig = extractFloat32Frac( b );
79715144b0fSOlivier Houchard     bExp = extractFloat32Exp( b );
79815144b0fSOlivier Houchard     expDiff = aExp - bExp;
79915144b0fSOlivier Houchard     aSig <<= 6;
80015144b0fSOlivier Houchard     bSig <<= 6;
80115144b0fSOlivier Houchard     if ( 0 < expDiff ) {
80215144b0fSOlivier Houchard         if ( aExp == 0xFF ) {
80315144b0fSOlivier Houchard             if ( aSig ) return propagateFloat32NaN( a, b );
80415144b0fSOlivier Houchard             return a;
80515144b0fSOlivier Houchard         }
80615144b0fSOlivier Houchard         if ( bExp == 0 ) {
80715144b0fSOlivier Houchard             --expDiff;
80815144b0fSOlivier Houchard         }
80915144b0fSOlivier Houchard         else {
81015144b0fSOlivier Houchard             bSig |= 0x20000000;
81115144b0fSOlivier Houchard         }
81215144b0fSOlivier Houchard         shift32RightJamming( bSig, expDiff, &bSig );
81315144b0fSOlivier Houchard         zExp = aExp;
81415144b0fSOlivier Houchard     }
81515144b0fSOlivier Houchard     else if ( expDiff < 0 ) {
81615144b0fSOlivier Houchard         if ( bExp == 0xFF ) {
81715144b0fSOlivier Houchard             if ( bSig ) return propagateFloat32NaN( a, b );
81815144b0fSOlivier Houchard             return packFloat32( zSign, 0xFF, 0 );
81915144b0fSOlivier Houchard         }
82015144b0fSOlivier Houchard         if ( aExp == 0 ) {
82115144b0fSOlivier Houchard             ++expDiff;
82215144b0fSOlivier Houchard         }
82315144b0fSOlivier Houchard         else {
82415144b0fSOlivier Houchard             aSig |= 0x20000000;
82515144b0fSOlivier Houchard         }
82615144b0fSOlivier Houchard         shift32RightJamming( aSig, - expDiff, &aSig );
82715144b0fSOlivier Houchard         zExp = bExp;
82815144b0fSOlivier Houchard     }
82915144b0fSOlivier Houchard     else {
83015144b0fSOlivier Houchard         if ( aExp == 0xFF ) {
83115144b0fSOlivier Houchard             if ( aSig | bSig ) return propagateFloat32NaN( a, b );
83215144b0fSOlivier Houchard             return a;
83315144b0fSOlivier Houchard         }
83415144b0fSOlivier Houchard         if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
83515144b0fSOlivier Houchard         zSig = 0x40000000 + aSig + bSig;
83615144b0fSOlivier Houchard         zExp = aExp;
83715144b0fSOlivier Houchard         goto roundAndPack;
83815144b0fSOlivier Houchard     }
83915144b0fSOlivier Houchard     aSig |= 0x20000000;
84015144b0fSOlivier Houchard     zSig = ( aSig + bSig )<<1;
84115144b0fSOlivier Houchard     --zExp;
84215144b0fSOlivier Houchard     if ( (sbits32) zSig < 0 ) {
84315144b0fSOlivier Houchard         zSig = aSig + bSig;
84415144b0fSOlivier Houchard         ++zExp;
84515144b0fSOlivier Houchard     }
84615144b0fSOlivier Houchard  roundAndPack:
84715144b0fSOlivier Houchard     return roundAndPackFloat32( zSign, zExp, zSig );
84815144b0fSOlivier Houchard 
84915144b0fSOlivier Houchard }
85015144b0fSOlivier Houchard 
85115144b0fSOlivier Houchard /*
85215144b0fSOlivier Houchard -------------------------------------------------------------------------------
85315144b0fSOlivier Houchard Returns the result of subtracting the absolute values of the single-
85415144b0fSOlivier Houchard precision floating-point values `a' and `b'.  If `zSign' is 1, the
85515144b0fSOlivier Houchard difference is negated before being returned.  `zSign' is ignored if the
85615144b0fSOlivier Houchard result is a NaN.  The subtraction is performed according to the IEC/IEEE
85715144b0fSOlivier Houchard Standard for Binary Floating-Point Arithmetic.
85815144b0fSOlivier Houchard -------------------------------------------------------------------------------
85915144b0fSOlivier Houchard */
subFloat32Sigs(float32 a,float32 b,flag zSign)86015144b0fSOlivier Houchard static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
86115144b0fSOlivier Houchard {
86215144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
86315144b0fSOlivier Houchard     bits32 aSig, bSig, zSig;
86415144b0fSOlivier Houchard     int16 expDiff;
86515144b0fSOlivier Houchard 
86615144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
86715144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
86815144b0fSOlivier Houchard     bSig = extractFloat32Frac( b );
86915144b0fSOlivier Houchard     bExp = extractFloat32Exp( b );
87015144b0fSOlivier Houchard     expDiff = aExp - bExp;
87115144b0fSOlivier Houchard     aSig <<= 7;
87215144b0fSOlivier Houchard     bSig <<= 7;
87315144b0fSOlivier Houchard     if ( 0 < expDiff ) goto aExpBigger;
87415144b0fSOlivier Houchard     if ( expDiff < 0 ) goto bExpBigger;
87515144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
87615144b0fSOlivier Houchard         if ( aSig | bSig ) return propagateFloat32NaN( a, b );
87715144b0fSOlivier Houchard         float_raise( float_flag_invalid );
87815144b0fSOlivier Houchard         return float32_default_nan;
87915144b0fSOlivier Houchard     }
88015144b0fSOlivier Houchard     if ( aExp == 0 ) {
88115144b0fSOlivier Houchard         aExp = 1;
88215144b0fSOlivier Houchard         bExp = 1;
88315144b0fSOlivier Houchard     }
88415144b0fSOlivier Houchard     if ( bSig < aSig ) goto aBigger;
88515144b0fSOlivier Houchard     if ( aSig < bSig ) goto bBigger;
88615144b0fSOlivier Houchard     return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
88715144b0fSOlivier Houchard  bExpBigger:
88815144b0fSOlivier Houchard     if ( bExp == 0xFF ) {
88915144b0fSOlivier Houchard         if ( bSig ) return propagateFloat32NaN( a, b );
89015144b0fSOlivier Houchard         return packFloat32( zSign ^ 1, 0xFF, 0 );
89115144b0fSOlivier Houchard     }
89215144b0fSOlivier Houchard     if ( aExp == 0 ) {
89315144b0fSOlivier Houchard         ++expDiff;
89415144b0fSOlivier Houchard     }
89515144b0fSOlivier Houchard     else {
89615144b0fSOlivier Houchard         aSig |= 0x40000000;
89715144b0fSOlivier Houchard     }
89815144b0fSOlivier Houchard     shift32RightJamming( aSig, - expDiff, &aSig );
89915144b0fSOlivier Houchard     bSig |= 0x40000000;
90015144b0fSOlivier Houchard  bBigger:
90115144b0fSOlivier Houchard     zSig = bSig - aSig;
90215144b0fSOlivier Houchard     zExp = bExp;
90315144b0fSOlivier Houchard     zSign ^= 1;
90415144b0fSOlivier Houchard     goto normalizeRoundAndPack;
90515144b0fSOlivier Houchard  aExpBigger:
90615144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
90715144b0fSOlivier Houchard         if ( aSig ) return propagateFloat32NaN( a, b );
90815144b0fSOlivier Houchard         return a;
90915144b0fSOlivier Houchard     }
91015144b0fSOlivier Houchard     if ( bExp == 0 ) {
91115144b0fSOlivier Houchard         --expDiff;
91215144b0fSOlivier Houchard     }
91315144b0fSOlivier Houchard     else {
91415144b0fSOlivier Houchard         bSig |= 0x40000000;
91515144b0fSOlivier Houchard     }
91615144b0fSOlivier Houchard     shift32RightJamming( bSig, expDiff, &bSig );
91715144b0fSOlivier Houchard     aSig |= 0x40000000;
91815144b0fSOlivier Houchard  aBigger:
91915144b0fSOlivier Houchard     zSig = aSig - bSig;
92015144b0fSOlivier Houchard     zExp = aExp;
92115144b0fSOlivier Houchard  normalizeRoundAndPack:
92215144b0fSOlivier Houchard     --zExp;
92315144b0fSOlivier Houchard     return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
92415144b0fSOlivier Houchard 
92515144b0fSOlivier Houchard }
92615144b0fSOlivier Houchard 
92715144b0fSOlivier Houchard /*
92815144b0fSOlivier Houchard -------------------------------------------------------------------------------
92915144b0fSOlivier Houchard Returns the result of adding the single-precision floating-point values `a'
93015144b0fSOlivier Houchard and `b'.  The operation is performed according to the IEC/IEEE Standard for
93115144b0fSOlivier Houchard Binary Floating-Point Arithmetic.
93215144b0fSOlivier Houchard -------------------------------------------------------------------------------
93315144b0fSOlivier Houchard */
float32_add(float32 a,float32 b)93415144b0fSOlivier Houchard float32 float32_add( float32 a, float32 b )
93515144b0fSOlivier Houchard {
93615144b0fSOlivier Houchard     flag aSign, bSign;
93715144b0fSOlivier Houchard 
93815144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
93915144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
94015144b0fSOlivier Houchard     if ( aSign == bSign ) {
94115144b0fSOlivier Houchard         return addFloat32Sigs( a, b, aSign );
94215144b0fSOlivier Houchard     }
94315144b0fSOlivier Houchard     else {
94415144b0fSOlivier Houchard         return subFloat32Sigs( a, b, aSign );
94515144b0fSOlivier Houchard     }
94615144b0fSOlivier Houchard 
94715144b0fSOlivier Houchard }
94815144b0fSOlivier Houchard 
94915144b0fSOlivier Houchard /*
95015144b0fSOlivier Houchard -------------------------------------------------------------------------------
95115144b0fSOlivier Houchard Returns the result of subtracting the single-precision floating-point values
95215144b0fSOlivier Houchard `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
95315144b0fSOlivier Houchard for Binary Floating-Point Arithmetic.
95415144b0fSOlivier Houchard -------------------------------------------------------------------------------
95515144b0fSOlivier Houchard */
float32_sub(float32 a,float32 b)95615144b0fSOlivier Houchard float32 float32_sub( float32 a, float32 b )
95715144b0fSOlivier Houchard {
95815144b0fSOlivier Houchard     flag aSign, bSign;
95915144b0fSOlivier Houchard 
96015144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
96115144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
96215144b0fSOlivier Houchard     if ( aSign == bSign ) {
96315144b0fSOlivier Houchard         return subFloat32Sigs( a, b, aSign );
96415144b0fSOlivier Houchard     }
96515144b0fSOlivier Houchard     else {
96615144b0fSOlivier Houchard         return addFloat32Sigs( a, b, aSign );
96715144b0fSOlivier Houchard     }
96815144b0fSOlivier Houchard 
96915144b0fSOlivier Houchard }
97015144b0fSOlivier Houchard 
97115144b0fSOlivier Houchard /*
97215144b0fSOlivier Houchard -------------------------------------------------------------------------------
97315144b0fSOlivier Houchard Returns the result of multiplying the single-precision floating-point values
97415144b0fSOlivier Houchard `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
97515144b0fSOlivier Houchard for Binary Floating-Point Arithmetic.
97615144b0fSOlivier Houchard -------------------------------------------------------------------------------
97715144b0fSOlivier Houchard */
float32_mul(float32 a,float32 b)97815144b0fSOlivier Houchard float32 float32_mul( float32 a, float32 b )
97915144b0fSOlivier Houchard {
98015144b0fSOlivier Houchard     flag aSign, bSign, zSign;
98115144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
98215144b0fSOlivier Houchard     bits32 aSig, bSig, zSig0, zSig1;
98315144b0fSOlivier Houchard 
98415144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
98515144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
98615144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
98715144b0fSOlivier Houchard     bSig = extractFloat32Frac( b );
98815144b0fSOlivier Houchard     bExp = extractFloat32Exp( b );
98915144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
99015144b0fSOlivier Houchard     zSign = aSign ^ bSign;
99115144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
99215144b0fSOlivier Houchard         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
99315144b0fSOlivier Houchard             return propagateFloat32NaN( a, b );
99415144b0fSOlivier Houchard         }
99515144b0fSOlivier Houchard         if ( ( bExp | bSig ) == 0 ) {
99615144b0fSOlivier Houchard             float_raise( float_flag_invalid );
99715144b0fSOlivier Houchard             return float32_default_nan;
99815144b0fSOlivier Houchard         }
99915144b0fSOlivier Houchard         return packFloat32( zSign, 0xFF, 0 );
100015144b0fSOlivier Houchard     }
100115144b0fSOlivier Houchard     if ( bExp == 0xFF ) {
100215144b0fSOlivier Houchard         if ( bSig ) return propagateFloat32NaN( a, b );
100315144b0fSOlivier Houchard         if ( ( aExp | aSig ) == 0 ) {
100415144b0fSOlivier Houchard             float_raise( float_flag_invalid );
100515144b0fSOlivier Houchard             return float32_default_nan;
100615144b0fSOlivier Houchard         }
100715144b0fSOlivier Houchard         return packFloat32( zSign, 0xFF, 0 );
100815144b0fSOlivier Houchard     }
100915144b0fSOlivier Houchard     if ( aExp == 0 ) {
101015144b0fSOlivier Houchard         if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
101115144b0fSOlivier Houchard         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
101215144b0fSOlivier Houchard     }
101315144b0fSOlivier Houchard     if ( bExp == 0 ) {
101415144b0fSOlivier Houchard         if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
101515144b0fSOlivier Houchard         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
101615144b0fSOlivier Houchard     }
101715144b0fSOlivier Houchard     zExp = aExp + bExp - 0x7F;
101815144b0fSOlivier Houchard     aSig = ( aSig | 0x00800000 )<<7;
101915144b0fSOlivier Houchard     bSig = ( bSig | 0x00800000 )<<8;
102015144b0fSOlivier Houchard     mul32To64( aSig, bSig, &zSig0, &zSig1 );
102115144b0fSOlivier Houchard     zSig0 |= ( zSig1 != 0 );
102215144b0fSOlivier Houchard     if ( 0 <= (sbits32) ( zSig0<<1 ) ) {
102315144b0fSOlivier Houchard         zSig0 <<= 1;
102415144b0fSOlivier Houchard         --zExp;
102515144b0fSOlivier Houchard     }
102615144b0fSOlivier Houchard     return roundAndPackFloat32( zSign, zExp, zSig0 );
102715144b0fSOlivier Houchard 
102815144b0fSOlivier Houchard }
102915144b0fSOlivier Houchard 
103015144b0fSOlivier Houchard /*
103115144b0fSOlivier Houchard -------------------------------------------------------------------------------
103215144b0fSOlivier Houchard Returns the result of dividing the single-precision floating-point value `a'
103315144b0fSOlivier Houchard by the corresponding value `b'.  The operation is performed according to the
103415144b0fSOlivier Houchard IEC/IEEE Standard for Binary Floating-Point Arithmetic.
103515144b0fSOlivier Houchard -------------------------------------------------------------------------------
103615144b0fSOlivier Houchard */
float32_div(float32 a,float32 b)103715144b0fSOlivier Houchard float32 float32_div( float32 a, float32 b )
103815144b0fSOlivier Houchard {
103915144b0fSOlivier Houchard     flag aSign, bSign, zSign;
104015144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
104115144b0fSOlivier Houchard     bits32 aSig, bSig, zSig, rem0, rem1, term0, term1;
104215144b0fSOlivier Houchard 
104315144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
104415144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
104515144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
104615144b0fSOlivier Houchard     bSig = extractFloat32Frac( b );
104715144b0fSOlivier Houchard     bExp = extractFloat32Exp( b );
104815144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
104915144b0fSOlivier Houchard     zSign = aSign ^ bSign;
105015144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
105115144b0fSOlivier Houchard         if ( aSig ) return propagateFloat32NaN( a, b );
105215144b0fSOlivier Houchard         if ( bExp == 0xFF ) {
105315144b0fSOlivier Houchard             if ( bSig ) return propagateFloat32NaN( a, b );
105415144b0fSOlivier Houchard             float_raise( float_flag_invalid );
105515144b0fSOlivier Houchard             return float32_default_nan;
105615144b0fSOlivier Houchard         }
105715144b0fSOlivier Houchard         return packFloat32( zSign, 0xFF, 0 );
105815144b0fSOlivier Houchard     }
105915144b0fSOlivier Houchard     if ( bExp == 0xFF ) {
106015144b0fSOlivier Houchard         if ( bSig ) return propagateFloat32NaN( a, b );
106115144b0fSOlivier Houchard         return packFloat32( zSign, 0, 0 );
106215144b0fSOlivier Houchard     }
106315144b0fSOlivier Houchard     if ( bExp == 0 ) {
106415144b0fSOlivier Houchard         if ( bSig == 0 ) {
106515144b0fSOlivier Houchard             if ( ( aExp | aSig ) == 0 ) {
106615144b0fSOlivier Houchard                 float_raise( float_flag_invalid );
106715144b0fSOlivier Houchard                 return float32_default_nan;
106815144b0fSOlivier Houchard             }
106915144b0fSOlivier Houchard             float_raise( float_flag_divbyzero );
107015144b0fSOlivier Houchard             return packFloat32( zSign, 0xFF, 0 );
107115144b0fSOlivier Houchard         }
107215144b0fSOlivier Houchard         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
107315144b0fSOlivier Houchard     }
107415144b0fSOlivier Houchard     if ( aExp == 0 ) {
107515144b0fSOlivier Houchard         if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
107615144b0fSOlivier Houchard         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
107715144b0fSOlivier Houchard     }
107815144b0fSOlivier Houchard     zExp = aExp - bExp + 0x7D;
107915144b0fSOlivier Houchard     aSig = ( aSig | 0x00800000 )<<7;
108015144b0fSOlivier Houchard     bSig = ( bSig | 0x00800000 )<<8;
108115144b0fSOlivier Houchard     if ( bSig <= ( aSig + aSig ) ) {
108215144b0fSOlivier Houchard         aSig >>= 1;
108315144b0fSOlivier Houchard         ++zExp;
108415144b0fSOlivier Houchard     }
108515144b0fSOlivier Houchard     zSig = estimateDiv64To32( aSig, 0, bSig );
108615144b0fSOlivier Houchard     if ( ( zSig & 0x3F ) <= 2 ) {
108715144b0fSOlivier Houchard         mul32To64( bSig, zSig, &term0, &term1 );
108815144b0fSOlivier Houchard         sub64( aSig, 0, term0, term1, &rem0, &rem1 );
108915144b0fSOlivier Houchard         while ( (sbits32) rem0 < 0 ) {
109015144b0fSOlivier Houchard             --zSig;
109115144b0fSOlivier Houchard             add64( rem0, rem1, 0, bSig, &rem0, &rem1 );
109215144b0fSOlivier Houchard         }
109315144b0fSOlivier Houchard         zSig |= ( rem1 != 0 );
109415144b0fSOlivier Houchard     }
109515144b0fSOlivier Houchard     return roundAndPackFloat32( zSign, zExp, zSig );
109615144b0fSOlivier Houchard 
109715144b0fSOlivier Houchard }
109815144b0fSOlivier Houchard 
109915144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
110015144b0fSOlivier Houchard /*
110115144b0fSOlivier Houchard -------------------------------------------------------------------------------
110215144b0fSOlivier Houchard Returns the remainder of the single-precision floating-point value `a'
110315144b0fSOlivier Houchard with respect to the corresponding value `b'.  The operation is performed
110415144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
110515144b0fSOlivier Houchard -------------------------------------------------------------------------------
110615144b0fSOlivier Houchard */
float32_rem(float32 a,float32 b)110715144b0fSOlivier Houchard float32 float32_rem( float32 a, float32 b )
110815144b0fSOlivier Houchard {
110915144b0fSOlivier Houchard     flag aSign, bSign, zSign;
111015144b0fSOlivier Houchard     int16 aExp, bExp, expDiff;
111115144b0fSOlivier Houchard     bits32 aSig, bSig, q, allZero, alternateASig;
111215144b0fSOlivier Houchard     sbits32 sigMean;
111315144b0fSOlivier Houchard 
111415144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
111515144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
111615144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
111715144b0fSOlivier Houchard     bSig = extractFloat32Frac( b );
111815144b0fSOlivier Houchard     bExp = extractFloat32Exp( b );
111915144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
112015144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
112115144b0fSOlivier Houchard         if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
112215144b0fSOlivier Houchard             return propagateFloat32NaN( a, b );
112315144b0fSOlivier Houchard         }
112415144b0fSOlivier Houchard         float_raise( float_flag_invalid );
112515144b0fSOlivier Houchard         return float32_default_nan;
112615144b0fSOlivier Houchard     }
112715144b0fSOlivier Houchard     if ( bExp == 0xFF ) {
112815144b0fSOlivier Houchard         if ( bSig ) return propagateFloat32NaN( a, b );
112915144b0fSOlivier Houchard         return a;
113015144b0fSOlivier Houchard     }
113115144b0fSOlivier Houchard     if ( bExp == 0 ) {
113215144b0fSOlivier Houchard         if ( bSig == 0 ) {
113315144b0fSOlivier Houchard             float_raise( float_flag_invalid );
113415144b0fSOlivier Houchard             return float32_default_nan;
113515144b0fSOlivier Houchard         }
113615144b0fSOlivier Houchard         normalizeFloat32Subnormal( bSig, &bExp, &bSig );
113715144b0fSOlivier Houchard     }
113815144b0fSOlivier Houchard     if ( aExp == 0 ) {
113915144b0fSOlivier Houchard         if ( aSig == 0 ) return a;
114015144b0fSOlivier Houchard         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
114115144b0fSOlivier Houchard     }
114215144b0fSOlivier Houchard     expDiff = aExp - bExp;
114315144b0fSOlivier Houchard     aSig = ( aSig | 0x00800000 )<<8;
114415144b0fSOlivier Houchard     bSig = ( bSig | 0x00800000 )<<8;
114515144b0fSOlivier Houchard     if ( expDiff < 0 ) {
114615144b0fSOlivier Houchard         if ( expDiff < -1 ) return a;
114715144b0fSOlivier Houchard         aSig >>= 1;
114815144b0fSOlivier Houchard     }
114915144b0fSOlivier Houchard     q = ( bSig <= aSig );
115015144b0fSOlivier Houchard     if ( q ) aSig -= bSig;
115115144b0fSOlivier Houchard     expDiff -= 32;
115215144b0fSOlivier Houchard     while ( 0 < expDiff ) {
115315144b0fSOlivier Houchard         q = estimateDiv64To32( aSig, 0, bSig );
115415144b0fSOlivier Houchard         q = ( 2 < q ) ? q - 2 : 0;
115515144b0fSOlivier Houchard         aSig = - ( ( bSig>>2 ) * q );
115615144b0fSOlivier Houchard         expDiff -= 30;
115715144b0fSOlivier Houchard     }
115815144b0fSOlivier Houchard     expDiff += 32;
115915144b0fSOlivier Houchard     if ( 0 < expDiff ) {
116015144b0fSOlivier Houchard         q = estimateDiv64To32( aSig, 0, bSig );
116115144b0fSOlivier Houchard         q = ( 2 < q ) ? q - 2 : 0;
116215144b0fSOlivier Houchard         q >>= 32 - expDiff;
116315144b0fSOlivier Houchard         bSig >>= 2;
116415144b0fSOlivier Houchard         aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
116515144b0fSOlivier Houchard     }
116615144b0fSOlivier Houchard     else {
116715144b0fSOlivier Houchard         aSig >>= 2;
116815144b0fSOlivier Houchard         bSig >>= 2;
116915144b0fSOlivier Houchard     }
117015144b0fSOlivier Houchard     do {
117115144b0fSOlivier Houchard         alternateASig = aSig;
117215144b0fSOlivier Houchard         ++q;
117315144b0fSOlivier Houchard         aSig -= bSig;
117415144b0fSOlivier Houchard     } while ( 0 <= (sbits32) aSig );
117515144b0fSOlivier Houchard     sigMean = aSig + alternateASig;
117615144b0fSOlivier Houchard     if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
117715144b0fSOlivier Houchard         aSig = alternateASig;
117815144b0fSOlivier Houchard     }
117915144b0fSOlivier Houchard     zSign = ( (sbits32) aSig < 0 );
118015144b0fSOlivier Houchard     if ( zSign ) aSig = - aSig;
118115144b0fSOlivier Houchard     return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
118215144b0fSOlivier Houchard 
118315144b0fSOlivier Houchard }
118415144b0fSOlivier Houchard #endif
118515144b0fSOlivier Houchard 
118615144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
118715144b0fSOlivier Houchard /*
118815144b0fSOlivier Houchard -------------------------------------------------------------------------------
118915144b0fSOlivier Houchard Returns the square root of the single-precision floating-point value `a'.
119015144b0fSOlivier Houchard The operation is performed according to the IEC/IEEE Standard for Binary
119115144b0fSOlivier Houchard Floating-Point Arithmetic.
119215144b0fSOlivier Houchard -------------------------------------------------------------------------------
119315144b0fSOlivier Houchard */
float32_sqrt(float32 a)119415144b0fSOlivier Houchard float32 float32_sqrt( float32 a )
119515144b0fSOlivier Houchard {
119615144b0fSOlivier Houchard     flag aSign;
119715144b0fSOlivier Houchard     int16 aExp, zExp;
119815144b0fSOlivier Houchard     bits32 aSig, zSig, rem0, rem1, term0, term1;
119915144b0fSOlivier Houchard 
120015144b0fSOlivier Houchard     aSig = extractFloat32Frac( a );
120115144b0fSOlivier Houchard     aExp = extractFloat32Exp( a );
120215144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
120315144b0fSOlivier Houchard     if ( aExp == 0xFF ) {
120415144b0fSOlivier Houchard         if ( aSig ) return propagateFloat32NaN( a, 0 );
120515144b0fSOlivier Houchard         if ( ! aSign ) return a;
120615144b0fSOlivier Houchard         float_raise( float_flag_invalid );
120715144b0fSOlivier Houchard         return float32_default_nan;
120815144b0fSOlivier Houchard     }
120915144b0fSOlivier Houchard     if ( aSign ) {
121015144b0fSOlivier Houchard         if ( ( aExp | aSig ) == 0 ) return a;
121115144b0fSOlivier Houchard         float_raise( float_flag_invalid );
121215144b0fSOlivier Houchard         return float32_default_nan;
121315144b0fSOlivier Houchard     }
121415144b0fSOlivier Houchard     if ( aExp == 0 ) {
121515144b0fSOlivier Houchard         if ( aSig == 0 ) return 0;
121615144b0fSOlivier Houchard         normalizeFloat32Subnormal( aSig, &aExp, &aSig );
121715144b0fSOlivier Houchard     }
121815144b0fSOlivier Houchard     zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
121915144b0fSOlivier Houchard     aSig = ( aSig | 0x00800000 )<<8;
122015144b0fSOlivier Houchard     zSig = estimateSqrt32( aExp, aSig ) + 2;
122115144b0fSOlivier Houchard     if ( ( zSig & 0x7F ) <= 5 ) {
122215144b0fSOlivier Houchard         if ( zSig < 2 ) {
122315144b0fSOlivier Houchard             zSig = 0x7FFFFFFF;
122415144b0fSOlivier Houchard             goto roundAndPack;
122515144b0fSOlivier Houchard         }
122615144b0fSOlivier Houchard         else {
122715144b0fSOlivier Houchard             aSig >>= aExp & 1;
122815144b0fSOlivier Houchard             mul32To64( zSig, zSig, &term0, &term1 );
122915144b0fSOlivier Houchard             sub64( aSig, 0, term0, term1, &rem0, &rem1 );
123015144b0fSOlivier Houchard             while ( (sbits32) rem0 < 0 ) {
123115144b0fSOlivier Houchard                 --zSig;
123215144b0fSOlivier Houchard                 shortShift64Left( 0, zSig, 1, &term0, &term1 );
123315144b0fSOlivier Houchard                 term1 |= 1;
123415144b0fSOlivier Houchard                 add64( rem0, rem1, term0, term1, &rem0, &rem1 );
123515144b0fSOlivier Houchard             }
123615144b0fSOlivier Houchard             zSig |= ( ( rem0 | rem1 ) != 0 );
123715144b0fSOlivier Houchard         }
123815144b0fSOlivier Houchard     }
123915144b0fSOlivier Houchard     shift32RightJamming( zSig, 1, &zSig );
124015144b0fSOlivier Houchard  roundAndPack:
124115144b0fSOlivier Houchard     return roundAndPackFloat32( 0, zExp, zSig );
124215144b0fSOlivier Houchard 
124315144b0fSOlivier Houchard }
124415144b0fSOlivier Houchard #endif
124515144b0fSOlivier Houchard 
124615144b0fSOlivier Houchard /*
124715144b0fSOlivier Houchard -------------------------------------------------------------------------------
124815144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is equal to
124915144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The comparison is performed
125015144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
125115144b0fSOlivier Houchard -------------------------------------------------------------------------------
125215144b0fSOlivier Houchard */
float32_eq(float32 a,float32 b)125315144b0fSOlivier Houchard flag float32_eq( float32 a, float32 b )
125415144b0fSOlivier Houchard {
125515144b0fSOlivier Houchard 
125615144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
125715144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
125815144b0fSOlivier Houchard        ) {
125915144b0fSOlivier Houchard         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
126015144b0fSOlivier Houchard             float_raise( float_flag_invalid );
126115144b0fSOlivier Houchard         }
126215144b0fSOlivier Houchard         return 0;
126315144b0fSOlivier Houchard     }
126415144b0fSOlivier Houchard     return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
126515144b0fSOlivier Houchard 
126615144b0fSOlivier Houchard }
126715144b0fSOlivier Houchard 
126815144b0fSOlivier Houchard /*
126915144b0fSOlivier Houchard -------------------------------------------------------------------------------
127015144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is less than
127115144b0fSOlivier Houchard or equal to the corresponding value `b', and 0 otherwise.  The comparison
127215144b0fSOlivier Houchard is performed according to the IEC/IEEE Standard for Binary Floating-Point
127315144b0fSOlivier Houchard Arithmetic.
127415144b0fSOlivier Houchard -------------------------------------------------------------------------------
127515144b0fSOlivier Houchard */
float32_le(float32 a,float32 b)127615144b0fSOlivier Houchard flag float32_le( float32 a, float32 b )
127715144b0fSOlivier Houchard {
127815144b0fSOlivier Houchard     flag aSign, bSign;
127915144b0fSOlivier Houchard 
128015144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
128115144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
128215144b0fSOlivier Houchard        ) {
128315144b0fSOlivier Houchard         float_raise( float_flag_invalid );
128415144b0fSOlivier Houchard         return 0;
128515144b0fSOlivier Houchard     }
128615144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
128715144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
128815144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
128915144b0fSOlivier Houchard     return ( a == b ) || ( aSign ^ ( a < b ) );
129015144b0fSOlivier Houchard 
129115144b0fSOlivier Houchard }
129215144b0fSOlivier Houchard 
129315144b0fSOlivier Houchard /*
129415144b0fSOlivier Houchard -------------------------------------------------------------------------------
129515144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is less than
129615144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The comparison is performed
129715144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
129815144b0fSOlivier Houchard -------------------------------------------------------------------------------
129915144b0fSOlivier Houchard */
float32_lt(float32 a,float32 b)130015144b0fSOlivier Houchard flag float32_lt( float32 a, float32 b )
130115144b0fSOlivier Houchard {
130215144b0fSOlivier Houchard     flag aSign, bSign;
130315144b0fSOlivier Houchard 
130415144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
130515144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
130615144b0fSOlivier Houchard        ) {
130715144b0fSOlivier Houchard         float_raise( float_flag_invalid );
130815144b0fSOlivier Houchard         return 0;
130915144b0fSOlivier Houchard     }
131015144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
131115144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
131215144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
131315144b0fSOlivier Houchard     return ( a != b ) && ( aSign ^ ( a < b ) );
131415144b0fSOlivier Houchard 
131515144b0fSOlivier Houchard }
131615144b0fSOlivier Houchard 
131715144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC /* Not needed */
131815144b0fSOlivier Houchard /*
131915144b0fSOlivier Houchard -------------------------------------------------------------------------------
132015144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is equal to
132115144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The invalid exception is
132215144b0fSOlivier Houchard raised if either operand is a NaN.  Otherwise, the comparison is performed
132315144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
132415144b0fSOlivier Houchard -------------------------------------------------------------------------------
132515144b0fSOlivier Houchard */
float32_eq_signaling(float32 a,float32 b)132615144b0fSOlivier Houchard flag float32_eq_signaling( float32 a, float32 b )
132715144b0fSOlivier Houchard {
132815144b0fSOlivier Houchard 
132915144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
133015144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
133115144b0fSOlivier Houchard        ) {
133215144b0fSOlivier Houchard         float_raise( float_flag_invalid );
133315144b0fSOlivier Houchard         return 0;
133415144b0fSOlivier Houchard     }
133515144b0fSOlivier Houchard     return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
133615144b0fSOlivier Houchard 
133715144b0fSOlivier Houchard }
133815144b0fSOlivier Houchard 
133915144b0fSOlivier Houchard /*
134015144b0fSOlivier Houchard -------------------------------------------------------------------------------
134115144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is less than or
134215144b0fSOlivier Houchard equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
134315144b0fSOlivier Houchard cause an exception.  Otherwise, the comparison is performed according to the
134415144b0fSOlivier Houchard IEC/IEEE Standard for Binary Floating-Point Arithmetic.
134515144b0fSOlivier Houchard -------------------------------------------------------------------------------
134615144b0fSOlivier Houchard */
float32_le_quiet(float32 a,float32 b)134715144b0fSOlivier Houchard flag float32_le_quiet( float32 a, float32 b )
134815144b0fSOlivier Houchard {
134915144b0fSOlivier Houchard     flag aSign, bSign;
135015144b0fSOlivier Houchard     int16 aExp, bExp;
135115144b0fSOlivier Houchard 
135215144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
135315144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
135415144b0fSOlivier Houchard        ) {
135515144b0fSOlivier Houchard         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
135615144b0fSOlivier Houchard             float_raise( float_flag_invalid );
135715144b0fSOlivier Houchard         }
135815144b0fSOlivier Houchard         return 0;
135915144b0fSOlivier Houchard     }
136015144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
136115144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
136215144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
136315144b0fSOlivier Houchard     return ( a == b ) || ( aSign ^ ( a < b ) );
136415144b0fSOlivier Houchard 
136515144b0fSOlivier Houchard }
136615144b0fSOlivier Houchard 
136715144b0fSOlivier Houchard /*
136815144b0fSOlivier Houchard -------------------------------------------------------------------------------
136915144b0fSOlivier Houchard Returns 1 if the single-precision floating-point value `a' is less than
137015144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
137115144b0fSOlivier Houchard exception.  Otherwise, the comparison is performed according to the IEC/IEEE
137215144b0fSOlivier Houchard Standard for Binary Floating-Point Arithmetic.
137315144b0fSOlivier Houchard -------------------------------------------------------------------------------
137415144b0fSOlivier Houchard */
float32_lt_quiet(float32 a,float32 b)137515144b0fSOlivier Houchard flag float32_lt_quiet( float32 a, float32 b )
137615144b0fSOlivier Houchard {
137715144b0fSOlivier Houchard     flag aSign, bSign;
137815144b0fSOlivier Houchard 
137915144b0fSOlivier Houchard     if (    ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
138015144b0fSOlivier Houchard          || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
138115144b0fSOlivier Houchard        ) {
138215144b0fSOlivier Houchard         if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
138315144b0fSOlivier Houchard             float_raise( float_flag_invalid );
138415144b0fSOlivier Houchard         }
138515144b0fSOlivier Houchard         return 0;
138615144b0fSOlivier Houchard     }
138715144b0fSOlivier Houchard     aSign = extractFloat32Sign( a );
138815144b0fSOlivier Houchard     bSign = extractFloat32Sign( b );
138915144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
139015144b0fSOlivier Houchard     return ( a != b ) && ( aSign ^ ( a < b ) );
139115144b0fSOlivier Houchard 
139215144b0fSOlivier Houchard }
139315144b0fSOlivier Houchard #endif /* !SOFTFLOAT_FOR_GCC */
139415144b0fSOlivier Houchard 
139515144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC /* Not needed */
139615144b0fSOlivier Houchard /*
139715144b0fSOlivier Houchard -------------------------------------------------------------------------------
139815144b0fSOlivier Houchard Returns the result of converting the double-precision floating-point value
139915144b0fSOlivier Houchard `a' to the 32-bit two's complement integer format.  The conversion is
140015144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
140115144b0fSOlivier Houchard Arithmetic---which means in particular that the conversion is rounded
140215144b0fSOlivier Houchard according to the current rounding mode.  If `a' is a NaN, the largest
140315144b0fSOlivier Houchard positive integer is returned.  Otherwise, if the conversion overflows, the
140415144b0fSOlivier Houchard largest integer with the same sign as `a' is returned.
140515144b0fSOlivier Houchard -------------------------------------------------------------------------------
140615144b0fSOlivier Houchard */
float64_to_int32(float64 a)140715144b0fSOlivier Houchard int32 float64_to_int32( float64 a )
140815144b0fSOlivier Houchard {
140915144b0fSOlivier Houchard     flag aSign;
141015144b0fSOlivier Houchard     int16 aExp, shiftCount;
141115144b0fSOlivier Houchard     bits32 aSig0, aSig1, absZ, aSigExtra;
141215144b0fSOlivier Houchard     int32 z;
141315144b0fSOlivier Houchard     int8 roundingMode;
141415144b0fSOlivier Houchard 
141515144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
141615144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
141715144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
141815144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
141915144b0fSOlivier Houchard     shiftCount = aExp - 0x413;
142015144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
142115144b0fSOlivier Houchard         if ( 0x41E < aExp ) {
142215144b0fSOlivier Houchard             if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;
142315144b0fSOlivier Houchard             goto invalid;
142415144b0fSOlivier Houchard         }
142515144b0fSOlivier Houchard         shortShift64Left(
142615144b0fSOlivier Houchard             aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );
142715144b0fSOlivier Houchard         if ( 0x80000000 < absZ ) goto invalid;
142815144b0fSOlivier Houchard     }
142915144b0fSOlivier Houchard     else {
143015144b0fSOlivier Houchard         aSig1 = ( aSig1 != 0 );
143115144b0fSOlivier Houchard         if ( aExp < 0x3FE ) {
143215144b0fSOlivier Houchard             aSigExtra = aExp | aSig0 | aSig1;
143315144b0fSOlivier Houchard             absZ = 0;
143415144b0fSOlivier Houchard         }
143515144b0fSOlivier Houchard         else {
143615144b0fSOlivier Houchard             aSig0 |= 0x00100000;
143715144b0fSOlivier Houchard             aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;
143815144b0fSOlivier Houchard             absZ = aSig0>>( - shiftCount );
143915144b0fSOlivier Houchard         }
144015144b0fSOlivier Houchard     }
144115144b0fSOlivier Houchard     roundingMode = float_rounding_mode;
144215144b0fSOlivier Houchard     if ( roundingMode == float_round_nearest_even ) {
144315144b0fSOlivier Houchard         if ( (sbits32) aSigExtra < 0 ) {
144415144b0fSOlivier Houchard             ++absZ;
144515144b0fSOlivier Houchard             if ( (bits32) ( aSigExtra<<1 ) == 0 ) absZ &= ~1;
144615144b0fSOlivier Houchard         }
144715144b0fSOlivier Houchard         z = aSign ? - absZ : absZ;
144815144b0fSOlivier Houchard     }
144915144b0fSOlivier Houchard     else {
145015144b0fSOlivier Houchard         aSigExtra = ( aSigExtra != 0 );
145115144b0fSOlivier Houchard         if ( aSign ) {
145215144b0fSOlivier Houchard             z = - (   absZ
145315144b0fSOlivier Houchard                     + ( ( roundingMode == float_round_down ) & aSigExtra ) );
145415144b0fSOlivier Houchard         }
145515144b0fSOlivier Houchard         else {
145615144b0fSOlivier Houchard             z = absZ + ( ( roundingMode == float_round_up ) & aSigExtra );
145715144b0fSOlivier Houchard         }
145815144b0fSOlivier Houchard     }
145915144b0fSOlivier Houchard     if ( ( aSign ^ ( z < 0 ) ) && z ) {
146015144b0fSOlivier Houchard  invalid:
146115144b0fSOlivier Houchard         float_raise( float_flag_invalid );
146215144b0fSOlivier Houchard         return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
146315144b0fSOlivier Houchard     }
146415144b0fSOlivier Houchard     if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
146515144b0fSOlivier Houchard     return z;
146615144b0fSOlivier Houchard 
146715144b0fSOlivier Houchard }
146815144b0fSOlivier Houchard #endif /* !SOFTFLOAT_FOR_GCC */
146915144b0fSOlivier Houchard 
147015144b0fSOlivier Houchard /*
147115144b0fSOlivier Houchard -------------------------------------------------------------------------------
147215144b0fSOlivier Houchard Returns the result of converting the double-precision floating-point value
147315144b0fSOlivier Houchard `a' to the 32-bit two's complement integer format.  The conversion is
147415144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
147515144b0fSOlivier Houchard Arithmetic, except that the conversion is always rounded toward zero.
147615144b0fSOlivier Houchard If `a' is a NaN, the largest positive integer is returned.  Otherwise, if
147715144b0fSOlivier Houchard the conversion overflows, the largest integer with the same sign as `a' is
147815144b0fSOlivier Houchard returned.
147915144b0fSOlivier Houchard -------------------------------------------------------------------------------
148015144b0fSOlivier Houchard */
float64_to_int32_round_to_zero(float64 a)148115144b0fSOlivier Houchard int32 float64_to_int32_round_to_zero( float64 a )
148215144b0fSOlivier Houchard {
148315144b0fSOlivier Houchard     flag aSign;
148415144b0fSOlivier Houchard     int16 aExp, shiftCount;
148515144b0fSOlivier Houchard     bits32 aSig0, aSig1, absZ, aSigExtra;
148615144b0fSOlivier Houchard     int32 z;
148715144b0fSOlivier Houchard 
148815144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
148915144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
149015144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
149115144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
149215144b0fSOlivier Houchard     shiftCount = aExp - 0x413;
149315144b0fSOlivier Houchard     if ( 0 <= shiftCount ) {
149415144b0fSOlivier Houchard         if ( 0x41E < aExp ) {
149515144b0fSOlivier Houchard             if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;
149615144b0fSOlivier Houchard             goto invalid;
149715144b0fSOlivier Houchard         }
149815144b0fSOlivier Houchard         shortShift64Left(
149915144b0fSOlivier Houchard             aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );
150015144b0fSOlivier Houchard     }
150115144b0fSOlivier Houchard     else {
150215144b0fSOlivier Houchard         if ( aExp < 0x3FF ) {
150315144b0fSOlivier Houchard             if ( aExp | aSig0 | aSig1 ) {
150415144b0fSOlivier Houchard                 float_exception_flags |= float_flag_inexact;
150515144b0fSOlivier Houchard             }
150615144b0fSOlivier Houchard             return 0;
150715144b0fSOlivier Houchard         }
150815144b0fSOlivier Houchard         aSig0 |= 0x00100000;
150915144b0fSOlivier Houchard         aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;
151015144b0fSOlivier Houchard         absZ = aSig0>>( - shiftCount );
151115144b0fSOlivier Houchard     }
151215144b0fSOlivier Houchard     z = aSign ? - absZ : absZ;
151315144b0fSOlivier Houchard     if ( ( aSign ^ ( z < 0 ) ) && z ) {
151415144b0fSOlivier Houchard  invalid:
151515144b0fSOlivier Houchard         float_raise( float_flag_invalid );
151615144b0fSOlivier Houchard         return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
151715144b0fSOlivier Houchard     }
151815144b0fSOlivier Houchard     if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
151915144b0fSOlivier Houchard     return z;
152015144b0fSOlivier Houchard 
152115144b0fSOlivier Houchard }
152215144b0fSOlivier Houchard 
152315144b0fSOlivier Houchard /*
152415144b0fSOlivier Houchard -------------------------------------------------------------------------------
152515144b0fSOlivier Houchard Returns the result of converting the double-precision floating-point value
152615144b0fSOlivier Houchard `a' to the single-precision floating-point format.  The conversion is
152715144b0fSOlivier Houchard performed according to the IEC/IEEE Standard for Binary Floating-Point
152815144b0fSOlivier Houchard Arithmetic.
152915144b0fSOlivier Houchard -------------------------------------------------------------------------------
153015144b0fSOlivier Houchard */
float64_to_float32(float64 a)153115144b0fSOlivier Houchard float32 float64_to_float32( float64 a )
153215144b0fSOlivier Houchard {
153315144b0fSOlivier Houchard     flag aSign;
153415144b0fSOlivier Houchard     int16 aExp;
153515144b0fSOlivier Houchard     bits32 aSig0, aSig1, zSig;
153615144b0fSOlivier Houchard     bits32 allZero;
153715144b0fSOlivier Houchard 
153815144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
153915144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
154015144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
154115144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
154215144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
154315144b0fSOlivier Houchard         if ( aSig0 | aSig1 ) {
154415144b0fSOlivier Houchard             return commonNaNToFloat32( float64ToCommonNaN( a ) );
154515144b0fSOlivier Houchard         }
154615144b0fSOlivier Houchard         return packFloat32( aSign, 0xFF, 0 );
154715144b0fSOlivier Houchard     }
154815144b0fSOlivier Houchard     shift64RightJamming( aSig0, aSig1, 22, &allZero, &zSig );
154915144b0fSOlivier Houchard     if ( aExp ) zSig |= 0x40000000;
155015144b0fSOlivier Houchard     return roundAndPackFloat32( aSign, aExp - 0x381, zSig );
155115144b0fSOlivier Houchard 
155215144b0fSOlivier Houchard }
155315144b0fSOlivier Houchard 
155415144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
155515144b0fSOlivier Houchard /*
155615144b0fSOlivier Houchard -------------------------------------------------------------------------------
155715144b0fSOlivier Houchard Rounds the double-precision floating-point value `a' to an integer,
155815144b0fSOlivier Houchard and returns the result as a double-precision floating-point value.  The
155915144b0fSOlivier Houchard operation is performed according to the IEC/IEEE Standard for Binary
156015144b0fSOlivier Houchard Floating-Point Arithmetic.
156115144b0fSOlivier Houchard -------------------------------------------------------------------------------
156215144b0fSOlivier Houchard */
float64_round_to_int(float64 a)156315144b0fSOlivier Houchard float64 float64_round_to_int( float64 a )
156415144b0fSOlivier Houchard {
156515144b0fSOlivier Houchard     flag aSign;
156615144b0fSOlivier Houchard     int16 aExp;
156715144b0fSOlivier Houchard     bits32 lastBitMask, roundBitsMask;
156815144b0fSOlivier Houchard     int8 roundingMode;
156915144b0fSOlivier Houchard     float64 z;
157015144b0fSOlivier Houchard 
157115144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
157215144b0fSOlivier Houchard     if ( 0x413 <= aExp ) {
157315144b0fSOlivier Houchard         if ( 0x433 <= aExp ) {
157415144b0fSOlivier Houchard             if (    ( aExp == 0x7FF )
157515144b0fSOlivier Houchard                  && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) ) {
157615144b0fSOlivier Houchard                 return propagateFloat64NaN( a, a );
157715144b0fSOlivier Houchard             }
157815144b0fSOlivier Houchard             return a;
157915144b0fSOlivier Houchard         }
158015144b0fSOlivier Houchard         lastBitMask = 1;
158115144b0fSOlivier Houchard         lastBitMask = ( lastBitMask<<( 0x432 - aExp ) )<<1;
158215144b0fSOlivier Houchard         roundBitsMask = lastBitMask - 1;
158315144b0fSOlivier Houchard         z = a;
158415144b0fSOlivier Houchard         roundingMode = float_rounding_mode;
158515144b0fSOlivier Houchard         if ( roundingMode == float_round_nearest_even ) {
158615144b0fSOlivier Houchard             if ( lastBitMask ) {
158715144b0fSOlivier Houchard                 add64( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
158815144b0fSOlivier Houchard                 if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
158915144b0fSOlivier Houchard             }
159015144b0fSOlivier Houchard             else {
159115144b0fSOlivier Houchard                 if ( (sbits32) z.low < 0 ) {
159215144b0fSOlivier Houchard                     ++z.high;
159315144b0fSOlivier Houchard                     if ( (bits32) ( z.low<<1 ) == 0 ) z.high &= ~1;
159415144b0fSOlivier Houchard                 }
159515144b0fSOlivier Houchard             }
159615144b0fSOlivier Houchard         }
159715144b0fSOlivier Houchard         else if ( roundingMode != float_round_to_zero ) {
159815144b0fSOlivier Houchard             if (   extractFloat64Sign( z )
159915144b0fSOlivier Houchard                  ^ ( roundingMode == float_round_up ) ) {
160015144b0fSOlivier Houchard                 add64( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
160115144b0fSOlivier Houchard             }
160215144b0fSOlivier Houchard         }
160315144b0fSOlivier Houchard         z.low &= ~ roundBitsMask;
160415144b0fSOlivier Houchard     }
160515144b0fSOlivier Houchard     else {
160615144b0fSOlivier Houchard         if ( aExp <= 0x3FE ) {
160715144b0fSOlivier Houchard             if ( ( ( (bits32) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
160815144b0fSOlivier Houchard             float_exception_flags |= float_flag_inexact;
160915144b0fSOlivier Houchard             aSign = extractFloat64Sign( a );
161015144b0fSOlivier Houchard             switch ( float_rounding_mode ) {
161115144b0fSOlivier Houchard              case float_round_nearest_even:
161215144b0fSOlivier Houchard                 if (    ( aExp == 0x3FE )
161315144b0fSOlivier Houchard                      && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) )
161415144b0fSOlivier Houchard                    ) {
161515144b0fSOlivier Houchard                     return packFloat64( aSign, 0x3FF, 0, 0 );
161615144b0fSOlivier Houchard                 }
161715144b0fSOlivier Houchard                 break;
161815144b0fSOlivier Houchard              case float_round_down:
161915144b0fSOlivier Houchard                 return
162015144b0fSOlivier Houchard                       aSign ? packFloat64( 1, 0x3FF, 0, 0 )
162115144b0fSOlivier Houchard                     : packFloat64( 0, 0, 0, 0 );
162215144b0fSOlivier Houchard              case float_round_up:
162315144b0fSOlivier Houchard                 return
162415144b0fSOlivier Houchard                       aSign ? packFloat64( 1, 0, 0, 0 )
162515144b0fSOlivier Houchard                     : packFloat64( 0, 0x3FF, 0, 0 );
162615144b0fSOlivier Houchard             }
162715144b0fSOlivier Houchard             return packFloat64( aSign, 0, 0, 0 );
162815144b0fSOlivier Houchard         }
162915144b0fSOlivier Houchard         lastBitMask = 1;
163015144b0fSOlivier Houchard         lastBitMask <<= 0x413 - aExp;
163115144b0fSOlivier Houchard         roundBitsMask = lastBitMask - 1;
163215144b0fSOlivier Houchard         z.low = 0;
163315144b0fSOlivier Houchard         z.high = a.high;
163415144b0fSOlivier Houchard         roundingMode = float_rounding_mode;
163515144b0fSOlivier Houchard         if ( roundingMode == float_round_nearest_even ) {
163615144b0fSOlivier Houchard             z.high += lastBitMask>>1;
163715144b0fSOlivier Houchard             if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
163815144b0fSOlivier Houchard                 z.high &= ~ lastBitMask;
163915144b0fSOlivier Houchard             }
164015144b0fSOlivier Houchard         }
164115144b0fSOlivier Houchard         else if ( roundingMode != float_round_to_zero ) {
164215144b0fSOlivier Houchard             if (   extractFloat64Sign( z )
164315144b0fSOlivier Houchard                  ^ ( roundingMode == float_round_up ) ) {
164415144b0fSOlivier Houchard                 z.high |= ( a.low != 0 );
164515144b0fSOlivier Houchard                 z.high += roundBitsMask;
164615144b0fSOlivier Houchard             }
164715144b0fSOlivier Houchard         }
164815144b0fSOlivier Houchard         z.high &= ~ roundBitsMask;
164915144b0fSOlivier Houchard     }
165015144b0fSOlivier Houchard     if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
165115144b0fSOlivier Houchard         float_exception_flags |= float_flag_inexact;
165215144b0fSOlivier Houchard     }
165315144b0fSOlivier Houchard     return z;
165415144b0fSOlivier Houchard 
165515144b0fSOlivier Houchard }
165615144b0fSOlivier Houchard #endif
165715144b0fSOlivier Houchard 
165815144b0fSOlivier Houchard /*
165915144b0fSOlivier Houchard -------------------------------------------------------------------------------
166015144b0fSOlivier Houchard Returns the result of adding the absolute values of the double-precision
166115144b0fSOlivier Houchard floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
166215144b0fSOlivier Houchard before being returned.  `zSign' is ignored if the result is a NaN.
166315144b0fSOlivier Houchard The addition is performed according to the IEC/IEEE Standard for Binary
166415144b0fSOlivier Houchard Floating-Point Arithmetic.
166515144b0fSOlivier Houchard -------------------------------------------------------------------------------
166615144b0fSOlivier Houchard */
addFloat64Sigs(float64 a,float64 b,flag zSign)166715144b0fSOlivier Houchard static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
166815144b0fSOlivier Houchard {
166915144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
167015144b0fSOlivier Houchard     bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
167115144b0fSOlivier Houchard     int16 expDiff;
167215144b0fSOlivier Houchard 
167315144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
167415144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
167515144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
167615144b0fSOlivier Houchard     bSig1 = extractFloat64Frac1( b );
167715144b0fSOlivier Houchard     bSig0 = extractFloat64Frac0( b );
167815144b0fSOlivier Houchard     bExp = extractFloat64Exp( b );
167915144b0fSOlivier Houchard     expDiff = aExp - bExp;
168015144b0fSOlivier Houchard     if ( 0 < expDiff ) {
168115144b0fSOlivier Houchard         if ( aExp == 0x7FF ) {
168215144b0fSOlivier Houchard             if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
168315144b0fSOlivier Houchard             return a;
168415144b0fSOlivier Houchard         }
168515144b0fSOlivier Houchard         if ( bExp == 0 ) {
168615144b0fSOlivier Houchard             --expDiff;
168715144b0fSOlivier Houchard         }
168815144b0fSOlivier Houchard         else {
168915144b0fSOlivier Houchard             bSig0 |= 0x00100000;
169015144b0fSOlivier Houchard         }
169115144b0fSOlivier Houchard         shift64ExtraRightJamming(
169215144b0fSOlivier Houchard             bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
169315144b0fSOlivier Houchard         zExp = aExp;
169415144b0fSOlivier Houchard     }
169515144b0fSOlivier Houchard     else if ( expDiff < 0 ) {
169615144b0fSOlivier Houchard         if ( bExp == 0x7FF ) {
169715144b0fSOlivier Houchard             if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
169815144b0fSOlivier Houchard             return packFloat64( zSign, 0x7FF, 0, 0 );
169915144b0fSOlivier Houchard         }
170015144b0fSOlivier Houchard         if ( aExp == 0 ) {
170115144b0fSOlivier Houchard             ++expDiff;
170215144b0fSOlivier Houchard         }
170315144b0fSOlivier Houchard         else {
170415144b0fSOlivier Houchard             aSig0 |= 0x00100000;
170515144b0fSOlivier Houchard         }
170615144b0fSOlivier Houchard         shift64ExtraRightJamming(
170715144b0fSOlivier Houchard             aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
170815144b0fSOlivier Houchard         zExp = bExp;
170915144b0fSOlivier Houchard     }
171015144b0fSOlivier Houchard     else {
171115144b0fSOlivier Houchard         if ( aExp == 0x7FF ) {
171215144b0fSOlivier Houchard             if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
171315144b0fSOlivier Houchard                 return propagateFloat64NaN( a, b );
171415144b0fSOlivier Houchard             }
171515144b0fSOlivier Houchard             return a;
171615144b0fSOlivier Houchard         }
171715144b0fSOlivier Houchard         add64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
171815144b0fSOlivier Houchard         if ( aExp == 0 ) return packFloat64( zSign, 0, zSig0, zSig1 );
171915144b0fSOlivier Houchard         zSig2 = 0;
172015144b0fSOlivier Houchard         zSig0 |= 0x00200000;
172115144b0fSOlivier Houchard         zExp = aExp;
172215144b0fSOlivier Houchard         goto shiftRight1;
172315144b0fSOlivier Houchard     }
172415144b0fSOlivier Houchard     aSig0 |= 0x00100000;
172515144b0fSOlivier Houchard     add64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
172615144b0fSOlivier Houchard     --zExp;
172715144b0fSOlivier Houchard     if ( zSig0 < 0x00200000 ) goto roundAndPack;
172815144b0fSOlivier Houchard     ++zExp;
172915144b0fSOlivier Houchard  shiftRight1:
173015144b0fSOlivier Houchard     shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
173115144b0fSOlivier Houchard  roundAndPack:
173215144b0fSOlivier Houchard     return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
173315144b0fSOlivier Houchard 
173415144b0fSOlivier Houchard }
173515144b0fSOlivier Houchard 
173615144b0fSOlivier Houchard /*
173715144b0fSOlivier Houchard -------------------------------------------------------------------------------
173815144b0fSOlivier Houchard Returns the result of subtracting the absolute values of the double-
173915144b0fSOlivier Houchard precision floating-point values `a' and `b'.  If `zSign' is 1, the
174015144b0fSOlivier Houchard difference is negated before being returned.  `zSign' is ignored if the
174115144b0fSOlivier Houchard result is a NaN.  The subtraction is performed according to the IEC/IEEE
174215144b0fSOlivier Houchard Standard for Binary Floating-Point Arithmetic.
174315144b0fSOlivier Houchard -------------------------------------------------------------------------------
174415144b0fSOlivier Houchard */
subFloat64Sigs(float64 a,float64 b,flag zSign)174515144b0fSOlivier Houchard static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
174615144b0fSOlivier Houchard {
174715144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
174815144b0fSOlivier Houchard     bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
174915144b0fSOlivier Houchard     int16 expDiff;
175015144b0fSOlivier Houchard 
175115144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
175215144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
175315144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
175415144b0fSOlivier Houchard     bSig1 = extractFloat64Frac1( b );
175515144b0fSOlivier Houchard     bSig0 = extractFloat64Frac0( b );
175615144b0fSOlivier Houchard     bExp = extractFloat64Exp( b );
175715144b0fSOlivier Houchard     expDiff = aExp - bExp;
175815144b0fSOlivier Houchard     shortShift64Left( aSig0, aSig1, 10, &aSig0, &aSig1 );
175915144b0fSOlivier Houchard     shortShift64Left( bSig0, bSig1, 10, &bSig0, &bSig1 );
176015144b0fSOlivier Houchard     if ( 0 < expDiff ) goto aExpBigger;
176115144b0fSOlivier Houchard     if ( expDiff < 0 ) goto bExpBigger;
176215144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
176315144b0fSOlivier Houchard         if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
176415144b0fSOlivier Houchard             return propagateFloat64NaN( a, b );
176515144b0fSOlivier Houchard         }
176615144b0fSOlivier Houchard         float_raise( float_flag_invalid );
176715144b0fSOlivier Houchard         return float64_default_nan;
176815144b0fSOlivier Houchard     }
176915144b0fSOlivier Houchard     if ( aExp == 0 ) {
177015144b0fSOlivier Houchard         aExp = 1;
177115144b0fSOlivier Houchard         bExp = 1;
177215144b0fSOlivier Houchard     }
177315144b0fSOlivier Houchard     if ( bSig0 < aSig0 ) goto aBigger;
177415144b0fSOlivier Houchard     if ( aSig0 < bSig0 ) goto bBigger;
177515144b0fSOlivier Houchard     if ( bSig1 < aSig1 ) goto aBigger;
177615144b0fSOlivier Houchard     if ( aSig1 < bSig1 ) goto bBigger;
177715144b0fSOlivier Houchard     return packFloat64( float_rounding_mode == float_round_down, 0, 0, 0 );
177815144b0fSOlivier Houchard  bExpBigger:
177915144b0fSOlivier Houchard     if ( bExp == 0x7FF ) {
178015144b0fSOlivier Houchard         if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
178115144b0fSOlivier Houchard         return packFloat64( zSign ^ 1, 0x7FF, 0, 0 );
178215144b0fSOlivier Houchard     }
178315144b0fSOlivier Houchard     if ( aExp == 0 ) {
178415144b0fSOlivier Houchard         ++expDiff;
178515144b0fSOlivier Houchard     }
178615144b0fSOlivier Houchard     else {
178715144b0fSOlivier Houchard         aSig0 |= 0x40000000;
178815144b0fSOlivier Houchard     }
178915144b0fSOlivier Houchard     shift64RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
179015144b0fSOlivier Houchard     bSig0 |= 0x40000000;
179115144b0fSOlivier Houchard  bBigger:
179215144b0fSOlivier Houchard     sub64( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
179315144b0fSOlivier Houchard     zExp = bExp;
179415144b0fSOlivier Houchard     zSign ^= 1;
179515144b0fSOlivier Houchard     goto normalizeRoundAndPack;
179615144b0fSOlivier Houchard  aExpBigger:
179715144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
179815144b0fSOlivier Houchard         if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
179915144b0fSOlivier Houchard         return a;
180015144b0fSOlivier Houchard     }
180115144b0fSOlivier Houchard     if ( bExp == 0 ) {
180215144b0fSOlivier Houchard         --expDiff;
180315144b0fSOlivier Houchard     }
180415144b0fSOlivier Houchard     else {
180515144b0fSOlivier Houchard         bSig0 |= 0x40000000;
180615144b0fSOlivier Houchard     }
180715144b0fSOlivier Houchard     shift64RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
180815144b0fSOlivier Houchard     aSig0 |= 0x40000000;
180915144b0fSOlivier Houchard  aBigger:
181015144b0fSOlivier Houchard     sub64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
181115144b0fSOlivier Houchard     zExp = aExp;
181215144b0fSOlivier Houchard  normalizeRoundAndPack:
181315144b0fSOlivier Houchard     --zExp;
181415144b0fSOlivier Houchard     return normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1 );
181515144b0fSOlivier Houchard 
181615144b0fSOlivier Houchard }
181715144b0fSOlivier Houchard 
181815144b0fSOlivier Houchard /*
181915144b0fSOlivier Houchard -------------------------------------------------------------------------------
182015144b0fSOlivier Houchard Returns the result of adding the double-precision floating-point values `a'
182115144b0fSOlivier Houchard and `b'.  The operation is performed according to the IEC/IEEE Standard for
182215144b0fSOlivier Houchard Binary Floating-Point Arithmetic.
182315144b0fSOlivier Houchard -------------------------------------------------------------------------------
182415144b0fSOlivier Houchard */
float64_add(float64 a,float64 b)182515144b0fSOlivier Houchard float64 float64_add( float64 a, float64 b )
182615144b0fSOlivier Houchard {
182715144b0fSOlivier Houchard     flag aSign, bSign;
182815144b0fSOlivier Houchard 
182915144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
183015144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
183115144b0fSOlivier Houchard     if ( aSign == bSign ) {
183215144b0fSOlivier Houchard         return addFloat64Sigs( a, b, aSign );
183315144b0fSOlivier Houchard     }
183415144b0fSOlivier Houchard     else {
183515144b0fSOlivier Houchard         return subFloat64Sigs( a, b, aSign );
183615144b0fSOlivier Houchard     }
183715144b0fSOlivier Houchard 
183815144b0fSOlivier Houchard }
183915144b0fSOlivier Houchard 
184015144b0fSOlivier Houchard /*
184115144b0fSOlivier Houchard -------------------------------------------------------------------------------
184215144b0fSOlivier Houchard Returns the result of subtracting the double-precision floating-point values
184315144b0fSOlivier Houchard `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
184415144b0fSOlivier Houchard for Binary Floating-Point Arithmetic.
184515144b0fSOlivier Houchard -------------------------------------------------------------------------------
184615144b0fSOlivier Houchard */
float64_sub(float64 a,float64 b)184715144b0fSOlivier Houchard float64 float64_sub( float64 a, float64 b )
184815144b0fSOlivier Houchard {
184915144b0fSOlivier Houchard     flag aSign, bSign;
185015144b0fSOlivier Houchard 
185115144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
185215144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
185315144b0fSOlivier Houchard     if ( aSign == bSign ) {
185415144b0fSOlivier Houchard         return subFloat64Sigs( a, b, aSign );
185515144b0fSOlivier Houchard     }
185615144b0fSOlivier Houchard     else {
185715144b0fSOlivier Houchard         return addFloat64Sigs( a, b, aSign );
185815144b0fSOlivier Houchard     }
185915144b0fSOlivier Houchard 
186015144b0fSOlivier Houchard }
186115144b0fSOlivier Houchard 
186215144b0fSOlivier Houchard /*
186315144b0fSOlivier Houchard -------------------------------------------------------------------------------
186415144b0fSOlivier Houchard Returns the result of multiplying the double-precision floating-point values
186515144b0fSOlivier Houchard `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
186615144b0fSOlivier Houchard for Binary Floating-Point Arithmetic.
186715144b0fSOlivier Houchard -------------------------------------------------------------------------------
186815144b0fSOlivier Houchard */
float64_mul(float64 a,float64 b)186915144b0fSOlivier Houchard float64 float64_mul( float64 a, float64 b )
187015144b0fSOlivier Houchard {
187115144b0fSOlivier Houchard     flag aSign, bSign, zSign;
187215144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
187315144b0fSOlivier Houchard     bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
187415144b0fSOlivier Houchard 
187515144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
187615144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
187715144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
187815144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
187915144b0fSOlivier Houchard     bSig1 = extractFloat64Frac1( b );
188015144b0fSOlivier Houchard     bSig0 = extractFloat64Frac0( b );
188115144b0fSOlivier Houchard     bExp = extractFloat64Exp( b );
188215144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
188315144b0fSOlivier Houchard     zSign = aSign ^ bSign;
188415144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
188515144b0fSOlivier Houchard         if (    ( aSig0 | aSig1 )
188615144b0fSOlivier Houchard              || ( ( bExp == 0x7FF ) && ( bSig0 | bSig1 ) ) ) {
188715144b0fSOlivier Houchard             return propagateFloat64NaN( a, b );
188815144b0fSOlivier Houchard         }
188915144b0fSOlivier Houchard         if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
189015144b0fSOlivier Houchard         return packFloat64( zSign, 0x7FF, 0, 0 );
189115144b0fSOlivier Houchard     }
189215144b0fSOlivier Houchard     if ( bExp == 0x7FF ) {
189315144b0fSOlivier Houchard         if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
189415144b0fSOlivier Houchard         if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
189515144b0fSOlivier Houchard  invalid:
189615144b0fSOlivier Houchard             float_raise( float_flag_invalid );
189715144b0fSOlivier Houchard             return float64_default_nan;
189815144b0fSOlivier Houchard         }
189915144b0fSOlivier Houchard         return packFloat64( zSign, 0x7FF, 0, 0 );
190015144b0fSOlivier Houchard     }
190115144b0fSOlivier Houchard     if ( aExp == 0 ) {
190215144b0fSOlivier Houchard         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
190315144b0fSOlivier Houchard         normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
190415144b0fSOlivier Houchard     }
190515144b0fSOlivier Houchard     if ( bExp == 0 ) {
190615144b0fSOlivier Houchard         if ( ( bSig0 | bSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
190715144b0fSOlivier Houchard         normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
190815144b0fSOlivier Houchard     }
190915144b0fSOlivier Houchard     zExp = aExp + bExp - 0x400;
191015144b0fSOlivier Houchard     aSig0 |= 0x00100000;
191115144b0fSOlivier Houchard     shortShift64Left( bSig0, bSig1, 12, &bSig0, &bSig1 );
191215144b0fSOlivier Houchard     mul64To128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
191315144b0fSOlivier Houchard     add64( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
191415144b0fSOlivier Houchard     zSig2 |= ( zSig3 != 0 );
191515144b0fSOlivier Houchard     if ( 0x00200000 <= zSig0 ) {
191615144b0fSOlivier Houchard         shift64ExtraRightJamming(
191715144b0fSOlivier Houchard             zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
191815144b0fSOlivier Houchard         ++zExp;
191915144b0fSOlivier Houchard     }
192015144b0fSOlivier Houchard     return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
192115144b0fSOlivier Houchard 
192215144b0fSOlivier Houchard }
192315144b0fSOlivier Houchard 
192415144b0fSOlivier Houchard /*
192515144b0fSOlivier Houchard -------------------------------------------------------------------------------
192615144b0fSOlivier Houchard Returns the result of dividing the double-precision floating-point value `a'
192715144b0fSOlivier Houchard by the corresponding value `b'.  The operation is performed according to the
192815144b0fSOlivier Houchard IEC/IEEE Standard for Binary Floating-Point Arithmetic.
192915144b0fSOlivier Houchard -------------------------------------------------------------------------------
193015144b0fSOlivier Houchard */
float64_div(float64 a,float64 b)193115144b0fSOlivier Houchard float64 float64_div( float64 a, float64 b )
193215144b0fSOlivier Houchard {
193315144b0fSOlivier Houchard     flag aSign, bSign, zSign;
193415144b0fSOlivier Houchard     int16 aExp, bExp, zExp;
193515144b0fSOlivier Houchard     bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
193615144b0fSOlivier Houchard     bits32 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
193715144b0fSOlivier Houchard 
193815144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
193915144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
194015144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
194115144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
194215144b0fSOlivier Houchard     bSig1 = extractFloat64Frac1( b );
194315144b0fSOlivier Houchard     bSig0 = extractFloat64Frac0( b );
194415144b0fSOlivier Houchard     bExp = extractFloat64Exp( b );
194515144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
194615144b0fSOlivier Houchard     zSign = aSign ^ bSign;
194715144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
194815144b0fSOlivier Houchard         if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
194915144b0fSOlivier Houchard         if ( bExp == 0x7FF ) {
195015144b0fSOlivier Houchard             if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
195115144b0fSOlivier Houchard             goto invalid;
195215144b0fSOlivier Houchard         }
195315144b0fSOlivier Houchard         return packFloat64( zSign, 0x7FF, 0, 0 );
195415144b0fSOlivier Houchard     }
195515144b0fSOlivier Houchard     if ( bExp == 0x7FF ) {
195615144b0fSOlivier Houchard         if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
195715144b0fSOlivier Houchard         return packFloat64( zSign, 0, 0, 0 );
195815144b0fSOlivier Houchard     }
195915144b0fSOlivier Houchard     if ( bExp == 0 ) {
196015144b0fSOlivier Houchard         if ( ( bSig0 | bSig1 ) == 0 ) {
196115144b0fSOlivier Houchard             if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
196215144b0fSOlivier Houchard  invalid:
196315144b0fSOlivier Houchard                 float_raise( float_flag_invalid );
196415144b0fSOlivier Houchard                 return float64_default_nan;
196515144b0fSOlivier Houchard             }
196615144b0fSOlivier Houchard             float_raise( float_flag_divbyzero );
196715144b0fSOlivier Houchard             return packFloat64( zSign, 0x7FF, 0, 0 );
196815144b0fSOlivier Houchard         }
196915144b0fSOlivier Houchard         normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
197015144b0fSOlivier Houchard     }
197115144b0fSOlivier Houchard     if ( aExp == 0 ) {
197215144b0fSOlivier Houchard         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
197315144b0fSOlivier Houchard         normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
197415144b0fSOlivier Houchard     }
197515144b0fSOlivier Houchard     zExp = aExp - bExp + 0x3FD;
197615144b0fSOlivier Houchard     shortShift64Left( aSig0 | 0x00100000, aSig1, 11, &aSig0, &aSig1 );
197715144b0fSOlivier Houchard     shortShift64Left( bSig0 | 0x00100000, bSig1, 11, &bSig0, &bSig1 );
197815144b0fSOlivier Houchard     if ( le64( bSig0, bSig1, aSig0, aSig1 ) ) {
197915144b0fSOlivier Houchard         shift64Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
198015144b0fSOlivier Houchard         ++zExp;
198115144b0fSOlivier Houchard     }
198215144b0fSOlivier Houchard     zSig0 = estimateDiv64To32( aSig0, aSig1, bSig0 );
198315144b0fSOlivier Houchard     mul64By32To96( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
198415144b0fSOlivier Houchard     sub96( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
198515144b0fSOlivier Houchard     while ( (sbits32) rem0 < 0 ) {
198615144b0fSOlivier Houchard         --zSig0;
198715144b0fSOlivier Houchard         add96( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
198815144b0fSOlivier Houchard     }
198915144b0fSOlivier Houchard     zSig1 = estimateDiv64To32( rem1, rem2, bSig0 );
199015144b0fSOlivier Houchard     if ( ( zSig1 & 0x3FF ) <= 4 ) {
199115144b0fSOlivier Houchard         mul64By32To96( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
199215144b0fSOlivier Houchard         sub96( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
199315144b0fSOlivier Houchard         while ( (sbits32) rem1 < 0 ) {
199415144b0fSOlivier Houchard             --zSig1;
199515144b0fSOlivier Houchard             add96( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
199615144b0fSOlivier Houchard         }
199715144b0fSOlivier Houchard         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
199815144b0fSOlivier Houchard     }
199915144b0fSOlivier Houchard     shift64ExtraRightJamming( zSig0, zSig1, 0, 11, &zSig0, &zSig1, &zSig2 );
200015144b0fSOlivier Houchard     return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
200115144b0fSOlivier Houchard 
200215144b0fSOlivier Houchard }
200315144b0fSOlivier Houchard 
200415144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
200515144b0fSOlivier Houchard /*
200615144b0fSOlivier Houchard -------------------------------------------------------------------------------
200715144b0fSOlivier Houchard Returns the remainder of the double-precision floating-point value `a'
200815144b0fSOlivier Houchard with respect to the corresponding value `b'.  The operation is performed
200915144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
201015144b0fSOlivier Houchard -------------------------------------------------------------------------------
201115144b0fSOlivier Houchard */
float64_rem(float64 a,float64 b)201215144b0fSOlivier Houchard float64 float64_rem( float64 a, float64 b )
201315144b0fSOlivier Houchard {
201415144b0fSOlivier Houchard     flag aSign, bSign, zSign;
201515144b0fSOlivier Houchard     int16 aExp, bExp, expDiff;
201615144b0fSOlivier Houchard     bits32 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
201715144b0fSOlivier Houchard     bits32 allZero, alternateASig0, alternateASig1, sigMean1;
201815144b0fSOlivier Houchard     sbits32 sigMean0;
201915144b0fSOlivier Houchard     float64 z;
202015144b0fSOlivier Houchard 
202115144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
202215144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
202315144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
202415144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
202515144b0fSOlivier Houchard     bSig1 = extractFloat64Frac1( b );
202615144b0fSOlivier Houchard     bSig0 = extractFloat64Frac0( b );
202715144b0fSOlivier Houchard     bExp = extractFloat64Exp( b );
202815144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
202915144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
203015144b0fSOlivier Houchard         if (    ( aSig0 | aSig1 )
203115144b0fSOlivier Houchard              || ( ( bExp == 0x7FF ) && ( bSig0 | bSig1 ) ) ) {
203215144b0fSOlivier Houchard             return propagateFloat64NaN( a, b );
203315144b0fSOlivier Houchard         }
203415144b0fSOlivier Houchard         goto invalid;
203515144b0fSOlivier Houchard     }
203615144b0fSOlivier Houchard     if ( bExp == 0x7FF ) {
203715144b0fSOlivier Houchard         if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
203815144b0fSOlivier Houchard         return a;
203915144b0fSOlivier Houchard     }
204015144b0fSOlivier Houchard     if ( bExp == 0 ) {
204115144b0fSOlivier Houchard         if ( ( bSig0 | bSig1 ) == 0 ) {
204215144b0fSOlivier Houchard  invalid:
204315144b0fSOlivier Houchard             float_raise( float_flag_invalid );
204415144b0fSOlivier Houchard             return float64_default_nan;
204515144b0fSOlivier Houchard         }
204615144b0fSOlivier Houchard         normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
204715144b0fSOlivier Houchard     }
204815144b0fSOlivier Houchard     if ( aExp == 0 ) {
204915144b0fSOlivier Houchard         if ( ( aSig0 | aSig1 ) == 0 ) return a;
205015144b0fSOlivier Houchard         normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
205115144b0fSOlivier Houchard     }
205215144b0fSOlivier Houchard     expDiff = aExp - bExp;
205315144b0fSOlivier Houchard     if ( expDiff < -1 ) return a;
205415144b0fSOlivier Houchard     shortShift64Left(
205515144b0fSOlivier Houchard         aSig0 | 0x00100000, aSig1, 11 - ( expDiff < 0 ), &aSig0, &aSig1 );
205615144b0fSOlivier Houchard     shortShift64Left( bSig0 | 0x00100000, bSig1, 11, &bSig0, &bSig1 );
205715144b0fSOlivier Houchard     q = le64( bSig0, bSig1, aSig0, aSig1 );
205815144b0fSOlivier Houchard     if ( q ) sub64( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
205915144b0fSOlivier Houchard     expDiff -= 32;
206015144b0fSOlivier Houchard     while ( 0 < expDiff ) {
206115144b0fSOlivier Houchard         q = estimateDiv64To32( aSig0, aSig1, bSig0 );
206215144b0fSOlivier Houchard         q = ( 4 < q ) ? q - 4 : 0;
206315144b0fSOlivier Houchard         mul64By32To96( bSig0, bSig1, q, &term0, &term1, &term2 );
206415144b0fSOlivier Houchard         shortShift96Left( term0, term1, term2, 29, &term1, &term2, &allZero );
206515144b0fSOlivier Houchard         shortShift64Left( aSig0, aSig1, 29, &aSig0, &allZero );
206615144b0fSOlivier Houchard         sub64( aSig0, 0, term1, term2, &aSig0, &aSig1 );
206715144b0fSOlivier Houchard         expDiff -= 29;
206815144b0fSOlivier Houchard     }
206915144b0fSOlivier Houchard     if ( -32 < expDiff ) {
207015144b0fSOlivier Houchard         q = estimateDiv64To32( aSig0, aSig1, bSig0 );
207115144b0fSOlivier Houchard         q = ( 4 < q ) ? q - 4 : 0;
207215144b0fSOlivier Houchard         q >>= - expDiff;
207315144b0fSOlivier Houchard         shift64Right( bSig0, bSig1, 8, &bSig0, &bSig1 );
207415144b0fSOlivier Houchard         expDiff += 24;
207515144b0fSOlivier Houchard         if ( expDiff < 0 ) {
207615144b0fSOlivier Houchard             shift64Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
207715144b0fSOlivier Houchard         }
207815144b0fSOlivier Houchard         else {
207915144b0fSOlivier Houchard             shortShift64Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
208015144b0fSOlivier Houchard         }
208115144b0fSOlivier Houchard         mul64By32To96( bSig0, bSig1, q, &term0, &term1, &term2 );
208215144b0fSOlivier Houchard         sub64( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
208315144b0fSOlivier Houchard     }
208415144b0fSOlivier Houchard     else {
208515144b0fSOlivier Houchard         shift64Right( aSig0, aSig1, 8, &aSig0, &aSig1 );
208615144b0fSOlivier Houchard         shift64Right( bSig0, bSig1, 8, &bSig0, &bSig1 );
208715144b0fSOlivier Houchard     }
208815144b0fSOlivier Houchard     do {
208915144b0fSOlivier Houchard         alternateASig0 = aSig0;
209015144b0fSOlivier Houchard         alternateASig1 = aSig1;
209115144b0fSOlivier Houchard         ++q;
209215144b0fSOlivier Houchard         sub64( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
209315144b0fSOlivier Houchard     } while ( 0 <= (sbits32) aSig0 );
209415144b0fSOlivier Houchard     add64(
209515144b0fSOlivier Houchard         aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
209615144b0fSOlivier Houchard     if (    ( sigMean0 < 0 )
209715144b0fSOlivier Houchard          || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
209815144b0fSOlivier Houchard         aSig0 = alternateASig0;
209915144b0fSOlivier Houchard         aSig1 = alternateASig1;
210015144b0fSOlivier Houchard     }
210115144b0fSOlivier Houchard     zSign = ( (sbits32) aSig0 < 0 );
210215144b0fSOlivier Houchard     if ( zSign ) sub64( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
210315144b0fSOlivier Houchard     return
210415144b0fSOlivier Houchard         normalizeRoundAndPackFloat64( aSign ^ zSign, bExp - 4, aSig0, aSig1 );
210515144b0fSOlivier Houchard 
210615144b0fSOlivier Houchard }
210715144b0fSOlivier Houchard #endif
210815144b0fSOlivier Houchard 
210915144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
211015144b0fSOlivier Houchard /*
211115144b0fSOlivier Houchard -------------------------------------------------------------------------------
211215144b0fSOlivier Houchard Returns the square root of the double-precision floating-point value `a'.
211315144b0fSOlivier Houchard The operation is performed according to the IEC/IEEE Standard for Binary
211415144b0fSOlivier Houchard Floating-Point Arithmetic.
211515144b0fSOlivier Houchard -------------------------------------------------------------------------------
211615144b0fSOlivier Houchard */
float64_sqrt(float64 a)211715144b0fSOlivier Houchard float64 float64_sqrt( float64 a )
211815144b0fSOlivier Houchard {
211915144b0fSOlivier Houchard     flag aSign;
212015144b0fSOlivier Houchard     int16 aExp, zExp;
212115144b0fSOlivier Houchard     bits32 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
212215144b0fSOlivier Houchard     bits32 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
212315144b0fSOlivier Houchard     float64 z;
212415144b0fSOlivier Houchard 
212515144b0fSOlivier Houchard     aSig1 = extractFloat64Frac1( a );
212615144b0fSOlivier Houchard     aSig0 = extractFloat64Frac0( a );
212715144b0fSOlivier Houchard     aExp = extractFloat64Exp( a );
212815144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
212915144b0fSOlivier Houchard     if ( aExp == 0x7FF ) {
213015144b0fSOlivier Houchard         if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, a );
213115144b0fSOlivier Houchard         if ( ! aSign ) return a;
213215144b0fSOlivier Houchard         goto invalid;
213315144b0fSOlivier Houchard     }
213415144b0fSOlivier Houchard     if ( aSign ) {
213515144b0fSOlivier Houchard         if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
213615144b0fSOlivier Houchard  invalid:
213715144b0fSOlivier Houchard         float_raise( float_flag_invalid );
213815144b0fSOlivier Houchard         return float64_default_nan;
213915144b0fSOlivier Houchard     }
214015144b0fSOlivier Houchard     if ( aExp == 0 ) {
214115144b0fSOlivier Houchard         if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( 0, 0, 0, 0 );
214215144b0fSOlivier Houchard         normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
214315144b0fSOlivier Houchard     }
214415144b0fSOlivier Houchard     zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
214515144b0fSOlivier Houchard     aSig0 |= 0x00100000;
214615144b0fSOlivier Houchard     shortShift64Left( aSig0, aSig1, 11, &term0, &term1 );
214715144b0fSOlivier Houchard     zSig0 = ( estimateSqrt32( aExp, term0 )>>1 ) + 1;
214815144b0fSOlivier Houchard     if ( zSig0 == 0 ) zSig0 = 0x7FFFFFFF;
214915144b0fSOlivier Houchard     doubleZSig0 = zSig0 + zSig0;
215015144b0fSOlivier Houchard     shortShift64Left( aSig0, aSig1, 9 - ( aExp & 1 ), &aSig0, &aSig1 );
215115144b0fSOlivier Houchard     mul32To64( zSig0, zSig0, &term0, &term1 );
215215144b0fSOlivier Houchard     sub64( aSig0, aSig1, term0, term1, &rem0, &rem1 );
215315144b0fSOlivier Houchard     while ( (sbits32) rem0 < 0 ) {
215415144b0fSOlivier Houchard         --zSig0;
215515144b0fSOlivier Houchard         doubleZSig0 -= 2;
215615144b0fSOlivier Houchard         add64( rem0, rem1, 0, doubleZSig0 | 1, &rem0, &rem1 );
215715144b0fSOlivier Houchard     }
215815144b0fSOlivier Houchard     zSig1 = estimateDiv64To32( rem1, 0, doubleZSig0 );
215915144b0fSOlivier Houchard     if ( ( zSig1 & 0x1FF ) <= 5 ) {
216015144b0fSOlivier Houchard         if ( zSig1 == 0 ) zSig1 = 1;
216115144b0fSOlivier Houchard         mul32To64( doubleZSig0, zSig1, &term1, &term2 );
216215144b0fSOlivier Houchard         sub64( rem1, 0, term1, term2, &rem1, &rem2 );
216315144b0fSOlivier Houchard         mul32To64( zSig1, zSig1, &term2, &term3 );
216415144b0fSOlivier Houchard         sub96( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
216515144b0fSOlivier Houchard         while ( (sbits32) rem1 < 0 ) {
216615144b0fSOlivier Houchard             --zSig1;
216715144b0fSOlivier Houchard             shortShift64Left( 0, zSig1, 1, &term2, &term3 );
216815144b0fSOlivier Houchard             term3 |= 1;
216915144b0fSOlivier Houchard             term2 |= doubleZSig0;
217015144b0fSOlivier Houchard             add96( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
217115144b0fSOlivier Houchard         }
217215144b0fSOlivier Houchard         zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
217315144b0fSOlivier Houchard     }
217415144b0fSOlivier Houchard     shift64ExtraRightJamming( zSig0, zSig1, 0, 10, &zSig0, &zSig1, &zSig2 );
217515144b0fSOlivier Houchard     return roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2 );
217615144b0fSOlivier Houchard 
217715144b0fSOlivier Houchard }
217815144b0fSOlivier Houchard #endif
217915144b0fSOlivier Houchard 
218015144b0fSOlivier Houchard /*
218115144b0fSOlivier Houchard -------------------------------------------------------------------------------
218215144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is equal to
218315144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The comparison is performed
218415144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
218515144b0fSOlivier Houchard -------------------------------------------------------------------------------
218615144b0fSOlivier Houchard */
float64_eq(float64 a,float64 b)218715144b0fSOlivier Houchard flag float64_eq( float64 a, float64 b )
218815144b0fSOlivier Houchard {
218915144b0fSOlivier Houchard 
219015144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
219115144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
219215144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
219315144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
219415144b0fSOlivier Houchard        ) {
219515144b0fSOlivier Houchard         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
219615144b0fSOlivier Houchard             float_raise( float_flag_invalid );
219715144b0fSOlivier Houchard         }
219815144b0fSOlivier Houchard         return 0;
219915144b0fSOlivier Houchard     }
220015144b0fSOlivier Houchard     return ( a == b ) ||
220115144b0fSOlivier Houchard 	( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) == 0 );
220215144b0fSOlivier Houchard 
220315144b0fSOlivier Houchard }
220415144b0fSOlivier Houchard 
220515144b0fSOlivier Houchard /*
220615144b0fSOlivier Houchard -------------------------------------------------------------------------------
220715144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is less than
220815144b0fSOlivier Houchard or equal to the corresponding value `b', and 0 otherwise.  The comparison
220915144b0fSOlivier Houchard is performed according to the IEC/IEEE Standard for Binary Floating-Point
221015144b0fSOlivier Houchard Arithmetic.
221115144b0fSOlivier Houchard -------------------------------------------------------------------------------
221215144b0fSOlivier Houchard */
float64_le(float64 a,float64 b)221315144b0fSOlivier Houchard flag float64_le( float64 a, float64 b )
221415144b0fSOlivier Houchard {
221515144b0fSOlivier Houchard     flag aSign, bSign;
221615144b0fSOlivier Houchard 
221715144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
221815144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
221915144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
222015144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
222115144b0fSOlivier Houchard        ) {
222215144b0fSOlivier Houchard         float_raise( float_flag_invalid );
222315144b0fSOlivier Houchard         return 0;
222415144b0fSOlivier Houchard     }
222515144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
222615144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
222715144b0fSOlivier Houchard     if ( aSign != bSign )
222815144b0fSOlivier Houchard 	return aSign ||
222915144b0fSOlivier Houchard 	    ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) ==
223015144b0fSOlivier Houchard 	      0 );
223115144b0fSOlivier Houchard     return ( a == b ) ||
223215144b0fSOlivier Houchard 	( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
223315144b0fSOlivier Houchard }
223415144b0fSOlivier Houchard 
223515144b0fSOlivier Houchard /*
223615144b0fSOlivier Houchard -------------------------------------------------------------------------------
223715144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is less than
223815144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The comparison is performed
223915144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
224015144b0fSOlivier Houchard -------------------------------------------------------------------------------
224115144b0fSOlivier Houchard */
float64_lt(float64 a,float64 b)224215144b0fSOlivier Houchard flag float64_lt( float64 a, float64 b )
224315144b0fSOlivier Houchard {
224415144b0fSOlivier Houchard     flag aSign, bSign;
224515144b0fSOlivier Houchard 
224615144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
224715144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
224815144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
224915144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
225015144b0fSOlivier Houchard        ) {
225115144b0fSOlivier Houchard         float_raise( float_flag_invalid );
225215144b0fSOlivier Houchard         return 0;
225315144b0fSOlivier Houchard     }
225415144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
225515144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
225615144b0fSOlivier Houchard     if ( aSign != bSign )
225715144b0fSOlivier Houchard 	return aSign &&
225815144b0fSOlivier Houchard 	    ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) !=
225915144b0fSOlivier Houchard 	      0 );
226015144b0fSOlivier Houchard     return ( a != b ) &&
226115144b0fSOlivier Houchard 	( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
226215144b0fSOlivier Houchard 
226315144b0fSOlivier Houchard }
226415144b0fSOlivier Houchard 
226515144b0fSOlivier Houchard #ifndef SOFTFLOAT_FOR_GCC
226615144b0fSOlivier Houchard /*
226715144b0fSOlivier Houchard -------------------------------------------------------------------------------
226815144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is equal to
226915144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  The invalid exception is
227015144b0fSOlivier Houchard raised if either operand is a NaN.  Otherwise, the comparison is performed
227115144b0fSOlivier Houchard according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
227215144b0fSOlivier Houchard -------------------------------------------------------------------------------
227315144b0fSOlivier Houchard */
float64_eq_signaling(float64 a,float64 b)227415144b0fSOlivier Houchard flag float64_eq_signaling( float64 a, float64 b )
227515144b0fSOlivier Houchard {
227615144b0fSOlivier Houchard 
227715144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
227815144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
227915144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
228015144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
228115144b0fSOlivier Houchard        ) {
228215144b0fSOlivier Houchard         float_raise( float_flag_invalid );
228315144b0fSOlivier Houchard         return 0;
228415144b0fSOlivier Houchard     }
228515144b0fSOlivier Houchard     return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
228615144b0fSOlivier Houchard 
228715144b0fSOlivier Houchard }
228815144b0fSOlivier Houchard 
228915144b0fSOlivier Houchard /*
229015144b0fSOlivier Houchard -------------------------------------------------------------------------------
229115144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is less than or
229215144b0fSOlivier Houchard equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs do not
229315144b0fSOlivier Houchard cause an exception.  Otherwise, the comparison is performed according to the
229415144b0fSOlivier Houchard IEC/IEEE Standard for Binary Floating-Point Arithmetic.
229515144b0fSOlivier Houchard -------------------------------------------------------------------------------
229615144b0fSOlivier Houchard */
float64_le_quiet(float64 a,float64 b)229715144b0fSOlivier Houchard flag float64_le_quiet( float64 a, float64 b )
229815144b0fSOlivier Houchard {
229915144b0fSOlivier Houchard     flag aSign, bSign;
230015144b0fSOlivier Houchard 
230115144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
230215144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
230315144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
230415144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
230515144b0fSOlivier Houchard        ) {
230615144b0fSOlivier Houchard         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
230715144b0fSOlivier Houchard             float_raise( float_flag_invalid );
230815144b0fSOlivier Houchard         }
230915144b0fSOlivier Houchard         return 0;
231015144b0fSOlivier Houchard     }
231115144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
231215144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
231315144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
231415144b0fSOlivier Houchard     return ( a == b ) || ( aSign ^ ( a < b ) );
231515144b0fSOlivier Houchard 
231615144b0fSOlivier Houchard }
231715144b0fSOlivier Houchard 
231815144b0fSOlivier Houchard /*
231915144b0fSOlivier Houchard -------------------------------------------------------------------------------
232015144b0fSOlivier Houchard Returns 1 if the double-precision floating-point value `a' is less than
232115144b0fSOlivier Houchard the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause an
232215144b0fSOlivier Houchard exception.  Otherwise, the comparison is performed according to the IEC/IEEE
232315144b0fSOlivier Houchard Standard for Binary Floating-Point Arithmetic.
232415144b0fSOlivier Houchard -------------------------------------------------------------------------------
232515144b0fSOlivier Houchard */
float64_lt_quiet(float64 a,float64 b)232615144b0fSOlivier Houchard flag float64_lt_quiet( float64 a, float64 b )
232715144b0fSOlivier Houchard {
232815144b0fSOlivier Houchard     flag aSign, bSign;
232915144b0fSOlivier Houchard 
233015144b0fSOlivier Houchard     if (    (    ( extractFloat64Exp( a ) == 0x7FF )
233115144b0fSOlivier Houchard               && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
233215144b0fSOlivier Houchard          || (    ( extractFloat64Exp( b ) == 0x7FF )
233315144b0fSOlivier Houchard               && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
233415144b0fSOlivier Houchard        ) {
233515144b0fSOlivier Houchard         if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
233615144b0fSOlivier Houchard             float_raise( float_flag_invalid );
233715144b0fSOlivier Houchard         }
233815144b0fSOlivier Houchard         return 0;
233915144b0fSOlivier Houchard     }
234015144b0fSOlivier Houchard     aSign = extractFloat64Sign( a );
234115144b0fSOlivier Houchard     bSign = extractFloat64Sign( b );
234215144b0fSOlivier Houchard     if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
234315144b0fSOlivier Houchard     return ( a != b ) && ( aSign ^ ( a < b ) );
234415144b0fSOlivier Houchard 
234515144b0fSOlivier Houchard }
234615144b0fSOlivier Houchard 
234715144b0fSOlivier Houchard #endif
2348