forked from OSchip/llvm-project
Add instrastructure for IEEE quad precision.
Based on patch from GuanHong Liu. Differential Revision: http://llvm-reviews.chandlerc.com/D2796 llvm-svn: 204999
This commit is contained in:
parent
103dc2ef2f
commit
ea1f8fb775
|
@ -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 @@ static inline int rep_clz(rep_t a) {
|
|||
#else
|
||||
if (a & REP_C(0xffffffff00000000))
|
||||
return __builtin_clz(a >> 32);
|
||||
else
|
||||
else
|
||||
return 32 + __builtin_clz(a & REP_C(0xffffffff));
|
||||
#endif
|
||||
}
|
||||
|
@ -86,10 +86,118 @@ static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
|
|||
#undef loWord
|
||||
#undef hiWord
|
||||
|
||||
#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
|
||||
#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
|
||||
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_LoMask UINT64_C(0x00000000ffffffff)
|
||||
#define Word_HiMask UINT64_C(0xffffffff00000000)
|
||||
#define Word_FullMask UINT64_C(0xffffffffffffffff)
|
||||
#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
|
||||
#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
|
||||
#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
|
||||
#define Word_4(a) (uint64_t)(a & Word_LoMask)
|
||||
|
||||
// 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 & Word_FullMask) +
|
||||
((sum1 & Word_LoMask) << 32);
|
||||
const __uint128_t r1 = (sum0 >> 64) +
|
||||
((sum1 >> 32) & Word_FullMask) +
|
||||
(sum2 & Word_FullMask) +
|
||||
((sum3 << 32) & Word_HiMask);
|
||||
|
||||
*lo = r0 + (r1 << 64);
|
||||
*hi = (r1 >> 64) +
|
||||
(sum1 >> 96) +
|
||||
(sum2 >> 64) +
|
||||
(sum3 >> 32) +
|
||||
sum4 +
|
||||
(sum5 << 32) +
|
||||
(sum6 << 64);
|
||||
}
|
||||
#undef Word_1
|
||||
#undef Word_2
|
||||
#undef Word_3
|
||||
#undef Word_4
|
||||
#undef Word_HiMask
|
||||
#undef Word_LoMask
|
||||
#undef Word_FullMask
|
||||
#endif // __LDBL_MANT_DIG__ == 113
|
||||
#else
|
||||
#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)
|
||||
|
@ -142,7 +250,7 @@ static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int c
|
|||
*hi = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
|
||||
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
|
||||
|
||||
|
|
Loading…
Reference in New Issue