Index: lib/builtins/fp_lib.h =================================================================== --- lib/builtins/fp_lib.h +++ lib/builtins/fp_lib.h @@ -12,9 +12,9 @@ // many useful constants and utility routines that are used in the // implementation of the soft-float routines in compiler-rt. // -// Assumes that float and double correspond to the IEEE-754 binary32 and -// binary64 types, respectively, and that integer endianness matches floating -// point endianness on the target platform. +// Assumes that float, double and long double correspond to the IEEE-754 +// binary32, binary64 and binary 128 types, respectively, and that integer +// endianness matches floating point endianness on the target platform. // //===----------------------------------------------------------------------===// @@ -59,7 +59,7 @@ #else if (a & REP_C(0xffffffff00000000)) return __builtin_clz(a >> 32); - else + else return 32 + __builtin_clz(a & REP_C(0xffffffff)); #endif } @@ -84,10 +84,108 @@ *hi = hiWord(plohi) + hiWord(philo) + hiWord(r1) + phihi; } +#elif defined QUAD_PRECISION +#if __LDBL_MANT_DIG__ == 113 +#define CRT_LDBL_128BIT +typedef __uint128_t rep_t; +typedef __int128_t srep_t; +typedef long double fp_t; +#define REP_C (__uint128_t) +// Note: Since there is no explicit way to tell compiler the constant is a +// 128-bit integer, we let the constant be casted to 128-bit integer +#define significandBits 112 + +static inline int rep_clz(rep_t a) { + const union + { + __uint128_t ll; +#if _YUGA_BIG_ENDIAN + struct { uint64_t high, low; } s; +#else + struct { uint64_t low, high; } s; +#endif + } uu = { .ll = a }; + + uint64_t word; + uint64_t add; + + if (uu.s.high){ + word = uu.s.high; + add = 0; + } + else{ + word = uu.s.low; + add = 64; + } + return __builtin_clzll(word) + add; +} + +#define Word_1(a) (uint64_t)((a >> 96) & 0xffffffffU) +#define Word_2(a) (uint64_t)((a >> 64) & 0xffffffffU) +#define Word_3(a) (uint64_t)((a >> 32) & 0xffffffffU) +#define Word_4(a) (uint64_t)(a & 0xffffffffU) + +// 128x128 -> 256 wide multiply for platforms that don't have such an operation; +// many 64-bit platforms have this operation, but they tend to have hardware +// floating-point, so we don't bother with a special case for them here. +static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) { + + const uint64_t product11 = Word_1(a) * Word_1(b); + const uint64_t product12 = Word_1(a) * Word_2(b); + const uint64_t product13 = Word_1(a) * Word_3(b); + const uint64_t product14 = Word_1(a) * Word_4(b); + const uint64_t product21 = Word_2(a) * Word_1(b); + const uint64_t product22 = Word_2(a) * Word_2(b); + const uint64_t product23 = Word_2(a) * Word_3(b); + const uint64_t product24 = Word_2(a) * Word_4(b); + const uint64_t product31 = Word_3(a) * Word_1(b); + const uint64_t product32 = Word_3(a) * Word_2(b); + const uint64_t product33 = Word_3(a) * Word_3(b); + const uint64_t product34 = Word_3(a) * Word_4(b); + const uint64_t product41 = Word_4(a) * Word_1(b); + const uint64_t product42 = Word_4(a) * Word_2(b); + const uint64_t product43 = Word_4(a) * Word_3(b); + const uint64_t product44 = Word_4(a) * Word_4(b); + + const __uint128_t sum0 = (__uint128_t)product44; + const __uint128_t sum1 = (__uint128_t)product34 + + (__uint128_t)product43; + const __uint128_t sum2 = (__uint128_t)product24 + + (__uint128_t)product33 + + (__uint128_t)product42; + const __uint128_t sum3 = (__uint128_t)product14 + + (__uint128_t)product23 + + (__uint128_t)product32 + + (__uint128_t)product41; + const __uint128_t sum4 = (__uint128_t)product13 + + (__uint128_t)product22 + + (__uint128_t)product31; + const __uint128_t sum5 = (__uint128_t)product12 + + (__uint128_t)product21; + const __uint128_t sum6 = (__uint128_t)product11; + + const __uint128_t r0 = (sum0 & 0xffffffffffffffff) + + ((sum1 & 0xffffffff) << 32); + const __uint128_t r1 = (sum0 >> 64) + + ((sum1 << 32) >> 64) + + (sum2 & 0xffffffffffffffff) + + ((sum3 & 0xffffffff) << 32); + + *lo = r0 + (r1 << 64); + *hi = (r1 >> 64) + + (sum1 >> 96) + + (sum2 >> 64) + + (sum3 >> 32) + + sum4 + + (sum5 << 32) + + (sum6 << 64); +} +#endif // __LDBL_MANT_DIG__ == 113 #else -#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined. +#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined. #endif +#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || defined(CRT_LDBL_128BIT) #define typeWidth (sizeof(rep_t)*CHAR_BIT) #define exponentBits (typeWidth - significandBits - 1) #define maxExponent ((1 << exponentBits) - 1) @@ -140,5 +238,5 @@ *hi = 0; } } - +#endif #endif // FP_LIB_HEADER