12
12
// many useful constants and utility routines that are used in the
13
13
// implementation of the soft-float routines in compiler-rt.
14
14
//
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.
18
18
//
19
19
//===----------------------------------------------------------------------===//
20
20
@@ -59,7 +59,7 @@ static inline int rep_clz(rep_t a) {
59
59
#else
60
60
if (a & REP_C (0xffffffff00000000 ))
61
61
return __builtin_clz (a >> 32 );
62
- else
62
+ else
63
63
return 32 + __builtin_clz (a & REP_C (0xffffffff ));
64
64
#endif
65
65
}
@@ -86,10 +86,118 @@ static inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
86
86
#undef loWord
87
87
#undef hiWord
88
88
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 ;
89
106
#else
90
- #error Either SINGLE_PRECISION or DOUBLE_PRECISION must be defined.
107
+ struct { uint64_t low , high ; } s ;
91
108
#endif
109
+ } uu = { .ll = a };
110
+
111
+ uint64_t word ;
112
+ uint64_t add ;
92
113
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 )
93
201
#define typeWidth (sizeof(rep_t)*CHAR_BIT)
94
202
#define exponentBits (typeWidth - significandBits - 1)
95
203
#define maxExponent ((1 << exponentBits) - 1)
@@ -142,7 +250,7 @@ static inline void wideRightShiftWithSticky(rep_t *hi, rep_t *lo, unsigned int c
142
250
* hi = 0 ;
143
251
}
144
252
}
145
-
253
+ #endif
146
254
COMPILER_RT_ABI fp_t __adddf3 (fp_t a , fp_t b );
147
255
COMPILER_RT_ABI fp_t __addsf3 (fp_t a , fp_t b );
148
256
0 commit comments