libgcc _BitInt helper documentation [PR102989]

On Mon, Aug 21, 2023 at 05:32:04PM +0000, Joseph Myers wrote:
> I think the libgcc functions (i.e. those exported by libgcc, to which
> references are generated by the compiler) need documenting in libgcc.texi.
> Internal functions or macros in the libgcc patch need appropriate comments
> specifying their semantics; especially FP_TO_BITINT and FP_FROM_BITINT
> which have a lot of arguments and no comments saying what the semantics of
> the macros and their arguments are supposed to me.

Here is an incremental patch which does that.

2023-09-06  Jakub Jelinek  <jakub@redhat.com>

	PR c/102989
gcc/
	* doc/libgcc.texi (Bit-precise integer arithmetic functions):
	Document general rules for _BitInt support library functions
	and document __mulbitint3 and __divmodbitint4.
	(Conversion functions): Document __fix{s,d,x,t}fbitint,
	__floatbitint{s,d,x,t,h,b}f, __bid_fix{s,d,t}dbitint and
	__bid_floatbitint{s,d,t}d.
libgcc/
	* libgcc2.c (bitint_negate): Add function comment.
	* soft-fp/bitint.h (bitint_negate): Add function comment.
	(FP_TO_BITINT, FP_FROM_BITINT): Add comment explaining the macros.
This commit is contained in:
Jakub Jelinek 2023-09-06 17:42:37 +02:00
parent f76ae4369c
commit f6e0ec5696
3 changed files with 111 additions and 0 deletions

View File

@ -218,6 +218,51 @@ These functions return the number of bits set in @var{a}.
These functions return the @var{a} byteswapped.
@end deftypefn
@subsection Bit-precise integer arithmetic functions
@code{_BitInt(@var{n})} library functions operate on arrays of limbs, where
each limb has @code{__LIBGCC_BITINT_LIMB_WIDTH__} bits and the limbs are
ordered according to @code{__LIBGCC_BITINT_ORDER__} ordering. The most
significant limb if @var{n} is not divisible by
@code{__LIBGCC_BITINT_LIMB_WIDTH__} contains padding bits which should be
ignored on read (sign or zero extended), but extended on write. For the
library functions, all bit-precise integers regardless of @var{n} are
represented like that, even when the target ABI says that for some small
@var{n} they should be represented differently in memory. A pointer
to the array of limbs argument is always accompanied with a bit size
argument. If that argument is positive, it is number of bits and the
number is assumed to be zero-extended to infinite precision, if that
argument is negative, it is negated number of bits above which all bits
are assumed to be sign-extended to infinite precision. These number of bits
arguments don't need to match actual @var{n} for the operation used in the
source, they could be lowered because of sign or zero extensions on the
input or because value-range optimization figures value will need certain
lower number of bits. For big-endian ordering of limbs, when lowering
the bit size argument the pointer argument needs to be adjusted as well.
Negative bit size argument should be always smaller or equal to @code{-2},
because @code{signed _BitInt(1)} is not valid.
For output arguments, either the corresponding bit size argument should
be always positive (for multiplication and division), or is negative when
the output of conversion from floating-point value is signed and positive
when unsigned. The arrays of limbs output arguments point to should not
overlap any inputs, while input arrays of limbs can overlap.
@code{UBILtype} below stands for unsigned integer type with
@code{__LIBGCC_BITINT_LIMB_WIDTH__} bit precision.
@deftypefn {Runtime Function} void __mulbitint3 (@code{UBILtype} *@var{ret}, int32_t @var{retprec}, const @code{UBILtype} *u, int32_t @var{uprec}, const @code{UBILtype} *v, int32_t @var{vprec})
This function multiplies bit-precise integer operands @var{u} and @var{v} and stores
result into @var{retprec} precision bit-precise integer result @var{ret}.
@end deftypefn
@deftypefn {Runtime Function} void __divmodbitint4 (@code{UBILtype} *@var{q}, int32_t @var{qprec}, @code{UBILtype} *@var{r}, int32_t @var{rprec}, const @code{UBILtype} *u, int32_t @var{uprec}, const @code{UBILtype} *v, int32_t @var{vprec})
This function divides bit-precise integer operands @var{u} and @var{v} and stores
quotient into @var{qprec} precision bit-precise integer result @var{q}
(unless @var{q} is @code{NULL} and @var{qprec} is 0, in that case quotient
is not stored anywhere) and remainder into @var{rprec} precision bit-precise
integer result @var{r} (similarly, unless @var{r} is @code{NULL} and @var{rprec}
is 0).
@end deftypefn
@node Soft float library routines
@section Routines for floating point emulation
@cindex soft float library
@ -384,6 +429,27 @@ These functions convert @var{i}, an unsigned long, to floating point.
These functions convert @var{i}, an unsigned long long, to floating point.
@end deftypefn
@deftypefn {Runtime Function} void __fixsfbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, float @var{a})
@deftypefnx {Runtime Function} void __fixdfbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, double @var{a})
@deftypefnx {Runtime Function} void __fixxfbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, __float80 @var{a})
@deftypefnx {Runtime Function} void __fixtfbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, _Float128 @var{a})
These functions convert @var{a} to bit-precise integer @var{r}, rounding toward zero.
If @var{rprec} is positive, it converts to unsigned bit-precise integer and
negative values all become zero, if @var{rprec} is negative, it converts
to signed bit-precise integer.
@end deftypefn
@deftypefn {Runtime Function} float __floatbitintsf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} double __floatbitintdf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} __float80 __floatbitintxf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} _Float128 __floatbitinttf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} _Float16 __floatbitinthf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} __bf16 __floatbitintbf (@code{UBILtype} *@var{i}, int32_t @var{iprec})
These functions convert bit-precise integer @var{i} to floating point. If
@var{iprec} is positive, it is conversion from unsigned bit-precise integer,
otherwise from signed bit-precise integer.
@end deftypefn
@subsection Comparison functions
There are two sets of basic comparison functions.
@ -707,6 +773,23 @@ These functions convert @var{i}, an unsigned integer, to decimal floating point.
These functions convert @var{i}, an unsigned long, to decimal floating point.
@end deftypefn
@deftypefn {Runtime Function} void __bid_fixsdbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, _Decimal32 @var{a})
@deftypefnx {Runtime Function} void __bid_fixddbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, _Decimal64 @var{a})
@deftypefnx {Runtime Function} void __bid_fixtdbitint (@code{UBILtype} *@var{r}, int32_t @var{rprec}, _Decimal128 @var{a})
These functions convert @var{a} to bit-precise integer @var{r}, rounding toward zero.
If @var{rprec} is positive, it converts to unsigned bit-precise integer and
negative values all become zero, if @var{rprec} is negative, it converts
to signed bit-precise integer. So far implemented for BID format only.
@end deftypefn
@deftypefn {Runtime Function} _Decimal32 __bid_floatbitintsd (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} _Decimal64 __bid_floatbitintdd (@code{UBILtype} *@var{i}, int32_t @var{iprec})
@deftypefnx {Runtime Function} _Decimal128 __bid_floatbitinttd (@code{UBILtype} *@var{i}, int32_t @var{iprec})
These functions convert bit-precise integer @var{i} to decimal floating point. If
@var{iprec} is positive, it is conversion from unsigned bit-precise integer,
otherwise from signed bit-precise integer. So far implemented for BID format only.
@end deftypefn
@subsection Comparison functions
@deftypefn {Runtime Function} int __dpd_unordsd2 (_Decimal32 @var{a}, _Decimal32 @var{b})

View File

@ -1640,6 +1640,8 @@ __mulbitint3 (UWtype *ret, SItype retprec,
#endif
#ifdef L_divmodbitint4
/* D = -S. */
static void
bitint_negate (UWtype *d, const UWtype *s, SItype n)
{

View File

@ -160,6 +160,9 @@ bitint_reduce_prec (const UBILtype **p, SItype prec)
# define BITINT_END(be, le) (le)
#endif
/* Negate N limbs from S into D. D and S should point to
the least significant limb. */
static inline __attribute__((__always_inline__)) void
bitint_negate (UBILtype *d, const UBILtype *s, SItype n)
{
@ -175,6 +178,19 @@ bitint_negate (UBILtype *d, const UBILtype *s, SItype n)
while (--n);
}
/* Common final part of __fix?fbitint conversion functions.
The A floating point value should have been converted using
soft-fp macros into RV, U##DI##type DI##_BITS precise normal
integral type and SHIFT, how many bits should that value be
shifted to the left. R is pointer to limbs array passed to the
function, RN number of limbs in it, ARPREC absolute value of
RPREC argument passed to it, RSIZE number of significant bits in RV.
RSIGNED is non-zero if the result is signed bit-precise integer,
otherwise zero. If OVF is true, instead of storing RV shifted left
by SHIFT bits and zero or sign extended store minimum or maximum
of the signed or unsigned bit-precise integer type or zero depending on if
RV contains the minimum or maximum signed or unsigned value or zero. */
#define FP_TO_BITINT(r, rn, arprec, shift, rv, rsize, rsigned, ovf, DI) \
if (ovf) \
{ \
@ -232,6 +248,16 @@ bitint_negate (UBILtype *d, const UBILtype *s, SItype n)
* sizeof (UBILtype)); \
}
/* Common initial part of __floatbitint?f conversion functions.
I and IPREC are arguments passed to those functions, convert that
into a pair of DI##type IV integer and SHIFT, such that converting
IV to floating point and multiplicating that by pow (2, SHIFT)
gives the expected result. IV size needs to be chosen such that
it is larger than number of bits in floating-point mantissa and
contains there even at least a two bits below the mantissa for
rounding purposes. If any of the SHIFT bits shifted out is non-zero,
the least significant bit should be non-zero. */
#define FP_FROM_BITINT(i, iprec, iv, shift, DI) \
do \
{ \