177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao/* ===-- floatuntidf.c - Implement __floatuntidf ---------------------------===
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 __floatuntidf 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 *             tu_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__floatuntidf(tu_int a)
3277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao{
3377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    if (a == 0)
3477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        return 0.0;
3577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    const unsigned N = sizeof(tu_int) * CHAR_BIT;
3677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int sd = N - __clzti2(a);  /* number of significant digits */
3777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    int e = sd - 1;             /* exponent */
3877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    if (sd > DBL_MANT_DIG)
3977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    {
4077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /*  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
4177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
4277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *                                                12345678901234567890123456
4377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  1 = msb 1 bit
4477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  P = bit DBL_MANT_DIG-1 bits to the right of 1
4577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  Q = bit DBL_MANT_DIG bits to the right of 1
4677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao         *  R = "or" of all bits to the right of Q
4777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao	 */
4877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        switch (sd)
4977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        {
5077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        case DBL_MANT_DIG + 1:
5177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a <<= 1;
5277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            break;
5377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        case DBL_MANT_DIG + 2:
5477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            break;
5577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        default:
5677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a = (a >> (sd - (DBL_MANT_DIG+2))) |
5777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                ((a & ((tu_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0);
5877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        };
5977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* finish: */
6077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a |= (a & 4) != 0;  /* Or P into R */
6177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        ++a;  /* round - this step may add a significant bit */
6277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a >>= 2;  /* dump Q and R */
6377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */
6477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        if (a & ((tu_int)1 << DBL_MANT_DIG))
6577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        {
6677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            a >>= 1;
6777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao            ++e;
6877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        }
6977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG bits */
7077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    }
7177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    else
7277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    {
7377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        a <<= (DBL_MANT_DIG - sd);
7477ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao        /* a is now rounded to DBL_MANT_DIG bits */
7577ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    }
7677ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    double_bits fb;
7777ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    fb.u.s.high = ((e + 1023) << 20)      |        /* exponent */
7877ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao                ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */
7977ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    fb.u.s.low = (su_int)a;                         /* mantissa-low */
8077ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao    return fb.f;
8177ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao}
8277ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao
8377ed6142daed1e068fbda64405d0de9845e40e1Shih-wei Liao#endif
84