xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/floattisf.c (revision f7f78b3373aafafa211473d7733a8806c0e402c0)
1156cd587Sjoerg /* ===-- floattisf.c - Implement __floattisf -------------------------------===
2156cd587Sjoerg  *
3156cd587Sjoerg  *                     The LLVM Compiler Infrastructure
4156cd587Sjoerg  *
5156cd587Sjoerg  * This file is dual licensed under the MIT and the University of Illinois Open
6156cd587Sjoerg  * Source Licenses. See LICENSE.TXT for details.
7156cd587Sjoerg  *
8156cd587Sjoerg  * ===----------------------------------------------------------------------===
9156cd587Sjoerg  *
10156cd587Sjoerg  * This file implements __floattisf for the compiler_rt library.
11156cd587Sjoerg  *
12156cd587Sjoerg  * ===----------------------------------------------------------------------===
13156cd587Sjoerg  */
14156cd587Sjoerg 
15156cd587Sjoerg #include "int_lib.h"
16156cd587Sjoerg 
17156cd587Sjoerg #ifdef CRT_HAS_128BIT
18156cd587Sjoerg 
19156cd587Sjoerg /* Returns: convert a to a float, rounding toward even. */
20156cd587Sjoerg 
21156cd587Sjoerg /* Assumption: float is a IEEE 32 bit floating point type
22156cd587Sjoerg  *             ti_int is a 128 bit integral type
23156cd587Sjoerg  */
24156cd587Sjoerg 
25156cd587Sjoerg /* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
26156cd587Sjoerg 
27*f7f78b33Sjoerg COMPILER_RT_ABI float
__floattisf(ti_int a)28156cd587Sjoerg __floattisf(ti_int a)
29156cd587Sjoerg {
30156cd587Sjoerg     if (a == 0)
31156cd587Sjoerg         return 0.0F;
32156cd587Sjoerg     const unsigned N = sizeof(ti_int) * CHAR_BIT;
33156cd587Sjoerg     const ti_int s = a >> (N-1);
34156cd587Sjoerg     a = (a ^ s) - s;
35156cd587Sjoerg     int sd = N - __clzti2(a);  /* number of significant digits */
36156cd587Sjoerg     int e = sd - 1;             /* exponent */
37156cd587Sjoerg     if (sd > FLT_MANT_DIG)
38156cd587Sjoerg     {
39156cd587Sjoerg         /*  start:  0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx
40156cd587Sjoerg         * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR
41156cd587Sjoerg         *                                                12345678901234567890123456
42156cd587Sjoerg         *  1 = msb 1 bit
43156cd587Sjoerg         *  P = bit FLT_MANT_DIG-1 bits to the right of 1
44156cd587Sjoerg         *  Q = bit FLT_MANT_DIG bits to the right of 1
45156cd587Sjoerg         *  R = "or" of all bits to the right of Q
46156cd587Sjoerg         */
47156cd587Sjoerg         switch (sd)
48156cd587Sjoerg         {
49156cd587Sjoerg         case FLT_MANT_DIG + 1:
50156cd587Sjoerg             a <<= 1;
51156cd587Sjoerg             break;
52156cd587Sjoerg         case FLT_MANT_DIG + 2:
53156cd587Sjoerg             break;
54156cd587Sjoerg         default:
55156cd587Sjoerg             a = ((tu_int)a >> (sd - (FLT_MANT_DIG+2))) |
56156cd587Sjoerg                 ((a & ((tu_int)(-1) >> ((N + FLT_MANT_DIG+2) - sd))) != 0);
57156cd587Sjoerg         };
58156cd587Sjoerg         /* finish: */
59156cd587Sjoerg         a |= (a & 4) != 0;  /* Or P into R */
60156cd587Sjoerg         ++a;  /* round - this step may add a significant bit */
61156cd587Sjoerg         a >>= 2;  /* dump Q and R */
62156cd587Sjoerg         /* a is now rounded to FLT_MANT_DIG or FLT_MANT_DIG+1 bits */
63156cd587Sjoerg         if (a & ((tu_int)1 << FLT_MANT_DIG))
64156cd587Sjoerg         {
65156cd587Sjoerg             a >>= 1;
66156cd587Sjoerg             ++e;
67156cd587Sjoerg         }
68156cd587Sjoerg         /* a is now rounded to FLT_MANT_DIG bits */
69156cd587Sjoerg     }
70156cd587Sjoerg     else
71156cd587Sjoerg     {
72156cd587Sjoerg         a <<= (FLT_MANT_DIG - sd);
73156cd587Sjoerg         /* a is now rounded to FLT_MANT_DIG bits */
74156cd587Sjoerg     }
75156cd587Sjoerg     float_bits fb;
76156cd587Sjoerg     fb.u = ((su_int)s & 0x80000000) |  /* sign */
77156cd587Sjoerg            ((e + 127) << 23)       |  /* exponent */
78156cd587Sjoerg            ((su_int)a & 0x007FFFFF);   /* mantissa */
79156cd587Sjoerg     return fb.f;
80156cd587Sjoerg }
81156cd587Sjoerg 
82156cd587Sjoerg #endif /* CRT_HAS_128BIT */
83