xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/fp_extend.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 FP_EXTEND_HEADER
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 
src_rep_t_clz_impl(src_rep_t a)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 
src_rep_t_clz_impl(src_rep_t a)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 
extract_sign_from_src(src_rep_t x)133 static inline src_rep_t extract_sign_from_src(src_rep_t x) {
134   const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
135   return (x & srcSignMask) >> (srcBits - 1);
136 }
137 
extract_exp_from_src(src_rep_t x)138 static inline src_rep_t extract_exp_from_src(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 
extract_sig_frac_from_src(src_rep_t x)144 static inline src_rep_t extract_sig_frac_from_src(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
clz_in_sig_frac(src_rep_t sigFrac)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 
construct_dst_rep(dst_rep_t sign,dst_rep_t exp,dst_rep_t sigFrac)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 
srcToRep(src_t x)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 
dstFromRep(dst_rep_t x)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