Skip to content

Commit ea1f8fb

Browse files
committed
Add instrastructure for IEEE quad precision.
Based on patch from GuanHong Liu. Differential Revision: http://llvm-reviews.chandlerc.com/D2796 llvm-svn: 204999
1 parent 103dc2e commit ea1f8fb

File tree

1 file changed

+114
-6
lines changed

1 file changed

+114
-6
lines changed

compiler-rt/lib/builtins/fp_lib.h

Lines changed: 114 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
// many useful constants and utility routines that are used in the
1313
// implementation of the soft-float routines in compiler-rt.
1414
//
15-
// Assumes that float and double correspond to the IEEE-754 binary32 and
16-
// binary64 types, respectively, and that integer endianness matches floating
17-
// point endianness on the target platform.
15+
// Assumes that float, double and long double correspond to the IEEE-754
16+
// binary32, binary64 and binary 128 types, respectively, and that integer
17+
// endianness matches floating point endianness on the target platform.
1818
//
1919
//===----------------------------------------------------------------------===//
2020

@@ -59,7 +59,7 @@ static inline int rep_clz(rep_t a) {
5959
#else
6060
if (a & REP_C(0xffffffff00000000))
6161
return __builtin_clz(a >> 32);
62-
else
62+
else
6363
return 32 + __builtin_clz(a & REP_C(0xffffffff));
6464
#endif
6565
}
@@ -86,10 +86,118 @@ static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
8686
#undef loWord
8787
#undef hiWord
8888

89+
#elif defined QUAD_PRECISION
90+
#if __LDBL_MANT_DIG__ == 113
91+
#define CRT_LDBL_128BIT
92+
typedef __uint128_t rep_t;
93+
typedef __int128_t srep_t;
94+
typedef long double fp_t;
95+
#define REP_C (__uint128_t)
96+
// Note: Since there is no explicit way to tell compiler the constant is a
97+
// 128-bit integer, we let the constant be casted to 128-bit integer
98+
#define significandBits 112
99+
100+
static inline int rep_clz(rep_t a) {
101+
const union
102+
{
103+
__uint128_t ll;
104+
#if _YUGA_BIG_ENDIAN
105+
struct { uint64_t high, low; } s;
89106
#else
90-
#error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
107+
struct { uint64_t low, high; } s;
91108
#endif
109+
} uu = { .ll = a };
110+
111+
uint64_t word;
112+
uint64_t add;
92113

114+
if (uu.s.high){
115+
word = uu.s.high;
116+
add = 0;
117+
}
118+
else{
119+
word = uu.s.low;
120+
add = 64;
121+
}
122+
return __builtin_clzll(word) + add;
123+
}
124+
125+
#define Word_LoMask UINT64_C(0x00000000ffffffff)
126+
#define Word_HiMask UINT64_C(0xffffffff00000000)
127+
#define Word_FullMask UINT64_C(0xffffffffffffffff)
128+
#define Word_1(a) (uint64_t)((a >> 96) & Word_LoMask)
129+
#define Word_2(a) (uint64_t)((a >> 64) & Word_LoMask)
130+
#define Word_3(a) (uint64_t)((a >> 32) & Word_LoMask)
131+
#define Word_4(a) (uint64_t)(a & Word_LoMask)
132+
133+
// 128x128 -> 256 wide multiply for platforms that don't have such an operation;
134+
// many 64-bit platforms have this operation, but they tend to have hardware
135+
// floating-point, so we don't bother with a special case for them here.
136+
static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
137+
138+
const uint64_t product11 = Word_1(a) * Word_1(b);
139+
const uint64_t product12 = Word_1(a) * Word_2(b);
140+
const uint64_t product13 = Word_1(a) * Word_3(b);
141+
const uint64_t product14 = Word_1(a) * Word_4(b);
142+
const uint64_t product21 = Word_2(a) * Word_1(b);
143+
const uint64_t product22 = Word_2(a) * Word_2(b);
144+
const uint64_t product23 = Word_2(a) * Word_3(b);
145+
const uint64_t product24 = Word_2(a) * Word_4(b);
146+
const uint64_t product31 = Word_3(a) * Word_1(b);
147+
const uint64_t product32 = Word_3(a) * Word_2(b);
148+
const uint64_t product33 = Word_3(a) * Word_3(b);
149+
const uint64_t product34 = Word_3(a) * Word_4(b);
150+
const uint64_t product41 = Word_4(a) * Word_1(b);
151+
const uint64_t product42 = Word_4(a) * Word_2(b);
152+
const uint64_t product43 = Word_4(a) * Word_3(b);
153+
const uint64_t product44 = Word_4(a) * Word_4(b);
154+
155+
const __uint128_t sum0 = (__uint128_t)product44;
156+
const __uint128_t sum1 = (__uint128_t)product34 +
157+
(__uint128_t)product43;
158+
const __uint128_t sum2 = (__uint128_t)product24 +
159+
(__uint128_t)product33 +
160+
(__uint128_t)product42;
161+
const __uint128_t sum3 = (__uint128_t)product14 +
162+
(__uint128_t)product23 +
163+
(__uint128_t)product32 +
164+
(__uint128_t)product41;
165+
const __uint128_t sum4 = (__uint128_t)product13 +
166+
(__uint128_t)product22 +
167+
(__uint128_t)product31;
168+
const __uint128_t sum5 = (__uint128_t)product12 +
169+
(__uint128_t)product21;
170+
const __uint128_t sum6 = (__uint128_t)product11;
171+
172+
const __uint128_t r0 = (sum0 & Word_FullMask) +
173+
((sum1 & Word_LoMask) << 32);
174+
const __uint128_t r1 = (sum0 >> 64) +
175+
((sum1 >> 32) & Word_FullMask) +
176+
(sum2 & Word_FullMask) +
177+
((sum3 << 32) & Word_HiMask);
178+
179+
*lo = r0 + (r1 << 64);
180+
*hi = (r1 >> 64) +
181+
(sum1 >> 96) +
182+
(sum2 >> 64) +
183+
(sum3 >> 32) +
184+
sum4 +
185+
(sum5 << 32) +
186+
(sum6 << 64);
187+
}
188+
#undef Word_1
189+
#undef Word_2
190+
#undef Word_3
191+
#undef Word_4
192+
#undef Word_HiMask
193+
#undef Word_LoMask
194+
#undef Word_FullMask
195+
#endif // __LDBL_MANT_DIG__ == 113
196+
#else
197+
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
198+
#endif
199+
200+
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || defined(CRT_LDBL_128BIT)
93201
#define typeWidth (sizeof(rep_t)*CHAR_BIT)
94202
#define exponentBits (typeWidth - significandBits - 1)
95203
#define maxExponent ((1 << exponentBits) - 1)
@@ -142,7 +250,7 @@ static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int c
142250
*hi = 0;
143251
}
144252
}
145-
253+
#endif
146254
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
147255
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
148256

0 commit comments

Comments
 (0)