xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/fp_extend.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-lib/fp_extend.h - low precision -> high precision conversion -*- C
20b57cec5SDimitry Andric //-*-===//
30b57cec5SDimitry Andric //
40b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric // Set source and destination setting
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef FP_EXTEND_HEADER
150b57cec5SDimitry Andric #define FP_EXTEND_HEADER
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "int_lib.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #if defined SRC_SINGLE
200b57cec5SDimitry Andric typedef float src_t;
210b57cec5SDimitry Andric typedef uint32_t src_rep_t;
220b57cec5SDimitry Andric #define SRC_REP_C UINT32_C
235f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
245f757f3fSDimitry Andric static const int srcSigFracBits = 23;
255f757f3fSDimitry Andric // -1 accounts for the sign bit.
265f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
275f757f3fSDimitry Andric static const int srcExpBits = 8;
285ffd83dbSDimitry Andric #define src_rep_t_clz clzsi
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #elif defined SRC_DOUBLE
310b57cec5SDimitry Andric typedef double src_t;
320b57cec5SDimitry Andric typedef uint64_t src_rep_t;
330b57cec5SDimitry Andric #define SRC_REP_C UINT64_C
345f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
355f757f3fSDimitry Andric static const int srcSigFracBits = 52;
365f757f3fSDimitry Andric // -1 accounts for the sign bit.
375f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
385f757f3fSDimitry Andric static const int srcExpBits = 11;
395f757f3fSDimitry Andric 
src_rep_t_clz_impl(src_rep_t a)40*0fca6ea1SDimitry Andric static inline int src_rep_t_clz_impl(src_rep_t a) { return __builtin_clzll(a); }
415f757f3fSDimitry Andric #define src_rep_t_clz src_rep_t_clz_impl
425f757f3fSDimitry Andric 
435f757f3fSDimitry Andric #elif defined SRC_80
445f757f3fSDimitry Andric typedef xf_float src_t;
455f757f3fSDimitry Andric typedef __uint128_t src_rep_t;
465f757f3fSDimitry Andric #define SRC_REP_C (__uint128_t)
475f757f3fSDimitry Andric // sign bit, exponent and significand occupy the lower 80 bits.
485f757f3fSDimitry Andric static const int srcBits = 80;
495f757f3fSDimitry Andric static const int srcSigFracBits = 63;
505f757f3fSDimitry Andric // -1 accounts for the sign bit.
515f757f3fSDimitry Andric // -1 accounts for the explicitly stored integer bit.
525f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1 - 1
535f757f3fSDimitry Andric static const int srcExpBits = 15;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #elif defined SRC_HALF
56e8d8bef9SDimitry Andric #ifdef COMPILER_RT_HAS_FLOAT16
57e8d8bef9SDimitry Andric typedef _Float16 src_t;
58e8d8bef9SDimitry Andric #else
590b57cec5SDimitry Andric typedef uint16_t src_t;
60e8d8bef9SDimitry Andric #endif
610b57cec5SDimitry Andric typedef uint16_t src_rep_t;
620b57cec5SDimitry Andric #define SRC_REP_C UINT16_C
635f757f3fSDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
645f757f3fSDimitry Andric static const int srcSigFracBits = 10;
655f757f3fSDimitry Andric // -1 accounts for the sign bit.
665f757f3fSDimitry Andric // srcBits - srcSigFracBits - 1
675f757f3fSDimitry Andric static const int srcExpBits = 5;
685f757f3fSDimitry Andric 
src_rep_t_clz_impl(src_rep_t a)695f757f3fSDimitry Andric static inline int src_rep_t_clz_impl(src_rep_t a) {
705f757f3fSDimitry Andric   return __builtin_clz(a) - 16;
715f757f3fSDimitry Andric }
725f757f3fSDimitry Andric 
735f757f3fSDimitry Andric #define src_rep_t_clz src_rep_t_clz_impl
740b57cec5SDimitry Andric 
75*0fca6ea1SDimitry Andric #elif defined SRC_BFLOAT16
76*0fca6ea1SDimitry Andric #ifdef COMPILER_RT_HAS_BFLOAT16
77*0fca6ea1SDimitry Andric typedef __bf16 src_t;
78*0fca6ea1SDimitry Andric #else
79*0fca6ea1SDimitry Andric typedef uint16_t src_t;
80*0fca6ea1SDimitry Andric #endif
81*0fca6ea1SDimitry Andric typedef uint16_t src_rep_t;
82*0fca6ea1SDimitry Andric #define SRC_REP_C UINT16_C
83*0fca6ea1SDimitry Andric static const int srcBits = sizeof(src_t) * CHAR_BIT;
84*0fca6ea1SDimitry Andric static const int srcSigFracBits = 7;
85*0fca6ea1SDimitry Andric // -1 accounts for the sign bit.
86*0fca6ea1SDimitry Andric // srcBits - srcSigFracBits - 1
87*0fca6ea1SDimitry Andric static const int srcExpBits = 8;
88*0fca6ea1SDimitry Andric #define src_rep_t_clz __builtin_clz
89*0fca6ea1SDimitry Andric 
900b57cec5SDimitry Andric #else
910b57cec5SDimitry Andric #error Source should be half, single, or double precision!
920b57cec5SDimitry Andric #endif // end source precision
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric #if defined DST_SINGLE
950b57cec5SDimitry Andric typedef float dst_t;
960b57cec5SDimitry Andric typedef uint32_t dst_rep_t;
970b57cec5SDimitry Andric #define DST_REP_C UINT32_C
985f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
995f757f3fSDimitry Andric static const int dstSigFracBits = 23;
1005f757f3fSDimitry Andric // -1 accounts for the sign bit.
1015f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
1025f757f3fSDimitry Andric static const int dstExpBits = 8;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric #elif defined DST_DOUBLE
1050b57cec5SDimitry Andric typedef double dst_t;
1060b57cec5SDimitry Andric typedef uint64_t dst_rep_t;
1070b57cec5SDimitry Andric #define DST_REP_C UINT64_C
1085f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
1095f757f3fSDimitry Andric static const int dstSigFracBits = 52;
1105f757f3fSDimitry Andric // -1 accounts for the sign bit.
1115f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
1125f757f3fSDimitry Andric static const int dstExpBits = 11;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric #elif defined DST_QUAD
1155f757f3fSDimitry Andric typedef tf_float dst_t;
1160b57cec5SDimitry Andric typedef __uint128_t dst_rep_t;
1170b57cec5SDimitry Andric #define DST_REP_C (__uint128_t)
1185f757f3fSDimitry Andric static const int dstBits = sizeof(dst_t) * CHAR_BIT;
1195f757f3fSDimitry Andric static const int dstSigFracBits = 112;
1205f757f3fSDimitry Andric // -1 accounts for the sign bit.
1215f757f3fSDimitry Andric // dstBits - dstSigFracBits - 1
1225f757f3fSDimitry Andric static const int dstExpBits = 15;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric #else
1250b57cec5SDimitry Andric #error Destination should be single, double, or quad precision!
1260b57cec5SDimitry Andric #endif // end destination precision
1270b57cec5SDimitry Andric 
1285f757f3fSDimitry Andric // End of specialization parameters.
1290b57cec5SDimitry Andric 
1305f757f3fSDimitry Andric // TODO: These helper routines should be placed into fp_lib.h
1315f757f3fSDimitry Andric // Currently they depend on macros/constants defined above.
1325f757f3fSDimitry Andric 
extract_sign_from_src(src_rep_t x)1335f757f3fSDimitry Andric static inline src_rep_t extract_sign_from_src(src_rep_t x) {
1345f757f3fSDimitry Andric   const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1);
1355f757f3fSDimitry Andric   return (x & srcSignMask) >> (srcBits - 1);
1365f757f3fSDimitry Andric }
1375f757f3fSDimitry Andric 
extract_exp_from_src(src_rep_t x)1385f757f3fSDimitry Andric static inline src_rep_t extract_exp_from_src(src_rep_t x) {
1395f757f3fSDimitry Andric   const int srcSigBits = srcBits - 1 - srcExpBits;
1405f757f3fSDimitry Andric   const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits;
1415f757f3fSDimitry Andric   return (x & srcExpMask) >> srcSigBits;
1425f757f3fSDimitry Andric }
1435f757f3fSDimitry Andric 
extract_sig_frac_from_src(src_rep_t x)1445f757f3fSDimitry Andric static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) {
1455f757f3fSDimitry Andric   const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1;
1465f757f3fSDimitry Andric   return x & srcSigFracMask;
1475f757f3fSDimitry Andric }
1485f757f3fSDimitry Andric 
1495f757f3fSDimitry Andric #ifdef src_rep_t_clz
clz_in_sig_frac(src_rep_t sigFrac)1505f757f3fSDimitry Andric static inline int clz_in_sig_frac(src_rep_t sigFrac) {
1515f757f3fSDimitry Andric       const int skip = 1 + srcExpBits;
1525f757f3fSDimitry Andric       return src_rep_t_clz(sigFrac) - skip;
1535f757f3fSDimitry Andric }
1545f757f3fSDimitry Andric #endif
1555f757f3fSDimitry Andric 
construct_dst_rep(dst_rep_t sign,dst_rep_t exp,dst_rep_t sigFrac)1565f757f3fSDimitry Andric static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) {
1575f757f3fSDimitry Andric   return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac;
1585f757f3fSDimitry Andric }
1595f757f3fSDimitry Andric 
1605f757f3fSDimitry Andric // Two helper routines for conversion to and from the representation of
1615f757f3fSDimitry Andric // floating-point data as integer values follow.
1625f757f3fSDimitry Andric 
srcToRep(src_t x)1635f757f3fSDimitry Andric static inline src_rep_t srcToRep(src_t x) {
1640b57cec5SDimitry Andric   const union {
1650b57cec5SDimitry Andric     src_t f;
1660b57cec5SDimitry Andric     src_rep_t i;
1670b57cec5SDimitry Andric   } rep = {.f = x};
1680b57cec5SDimitry Andric   return rep.i;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
dstFromRep(dst_rep_t x)1715f757f3fSDimitry Andric static inline dst_t dstFromRep(dst_rep_t x) {
1720b57cec5SDimitry Andric   const union {
1730b57cec5SDimitry Andric     dst_t f;
1740b57cec5SDimitry Andric     dst_rep_t i;
1750b57cec5SDimitry Andric   } rep = {.i = x};
1760b57cec5SDimitry Andric   return rep.f;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric // End helper routines.  Conversion implementation follows.
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric #endif // FP_EXTEND_HEADER
181