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
20typedef float src_t;
21typedef uint32_t src_rep_t;
22#define SRC_REP_C UINT32_C
23static const int srcBits = sizeof(src_t) * CHAR_BIT;
24static const int srcSigFracBits = 23;
25// -1 accounts for the sign bit.
26// srcBits - srcSigFracBits - 1
27static const int srcExpBits = 8;
28#define src_rep_t_clz clzsi
29
30#elif defined SRC_DOUBLE
31typedef double src_t;
32typedef uint64_t src_rep_t;
33#define SRC_REP_C UINT64_C
34static const int srcBits = sizeof(src_t) * CHAR_BIT;
35static const int srcSigFracBits = 52;
36// -1 accounts for the sign bit.
37// srcBits - srcSigFracBits - 1
38static const int srcExpBits = 11;
39
40static 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
53typedef xf_float src_t;
54typedef __uint128_t src_rep_t;
55#define SRC_REP_C (__uint128_t)
56// sign bit, exponent and significand occupy the lower 80 bits.
57static const int srcBits = 80;
58static 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
62static const int srcExpBits = 15;
63
64#elif defined SRC_HALF
65#ifdef COMPILER_RT_HAS_FLOAT16
66typedef _Float16 src_t;
67#else
68typedef uint16_t src_t;
69#endif
70typedef uint16_t src_rep_t;
71#define SRC_REP_C UINT16_C
72static const int srcBits = sizeof(src_t) * CHAR_BIT;
73static const int srcSigFracBits = 10;
74// -1 accounts for the sign bit.
75// srcBits - srcSigFracBits - 1
76static const int srcExpBits = 5;
77
78static 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
86typedef __bf16 src_t;
87#else
88typedef uint16_t src_t;
89#endif
90typedef uint16_t src_rep_t;
91#define SRC_REP_C UINT16_C
92static const int srcBits = sizeof(src_t) * CHAR_BIT;
93static const int srcSigFracBits = 7;
94// -1 accounts for the sign bit.
95// srcBits - srcSigFracBits - 1
96static 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
104typedef float dst_t;
105typedef uint32_t dst_rep_t;
106#define DST_REP_C UINT32_C
107static const int dstBits = sizeof(dst_t) * CHAR_BIT;
108static const int dstSigFracBits = 23;
109// -1 accounts for the sign bit.
110// dstBits - dstSigFracBits - 1
111static const int dstExpBits = 8;
112
113#elif defined DST_DOUBLE
114typedef double dst_t;
115typedef uint64_t dst_rep_t;
116#define DST_REP_C UINT64_C
117static const int dstBits = sizeof(dst_t) * CHAR_BIT;
118static const int dstSigFracBits = 52;
119// -1 accounts for the sign bit.
120// dstBits - dstSigFracBits - 1
121static const int dstExpBits = 11;
122
123#elif defined DST_QUAD
124typedef tf_float dst_t;
125typedef __uint128_t dst_rep_t;
126#define DST_REP_C (__uint128_t)
127static const int dstBits = sizeof(dst_t) * CHAR_BIT;
128static const int dstSigFracBits = 112;
129// -1 accounts for the sign bit.
130// dstBits - dstSigFracBits - 1
131static 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
142static inline src_rep_t extract_sign_from_src(src_rep_t x) {
143 const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
144 return (x & srcSignMask) >> (srcBits - 1);
145}
146
147static inline src_rep_t extract_exp_from_src(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
153static inline src_rep_t extract_sig_frac_from_src(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
159static 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
165static 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
172static 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
180static 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

source code of compiler-rt/lib/builtins/fp_extend.h