]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | /*===-- floatdidf.c - Implement __floatdidf -------------------------------=== |
2 | * | |
3 | * The LLVM Compiler Infrastructure | |
4 | * | |
5 | * This file is dual licensed under the MIT and the University of Illinois Open | |
6 | * Source Licenses. See LICENSE.TXT for details. | |
7 | * | |
8 | *===----------------------------------------------------------------------=== | |
9 | * | |
10 | * This file implements __floatdidf for the compiler_rt library. | |
11 | * | |
12 | *===----------------------------------------------------------------------=== | |
13 | */ | |
14 | ||
15 | #include "int_lib.h" | |
16 | ||
17 | /* Returns: convert a to a double, rounding toward even. */ | |
18 | ||
5bcae85e | 19 | /* Assumption: double is a IEEE 64 bit floating point type |
1a4d82fc JJ |
20 | * di_int is a 64 bit integral type |
21 | */ | |
22 | ||
23 | /* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */ | |
24 | ||
25 | ARM_EABI_FNALIAS(l2d, floatdidf) | |
26 | ||
27 | #ifndef __SOFT_FP__ | |
28 | /* Support for systems that have hardware floating-point; we'll set the inexact flag | |
29 | * as a side-effect of this computation. | |
30 | */ | |
31 | ||
32 | COMPILER_RT_ABI double | |
33 | __floatdidf(di_int a) | |
34 | { | |
5bcae85e SL |
35 | static const double twop52 = 4503599627370496.0; // 0x1.0p52 |
36 | static const double twop32 = 4294967296.0; // 0x1.0p32 | |
37 | ||
38 | union { int64_t x; double d; } low = { .d = twop52 }; | |
39 | ||
40 | const double high = (int32_t)(a >> 32) * twop32; | |
41 | low.x |= a & INT64_C(0x00000000ffffffff); | |
42 | ||
43 | const double result = (high - twop52) + low.d; | |
44 | return result; | |
1a4d82fc JJ |
45 | } |
46 | ||
47 | #else | |
48 | /* Support for systems that don't have hardware floating-point; there are no flags to | |
49 | * set, and we don't want to code-gen to an unknown soft-float implementation. | |
50 | */ | |
51 | ||
52 | COMPILER_RT_ABI double | |
53 | __floatdidf(di_int a) | |
54 | { | |
55 | if (a == 0) | |
56 | return 0.0; | |
57 | const unsigned N = sizeof(di_int) * CHAR_BIT; | |
58 | const di_int s = a >> (N-1); | |
59 | a = (a ^ s) - s; | |
60 | int sd = N - __builtin_clzll(a); /* number of significant digits */ | |
61 | int e = sd - 1; /* exponent */ | |
62 | if (sd > DBL_MANT_DIG) | |
63 | { | |
64 | /* start: 0000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQxxxxxxxxxxxxxxxxxx | |
65 | * finish: 000000000000000000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxPQR | |
66 | * 12345678901234567890123456 | |
67 | * 1 = msb 1 bit | |
68 | * P = bit DBL_MANT_DIG-1 bits to the right of 1 | |
69 | * Q = bit DBL_MANT_DIG bits to the right of 1 | |
70 | * R = "or" of all bits to the right of Q | |
71 | */ | |
72 | switch (sd) | |
73 | { | |
74 | case DBL_MANT_DIG + 1: | |
75 | a <<= 1; | |
76 | break; | |
77 | case DBL_MANT_DIG + 2: | |
78 | break; | |
79 | default: | |
80 | a = ((du_int)a >> (sd - (DBL_MANT_DIG+2))) | | |
81 | ((a & ((du_int)(-1) >> ((N + DBL_MANT_DIG+2) - sd))) != 0); | |
82 | }; | |
83 | /* finish: */ | |
84 | a |= (a & 4) != 0; /* Or P into R */ | |
85 | ++a; /* round - this step may add a significant bit */ | |
86 | a >>= 2; /* dump Q and R */ | |
87 | /* a is now rounded to DBL_MANT_DIG or DBL_MANT_DIG+1 bits */ | |
88 | if (a & ((du_int)1 << DBL_MANT_DIG)) | |
89 | { | |
90 | a >>= 1; | |
91 | ++e; | |
92 | } | |
93 | /* a is now rounded to DBL_MANT_DIG bits */ | |
94 | } | |
95 | else | |
96 | { | |
97 | a <<= (DBL_MANT_DIG - sd); | |
98 | /* a is now rounded to DBL_MANT_DIG bits */ | |
99 | } | |
100 | double_bits fb; | |
5bcae85e SL |
101 | fb.u.s.high = ((su_int)s & 0x80000000) | /* sign */ |
102 | ((e + 1023) << 20) | /* exponent */ | |
103 | ((su_int)(a >> 32) & 0x000FFFFF); /* mantissa-high */ | |
104 | fb.u.s.low = (su_int)a; /* mantissa-low */ | |
1a4d82fc JJ |
105 | return fb.f; |
106 | } | |
107 | #endif |