Daily bump.
[official-gcc.git] / libgcc / soft-fp / bitint.h
blobcb4d822cb49bdeb254faf29ffbc545e559288246
1 /* Software floating-point emulation.
2 Definitions for _BitInt implementation details.
4 Copyright (C) 2023 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #ifndef GCC_SOFT_FP_BITINT_H
28 #define GCC_SOFT_FP_BITINT_H
30 #ifdef __BITINT_MAXWIDTH__
31 #define BIL_UNITS_PER_WORD (__LIBGCC_BITINT_LIMB_WIDTH__ / __CHAR_BIT__)
33 #if BIL_UNITS_PER_WORD == 8
34 #define BIL_TYPE_SIZE (8 * __CHAR_BIT__)
35 #define BILtype DItype
36 typedef UDItype __attribute__ ((__may_alias__)) UBILtype;
37 #elif BIL_UNITS_PER_WORD == 4
38 #define BIL_TYPE_SIZE (4 * __CHAR_BIT__)
39 #define BILtype SItype
40 typedef USItype __attribute__ ((__may_alias__)) UBILtype;
41 #elif BIL_UNITS_PER_WORD == 2
42 #define BIL_TYPE_SIZE (2 * __CHAR_BIT__)
43 #define BILtype HItype
44 typedef UHItype __attribute__ ((__may_alias__)) UBILtype;
45 #else
46 #define BIL_TYPE_SIZE __CHAR_BIT__
47 #define BILtype QItype
48 typedef UQItype __attribute__ ((__may_alias__)) UBILtype;
49 #endif
51 /* If *P is zero or sign extended (the latter only for PREC < 0) from
52 some narrower _BitInt value, reduce precision. */
54 static inline __attribute__((__always_inline__)) SItype
55 bitint_reduce_prec (const UBILtype **p, SItype prec)
57 UBILtype mslimb;
58 SItype i;
59 if (prec < 0)
61 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
62 i = 0;
63 #else
64 i = ((USItype) -1 - prec) / BIL_TYPE_SIZE;
65 #endif
66 mslimb = (*p)[i];
67 if (mslimb & ((UBILtype) 1 << (((USItype) -1 - prec) % BIL_TYPE_SIZE)))
69 SItype n = ((USItype) -prec) % BIL_TYPE_SIZE;
70 if (n)
72 mslimb |= ((UBILtype) -1 << (((USItype) -1 - prec) % BIL_TYPE_SIZE));
73 if (mslimb == (UBILtype) -1)
75 prec += n;
76 if (prec >= -1)
77 return -2;
78 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
79 ++p;
80 #else
81 --i;
82 #endif
83 mslimb = (*p)[i];
84 n = 0;
87 while (mslimb == (UBILtype) -1)
89 prec += BIL_TYPE_SIZE;
90 if (prec >= -1)
91 return -2;
92 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
93 ++p;
94 #else
95 --i;
96 #endif
97 mslimb = (*p)[i];
99 if (n == 0)
101 if ((BILtype) mslimb >= 0)
103 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
104 --p;
105 #endif
106 return prec - 1;
109 return prec;
111 else
112 prec = -prec;
114 else
116 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
117 i = 0;
118 #else
119 i = ((USItype) prec - 1) / BIL_TYPE_SIZE;
120 #endif
121 mslimb = (*p)[i];
123 SItype n = ((USItype) prec) % BIL_TYPE_SIZE;
124 if (n)
126 mslimb &= ((UBILtype) 1 << (((USItype) prec) % BIL_TYPE_SIZE)) - 1;
127 if (mslimb == 0)
129 prec -= n;
130 if (prec == 0)
131 return 1;
132 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
133 ++p;
134 #else
135 --i;
136 #endif
137 mslimb = (*p)[i];
140 while (mslimb == 0)
142 prec -= BIL_TYPE_SIZE;
143 if (prec == 0)
144 return 1;
145 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
146 ++p;
147 #else
148 --i;
149 #endif
150 mslimb = (*p)[i];
152 return prec;
155 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
156 # define BITINT_INC -1
157 # define BITINT_END(be, le) (be)
158 #else
159 # define BITINT_INC 1
160 # define BITINT_END(be, le) (le)
161 #endif
163 /* Negate N limbs from S into D. D and S should point to
164 the least significant limb. */
166 static inline __attribute__((__always_inline__)) void
167 bitint_negate (UBILtype *d, const UBILtype *s, SItype n)
169 UBILtype c = 1;
172 UBILtype sv = *s, lo;
173 s += BITINT_INC;
174 c = __builtin_add_overflow (~sv, c, &lo);
175 *d = lo;
176 d += BITINT_INC;
178 while (--n);
181 /* Common final part of __fix?fbitint conversion functions.
182 The A floating point value should have been converted using
183 soft-fp macros into RV, U##DI##type DI##_BITS precise normal
184 integral type and SHIFT, how many bits should that value be
185 shifted to the left. R is pointer to limbs array passed to the
186 function, RN number of limbs in it, ARPREC absolute value of
187 RPREC argument passed to it, RSIZE number of significant bits in RV.
188 RSIGNED is non-zero if the result is signed bit-precise integer,
189 otherwise zero. If OVF is true, instead of storing RV shifted left
190 by SHIFT bits and zero or sign extended store minimum or maximum
191 of the signed or unsigned bit-precise integer type or zero depending on if
192 RV contains the minimum or maximum signed or unsigned value or zero. */
194 #define FP_TO_BITINT(r, rn, arprec, shift, rv, rsize, rsigned, ovf, DI) \
195 if (ovf) \
197 if ((rv & 1) != 0) \
198 __builtin_memset (r, -1, rn * sizeof (UBILtype)); \
199 else \
200 __builtin_memset (r, 0, rn * sizeof (UBILtype)); \
201 if (rv & (((U##DI##type) 1) << (rsize - 1))) \
202 r[BITINT_END (0, rn - 1)] \
203 |= (UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE); \
204 else \
205 r[BITINT_END (0, rn - 1)] \
206 &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); \
208 else \
210 USItype shiftl = shift / BIL_TYPE_SIZE; \
211 rsize = DI##_BITS; \
212 if (rsigned && (DI##type) rv >= 0) \
213 rsigned = 0; \
214 if (shift + DI##_BITS > arprec) \
215 rsize = arprec - shift; \
216 USItype shiftr = shift % BIL_TYPE_SIZE; \
217 if (shiftl) \
218 __builtin_memset (r + BITINT_END (rn - shiftl, 0), 0, \
219 shiftl * sizeof (UBILtype)); \
220 USItype idx = BITINT_END (rn - shiftl - 1, shiftl); \
221 DI##type rvs = rv; \
222 if (shiftr) \
224 r[idx] = (rsigned ? (UBILtype) rvs : (UBILtype) rv) << shiftr;\
225 idx += BITINT_INC; \
226 if (rsize > BIL_TYPE_SIZE - shiftr) \
228 rv >>= BIL_TYPE_SIZE - shiftr; \
229 rvs >>= BIL_TYPE_SIZE - shiftr; \
230 rsize -= BIL_TYPE_SIZE - shiftr; \
232 else \
233 rsize = 0; \
235 while (rsize) \
237 r[idx] = rsigned ? (UBILtype) rvs : (UBILtype) rv; \
238 idx += BITINT_INC; \
239 if (rsize <= BIL_TYPE_SIZE) \
240 break; \
241 rv >>= (DI##_BITS > BIL_TYPE_SIZE ? BIL_TYPE_SIZE : 0); \
242 rvs >>= (DI##_BITS > BIL_TYPE_SIZE ? BIL_TYPE_SIZE : 0); \
243 rsize -= BIL_TYPE_SIZE; \
245 if (idx < rn) \
246 __builtin_memset (r + BITINT_END (0, idx), rsigned ? -1 : 0, \
247 BITINT_END (idx + 1, rn - idx) \
248 * sizeof (UBILtype)); \
251 /* Common initial part of __floatbitint?f conversion functions.
252 I and IPREC are arguments passed to those functions, convert that
253 into a pair of DI##type IV integer and SHIFT, such that converting
254 IV to floating point and multiplicating that by pow (2, SHIFT)
255 gives the expected result. IV size needs to be chosen such that
256 it is larger than number of bits in floating-point mantissa and
257 contains there even at least a two bits below the mantissa for
258 rounding purposes. If any of the SHIFT bits shifted out is non-zero,
259 the least significant bit should be non-zero. */
261 #define FP_FROM_BITINT(i, iprec, iv, shift, DI) \
262 do \
264 iprec = bitint_reduce_prec (&i, iprec); \
265 USItype aiprec = iprec < 0 ? -iprec : iprec; \
266 USItype in = (aiprec + BIL_TYPE_SIZE - 1) / BIL_TYPE_SIZE; \
267 USItype idx = BITINT_END (0, in - 1); \
268 UBILtype msb = i[idx]; \
269 SItype n = 0; \
270 if (aiprec % BIL_TYPE_SIZE) \
272 if (iprec > 0) \
273 msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; \
274 else \
275 msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); \
277 if (iprec < 0) \
279 n = sizeof (0ULL) * __CHAR_BIT__ + 1 - __builtin_clzll (~msb);\
280 if (BIL_TYPE_SIZE > DI##_BITS && n > DI##_BITS) \
282 iv = msb >> (n - DI##_BITS); \
283 shift = n - DI##_BITS; \
284 n = 0; \
286 else \
288 iv = (BILtype) msb; \
289 n = DI##_BITS - n; \
292 /* bitint_reduce_prec guarantees that if msb is 0, then whole \
293 i must be zero, otherwise it would have reduced the \
294 precision. */ \
295 else if (msb == 0) \
296 iv = 0; \
297 else \
299 n = sizeof (0ULL) * __CHAR_BIT__ - __builtin_clzll (msb); \
300 if (BIL_TYPE_SIZE >= DI##_BITS && n >= DI##_BITS) \
302 iv = msb >> (n - DI##_BITS + 1); \
303 shift = n - DI##_BITS + 1; \
304 n = 0; \
306 else \
308 iv = msb; \
309 n = DI##_BITS - 1 - n; \
312 while (n && BITINT_END (idx < in - 1, idx)) \
314 idx -= BITINT_INC; \
315 msb = i[idx]; \
316 if (BIL_TYPE_SIZE < DI##_BITS && n >= BIL_TYPE_SIZE) \
318 iv = (U##DI##type) iv << (BIL_TYPE_SIZE < DI##_BITS \
319 ? BIL_TYPE_SIZE : 0); \
320 iv |= msb; \
321 n -= BIL_TYPE_SIZE; \
323 else \
325 iv = (U##DI##type) iv << n; \
326 iv |= msb >> (BIL_TYPE_SIZE - n); \
327 shift = BIL_TYPE_SIZE - n; \
328 break; \
332 UBILtype low_bits = 0; \
333 if (shift) \
334 low_bits = msb & (((UBILtype) 1 << shift) - 1); \
335 shift += BITINT_END (in - 1 - idx, idx) * BIL_TYPE_SIZE; \
336 while (!low_bits && BITINT_END (idx < in - 1, idx)) \
338 idx -= BITINT_INC; \
339 low_bits |= i[idx]; \
341 iv |= (low_bits != 0); \
343 while (0)
345 extern void __mulbitint3 (UBILtype *, SItype, const UBILtype *, SItype,
346 const UBILtype *, SItype);
347 extern void __divmodbitint4 (UBILtype *, SItype, UBILtype *, SItype,
348 const UBILtype *, SItype,
349 const UBILtype *, SItype);
351 extern USItype __bid_pow10bitint (UBILtype *, SItype, USItype);
353 #endif /* __BITINT_MAXWIDTH__ */
355 #endif /* GCC_SOFT_FP_BITINT_H */