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 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 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 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 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 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 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 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 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 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