xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/fp_extend.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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
230b57cec5SDimitry Andric static const int srcSigBits = 23;
245ffd83dbSDimitry Andric #define src_rep_t_clz clzsi
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #elif defined SRC_DOUBLE
270b57cec5SDimitry Andric typedef double src_t;
280b57cec5SDimitry Andric typedef uint64_t src_rep_t;
290b57cec5SDimitry Andric #define SRC_REP_C UINT64_C
300b57cec5SDimitry Andric static const int srcSigBits = 52;
310b57cec5SDimitry Andric static __inline int src_rep_t_clz(src_rep_t a) {
320b57cec5SDimitry Andric #if defined __LP64__
330b57cec5SDimitry Andric   return __builtin_clzl(a);
340b57cec5SDimitry Andric #else
350b57cec5SDimitry Andric   if (a & REP_C(0xffffffff00000000))
360b57cec5SDimitry Andric     return __builtin_clz(a >> 32);
370b57cec5SDimitry Andric   else
380b57cec5SDimitry Andric     return 32 + __builtin_clz(a & REP_C(0xffffffff));
390b57cec5SDimitry Andric #endif
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #elif defined SRC_HALF
43*e8d8bef9SDimitry Andric #ifdef COMPILER_RT_HAS_FLOAT16
44*e8d8bef9SDimitry Andric typedef _Float16 src_t;
45*e8d8bef9SDimitry Andric #else
460b57cec5SDimitry Andric typedef uint16_t src_t;
47*e8d8bef9SDimitry Andric #endif
480b57cec5SDimitry Andric typedef uint16_t src_rep_t;
490b57cec5SDimitry Andric #define SRC_REP_C UINT16_C
500b57cec5SDimitry Andric static const int srcSigBits = 10;
510b57cec5SDimitry Andric #define src_rep_t_clz __builtin_clz
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #else
540b57cec5SDimitry Andric #error Source should be half, single, or double precision!
550b57cec5SDimitry Andric #endif // end source precision
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric #if defined DST_SINGLE
580b57cec5SDimitry Andric typedef float dst_t;
590b57cec5SDimitry Andric typedef uint32_t dst_rep_t;
600b57cec5SDimitry Andric #define DST_REP_C UINT32_C
610b57cec5SDimitry Andric static const int dstSigBits = 23;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric #elif defined DST_DOUBLE
640b57cec5SDimitry Andric typedef double dst_t;
650b57cec5SDimitry Andric typedef uint64_t dst_rep_t;
660b57cec5SDimitry Andric #define DST_REP_C UINT64_C
670b57cec5SDimitry Andric static const int dstSigBits = 52;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric #elif defined DST_QUAD
700b57cec5SDimitry Andric typedef long double dst_t;
710b57cec5SDimitry Andric typedef __uint128_t dst_rep_t;
720b57cec5SDimitry Andric #define DST_REP_C (__uint128_t)
730b57cec5SDimitry Andric static const int dstSigBits = 112;
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric #else
760b57cec5SDimitry Andric #error Destination should be single, double, or quad precision!
770b57cec5SDimitry Andric #endif // end destination precision
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric // End of specialization parameters.  Two helper routines for conversion to and
800b57cec5SDimitry Andric // from the representation of floating-point data as integer values follow.
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric static __inline src_rep_t srcToRep(src_t x) {
830b57cec5SDimitry Andric   const union {
840b57cec5SDimitry Andric     src_t f;
850b57cec5SDimitry Andric     src_rep_t i;
860b57cec5SDimitry Andric   } rep = {.f = x};
870b57cec5SDimitry Andric   return rep.i;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric static __inline dst_t dstFromRep(dst_rep_t x) {
910b57cec5SDimitry Andric   const union {
920b57cec5SDimitry Andric     dst_t f;
930b57cec5SDimitry Andric     dst_rep_t i;
940b57cec5SDimitry Andric   } rep = {.i = x};
950b57cec5SDimitry Andric   return rep.f;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric // End helper routines.  Conversion implementation follows.
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric #endif // FP_EXTEND_HEADER
100