1 /* ===-- floatdixf.c - Implement __floatdixf -------------------------------===
2  *
3  * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  * See https://llvm.org/LICENSE.txt for license information.
5  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  *
7  * ===----------------------------------------------------------------------===
8  *
9  * This file implements __floatdixf for the compiler_rt library.
10  *
11  * ===----------------------------------------------------------------------===
12  */
13 
14 #if !_ARCH_PPC
15 
16 #include "int_lib.h"
17 
18 /* Returns: convert a to a long double, rounding toward even. */
19 
20 /* Assumption: long double is a IEEE 80 bit floating point type padded to 128
21  * bits di_int is a 64 bit integral type
22  */
23 
24 /* gggg gggg gggg gggg gggg gggg gggg gggg | gggg gggg gggg gggg seee eeee eeee
25  * eeee | 1mmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm
26  * mmmm mmmm mmmm
27  */
28 
29 COMPILER_RT_ABI long double __floatdixf(di_int a) {
30   if (a == 0)
31     return 0.0;
32   const unsigned N = sizeof(di_int) * CHAR_BIT;
33   const di_int s = a >> (N - 1);
34   a = (a ^ s) - s;
35   int clz = __builtin_clzll(a);
36   int e = (N - 1) - clz; /* exponent */
37   long_double_bits fb;
38   fb.u.high.s.low = ((su_int)s & 0x00008000) | /* sign */
39                     (e + 16383);               /* exponent */
40   fb.u.low.all = a << clz;                     /* mantissa */
41   return fb.f;
42 }
43 
44 #endif /* !_ARCH_PPC */
45