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) { return __builtin_clzll(a); } |
41 | #define src_rep_t_clz src_rep_t_clz_impl |
42 | |
43 | #elif defined SRC_80 |
44 | typedef xf_float src_t; |
45 | typedef __uint128_t src_rep_t; |
46 | #define SRC_REP_C (__uint128_t) |
47 | // sign bit, exponent and significand occupy the lower 80 bits. |
48 | static const int srcBits = 80; |
49 | static const int srcSigFracBits = 63; |
50 | // -1 accounts for the sign bit. |
51 | // -1 accounts for the explicitly stored integer bit. |
52 | // srcBits - srcSigFracBits - 1 - 1 |
53 | static const int srcExpBits = 15; |
54 | |
55 | #elif defined SRC_HALF |
56 | #ifdef COMPILER_RT_HAS_FLOAT16 |
57 | typedef _Float16 src_t; |
58 | #else |
59 | typedef uint16_t src_t; |
60 | #endif |
61 | typedef uint16_t src_rep_t; |
62 | #define SRC_REP_C UINT16_C |
63 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
64 | static const int srcSigFracBits = 10; |
65 | // -1 accounts for the sign bit. |
66 | // srcBits - srcSigFracBits - 1 |
67 | static const int srcExpBits = 5; |
68 | |
69 | static inline int src_rep_t_clz_impl(src_rep_t a) { |
70 | return __builtin_clz(a) - 16; |
71 | } |
72 | |
73 | #define src_rep_t_clz src_rep_t_clz_impl |
74 | |
75 | #elif defined SRC_BFLOAT16 |
76 | #ifdef COMPILER_RT_HAS_BFLOAT16 |
77 | typedef __bf16 src_t; |
78 | #else |
79 | typedef uint16_t src_t; |
80 | #endif |
81 | typedef uint16_t src_rep_t; |
82 | #define SRC_REP_C UINT16_C |
83 | static const int srcBits = sizeof(src_t) * CHAR_BIT; |
84 | static const int srcSigFracBits = 7; |
85 | // -1 accounts for the sign bit. |
86 | // srcBits - srcSigFracBits - 1 |
87 | static const int srcExpBits = 8; |
88 | #define src_rep_t_clz __builtin_clz |
89 | |
90 | #else |
91 | #error Source should be half, single, or double precision! |
92 | #endif // end source precision |
93 | |
94 | #if defined DST_SINGLE |
95 | typedef float dst_t; |
96 | typedef uint32_t dst_rep_t; |
97 | #define DST_REP_C UINT32_C |
98 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
99 | static const int dstSigFracBits = 23; |
100 | // -1 accounts for the sign bit. |
101 | // dstBits - dstSigFracBits - 1 |
102 | static const int dstExpBits = 8; |
103 | |
104 | #elif defined DST_DOUBLE |
105 | typedef double dst_t; |
106 | typedef uint64_t dst_rep_t; |
107 | #define DST_REP_C UINT64_C |
108 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
109 | static const int dstSigFracBits = 52; |
110 | // -1 accounts for the sign bit. |
111 | // dstBits - dstSigFracBits - 1 |
112 | static const int dstExpBits = 11; |
113 | |
114 | #elif defined DST_QUAD |
115 | typedef tf_float dst_t; |
116 | typedef __uint128_t dst_rep_t; |
117 | #define DST_REP_C (__uint128_t) |
118 | static const int dstBits = sizeof(dst_t) * CHAR_BIT; |
119 | static const int dstSigFracBits = 112; |
120 | // -1 accounts for the sign bit. |
121 | // dstBits - dstSigFracBits - 1 |
122 | static const int dstExpBits = 15; |
123 | |
124 | #else |
125 | #error Destination should be single, double, or quad precision! |
126 | #endif // end destination precision |
127 | |
128 | // End of specialization parameters. |
129 | |
130 | // TODO: These helper routines should be placed into fp_lib.h |
131 | // Currently they depend on macros/constants defined above. |
132 | |
133 | static inline src_rep_t (src_rep_t x) { |
134 | const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); |
135 | return (x & srcSignMask) >> (srcBits - 1); |
136 | } |
137 | |
138 | static inline src_rep_t (src_rep_t x) { |
139 | const int srcSigBits = srcBits - 1 - srcExpBits; |
140 | const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; |
141 | return (x & srcExpMask) >> srcSigBits; |
142 | } |
143 | |
144 | static inline src_rep_t (src_rep_t x) { |
145 | const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; |
146 | return x & srcSigFracMask; |
147 | } |
148 | |
149 | #ifdef src_rep_t_clz |
150 | static inline int clz_in_sig_frac(src_rep_t sigFrac) { |
151 | const int skip = 1 + srcExpBits; |
152 | return src_rep_t_clz(sigFrac) - skip; |
153 | } |
154 | #endif |
155 | |
156 | static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { |
157 | return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; |
158 | } |
159 | |
160 | // Two helper routines for conversion to and from the representation of |
161 | // floating-point data as integer values follow. |
162 | |
163 | static inline src_rep_t srcToRep(src_t x) { |
164 | const union { |
165 | src_t f; |
166 | src_rep_t i; |
167 | } rep = {.f = x}; |
168 | return rep.i; |
169 | } |
170 | |
171 | static inline dst_t dstFromRep(dst_rep_t x) { |
172 | const union { |
173 | dst_t f; |
174 | dst_rep_t i; |
175 | } rep = {.i = x}; |
176 | return rep.f; |
177 | } |
178 | // End helper routines. Conversion implementation follows. |
179 | |
180 | #endif // FP_EXTEND_HEADER |
181 | |