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

Corinna Vinschen <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <YwkGxBxNzc/[email protected]>
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.
> >
> 
> +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.