177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* ===-- floattidf.c - Implement __floattidf -------------------------------===
277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *                    The LLVM Compiler Infrastructure
477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * This file is distributed under the University of Illinois Open Source
677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * License. See LICENSE.TXT for details.
777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * ===----------------------------------------------------------------------===
977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
1077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * This file implements __floattidf for the compiler_rt library.
1177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *
1277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao * ===----------------------------------------------------------------------===
1377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */
1477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
1577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#if __x86_64
1677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
1777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include "int_lib.h"
1877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#include <float.h>
1977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Returns: convert a to a double, rounding toward even.*/
2177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* Assumption: double is a IEEE 64 bit floating point type
2377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao *            ti_int is a 128 bit integral type
2477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao */
2577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
2777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
2877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaosi_int __clzti2(ti_int a);
2977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
3077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liaodouble
3177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao__floattidf(ti_int a)
3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{
3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    if (a == 0)
3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        return 0.0;
3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    const unsigned N = sizeof(ti_int) * CHAR_BIT;
3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    const ti_int s = a >> (N-1);
3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    a = (a ^ s) - s;
3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int sd = N - __clzti2(a);  /* number of significant digits */
3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int e = sd - 1;             /* exponent */
4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    if (sd > DBL_MANT_DIG)
4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    {
4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *                                               12345678901234567890123456
4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         * 1 = msb 1 bit
4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         * P = bit DBL_MANT_DIG-1 bits to the right of 1
4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         * Q = bit DBL_MANT_DIG bits to the right of 1
4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         * R = "or" of all bits to the right of Q
4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         */
5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        switch (sd)
5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        {
5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        case DBL_MANT_DIG + 1:
5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a <<= 1;
5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            break;
5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        case DBL_MANT_DIG + 2:
5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            break;
5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        default:
5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a = ((tu_int)a >> (sd - (DBL_MANT_DIG+2))) |
5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0);
6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        };
6177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* finish: */
6277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a |= (a & 4) != 0;  /* Or P into R */
6377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        ++a;  /* round - this step may add a significant bit */
6477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a >>= 2;  /* dump Q and R */
6577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */
6677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        if (a & ((tu_int)1 << DBL_MANT_DIG))
6777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        {
6877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a >>= 1;
6977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            ++e;
7077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        }
7177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG bits */
7277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    }
7377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    else
7477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    {
7577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a <<= (DBL_MANT_DIG - sd);
7677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG bits */
7777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    }
7877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    double_bits fb;
7977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    fb.u.s.high = ((su_int)s & 0x80000000) |        /* sign */
8077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                ((e + 1023) << 20)      |        /* exponent */
8177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */
8277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    fb.u.s.low = (su_int)a;                         /* mantissa-low */
8377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    return fb.f;
8477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao}
8577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
8677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif
87