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#else 85#error Source should be half, single, or double precision! 86#endif // end source precision 87 88#if defined DST_SINGLE 89typedef float dst_t; 90typedef uint32_t dst_rep_t; 91#define DST_REP_C UINT32_C 92static const int dstBits = sizeof(dst_t) * CHAR_BIT; 93static const int dstSigFracBits = 23; 94// -1 accounts for the sign bit. 95// dstBits - dstSigFracBits - 1 96static const int dstExpBits = 8; 97 98#elif defined DST_DOUBLE 99typedef double dst_t; 100typedef uint64_t dst_rep_t; 101#define DST_REP_C UINT64_C 102static const int dstBits = sizeof(dst_t) * CHAR_BIT; 103static const int dstSigFracBits = 52; 104// -1 accounts for the sign bit. 105// dstBits - dstSigFracBits - 1 106static const int dstExpBits = 11; 107 108#elif defined DST_QUAD 109typedef tf_float dst_t; 110typedef __uint128_t dst_rep_t; 111#define DST_REP_C (__uint128_t) 112static const int dstBits = sizeof(dst_t) * CHAR_BIT; 113static const int dstSigFracBits = 112; 114// -1 accounts for the sign bit. 115// dstBits - dstSigFracBits - 1 116static const int dstExpBits = 15; 117 118#else 119#error Destination should be single, double, or quad precision! 120#endif // end destination precision 121 122// End of specialization parameters. 123 124// TODO: These helper routines should be placed into fp_lib.h 125// Currently they depend on macros/constants defined above. 126 127static inline src_rep_t extract_sign_from_src(src_rep_t x) { 128 const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); 129 return (x & srcSignMask) >> (srcBits - 1); 130} 131 132static inline src_rep_t extract_exp_from_src(src_rep_t x) { 133 const int srcSigBits = srcBits - 1 - srcExpBits; 134 const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; 135 return (x & srcExpMask) >> srcSigBits; 136} 137 138static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) { 139 const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; 140 return x & srcSigFracMask; 141} 142 143#ifdef src_rep_t_clz 144static inline int clz_in_sig_frac(src_rep_t sigFrac) { 145 const int skip = 1 + srcExpBits; 146 return src_rep_t_clz(sigFrac) - skip; 147} 148#endif 149 150static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { 151 return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; 152} 153 154// Two helper routines for conversion to and from the representation of 155// floating-point data as integer values follow. 156 157static inline src_rep_t srcToRep(src_t x) { 158 const union { 159 src_t f; 160 src_rep_t i; 161 } rep = {.f = x}; 162 return rep.i; 163} 164 165static inline dst_t dstFromRep(dst_rep_t x) { 166 const union { 167 dst_t f; 168 dst_rep_t i; 169 } rep = {.i = x}; 170 return rep.f; 171} 172// End helper routines. Conversion implementation follows. 173 174#endif // FP_EXTEND_HEADER 175