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
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
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 #define UBILtype UDItype
37 #elif BIL_UNITS_PER_WORD == 4
38 #define BIL_TYPE_SIZE (4 * __CHAR_BIT__)
39 #define BILtype SItype
40 #define UBILtype USItype
41 #elif BIL_UNITS_PER_WORD == 2
42 #define BIL_TYPE_SIZE (2 * __CHAR_BIT__)
43 #define BILtype HItype
44 #define UBILtype UHItype
46 #define BIL_TYPE_SIZE __CHAR_BIT__
47 #define BILtype QItype
48 #define UBILtype UQItype
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
)
61 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
64 i
= ((USItype
) -1 - prec
) / BIL_TYPE_SIZE
;
67 if (mslimb
& ((UBILtype
) 1 << (((USItype
) -1 - prec
) % BIL_TYPE_SIZE
)))
69 SItype n
= ((USItype
) -prec
) % BIL_TYPE_SIZE
;
72 mslimb
|= ((UBILtype
) -1 << (((USItype
) -1 - prec
) % BIL_TYPE_SIZE
));
73 if (mslimb
== (UBILtype
) -1)
78 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
87 while (mslimb
== (UBILtype
) -1)
89 prec
+= BIL_TYPE_SIZE
;
92 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
101 if ((BILtype
) mslimb
>= 0)
103 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
116 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
119 i
= ((USItype
) prec
- 1) / BIL_TYPE_SIZE
;
123 SItype n
= ((USItype
) prec
) % BIL_TYPE_SIZE
;
126 mslimb
&= ((UBILtype
) 1 << (((USItype
) prec
) % BIL_TYPE_SIZE
)) - 1;
132 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
142 prec
-= BIL_TYPE_SIZE
;
145 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
155 #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__
156 # define BITINT_INC -1
157 # define BITINT_END(be, le) (be)
159 # define BITINT_INC 1
160 # define BITINT_END(be, le) (le)
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
)
172 UBILtype sv
= *s
, lo
;
174 c
= __builtin_add_overflow (~sv
, c
, &lo
);
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) \
198 __builtin_memset (r, -1, rn * sizeof (UBILtype)); \
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); \
205 r[BITINT_END (0, rn - 1)] \
206 &= ~((UBILtype) -1 << ((arprec - 1) % BIL_TYPE_SIZE)); \
210 USItype shiftl = shift / BIL_TYPE_SIZE; \
212 if (rsigned && (DI##type) rv >= 0) \
214 if (shift + DI##_BITS > arprec) \
215 rsize = arprec - shift; \
216 USItype shiftr = shift % BIL_TYPE_SIZE; \
218 __builtin_memset (r + BITINT_END (rn - shiftl, 0), 0, \
219 shiftl * sizeof (UBILtype)); \
220 USItype idx = BITINT_END (rn - shiftl - 1, shiftl); \
224 r[idx] = (rsigned ? (UBILtype) rvs : (UBILtype) rv) << shiftr;\
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; \
237 r[idx] = rsigned ? (UBILtype) rvs : (UBILtype) rv; \
239 if (rsize <= BIL_TYPE_SIZE) \
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; \
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) \
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]; \
270 if (aiprec % BIL_TYPE_SIZE) \
273 msb &= ((UBILtype) 1 << (aiprec % BIL_TYPE_SIZE)) - 1; \
275 msb |= (UBILtype) -1 << (aiprec % BIL_TYPE_SIZE); \
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; \
288 iv = (BILtype) msb; \
292 /* bitint_reduce_prec guarantees that if msb is 0, then whole \
293 i must be zero, otherwise it would have reduced the \
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; \
309 n = DI##_BITS - 1 - n; \
312 while (n && BITINT_END (idx < in - 1, 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); \
321 n -= BIL_TYPE_SIZE; \
325 iv = (U##DI##type) iv << n; \
326 iv |= msb >> (BIL_TYPE_SIZE - n); \
327 shift = BIL_TYPE_SIZE - n; \
332 UBILtype low_bits = 0; \
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)) \
339 low_bits |= i[idx]; \
341 iv |= (low_bits != 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 */