1 | //===-lib/fp_extend.h - low precision -> high precision conversion -*- C |
2 | //-*-===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // Set source and destination setting |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef FP_EXTEND_HEADER |
15 | #define |
16 | |
17 | #include "int_lib.h" |
18 | |
19 | #if defined SRC_SINGLE |
20 | typedef float src_t; |
21 | typedef uint32_t src_rep_t; |
22 | #define SRC_REP_C UINT32_C |
23 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
24 | static const int srcSigFracBits = 23; |
25 | // -1 accounts for the sign bit. |
26 | // srcBits - srcSigFracBits - 1 |
27 | static const int srcExpBits = 8; |
28 | #define src_rep_t_clz clzsi |
29 | |
30 | #elif defined SRC_DOUBLE |
31 | typedef double src_t; |
32 | typedef uint64_t src_rep_t; |
33 | #define SRC_REP_C UINT64_C |
34 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
35 | static const int srcSigFracBits = 52; |
36 | // -1 accounts for the sign bit. |
37 | // srcBits - srcSigFracBits - 1 |
38 | static const int srcExpBits = 11; |
39 | |
40 | static inline int src_rep_t_clz_impl(src_rep_t a) { |
41 | #if defined __LP64__ |
42 | return __builtin_clzl(a); |
43 | #else |
44 | if (a & REP_C(0xffffffff00000000)) |
45 | return clzsi(a >> 32); |
46 | else |
47 | return 32 + clzsi(a & REP_C(0xffffffff)); |
48 | #endif |
49 | } |
50 | #define src_rep_t_clz src_rep_t_clz_impl |
51 | |
52 | #elif defined SRC_80 |
53 | typedef xf_float src_t; |
54 | typedef __uint128_t src_rep_t; |
55 | #define SRC_REP_C (__uint128_t) |
56 | // sign bit, exponent and significand occupy the lower 80 bits. |
57 | static const int srcBits = 80; |
58 | static const int srcSigFracBits = 63; |
59 | // -1 accounts for the sign bit. |
60 | // -1 accounts for the explicitly stored integer bit. |
61 | // srcBits - srcSigFracBits - 1 - 1 |
62 | static const int srcExpBits = 15; |
63 | |
64 | #elif defined SRC_HALF |
65 | #ifdef COMPILER_RT_HAS_FLOAT16 |
66 | typedef _Float16 src_t; |
67 | #else |
68 | typedef uint16_t src_t; |
69 | #endif |
70 | typedef uint16_t src_rep_t; |
71 | #define SRC_REP_C UINT16_C |
72 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
73 | static const int srcSigFracBits = 10; |
74 | // -1 accounts for the sign bit. |
75 | // srcBits - srcSigFracBits - 1 |
76 | static const int srcExpBits = 5; |
77 | |
78 | static inline int src_rep_t_clz_impl(src_rep_t a) { |
79 | return __builtin_clz(a) - 16; |
80 | } |
81 | |
82 | #define src_rep_t_clz src_rep_t_clz_impl |
83 | |
84 | #elif defined SRC_BFLOAT16 |
85 | #ifdef COMPILER_RT_HAS_BFLOAT16 |
86 | typedef __bf16 src_t; |
87 | #else |
88 | typedef uint16_t src_t; |
89 | #endif |
90 | typedef uint16_t src_rep_t; |
91 | #define SRC_REP_C UINT16_C |
92 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
93 | static const int srcSigFracBits = 7; |
94 | // -1 accounts for the sign bit. |
95 | // srcBits - srcSigFracBits - 1 |
96 | static const int srcExpBits = 8; |
97 | #define src_rep_t_clz __builtin_clz |
98 | |
99 | #else |
100 | #error Source should be half, single, or double precision! |
101 | #endif // end source precision |
102 | |
103 | #if defined DST_SINGLE |
104 | typedef float dst_t; |
105 | typedef uint32_t dst_rep_t; |
106 | #define DST_REP_C UINT32_C |
107 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
108 | static const int dstSigFracBits = 23; |
109 | // -1 accounts for the sign bit. |
110 | // dstBits - dstSigFracBits - 1 |
111 | static const int dstExpBits = 8; |
112 | |
113 | #elif defined DST_DOUBLE |
114 | typedef double dst_t; |
115 | typedef uint64_t dst_rep_t; |
116 | #define DST_REP_C UINT64_C |
117 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
118 | static const int dstSigFracBits = 52; |
119 | // -1 accounts for the sign bit. |
120 | // dstBits - dstSigFracBits - 1 |
121 | static const int dstExpBits = 11; |
122 | |
123 | #elif defined DST_QUAD |
124 | typedef tf_float dst_t; |
125 | typedef __uint128_t dst_rep_t; |
126 | #define DST_REP_C (__uint128_t) |
127 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
128 | static const int dstSigFracBits = 112; |
129 | // -1 accounts for the sign bit. |
130 | // dstBits - dstSigFracBits - 1 |
131 | static const int dstExpBits = 15; |
132 | |
133 | #else |
134 | #error Destination should be single, double, or quad precision! |
135 | #endif // end destination precision |
136 | |
137 | // End of specialization parameters. |
138 | |
139 | // TODO: These helper routines should be placed into fp_lib.h |
140 | // Currently they depend on macros/constants defined above. |
141 | |
142 | static inline src_rep_t (src_rep_t x) { |
143 | const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); |
144 | return (x & srcSignMask) >> (srcBits - 1); |
145 | } |
146 | |
147 | static inline src_rep_t (src_rep_t x) { |
148 | const int srcSigBits = srcBits - 1 - srcExpBits; |
149 | const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; |
150 | return (x & srcExpMask) >> srcSigBits; |
151 | } |
152 | |
153 | static inline src_rep_t (src_rep_t x) { |
154 | const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; |
155 | return x & srcSigFracMask; |
156 | } |
157 | |
158 | #ifdef src_rep_t_clz |
159 | static inline int clz_in_sig_frac(src_rep_t sigFrac) { |
160 | const int skip = 1 + srcExpBits; |
161 | return src_rep_t_clz(sigFrac) - skip; |
162 | } |
163 | #endif |
164 | |
165 | static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { |
166 | return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; |
167 | } |
168 | |
169 | // Two helper routines for conversion to and from the representation of |
170 | // floating-point data as integer values follow. |
171 | |
172 | static inline src_rep_t srcToRep(src_t x) { |
173 | const union { |
174 | src_t f; |
175 | src_rep_t i; |
176 | } rep = {.f = x}; |
177 | return rep.i; |
178 | } |
179 | |
180 | static inline dst_t dstFromRep(dst_rep_t x) { |
181 | const union { |
182 | dst_t f; |
183 | dst_rep_t i; |
184 | } rep = {.i = x}; |
185 | return rep.f; |
186 | } |
187 | // End helper routines. Conversion implementation follows. |
188 | |
189 | #endif // FP_EXTEND_HEADER |
190 | |