xref: /freebsd/lib/libc/softfloat/bits32/softfloat-macros (revision c36abe0dcf91e964fbb194f3f8589dc8f05cd146)
115144b0fSOlivier Houchard/* $FreeBSD$ */
215144b0fSOlivier Houchard
315144b0fSOlivier Houchard/*
415144b0fSOlivier Houchard===============================================================================
515144b0fSOlivier Houchard
615144b0fSOlivier HouchardThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
715144b0fSOlivier HouchardArithmetic Package, Release 2a.
815144b0fSOlivier Houchard
915144b0fSOlivier HouchardWritten by John R. Hauser.  This work was made possible in part by the
1015144b0fSOlivier HouchardInternational Computer Science Institute, located at Suite 600, 1947 Center
1115144b0fSOlivier HouchardStreet, Berkeley, California 94704.  Funding was partially provided by the
1215144b0fSOlivier HouchardNational Science Foundation under grant MIP-9311980.  The original version
1315144b0fSOlivier Houchardof this code was written as part of a project to build a fixed-point vector
1415144b0fSOlivier Houchardprocessor in collaboration with the University of California at Berkeley,
1515144b0fSOlivier Houchardoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
1615144b0fSOlivier Houchardis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
1715144b0fSOlivier Houchardarithmetic/SoftFloat.html'.
1815144b0fSOlivier Houchard
1915144b0fSOlivier HouchardTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
2015144b0fSOlivier Houchardhas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
2115144b0fSOlivier HouchardTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
2215144b0fSOlivier HouchardPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
2315144b0fSOlivier HouchardAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
2415144b0fSOlivier Houchard
2515144b0fSOlivier HouchardDerivative works are acceptable, even for commercial purposes, so long as
2615144b0fSOlivier Houchard(1) they include prominent notice that the work is derivative, and (2) they
2715144b0fSOlivier Houchardinclude prominent notice akin to these four paragraphs for those parts of
2815144b0fSOlivier Houchardthis code that are retained.
2915144b0fSOlivier Houchard
3015144b0fSOlivier Houchard===============================================================================
3115144b0fSOlivier Houchard*/
3215144b0fSOlivier Houchard
3315144b0fSOlivier Houchard/*
3415144b0fSOlivier Houchard-------------------------------------------------------------------------------
3515144b0fSOlivier HouchardShifts `a' right by the number of bits given in `count'.  If any nonzero
3615144b0fSOlivier Houchardbits are shifted off, they are ``jammed'' into the least significant bit of
3715144b0fSOlivier Houchardthe result by setting the least significant bit to 1.  The value of `count'
3815144b0fSOlivier Houchardcan be arbitrarily large; in particular, if `count' is greater than 32, the
3915144b0fSOlivier Houchardresult will be either 0 or 1, depending on whether `a' is zero or nonzero.
4015144b0fSOlivier HouchardThe result is stored in the location pointed to by `zPtr'.
4115144b0fSOlivier Houchard-------------------------------------------------------------------------------
4215144b0fSOlivier Houchard*/
4315144b0fSOlivier HouchardINLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
4415144b0fSOlivier Houchard{
4515144b0fSOlivier Houchard    bits32 z;
4615144b0fSOlivier Houchard
4715144b0fSOlivier Houchard    if ( count == 0 ) {
4815144b0fSOlivier Houchard        z = a;
4915144b0fSOlivier Houchard    }
5015144b0fSOlivier Houchard    else if ( count < 32 ) {
5115144b0fSOlivier Houchard        z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
5215144b0fSOlivier Houchard    }
5315144b0fSOlivier Houchard    else {
5415144b0fSOlivier Houchard        z = ( a != 0 );
5515144b0fSOlivier Houchard    }
5615144b0fSOlivier Houchard    *zPtr = z;
5715144b0fSOlivier Houchard
5815144b0fSOlivier Houchard}
5915144b0fSOlivier Houchard
6015144b0fSOlivier Houchard/*
6115144b0fSOlivier Houchard-------------------------------------------------------------------------------
6215144b0fSOlivier HouchardShifts the 64-bit value formed by concatenating `a0' and `a1' right by the
6315144b0fSOlivier Houchardnumber of bits given in `count'.  Any bits shifted off are lost.  The value
6415144b0fSOlivier Houchardof `count' can be arbitrarily large; in particular, if `count' is greater
6515144b0fSOlivier Houchardthan 64, the result will be 0.  The result is broken into two 32-bit pieces
6615144b0fSOlivier Houchardwhich are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
6715144b0fSOlivier Houchard-------------------------------------------------------------------------------
6815144b0fSOlivier Houchard*/
6915144b0fSOlivier HouchardINLINE void
7015144b0fSOlivier Houchard shift64Right(
7115144b0fSOlivier Houchard     bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
7215144b0fSOlivier Houchard{
7315144b0fSOlivier Houchard    bits32 z0, z1;
7415144b0fSOlivier Houchard    int8 negCount = ( - count ) & 31;
7515144b0fSOlivier Houchard
7615144b0fSOlivier Houchard    if ( count == 0 ) {
7715144b0fSOlivier Houchard        z1 = a1;
7815144b0fSOlivier Houchard        z0 = a0;
7915144b0fSOlivier Houchard    }
8015144b0fSOlivier Houchard    else if ( count < 32 ) {
8115144b0fSOlivier Houchard        z1 = ( a0<<negCount ) | ( a1>>count );
8215144b0fSOlivier Houchard        z0 = a0>>count;
8315144b0fSOlivier Houchard    }
8415144b0fSOlivier Houchard    else {
8515144b0fSOlivier Houchard        z1 = ( count < 64 ) ? ( a0>>( count & 31 ) ) : 0;
8615144b0fSOlivier Houchard        z0 = 0;
8715144b0fSOlivier Houchard    }
8815144b0fSOlivier Houchard    *z1Ptr = z1;
8915144b0fSOlivier Houchard    *z0Ptr = z0;
9015144b0fSOlivier Houchard
9115144b0fSOlivier Houchard}
9215144b0fSOlivier Houchard
9315144b0fSOlivier Houchard/*
9415144b0fSOlivier Houchard-------------------------------------------------------------------------------
9515144b0fSOlivier HouchardShifts the 64-bit value formed by concatenating `a0' and `a1' right by the
9615144b0fSOlivier Houchardnumber of bits given in `count'.  If any nonzero bits are shifted off, they
9715144b0fSOlivier Houchardare ``jammed'' into the least significant bit of the result by setting the
9815144b0fSOlivier Houchardleast significant bit to 1.  The value of `count' can be arbitrarily large;
9915144b0fSOlivier Houchardin particular, if `count' is greater than 64, the result will be either 0
10015144b0fSOlivier Houchardor 1, depending on whether the concatenation of `a0' and `a1' is zero or
10115144b0fSOlivier Houchardnonzero.  The result is broken into two 32-bit pieces which are stored at
10215144b0fSOlivier Houchardthe locations pointed to by `z0Ptr' and `z1Ptr'.
10315144b0fSOlivier Houchard-------------------------------------------------------------------------------
10415144b0fSOlivier Houchard*/
10515144b0fSOlivier HouchardINLINE void
10615144b0fSOlivier Houchard shift64RightJamming(
10715144b0fSOlivier Houchard     bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
10815144b0fSOlivier Houchard{
10915144b0fSOlivier Houchard    bits32 z0, z1;
11015144b0fSOlivier Houchard    int8 negCount = ( - count ) & 31;
11115144b0fSOlivier Houchard
11215144b0fSOlivier Houchard    if ( count == 0 ) {
11315144b0fSOlivier Houchard        z1 = a1;
11415144b0fSOlivier Houchard        z0 = a0;
11515144b0fSOlivier Houchard    }
11615144b0fSOlivier Houchard    else if ( count < 32 ) {
11715144b0fSOlivier Houchard        z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
11815144b0fSOlivier Houchard        z0 = a0>>count;
11915144b0fSOlivier Houchard    }
12015144b0fSOlivier Houchard    else {
12115144b0fSOlivier Houchard        if ( count == 32 ) {
12215144b0fSOlivier Houchard            z1 = a0 | ( a1 != 0 );
12315144b0fSOlivier Houchard        }
12415144b0fSOlivier Houchard        else if ( count < 64 ) {
12515144b0fSOlivier Houchard            z1 = ( a0>>( count & 31 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
12615144b0fSOlivier Houchard        }
12715144b0fSOlivier Houchard        else {
12815144b0fSOlivier Houchard            z1 = ( ( a0 | a1 ) != 0 );
12915144b0fSOlivier Houchard        }
13015144b0fSOlivier Houchard        z0 = 0;
13115144b0fSOlivier Houchard    }
13215144b0fSOlivier Houchard    *z1Ptr = z1;
13315144b0fSOlivier Houchard    *z0Ptr = z0;
13415144b0fSOlivier Houchard
13515144b0fSOlivier Houchard}
13615144b0fSOlivier Houchard
13715144b0fSOlivier Houchard/*
13815144b0fSOlivier Houchard-------------------------------------------------------------------------------
13915144b0fSOlivier HouchardShifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
14015144b0fSOlivier Houchardby 32 _plus_ the number of bits given in `count'.  The shifted result is
14115144b0fSOlivier Houchardat most 64 nonzero bits; these are broken into two 32-bit pieces which are
14215144b0fSOlivier Houchardstored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted
14315144b0fSOlivier Houchardoff form a third 32-bit result as follows:  The _last_ bit shifted off is
14415144b0fSOlivier Houchardthe most-significant bit of the extra result, and the other 31 bits of the
14515144b0fSOlivier Houchardextra result are all zero if and only if _all_but_the_last_ bits shifted off
14615144b0fSOlivier Houchardwere all zero.  This extra result is stored in the location pointed to by
14715144b0fSOlivier Houchard`z2Ptr'.  The value of `count' can be arbitrarily large.
14815144b0fSOlivier Houchard    (This routine makes more sense if `a0', `a1', and `a2' are considered
14915144b0fSOlivier Houchardto form a fixed-point value with binary point between `a1' and `a2'.  This
15015144b0fSOlivier Houchardfixed-point value is shifted right by the number of bits given in `count',
15115144b0fSOlivier Houchardand the integer part of the result is returned at the locations pointed to
15215144b0fSOlivier Houchardby `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly
15315144b0fSOlivier Houchardcorrupted as described above, and is returned at the location pointed to by
15415144b0fSOlivier Houchard`z2Ptr'.)
15515144b0fSOlivier Houchard-------------------------------------------------------------------------------
15615144b0fSOlivier Houchard*/
15715144b0fSOlivier HouchardINLINE void
15815144b0fSOlivier Houchard shift64ExtraRightJamming(
15915144b0fSOlivier Houchard     bits32 a0,
16015144b0fSOlivier Houchard     bits32 a1,
16115144b0fSOlivier Houchard     bits32 a2,
16215144b0fSOlivier Houchard     int16 count,
16315144b0fSOlivier Houchard     bits32 *z0Ptr,
16415144b0fSOlivier Houchard     bits32 *z1Ptr,
16515144b0fSOlivier Houchard     bits32 *z2Ptr
16615144b0fSOlivier Houchard )
16715144b0fSOlivier Houchard{
16815144b0fSOlivier Houchard    bits32 z0, z1, z2;
16915144b0fSOlivier Houchard    int8 negCount = ( - count ) & 31;
17015144b0fSOlivier Houchard
17115144b0fSOlivier Houchard    if ( count == 0 ) {
17215144b0fSOlivier Houchard        z2 = a2;
17315144b0fSOlivier Houchard        z1 = a1;
17415144b0fSOlivier Houchard        z0 = a0;
17515144b0fSOlivier Houchard    }
17615144b0fSOlivier Houchard    else {
17715144b0fSOlivier Houchard        if ( count < 32 ) {
17815144b0fSOlivier Houchard            z2 = a1<<negCount;
17915144b0fSOlivier Houchard            z1 = ( a0<<negCount ) | ( a1>>count );
18015144b0fSOlivier Houchard            z0 = a0>>count;
18115144b0fSOlivier Houchard        }
18215144b0fSOlivier Houchard        else {
18315144b0fSOlivier Houchard            if ( count == 32 ) {
18415144b0fSOlivier Houchard                z2 = a1;
18515144b0fSOlivier Houchard                z1 = a0;
18615144b0fSOlivier Houchard            }
18715144b0fSOlivier Houchard            else {
18815144b0fSOlivier Houchard                a2 |= a1;
18915144b0fSOlivier Houchard                if ( count < 64 ) {
19015144b0fSOlivier Houchard                    z2 = a0<<negCount;
19115144b0fSOlivier Houchard                    z1 = a0>>( count & 31 );
19215144b0fSOlivier Houchard                }
19315144b0fSOlivier Houchard                else {
19415144b0fSOlivier Houchard                    z2 = ( count == 64 ) ? a0 : ( a0 != 0 );
19515144b0fSOlivier Houchard                    z1 = 0;
19615144b0fSOlivier Houchard                }
19715144b0fSOlivier Houchard            }
19815144b0fSOlivier Houchard            z0 = 0;
19915144b0fSOlivier Houchard        }
20015144b0fSOlivier Houchard        z2 |= ( a2 != 0 );
20115144b0fSOlivier Houchard    }
20215144b0fSOlivier Houchard    *z2Ptr = z2;
20315144b0fSOlivier Houchard    *z1Ptr = z1;
20415144b0fSOlivier Houchard    *z0Ptr = z0;
20515144b0fSOlivier Houchard
20615144b0fSOlivier Houchard}
20715144b0fSOlivier Houchard
20815144b0fSOlivier Houchard/*
20915144b0fSOlivier Houchard-------------------------------------------------------------------------------
21015144b0fSOlivier HouchardShifts the 64-bit value formed by concatenating `a0' and `a1' left by the
21115144b0fSOlivier Houchardnumber of bits given in `count'.  Any bits shifted off are lost.  The value
21215144b0fSOlivier Houchardof `count' must be less than 32.  The result is broken into two 32-bit
21315144b0fSOlivier Houchardpieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
21415144b0fSOlivier Houchard-------------------------------------------------------------------------------
21515144b0fSOlivier Houchard*/
21615144b0fSOlivier HouchardINLINE void
21715144b0fSOlivier Houchard shortShift64Left(
21815144b0fSOlivier Houchard     bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
21915144b0fSOlivier Houchard{
22015144b0fSOlivier Houchard
22115144b0fSOlivier Houchard    *z1Ptr = a1<<count;
22215144b0fSOlivier Houchard    *z0Ptr =
22315144b0fSOlivier Houchard        ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 31 ) );
22415144b0fSOlivier Houchard
22515144b0fSOlivier Houchard}
22615144b0fSOlivier Houchard
22715144b0fSOlivier Houchard/*
22815144b0fSOlivier Houchard-------------------------------------------------------------------------------
22915144b0fSOlivier HouchardShifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
23015144b0fSOlivier Houchardby the number of bits given in `count'.  Any bits shifted off are lost.
23115144b0fSOlivier HouchardThe value of `count' must be less than 32.  The result is broken into three
23215144b0fSOlivier Houchard32-bit pieces which are stored at the locations pointed to by `z0Ptr',
23315144b0fSOlivier Houchard`z1Ptr', and `z2Ptr'.
23415144b0fSOlivier Houchard-------------------------------------------------------------------------------
23515144b0fSOlivier Houchard*/
23615144b0fSOlivier HouchardINLINE void
23715144b0fSOlivier Houchard shortShift96Left(
23815144b0fSOlivier Houchard     bits32 a0,
23915144b0fSOlivier Houchard     bits32 a1,
24015144b0fSOlivier Houchard     bits32 a2,
24115144b0fSOlivier Houchard     int16 count,
24215144b0fSOlivier Houchard     bits32 *z0Ptr,
24315144b0fSOlivier Houchard     bits32 *z1Ptr,
24415144b0fSOlivier Houchard     bits32 *z2Ptr
24515144b0fSOlivier Houchard )
24615144b0fSOlivier Houchard{
24715144b0fSOlivier Houchard    bits32 z0, z1, z2;
24815144b0fSOlivier Houchard    int8 negCount;
24915144b0fSOlivier Houchard
25015144b0fSOlivier Houchard    z2 = a2<<count;
25115144b0fSOlivier Houchard    z1 = a1<<count;
25215144b0fSOlivier Houchard    z0 = a0<<count;
25315144b0fSOlivier Houchard    if ( 0 < count ) {
25415144b0fSOlivier Houchard        negCount = ( ( - count ) & 31 );
25515144b0fSOlivier Houchard        z1 |= a2>>negCount;
25615144b0fSOlivier Houchard        z0 |= a1>>negCount;
25715144b0fSOlivier Houchard    }
25815144b0fSOlivier Houchard    *z2Ptr = z2;
25915144b0fSOlivier Houchard    *z1Ptr = z1;
26015144b0fSOlivier Houchard    *z0Ptr = z0;
26115144b0fSOlivier Houchard
26215144b0fSOlivier Houchard}
26315144b0fSOlivier Houchard
26415144b0fSOlivier Houchard/*
26515144b0fSOlivier Houchard-------------------------------------------------------------------------------
26615144b0fSOlivier HouchardAdds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
26715144b0fSOlivier Houchardvalue formed by concatenating `b0' and `b1'.  Addition is modulo 2^64, so
26815144b0fSOlivier Houchardany carry out is lost.  The result is broken into two 32-bit pieces which
26915144b0fSOlivier Houchardare stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
27015144b0fSOlivier Houchard-------------------------------------------------------------------------------
27115144b0fSOlivier Houchard*/
27215144b0fSOlivier HouchardINLINE void
27315144b0fSOlivier Houchard add64(
27415144b0fSOlivier Houchard     bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
27515144b0fSOlivier Houchard{
27615144b0fSOlivier Houchard    bits32 z1;
27715144b0fSOlivier Houchard
27815144b0fSOlivier Houchard    z1 = a1 + b1;
27915144b0fSOlivier Houchard    *z1Ptr = z1;
28015144b0fSOlivier Houchard    *z0Ptr = a0 + b0 + ( z1 < a1 );
28115144b0fSOlivier Houchard
28215144b0fSOlivier Houchard}
28315144b0fSOlivier Houchard
28415144b0fSOlivier Houchard/*
28515144b0fSOlivier Houchard-------------------------------------------------------------------------------
28615144b0fSOlivier HouchardAdds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
28715144b0fSOlivier Houchard96-bit value formed by concatenating `b0', `b1', and `b2'.  Addition is
28815144b0fSOlivier Houchardmodulo 2^96, so any carry out is lost.  The result is broken into three
28915144b0fSOlivier Houchard32-bit pieces which are stored at the locations pointed to by `z0Ptr',
29015144b0fSOlivier Houchard`z1Ptr', and `z2Ptr'.
29115144b0fSOlivier Houchard-------------------------------------------------------------------------------
29215144b0fSOlivier Houchard*/
29315144b0fSOlivier HouchardINLINE void
29415144b0fSOlivier Houchard add96(
29515144b0fSOlivier Houchard     bits32 a0,
29615144b0fSOlivier Houchard     bits32 a1,
29715144b0fSOlivier Houchard     bits32 a2,
29815144b0fSOlivier Houchard     bits32 b0,
29915144b0fSOlivier Houchard     bits32 b1,
30015144b0fSOlivier Houchard     bits32 b2,
30115144b0fSOlivier Houchard     bits32 *z0Ptr,
30215144b0fSOlivier Houchard     bits32 *z1Ptr,
30315144b0fSOlivier Houchard     bits32 *z2Ptr
30415144b0fSOlivier Houchard )
30515144b0fSOlivier Houchard{
30615144b0fSOlivier Houchard    bits32 z0, z1, z2;
30715144b0fSOlivier Houchard    int8 carry0, carry1;
30815144b0fSOlivier Houchard
30915144b0fSOlivier Houchard    z2 = a2 + b2;
31015144b0fSOlivier Houchard    carry1 = ( z2 < a2 );
31115144b0fSOlivier Houchard    z1 = a1 + b1;
31215144b0fSOlivier Houchard    carry0 = ( z1 < a1 );
31315144b0fSOlivier Houchard    z0 = a0 + b0;
31415144b0fSOlivier Houchard    z1 += carry1;
315*c36abe0dSDavid Schultz    z0 += ( z1 < (bits32)carry1 );
31615144b0fSOlivier Houchard    z0 += carry0;
31715144b0fSOlivier Houchard    *z2Ptr = z2;
31815144b0fSOlivier Houchard    *z1Ptr = z1;
31915144b0fSOlivier Houchard    *z0Ptr = z0;
32015144b0fSOlivier Houchard
32115144b0fSOlivier Houchard}
32215144b0fSOlivier Houchard
32315144b0fSOlivier Houchard/*
32415144b0fSOlivier Houchard-------------------------------------------------------------------------------
32515144b0fSOlivier HouchardSubtracts the 64-bit value formed by concatenating `b0' and `b1' from the
32615144b0fSOlivier Houchard64-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo
32715144b0fSOlivier Houchard2^64, so any borrow out (carry out) is lost.  The result is broken into two
32815144b0fSOlivier Houchard32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
32915144b0fSOlivier Houchard`z1Ptr'.
33015144b0fSOlivier Houchard-------------------------------------------------------------------------------
33115144b0fSOlivier Houchard*/
33215144b0fSOlivier HouchardINLINE void
33315144b0fSOlivier Houchard sub64(
33415144b0fSOlivier Houchard     bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
33515144b0fSOlivier Houchard{
33615144b0fSOlivier Houchard
33715144b0fSOlivier Houchard    *z1Ptr = a1 - b1;
33815144b0fSOlivier Houchard    *z0Ptr = a0 - b0 - ( a1 < b1 );
33915144b0fSOlivier Houchard
34015144b0fSOlivier Houchard}
34115144b0fSOlivier Houchard
34215144b0fSOlivier Houchard/*
34315144b0fSOlivier Houchard-------------------------------------------------------------------------------
34415144b0fSOlivier HouchardSubtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
34515144b0fSOlivier Houchardthe 96-bit value formed by concatenating `a0', `a1', and `a2'.  Subtraction
34615144b0fSOlivier Houchardis modulo 2^96, so any borrow out (carry out) is lost.  The result is broken
34715144b0fSOlivier Houchardinto three 32-bit pieces which are stored at the locations pointed to by
34815144b0fSOlivier Houchard`z0Ptr', `z1Ptr', and `z2Ptr'.
34915144b0fSOlivier Houchard-------------------------------------------------------------------------------
35015144b0fSOlivier Houchard*/
35115144b0fSOlivier HouchardINLINE void
35215144b0fSOlivier Houchard sub96(
35315144b0fSOlivier Houchard     bits32 a0,
35415144b0fSOlivier Houchard     bits32 a1,
35515144b0fSOlivier Houchard     bits32 a2,
35615144b0fSOlivier Houchard     bits32 b0,
35715144b0fSOlivier Houchard     bits32 b1,
35815144b0fSOlivier Houchard     bits32 b2,
35915144b0fSOlivier Houchard     bits32 *z0Ptr,
36015144b0fSOlivier Houchard     bits32 *z1Ptr,
36115144b0fSOlivier Houchard     bits32 *z2Ptr
36215144b0fSOlivier Houchard )
36315144b0fSOlivier Houchard{
36415144b0fSOlivier Houchard    bits32 z0, z1, z2;
36515144b0fSOlivier Houchard    int8 borrow0, borrow1;
36615144b0fSOlivier Houchard
36715144b0fSOlivier Houchard    z2 = a2 - b2;
36815144b0fSOlivier Houchard    borrow1 = ( a2 < b2 );
36915144b0fSOlivier Houchard    z1 = a1 - b1;
37015144b0fSOlivier Houchard    borrow0 = ( a1 < b1 );
37115144b0fSOlivier Houchard    z0 = a0 - b0;
372*c36abe0dSDavid Schultz    z0 -= ( z1 < (bits32)borrow1 );
37315144b0fSOlivier Houchard    z1 -= borrow1;
37415144b0fSOlivier Houchard    z0 -= borrow0;
37515144b0fSOlivier Houchard    *z2Ptr = z2;
37615144b0fSOlivier Houchard    *z1Ptr = z1;
37715144b0fSOlivier Houchard    *z0Ptr = z0;
37815144b0fSOlivier Houchard
37915144b0fSOlivier Houchard}
38015144b0fSOlivier Houchard
38115144b0fSOlivier Houchard/*
38215144b0fSOlivier Houchard-------------------------------------------------------------------------------
38315144b0fSOlivier HouchardMultiplies `a' by `b' to obtain a 64-bit product.  The product is broken
38415144b0fSOlivier Houchardinto two 32-bit pieces which are stored at the locations pointed to by
38515144b0fSOlivier Houchard`z0Ptr' and `z1Ptr'.
38615144b0fSOlivier Houchard-------------------------------------------------------------------------------
38715144b0fSOlivier Houchard*/
38815144b0fSOlivier HouchardINLINE void mul32To64( bits32 a, bits32 b, bits32 *z0Ptr, bits32 *z1Ptr )
38915144b0fSOlivier Houchard{
39015144b0fSOlivier Houchard    bits16 aHigh, aLow, bHigh, bLow;
39115144b0fSOlivier Houchard    bits32 z0, zMiddleA, zMiddleB, z1;
39215144b0fSOlivier Houchard
39315144b0fSOlivier Houchard    aLow = a;
39415144b0fSOlivier Houchard    aHigh = a>>16;
39515144b0fSOlivier Houchard    bLow = b;
39615144b0fSOlivier Houchard    bHigh = b>>16;
39715144b0fSOlivier Houchard    z1 = ( (bits32) aLow ) * bLow;
39815144b0fSOlivier Houchard    zMiddleA = ( (bits32) aLow ) * bHigh;
39915144b0fSOlivier Houchard    zMiddleB = ( (bits32) aHigh ) * bLow;
40015144b0fSOlivier Houchard    z0 = ( (bits32) aHigh ) * bHigh;
40115144b0fSOlivier Houchard    zMiddleA += zMiddleB;
40215144b0fSOlivier Houchard    z0 += ( ( (bits32) ( zMiddleA < zMiddleB ) )<<16 ) + ( zMiddleA>>16 );
40315144b0fSOlivier Houchard    zMiddleA <<= 16;
40415144b0fSOlivier Houchard    z1 += zMiddleA;
40515144b0fSOlivier Houchard    z0 += ( z1 < zMiddleA );
40615144b0fSOlivier Houchard    *z1Ptr = z1;
40715144b0fSOlivier Houchard    *z0Ptr = z0;
40815144b0fSOlivier Houchard
40915144b0fSOlivier Houchard}
41015144b0fSOlivier Houchard
41115144b0fSOlivier Houchard/*
41215144b0fSOlivier Houchard-------------------------------------------------------------------------------
41315144b0fSOlivier HouchardMultiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
41415144b0fSOlivier Houchardto obtain a 96-bit product.  The product is broken into three 32-bit pieces
41515144b0fSOlivier Houchardwhich are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
41615144b0fSOlivier Houchard`z2Ptr'.
41715144b0fSOlivier Houchard-------------------------------------------------------------------------------
41815144b0fSOlivier Houchard*/
41915144b0fSOlivier HouchardINLINE void
42015144b0fSOlivier Houchard mul64By32To96(
42115144b0fSOlivier Houchard     bits32 a0,
42215144b0fSOlivier Houchard     bits32 a1,
42315144b0fSOlivier Houchard     bits32 b,
42415144b0fSOlivier Houchard     bits32 *z0Ptr,
42515144b0fSOlivier Houchard     bits32 *z1Ptr,
42615144b0fSOlivier Houchard     bits32 *z2Ptr
42715144b0fSOlivier Houchard )
42815144b0fSOlivier Houchard{
42915144b0fSOlivier Houchard    bits32 z0, z1, z2, more1;
43015144b0fSOlivier Houchard
43115144b0fSOlivier Houchard    mul32To64( a1, b, &z1, &z2 );
43215144b0fSOlivier Houchard    mul32To64( a0, b, &z0, &more1 );
43315144b0fSOlivier Houchard    add64( z0, more1, 0, z1, &z0, &z1 );
43415144b0fSOlivier Houchard    *z2Ptr = z2;
43515144b0fSOlivier Houchard    *z1Ptr = z1;
43615144b0fSOlivier Houchard    *z0Ptr = z0;
43715144b0fSOlivier Houchard
43815144b0fSOlivier Houchard}
43915144b0fSOlivier Houchard
44015144b0fSOlivier Houchard/*
44115144b0fSOlivier Houchard-------------------------------------------------------------------------------
44215144b0fSOlivier HouchardMultiplies the 64-bit value formed by concatenating `a0' and `a1' to the
44315144b0fSOlivier Houchard64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
44415144b0fSOlivier Houchardproduct.  The product is broken into four 32-bit pieces which are stored at
44515144b0fSOlivier Houchardthe locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
44615144b0fSOlivier Houchard-------------------------------------------------------------------------------
44715144b0fSOlivier Houchard*/
44815144b0fSOlivier HouchardINLINE void
44915144b0fSOlivier Houchard mul64To128(
45015144b0fSOlivier Houchard     bits32 a0,
45115144b0fSOlivier Houchard     bits32 a1,
45215144b0fSOlivier Houchard     bits32 b0,
45315144b0fSOlivier Houchard     bits32 b1,
45415144b0fSOlivier Houchard     bits32 *z0Ptr,
45515144b0fSOlivier Houchard     bits32 *z1Ptr,
45615144b0fSOlivier Houchard     bits32 *z2Ptr,
45715144b0fSOlivier Houchard     bits32 *z3Ptr
45815144b0fSOlivier Houchard )
45915144b0fSOlivier Houchard{
46015144b0fSOlivier Houchard    bits32 z0, z1, z2, z3;
46115144b0fSOlivier Houchard    bits32 more1, more2;
46215144b0fSOlivier Houchard
46315144b0fSOlivier Houchard    mul32To64( a1, b1, &z2, &z3 );
46415144b0fSOlivier Houchard    mul32To64( a1, b0, &z1, &more2 );
46515144b0fSOlivier Houchard    add64( z1, more2, 0, z2, &z1, &z2 );
46615144b0fSOlivier Houchard    mul32To64( a0, b0, &z0, &more1 );
46715144b0fSOlivier Houchard    add64( z0, more1, 0, z1, &z0, &z1 );
46815144b0fSOlivier Houchard    mul32To64( a0, b1, &more1, &more2 );
46915144b0fSOlivier Houchard    add64( more1, more2, 0, z2, &more1, &z2 );
47015144b0fSOlivier Houchard    add64( z0, z1, 0, more1, &z0, &z1 );
47115144b0fSOlivier Houchard    *z3Ptr = z3;
47215144b0fSOlivier Houchard    *z2Ptr = z2;
47315144b0fSOlivier Houchard    *z1Ptr = z1;
47415144b0fSOlivier Houchard    *z0Ptr = z0;
47515144b0fSOlivier Houchard
47615144b0fSOlivier Houchard}
47715144b0fSOlivier Houchard
47815144b0fSOlivier Houchard/*
47915144b0fSOlivier Houchard-------------------------------------------------------------------------------
48015144b0fSOlivier HouchardReturns an approximation to the 32-bit integer quotient obtained by dividing
48115144b0fSOlivier Houchard`b' into the 64-bit value formed by concatenating `a0' and `a1'.  The
48215144b0fSOlivier Houcharddivisor `b' must be at least 2^31.  If q is the exact quotient truncated
48315144b0fSOlivier Houchardtoward zero, the approximation returned lies between q and q + 2 inclusive.
48415144b0fSOlivier HouchardIf the exact quotient q is larger than 32 bits, the maximum positive 32-bit
48515144b0fSOlivier Houchardunsigned integer is returned.
48615144b0fSOlivier Houchard-------------------------------------------------------------------------------
48715144b0fSOlivier Houchard*/
48815144b0fSOlivier Houchardstatic bits32 estimateDiv64To32( bits32 a0, bits32 a1, bits32 b )
48915144b0fSOlivier Houchard{
49015144b0fSOlivier Houchard    bits32 b0, b1;
49115144b0fSOlivier Houchard    bits32 rem0, rem1, term0, term1;
49215144b0fSOlivier Houchard    bits32 z;
49315144b0fSOlivier Houchard
49415144b0fSOlivier Houchard    if ( b <= a0 ) return 0xFFFFFFFF;
49515144b0fSOlivier Houchard    b0 = b>>16;
49615144b0fSOlivier Houchard    z = ( b0<<16 <= a0 ) ? 0xFFFF0000 : ( a0 / b0 )<<16;
49715144b0fSOlivier Houchard    mul32To64( b, z, &term0, &term1 );
49815144b0fSOlivier Houchard    sub64( a0, a1, term0, term1, &rem0, &rem1 );
49915144b0fSOlivier Houchard    while ( ( (sbits32) rem0 ) < 0 ) {
50015144b0fSOlivier Houchard        z -= 0x10000;
50115144b0fSOlivier Houchard        b1 = b<<16;
50215144b0fSOlivier Houchard        add64( rem0, rem1, b0, b1, &rem0, &rem1 );
50315144b0fSOlivier Houchard    }
50415144b0fSOlivier Houchard    rem0 = ( rem0<<16 ) | ( rem1>>16 );
50515144b0fSOlivier Houchard    z |= ( b0<<16 <= rem0 ) ? 0xFFFF : rem0 / b0;
50615144b0fSOlivier Houchard    return z;
50715144b0fSOlivier Houchard
50815144b0fSOlivier Houchard}
50915144b0fSOlivier Houchard
51015144b0fSOlivier Houchard#ifndef SOFTFLOAT_FOR_GCC
51115144b0fSOlivier Houchard/*
51215144b0fSOlivier Houchard-------------------------------------------------------------------------------
51315144b0fSOlivier HouchardReturns an approximation to the square root of the 32-bit significand given
51415144b0fSOlivier Houchardby `a'.  Considered as an integer, `a' must be at least 2^31.  If bit 0 of
51515144b0fSOlivier Houchard`aExp' (the least significant bit) is 1, the integer returned approximates
51615144b0fSOlivier Houchard2^31*sqrt(`a'/2^31), where `a' is considered an integer.  If bit 0 of `aExp'
51715144b0fSOlivier Houchardis 0, the integer returned approximates 2^31*sqrt(`a'/2^30).  In either
51815144b0fSOlivier Houchardcase, the approximation returned lies strictly within +/-2 of the exact
51915144b0fSOlivier Houchardvalue.
52015144b0fSOlivier Houchard-------------------------------------------------------------------------------
52115144b0fSOlivier Houchard*/
52215144b0fSOlivier Houchardstatic bits32 estimateSqrt32( int16 aExp, bits32 a )
52315144b0fSOlivier Houchard{
52415144b0fSOlivier Houchard    static const bits16 sqrtOddAdjustments[] = {
52515144b0fSOlivier Houchard        0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
52615144b0fSOlivier Houchard        0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
52715144b0fSOlivier Houchard    };
52815144b0fSOlivier Houchard    static const bits16 sqrtEvenAdjustments[] = {
52915144b0fSOlivier Houchard        0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
53015144b0fSOlivier Houchard        0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
53115144b0fSOlivier Houchard    };
53215144b0fSOlivier Houchard    int8 index;
53315144b0fSOlivier Houchard    bits32 z;
53415144b0fSOlivier Houchard
53515144b0fSOlivier Houchard    index = ( a>>27 ) & 15;
53615144b0fSOlivier Houchard    if ( aExp & 1 ) {
53715144b0fSOlivier Houchard        z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
53815144b0fSOlivier Houchard        z = ( ( a / z )<<14 ) + ( z<<15 );
53915144b0fSOlivier Houchard        a >>= 1;
54015144b0fSOlivier Houchard    }
54115144b0fSOlivier Houchard    else {
54215144b0fSOlivier Houchard        z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
54315144b0fSOlivier Houchard        z = a / z + z;
54415144b0fSOlivier Houchard        z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
54515144b0fSOlivier Houchard        if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
54615144b0fSOlivier Houchard    }
54715144b0fSOlivier Houchard    return ( ( estimateDiv64To32( a, 0, z ) )>>1 ) + ( z>>1 );
54815144b0fSOlivier Houchard
54915144b0fSOlivier Houchard}
55015144b0fSOlivier Houchard#endif
55115144b0fSOlivier Houchard
55215144b0fSOlivier Houchard/*
55315144b0fSOlivier Houchard-------------------------------------------------------------------------------
55415144b0fSOlivier HouchardReturns the number of leading 0 bits before the most-significant 1 bit of
55515144b0fSOlivier Houchard`a'.  If `a' is zero, 32 is returned.
55615144b0fSOlivier Houchard-------------------------------------------------------------------------------
55715144b0fSOlivier Houchard*/
55815144b0fSOlivier Houchardstatic int8 countLeadingZeros32( bits32 a )
55915144b0fSOlivier Houchard{
56015144b0fSOlivier Houchard    static const int8 countLeadingZerosHigh[] = {
56115144b0fSOlivier Houchard        8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
56215144b0fSOlivier Houchard        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
56315144b0fSOlivier Houchard        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
56415144b0fSOlivier Houchard        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
56515144b0fSOlivier Houchard        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56615144b0fSOlivier Houchard        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56715144b0fSOlivier Houchard        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56815144b0fSOlivier Houchard        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
56915144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57015144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57115144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57215144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57315144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57415144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57515144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57615144b0fSOlivier Houchard        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
57715144b0fSOlivier Houchard    };
57815144b0fSOlivier Houchard    int8 shiftCount;
57915144b0fSOlivier Houchard
58015144b0fSOlivier Houchard    shiftCount = 0;
58115144b0fSOlivier Houchard    if ( a < 0x10000 ) {
58215144b0fSOlivier Houchard        shiftCount += 16;
58315144b0fSOlivier Houchard        a <<= 16;
58415144b0fSOlivier Houchard    }
58515144b0fSOlivier Houchard    if ( a < 0x1000000 ) {
58615144b0fSOlivier Houchard        shiftCount += 8;
58715144b0fSOlivier Houchard        a <<= 8;
58815144b0fSOlivier Houchard    }
58915144b0fSOlivier Houchard    shiftCount += countLeadingZerosHigh[ a>>24 ];
59015144b0fSOlivier Houchard    return shiftCount;
59115144b0fSOlivier Houchard
59215144b0fSOlivier Houchard}
59315144b0fSOlivier Houchard
59415144b0fSOlivier Houchard/*
59515144b0fSOlivier Houchard-------------------------------------------------------------------------------
59615144b0fSOlivier HouchardReturns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
59715144b0fSOlivier Houchardequal to the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
59815144b0fSOlivier Houchardreturns 0.
59915144b0fSOlivier Houchard-------------------------------------------------------------------------------
60015144b0fSOlivier Houchard*/
60115144b0fSOlivier HouchardINLINE flag eq64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
60215144b0fSOlivier Houchard{
60315144b0fSOlivier Houchard
60415144b0fSOlivier Houchard    return ( a0 == b0 ) && ( a1 == b1 );
60515144b0fSOlivier Houchard
60615144b0fSOlivier Houchard}
60715144b0fSOlivier Houchard
60815144b0fSOlivier Houchard/*
60915144b0fSOlivier Houchard-------------------------------------------------------------------------------
61015144b0fSOlivier HouchardReturns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
61115144b0fSOlivier Houchardthan or equal to the 64-bit value formed by concatenating `b0' and `b1'.
61215144b0fSOlivier HouchardOtherwise, returns 0.
61315144b0fSOlivier Houchard-------------------------------------------------------------------------------
61415144b0fSOlivier Houchard*/
61515144b0fSOlivier HouchardINLINE flag le64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
61615144b0fSOlivier Houchard{
61715144b0fSOlivier Houchard
61815144b0fSOlivier Houchard    return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
61915144b0fSOlivier Houchard
62015144b0fSOlivier Houchard}
62115144b0fSOlivier Houchard
62215144b0fSOlivier Houchard/*
62315144b0fSOlivier Houchard-------------------------------------------------------------------------------
62415144b0fSOlivier HouchardReturns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
62515144b0fSOlivier Houchardthan the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
62615144b0fSOlivier Houchardreturns 0.
62715144b0fSOlivier Houchard-------------------------------------------------------------------------------
62815144b0fSOlivier Houchard*/
62915144b0fSOlivier HouchardINLINE flag lt64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
63015144b0fSOlivier Houchard{
63115144b0fSOlivier Houchard
63215144b0fSOlivier Houchard    return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
63315144b0fSOlivier Houchard
63415144b0fSOlivier Houchard}
63515144b0fSOlivier Houchard
63615144b0fSOlivier Houchard/*
63715144b0fSOlivier Houchard-------------------------------------------------------------------------------
63815144b0fSOlivier HouchardReturns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
63915144b0fSOlivier Houchardequal to the 64-bit value formed by concatenating `b0' and `b1'.  Otherwise,
64015144b0fSOlivier Houchardreturns 0.
64115144b0fSOlivier Houchard-------------------------------------------------------------------------------
64215144b0fSOlivier Houchard*/
64315144b0fSOlivier HouchardINLINE flag ne64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
64415144b0fSOlivier Houchard{
64515144b0fSOlivier Houchard
64615144b0fSOlivier Houchard    return ( a0 != b0 ) || ( a1 != b1 );
64715144b0fSOlivier Houchard
64815144b0fSOlivier Houchard}
64915144b0fSOlivier Houchard
650