floattidf.c revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
1b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham/* ===-- floattidf.c - Implement __floattidf -------------------------------===
224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *
324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *                    The LLVM Compiler Infrastructure
424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *
524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * This file is dual licensed under the MIT and the University of Illinois Open
624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * Source Licenses. See LICENSE.TXT for details.
724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *
824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner * ===----------------------------------------------------------------------===
924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner *
10d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea * This file implements __floattidf for the compiler_rt library.
11d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea *
12b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham * ===----------------------------------------------------------------------===
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner */
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "int_lib.h"
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#ifdef CRT_HAS_128BIT
18b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham
19b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham/* Returns: convert a to a double, rounding toward even.*/
204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner/* Assumption: double is a IEEE 64 bit floating point type
224f385f181467701d2c5225f2c954ed5771e0763fJim Ingham *            ti_int is a 128 bit integral type
23b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham */
24b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
266e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton
276e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonCOMPILER_RT_ABI double
286e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton__floattidf(ti_int a)
2973844aa19a7360b662e2be710fc3c969d6c86606Greg Clayton{
30b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    if (a == 0)
3149ce8969d3154e1560106cfe530444c09410f217Greg Clayton        return 0.0;
32b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    const unsigned N = sizeof(ti_int) * CHAR_BIT;
33b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    const ti_int s = a >> (N-1);
34b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    a = (a ^ s) - s;
35b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    int sd = N - __clzti2(a);  /* number of significant digits */
36b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham    int e = sd - 1;             /* exponent */
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (sd > DBL_MANT_DIG)
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        /* start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
40ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar         *  finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
41ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar         *                                               12345678901234567890123456
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner         * 1 = msb 1 bit
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner         * P = bit DBL_MANT_DIG-1 bits to the right of 1
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner         * Q = bit DBL_MANT_DIG bits to the right of 1
456507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham         * R = "or" of all bits to the right of Q
4612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham         */
4712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        switch (sd)
486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {
496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        case DBL_MANT_DIG + 1:
506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            a <<= 1;
516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            break;
526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        case DBL_MANT_DIG + 2:
536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            break;
546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        default:
556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            a = ((tu_int)a >> (sd - (DBL_MANT_DIG+2))) |
566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0);
576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        };
586507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        /* finish: */
596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        a |= (a & 4) != 0;  /* Or P into R */
606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        ++a;  /* round - this step may add a significant bit */
616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        a >>= 2;  /* dump Q and R */
626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */
636507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        if (a & ((tu_int)1 << DBL_MANT_DIG))
646507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {
656507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            a >>= 1;
666507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            ++e;
676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }
686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        /* a is now rounded to DBL_MANT_DIG bits */
696507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }
706507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    else
716507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {
726507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        a <<= (DBL_MANT_DIG - sd);
736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        /* a is now rounded to DBL_MANT_DIG bits */
746507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }
756507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    double_bits fb;
766507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    fb.u.s.high = ((su_int)s & 0x80000000) |        /* sign */
776507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                ((e + 1023) << 20)      |        /* exponent */
786507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */
796507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    fb.u.s.low = (su_int)a;                         /* mantissa-low */
806507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    return fb.f;
816507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham}
826507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
836507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham#endif /* CRT_HAS_128BIT */
846507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham