xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/fp_trunc.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //=== lib/fp_trunc.h - high precision -> low precision conversion *- C -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Set source and destination precision setting
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef FP_TRUNC_HEADER
140b57cec5SDimitry Andric #define FP_TRUNC_HEADER
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "int_lib.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #if defined SRC_SINGLE
190b57cec5SDimitry Andric typedef float src_t;
200b57cec5SDimitry Andric typedef uint32_t src_rep_t;
210b57cec5SDimitry Andric #define SRC_REP_C UINT32_C
22*5f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
23*5f757f3fSDimitry Andric static const int srcSigFracBits = 23;
24*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
25*5f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
26*5f757f3fSDimitry Andric static const int srcExpBits = 8;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #elif defined SRC_DOUBLE
290b57cec5SDimitry Andric typedef double src_t;
300b57cec5SDimitry Andric typedef uint64_t src_rep_t;
310b57cec5SDimitry Andric #define SRC_REP_C UINT64_C
32*5f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
33*5f757f3fSDimitry Andric static const int srcSigFracBits = 52;
34*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
35*5f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
36*5f757f3fSDimitry Andric static const int srcExpBits = 11;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #elif defined SRC_QUAD
39*5f757f3fSDimitry Andric typedef tf_float src_t;
400b57cec5SDimitry Andric typedef __uint128_t src_rep_t;
410b57cec5SDimitry Andric #define SRC_REP_C (__uint128_t)
42*5f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
43*5f757f3fSDimitry Andric static const int srcSigFracBits = 112;
44*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
45*5f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
46*5f757f3fSDimitry Andric static const int srcExpBits = 15;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric #else
490b57cec5SDimitry Andric #error Source should be double precision or quad precision!
500b57cec5SDimitry Andric #endif // end source precision
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric #if defined DST_DOUBLE
530b57cec5SDimitry Andric typedef double dst_t;
540b57cec5SDimitry Andric typedef uint64_t dst_rep_t;
550b57cec5SDimitry Andric #define DST_REP_C UINT64_C
56*5f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
57*5f757f3fSDimitry Andric static const int dstSigFracBits = 52;
58*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
59*5f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
60*5f757f3fSDimitry Andric static const int dstExpBits = 11;
61*5f757f3fSDimitry Andric 
62*5f757f3fSDimitry Andric #elif defined DST_80
63*5f757f3fSDimitry Andric typedef xf_float dst_t;
64*5f757f3fSDimitry Andric typedef __uint128_t dst_rep_t;
65*5f757f3fSDimitry Andric #define DST_REP_C (__uint128_t)
66*5f757f3fSDimitry Andric static const int dstBits = 80;
67*5f757f3fSDimitry Andric static const int dstSigFracBits = 63;
68*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
69*5f757f3fSDimitry Andric // -1 accounts for the explicitly stored integer bit.
70*5f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1 - 1
71*5f757f3fSDimitry Andric static const int dstExpBits = 15;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric #elif defined DST_SINGLE
740b57cec5SDimitry Andric typedef float dst_t;
750b57cec5SDimitry Andric typedef uint32_t dst_rep_t;
760b57cec5SDimitry Andric #define DST_REP_C UINT32_C
77*5f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
78*5f757f3fSDimitry Andric static const int dstSigFracBits = 23;
79*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
80*5f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
81*5f757f3fSDimitry Andric static const int dstExpBits = 8;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric #elif defined DST_HALF
84e8d8bef9SDimitry Andric #ifdef COMPILER_RT_HAS_FLOAT16
85e8d8bef9SDimitry Andric typedef _Float16 dst_t;
86e8d8bef9SDimitry Andric #else
870b57cec5SDimitry Andric typedef uint16_t dst_t;
88e8d8bef9SDimitry Andric #endif
890b57cec5SDimitry Andric typedef uint16_t dst_rep_t;
900b57cec5SDimitry Andric #define DST_REP_C UINT16_C
91*5f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
92*5f757f3fSDimitry Andric static const int dstSigFracBits = 10;
93*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
94*5f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
95*5f757f3fSDimitry Andric static const int dstExpBits = 5;
960b57cec5SDimitry Andric 
9781ad6265SDimitry Andric #elif defined DST_BFLOAT
9861cfbce3SDimitry Andric typedef __bf16 dst_t;
9981ad6265SDimitry Andric typedef uint16_t dst_rep_t;
10081ad6265SDimitry Andric #define DST_REP_C UINT16_C
101*5f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
102*5f757f3fSDimitry Andric static const int dstSigFracBits = 7;
103*5f757f3fSDimitry Andric // -1 accounts for the sign bit.
104*5f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
105*5f757f3fSDimitry Andric static const int dstExpBits = 8;
10681ad6265SDimitry Andric 
1070b57cec5SDimitry Andric #else
1080b57cec5SDimitry Andric #error Destination should be single precision or double precision!
1090b57cec5SDimitry Andric #endif // end destination precision
1100b57cec5SDimitry Andric 
111*5f757f3fSDimitry Andric // TODO: These helper routines should be placed into fp_lib.h
112*5f757f3fSDimitry Andric // Currently they depend on macros/constants defined above.
113*5f757f3fSDimitry Andric 
114*5f757f3fSDimitry Andric static inline src_rep_t extract_sign_from_src(src_rep_t x) {
115*5f757f3fSDimitry Andric   const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
116*5f757f3fSDimitry Andric   return (x & srcSignMask) >> (srcBits - 1);
117*5f757f3fSDimitry Andric }
118*5f757f3fSDimitry Andric 
119*5f757f3fSDimitry Andric static inline src_rep_t extract_exp_from_src(src_rep_t x) {
120*5f757f3fSDimitry Andric   const int srcSigBits = srcBits - 1 - srcExpBits;
121*5f757f3fSDimitry Andric   const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits;
122*5f757f3fSDimitry Andric   return (x & srcExpMask) >> srcSigBits;
123*5f757f3fSDimitry Andric }
124*5f757f3fSDimitry Andric 
125*5f757f3fSDimitry Andric static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) {
126*5f757f3fSDimitry Andric   const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1;
127*5f757f3fSDimitry Andric   return x & srcSigFracMask;
128*5f757f3fSDimitry Andric }
129*5f757f3fSDimitry Andric 
130*5f757f3fSDimitry Andric static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) {
131*5f757f3fSDimitry Andric   dst_rep_t result = (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
132*5f757f3fSDimitry Andric   // Set the explicit integer bit in F80 if present.
133*5f757f3fSDimitry Andric   if (dstBits == 80 && exp) {
134*5f757f3fSDimitry Andric     result |= (DST_REP_C(1) << dstSigFracBits);
135*5f757f3fSDimitry Andric   }
136*5f757f3fSDimitry Andric   return result;
137*5f757f3fSDimitry Andric }
138*5f757f3fSDimitry Andric 
1390b57cec5SDimitry Andric // End of specialization parameters.  Two helper routines for conversion to and
1400b57cec5SDimitry Andric // from the representation of floating-point data as integer values follow.
1410b57cec5SDimitry Andric 
142*5f757f3fSDimitry Andric static inline src_rep_t srcToRep(src_t x) {
1430b57cec5SDimitry Andric   const union {
1440b57cec5SDimitry Andric     src_t f;
1450b57cec5SDimitry Andric     src_rep_t i;
1460b57cec5SDimitry Andric   } rep = {.f = x};
1470b57cec5SDimitry Andric   return rep.i;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
150*5f757f3fSDimitry Andric static inline dst_t dstFromRep(dst_rep_t x) {
1510b57cec5SDimitry Andric   const union {
1520b57cec5SDimitry Andric     dst_t f;
1530b57cec5SDimitry Andric     dst_rep_t i;
1540b57cec5SDimitry Andric   } rep = {.i = x};
1550b57cec5SDimitry Andric   return rep.f;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric #endif // FP_TRUNC_HEADER
159