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