Re: [PATCH newlib v1 0/4] Add FreeBSD long double functions

Jeff Johnston <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <CAOox84uKcME+ZfrBkUZT-fJE-nLxw=yOSLC0j4amKrxpJY_Cfw@mail.gmail.com>
On Fri, Aug 26, 2022 at 1:45 PM Corinna Vinschen <[email protected]>
wrote:

> On Aug 26 10:45, Joel Sherrill wrote:
> > On Fri, Aug 26, 2022 at 10:05 AM Corinna Vinschen <[email protected]>
> > wrote:
> > > No, I wrote, create a *single* _fpmath.h file with the massive amount
> > > of definitions (*all* seven) based on LDBL_MANT_DIG.
> > >
> > > There are very few special targets, like x86/x86_64 which need a tweak
> > > in the macros, most of the time the macros should be the same.
> > >
> > > Instead of having 61 files, only have one.  In theory there should be
> > > only two definitions for targets with LDBL_MANT_DIG == DBL_MANT_DIG
> > > to support little and big endian, more shouldn't be required.
> > >
> > > For all others, we already have *ieee*.h files with matching
> definitions
> > > which can be used as role models for the various (but few) definitions
> of
> > > union IEEEl2bits.  See, for instance,
> newlib/libc/include/machine/ieee.h.
> > >
> > > > This approach works and doesn't abandon the targets which the
> > > > ldbl==dbl method works for.
> > >
> > > I never said to abandon these targets, but fwiw, I think you're
> > > overestimating the complexity to generate a single _fpmath.h
> > > file with matching definitions for these targes as well.  The
> > > information is basically already present in newlib.
> > >
> > So don't preserve the FreeBSD files as close to a direct copy
> > as possible?
>
> We're only talking about the _fpmath.h files, not all the other
> files.
>
> If you like, copy over the handful of target-dependent _fpmath.h
> files, but *also* add a generic _fpmath.h file for all other
> targets, IMHO.
>
> > Maybe I am overestimating it. I just don't see the single _fpmath.h
> > to rule them all with confidence like you do. I am not seeing the
> > set of parameters in my head which makes this generic with
> > some macros.
> >
> > I'd appreciate help on this.
>
> newlib/libc/include/machine/ieee.h does not help?
>
> Kind of like this:
>
> #if LDBL_MANT_DIG == 24
>   union IEEEl2bits {
>           long double     e;
> #  ifdef __IEEE_LITTLE_ENDIAN
>           struct {
>                   __uint32_t   manl    :16;
>                   __uint32_t   manh    :7;
>                   __uint32_t   exp     :8;
>                   __uint32_t   sign    :1;
>           } bits;
>           struct {
>                   __uint32_t   manl    :16;
>                   __uint32_t   manh    :7;
>                   __uint32_t   expsign :9;
>           } xbits;
> #  else
>           struct {
>                   __uint32_t   sign    :1;
>                   __uint32_t   exp     :8;
>                   __uint32_t   manh    :7;
>                   __uint32_t   manl    :16;
>           } bits;
>           struct {
>                   __uint32_t   expsign :9;
>                   __uint32_t   manh    :7;
>                   __uint32_t   manl    :16;
>           } xbits;
> #  endif
>   };
> #  define LDBL_NBIT       0
> #  define LDBL_IMPLICIT_NBIT
> #  define mask_nbit_l(u)  ((void)0)
>
> #  define LDBL_MANH_SIZE  7
> #  define LDBL_MANL_SIZE  16
>
> #  define LDBL_TO_ARRAY32(u, a) do {                              \
>           (a)[0] = (uint32_t)(u).bits.manl                        \
>                    | ((uint32_t)(u).bits.manh << LDBL_MANL_SIZE)  \
>           (a)[1] = 0;                                             \
>   } while(0)
> #elif LDBL_MANT_DIG == 53
>   union IEEEl2bits {
>           long double     e;
> #  ifdef __IEEE_LITTLE_ENDIAN
>           struct {
>                   __uint64_t   manl    :32;
>                   __uint64_t   manh    :20;
>                   __uint64_t   exp     :11;
>                   __uint64_t   sign    :1;
>           } bits;
>           struct {
>                   __uint64_t   manl    :32;
>                   __uint64_t   manh    :20;
>                   __uint64_t   expsign :12;
>           } xbits;
> #  else
>           struct {
>                   __uint64_t   sign    :1;
>                   __uint64_t   exp     :11;
>                   __uint64_t   manh    :20;
>                   __uint64_t   manl    :32;
>           } bits;
>           struct {
>                   __uint64_t   expsign :12;
>                   __uint64_t   manh    :20;
>                   __uint64_t   manl    :32;
>           } xbits;
> #  endif
>   };
> #  define LDBL_NBIT       0
> #  define LDBL_IMPLICIT_NBIT
> #  define mask_nbit_l(u)  ((void)0)
>
> #  define LDBL_MANH_SIZE  20
> #  define LDBL_MANL_SIZE  32
>
> #  define LDBL_TO_ARRAY32(u, a) do {                              \
>           (a)[0] = (uint32_t)(u).bits.manl;                       \
>           (a)[1] = (uint32_t)(u).bits.manh;                       \
>   } while(0)
> #elif LDBL_MANT_DIG == 64
>   union IEEEl2bits {
>           long double     e;
> #  ifdef __IEEE_LITTLE_ENDIAN
>           struct {
>                   __uint64_t   manl    :32;
>                   __uint64_t   manh    :32;
>                   __uint64_t   exp     :15;
>                   __uint64_t   sign    :1;
>                   __uint64_t   junk    :16
>           } bits;
>           struct {
>                   __uint64_t   man     :64;
>                   __uint64_t   expsign :16;
>                   __uint64_t   junk    :16
>           } xbits;
> #  else
>           struct {
>                   __uint64_t   junk    :16
>                   __uint64_t   sign    :1;
>                   __uint64_t   exp     :15;
>                   __uint64_t   manh    :32;
>                   __uint64_t   manl    :32;
>           } bits;
>           struct {
>                   __uint64_t   junk    :16
>                   __uint64_t   expsign :16;
>                   __uint64_t   man     :64;
>           } xbits;
> #  endif
>   };
>
> #  define LDBL_NBIT       0x80000000
> #  define mask_nbit_l(u)  ((u).bits.manh &= ~LDBL_NBIT)
>
> #  define LDBL_MANH_SIZE  32
> #  define LDBL_MANL_SIZE  32
>
> #  define LDBL_TO_ARRAY32(u, a) do {                              \
>           (a)[0] = (uint32_t)(u).bits.manl;                       \
>           (a)[1] = (uint32_t)(u).bits.manh;                       \
>   } while(0)
> #elif LDBL_MANT_DIG == 113
>   union IEEEl2bits {
>           long double     e;
> #  ifdef __IEEE_LITTLE_ENDIAN
>           struct {
>                   __uint64_t   manl    :64;
>                   __uint64_t   manh    :48;
>                   __uint64_t   exp     :15;
>                   __uint64_t   sign    :1;
>           } bits;
>           struct {
>                   __uint64_t   manl    :64;
>                   __uint64_t   manh    :48;
>                   __uint64_t   expsign :16;
>           } xbits;
> #  else
>           struct {
>                   __uint64_t   sign    :1;
>                   __uint64_t   exp     :15;
>                   __uint64_t   manh    :48;
>                   __uint64_t   manl    :64;
>           } bits;
>           struct {
>                   __uint64_t   expsign :16;
>                   __uint64_t   manh    :48;
>                   __uint64_t   manl    :64;
>           } xbits;
> #  endif
>   };
>
> #  define LDBL_NBIT       0
> #  define LDBL_IMPLICIT_NBIT
> #  define mask_nbit_l(u)  ((void)0)
>
> #  define LDBL_MANH_SIZE  48
> #  define LDBL_MANL_SIZE  64
>
> #  define LDBL_TO_ARRAY32(u, a) do {                      \
>           (a)[0] = (uint32_t)(u).bits.manl;               \
>           (a)[1] = (uint32_t)((u).bits.manl >> 32);       \
>           (a)[2] = (uint32_t)(u).bits.manh;               \
>           (a)[3] = (uint32_t)((u).bits.manh >> 32);       \
>   } while(0)
> #endif
>
> There's also a ___IEEE_BYTES_LITTLE_ENDIAN definition which I ignored
> for now.  Also, the LDBL_MANT_DIG == 64 is defined for x86-only and the
> manl/manh fields for LDBL_MANT_DIG == 23 are faked on a 16 bit border
> just to have a manl and a manh definition.
>
> I don't claim that it works OOTB with the above, but apart from
> the LDBL_NBIT/mask_nbit_l values which differ for x86/x86_64 CPUs,
> it should be a good start, I think.
>
> > > Jeff, ping?  Your POV would be much appreciated here.
> > >
>

Sorry for the late reply.  I agree with your proposal Corinna.

>
> > +1
> >
> > I also have come across there needs to be a way to pick between ld80
> > and ld128 headers and implementation files. FreeBSD has them in
> > separate directories. Apparently their build system builds common
> > plus an architecture specific _fpmath.h and a choice of ld80/ld128
> > which adds at least two other header files
>
> But then again, FreeBSD supports ARM and PowerPC, both of which come
> with 64 bit long double.  So, besides ld80/ld128, there's apparently a
> generic implementation, too, to support non-ld80 and non-ld128 long
> double, right?
>
>
> Corinna
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.