137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/*===-- floatundisf.c - Implement __floatundisf ---------------------------===
237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *                     The LLVM Compiler Infrastructure
437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
59ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * This file is dual licensed under the MIT and the University of Illinois Open
69ad441ffec97db647fee3725b3424284fb913e14Howard Hinnant * Source Licenses. See LICENSE.TXT for details.
737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * ===----------------------------------------------------------------------===
937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
1037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan * This file implements __floatundisf for the compiler_rt library.
1137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *
1237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *===----------------------------------------------------------------------===
1337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */
14b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
1537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Returns: convert a to a float, rounding toward even. */
16b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
1737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* Assumption: float is a IEEE 32 bit floating point type
1837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan *            du_int is a 64 bit integral type
1937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan */
20b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
2137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
22b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar
2337b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov#include "int_lib.h"
2437b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov
250193b74976719b8aea4cb8874ba36b75836a8d6eChandler CarruthARM_EABI_FNALIAS(ul2f, floatundisf)
2637b97d1cf4501b94347e0b4e880f4b25825a289fAnton Korobeynikov
271c5f89b1dd741135a4007ab577723d422f421eecAnton KorobeynikovCOMPILER_RT_ABI float
28b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar__floatundisf(du_int a)
29b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar{
30b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (a == 0)
31b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        return 0.0F;
32b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    const unsigned N = sizeof(du_int) * CHAR_BIT;
3337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan    int sd = N - __builtin_clzll(a);  /* number of significant digits */
3437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan    int e = sd - 1;             /* 8 exponent */
35b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    if (sd > FLT_MANT_DIG)
36b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
3737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /*  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
3837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *  finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
3937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *                                                12345678901234567890123456
4037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *  1 = msb 1 bit
4137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *  P = bit FLT_MANT_DIG-1 bits to the right of 1
4237a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *  Q = bit FLT_MANT_DIG bits to the right of 1
4337a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         *  R = "or" of all bits to the right of Q
4437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan         */
45b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        switch (sd)
46b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
47b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        case FLT_MANT_DIG + 1:
48b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            a <<= 1;
49b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            break;
50b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        case FLT_MANT_DIG + 2:
51b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            break;
52b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        default:
53b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            a = (a >> (sd - (FLT_MANT_DIG+2))) |
54b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar                ((a & ((du_int)(-1) >> ((N + FLT_MANT_DIG+2) - sd))) != 0);
55b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        };
5637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* finish: */
5737a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        a |= (a & 4) != 0;  /* Or P into R */
5837a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        ++a;  /* round - this step may add a significant bit */
5937a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        a >>= 2;  /* dump Q and R */
6037a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits */
61b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        if (a & ((du_int)1 << FLT_MANT_DIG))
62b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        {
63b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            a >>= 1;
64b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar            ++e;
65b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        }
6637a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* a is now rounded to FLT_MANT_DIG bits */
67b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
68b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    else
69b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    {
70b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar        a <<= (FLT_MANT_DIG - sd);
7137a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan        /* a is now rounded to FLT_MANT_DIG bits */
72b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    }
73b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    float_bits fb;
7437a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan    fb.u = ((e + 127) << 23)       |  /* exponent */
7537a6a455466e5b197311771a777ab241e471ed8aEdward O'Callaghan           ((su_int)a & 0x007FFFFF);  /* mantissa */
76b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar    return fb.f;
77b3a6901e66f55b35aa9e01bcb24134e6a65ea004Daniel Dunbar}
78