public inbox for newlib@sourceware.org
 help / color / mirror / Atom feed
From: Corinna Vinschen <vinschen@redhat.com>
To: Jennifer Averett <jennifer.averett@oarcorp.com>
Cc: newlib@sourceware.org
Subject: Re: [PATCH v2 1/3] newlib: Add FreeBSD files for non LDBL_EQ_DBL support
Date: Mon, 24 Apr 2023 10:51:28 +0200	[thread overview]
Message-ID: <ZEZDEBZ72SapHnz4@calimero.vinschen.de> (raw)
In-Reply-To: <20230420212309.2375488-2-jennifer.averett@oarcorp.com>

Hi Jennifer,

On Apr 20 16:23, Jennifer Averett wrote:
> FreeBSD files to add long double support for i386,
> aarch64 and x86_64.

Building on Cygwin, I'm ewncountering a few errors:

newlib/libm/ld/s_ilogbl.c: In function ‘ilogbl’:
newlib/libm/ld/s_ilogbl.c:26:9: error: unknown type name ‘uint64_t’
   26 |         uint64_t m;
      |         ^~~~~~~~
newlib/libm/ld/s_ilogbl.c:21:1: note: ‘uint64_t’ is defined in header ‘<stdint.h>’; did you forget to ‘#include <stdint.h>’?
   20 | #include "fpmath.h"
  +++ |+#include <stdint.h>
   21 | 

newlib/libm/ld/s_rintl.c: In function ‘rintl’:
  CC       libm/complex/libm_a-creal.o
newlib/libm/ld/s_rintl.c:60:9: error: unknown type name ‘uint32_t’
   60 |         uint32_t expsign;
      |         ^~~~~~~~
newlib/libm/ld/s_rintl.c:36:1: note: ‘uint32_t’ is defined in header ‘<stdint.h>’; did you forget to ‘#include <stdint.h>’?
   35 | #include "fpmath.h"
  +++ |+#include <stdint.h>
   36 | 

newlib/libm/ld/s_ilogbl.c: In function ‘ilogbl’:
newlib/libm/ld/s_ilogbl.c:26:9: error: unknown type name ‘uint64_t’
   26 |         uint64_t m;
      |         ^~~~~~~~
newlib/libm/ld/s_ilogbl.c:21:1: note: ‘uint64_t’ is defined in header ‘<stdint.h>’; did you forget to ‘#include <stdint.h>’?
   20 | #include "fpmath.h"
  +++ |+#include <stdint.h>
   21 | 

Adding #include <stdint.h> actually fixes them.


Thanks,
Corinna


> ---
>  newlib/libc/include/sys/endian.h              | 177 ++++
>  newlib/libc/machine/aarch64/machine/_fpmath.h |  58 ++
>  newlib/libc/machine/i386/machine/_fpmath.h    |  56 ++
>  newlib/libc/machine/x86_64/machine/_fpmath.h  |  57 ++
>  newlib/libm/ld/e_acoshl.c                     |  89 ++
>  newlib/libm/ld/e_acosl.c                      |  87 ++
>  newlib/libm/ld/e_asinl.c                      |  77 ++
>  newlib/libm/ld/e_atan2l.c                     | 120 +++
>  newlib/libm/ld/e_atanhl.c                     |  74 ++
>  newlib/libm/ld/e_coshl.c                      | 132 +++
>  newlib/libm/ld/e_fmodl.c                      | 149 +++
>  newlib/libm/ld/e_lgammal.c                    |  25 +
>  newlib/libm/ld/e_remainderl.c                 |  40 +
>  newlib/libm/ld/e_sinhl.c                      | 134 +++
>  newlib/libm/ld/fpmath.h                       |  82 ++
>  newlib/libm/ld/math_private.h                 | 924 ++++++++++++++++++
>  newlib/libm/ld/s_asinhl.c                     |  91 ++
>  newlib/libm/ld/s_atanl.c                      |  85 ++
>  newlib/libm/ld/s_cbrtl.c                      | 143 +++
>  newlib/libm/ld/s_ceill.c                      | 101 ++
>  newlib/libm/ld/s_copysignl.c                  |  44 +
>  newlib/libm/ld/s_cosl.c                       | 102 ++
>  newlib/libm/ld/s_fabsl.c                      |  45 +
>  newlib/libm/ld/s_fdim.c                       |  48 +
>  newlib/libm/ld/s_floorl.c                     | 101 ++
>  newlib/libm/ld/s_fmal.c                       | 274 ++++++
>  newlib/libm/ld/s_fmaxl.c                      |  57 ++
>  newlib/libm/ld/s_fminl.c                      |  57 ++
>  newlib/libm/ld/s_frexpl.c                     |  64 ++
>  newlib/libm/ld/s_ilogbl.c                     |  53 +
>  newlib/libm/ld/s_llrintl.c                    |   9 +
>  newlib/libm/ld/s_llroundl.c                   |  11 +
>  newlib/libm/ld/s_logbl.c                      |  54 +
>  newlib/libm/ld/s_lrint.c                      |  60 ++
>  newlib/libm/ld/s_lrintl.c                     |   9 +
>  newlib/libm/ld/s_lround.c                     |  70 ++
>  newlib/libm/ld/s_lroundl.c                    |  11 +
>  newlib/libm/ld/s_modfl.c                      | 103 ++
>  newlib/libm/ld/s_nearbyint.c                  |  61 ++
>  newlib/libm/ld/s_nextafterl.c                 |  80 ++
>  newlib/libm/ld/s_nexttoward.c                 |  72 ++
>  newlib/libm/ld/s_nexttowardf.c                |  59 ++
>  newlib/libm/ld/s_remquol.c                    | 173 ++++
>  newlib/libm/ld/s_rintl.c                      |  92 ++
>  newlib/libm/ld/s_roundl.c                     |  64 ++
>  newlib/libm/ld/s_scalbln.c                    |  56 ++
>  newlib/libm/ld/s_scalbnl.c                    |  49 +
>  newlib/libm/ld/s_sinl.c                       |  95 ++
>  newlib/libm/ld/s_tanhl.c                      | 174 ++++
>  newlib/libm/ld/s_tanl.c                       |  97 ++
>  newlib/libm/ld/s_truncl.c                     |  68 ++
>  newlib/libm/ld128/b_tgammal.c                 |  57 ++
>  newlib/libm/ld128/e_lgammal_r.c               | 330 +++++++
>  newlib/libm/ld128/e_powl.c                    | 443 +++++++++
>  newlib/libm/ld128/e_rem_pio2l.h               | 135 +++
>  newlib/libm/ld128/invtrig.c                   | 102 ++
>  newlib/libm/ld128/invtrig.h                   | 115 +++
>  newlib/libm/ld128/k_cosl.c                    |  59 ++
>  newlib/libm/ld128/k_expl.h                    | 324 ++++++
>  newlib/libm/ld128/k_sinl.c                    |  59 ++
>  newlib/libm/ld128/s_erfl.c                    | 329 +++++++
>  newlib/libm/ld128/s_exp2l.c                   | 429 ++++++++
>  newlib/libm/ld128/s_expl.c                    | 326 ++++++
>  newlib/libm/ld128/s_logl.c                    | 740 ++++++++++++++
>  newlib/libm/ld80/b_expl.c                     | 113 +++
>  newlib/libm/ld80/b_logl.c                     | 375 +++++++
>  newlib/libm/ld80/b_tgammal.c                  | 419 ++++++++
>  newlib/libm/ld80/e_lgammal_r.c                | 358 +++++++
>  newlib/libm/ld80/e_powl.c                     | 662 +++++++++++++
>  newlib/libm/ld80/e_rem_pio2l.h                | 143 +++
>  newlib/libm/ld80/invtrig.c                    |  84 ++
>  newlib/libm/ld80/invtrig.h                    | 116 +++
>  newlib/libm/ld80/k_cosl.c                     |  78 ++
>  newlib/libm/ld80/k_cospil.h                   |  42 +
>  newlib/libm/ld80/k_expl.h                     | 301 ++++++
>  newlib/libm/ld80/k_sinl.c                     |  62 ++
>  newlib/libm/ld80/k_sinpil.h                   |  42 +
>  newlib/libm/ld80/s_cospil.c                   | 129 +++
>  newlib/libm/ld80/s_erfl.c                     | 337 +++++++
>  newlib/libm/ld80/s_exp2l.c                    | 290 ++++++
>  newlib/libm/ld80/s_expl.c                     | 279 ++++++
>  newlib/libm/ld80/s_logl.c                     | 722 ++++++++++++++
>  newlib/libm/ld80/s_sinpil.c                   | 140 +++
>  83 files changed, 13153 insertions(+)
>  create mode 100644 newlib/libc/include/sys/endian.h
>  create mode 100644 newlib/libc/machine/aarch64/machine/_fpmath.h
>  create mode 100644 newlib/libc/machine/i386/machine/_fpmath.h
>  create mode 100644 newlib/libc/machine/x86_64/machine/_fpmath.h
>  create mode 100644 newlib/libm/ld/e_acoshl.c
>  create mode 100644 newlib/libm/ld/e_acosl.c
>  create mode 100644 newlib/libm/ld/e_asinl.c
>  create mode 100644 newlib/libm/ld/e_atan2l.c
>  create mode 100644 newlib/libm/ld/e_atanhl.c
>  create mode 100644 newlib/libm/ld/e_coshl.c
>  create mode 100644 newlib/libm/ld/e_fmodl.c
>  create mode 100644 newlib/libm/ld/e_lgammal.c
>  create mode 100644 newlib/libm/ld/e_remainderl.c
>  create mode 100644 newlib/libm/ld/e_sinhl.c
>  create mode 100644 newlib/libm/ld/fpmath.h
>  create mode 100644 newlib/libm/ld/math_private.h
>  create mode 100644 newlib/libm/ld/s_asinhl.c
>  create mode 100644 newlib/libm/ld/s_atanl.c
>  create mode 100644 newlib/libm/ld/s_cbrtl.c
>  create mode 100644 newlib/libm/ld/s_ceill.c
>  create mode 100644 newlib/libm/ld/s_copysignl.c
>  create mode 100644 newlib/libm/ld/s_cosl.c
>  create mode 100644 newlib/libm/ld/s_fabsl.c
>  create mode 100644 newlib/libm/ld/s_fdim.c
>  create mode 100644 newlib/libm/ld/s_floorl.c
>  create mode 100644 newlib/libm/ld/s_fmal.c
>  create mode 100644 newlib/libm/ld/s_fmaxl.c
>  create mode 100644 newlib/libm/ld/s_fminl.c
>  create mode 100644 newlib/libm/ld/s_frexpl.c
>  create mode 100644 newlib/libm/ld/s_ilogbl.c
>  create mode 100644 newlib/libm/ld/s_llrintl.c
>  create mode 100644 newlib/libm/ld/s_llroundl.c
>  create mode 100644 newlib/libm/ld/s_logbl.c
>  create mode 100644 newlib/libm/ld/s_lrint.c
>  create mode 100644 newlib/libm/ld/s_lrintl.c
>  create mode 100644 newlib/libm/ld/s_lround.c
>  create mode 100644 newlib/libm/ld/s_lroundl.c
>  create mode 100644 newlib/libm/ld/s_modfl.c
>  create mode 100644 newlib/libm/ld/s_nearbyint.c
>  create mode 100644 newlib/libm/ld/s_nextafterl.c
>  create mode 100644 newlib/libm/ld/s_nexttoward.c
>  create mode 100644 newlib/libm/ld/s_nexttowardf.c
>  create mode 100644 newlib/libm/ld/s_remquol.c
>  create mode 100644 newlib/libm/ld/s_rintl.c
>  create mode 100644 newlib/libm/ld/s_roundl.c
>  create mode 100644 newlib/libm/ld/s_scalbln.c
>  create mode 100644 newlib/libm/ld/s_scalbnl.c
>  create mode 100644 newlib/libm/ld/s_sinl.c
>  create mode 100644 newlib/libm/ld/s_tanhl.c
>  create mode 100644 newlib/libm/ld/s_tanl.c
>  create mode 100644 newlib/libm/ld/s_truncl.c
>  create mode 100644 newlib/libm/ld128/b_tgammal.c
>  create mode 100644 newlib/libm/ld128/e_lgammal_r.c
>  create mode 100644 newlib/libm/ld128/e_powl.c
>  create mode 100644 newlib/libm/ld128/e_rem_pio2l.h
>  create mode 100644 newlib/libm/ld128/invtrig.c
>  create mode 100644 newlib/libm/ld128/invtrig.h
>  create mode 100644 newlib/libm/ld128/k_cosl.c
>  create mode 100644 newlib/libm/ld128/k_expl.h
>  create mode 100644 newlib/libm/ld128/k_sinl.c
>  create mode 100644 newlib/libm/ld128/s_erfl.c
>  create mode 100644 newlib/libm/ld128/s_exp2l.c
>  create mode 100644 newlib/libm/ld128/s_expl.c
>  create mode 100644 newlib/libm/ld128/s_logl.c
>  create mode 100644 newlib/libm/ld80/b_expl.c
>  create mode 100644 newlib/libm/ld80/b_logl.c
>  create mode 100644 newlib/libm/ld80/b_tgammal.c
>  create mode 100644 newlib/libm/ld80/e_lgammal_r.c
>  create mode 100644 newlib/libm/ld80/e_powl.c
>  create mode 100644 newlib/libm/ld80/e_rem_pio2l.h
>  create mode 100644 newlib/libm/ld80/invtrig.c
>  create mode 100644 newlib/libm/ld80/invtrig.h
>  create mode 100644 newlib/libm/ld80/k_cosl.c
>  create mode 100644 newlib/libm/ld80/k_cospil.h
>  create mode 100644 newlib/libm/ld80/k_expl.h
>  create mode 100644 newlib/libm/ld80/k_sinl.c
>  create mode 100644 newlib/libm/ld80/k_sinpil.h
>  create mode 100644 newlib/libm/ld80/s_cospil.c
>  create mode 100644 newlib/libm/ld80/s_erfl.c
>  create mode 100644 newlib/libm/ld80/s_exp2l.c
>  create mode 100644 newlib/libm/ld80/s_expl.c
>  create mode 100644 newlib/libm/ld80/s_logl.c
>  create mode 100644 newlib/libm/ld80/s_sinpil.c
> 
> diff --git a/newlib/libc/include/sys/endian.h b/newlib/libc/include/sys/endian.h
> new file mode 100644
> index 000000000..d91c442e9
> --- /dev/null
> +++ b/newlib/libc/include/sys/endian.h
> @@ -0,0 +1,177 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2002 Thomas Moestl <tmm@FreeBSD.org>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#ifndef _SYS_ENDIAN_H_
> +#define _SYS_ENDIAN_H_
> +
> +#include <sys/cdefs.h>
> +#include <sys/_types.h>
> +#include <machine/endian.h>
> +
> +#ifndef _UINT8_T_DECLARED
> +typedef	__uint8_t	uint8_t;
> +#define	_UINT8_T_DECLARED
> +#endif
> +
> +#ifndef _UINT16_T_DECLARED
> +typedef	__uint16_t	uint16_t;
> +#define	_UINT16_T_DECLARED
> +#endif
> +
> +#ifndef _UINT32_T_DECLARED
> +typedef	__uint32_t	uint32_t;
> +#define	_UINT32_T_DECLARED
> +#endif
> +
> +#ifndef _UINT64_T_DECLARED
> +typedef	__uint64_t	uint64_t;
> +#define	_UINT64_T_DECLARED
> +#endif
> +
> +/*
> + * Note: While tempting to try to avoid namespace pollution from this file,
> + * several software packages assume these marcos are defined, even when it
> + * defines _POSIX_C_SOURCE to request an unpolluted namespace.
> + */
> +
> +/*
> + * General byte order swapping functions.
> + */
> +#define	bswap16(x)	__bswap16(x)
> +#define	bswap32(x)	__bswap32(x)
> +#define	bswap64(x)	__bswap64(x)
> +
> +/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */
> +static __inline uint16_t
> +be16dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return ((p[0] << 8) | p[1]);
> +}
> +
> +static __inline uint32_t
> +be32dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
> +}
> +
> +static __inline uint64_t
> +be64dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4));
> +}
> +
> +static __inline uint16_t
> +le16dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return ((p[1] << 8) | p[0]);
> +}
> +
> +static __inline uint32_t
> +le32dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
> +}
> +
> +static __inline uint64_t
> +le64dec(const void *pp)
> +{
> +	uint8_t const *p = (uint8_t const *)pp;
> +
> +	return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
> +}
> +
> +static __inline void
> +be16enc(void *pp, uint16_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	p[0] = (u >> 8) & 0xff;
> +	p[1] = u & 0xff;
> +}
> +
> +static __inline void
> +be32enc(void *pp, uint32_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	p[0] = (u >> 24) & 0xff;
> +	p[1] = (u >> 16) & 0xff;
> +	p[2] = (u >> 8) & 0xff;
> +	p[3] = u & 0xff;
> +}
> +
> +static __inline void
> +be64enc(void *pp, uint64_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	be32enc(p, (uint32_t)(u >> 32));
> +	be32enc(p + 4, (uint32_t)(u & 0xffffffffU));
> +}
> +
> +static __inline void
> +le16enc(void *pp, uint16_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	p[0] = u & 0xff;
> +	p[1] = (u >> 8) & 0xff;
> +}
> +
> +static __inline void
> +le32enc(void *pp, uint32_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	p[0] = u & 0xff;
> +	p[1] = (u >> 8) & 0xff;
> +	p[2] = (u >> 16) & 0xff;
> +	p[3] = (u >> 24) & 0xff;
> +}
> +
> +static __inline void
> +le64enc(void *pp, uint64_t u)
> +{
> +	uint8_t *p = (uint8_t *)pp;
> +
> +	le32enc(p, (uint32_t)(u & 0xffffffffU));
> +	le32enc(p + 4, (uint32_t)(u >> 32));
> +}
> +#endif	/* _SYS_ENDIAN_H_ */
> diff --git a/newlib/libc/machine/aarch64/machine/_fpmath.h b/newlib/libc/machine/aarch64/machine/_fpmath.h
> new file mode 100644
> index 000000000..71d0a7152
> --- /dev/null
> +++ b/newlib/libc/machine/aarch64/machine/_fpmath.h
> @@ -0,0 +1,58 @@
> +/*-
> + * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
> + * Copyright (2) 2014 The FreeBSD Foundation
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +union IEEEl2bits {
> +	long double	e;
> +	struct {
> +		unsigned long	manl	:64;
> +		unsigned long	manh	:48;
> +		unsigned int	exp	:15;
> +		unsigned int	sign	:1;
> +	} bits;
> +	/* TODO andrew: Check the packing here */
> +	struct {
> +		unsigned long	manl	:64;
> +		unsigned long	manh	:48;
> +		unsigned int	expsign	:16;
> +	} xbits;
> +};
> +
> +#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)
> diff --git a/newlib/libc/machine/i386/machine/_fpmath.h b/newlib/libc/machine/i386/machine/_fpmath.h
> new file mode 100644
> index 000000000..874439c34
> --- /dev/null
> +++ b/newlib/libc/machine/i386/machine/_fpmath.h
> @@ -0,0 +1,56 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +union IEEEl2bits {
> +	long double	e;
> +	struct {
> +		unsigned int	manl	:32;
> +		unsigned int	manh	:32;
> +		unsigned int	exp	:15;
> +		unsigned int	sign	:1;
> +		unsigned int	junk	:16;
> +	} bits;
> +	struct {
> +		unsigned long long man	:64;
> +		unsigned int 	expsign	:16;
> +		unsigned int	junk	:16;
> +	} xbits;
> +};
> +
> +#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)
> diff --git a/newlib/libc/machine/x86_64/machine/_fpmath.h b/newlib/libc/machine/x86_64/machine/_fpmath.h
> new file mode 100644
> index 000000000..8be7b7dba
> --- /dev/null
> +++ b/newlib/libc/machine/x86_64/machine/_fpmath.h
> @@ -0,0 +1,57 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +union IEEEl2bits {
> +	long double	e;
> +	struct {
> +		unsigned int	manl	:32;
> +		unsigned int	manh	:32;
> +		unsigned int	exp	:15;
> +		unsigned int	sign	:1;
> +		unsigned int	junkl	:16;
> +		unsigned int	junkh	:32;
> +	} bits;
> +	struct {
> +		unsigned long	man	:64;
> +		unsigned int	expsign	:16;
> +		unsigned long	junk	:48;
> +	} xbits;
> +};
> +
> +#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)
> diff --git a/newlib/libm/ld/e_acoshl.c b/newlib/libm/ld/e_acoshl.c
> new file mode 100644
> index 000000000..b9f3aed67
> --- /dev/null
> +++ b/newlib/libm/ld/e_acoshl.c
> @@ -0,0 +1,89 @@
> +/* from: FreeBSD: head/lib/msun/src/e_acosh.c 176451 2008-02-22 02:30:36Z das */
> +
> +/* @(#)e_acosh.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + *
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_acosh.c for complete comments.
> + *
> + * Converted to long double by David Schultz <das@FreeBSD.ORG> and
> + * Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* EXP_LARGE is the threshold above which we use acosh(x) ~= log(2x). */
> +#if LDBL_MANT_DIG == 64
> +#define	EXP_LARGE	34
> +#elif LDBL_MANT_DIG == 113
> +#define	EXP_LARGE	58
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const double
> +one	= 1.0;
> +
> +#if LDBL_MANT_DIG == 64
> +static const union IEEEl2bits
> +u_ln2 =  LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L);
> +#define	ln2	u_ln2.e
> +#elif LDBL_MANT_DIG == 113
> +static const long double
> +ln2 =  6.93147180559945309417232121458176568e-1L;	/* 0x162e42fefa39ef35793c7673007e6.0p-113 */
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +acoshl(long double x)
> +{
> +	long double t;
> +	int16_t hx;
> +
> +	ENTERI();
> +	GET_LDBL_EXPSIGN(hx, x);
> +	if (hx < 0x3fff) {		/* x < 1, or misnormal */
> +	    RETURNI((x-x)/(x-x));
> +	} else if (hx >= BIAS + EXP_LARGE) { /* x >= LARGE */
> +	    if (hx >= 0x7fff) {		/* x is inf, NaN or misnormal */
> +	        RETURNI(x+x);
> +	    } else 
> +		RETURNI(logl(x)+ln2);	/* acosh(huge)=log(2x), or misnormal */
> +	} else if (hx == 0x3fff && x == 1) {
> +	    RETURNI(0.0);		/* acosh(1) = 0 */
> +	} else if (hx >= 0x4000) {	/* LARGE > x >= 2, or misnormal */
> +	    t=x*x;
> +	    RETURNI(logl(2.0*x-one/(x+sqrtl(t-one))));
> +	} else {			/* 1<x<2 */
> +	    t = x-one;
> +	    RETURNI(log1pl(t+sqrtl(2.0*t+t*t)));
> +	}
> +}
> diff --git a/newlib/libm/ld/e_acosl.c b/newlib/libm/ld/e_acosl.c
> new file mode 100644
> index 000000000..d33c8feda
> --- /dev/null
> +++ b/newlib/libm/ld/e_acosl.c
> @@ -0,0 +1,87 @@
> +
> +/* @(#)e_acos.c 1.3 95/01/18 */
> +/* FreeBSD: head/lib/msun/src/e_acos.c 176451 2008-02-22 02:30:36Z das */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See comments in e_acos.c.
> + * Converted to long double by David Schultz <das@FreeBSD.ORG>.
> + */
> +
> +#include <float.h>
> +
> +#include "invtrig.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const long double
> +one=  1.00000000000000000000e+00;
> +
> +#ifdef __i386__
> +/* XXX Work around the fact that gcc truncates long double constants on i386 */
> +static volatile double
> +pi1 =  3.14159265358979311600e+00,	/*  0x1.921fb54442d18p+1  */
> +pi2 =  1.22514845490862001043e-16;	/*  0x1.1a80000000000p-53 */
> +#define	pi	((long double)pi1 + pi2)
> +#else
> +static const long double
> +pi =  3.14159265358979323846264338327950280e+00L;
> +#endif
> +
> +long double
> +acosl(long double x)
> +{
> +	union IEEEl2bits u;
> +	long double z,p,q,r,w,s,c,df;
> +	int16_t expsign, expt;
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	expt = expsign & 0x7fff;
> +	if(expt >= BIAS) {	/* |x| >= 1 */
> +	    if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0) {
> +		if (expsign>0) return 0.0;	/* acos(1) = 0  */
> +		else return pi+2.0*pio2_lo;	/* acos(-1)= pi */
> +	    }
> +	    return (x-x)/(x-x);		/* acos(|x|>1) is NaN */
> +	}
> +	if(expt<BIAS-1) {	/* |x| < 0.5 */
> +	    if(expt<ACOS_CONST) return pio2_hi+pio2_lo;/*x tiny: acosl=pi/2*/
> +	    z = x*x;
> +	    p = P(z);
> +	    q = Q(z);
> +	    r = p/q;
> +	    return pio2_hi - (x - (pio2_lo-x*r));
> +	} else  if (expsign<0) {	/* x < -0.5 */
> +	    z = (one+x)*0.5;
> +	    p = P(z);
> +	    q = Q(z);
> +	    s = sqrtl(z);
> +	    r = p/q;
> +	    w = r*s-pio2_lo;
> +	    return pi - 2.0*(s+w);
> +	} else {			/* x > 0.5 */
> +	    z = (one-x)*0.5;
> +	    s = sqrtl(z);
> +	    u.e = s;
> +	    u.bits.manl = 0;
> +	    df = u.e;
> +	    c  = (z-df*df)/(s+df);
> +	    p = P(z);
> +	    q = Q(z);
> +	    r = p/q;
> +	    w = r*s+c;
> +	    return 2.0*(df+w);
> +	}
> +}
> diff --git a/newlib/libm/ld/e_asinl.c b/newlib/libm/ld/e_asinl.c
> new file mode 100644
> index 000000000..a85765f1b
> --- /dev/null
> +++ b/newlib/libm/ld/e_asinl.c
> @@ -0,0 +1,77 @@
> +
> +/* @(#)e_asin.c 1.3 95/01/18 */
> +/* FreeBSD: head/lib/msun/src/e_asin.c 176451 2008-02-22 02:30:36Z das */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See comments in e_asin.c.
> + * Converted to long double by David Schultz <das@FreeBSD.ORG>.
> + */
> +
> +#include <float.h>
> +
> +#include "invtrig.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const long double
> +one =  1.00000000000000000000e+00,
> +huge = 1.000e+300;
> +
> +long double
> +asinl(long double x)
> +{
> +	union IEEEl2bits u;
> +	long double t=0.0,w,p,q,c,r,s;
> +	int16_t expsign, expt;
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	expt = expsign & 0x7fff;
> +	if(expt >= BIAS) {		/* |x|>= 1 */
> +		if(expt==BIAS && ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)==0)
> +		    /* asin(1)=+-pi/2 with inexact */
> +		    return x*pio2_hi+x*pio2_lo;	
> +	    return (x-x)/(x-x);		/* asin(|x|>1) is NaN */   
> +	} else if (expt<BIAS-1) {	/* |x|<0.5 */
> +	    if(expt<ASIN_LINEAR) {	/* if |x| is small, asinl(x)=x */
> +		if(huge+x>one) return x;/* return x with inexact if x!=0*/
> +	    }
> +	    t = x*x;
> +	    p = P(t);
> +	    q = Q(t);
> +	    w = p/q;
> +	    return x+x*w;
> +	}
> +	/* 1> |x|>= 0.5 */
> +	w = one-fabsl(x);
> +	t = w*0.5;
> +	p = P(t);
> +	q = Q(t);
> +	s = sqrtl(t);
> +	if(u.bits.manh>=THRESH) { 	/* if |x| is close to 1 */
> +	    w = p/q;
> +	    t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
> +	} else {
> +	    u.e = s;
> +	    u.bits.manl = 0;
> +	    w = u.e;
> +	    c  = (t-w*w)/(s+w);
> +	    r  = p/q;
> +	    p  = 2.0*s*r-(pio2_lo-2.0*c);
> +	    q  = pio4_hi-2.0*w;
> +	    t  = pio4_hi-(p-q);
> +	}    
> +	if(expsign>0) return t; else return -t;    
> +}
> diff --git a/newlib/libm/ld/e_atan2l.c b/newlib/libm/ld/e_atan2l.c
> new file mode 100644
> index 000000000..94ebdec54
> --- /dev/null
> +++ b/newlib/libm/ld/e_atan2l.c
> @@ -0,0 +1,120 @@
> +
> +/* @(#)e_atan2.c 1.3 95/01/18 */
> +/* FreeBSD: head/lib/msun/src/e_atan2.c 176451 2008-02-22 02:30:36Z das */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + *
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See comments in e_atan2.c.
> + * Converted to long double by David Schultz <das@FreeBSD.ORG>.
> + */
> +
> +#include <float.h>
> +
> +#include "invtrig.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static volatile long double
> +tiny  = 1.0e-300;
> +static const long double
> +zero  = 0.0;
> +
> +#ifdef __i386__
> +/* XXX Work around the fact that gcc truncates long double constants on i386 */
> +static volatile double
> +pi1 =  3.14159265358979311600e+00,	/*  0x1.921fb54442d18p+1  */
> +pi2 =  1.22514845490862001043e-16;	/*  0x1.1a80000000000p-53 */
> +#define	pi	((long double)pi1 + pi2)
> +#else
> +static const long double
> +pi =  3.14159265358979323846264338327950280e+00L;
> +#endif
> +
> +long double
> +atan2l(long double y, long double x)
> +{
> +	union IEEEl2bits ux, uy;
> +	long double z;
> +	int32_t k,m;
> +	int16_t exptx, expsignx, expty, expsigny;
> +
> +	uy.e = y;
> +	expsigny = uy.xbits.expsign;
> +	expty = expsigny & 0x7fff;
> +	ux.e = x;
> +	expsignx = ux.xbits.expsign;
> +	exptx = expsignx & 0x7fff;
> +
> +	if ((exptx==BIAS+LDBL_MAX_EXP &&
> +	     ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)!=0) ||	/* x is NaN */
> +	    (expty==BIAS+LDBL_MAX_EXP &&
> +	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0))	/* y is NaN */
> +	    return nan_mix(x, y);
> +	if (expsignx==BIAS && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
> +	    return atanl(y);					/* x=1.0 */
> +	m = ((expsigny>>15)&1)|((expsignx>>14)&2);	/* 2*sign(x)+sign(y) */
> +
> +    /* when y = 0 */
> +	if(expty==0 && ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)==0) {
> +	    switch(m) {
> +		case 0: 
> +		case 1: return y; 	/* atan(+-0,+anything)=+-0 */
> +		case 2: return  pi+tiny;/* atan(+0,-anything) = pi */
> +		case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
> +	    }
> +	}
> +    /* when x = 0 */
> +	if(exptx==0 && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)==0)
> +	    return (expsigny<0)?  -pio2_hi-tiny: pio2_hi+tiny;
> +
> +    /* when x is INF */
> +	if(exptx==BIAS+LDBL_MAX_EXP) {
> +	    if(expty==BIAS+LDBL_MAX_EXP) {
> +		switch(m) {
> +		    case 0: return  pio2_hi*0.5+tiny;/* atan(+INF,+INF) */
> +		    case 1: return -pio2_hi*0.5-tiny;/* atan(-INF,+INF) */
> +		    case 2: return  1.5*pio2_hi+tiny;/*atan(+INF,-INF)*/
> +		    case 3: return -1.5*pio2_hi-tiny;/*atan(-INF,-INF)*/
> +		}
> +	    } else {
> +		switch(m) {
> +		    case 0: return  zero  ;	/* atan(+...,+INF) */
> +		    case 1: return -zero  ;	/* atan(-...,+INF) */
> +		    case 2: return  pi+tiny  ;	/* atan(+...,-INF) */
> +		    case 3: return -pi-tiny  ;	/* atan(-...,-INF) */
> +		}
> +	    }
> +	}
> +    /* when y is INF */
> +	if(expty==BIAS+LDBL_MAX_EXP)
> +	    return (expsigny<0)? -pio2_hi-tiny: pio2_hi+tiny;
> +
> +    /* compute y/x */
> +	k = expty-exptx;
> +	if(k > LDBL_MANT_DIG+2) {			/* |y/x| huge */
> +	    z=pio2_hi+pio2_lo;
> +	    m&=1;
> +	}
> +	else if(expsignx<0&&k<-LDBL_MANT_DIG-2) z=0.0; 	/* |y/x| tiny, x<0 */
> +	else z=atanl(fabsl(y/x));		/* safe to do y/x */
> +	switch (m) {
> +	    case 0: return       z  ;	/* atan(+,+) */
> +	    case 1: return      -z  ;	/* atan(-,+) */
> +	    case 2: return  pi-(z-pi_lo);/* atan(+,-) */
> +	    default: /* case 3 */
> +	    	    return  (z-pi_lo)-pi;/* atan(-,-) */
> +	}
> +}
> diff --git a/newlib/libm/ld/e_atanhl.c b/newlib/libm/ld/e_atanhl.c
> new file mode 100644
> index 000000000..11d56ea52
> --- /dev/null
> +++ b/newlib/libm/ld/e_atanhl.c
> @@ -0,0 +1,74 @@
> +/* from: FreeBSD: head/lib/msun/src/e_atanh.c 176451 2008-02-22 02:30:36Z das */
> +
> +/* @(#)e_atanh.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + *
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_atanh.c for complete comments.
> + *
> + * Converted to long double by David Schultz <das@FreeBSD.ORG> and
> + * Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* EXP_TINY is the threshold below which we use atanh(x) ~= x. */
> +#if LDBL_MANT_DIG == 64
> +#define	EXP_TINY	-34
> +#elif LDBL_MANT_DIG == 113
> +#define	EXP_TINY	-58
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const double one = 1.0, huge = 1e300;
> +static const double zero = 0.0;
> +
> +long double
> +atanhl(long double x)
> +{
> +	long double t;
> +	uint16_t hx, ix;
> +
> +	ENTERI();
> +	GET_LDBL_EXPSIGN(hx, x);
> +	ix = hx & 0x7fff;
> +	if (ix >= 0x3fff)		/* |x| >= 1, or NaN or misnormal */
> +	    RETURNI(fabsl(x) == 1 ? x / zero : (x - x) / (x - x));
> +	if (ix < BIAS + EXP_TINY && (huge + x) > zero)
> +	    RETURNI(x);			/* x is tiny */
> +	SET_LDBL_EXPSIGN(x, ix);
> +	if (ix < 0x3ffe) {		/* |x| < 0.5, or misnormal */
> +	    t = x+x;
> +	    t = 0.5*log1pl(t+t*x/(one-x));
> +	} else 
> +	    t = 0.5*log1pl((x+x)/(one-x));
> +	RETURNI((hx & 0x8000) == 0 ? t : -t);
> +}
> diff --git a/newlib/libm/ld/e_coshl.c b/newlib/libm/ld/e_coshl.c
> new file mode 100644
> index 000000000..4e3b28311
> --- /dev/null
> +++ b/newlib/libm/ld/e_coshl.c
> @@ -0,0 +1,132 @@
> +/* from: FreeBSD: head/lib/msun/src/e_coshl.c XXX */
> +
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_cosh.c for complete comments.
> + *
> + * Converted to long double by Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +#include "k_expl.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const volatile long double huge = 0x1p10000L, tiny = 0x1p-10000L;
> +#if LDBL_MANT_DIG == 64
> +/*
> + * Domain [-1, 1], range ~[-1.8211e-21, 1.8211e-21]:
> + * |cosh(x) - c(x)| < 2**-68.8
> + */
> +static const union IEEEl2bits
> +C4u = LD80C(0xaaaaaaaaaaaaac78, -5,  4.16666666666666682297e-2L);
> +#define	C4	C4u.e
> +static const double
> +C2  =  0.5,
> +C6  =  1.3888888888888616e-3,		/*  0x16c16c16c16b99.0p-62 */
> +C8  =  2.4801587301767953e-5,		/*  0x1a01a01a027061.0p-68 */
> +C10 =  2.7557319163300398e-7,		/*  0x127e4fb6c9b55f.0p-74 */
> +C12 =  2.0876768371393075e-9,		/*  0x11eed99406a3f4.0p-81 */
> +C14 =  1.1469537039374480e-11,		/*  0x1938c67cd18c48.0p-89 */
> +C16 =  4.8473490896852041e-14;		/*  0x1b49c429701e45.0p-97 */
> +#elif LDBL_MANT_DIG == 113
> +/*
> + * Domain [-1, 1], range ~[-2.3194e-37, 2.3194e-37]:
> + * |cosh(x) - c(x)| < 2**-121.69
> + */
> +static const long double
> +C4  =  4.16666666666666666666666666666666225e-2L,	/*  0x1555555555555555555555555554e.0p-117L */
> +C6  =  1.38888888888888888888888888889434831e-3L,	/*  0x16c16c16c16c16c16c16c16c1dd7a.0p-122L */
> +C8  =  2.48015873015873015873015871870962089e-5L,	/*  0x1a01a01a01a01a01a01a017af2756.0p-128L */
> +C10 =  2.75573192239858906525574318600800201e-7L,	/*  0x127e4fb7789f5c72ef01c8a040640.0p-134L */
> +C12 =  2.08767569878680989791444691755468269e-9L,	/*  0x11eed8eff8d897b543d0679607399.0p-141L */
> +C14=  1.14707455977297247387801189650495351e-11L,	/*  0x193974a8c07c9d24ae169a7fa9b54.0p-149L */
> +C16 =  4.77947733238737883626416876486279985e-14L;	/*  0x1ae7f3e733b814d4e1b90f5727fe4.0p-157L */
> +static const double
> +C2  =  0.5,
> +C18 =  1.5619206968597871e-16,		/*  0x16827863b9900b.0p-105 */
> +C20 =  4.1103176218528049e-19,		/*  0x1e542ba3d3c269.0p-114 */
> +C22 =  8.8967926401641701e-22,		/*  0x10ce399542a014.0p-122 */
> +C24 =  1.6116681626523904e-24,		/*  0x1f2c981d1f0cb7.0p-132 */
> +C26 =  2.5022374732804632e-27;		/*  0x18c7ecf8b2c4a0.0p-141 */
> +#else
> +#error "Unsupported long double format"
> +#endif /* LDBL_MANT_DIG == 64 */
> +
> +/* log(2**16385 - 0.5) rounded up: */
> +static const float
> +o_threshold =  1.13572168e4;		/*  0xb174de.0p-10 */
> +
> +long double
> +coshl(long double x)
> +{
> +	long double hi,lo,x2,x4;
> +#if LDBL_MANT_DIG == 113
> +	double dx2;
> +#endif
> +	uint16_t ix;
> +
> +	GET_LDBL_EXPSIGN(ix,x);
> +	ix &= 0x7fff;
> +
> +    /* x is INF or NaN */
> +	if(ix>=0x7fff) return x*x;
> +
> +	ENTERI();
> +
> +    /* |x| < 1, return 1 or c(x) */
> +	if(ix<0x3fff) {
> +	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x| < TINY */
> +		RETURNI(1+tiny);	/* cosh(tiny) = 1(+) with inexact */
> +	    x2 = x*x;
> +#if LDBL_MANT_DIG == 64
> +	    x4 = x2*x2;
> +	    RETURNI(((C16*x2 + C14)*x4 + (C12*x2 + C10))*(x4*x4*x2) +
> +		((C8*x2 + C6)*x2 + C4)*x4 + C2*x2 + 1);
> +#elif LDBL_MANT_DIG == 113
> +	    dx2 = x2;
> +	    RETURNI((((((((((((C26*dx2 + C24)*dx2 + C22)*dx2 +
> +		C20)*x2 + C18)*x2 +
> +		C16)*x2 + C14)*x2 + C12)*x2 + C10)*x2 + C8)*x2 + C6)*x2 +
> +		C4)*(x2*x2) + C2*x2 + 1);
> +#endif
> +	}
> +
> +    /* |x| in [1, 64), return accurate exp(|x|)/2+1/exp(|x|)/2 */
> +	if (ix < 0x4005) {
> +	    k_hexpl(fabsl(x), &hi, &lo);
> +	    RETURNI(lo + 0.25/(hi + lo) + hi);
> +	}
> +
> +    /* |x| in [64, o_threshold], return correctly-overflowing exp(|x|)/2 */
> +	if (fabsl(x) <= o_threshold)
> +	    RETURNI(hexpl(fabsl(x)));
> +
> +    /* |x| > o_threshold, cosh(x) overflow */
> +	RETURNI(huge*huge);
> +}
> diff --git a/newlib/libm/ld/e_fmodl.c b/newlib/libm/ld/e_fmodl.c
> new file mode 100644
> index 000000000..ad3bcc34c
> --- /dev/null
> +++ b/newlib/libm/ld/e_fmodl.c
> @@ -0,0 +1,149 @@
> +/* @(#)e_fmod.c 1.3 95/01/18 */
> +/*-
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#define	BIAS (LDBL_MAX_EXP - 1)
> +
> +#if LDBL_MANL_SIZE > 32
> +typedef	uint64_t manl_t;
> +#else
> +typedef	uint32_t manl_t;
> +#endif
> +
> +#if LDBL_MANH_SIZE > 32
> +typedef	uint64_t manh_t;
> +#else
> +typedef	uint32_t manh_t;
> +#endif
> +
> +/*
> + * These macros add and remove an explicit integer bit in front of the
> + * fractional mantissa, if the architecture doesn't have such a bit by
> + * default already.
> + */
> +#ifdef LDBL_IMPLICIT_NBIT
> +#define	SET_NBIT(hx)	((hx) | (1ULL << LDBL_MANH_SIZE))
> +#define	HFRAC_BITS	LDBL_MANH_SIZE
> +#else
> +#define	SET_NBIT(hx)	(hx)
> +#define	HFRAC_BITS	(LDBL_MANH_SIZE - 1)
> +#endif
> +
> +#define	MANL_SHIFT	(LDBL_MANL_SIZE - 1)
> +
> +static const long double one = 1.0, Zero[] = {0.0, -0.0,};
> +
> +/*
> + * fmodl(x,y)
> + * Return x mod y in exact arithmetic
> + * Method: shift and subtract
> + *
> + * Assumptions:
> + * - The low part of the mantissa fits in a manl_t exactly.
> + * - The high part of the mantissa fits in an int64_t with enough room
> + *   for an explicit integer bit in front of the fractional bits.
> + */
> +long double
> +fmodl(long double x, long double y)
> +{
> +	union IEEEl2bits ux, uy;
> +	int64_t hx,hz;	/* We need a carry bit even if LDBL_MANH_SIZE is 32. */
> +	manh_t hy;
> +	manl_t lx,ly,lz;
> +	int ix,iy,n,sx;
> +
> +	ux.e = x;
> +	uy.e = y;
> +	sx = ux.bits.sign;
> +
> +    /* purge off exception values */
> +	if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
> +	   (ux.bits.exp == BIAS + LDBL_MAX_EXP) ||	 /* or x not finite */
> +	   (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
> +	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
> +	    return nan_mix_op(x, y, *)/nan_mix_op(x, y, *);
> +	if(ux.bits.exp<=uy.bits.exp) {
> +	    if((ux.bits.exp<uy.bits.exp) ||
> +	       (ux.bits.manh<=uy.bits.manh &&
> +		(ux.bits.manh<uy.bits.manh ||
> +		 ux.bits.manl<uy.bits.manl))) {
> +		return x;		/* |x|<|y| return x or x-y */
> +	    }
> +	    if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
> +		return Zero[sx];	/* |x|=|y| return x*0*/
> +	    }
> +	}
> +
> +    /* determine ix = ilogb(x) */
> +	if(ux.bits.exp == 0) {	/* subnormal x */
> +	    ux.e *= 0x1.0p512;
> +	    ix = ux.bits.exp - (BIAS + 512);
> +	} else {
> +	    ix = ux.bits.exp - BIAS;
> +	}
> +
> +    /* determine iy = ilogb(y) */
> +	if(uy.bits.exp == 0) {	/* subnormal y */
> +	    uy.e *= 0x1.0p512;
> +	    iy = uy.bits.exp - (BIAS + 512);
> +	} else {
> +	    iy = uy.bits.exp - BIAS;
> +	}
> +
> +    /* set up {hx,lx}, {hy,ly} and align y to x */
> +	hx = SET_NBIT(ux.bits.manh);
> +	hy = SET_NBIT(uy.bits.manh);
> +	lx = ux.bits.manl;
> +	ly = uy.bits.manl;
> +
> +    /* fix point fmod */
> +	n = ix - iy;
> +
> +	while(n--) {
> +	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
> +	    if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
> +	    else {
> +		if ((hz|lz)==0)		/* return sign(x)*0 */
> +		    return Zero[sx];
> +		hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz;
> +	    }
> +	}
> +	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
> +	if(hz>=0) {hx=hz;lx=lz;}
> +
> +    /* convert back to floating value and restore the sign */
> +	if((hx|lx)==0)			/* return sign(x)*0 */
> +	    return Zero[sx];
> +	while(hx<(1ULL<<HFRAC_BITS)) {	/* normalize x */
> +	    hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
> +	    iy -= 1;
> +	}
> +	ux.bits.manh = hx; /* The mantissa is truncated here if needed. */
> +	ux.bits.manl = lx;
> +	if (iy < LDBL_MIN_EXP) {
> +	    ux.bits.exp = iy + (BIAS + 512);
> +	    ux.e *= 0x1p-512;
> +	} else {
> +	    ux.bits.exp = iy + BIAS;
> +	}
> +	x = ux.e * one;		/* create necessary signal */
> +	return x;		/* exact output */
> +}
> diff --git a/newlib/libm/ld/e_lgammal.c b/newlib/libm/ld/e_lgammal.c
> new file mode 100644
> index 000000000..ebc2fc78c
> --- /dev/null
> +++ b/newlib/libm/ld/e_lgammal.c
> @@ -0,0 +1,25 @@
> +/* @(#)e_lgamma.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include "math.h"
> +#include "math_private.h"
> +
> +extern int signgam;
> +
> +long double
> +lgammal(long double x)
> +{
> +	return lgammal_r(x,&signgam);
> +}
> diff --git a/newlib/libm/ld/e_remainderl.c b/newlib/libm/ld/e_remainderl.c
> new file mode 100644
> index 000000000..4a6786309
> --- /dev/null
> +++ b/newlib/libm/ld/e_remainderl.c
> @@ -0,0 +1,40 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +long double
> +remainderl(long double x, long double y)
> +{
> +	int quo;
> +
> +	return (remquol(x, y, &quo));
> +}
> diff --git a/newlib/libm/ld/e_sinhl.c b/newlib/libm/ld/e_sinhl.c
> new file mode 100644
> index 000000000..38d3df195
> --- /dev/null
> +++ b/newlib/libm/ld/e_sinhl.c
> @@ -0,0 +1,134 @@
> +/* from: FreeBSD: head/lib/msun/src/e_sinhl.c XXX */
> +
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_sinh.c for complete comments.
> + *
> + * Converted to long double by Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +#include "k_expl.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const long double shuge = 0x1p16383L;
> +#if LDBL_MANT_DIG == 64
> +/*
> + * Domain [-1, 1], range ~[-6.6749e-22, 6.6749e-22]:
> + * |sinh(x)/x - s(x)| < 2**-70.3
> + */
> +static const union IEEEl2bits
> +S3u = LD80C(0xaaaaaaaaaaaaaaaa, -3,  1.66666666666666666658e-1L);
> +#define	S3	S3u.e
> +static const double
> +S5  =  8.3333333333333332e-3,		/*  0x11111111111111.0p-59 */
> +S7  =  1.9841269841270074e-4,		/*  0x1a01a01a01a070.0p-65 */
> +S9  =  2.7557319223873889e-6,		/*  0x171de3a5565fe6.0p-71 */
> +S11 =  2.5052108406704084e-8,		/*  0x1ae6456857530f.0p-78 */
> +S13 =  1.6059042748655297e-10,		/*  0x161245fa910697.0p-85 */
> +S15 =  7.6470006914396920e-13,		/*  0x1ae7ce4eff2792.0p-93 */
> +S17 =  2.8346142308424267e-15;		/*  0x19882ce789ffc6.0p-101 */
> +#elif LDBL_MANT_DIG == 113
> +/*
> + * Domain [-1, 1], range ~[-2.9673e-36, 2.9673e-36]:
> + * |sinh(x)/x - s(x)| < 2**-118.0
> + */
> +static const long double
> +S3  =  1.66666666666666666666666666666666033e-1L,	/*  0x1555555555555555555555555553b.0p-115L */
> +S5  =  8.33333333333333333333333333337643193e-3L,	/*  0x111111111111111111111111180f5.0p-119L */
> +S7  =  1.98412698412698412698412697391263199e-4L,	/*  0x1a01a01a01a01a01a01a0176aad11.0p-125L */
> +S9  =  2.75573192239858906525574406205464218e-6L,	/*  0x171de3a556c7338faac243aaa9592.0p-131L */
> +S11 =  2.50521083854417187749675637460977997e-8L,	/*  0x1ae64567f544e38fe59b3380d7413.0p-138L */
> +S13 =  1.60590438368216146368737762431552702e-10L,	/*  0x16124613a86d098059c7620850fc2.0p-145L */
> +S15 =  7.64716373181980539786802470969096440e-13L,	/*  0x1ae7f3e733b814193af09ce723043.0p-153L */
> +S17 =  2.81145725434775409870584280722701574e-15L;	/*  0x1952c77030c36898c3fd0b6dfc562.0p-161L */
> +static const double
> +S19=  8.2206352435411005e-18,		/*  0x12f49b4662b86d.0p-109 */
> +S21=  1.9572943931418891e-20,		/*  0x171b8f2fab9628.0p-118 */
> +S23 =  3.8679983530666939e-23,		/*  0x17617002b73afc.0p-127 */
> +S25 =  6.5067867911512749e-26;		/*  0x1423352626048a.0p-136 */
> +#else
> +#error "Unsupported long double format"
> +#endif /* LDBL_MANT_DIG == 64 */
> +
> +/* log(2**16385 - 0.5) rounded up: */
> +static const float
> +o_threshold =  1.13572168e4;		/*  0xb174de.0p-10 */
> +
> +long double
> +sinhl(long double x)
> +{
> +	long double hi,lo,x2,x4;
> +#if LDBL_MANT_DIG == 113
> +	double dx2;
> +#endif
> +	double s;
> +	int16_t ix,jx;
> +
> +	GET_LDBL_EXPSIGN(jx,x);
> +	ix = jx&0x7fff;
> +
> +    /* x is INF or NaN */
> +	if(ix>=0x7fff) return x+x;
> +
> +	ENTERI();
> +
> +	s = 1;
> +	if (jx<0) s = -1;
> +
> +    /* |x| < 64, return x, s(x), or accurate s*(exp(|x|)/2-1/exp(|x|)/2) */
> +	if (ix<0x4005) {		/* |x|<64 */
> +	    if (ix<BIAS-(LDBL_MANT_DIG+1)/2) 	/* |x|<TINY */
> +		if(shuge+x>1) RETURNI(x);  /* sinh(tiny) = tiny with inexact */
> +	    if (ix<0x3fff) {		/* |x|<1 */
> +		x2 = x*x;
> +#if LDBL_MANT_DIG == 64
> +		x4 = x2*x2;
> +		RETURNI(((S17*x2 + S15)*x4 + (S13*x2 + S11))*(x2*x*x4*x4) +
> +		    ((S9*x2 + S7)*x2 + S5)*(x2*x*x2) + S3*(x2*x) + x);
> +#elif LDBL_MANT_DIG == 113
> +		dx2 = x2;
> +		RETURNI(((((((((((S25*dx2 + S23)*dx2 +
> +		    S21)*x2 + S19)*x2 +
> +		    S17)*x2 + S15)*x2 + S13)*x2 + S11)*x2 + S9)*x2 + S7)*x2 +
> +		    S5)* (x2*x*x2) +
> +		    S3*(x2*x) + x);
> +#endif
> +	    }
> +	    k_hexpl(fabsl(x), &hi, &lo);
> +	    RETURNI(s*(lo - 0.25/(hi + lo) + hi));
> +	}
> +
> +    /* |x| in [64, o_threshold], return correctly-overflowing s*exp(|x|)/2 */
> +	if (fabsl(x) <= o_threshold)
> +	    RETURNI(s*hexpl(fabsl(x)));
> +
> +    /* |x| > o_threshold, sinh(x) overflow */
> +	return x*shuge;
> +}
> diff --git a/newlib/libm/ld/fpmath.h b/newlib/libm/ld/fpmath.h
> new file mode 100644
> index 000000000..ce935eb40
> --- /dev/null
> +++ b/newlib/libm/ld/fpmath.h
> @@ -0,0 +1,82 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
> + * Copyright (c) 2002 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#ifndef _FPMATH_H_
> +#define _FPMATH_H_
> +
> +#include <sys/endian.h>
> +#include "_fpmath.h"
> +
> +#ifndef _IEEE_WORD_ORDER
> +#define	_IEEE_WORD_ORDER	_BYTE_ORDER
> +#endif
> +
> +union IEEEf2bits {
> +	float	f;
> +	struct {
> +#if _BYTE_ORDER == _LITTLE_ENDIAN
> +		unsigned int	man	:23;
> +		unsigned int	exp	:8;
> +		unsigned int	sign	:1;
> +#else /* _BIG_ENDIAN */
> +		unsigned int	sign	:1;
> +		unsigned int	exp	:8;
> +		unsigned int	man	:23;
> +#endif
> +	} bits;
> +};
> +
> +#define	DBL_MANH_SIZE	20
> +#define	DBL_MANL_SIZE	32
> +
> +union IEEEd2bits {
> +	double	d;
> +	struct {
> +#if _BYTE_ORDER == _LITTLE_ENDIAN
> +#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
> +		unsigned int	manl	:32;
> +#endif
> +		unsigned int	manh	:20;
> +		unsigned int	exp	:11;
> +		unsigned int	sign	:1;
> +#if _IEEE_WORD_ORDER == _BIG_ENDIAN
> +		unsigned int	manl	:32;
> +#endif
> +#else /* _BIG_ENDIAN */
> +		unsigned int	sign	:1;
> +		unsigned int	exp	:11;
> +		unsigned int	manh	:20;
> +		unsigned int	manl	:32;
> +#endif
> +	} bits;
> +};
> +
> +#endif /* !_FPMATH_H */
> diff --git a/newlib/libm/ld/math_private.h b/newlib/libm/ld/math_private.h
> new file mode 100644
> index 000000000..df526e71e
> --- /dev/null
> +++ b/newlib/libm/ld/math_private.h
> @@ -0,0 +1,924 @@
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +/*
> + * from: @(#)fdlibm.h 5.1 93/09/24
> + * $FreeBSD$
> + */
> +
> +#ifndef _MATH_PRIVATE_H_
> +#define	_MATH_PRIVATE_H_
> +
> +#include <sys/types.h>
> +#include <machine/endian.h>
> +
> +/*
> + * The original fdlibm code used statements like:
> + *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
> + *	ix0 = *(n0+(int*)&x);			* high word of x *
> + *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
> + * to dig two 32 bit words out of the 64 bit IEEE floating point
> + * value.  That is non-ANSI, and, moreover, the gcc instruction
> + * scheduler gets it wrong.  We instead use the following macros.
> + * Unlike the original code, we determine the endianness at compile
> + * time, not at run time; I don't see much benefit to selecting
> + * endianness at run time.
> + */
> +
> +/*
> + * A union which permits us to convert between a double and two 32 bit
> + * ints.
> + */
> +
> +#ifdef __arm__
> +#if defined(__VFP_FP__) || defined(__ARM_EABI__)
> +#define	IEEE_WORD_ORDER	BYTE_ORDER
> +#else
> +#define	IEEE_WORD_ORDER	BIG_ENDIAN
> +#endif
> +#else /* __arm__ */
> +#define	IEEE_WORD_ORDER	BYTE_ORDER
> +#endif
> +
> +/* A union which permits us to convert between a long double and
> +   four 32 bit ints.  */
> +
> +#if IEEE_WORD_ORDER == BIG_ENDIAN
> +
> +typedef union
> +{
> +  long double value;
> +  struct {
> +    u_int32_t mswhi;
> +    u_int32_t mswlo;
> +    u_int32_t lswhi;
> +    u_int32_t lswlo;
> +  } parts32;
> +  struct {
> +    u_int64_t msw;
> +    u_int64_t lsw;
> +  } parts64;
> +} ieee_quad_shape_type;
> +
> +#endif
> +
> +#if IEEE_WORD_ORDER == LITTLE_ENDIAN
> +
> +typedef union
> +{
> +  long double value;
> +  struct {
> +    u_int32_t lswlo;
> +    u_int32_t lswhi;
> +    u_int32_t mswlo;
> +    u_int32_t mswhi;
> +  } parts32;
> +  struct {
> +    u_int64_t lsw;
> +    u_int64_t msw;
> +  } parts64;
> +} ieee_quad_shape_type;
> +
> +#endif
> +
> +#if IEEE_WORD_ORDER == BIG_ENDIAN
> +
> +typedef union
> +{
> +  double value;
> +  struct
> +  {
> +    u_int32_t msw;
> +    u_int32_t lsw;
> +  } parts;
> +  struct
> +  {
> +    u_int64_t w;
> +  } xparts;
> +} ieee_double_shape_type;
> +
> +#endif
> +
> +#if IEEE_WORD_ORDER == LITTLE_ENDIAN
> +
> +typedef union
> +{
> +  double value;
> +  struct
> +  {
> +    u_int32_t lsw;
> +    u_int32_t msw;
> +  } parts;
> +  struct
> +  {
> +    u_int64_t w;
> +  } xparts;
> +} ieee_double_shape_type;
> +
> +#endif
> +
> +/* Get two 32 bit ints from a double.  */
> +
> +#define EXTRACT_WORDS(ix0,ix1,d)				\
> +do {								\
> +  ieee_double_shape_type ew_u;					\
> +  ew_u.value = (d);						\
> +  (ix0) = ew_u.parts.msw;					\
> +  (ix1) = ew_u.parts.lsw;					\
> +} while (0)
> +
> +/* Get a 64-bit int from a double. */
> +#define EXTRACT_WORD64(ix,d)					\
> +do {								\
> +  ieee_double_shape_type ew_u;					\
> +  ew_u.value = (d);						\
> +  (ix) = ew_u.xparts.w;						\
> +} while (0)
> +
> +/* Get the more significant 32 bit int from a double.  */
> +
> +#define GET_HIGH_WORD(i,d)					\
> +do {								\
> +  ieee_double_shape_type gh_u;					\
> +  gh_u.value = (d);						\
> +  (i) = gh_u.parts.msw;						\
> +} while (0)
> +
> +/* Get the less significant 32 bit int from a double.  */
> +
> +#define GET_LOW_WORD(i,d)					\
> +do {								\
> +  ieee_double_shape_type gl_u;					\
> +  gl_u.value = (d);						\
> +  (i) = gl_u.parts.lsw;						\
> +} while (0)
> +
> +/* Set a double from two 32 bit ints.  */
> +
> +#define INSERT_WORDS(d,ix0,ix1)					\
> +do {								\
> +  ieee_double_shape_type iw_u;					\
> +  iw_u.parts.msw = (ix0);					\
> +  iw_u.parts.lsw = (ix1);					\
> +  (d) = iw_u.value;						\
> +} while (0)
> +
> +/* Set a double from a 64-bit int. */
> +#define INSERT_WORD64(d,ix)					\
> +do {								\
> +  ieee_double_shape_type iw_u;					\
> +  iw_u.xparts.w = (ix);						\
> +  (d) = iw_u.value;						\
> +} while (0)
> +
> +/* Set the more significant 32 bits of a double from an int.  */
> +
> +#define SET_HIGH_WORD(d,v)					\
> +do {								\
> +  ieee_double_shape_type sh_u;					\
> +  sh_u.value = (d);						\
> +  sh_u.parts.msw = (v);						\
> +  (d) = sh_u.value;						\
> +} while (0)
> +
> +/* Set the less significant 32 bits of a double from an int.  */
> +
> +#define SET_LOW_WORD(d,v)					\
> +do {								\
> +  ieee_double_shape_type sl_u;					\
> +  sl_u.value = (d);						\
> +  sl_u.parts.lsw = (v);						\
> +  (d) = sl_u.value;						\
> +} while (0)
> +
> +/*
> + * A union which permits us to convert between a float and a 32 bit
> + * int.
> + */
> +
> +typedef union
> +{
> +  float value;
> +  /* FIXME: Assumes 32 bit int.  */
> +  unsigned int word;
> +} ieee_float_shape_type;
> +
> +/* Get a 32 bit int from a float.  */
> +
> +#define GET_FLOAT_WORD(i,d)					\
> +do {								\
> +  ieee_float_shape_type gf_u;					\
> +  gf_u.value = (d);						\
> +  (i) = gf_u.word;						\
> +} while (0)
> +
> +/* Set a float from a 32 bit int.  */
> +
> +#define SET_FLOAT_WORD(d,i)					\
> +do {								\
> +  ieee_float_shape_type sf_u;					\
> +  sf_u.word = (i);						\
> +  (d) = sf_u.value;						\
> +} while (0)
> +
> +/*
> + * Get expsign and mantissa as 16 bit and 64 bit ints from an 80 bit long
> + * double.
> + */
> +
> +#define	EXTRACT_LDBL80_WORDS(ix0,ix1,d)				\
> +do {								\
> +  union IEEEl2bits ew_u;					\
> +  ew_u.e = (d);							\
> +  (ix0) = ew_u.xbits.expsign;					\
> +  (ix1) = ew_u.xbits.man;					\
> +} while (0)
> +
> +/*
> + * Get expsign and mantissa as one 16 bit and two 64 bit ints from a 128 bit
> + * long double.
> + */
> +
> +#define	EXTRACT_LDBL128_WORDS(ix0,ix1,ix2,d)			\
> +do {								\
> +  union IEEEl2bits ew_u;					\
> +  ew_u.e = (d);							\
> +  (ix0) = ew_u.xbits.expsign;					\
> +  (ix1) = ew_u.xbits.manh;					\
> +  (ix2) = ew_u.xbits.manl;					\
> +} while (0)
> +
> +/* Get expsign as a 16 bit int from a long double.  */
> +
> +#define	GET_LDBL_EXPSIGN(i,d)					\
> +do {								\
> +  union IEEEl2bits ge_u;					\
> +  ge_u.e = (d);							\
> +  (i) = ge_u.xbits.expsign;					\
> +} while (0)
> +
> +/*
> + * Set an 80 bit long double from a 16 bit int expsign and a 64 bit int
> + * mantissa.
> + */
> +
> +#define	INSERT_LDBL80_WORDS(d,ix0,ix1)				\
> +do {								\
> +  union IEEEl2bits iw_u;					\
> +  iw_u.xbits.expsign = (ix0);					\
> +  iw_u.xbits.man = (ix1);					\
> +  (d) = iw_u.e;							\
> +} while (0)
> +
> +/*
> + * Set a 128 bit long double from a 16 bit int expsign and two 64 bit ints
> + * comprising the mantissa.
> + */
> +
> +#define	INSERT_LDBL128_WORDS(d,ix0,ix1,ix2)			\
> +do {								\
> +  union IEEEl2bits iw_u;					\
> +  iw_u.xbits.expsign = (ix0);					\
> +  iw_u.xbits.manh = (ix1);					\
> +  iw_u.xbits.manl = (ix2);					\
> +  (d) = iw_u.e;							\
> +} while (0)
> +
> +/* Set expsign of a long double from a 16 bit int.  */
> +
> +#define	SET_LDBL_EXPSIGN(d,v)					\
> +do {								\
> +  union IEEEl2bits se_u;					\
> +  se_u.e = (d);							\
> +  se_u.xbits.expsign = (v);					\
> +  (d) = se_u.e;							\
> +} while (0)
> +
> +#ifdef __i386__
> +/* Long double constants are broken on i386. */
> +#define	LD80C(m, ex, v) {						\
> +	.xbits.man = __CONCAT(m, ULL),					\
> +	.xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0),	\
> +}
> +#else
> +/* The above works on non-i386 too, but we use this to check v. */
> +#define	LD80C(m, ex, v)	{ .e = (v), }
> +#endif
> +
> +#ifdef FLT_EVAL_METHOD
> +/*
> + * Attempt to get strict C99 semantics for assignment with non-C99 compilers.
> + */
> +#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0
> +#define	STRICT_ASSIGN(type, lval, rval)	((lval) = (rval))
> +#else
> +#define	STRICT_ASSIGN(type, lval, rval) do {	\
> +	volatile type __lval;			\
> +						\
> +	if (sizeof(type) >= sizeof(long double))	\
> +		(lval) = (rval);		\
> +	else {					\
> +		__lval = (rval);		\
> +		(lval) = __lval;		\
> +	}					\
> +} while (0)
> +#endif
> +#endif /* FLT_EVAL_METHOD */
> +
> +/* Support switching the mode to FP_PE if necessary. */
> +#if defined(__i386__) && !defined(NO_FPSETPREC)
> +#define	ENTERI() ENTERIT(long double)
> +#define	ENTERIT(returntype)			\
> +	returntype __retval;			\
> +	fp_prec_t __oprec;			\
> +						\
> +	if ((__oprec = fpgetprec()) != FP_PE)	\
> +		fpsetprec(FP_PE)
> +#define	RETURNI(x) do {				\
> +	__retval = (x);				\
> +	if (__oprec != FP_PE)			\
> +		fpsetprec(__oprec);		\
> +	RETURNF(__retval);			\
> +} while (0)
> +#define	ENTERV()				\
> +	fp_prec_t __oprec;			\
> +						\
> +	if ((__oprec = fpgetprec()) != FP_PE)	\
> +		fpsetprec(FP_PE)
> +#define	RETURNV() do {				\
> +	if (__oprec != FP_PE)			\
> +		fpsetprec(__oprec);		\
> +	return;			\
> +} while (0)
> +#else
> +#define	ENTERI()
> +#define	ENTERIT(x)
> +#define	RETURNI(x)	RETURNF(x)
> +#define	ENTERV()
> +#define	RETURNV()	return
> +#endif
> +
> +/* Default return statement if hack*_t() is not used. */
> +#define      RETURNF(v)      return (v)
> +
> +/*
> + * 2sum gives the same result as 2sumF without requiring |a| >= |b| or
> + * a == 0, but is slower.
> + */
> +#define	_2sum(a, b) do {	\
> +	__typeof(a) __s, __w;	\
> +				\
> +	__w = (a) + (b);	\
> +	__s = __w - (a);	\
> +	(b) = ((a) - (__w - __s)) + ((b) - __s); \
> +	(a) = __w;		\
> +} while (0)
> +
> +/*
> + * 2sumF algorithm.
> + *
> + * "Normalize" the terms in the infinite-precision expression a + b for
> + * the sum of 2 floating point values so that b is as small as possible
> + * relative to 'a'.  (The resulting 'a' is the value of the expression in
> + * the same precision as 'a' and the resulting b is the rounding error.)
> + * |a| must be >= |b| or 0, b's type must be no larger than 'a's type, and
> + * exponent overflow or underflow must not occur.  This uses a Theorem of
> + * Dekker (1971).  See Knuth (1981) 4.2.2 Theorem C.  The name "TwoSum"
> + * is apparently due to Skewchuk (1997).
> + *
> + * For this to always work, assignment of a + b to 'a' must not retain any
> + * extra precision in a + b.  This is required by C standards but broken
> + * in many compilers.  The brokenness cannot be worked around using
> + * STRICT_ASSIGN() like we do elsewhere, since the efficiency of this
> + * algorithm would be destroyed by non-null strict assignments.  (The
> + * compilers are correct to be broken -- the efficiency of all floating
> + * point code calculations would be destroyed similarly if they forced the
> + * conversions.)
> + *
> + * Fortunately, a case that works well can usually be arranged by building
> + * any extra precision into the type of 'a' -- 'a' should have type float_t,
> + * double_t or long double.  b's type should be no larger than 'a's type.
> + * Callers should use these types with scopes as large as possible, to
> + * reduce their own extra-precision and efficiciency problems.  In
> + * particular, they shouldn't convert back and forth just to call here.
> + */
> +#ifdef DEBUG
> +#define	_2sumF(a, b) do {				\
> +	__typeof(a) __w;				\
> +	volatile __typeof(a) __ia, __ib, __r, __vw;	\
> +							\
> +	__ia = (a);					\
> +	__ib = (b);					\
> +	assert(__ia == 0 || fabsl(__ia) >= fabsl(__ib));	\
> +							\
> +	__w = (a) + (b);				\
> +	(b) = ((a) - __w) + (b);			\
> +	(a) = __w;					\
> +							\
> +	/* The next 2 assertions are weak if (a) is already long double. */ \
> +	assert((long double)__ia + __ib == (long double)(a) + (b));	\
> +	__vw = __ia + __ib;				\
> +	__r = __ia - __vw;				\
> +	__r += __ib;					\
> +	assert(__vw == (a) && __r == (b));		\
> +} while (0)
> +#else /* !DEBUG */
> +#define	_2sumF(a, b) do {	\
> +	__typeof(a) __w;	\
> +				\
> +	__w = (a) + (b);	\
> +	(b) = ((a) - __w) + (b); \
> +	(a) = __w;		\
> +} while (0)
> +#endif /* DEBUG */
> +
> +/*
> + * Set x += c, where x is represented in extra precision as a + b.
> + * x must be sufficiently normalized and sufficiently larger than c,
> + * and the result is then sufficiently normalized.
> + *
> + * The details of ordering are that |a| must be >= |c| (so that (a, c)
> + * can be normalized without extra work to swap 'a' with c).  The details of
> + * the normalization are that b must be small relative to the normalized 'a'.
> + * Normalization of (a, c) makes the normalized c tiny relative to the
> + * normalized a, so b remains small relative to 'a' in the result.  However,
> + * b need not ever be tiny relative to 'a'.  For example, b might be about
> + * 2**20 times smaller than 'a' to give about 20 extra bits of precision.
> + * That is usually enough, and adding c (which by normalization is about
> + * 2**53 times smaller than a) cannot change b significantly.  However,
> + * cancellation of 'a' with c in normalization of (a, c) may reduce 'a'
> + * significantly relative to b.  The caller must ensure that significant
> + * cancellation doesn't occur, either by having c of the same sign as 'a',
> + * or by having |c| a few percent smaller than |a|.  Pre-normalization of
> + * (a, b) may help.
> + *
> + * This is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
> + * exercise 19).  We gain considerable efficiency by requiring the terms to
> + * be sufficiently normalized and sufficiently increasing.
> + */
> +#define	_3sumF(a, b, c) do {	\
> +	__typeof(a) __tmp;	\
> +				\
> +	__tmp = (c);		\
> +	_2sumF(__tmp, (a));	\
> +	(b) += (a);		\
> +	(a) = __tmp;		\
> +} while (0)
> +
> +/*
> + * Common routine to process the arguments to nan(), nanf(), and nanl().
> + */
> +void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
> +
> +/*
> + * Mix 0, 1 or 2 NaNs.  First add 0 to each arg.  This normally just turns
> + * signaling NaNs into quiet NaNs by setting a quiet bit.  We do this
> + * because we want to never return a signaling NaN, and also because we
> + * don't want the quiet bit to affect the result.  Then mix the converted
> + * args using the specified operation.
> + *
> + * When one arg is NaN, the result is typically that arg quieted.  When both
> + * args are NaNs, the result is typically the quietening of the arg whose
> + * mantissa is largest after quietening.  When neither arg is NaN, the
> + * result may be NaN because it is indeterminate, or finite for subsequent
> + * construction of a NaN as the indeterminate 0.0L/0.0L.
> + *
> + * Technical complications: the result in bits after rounding to the final
> + * precision might depend on the runtime precision and/or on compiler
> + * optimizations, especially when different register sets are used for
> + * different precisions.  Try to make the result not depend on at least the
> + * runtime precision by always doing the main mixing step in long double
> + * precision.  Try to reduce dependencies on optimizations by adding the
> + * the 0's in different precisions (unless everything is in long double
> + * precision).
> + */
> +#define	nan_mix(x, y)		(nan_mix_op((x), (y), +))
> +#define	nan_mix_op(x, y, op)	(((x) + 0.0L) op ((y) + 0))
> +
> +#ifdef _COMPLEX_H
> +
> +/*
> + * C99 specifies that complex numbers have the same representation as
> + * an array of two elements, where the first element is the real part
> + * and the second element is the imaginary part.
> + */
> +typedef union {
> +	float complex f;
> +	float a[2];
> +} float_complex;
> +typedef union {
> +	double complex f;
> +	double a[2];
> +} double_complex;
> +typedef union {
> +	long double complex f;
> +	long double a[2];
> +} long_double_complex;
> +#define	REALPART(z)	((z).a[0])
> +#define	IMAGPART(z)	((z).a[1])
> +
> +/*
> + * Inline functions that can be used to construct complex values.
> + *
> + * The C99 standard intends x+I*y to be used for this, but x+I*y is
> + * currently unusable in general since gcc introduces many overflow,
> + * underflow, sign and efficiency bugs by rewriting I*y as
> + * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product.
> + * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted
> + * to -0.0+I*0.0.
> + *
> + * The C11 standard introduced the macros CMPLX(), CMPLXF() and CMPLXL()
> + * to construct complex values.  Compilers that conform to the C99
> + * standard require the following functions to avoid the above issues.
> + */
> +
> +#ifndef CMPLXF
> +static __inline float complex
> +CMPLXF(float x, float y)
> +{
> +	float_complex z;
> +
> +	REALPART(z) = x;
> +	IMAGPART(z) = y;
> +	return (z.f);
> +}
> +#endif
> +
> +#ifndef CMPLX
> +static __inline double complex
> +CMPLX(double x, double y)
> +{
> +	double_complex z;
> +
> +	REALPART(z) = x;
> +	IMAGPART(z) = y;
> +	return (z.f);
> +}
> +#endif
> +
> +#ifndef CMPLXL
> +static __inline long double complex
> +CMPLXL(long double x, long double y)
> +{
> +	long_double_complex z;
> +
> +	REALPART(z) = x;
> +	IMAGPART(z) = y;
> +	return (z.f);
> +}
> +#endif
> +
> +#endif /* _COMPLEX_H */
> + 
> +/*
> + * The rnint() family rounds to the nearest integer for a restricted range
> + * range of args (up to about 2**MANT_DIG).  We assume that the current
> + * rounding mode is FE_TONEAREST so that this can be done efficiently.
> + * Extra precision causes more problems in practice, and we only centralize
> + * this here to reduce those problems, and have not solved the efficiency
> + * problems.  The exp2() family uses a more delicate version of this that
> + * requires extracting bits from the intermediate value, so it is not
> + * centralized here and should copy any solution of the efficiency problems.
> + */
> +
> +static inline double
> +rnint(__double_t x)
> +{
> +	/*
> +	 * This casts to double to kill any extra precision.  This depends
> +	 * on the cast being applied to a double_t to avoid compiler bugs
> +	 * (this is a cleaner version of STRICT_ASSIGN()).  This is
> +	 * inefficient if there actually is extra precision, but is hard
> +	 * to improve on.  We use double_t in the API to minimise conversions
> +	 * for just calling here.  Note that we cannot easily change the
> +	 * magic number to the one that works directly with double_t, since
> +	 * the rounding precision is variable at runtime on x86 so the
> +	 * magic number would need to be variable.  Assuming that the
> +	 * rounding precision is always the default is too fragile.  This
> +	 * and many other complications will move when the default is
> +	 * changed to FP_PE.
> +	 */
> +	return ((double)(x + 0x1.8p52) - 0x1.8p52);
> +}
> +
> +static inline float
> +rnintf(__float_t x)
> +{
> +	/*
> +	 * As for rnint(), except we could just call that to handle the
> +	 * extra precision case, usually without losing efficiency.
> +	 */
> +	return ((float)(x + 0x1.8p23F) - 0x1.8p23F);
> +}
> +
> +#ifdef LDBL_MANT_DIG
> +/*
> + * The complications for extra precision are smaller for rnintl() since it
> + * can safely assume that the rounding precision has been increased from
> + * its default to FP_PE on x86.  We don't exploit that here to get small
> + * optimizations from limiting the rangle to double.  We just need it for
> + * the magic number to work with long doubles.  ld128 callers should use
> + * rnint() instead of this if possible.  ld80 callers should prefer
> + * rnintl() since for amd64 this avoids swapping the register set, while
> + * for i386 it makes no difference (assuming FP_PE), and for other arches
> + * it makes little difference.
> + */
> +static inline long double
> +rnintl(long double x)
> +{
> +	return (x + __CONCAT(0x1.8p, LDBL_MANT_DIG) / 2 -
> +	    __CONCAT(0x1.8p, LDBL_MANT_DIG) / 2);
> +}
> +#endif /* LDBL_MANT_DIG */
> +
> +/*
> + * irint() and i64rint() give the same result as casting to their integer
> + * return type provided their arg is a floating point integer.  They can
> + * sometimes be more efficient because no rounding is required.
> + */
> +#if defined(amd64) || defined(__i386__)
> +#define	irint(x)						\
> +    (sizeof(x) == sizeof(float) &&				\
> +    sizeof(__float_t) == sizeof(long double) ? irintf(x) :	\
> +    sizeof(x) == sizeof(double) &&				\
> +    sizeof(__double_t) == sizeof(long double) ? irintd(x) :	\
> +    sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
> +#else
> +#define	irint(x)	((int)(x))
> +#endif
> +
> +#define	i64rint(x)	((int64_t)(x))	/* only needed for ld128 so not opt. */
> +
> +#if defined(__i386__)
> +static __inline int
> +irintf(float x)
> +{
> +	int n;
> +
> +	__asm("fistl %0" : "=m" (n) : "t" (x));
> +	return (n);
> +}
> +
> +static __inline int
> +irintd(double x)
> +{
> +	int n;
> +
> +	__asm("fistl %0" : "=m" (n) : "t" (x));
> +	return (n);
> +}
> +#endif
> +
> +#if defined(__amd64__) || defined(__i386__)
> +static __inline int
> +irintl(long double x)
> +{
> +	int n;
> +
> +	__asm("fistl %0" : "=m" (n) : "t" (x));
> +	return (n);
> +}
> +#endif
> +
> +#ifdef DEBUG
> +#if defined(__amd64__) || defined(__i386__)
> +#define	breakpoint()	asm("int $3")
> +#else
> +#include <signal.h>
> +
> +#define	breakpoint()	raise(SIGTRAP)
> +#endif
> +#endif
> +
> +/* Write a pari script to test things externally. */
> +#ifdef DOPRINT
> +#include <stdio.h>
> +
> +#ifndef DOPRINT_SWIZZLE
> +#define	DOPRINT_SWIZZLE		0
> +#endif
> +
> +#ifdef DOPRINT_LD80
> +
> +#define	DOPRINT_START(xp) do {						\
> +	uint64_t __lx;							\
> +	uint16_t __hx;							\
> +									\
> +	/* Hack to give more-problematic args. */			\
> +	EXTRACT_LDBL80_WORDS(__hx, __lx, *xp);				\
> +	__lx ^= DOPRINT_SWIZZLE;					\
> +	INSERT_LDBL80_WORDS(*xp, __hx, __lx);				\
> +	printf("x = %.21Lg; ", (long double)*xp);			\
> +} while (0)
> +#define	DOPRINT_END1(v)							\
> +	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
> +#define	DOPRINT_END2(hi, lo)						\
> +	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
> +	    (long double)(hi), (long double)(lo))
> +
> +#elif defined(DOPRINT_D64)
> +
> +#define	DOPRINT_START(xp) do {						\
> +	uint32_t __hx, __lx;						\
> +									\
> +	EXTRACT_WORDS(__hx, __lx, *xp);					\
> +	__lx ^= DOPRINT_SWIZZLE;					\
> +	INSERT_WORDS(*xp, __hx, __lx);					\
> +	printf("x = %.21Lg; ", (long double)*xp);			\
> +} while (0)
> +#define	DOPRINT_END1(v)							\
> +	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
> +#define	DOPRINT_END2(hi, lo)						\
> +	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
> +	    (long double)(hi), (long double)(lo))
> +
> +#elif defined(DOPRINT_F32)
> +
> +#define	DOPRINT_START(xp) do {						\
> +	uint32_t __hx;							\
> +									\
> +	GET_FLOAT_WORD(__hx, *xp);					\
> +	__hx ^= DOPRINT_SWIZZLE;					\
> +	SET_FLOAT_WORD(*xp, __hx);					\
> +	printf("x = %.21Lg; ", (long double)*xp);			\
> +} while (0)
> +#define	DOPRINT_END1(v)							\
> +	printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v))
> +#define	DOPRINT_END2(hi, lo)						\
> +	printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n",		\
> +	    (long double)(hi), (long double)(lo))
> +
> +#else /* !DOPRINT_LD80 && !DOPRINT_D64 (LD128 only) */
> +
> +#ifndef DOPRINT_SWIZZLE_HIGH
> +#define	DOPRINT_SWIZZLE_HIGH	0
> +#endif
> +
> +#define	DOPRINT_START(xp) do {						\
> +	uint64_t __lx, __llx;						\
> +	uint16_t __hx;							\
> +									\
> +	EXTRACT_LDBL128_WORDS(__hx, __lx, __llx, *xp);			\
> +	__llx ^= DOPRINT_SWIZZLE;					\
> +	__lx ^= DOPRINT_SWIZZLE_HIGH;					\
> +	INSERT_LDBL128_WORDS(*xp, __hx, __lx, __llx);			\
> +	printf("x = %.36Lg; ", (long double)*xp);					\
> +} while (0)
> +#define	DOPRINT_END1(v)							\
> +	printf("y = %.36Lg; z = 0; show(x, y, z);\n", (long double)(v))
> +#define	DOPRINT_END2(hi, lo)						\
> +	printf("y = %.36Lg; z = %.36Lg; show(x, y, z);\n",		\
> +	    (long double)(hi), (long double)(lo))
> +
> +#endif /* DOPRINT_LD80 */
> +
> +#else /* !DOPRINT */
> +#define	DOPRINT_START(xp)
> +#define	DOPRINT_END1(v)
> +#define	DOPRINT_END2(hi, lo)
> +#endif /* DOPRINT */
> +
> +#define	RETURNP(x) do {			\
> +	DOPRINT_END1(x);		\
> +	RETURNF(x);			\
> +} while (0)
> +#define	RETURNPI(x) do {		\
> +	DOPRINT_END1(x);		\
> +	RETURNI(x);			\
> +} while (0)
> +#define	RETURN2P(x, y) do {		\
> +	DOPRINT_END2((x), (y));		\
> +	RETURNF((x) + (y));		\
> +} while (0)
> +#define	RETURN2PI(x, y) do {		\
> +	DOPRINT_END2((x), (y));		\
> +	RETURNI((x) + (y));		\
> +} while (0)
> +#ifdef STRUCT_RETURN
> +#define	RETURNSP(rp) do {		\
> +	if (!(rp)->lo_set)		\
> +		RETURNP((rp)->hi);	\
> +	RETURN2P((rp)->hi, (rp)->lo);	\
> +} while (0)
> +#define	RETURNSPI(rp) do {		\
> +	if (!(rp)->lo_set)		\
> +		RETURNPI((rp)->hi);	\
> +	RETURN2PI((rp)->hi, (rp)->lo);	\
> +} while (0)
> +#endif
> +#define	SUM2P(x, y) ({			\
> +	const __typeof (x) __x = (x);	\
> +	const __typeof (y) __y = (y);	\
> +					\
> +	DOPRINT_END2(__x, __y);		\
> +	__x + __y;			\
> +})
> +
> +/*
> + * ieee style elementary functions
> + *
> + * We rename functions here to improve other sources' diffability
> + * against fdlibm.
> + */
> +#define	__ieee754_sqrt	sqrt
> +#define	__ieee754_acos	acos
> +#define	__ieee754_acosh	acosh
> +#define	__ieee754_log	log
> +#define	__ieee754_log2	log2
> +#define	__ieee754_atanh	atanh
> +#define	__ieee754_asin	asin
> +#define	__ieee754_atan2	atan2
> +#define	__ieee754_exp	exp
> +#define	__ieee754_cosh	cosh
> +#define	__ieee754_fmod	fmod
> +#define	__ieee754_pow	pow
> +#define	__ieee754_lgamma lgamma
> +#define	__ieee754_gamma	gamma
> +#define	__ieee754_lgamma_r lgamma_r
> +#define	__ieee754_gamma_r gamma_r
> +#define	__ieee754_log10	log10
> +#define	__ieee754_sinh	sinh
> +#define	__ieee754_hypot	hypot
> +#define	__ieee754_j0	j0
> +#define	__ieee754_j1	j1
> +#define	__ieee754_y0	y0
> +#define	__ieee754_y1	y1
> +#define	__ieee754_jn	jn
> +#define	__ieee754_yn	yn
> +#define	__ieee754_remainder remainder
> +#define	__ieee754_scalb	scalb
> +#define	__ieee754_sqrtf	sqrtf
> +#define	__ieee754_acosf	acosf
> +#define	__ieee754_acoshf acoshf
> +#define	__ieee754_logf	logf
> +#define	__ieee754_atanhf atanhf
> +#define	__ieee754_asinf	asinf
> +#define	__ieee754_atan2f atan2f
> +#define	__ieee754_expf	expf
> +#define	__ieee754_coshf	coshf
> +#define	__ieee754_fmodf	fmodf
> +#define	__ieee754_powf	powf
> +#define	__ieee754_lgammaf lgammaf
> +#define	__ieee754_gammaf gammaf
> +#define	__ieee754_lgammaf_r lgammaf_r
> +#define	__ieee754_gammaf_r gammaf_r
> +#define	__ieee754_log10f log10f
> +#define	__ieee754_log2f log2f
> +#define	__ieee754_sinhf	sinhf
> +#define	__ieee754_hypotf hypotf
> +#define	__ieee754_j0f	j0f
> +#define	__ieee754_j1f	j1f
> +#define	__ieee754_y0f	y0f
> +#define	__ieee754_y1f	y1f
> +#define	__ieee754_jnf	jnf
> +#define	__ieee754_ynf	ynf
> +#define	__ieee754_remainderf remainderf
> +#define	__ieee754_scalbf scalbf
> +
> +/* fdlibm kernel function */
> +int	__kernel_rem_pio2(double*,double*,int,int,int);
> +
> +/* double precision kernel functions */
> +#ifndef INLINE_REM_PIO2
> +int	__ieee754_rem_pio2(double,double*);
> +#endif
> +double	__kernel_sin(double,double,int);
> +double	__kernel_cos(double,double);
> +double	__kernel_tan(double,double,int);
> +double	__ldexp_exp(double,int);
> +#ifdef _COMPLEX_H
> +double complex __ldexp_cexp(double complex,int);
> +#endif
> +
> +/* float precision kernel functions */
> +#ifndef INLINE_REM_PIO2F
> +int	__ieee754_rem_pio2f(float,double*);
> +#endif
> +#ifndef INLINE_KERNEL_SINDF
> +float	__kernel_sindf(double);
> +#endif
> +#ifndef INLINE_KERNEL_COSDF
> +float	__kernel_cosdf(double);
> +#endif
> +#ifndef INLINE_KERNEL_TANDF
> +float	__kernel_tandf(double,int);
> +#endif
> +float	__ldexp_expf(float,int);
> +#ifdef _COMPLEX_H
> +float complex __ldexp_cexpf(float complex,int);
> +#endif
> +
> +/* long double precision kernel functions */
> +long double __kernel_sinl(long double, long double, int);
> +long double __kernel_cosl(long double, long double);
> +long double __kernel_tanl(long double, long double, int);
> +
> +#endif /* !_MATH_PRIVATE_H_ */
> diff --git a/newlib/libm/ld/s_asinhl.c b/newlib/libm/ld/s_asinhl.c
> new file mode 100644
> index 000000000..ba28f599c
> --- /dev/null
> +++ b/newlib/libm/ld/s_asinhl.c
> @@ -0,0 +1,91 @@
> +/* from: FreeBSD: head/lib/msun/src/e_acosh.c 176451 2008-02-22 02:30:36Z das */
> +
> +/* @(#)s_asinh.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See s_asinh.c for complete comments.
> + *
> + * Converted to long double by David Schultz <das@FreeBSD.ORG> and
> + * Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* EXP_LARGE is the threshold above which we use asinh(x) ~= log(2x). */
> +/* EXP_TINY is the threshold below which we use asinh(x) ~= x. */
> +#if LDBL_MANT_DIG == 64
> +#define	EXP_LARGE	34
> +#define	EXP_TINY	-34
> +#elif LDBL_MANT_DIG == 113
> +#define	EXP_LARGE	58
> +#define	EXP_TINY	-58
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const double
> +one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
> +huge=  1.00000000000000000000e+300;
> +
> +#if LDBL_MANT_DIG == 64
> +static const union IEEEl2bits
> +u_ln2 =  LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309417e-1L);
> +#define	ln2	u_ln2.e
> +#elif LDBL_MANT_DIG == 113
> +static const long double
> +ln2 =  6.93147180559945309417232121458176568e-1L;	/* 0x162e42fefa39ef35793c7673007e6.0p-113 */
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +asinhl(long double x)
> +{
> +	long double t, w;
> +	uint16_t hx, ix;
> +
> +	ENTERI();
> +	GET_LDBL_EXPSIGN(hx, x);
> +	ix = hx & 0x7fff;
> +	if (ix >= 0x7fff) RETURNI(x+x);	/* x is inf, NaN or misnormal */
> +	if (ix < BIAS + EXP_TINY) {	/* |x| < TINY, or misnormal */
> +	    if (huge + x > one) RETURNI(x);	/* return x inexact except 0 */
> +	}
> +	if (ix >= BIAS + EXP_LARGE) {	/* |x| >= LARGE, or misnormal */
> +	    w = logl(fabsl(x))+ln2;
> +	} else if (ix >= 0x4000) {	/* LARGE > |x| >= 2.0, or misnormal */
> +	    t = fabsl(x);
> +	    w = logl(2.0*t+one/(sqrtl(x*x+one)+t));
> +	} else {		/* 2.0 > |x| >= TINY, or misnormal */
> +	    t = x*x;
> +	    w =log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
> +	}
> +	RETURNI((hx & 0x8000) == 0 ? w : -w);
> +}
> diff --git a/newlib/libm/ld/s_atanl.c b/newlib/libm/ld/s_atanl.c
> new file mode 100644
> index 000000000..ff29c3ce8
> --- /dev/null
> +++ b/newlib/libm/ld/s_atanl.c
> @@ -0,0 +1,85 @@
> +/* @(#)s_atan.c 5.1 93/09/24 */
> +/* FreeBSD: head/lib/msun/src/s_atan.c 176451 2008-02-22 02:30:36Z das */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See comments in s_atan.c.
> + * Converted to long double by David Schultz <das@FreeBSD.ORG>.
> + */
> +
> +#include <float.h>
> +
> +#include "invtrig.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const long double
> +one   = 1.0,
> +huge   = 1.0e300;
> +
> +long double
> +atanl(long double x)
> +{
> +	union IEEEl2bits u;
> +	long double w,s1,s2,z;
> +	int id;
> +	int16_t expsign, expt;
> +	int32_t expman;
> +
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	expt = expsign & 0x7fff;
> +	if(expt >= ATAN_CONST) {	/* if |x| is large, atan(x)~=pi/2 */
> +	    if(expt == BIAS + LDBL_MAX_EXP &&
> +	       ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0)
> +		return x+x;		/* NaN */
> +	    if(expsign>0) return  atanhi[3]+atanlo[3];
> +	    else     return -atanhi[3]-atanlo[3];
> +	}
> +	/* Extract the exponent and the first few bits of the mantissa. */
> +	/* XXX There should be a more convenient way to do this. */
> +	expman = (expt << 8) | ((u.bits.manh >> (MANH_SIZE - 9)) & 0xff);
> +	if (expman < ((BIAS - 2) << 8) + 0xc0) {	/* |x| < 0.4375 */
> +	    if (expt < ATAN_LINEAR) {	/* if |x| is small, atanl(x)~=x */
> +		if(huge+x>one) return x;	/* raise inexact */
> +	    }
> +	    id = -1;
> +	} else {
> +	x = fabsl(x);
> +	if (expman < (BIAS << 8) + 0x30) {		/* |x| < 1.1875 */
> +	    if (expman < ((BIAS - 1) << 8) + 0x60) {	/* 7/16 <=|x|<11/16 */
> +		id = 0; x = (2.0*x-one)/(2.0+x);
> +	    } else {			/* 11/16<=|x|< 19/16 */
> +		id = 1; x  = (x-one)/(x+one);
> +	    }
> +	} else {
> +	    if (expman < ((BIAS + 1) << 8) + 0x38) {	/* |x| < 2.4375 */
> +		id = 2; x  = (x-1.5)/(one+1.5*x);
> +	    } else {			/* 2.4375 <= |x| < 2^ATAN_CONST */
> +		id = 3; x  = -1.0/x;
> +	    }
> +	}}
> +    /* end of argument reduction */
> +	z = x*x;
> +	w = z*z;
> +    /* break sum aT[i]z**(i+1) into odd and even poly */
> +	s1 = z*T_even(w);
> +	s2 = w*T_odd(w);
> +	if (id<0) return x - x*(s1+s2);
> +	else {
> +	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
> +	    return (expsign<0)? -z:z;
> +	}
> +}
> diff --git a/newlib/libm/ld/s_cbrtl.c b/newlib/libm/ld/s_cbrtl.c
> new file mode 100644
> index 000000000..b15c96ecd
> --- /dev/null
> +++ b/newlib/libm/ld/s_cbrtl.c
> @@ -0,0 +1,143 @@
> +/*-
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + *
> + * The argument reduction and testing for exceptional cases was
> + * written by Steven G. Kargl with input from Bruce D. Evans
> + * and David A. Schultz.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"    
> +#include "math.h"
> +#include "math_private.h"
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const unsigned
> +    B1 = 709958130;	/* B1 = (127-127.0/3-0.03306235651)*2**23 */
> +
> +long double
> +cbrtl(long double x)
> +{
> +	union IEEEl2bits u, v;
> +	long double r, s, t, w;
> +	double dr, dt, dx;
> +	float ft, fx;
> +	uint32_t hx;
> +	uint16_t expsign;
> +	int k;
> +
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	k = expsign & 0x7fff;
> +
> +	/*
> +	 * If x = +-Inf, then cbrt(x) = +-Inf.
> +	 * If x = NaN, then cbrt(x) = NaN.
> +	 */
> +	if (k == BIAS + LDBL_MAX_EXP)
> +		return (x + x);
> +
> +	ENTERI();
> +	if (k == 0) {
> +		/* If x = +-0, then cbrt(x) = +-0. */
> +		if ((u.bits.manh | u.bits.manl) == 0)
> +			RETURNI(x);
> +		/* Adjust subnormal numbers. */
> +		u.e *= 0x1.0p514;
> +		k = u.bits.exp;
> +		k -= BIAS + 514;
> + 	} else
> +		k -= BIAS;
> +	u.xbits.expsign = BIAS;
> +	v.e = 1; 
> +
> +	x = u.e;
> +	switch (k % 3) {
> +	case 1:
> +	case -2:
> +		x = 2*x;
> +		k--;
> +		break;
> +	case 2:
> +	case -1:
> +		x = 4*x;
> +		k -= 2;
> +		break;
> +	}
> +	v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3);
> +
> +	/*
> +	 * The following is the guts of s_cbrtf, with the handling of
> +	 * special values removed and extra care for accuracy not taken,
> +	 * but with most of the extra accuracy not discarded.
> +	 */
> +
> +	/* ~5-bit estimate: */
> +	fx = x;
> +	GET_FLOAT_WORD(hx, fx);
> +	SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1));
> +
> +	/* ~16-bit estimate: */
> +	dx = x;
> +	dt = ft;
> +	dr = dt * dt * dt;
> +	dt = dt * (dx + dx + dr) / (dx + dr + dr);
> +
> +	/* ~47-bit estimate: */
> +	dr = dt * dt * dt;
> +	dt = dt * (dx + dx + dr) / (dx + dr + dr);
> +
> +#if LDBL_MANT_DIG == 64
> +	/*
> +	 * dt is cbrtl(x) to ~47 bits (after x has been reduced to 1 <= x < 8).
> +	 * Round it away from zero to 32 bits (32 so that t*t is exact, and
> +	 * away from zero for technical reasons).
> +	 */
> +	volatile double vd2 = 0x1.0p32;
> +	volatile double vd1 = 0x1.0p-31;
> +	#define vd ((long double)vd2 + vd1)
> +
> +	t = dt + vd - 0x1.0p32;
> +#elif LDBL_MANT_DIG == 113
> +	/*
> +	 * Round dt away from zero to 47 bits.  Since we don't trust the 47,
> +	 * add 2 47-bit ulps instead of 1 to round up.  Rounding is slow and
> +	 * might be avoidable in this case, since on most machines dt will
> +	 * have been evaluated in 53-bit precision and the technical reasons
> +	 * for rounding up might not apply to either case in cbrtl() since
> +	 * dt is much more accurate than needed.
> +	 */
> +	t = dt + 0x2.0p-46 + 0x1.0p60L - 0x1.0p60;
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +	/*
> +     	 * Final step Newton iteration to 64 or 113 bits with
> +	 * error < 0.667 ulps
> +	 */
> +	s=t*t;				/* t*t is exact */
> +	r=x/s;				/* error <= 0.5 ulps; |r| < |t| */
> +	w=t+t;				/* t+t is exact */
> +	r=(r-t)/(w+r);			/* r-t is exact; w+r ~= 3*t */
> +	t=t+t*r;			/* error <= (0.5 + 0.5/3) * ulp */
> +
> +	t *= v.e;
> +	RETURNI(t);
> +}
> diff --git a/newlib/libm/ld/s_ceill.c b/newlib/libm/ld/s_ceill.c
> new file mode 100644
> index 000000000..2d1045fe6
> --- /dev/null
> +++ b/newlib/libm/ld/s_ceill.c
> @@ -0,0 +1,101 @@
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + *
> + * From: @(#)s_ceil.c 5.1 93/09/24
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ceill(x)
> + * Return x rounded toward -inf to integral value
> + * Method:
> + *	Bit twiddling.
> + * Exception:
> + *	Inexact flag raised if x not equal to ceill(x).
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +
> +#ifdef LDBL_IMPLICIT_NBIT
> +#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
> +#define	INC_MANH(u, c)	do {					\
> +	uint64_t o = u.bits.manh;				\
> +	u.bits.manh += (c);					\
> +	if (u.bits.manh < o)					\
> +		u.bits.exp++;					\
> +} while (0)
> +#else
> +#define	MANH_SIZE	LDBL_MANH_SIZE
> +#define	INC_MANH(u, c)	do {					\
> +	uint64_t o = u.bits.manh;				\
> +	u.bits.manh += (c);					\
> +	if (u.bits.manh < o) {					\
> +		u.bits.exp++;					\
> +		u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);	\
> +	}							\
> +} while (0)
> +#endif
> +
> +static const long double huge = 1.0e300;
> +
> +long double
> +ceill(long double x)
> +{
> +	union IEEEl2bits u = { .e = x };
> +	int e = u.bits.exp - LDBL_MAX_EXP + 1;
> +
> +	if (e < MANH_SIZE - 1) {
> +		if (e < 0) {			/* raise inexact if x != 0 */
> +			if (huge + x > 0.0)
> +				if (u.bits.exp > 0 ||
> +				    (u.bits.manh | u.bits.manl) != 0)
> +					u.e = u.bits.sign ? -0.0 : 1.0;
> +		} else {
> +			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
> +			if (((u.bits.manh & m) | u.bits.manl) == 0)
> +				return (x);	/* x is integral */
> +			if (!u.bits.sign) {
> +#ifdef LDBL_IMPLICIT_NBIT
> +				if (e == 0)
> +					u.bits.exp++;
> +				else
> +#endif
> +				INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
> +			}
> +			if (huge + x > 0.0) {	/* raise inexact flag */
> +				u.bits.manh &= ~m;
> +				u.bits.manl = 0;
> +			}
> +		}
> +	} else if (e < LDBL_MANT_DIG - 1) {
> +		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
> +		if ((u.bits.manl & m) == 0)
> +			return (x);	/* x is integral */
> +		if (!u.bits.sign) {
> +			if (e == MANH_SIZE - 1)
> +				INC_MANH(u, 1);
> +			else {
> +				uint64_t o = u.bits.manl;
> +				u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
> +				if (u.bits.manl < o)	/* got a carry */
> +					INC_MANH(u, 1);
> +			}
> +		}
> +		if (huge + x > 0.0)		/* raise inexact flag */
> +			u.bits.manl &= ~m;
> +	}
> +	return (u.e);
> +}
> diff --git a/newlib/libm/ld/s_copysignl.c b/newlib/libm/ld/s_copysignl.c
> new file mode 100644
> index 000000000..bd6744705
> --- /dev/null
> +++ b/newlib/libm/ld/s_copysignl.c
> @@ -0,0 +1,44 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 Stefan Farfeleder
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +long double
> +copysignl(long double x, long double y)
> +{
> +	union IEEEl2bits ux, uy;
> +
> +	ux.e = x;
> +	uy.e = y;
> +	ux.bits.sign = uy.bits.sign;
> +	return (ux.e);
> +}
> diff --git a/newlib/libm/ld/s_cosl.c b/newlib/libm/ld/s_cosl.c
> new file mode 100644
> index 000000000..3d066483f
> --- /dev/null
> +++ b/newlib/libm/ld/s_cosl.c
> @@ -0,0 +1,102 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows
> + * an accuracy of <= 0.7412 ULP.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +#if LDBL_MANT_DIG == 64
> +#include "../ld80/e_rem_pio2l.h"
> +static const union IEEEl2bits
> +pio4u = LD80C(0xc90fdaa22168c235, -00001,  7.85398163397448309628e-01L);
> +#define	pio4	(pio4u.e)
> +#elif LDBL_MANT_DIG == 113
> +#include "../ld128/e_rem_pio2l.h"
> +long double pio4 =  7.85398163397448309615660845819875721e-1L;
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +cosl(long double x)
> +{
> +	union IEEEl2bits z;
> +	int e0;
> +	long double y[2];
> +	long double hi, lo;
> +
> +	z.e = x;
> +	z.bits.sign = 0;
> +
> +	/* If x = +-0 or x is a subnormal number, then cos(x) = 1 */
> +	if (z.bits.exp == 0)
> +		return (1.0);
> +
> +	/* If x = NaN or Inf, then cos(x) = NaN. */
> +	if (z.bits.exp == 32767)
> +		return ((x - x) / (x - x));
> +
> +	ENTERI();
> +
> +	/* Optimize the case where x is already within range. */
> +	if (z.e < pio4)
> +		RETURNI(__kernel_cosl(z.e, 0));
> +
> +	e0 = __ieee754_rem_pio2l(x, y);
> +	hi = y[0];
> +	lo = y[1];
> +
> +	switch (e0 & 3) {
> +	case 0:
> +	    hi = __kernel_cosl(hi, lo);
> +	    break;
> +	case 1:
> +	    hi = - __kernel_sinl(hi, lo, 1);
> +	    break;
> +	case 2:
> +	    hi = - __kernel_cosl(hi, lo);
> +	    break;
> +	case 3:
> +	    hi = __kernel_sinl(hi, lo, 1);
> +	    break;
> +	}
> +	
> +	RETURNI(hi);
> +}
> diff --git a/newlib/libm/ld/s_fabsl.c b/newlib/libm/ld/s_fabsl.c
> new file mode 100644
> index 000000000..5076d8a9b
> --- /dev/null
> +++ b/newlib/libm/ld/s_fabsl.c
> @@ -0,0 +1,45 @@
> +/*-
> + * SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 2003 Dag-Erling Smørgrav
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer
> + *    in this position and unchanged.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. The name of the author may not be used to endorse or promote products
> + *    derived from this software without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +long double
> +fabsl(long double x)
> +{
> +	union IEEEl2bits u;
> +
> +	u.e = x;
> +	u.bits.sign = 0;
> +	return (u.e);
> +}
> diff --git a/newlib/libm/ld/s_fdim.c b/newlib/libm/ld/s_fdim.c
> new file mode 100644
> index 000000000..c40c3e9d3
> --- /dev/null
> +++ b/newlib/libm/ld/s_fdim.c
> @@ -0,0 +1,48 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +#define	DECL(type, fn)			\
> +type					\
> +fn(type x, type y)			\
> +{					\
> +					\
> +	if (isnan(x))			\
> +		return (x);		\
> +	if (isnan(y))			\
> +		return (y);		\
> +	return (x > y ? x - y : 0.0);	\
> +}
> +
> +DECL(double, fdim)
> +DECL(float, fdimf)
> +DECL(long double, fdiml)
> diff --git a/newlib/libm/ld/s_floorl.c b/newlib/libm/ld/s_floorl.c
> new file mode 100644
> index 000000000..6cec3e781
> --- /dev/null
> +++ b/newlib/libm/ld/s_floorl.c
> @@ -0,0 +1,101 @@
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + *
> + * From: @(#)s_floor.c 5.1 93/09/24
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * floorl(x)
> + * Return x rounded toward -inf to integral value
> + * Method:
> + *	Bit twiddling.
> + * Exception:
> + *	Inexact flag raised if x not equal to floorl(x).
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +
> +#ifdef LDBL_IMPLICIT_NBIT
> +#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
> +#define	INC_MANH(u, c)	do {					\
> +	uint64_t o = u.bits.manh;				\
> +	u.bits.manh += (c);					\
> +	if (u.bits.manh < o)					\
> +		u.bits.exp++;					\
> +} while (0)
> +#else
> +#define	MANH_SIZE	LDBL_MANH_SIZE
> +#define	INC_MANH(u, c)	do {					\
> +	uint64_t o = u.bits.manh;				\
> +	u.bits.manh += (c);					\
> +	if (u.bits.manh < o) {					\
> +		u.bits.exp++;					\
> +		u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1);	\
> +	}							\
> +} while (0)
> +#endif
> +
> +static const long double huge = 1.0e300;
> +
> +long double
> +floorl(long double x)
> +{
> +	union IEEEl2bits u = { .e = x };
> +	int e = u.bits.exp - LDBL_MAX_EXP + 1;
> +
> +	if (e < MANH_SIZE - 1) {
> +		if (e < 0) {			/* raise inexact if x != 0 */
> +			if (huge + x > 0.0)
> +				if (u.bits.exp > 0 ||
> +				    (u.bits.manh | u.bits.manl) != 0)
> +					u.e = u.bits.sign ? -1.0 : 0.0;
> +		} else {
> +			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
> +			if (((u.bits.manh & m) | u.bits.manl) == 0)
> +				return (x);	/* x is integral */
> +			if (u.bits.sign) {
> +#ifdef LDBL_IMPLICIT_NBIT
> +				if (e == 0)
> +					u.bits.exp++;
> +				else
> +#endif
> +				INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
> +			}
> +			if (huge + x > 0.0) {	/* raise inexact flag */
> +				u.bits.manh &= ~m;
> +				u.bits.manl = 0;
> +			}
> +		}
> +	} else if (e < LDBL_MANT_DIG - 1) {
> +		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
> +		if ((u.bits.manl & m) == 0)
> +			return (x);	/* x is integral */
> +		if (u.bits.sign) {
> +			if (e == MANH_SIZE - 1)
> +				INC_MANH(u, 1);
> +			else {
> +				uint64_t o = u.bits.manl;
> +				u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
> +				if (u.bits.manl < o)	/* got a carry */
> +					INC_MANH(u, 1);
> +			}
> +		}
> +		if (huge + x > 0.0)		/* raise inexact flag */
> +			u.bits.manl &= ~m;
> +	}
> +	return (u.e);
> +}
> diff --git a/newlib/libm/ld/s_fmal.c b/newlib/libm/ld/s_fmal.c
> new file mode 100644
> index 000000000..a379346c1
> --- /dev/null
> +++ b/newlib/libm/ld/s_fmal.c
> @@ -0,0 +1,274 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <fenv.h>
> +#include <float.h>
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +/*
> + * A struct dd represents a floating-point number with twice the precision
> + * of a long double.  We maintain the invariant that "hi" stores the high-order
> + * bits of the result.
> + */
> +struct dd {
> +	long double hi;
> +	long double lo;
> +};
> +
> +/*
> + * Compute a+b exactly, returning the exact result in a struct dd.  We assume
> + * that both a and b are finite, but make no assumptions about their relative
> + * magnitudes.
> + */
> +static inline struct dd
> +dd_add(long double a, long double b)
> +{
> +	struct dd ret;
> +	long double s;
> +
> +	ret.hi = a + b;
> +	s = ret.hi - a;
> +	ret.lo = (a - (ret.hi - s)) + (b - s);
> +	return (ret);
> +}
> +
> +/*
> + * Compute a+b, with a small tweak:  The least significant bit of the
> + * result is adjusted into a sticky bit summarizing all the bits that
> + * were lost to rounding.  This adjustment negates the effects of double
> + * rounding when the result is added to another number with a higher
> + * exponent.  For an explanation of round and sticky bits, see any reference
> + * on FPU design, e.g.,
> + *
> + *     J. Coonen.  An Implementation Guide to a Proposed Standard for
> + *     Floating-Point Arithmetic.  Computer, vol. 13, no. 1, Jan 1980.
> + */
> +static inline long double
> +add_adjusted(long double a, long double b)
> +{
> +	struct dd sum;
> +	union IEEEl2bits u;
> +
> +	sum = dd_add(a, b);
> +	if (sum.lo != 0) {
> +		u.e = sum.hi;
> +		if ((u.bits.manl & 1) == 0)
> +			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
> +	}
> +	return (sum.hi);
> +}
> +
> +/*
> + * Compute ldexp(a+b, scale) with a single rounding error. It is assumed
> + * that the result will be subnormal, and care is taken to ensure that
> + * double rounding does not occur.
> + */
> +static inline long double
> +add_and_denormalize(long double a, long double b, int scale)
> +{
> +	struct dd sum;
> +	int bits_lost;
> +	union IEEEl2bits u;
> +
> +	sum = dd_add(a, b);
> +
> +	/*
> +	 * If we are losing at least two bits of accuracy to denormalization,
> +	 * then the first lost bit becomes a round bit, and we adjust the
> +	 * lowest bit of sum.hi to make it a sticky bit summarizing all the
> +	 * bits in sum.lo. With the sticky bit adjusted, the hardware will
> +	 * break any ties in the correct direction.
> +	 *
> +	 * If we are losing only one bit to denormalization, however, we must
> +	 * break the ties manually.
> +	 */
> +	if (sum.lo != 0) {
> +		u.e = sum.hi;
> +		bits_lost = -u.bits.exp - scale + 1;
> +		if ((bits_lost != 1) ^ (int)(u.bits.manl & 1))
> +			sum.hi = nextafterl(sum.hi, INFINITY * sum.lo);
> +	}
> +	return (ldexp(sum.hi, scale));
> +}
> +
> +/*
> + * Compute a*b exactly, returning the exact result in a struct dd.  We assume
> + * that both a and b are normalized, so no underflow or overflow will occur.
> + * The current rounding mode must be round-to-nearest.
> + */
> +static inline struct dd
> +dd_mul(long double a, long double b)
> +{
> +#if LDBL_MANT_DIG == 64
> +	static const long double split = 0x1p32L + 1.0;
> +#elif LDBL_MANT_DIG == 113
> +	static const long double split = 0x1p57L + 1.0;
> +#endif
> +	struct dd ret;
> +	long double ha, hb, la, lb, p, q;
> +
> +	p = a * split;
> +	ha = a - p;
> +	ha += p;
> +	la = a - ha;
> +
> +	p = b * split;
> +	hb = b - p;
> +	hb += p;
> +	lb = b - hb;
> +
> +	p = ha * hb;
> +	q = ha * lb + la * hb;
> +
> +	ret.hi = p + q;
> +	ret.lo = p - ret.hi + q + la * lb;
> +	return (ret);
> +}
> +
> +/*
> + * Fused multiply-add: Compute x * y + z with a single rounding error.
> + *
> + * We use scaling to avoid overflow/underflow, along with the
> + * canonical precision-doubling technique adapted from:
> + *
> + *	Dekker, T.  A Floating-Point Technique for Extending the
> + *	Available Precision.  Numer. Math. 18, 224-242 (1971).
> + */
> +long double
> +fmal(long double x, long double y, long double z)
> +{
> +	long double xs, ys, zs, adj;
> +	struct dd xy, r;
> +	int oround;
> +	int ex, ey, ez;
> +	int spread;
> +
> +	/*
> +	 * Handle special cases. The order of operations and the particular
> +	 * return values here are crucial in handling special cases involving
> +	 * infinities, NaNs, overflows, and signed zeroes correctly.
> +	 */
> +	if (x == 0.0 || y == 0.0)
> +		return (x * y + z);
> +	if (z == 0.0)
> +		return (x * y);
> +	if (!isfinite(x) || !isfinite(y))
> +		return (x * y + z);
> +	if (!isfinite(z))
> +		return (z);
> +
> +	xs = frexpl(x, &ex);
> +	ys = frexpl(y, &ey);
> +	zs = frexpl(z, &ez);
> +	oround = fegetround();
> +	spread = ex + ey - ez;
> +
> +	/*
> +	 * If x * y and z are many orders of magnitude apart, the scaling
> +	 * will overflow, so we handle these cases specially.  Rounding
> +	 * modes other than FE_TONEAREST are painful.
> +	 */
> +	if (spread < -LDBL_MANT_DIG) {
> +		feraiseexcept(FE_INEXACT);
> +		if (!isnormal(z))
> +			feraiseexcept(FE_UNDERFLOW);
> +		switch (oround) {
> +		case FE_TONEAREST:
> +			return (z);
> +		case FE_TOWARDZERO:
> +			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
> +				return (z);
> +			else
> +				return (nextafterl(z, 0));
> +		case FE_DOWNWARD:
> +			if (x > 0.0 ^ y < 0.0)
> +				return (z);
> +			else
> +				return (nextafterl(z, -INFINITY));
> +		default:	/* FE_UPWARD */
> +			if (x > 0.0 ^ y < 0.0)
> +				return (nextafterl(z, INFINITY));
> +			else
> +				return (z);
> +		}
> +	}
> +	if (spread <= LDBL_MANT_DIG * 2)
> +		zs = ldexpl(zs, -spread);
> +	else
> +		zs = copysignl(LDBL_MIN, zs);
> +
> +	fesetround(FE_TONEAREST);
> +	/* work around clang bug 8100 */
> +	volatile long double vxs = xs;
> +
> +	/*
> +	 * Basic approach for round-to-nearest:
> +	 *
> +	 *     (xy.hi, xy.lo) = x * y		(exact)
> +	 *     (r.hi, r.lo)   = xy.hi + z	(exact)
> +	 *     adj = xy.lo + r.lo		(inexact; low bit is sticky)
> +	 *     result = r.hi + adj		(correctly rounded)
> +	 */
> +	xy = dd_mul(vxs, ys);
> +	r = dd_add(xy.hi, zs);
> +
> +	spread = ex + ey;
> +
> +	if (r.hi == 0.0) {
> +		/*
> +		 * When the addends cancel to 0, ensure that the result has
> +		 * the correct sign.
> +		 */
> +		fesetround(oround);
> +		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
> +		return (xy.hi + vzs + ldexpl(xy.lo, spread));
> +	}
> +
> +	if (oround != FE_TONEAREST) {
> +		/*
> +		 * There is no need to worry about double rounding in directed
> +		 * rounding modes.
> +		 */
> +		fesetround(oround);
> +		/* work around clang bug 8100 */
> +		volatile long double vrlo = r.lo;
> +		adj = vrlo + xy.lo;
> +		return (ldexpl(r.hi + adj, spread));
> +	}
> +
> +	adj = add_adjusted(r.lo, xy.lo);
> +	if (spread + ilogbl(r.hi) > -16383)
> +		return (ldexpl(r.hi + adj, spread));
> +	else
> +		return (add_and_denormalize(r.hi, adj, spread));
> +}
> diff --git a/newlib/libm/ld/s_fmaxl.c b/newlib/libm/ld/s_fmaxl.c
> new file mode 100644
> index 000000000..c0d7c8832
> --- /dev/null
> +++ b/newlib/libm/ld/s_fmaxl.c
> @@ -0,0 +1,57 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +long double
> +fmaxl(long double x, long double y)
> +{
> +	union IEEEl2bits u[2];
> +
> +	u[0].e = x;
> +	mask_nbit_l(u[0]);
> +	u[1].e = y;
> +	mask_nbit_l(u[1]);
> +
> +	/* Check for NaNs to avoid raising spurious exceptions. */
> +	if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
> +		return (y);
> +	if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
> +		return (x);
> +
> +	/* Handle comparisons of signed zeroes. */
> +	if (u[0].bits.sign != u[1].bits.sign)
> +		return (u[0].bits.sign ? y : x);
> +
> +	return (x > y ? x : y);
> +}
> diff --git a/newlib/libm/ld/s_fminl.c b/newlib/libm/ld/s_fminl.c
> new file mode 100644
> index 000000000..97604b38b
> --- /dev/null
> +++ b/newlib/libm/ld/s_fminl.c
> @@ -0,0 +1,57 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +long double
> +fminl(long double x, long double y)
> +{
> +	union IEEEl2bits u[2];
> +
> +	u[0].e = x;
> +	mask_nbit_l(u[0]);
> +	u[1].e = y;
> +	mask_nbit_l(u[1]);
> +
> +	/* Check for NaNs to avoid raising spurious exceptions. */
> +	if (u[0].bits.exp == 32767 && (u[0].bits.manh | u[0].bits.manl) != 0)
> +		return (y);
> +	if (u[1].bits.exp == 32767 && (u[1].bits.manh | u[1].bits.manl) != 0)
> +		return (x);
> +
> +	/* Handle comparisons of signed zeroes. */
> +	if (u[0].bits.sign != u[1].bits.sign)
> +		return (u[1].bits.sign ? y : x);
> +
> +	return (x < y ? x : y);
> +}
> diff --git a/newlib/libm/ld/s_frexpl.c b/newlib/libm/ld/s_frexpl.c
> new file mode 100644
> index 000000000..66e284fdd
> --- /dev/null
> +++ b/newlib/libm/ld/s_frexpl.c
> @@ -0,0 +1,64 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +frexpl(long double x, int *ex)
> +{
> +	union IEEEl2bits u;
> +
> +	u.e = x;
> +	switch (u.bits.exp) {
> +	case 0:		/* 0 or subnormal */
> +		if ((u.bits.manl | u.bits.manh) == 0) {
> +			*ex = 0;
> +		} else {
> +			u.e *= 0x1.0p514;
> +			*ex = u.bits.exp - 0x4200;
> +			u.bits.exp = 0x3ffe;
> +		}
> +		break;
> +	case 0x7fff:	/* infinity or NaN; value of *ex is unspecified */
> +		break;
> +	default:	/* normal */
> +		*ex = u.bits.exp - 0x3ffe;
> +		u.bits.exp = 0x3ffe;
> +		break;
> +	}
> +	return (u.e);
> +}
> diff --git a/newlib/libm/ld/s_ilogbl.c b/newlib/libm/ld/s_ilogbl.c
> new file mode 100644
> index 000000000..3211f4409
> --- /dev/null
> +++ b/newlib/libm/ld/s_ilogbl.c
> @@ -0,0 +1,53 @@
> +/*
> + * From: @(#)s_ilogb.c 5.1 93/09/24
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <limits.h>
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +int
> +ilogbl(long double x)
> +{
> +	union IEEEl2bits u;
> +	unsigned long m;
> +	int b;
> +
> +	u.e = x;
> +	if (u.bits.exp == 0) {
> +		if ((u.bits.manl | u.bits.manh) == 0)
> +			return (FP_ILOGB0);
> +		/* denormalized */
> +		if (u.bits.manh == 0) {
> +			m = 1lu << (LDBL_MANL_SIZE - 1);
> +			for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1)
> +				b++;
> +		} else {
> +			m = 1lu << (LDBL_MANH_SIZE - 1);
> +			for (b = 0; !(u.bits.manh & m); m >>= 1)
> +				b++;
> +		}
> +#ifdef LDBL_IMPLICIT_NBIT
> +		b++;
> +#endif
> +		return (LDBL_MIN_EXP - b - 1);
> +	} else if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1)
> +		return (u.bits.exp - LDBL_MAX_EXP + 1);
> +	else if (u.bits.manl != 0 || u.bits.manh != 0)
> +		return (FP_ILOGBNAN);
> +	else
> +		return (INT_MAX);
> +}
> diff --git a/newlib/libm/ld/s_llrintl.c b/newlib/libm/ld/s_llrintl.c
> new file mode 100644
> index 000000000..6ef83759c
> --- /dev/null
> +++ b/newlib/libm/ld/s_llrintl.c
> @@ -0,0 +1,9 @@
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#define type		long double
> +#define	roundit		rintl
> +#define dtype		long long
> +#define	fn		llrintl
> +
> +#include "s_lrint.c"
> diff --git a/newlib/libm/ld/s_llroundl.c b/newlib/libm/ld/s_llroundl.c
> new file mode 100644
> index 000000000..02c44eb4b
> --- /dev/null
> +++ b/newlib/libm/ld/s_llroundl.c
> @@ -0,0 +1,11 @@
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#define type		long double
> +#define	roundit		roundl
> +#define dtype		long long
> +#define	DTYPE_MIN	LLONG_MIN
> +#define	DTYPE_MAX	LLONG_MAX
> +#define	fn		llroundl
> +
> +#include "s_lround.c"
> diff --git a/newlib/libm/ld/s_logbl.c b/newlib/libm/ld/s_logbl.c
> new file mode 100644
> index 000000000..ee1a91fd8
> --- /dev/null
> +++ b/newlib/libm/ld/s_logbl.c
> @@ -0,0 +1,54 @@
> +/*
> + * From: @(#)s_ilogb.c 5.1 93/09/24
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <limits.h>
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +long double
> +logbl(long double x)
> +{
> +	union IEEEl2bits u;
> +	unsigned long m;
> +	int b;
> +
> +	u.e = x;
> +	if (u.bits.exp == 0) {
> +		if ((u.bits.manl | u.bits.manh) == 0) {	/* x == 0 */
> +			u.bits.sign = 1;
> +			return (1.0L / u.e);
> +		}
> +		/* denormalized */
> +		if (u.bits.manh == 0) {
> +			m = 1lu << (LDBL_MANL_SIZE - 1);
> +			for (b = LDBL_MANH_SIZE; !(u.bits.manl & m); m >>= 1)
> +				b++;
> +		} else {
> +			m = 1lu << (LDBL_MANH_SIZE - 1);
> +			for (b = 0; !(u.bits.manh & m); m >>= 1)
> +				b++;
> +		}
> +#ifdef LDBL_IMPLICIT_NBIT
> +		b++;
> +#endif
> +		return ((long double)(LDBL_MIN_EXP - b - 1));
> +	}
> +	if (u.bits.exp < (LDBL_MAX_EXP << 1) - 1)	/* normal */
> +		return ((long double)(u.bits.exp - LDBL_MAX_EXP + 1));
> +	else						/* +/- inf or nan */
> +		return (x * x);
> +}
> diff --git a/newlib/libm/ld/s_lrint.c b/newlib/libm/ld/s_lrint.c
> new file mode 100644
> index 000000000..ad9b978fa
> --- /dev/null
> +++ b/newlib/libm/ld/s_lrint.c
> @@ -0,0 +1,60 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +#include <fenv.h>
> +#include <math.h>
> +
> +#ifndef type
> +__FBSDID("$FreeBSD$");
> +#define type		double
> +#define	roundit		rint
> +#define dtype		long
> +#define	fn		lrint
> +#endif
> +
> +/*
> + * C99 says we should not raise a spurious inexact exception when an
> + * invalid exception is raised.  Unfortunately, the set of inputs
> + * that overflows depends on the rounding mode when 'dtype' has more
> + * significant bits than 'type'.  Hence, we bend over backwards for the
> + * sake of correctness; an MD implementation could be more efficient.
> + */
> +dtype
> +fn(type x)
> +{
> +	fenv_t env;
> +	dtype d;
> +
> +	feholdexcept(&env);
> +	d = (dtype)roundit(x);
> +	if (fetestexcept(FE_INVALID))
> +		feclearexcept(FE_INEXACT);
> +	feupdateenv(&env);
> +	return (d);
> +}
> diff --git a/newlib/libm/ld/s_lrintl.c b/newlib/libm/ld/s_lrintl.c
> new file mode 100644
> index 000000000..497b442f3
> --- /dev/null
> +++ b/newlib/libm/ld/s_lrintl.c
> @@ -0,0 +1,9 @@
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#define type		long double
> +#define	roundit		rintl
> +#define dtype		long
> +#define	fn		lrintl
> +
> +#include "s_lrint.c"
> diff --git a/newlib/libm/ld/s_lround.c b/newlib/libm/ld/s_lround.c
> new file mode 100644
> index 000000000..1dd8e697f
> --- /dev/null
> +++ b/newlib/libm/ld/s_lround.c
> @@ -0,0 +1,70 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +#include <sys/limits.h>
> +#include <fenv.h>
> +#include <math.h>
> +
> +#ifndef type
> +__FBSDID("$FreeBSD$");
> +#define type		double
> +#define	roundit		round
> +#define dtype		long
> +#define	DTYPE_MIN	LONG_MIN
> +#define	DTYPE_MAX	LONG_MAX
> +#define	fn		lround
> +#endif
> +
> +/*
> + * If type has more precision than dtype, the endpoints dtype_(min|max) are
> + * of the form xxx.5; they are "out of range" because lround() rounds away
> + * from 0.  On the other hand, if type has less precision than dtype, then
> + * all values that are out of range are integral, so we might as well assume
> + * that everything is in range.  At compile time, INRANGE(x) should reduce to
> + * two floating-point comparisons in the former case, or TRUE otherwise.
> + */
> +static const type type_min = (type)DTYPE_MIN;
> +static const type type_max = (type)DTYPE_MAX;
> +static const type dtype_min = (type)DTYPE_MIN - 0.5;
> +static const type dtype_max = (type)DTYPE_MAX + 0.5;
> +#define	INRANGE(x)	(dtype_max - type_max != 0.5 || \
> +			 ((x) > dtype_min && (x) < dtype_max))
> +
> +dtype
> +fn(type x)
> +{
> +
> +	if (INRANGE(x)) {
> +		x = roundit(x);
> +		return ((dtype)x);
> +	} else {
> +		feraiseexcept(FE_INVALID);
> +		return (DTYPE_MAX);
> +	}
> +}
> diff --git a/newlib/libm/ld/s_lroundl.c b/newlib/libm/ld/s_lroundl.c
> new file mode 100644
> index 000000000..e410827e2
> --- /dev/null
> +++ b/newlib/libm/ld/s_lroundl.c
> @@ -0,0 +1,11 @@
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#define type		long double
> +#define	roundit		roundl
> +#define dtype		long
> +#define	DTYPE_MIN	LONG_MIN
> +#define	DTYPE_MAX	LONG_MAX
> +#define	fn		lroundl
> +
> +#include "s_lround.c"
> diff --git a/newlib/libm/ld/s_modfl.c b/newlib/libm/ld/s_modfl.c
> new file mode 100644
> index 000000000..2d83bbe33
> --- /dev/null
> +++ b/newlib/libm/ld/s_modfl.c
> @@ -0,0 +1,103 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * Derived from s_modf.c, which has the following Copyright:
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + *
> + * $FreeBSD$
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +#include <sys/types.h>
> +
> +#include "fpmath.h"
> +
> +#if LDBL_MANL_SIZE > 32
> +#define	MASK	((uint64_t)-1)
> +#else
> +#define	MASK	((uint32_t)-1)
> +#endif
> +/* Return the last n bits of a word, representing the fractional part. */
> +#define	GETFRAC(bits, n)	((bits) & ~(MASK << (n)))
> +/* The number of fraction bits in manh, not counting the integer bit */
> +#define	HIBITS	(LDBL_MANT_DIG - LDBL_MANL_SIZE)
> +
> +static const long double zero[] = { 0.0L, -0.0L };
> +
> +long double
> +modfl(long double x, long double *iptr)
> +{
> +	union IEEEl2bits ux;
> +	int e;
> +
> +	ux.e = x;
> +	e = ux.bits.exp - LDBL_MAX_EXP + 1;
> +	if (e < HIBITS) {			/* Integer part is in manh. */
> +		if (e < 0) {			/* |x|<1 */
> +			*iptr = zero[ux.bits.sign];
> +			return (x);
> +		} else {
> +			if ((GETFRAC(ux.bits.manh, HIBITS - 1 - e) |
> +			     ux.bits.manl) == 0) {	/* X is an integer. */
> +				*iptr = x;
> +				return (zero[ux.bits.sign]);
> +			} else {
> +				/* Clear all but the top e+1 bits. */
> +				ux.bits.manh >>= HIBITS - 1 - e;
> +				ux.bits.manh <<= HIBITS - 1 - e;
> +				ux.bits.manl = 0;
> +				*iptr = ux.e;
> +				return (x - ux.e);
> +			}
> +		}
> +	} else if (e >= LDBL_MANT_DIG - 1) {	/* x has no fraction part. */
> +		*iptr = x;
> +		if (x != x)			/* Handle NaNs. */
> +			return (x);
> +		return (zero[ux.bits.sign]);
> +	} else {				/* Fraction part is in manl. */
> +		if (GETFRAC(ux.bits.manl, LDBL_MANT_DIG - 1 - e) == 0) {
> +			/* x is integral. */
> +			*iptr = x;
> +			return (zero[ux.bits.sign]);
> +		} else {
> +			/* Clear all but the top e+1 bits. */
> +			ux.bits.manl >>= LDBL_MANT_DIG - 1 - e;
> +			ux.bits.manl <<= LDBL_MANT_DIG - 1 - e;
> +			*iptr = ux.e;
> +			return (x - ux.e);
> +		}
> +	}
> +}
> diff --git a/newlib/libm/ld/s_nearbyint.c b/newlib/libm/ld/s_nearbyint.c
> new file mode 100644
> index 000000000..796dbaf98
> --- /dev/null
> +++ b/newlib/libm/ld/s_nearbyint.c
> @@ -0,0 +1,61 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <fenv.h>
> +#include <math.h>
> +
> +/*
> + * We save and restore the floating-point environment to avoid raising
> + * an inexact exception.  We can get away with using fesetenv()
> + * instead of feclearexcept()/feupdateenv() to restore the environment
> + * because the only exception defined for rint() is overflow, and
> + * rounding can't overflow as long as emax >= p.
> + *
> + * The volatile keyword is needed below because clang incorrectly assumes
> + * that rint won't raise any floating-point exceptions. Declaring ret volatile
> + * is sufficient to trick the compiler into doing the right thing.
> + */
> +#define	DECL(type, fn, rint)	\
> +type				\
> +fn(type x)			\
> +{				\
> +	volatile type ret;	\
> +	fenv_t env;		\
> +				\
> +	fegetenv(&env);		\
> +	ret = rint(x);		\
> +	fesetenv(&env);		\
> +	return (ret);		\
> +}
> +
> +DECL(double, nearbyint, rint)
> +DECL(float, nearbyintf, rintf)
> +DECL(long double, nearbyintl, rintl)
> diff --git a/newlib/libm/ld/s_nextafterl.c b/newlib/libm/ld/s_nextafterl.c
> new file mode 100644
> index 000000000..9c61a436a
> --- /dev/null
> +++ b/newlib/libm/ld/s_nextafterl.c
> @@ -0,0 +1,80 @@
> +/* @(#)s_nextafter.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/* IEEE functions
> + *	nextafter(x,y)
> + *	return the next machine floating-point number of x in the
> + *	direction toward y.
> + *   Special cases:
> + */
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +nextafterl(long double x, long double y)
> +{
> +	volatile long double t;
> +	union IEEEl2bits ux, uy;
> +
> +	ux.e = x;
> +	uy.e = y;
> +
> +	if ((ux.bits.exp == 0x7fff &&
> +	     ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl) != 0) ||
> +	    (uy.bits.exp == 0x7fff &&
> +	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
> +	   return x+y;	/* x or y is nan */
> +	if(x==y) return y;		/* x=y, return y */
> +	if(x==0.0) {
> +	    ux.bits.manh = 0;			/* return +-minsubnormal */
> +	    ux.bits.manl = 1;
> +	    ux.bits.sign = uy.bits.sign;
> +	    t = ux.e*ux.e;
> +	    if(t==ux.e) return t; else return ux.e; /* raise underflow flag */
> +	}
> +	if(x>0.0 ^ x<y) {			/* x -= ulp */
> +	    if(ux.bits.manl==0) {
> +		if ((ux.bits.manh&~LDBL_NBIT)==0)
> +		    ux.bits.exp -= 1;
> +		ux.bits.manh = (ux.bits.manh - 1) | (ux.bits.manh & LDBL_NBIT);
> +	    }
> +	    ux.bits.manl -= 1;
> +	} else {				/* x += ulp */
> +	    ux.bits.manl += 1;
> +	    if(ux.bits.manl==0) {
> +		ux.bits.manh = (ux.bits.manh + 1) | (ux.bits.manh & LDBL_NBIT);
> +		if ((ux.bits.manh&~LDBL_NBIT)==0)
> +		    ux.bits.exp += 1;
> +	    }
> +	}
> +	if(ux.bits.exp==0x7fff) return x+x;	/* overflow  */
> +	if(ux.bits.exp==0) {			/* underflow */
> +	    mask_nbit_l(ux);
> +	    t = ux.e * ux.e;
> +	    if(t!=ux.e)			/* raise underflow flag */
> +		return ux.e;
> +	}
> +	return ux.e;
> +}
> +
> +__strong_reference(nextafterl, nexttowardl);
> diff --git a/newlib/libm/ld/s_nexttoward.c b/newlib/libm/ld/s_nexttoward.c
> new file mode 100644
> index 000000000..b2a50d313
> --- /dev/null
> +++ b/newlib/libm/ld/s_nexttoward.c
> @@ -0,0 +1,72 @@
> +/* @(#)s_nextafter.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * We assume that a long double has a 15-bit exponent.  On systems
> + * where long double is the same as double, nexttoward() is an alias
> + * for nextafter(), so we don't use this routine.
> + */
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +#error "Unsupported long double format"
> +#endif
> +
> +double
> +nexttoward(double x, long double y)
> +{
> +	union IEEEl2bits uy;
> +	volatile double t;
> +	int32_t hx,ix;
> +	u_int32_t lx;
> +
> +	EXTRACT_WORDS(hx,lx,x);
> +	ix = hx&0x7fffffff;		/* |x| */
> +	uy.e = y;
> +
> +	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||
> +	    (uy.bits.exp == 0x7fff &&
> +	     ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
> +	   return x+y;	/* x or y is nan */
> +	if(x==y) return (double)y;		/* x=y, return y */
> +	if(x==0.0) {
> +	    INSERT_WORDS(x,uy.bits.sign<<31,1);	/* return +-minsubnormal */
> +	    t = x*x;
> +	    if(t==x) return t; else return x;	/* raise underflow flag */
> +	}
> +	if(hx>0.0 ^ x < y) {			/* x -= ulp */
> +	    if(lx==0) hx -= 1;
> +	    lx -= 1;
> +	} else {				/* x += ulp */
> +	    lx += 1;
> +	    if(lx==0) hx += 1;
> +	}
> +	ix = hx&0x7ff00000;
> +	if(ix>=0x7ff00000) return x+x;	/* overflow  */
> +	if(ix<0x00100000) {		/* underflow */
> +	    t = x*x;
> +	    if(t!=x) {		/* raise underflow flag */
> +	        INSERT_WORDS(x,hx,lx);
> +		return x;
> +	    }
> +	}
> +	INSERT_WORDS(x,hx,lx);
> +	return x;
> +}
> diff --git a/newlib/libm/ld/s_nexttowardf.c b/newlib/libm/ld/s_nexttowardf.c
> new file mode 100644
> index 000000000..9ddfff961
> --- /dev/null
> +++ b/newlib/libm/ld/s_nexttowardf.c
> @@ -0,0 +1,59 @@
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#define	LDBL_INFNAN_EXP	(LDBL_MAX_EXP * 2 - 1)
> +
> +float
> +nexttowardf(float x, long double y)
> +{
> +	union IEEEl2bits uy;
> +	volatile float t;
> +	int32_t hx,ix;
> +
> +	GET_FLOAT_WORD(hx,x);
> +	ix = hx&0x7fffffff;		/* |x| */
> +	uy.e = y;
> +
> +	if((ix>0x7f800000) ||
> +	   (uy.bits.exp == LDBL_INFNAN_EXP &&
> +	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0))
> +	   return x+y;	/* x or y is nan */
> +	if(x==y) return (float)y;		/* x=y, return y */
> +	if(ix==0) {				/* x == 0 */
> +	    SET_FLOAT_WORD(x,(uy.bits.sign<<31)|1);/* return +-minsubnormal */
> +	    t = x*x;
> +	    if(t==x) return t; else return x;	/* raise underflow flag */
> +	}
> +	if(hx>=0 ^ x < y)			/* x -= ulp */
> +	    hx -= 1;
> +	else					/* x += ulp */
> +	    hx += 1;
> +	ix = hx&0x7f800000;
> +	if(ix>=0x7f800000) return x+x;	/* overflow  */
> +	if(ix<0x00800000) {		/* underflow */
> +	    t = x*x;
> +	    if(t!=x) {		/* raise underflow flag */
> +	        SET_FLOAT_WORD(x,hx);
> +		return x;
> +	    }
> +	}
> +	SET_FLOAT_WORD(x,hx);
> +	return x;
> +}
> diff --git a/newlib/libm/ld/s_remquol.c b/newlib/libm/ld/s_remquol.c
> new file mode 100644
> index 000000000..a9f5813d0
> --- /dev/null
> +++ b/newlib/libm/ld/s_remquol.c
> @@ -0,0 +1,173 @@
> +/* @(#)e_fmod.c 1.3 95/01/18 */
> +/*-
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#define	BIAS (LDBL_MAX_EXP - 1)
> +
> +#if LDBL_MANL_SIZE > 32
> +typedef	uint64_t manl_t;
> +#else
> +typedef	uint32_t manl_t;
> +#endif
> +
> +#if LDBL_MANH_SIZE > 32
> +typedef	uint64_t manh_t;
> +#else
> +typedef	uint32_t manh_t;
> +#endif
> +
> +/*
> + * These macros add and remove an explicit integer bit in front of the
> + * fractional mantissa, if the architecture doesn't have such a bit by
> + * default already.
> + */
> +#ifdef LDBL_IMPLICIT_NBIT
> +#define	SET_NBIT(hx)	((hx) | (1ULL << LDBL_MANH_SIZE))
> +#define	HFRAC_BITS	LDBL_MANH_SIZE
> +#else
> +#define	SET_NBIT(hx)	(hx)
> +#define	HFRAC_BITS	(LDBL_MANH_SIZE - 1)
> +#endif
> +
> +#define	MANL_SHIFT	(LDBL_MANL_SIZE - 1)
> +
> +static const long double Zero[] = {0.0L, -0.0L};
> +
> +/*
> + * Return the IEEE remainder and set *quo to the last n bits of the
> + * quotient, rounded to the nearest integer.  We choose n=31 because
> + * we wind up computing all the integer bits of the quotient anyway as
> + * a side-effect of computing the remainder by the shift and subtract
> + * method.  In practice, this is far more bits than are needed to use
> + * remquo in reduction algorithms.
> + *
> + * Assumptions:
> + * - The low part of the mantissa fits in a manl_t exactly.
> + * - The high part of the mantissa fits in an int64_t with enough room
> + *   for an explicit integer bit in front of the fractional bits.
> + */
> +long double
> +remquol(long double x, long double y, int *quo)
> +{
> +	union IEEEl2bits ux, uy;
> +	int64_t hx,hz;	/* We need a carry bit even if LDBL_MANH_SIZE is 32. */
> +	manh_t hy;
> +	manl_t lx,ly,lz;
> +	int ix,iy,n,q,sx,sxy;
> +
> +	ux.e = x;
> +	uy.e = y;
> +	sx = ux.bits.sign;
> +	sxy = sx ^ uy.bits.sign;
> +	ux.bits.sign = 0;	/* |x| */
> +	uy.bits.sign = 0;	/* |y| */
> +
> +    /* purge off exception values */
> +	if((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */
> +	   (ux.bits.exp == BIAS + LDBL_MAX_EXP) ||	 /* or x not finite */
> +	   (uy.bits.exp == BIAS + LDBL_MAX_EXP &&
> +	    ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */
> +	    return nan_mix_op(x, y, *)/nan_mix_op(x, y, *);
> +	if(ux.bits.exp<=uy.bits.exp) {
> +	    if((ux.bits.exp<uy.bits.exp) ||
> +	       (ux.bits.manh<=uy.bits.manh &&
> +		(ux.bits.manh<uy.bits.manh ||
> +		 ux.bits.manl<uy.bits.manl))) {
> +		q = 0;
> +		goto fixup;	/* |x|<|y| return x or x-y */
> +	    }
> +	    if(ux.bits.manh==uy.bits.manh && ux.bits.manl==uy.bits.manl) {
> +		*quo = (sxy ? -1 : 1);
> +		return Zero[sx];	/* |x|=|y| return x*0*/
> +	    }
> +	}
> +
> +    /* determine ix = ilogb(x) */
> +	if(ux.bits.exp == 0) {	/* subnormal x */
> +	    ux.e *= 0x1.0p512;
> +	    ix = ux.bits.exp - (BIAS + 512);
> +	} else {
> +	    ix = ux.bits.exp - BIAS;
> +	}
> +
> +    /* determine iy = ilogb(y) */
> +	if(uy.bits.exp == 0) {	/* subnormal y */
> +	    uy.e *= 0x1.0p512;
> +	    iy = uy.bits.exp - (BIAS + 512);
> +	} else {
> +	    iy = uy.bits.exp - BIAS;
> +	}
> +
> +    /* set up {hx,lx}, {hy,ly} and align y to x */
> +	hx = SET_NBIT(ux.bits.manh);
> +	hy = SET_NBIT(uy.bits.manh);
> +	lx = ux.bits.manl;
> +	ly = uy.bits.manl;
> +
> +    /* fix point fmod */
> +	n = ix - iy;
> +	q = 0;
> +	while(n--) {
> +	    hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
> +	    if(hz<0){hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;}
> +	    else {hx = hz+hz+(lz>>MANL_SHIFT); lx = lz+lz; q++;}
> +	    q <<= 1;
> +	}
> +	hz=hx-hy;lz=lx-ly; if(lx<ly) hz -= 1;
> +	if(hz>=0) {hx=hz;lx=lz;q++;}
> +
> +    /* convert back to floating value and restore the sign */
> +	if((hx|lx)==0) {			/* return sign(x)*0 */
> +	    q &= 0x7fffffff;
> +	    *quo = (sxy ? -q : q);
> +	    return Zero[sx];
> +	}
> +	while(hx<(1ULL<<HFRAC_BITS)) {	/* normalize x */
> +	    hx = hx+hx+(lx>>MANL_SHIFT); lx = lx+lx;
> +	    iy -= 1;
> +	}
> +	ux.bits.manh = hx; /* The integer bit is truncated here if needed. */
> +	ux.bits.manl = lx;
> +	if (iy < LDBL_MIN_EXP) {
> +	    ux.bits.exp = iy + (BIAS + 512);
> +	    ux.e *= 0x1p-512;
> +	} else {
> +	    ux.bits.exp = iy + BIAS;
> +	}
> +fixup:
> +	x = ux.e;		/* |x| */
> +	y = fabsl(y);
> +	if (y < LDBL_MIN * 2) {
> +	    if (x+x>y || (x+x==y && (q & 1))) {
> +		q++;
> +		x-=y;
> +	    }
> +	} else if (x>0.5*y || (x==0.5*y && (q & 1))) {
> +	    q++;
> +	    x-=y;
> +	}
> +	ux.e = x;
> +	ux.bits.sign ^= sx;
> +	x = ux.e;
> +	q &= 0x7fffffff;
> +	*quo = (sxy ? -q : q);
> +	return x;
> +}
> diff --git a/newlib/libm/ld/s_rintl.c b/newlib/libm/ld/s_rintl.c
> new file mode 100644
> index 000000000..1e9824d83
> --- /dev/null
> +++ b/newlib/libm/ld/s_rintl.c
> @@ -0,0 +1,92 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <math.h>
> +
> +#include "fpmath.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual bias, min exp and expsign packing. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const float
> +shift[2] = {
> +#if LDBL_MANT_DIG == 64
> +	0x1.0p63, -0x1.0p63
> +#elif LDBL_MANT_DIG == 113
> +	0x1.0p112, -0x1.0p112
> +#else
> +#error "Unsupported long double format"
> +#endif
> +};
> +static const float zero[2] = { 0.0, -0.0 };
> +
> +long double
> +rintl(long double x)
> +{
> +	union IEEEl2bits u;
> +	uint32_t expsign;
> +	int ex, sign;
> +
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	ex = expsign & 0x7fff;
> +
> +	if (ex >= BIAS + LDBL_MANT_DIG - 1) {
> +		if (ex == BIAS + LDBL_MAX_EXP)
> +			return (x + x);	/* Inf, NaN, or unsupported format */
> +		return (x);		/* finite and already an integer */
> +	}
> +	sign = expsign >> 15;
> +
> +	/*
> +	 * The following code assumes that intermediate results are
> +	 * evaluated in long double precision. If they are evaluated in
> +	 * greater precision, double rounding may occur, and if they are
> +	 * evaluated in less precision (as on i386), results will be
> +	 * wildly incorrect.
> +	 */
> +	x += shift[sign];
> +	x -= shift[sign];
> +
> +	/*
> +	 * If the result is +-0, then it must have the same sign as x, but
> +	 * the above calculation doesn't always give this.  Fix up the sign.
> +	 */
> +	if (ex < BIAS && x == 0.0L)
> +		return (zero[sign]);
> +
> +	return (x);
> +}
> diff --git a/newlib/libm/ld/s_roundl.c b/newlib/libm/ld/s_roundl.c
> new file mode 100644
> index 000000000..8d1c02a7f
> --- /dev/null
> +++ b/newlib/libm/ld/s_roundl.c
> @@ -0,0 +1,64 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2003, Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +long double
> +roundl(long double x)
> +{
> +	long double t;
> +	uint16_t hx;
> +
> +	GET_LDBL_EXPSIGN(hx, x);
> +	if ((hx & 0x7fff) == 0x7fff)
> +		return (x + x);
> +
> +	ENTERI();
> +
> +	if (!(hx & 0x8000)) {
> +		t = floorl(x);
> +		if (t - x <= -0.5L)
> +			t += 1;
> +		RETURNI(t);
> +	} else {
> +		t = floorl(-x);
> +		if (t + x <= -0.5L)
> +			t += 1;
> +		RETURNI(-t);
> +	}
> +}
> diff --git a/newlib/libm/ld/s_scalbln.c b/newlib/libm/ld/s_scalbln.c
> new file mode 100644
> index 000000000..c27420c92
> --- /dev/null
> +++ b/newlib/libm/ld/s_scalbln.c
> @@ -0,0 +1,56 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +#define	NMAX	65536
> +#define	NMIN	-65536
> +
> +double
> +scalbln(double x, long n)
> +{
> +
> +	return (scalbn(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
> +}
> +
> +float
> +scalblnf(float x, long n)
> +{
> +
> +	return (scalbnf(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
> +}
> +
> +long double
> +scalblnl(long double x, long n)
> +{
> +
> +	return (scalbnl(x, (n > NMAX) ? NMAX : (n < NMIN) ? NMIN : (int)n));
> +}
> diff --git a/newlib/libm/ld/s_scalbnl.c b/newlib/libm/ld/s_scalbnl.c
> new file mode 100644
> index 000000000..6044c1b1d
> --- /dev/null
> +++ b/newlib/libm/ld/s_scalbnl.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (c) 2005-2020 Rich Felker, et al.
> + *
> + * SPDX-License-Identifier: MIT
> + *
> + * Please see https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
> + * for all contributors to musl.
> + */
> +#include <math.h>
> +#include <float.h>
> +#include "math_private.h"
> +#include "fpmath.h"
> +/*
> + * scalbnl (long double x, int n)
> + * scalbnl(x,n) returns x* 2**n  computed by  exponent
> + * manipulation rather than by actually performing an
> + * exponentiation or a multiplication.
> + */
> +#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
> +long double scalbnl(long double x, int n)
> +{
> +	union IEEEl2bits u;
> +
> +	if (n > 16383) {
> +		x *= 0x1p16383L;
> +		n -= 16383;
> +		if (n > 16383) {
> +			x *= 0x1p16383L;
> +			n -= 16383;
> +			if (n > 16383)
> +				n = 16383;
> +		}
> +	} else if (n < -16382) {
> +		x *= 0x1p-16382L * 0x1p113L;
> +		n += 16382 - 113;
> +		if (n < -16382) {
> +			x *= 0x1p-16382L * 0x1p113L;
> +			n += 16382 - 113;
> +			if (n < -16382)
> +				n = -16382;
> +		}
> +	}
> +	u.e = 1.0;
> +	u.xbits.expsign = 0x3fff + n;
> +	return x * u.e;
> +}
> +__strong_reference(scalbnl, ldexpl);
> +#endif
> +
> diff --git a/newlib/libm/ld/s_sinl.c b/newlib/libm/ld/s_sinl.c
> new file mode 100644
> index 000000000..f1ef84c8c
> --- /dev/null
> +++ b/newlib/libm/ld/s_sinl.c
> @@ -0,0 +1,95 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "math.h"
> +#include "math_private.h"
> +#if LDBL_MANT_DIG == 64
> +#include "../ld80/e_rem_pio2l.h"
> +#elif LDBL_MANT_DIG == 113
> +#include "../ld128/e_rem_pio2l.h"
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +sinl(long double x)
> +{
> +	union IEEEl2bits z;
> +	int e0, s;
> +	long double y[2];
> +	long double hi, lo;
> +
> +	z.e = x;
> +	s = z.bits.sign;
> +	z.bits.sign = 0;
> +
> +	/* If x = +-0 or x is a subnormal number, then sin(x) = x */
> +	if (z.bits.exp == 0)
> +		return (x);
> +
> +	/* If x = NaN or Inf, then sin(x) = NaN. */
> +	if (z.bits.exp == 32767)
> +		return ((x - x) / (x - x));
> +
> +	ENTERI();
> +
> +	/* Optimize the case where x is already within range. */
> +	if (z.e < M_PI_4) {
> +		hi = __kernel_sinl(z.e, 0, 0);
> +		RETURNI(s ? -hi : hi);
> +	}
> +
> +	e0 = __ieee754_rem_pio2l(x, y);
> +	hi = y[0];
> +	lo = y[1];
> +
> +	switch (e0 & 3) {
> +	case 0:
> +	    hi = __kernel_sinl(hi, lo, 1);
> +	    break;
> +	case 1:
> +	    hi = __kernel_cosl(hi, lo);
> +	    break;
> +	case 2:
> +	    hi = - __kernel_sinl(hi, lo, 1);
> +	    break;
> +	case 3:
> +	    hi = - __kernel_cosl(hi, lo);
> +	    break;
> +	}
> +	
> +	RETURNI(hi);
> +}
> diff --git a/newlib/libm/ld/s_tanhl.c b/newlib/libm/ld/s_tanhl.c
> new file mode 100644
> index 000000000..b7531866d
> --- /dev/null
> +++ b/newlib/libm/ld/s_tanhl.c
> @@ -0,0 +1,174 @@
> +/* from: FreeBSD: head/lib/msun/src/s_tanhl.c XXX */
> +
> +/* @(#)s_tanh.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See s_tanh.c for complete comments.
> + *
> + * Converted to long double by Bruce D. Evans.
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "math.h"
> +#include "math_private.h"
> +#include "fpmath.h"
> +#include "k_expl.h"
> +
> +#if LDBL_MAX_EXP != 0x4000
> +/* We also require the usual expsign encoding. */
> +#error "Unsupported long double format"
> +#endif
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const volatile double tiny = 1.0e-300;
> +static const double one = 1.0;
> +#if LDBL_MANT_DIG == 64
> +/*
> + * Domain [-0.25, 0.25], range ~[-1.6304e-22, 1.6304e-22]:
> + * |tanh(x)/x - t(x)| < 2**-72.3
> + */
> +static const union IEEEl2bits
> +T3u = LD80C(0xaaaaaaaaaaaaaa9f, -2, -3.33333333333333333017e-1L);
> +#define	T3	T3u.e
> +static const double
> +T5  =  1.3333333333333314e-1,		/*  0x1111111111110a.0p-55 */
> +T7  = -5.3968253968210485e-2,		/* -0x1ba1ba1ba1a1a1.0p-57 */
> +T9  =  2.1869488531393817e-2,		/*  0x1664f488172022.0p-58 */
> +T11 = -8.8632352345964591e-3,		/* -0x1226e34bc138d5.0p-59 */
> +T13 =  3.5921169709993771e-3,		/*  0x1d6d371d3e400f.0p-61 */
> +T15 = -1.4555786415756001e-3,		/* -0x17d923aa63814d.0p-62 */
> +T17 =  5.8645267876296793e-4,		/*  0x13378589b85aa7.0p-63 */
> +T19 = -2.1121033571392224e-4;		/* -0x1baf0af80c4090.0p-65 */
> +#elif LDBL_MANT_DIG == 113
> +/*
> + * Domain [-0.25, 0.25], range ~[-2.4211e-37, 2.4211e-37]:
> + * |tanh(x)/x - t(x)| < 2**121.6
> + */
> +static const long double
> +T3 = -3.33333333333333333333333333333332980e-1L,	/* -0x1555555555555555555555555554e.0p-114L */
> +T5  =  1.33333333333333333333333333332707260e-1L,	/*  0x1111111111111111111111110ab7b.0p-115L */
> +T7  = -5.39682539682539682539682535723482314e-2L,	/* -0x1ba1ba1ba1ba1ba1ba1ba17b5fc98.0p-117L */
> +T9  =  2.18694885361552028218693591149061717e-2L,	/*  0x1664f4882c10f9f32d6b1a12a25e5.0p-118L */
> +T11 = -8.86323552990219656883762347736381851e-3L,	/* -0x1226e355e6c23c8f5a5a0f386cb4d.0p-119L */
> +T13 =  3.59212803657248101358314398220822722e-3L,	/*  0x1d6d3d0e157ddfb403ad3637442c6.0p-121L */
> +T15 = -1.45583438705131796512568010348874662e-3L;	/* -0x17da36452b75e150c44cc34253b34.0p-122L */
> +static const double
> +T17 =  5.9002744094556621e-4,		/*  0x1355824803668e.0p-63 */
> +T19 = -2.3912911424260516e-4,		/* -0x1f57d7734c8dde.0p-65 */
> +T21 =  9.6915379535512898e-5,		/*  0x1967e18ad6a6ca.0p-66 */
> +T23 = -3.9278322983156353e-5,		/* -0x1497d8e6b75729.0p-67 */
> +T25 =  1.5918887220143869e-5,		/*  0x10b1319998cafa.0p-68 */
> +T27 = -6.4514295231630956e-6,		/* -0x1b0f2b71b218eb.0p-70 */
> +T29 =  2.6120754043964365e-6,		/*  0x15e963a3cf3a39.0p-71 */
> +T31 = -1.0407567231003314e-6,		/* -0x1176041e656869.0p-72 */
> +T33 =  3.4744117554063574e-7;		/*  0x1750fe732cab9c.0p-74 */
> +#endif /* LDBL_MANT_DIG == 64 */
> +
> +static inline long double
> +divl(long double a, long double b, long double c, long double d,
> +    long double e, long double f)
> +{
> +	long double inv, r;
> +	float fr, fw;
> +
> +	_2sumF(a, c);
> +	b = b + c;
> +	_2sumF(d, f);
> +	e = e + f;
> +
> +	inv = 1 / (d + e);
> +
> +	r = (a + b) * inv;
> +	fr = r;
> +	r = fr;
> +
> +	fw = d + e;
> +	e = d - fw + e;
> +	d = fw;
> +
> +	r = r + (a - d * r + b - e * r) * inv;
> +
> +	return r;
> +}
> +
> +long double
> +tanhl(long double x)
> +{
> +	long double hi,lo,s,x2,x4,z;
> +#if LDBL_MANT_DIG == 113
> +	double dx2;
> +#endif
> +	int16_t jx,ix;
> +
> +	GET_LDBL_EXPSIGN(jx,x);
> +	ix = jx&0x7fff;
> +
> +    /* x is INF or NaN */
> +	if(ix>=0x7fff) {
> +	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
> +	    else       return one/x-one;    /* tanh(NaN) = NaN */
> +	}
> +
> +	ENTERI();
> +
> +    /* |x| < 40 */
> +	if (ix < 0x4004 || fabsl(x) < 40) {	/* |x|<40 */
> +	    if (__predict_false(ix<BIAS-(LDBL_MANT_DIG+1)/2)) {	/* |x|<TINY */
> +		/* tanh(+-0) = +0; tanh(tiny) = tiny(-+) with inexact: */
> +		return (x == 0 ? x : (0x1p200 * x - x) * 0x1p-200);
> +	    }
> +	    if (ix<0x3ffd) {		/* |x|<0.25 */
> +		x2 = x*x;
> +#if LDBL_MANT_DIG == 64
> +		x4 = x2*x2;
> +		RETURNI(((T19*x2 + T17)*x4 + (T15*x2 + T13))*(x2*x*x2*x4*x4) +
> +		    ((T11*x2 + T9)*x4 + (T7*x2 + T5))*(x2*x*x2) +
> +		    T3*(x2*x) + x);
> +#elif LDBL_MANT_DIG == 113
> +		dx2 = x2;
> +#if 0
> +		RETURNI(((((((((((((((T33*dx2 + T31)*dx2 + T29)*dx2 + T27)*dx2 +
> +		    T25)*x2 + T23)*x2 + T21)*x2 + T19)*x2 + T17)*x2 +
> +		    T15)*x2 + T13)*x2 + T11)*x2 + T9)*x2 + T7)*x2 + T5)*
> +		    (x2*x*x2) +
> +		    T3*(x2*x) + x);
> +#else
> +		long double q = ((((((((((((((T33*dx2 + T31)*dx2 + T29)*dx2 + T27)*dx2 +
> +		    T25)*x2 + T23)*x2 + T21)*x2 + T19)*x2 + T17)*x2 +
> +		    T15)*x2 + T13)*x2 + T11)*x2 + T9)*x2 + T7)*x2 + T5)*
> +		    (x2*x*x2);
> +		RETURNI(q + T3*(x2*x) + x);
> +#endif
> +#endif
> +	    }
> +	    k_hexpl(2*fabsl(x), &hi, &lo);
> +	    if (ix<0x4001 && fabsl(x) < 1.5)	/* |x|<1.5 */
> +		z = divl(hi, lo, -0.5, hi, lo, 0.5);
> +	    else
> +		z = one - one/(lo+0.5+hi);
> +    /* |x| >= 40, return +-1 */
> +	} else {
> +	    z = one - tiny;		/* raise inexact flag */
> +	}
> +	s = 1;
> +	if (jx<0) s = -1;
> +	RETURNI(s*z);
> +}
> diff --git a/newlib/libm/ld/s_tanl.c b/newlib/libm/ld/s_tanl.c
> new file mode 100644
> index 000000000..0c5228ec8
> --- /dev/null
> +++ b/newlib/libm/ld/s_tanl.c
> @@ -0,0 +1,97 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * Limited testing on pseudorandom numbers drawn within [0:4e8] shows
> + * an accuracy of <= 1.5 ULP where 247024 values of x out of 40 million
> + * possibles resulted in tan(x) that exceeded 0.5 ULP (ie., 0.6%).
> + */
> +
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "math.h"
> +#include "math_private.h"
> +#if LDBL_MANT_DIG == 64
> +#include "../ld80/e_rem_pio2l.h"
> +#elif LDBL_MANT_DIG == 113
> +#include "../ld128/e_rem_pio2l.h"
> +#else
> +#error "Unsupported long double format"
> +#endif
> +
> +long double
> +tanl(long double x)
> +{
> +	union IEEEl2bits z;
> +	int e0, s;
> +	long double y[2];
> +	long double hi, lo;
> +
> +	z.e = x;
> +	s = z.bits.sign;
> +	z.bits.sign = 0;
> +
> +	/* If x = +-0 or x is subnormal, then tan(x) = x. */
> +	if (z.bits.exp == 0)
> +		return (x);
> +
> +	/* If x = NaN or Inf, then tan(x) = NaN. */
> +	if (z.bits.exp == 32767)
> +		return ((x - x) / (x - x));
> +
> +	ENTERI();
> +
> +	/* Optimize the case where x is already within range. */
> +	if (z.e < M_PI_4) {
> +		hi = __kernel_tanl(z.e, 0, 0);
> +		RETURNI(s ? -hi : hi);
> +	}
> +
> +	e0 = __ieee754_rem_pio2l(x, y);
> +	hi = y[0];
> +	lo = y[1];
> +
> +	switch (e0 & 3) {
> +	case 0:
> +	case 2:
> +	    hi = __kernel_tanl(hi, lo, 0);
> +	    break;
> +	case 1:
> +	case 3:
> +	    hi = __kernel_tanl(hi, lo, 1);
> +	    break;
> +	}
> +
> +	RETURNI(hi);
> +}
> diff --git a/newlib/libm/ld/s_truncl.c b/newlib/libm/ld/s_truncl.c
> new file mode 100644
> index 000000000..9e2b51132
> --- /dev/null
> +++ b/newlib/libm/ld/s_truncl.c
> @@ -0,0 +1,68 @@
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + *
> + * From: @(#)s_floor.c 5.1 93/09/24
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * truncl(x)
> + * Return x rounded toward 0 to integral value
> + * Method:
> + *	Bit twiddling.
> + * Exception:
> + *	Inexact flag raised if x not equal to truncl(x).
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +
> +#ifdef LDBL_IMPLICIT_NBIT
> +#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
> +#else
> +#define	MANH_SIZE	LDBL_MANH_SIZE
> +#endif
> +
> +static const long double huge = 1.0e300;
> +static const float zero[] = { 0.0, -0.0 };
> +
> +long double
> +truncl(long double x)
> +{
> +	union IEEEl2bits u = { .e = x };
> +	int e = u.bits.exp - LDBL_MAX_EXP + 1;
> +
> +	if (e < MANH_SIZE - 1) {
> +		if (e < 0) {			/* raise inexact if x != 0 */
> +			if (huge + x > 0.0)
> +				u.e = zero[u.bits.sign];
> +		} else {
> +			uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
> +			if (((u.bits.manh & m) | u.bits.manl) == 0)
> +				return (x);	/* x is integral */
> +			if (huge + x > 0.0) {	/* raise inexact flag */
> +				u.bits.manh &= ~m;
> +				u.bits.manl = 0;
> +			}
> +		}
> +	} else if (e < LDBL_MANT_DIG - 1) {
> +		uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
> +		if ((u.bits.manl & m) == 0)
> +			return (x);	/* x is integral */
> +		if (huge + x > 0.0)		/* raise inexact flag */
> +			u.bits.manl &= ~m;
> +	}
> +	return (u.e);
> +}
> diff --git a/newlib/libm/ld128/b_tgammal.c b/newlib/libm/ld128/b_tgammal.c
> new file mode 100644
> index 000000000..1c995ab6d
> --- /dev/null
> +++ b/newlib/libm/ld128/b_tgammal.c
> @@ -0,0 +1,57 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2013 David Chisnall
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <float.h>
> +#include <math.h>
> +
> +/*
> + * If long double is not the same size as double, then these will lose
> + * precision and we should emit a warning whenever something links against
> + * them.
> + */
> +#if (LDBL_MANT_DIG > 53)
> +#define WARN_IMPRECISE(x) \
> +	__warn_references(x, # x " has lower than advertised precision");
> +#else
> +#define WARN_IMPRECISE(x)
> +#endif
> +/*
> + * Declare the functions as weak variants so that other libraries providing
> + * real versions can override them.
> + */
> +#define	DECLARE_WEAK(x)\
> +	__weak_reference(imprecise_## x, x);\
> +	WARN_IMPRECISE(x)
> +
> +#define DECLARE_IMPRECISE(f) \
> +	long double imprecise_ ## f ## l(long double v) { return f(v); }\
> +	DECLARE_WEAK(f ## l)
> +
> +DECLARE_IMPRECISE(tgamma);
> diff --git a/newlib/libm/ld128/e_lgammal_r.c b/newlib/libm/ld128/e_lgammal_r.c
> new file mode 100644
> index 000000000..53d3af17d
> --- /dev/null
> +++ b/newlib/libm/ld128/e_lgammal_r.c
> @@ -0,0 +1,330 @@
> +/* @(#)e_lgamma_r.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_lgamma_r.c for complete comments.
> + *
> + * Converted to long double by Steven G. Kargl.
> + */
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const volatile double vzero = 0;
> +
> +static const double
> +zero=  0,
> +half=  0.5,
> +one =  1;
> +
> +static const long double
> +pi  =  3.14159265358979323846264338327950288e+00L;
> +/*
> + * Domain y in [0x1p-119, 0.28], range ~[-1.4065e-36, 1.4065e-36]:
> + * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-119.1
> + */
> +static const long double
> +a0  =  7.72156649015328606065120900824024296e-02L,
> +a1  =  3.22467033424113218236207583323018498e-01L,
> +a2  =  6.73523010531980951332460538330282217e-02L,
> +a3  =  2.05808084277845478790009252803463129e-02L,
> +a4  =  7.38555102867398526627292839296001626e-03L,
> +a5  =  2.89051033074152328576829509522483468e-03L,
> +a6  =  1.19275391170326097618357349881842913e-03L,
> +a7  =  5.09669524743042462515256340206203019e-04L,
> +a8  =  2.23154758453578096143609255559576017e-04L,
> +a9  =  9.94575127818397632126978731542755129e-05L,
> +a10 =  4.49262367375420471287545895027098145e-05L,
> +a11 =  2.05072127845117995426519671481628849e-05L,
> +a12 =  9.43948816959096748454087141447939513e-06L,
> +a13 =  4.37486780697359330303852050718287419e-06L,
> +a14 =  2.03920783892362558276037363847651809e-06L,
> +a15 =  9.55191070057967287877923073200324649e-07L,
> +a16 =  4.48993286185740853170657139487620560e-07L,
> +a17 =  2.13107543597620911675316728179563522e-07L,
> +a18 =  9.70745379855304499867546549551023473e-08L,
> +a19 =  5.61889970390290257926487734695402075e-08L,
> +a20 =  6.42739653024130071866684358960960951e-09L,
> +a21 =  3.34491062143649291746195612991870119e-08L,
> +a22 = -1.57068547394315223934653011440641472e-08L,
> +a23 =  1.30812825422415841213733487745200632e-08L;
> +/*
> + * Domain x in [tc-0.24, tc+0.28], range ~[-6.3201e-37, 6.3201e-37]:
> + * |(lgamma(x) - tf) - t(x - tc)| < 2**-120.3.
> + */
> +static const long double
> +tc  =  1.46163214496836234126265954232572133e+00L,
> +tf  = -1.21486290535849608095514557177691584e-01L,
> +tt  =  1.57061739945077675484237837992951704e-36L,
> +t0  = -1.99238329499314692728655623767019240e-36L,
> +t1  = -6.08453430711711404116887457663281416e-35L,
> +t2  =  4.83836122723810585213722380854828904e-01L,
> +t3  = -1.47587722994530702030955093950668275e-01L,
> +t4  =  6.46249402389127526561003464202671923e-02L,
> +t5  = -3.27885410884813055008502586863748063e-02L,
> +t6  =  1.79706751152103942928638276067164935e-02L,
> +t7  = -1.03142230366363872751602029672767978e-02L,
> +t8  =  6.10053602051788840313573150785080958e-03L,
> +t9  = -3.68456960831637325470641021892968954e-03L,
> +t10 =  2.25976482322181046611440855340968560e-03L,
> +t11 = -1.40225144590445082933490395950664961e-03L,
> +t12 =  8.78232634717681264035014878172485575e-04L,
> +t13 = -5.54194952796682301220684760591403899e-04L,
> +t14 =  3.51912956837848209220421213975000298e-04L,
> +t15 = -2.24653443695947456542669289367055542e-04L,
> +t16 =  1.44070395420840737695611929680511823e-04L,
> +t17 = -9.27609865550394140067059487518862512e-05L,
> +t18 =  5.99347334438437081412945428365433073e-05L,
> +t19 = -3.88458388854572825603964274134801009e-05L,
> +t20 =  2.52476631610328129217896436186551043e-05L,
> +t21 = -1.64508584981658692556994212457518536e-05L,
> +t22 =  1.07434583475987007495523340296173839e-05L,
> +t23 = -7.03070407519397260929482550448878399e-06L,
> +t24 =  4.60968590693753579648385629003100469e-06L,
> +t25 = -3.02765473778832036018438676945512661e-06L,
> +t26 =  1.99238771545503819972741288511303401e-06L,
> +t27 = -1.31281299822614084861868817951788579e-06L,
> +t28 =  8.60844432267399655055574642052370223e-07L,
> +t29 = -5.64535486432397413273248363550536374e-07L,
> +t30 =  3.99357783676275660934903139592727737e-07L,
> +t31 = -2.95849029193433121795495215869311610e-07L,
> +t32 =  1.37790144435073124976696250804940384e-07L;
> +/*
> + * Domain y in [-0.1, 0.232], range ~[-1.4046e-37, 1.4181e-37]:
> + * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-122.8
> + */
> +static const long double
> +u0  = -7.72156649015328606065120900824024311e-02L,
> +u1  =  4.24082772271938167430983113242482656e-01L,
> +u2  =  2.96194003481457101058321977413332171e+00L,
> +u3  =  6.49503267711258043997790983071543710e+00L,
> +u4  =  7.40090051288150177152835698948644483e+00L,
> +u5  =  4.94698036296756044610805900340723464e+00L,
> +u6  =  2.00194224610796294762469550684947768e+00L,
> +u7  =  4.82073087750608895996915051568834949e-01L,
> +u8  =  6.46694052280506568192333848437585427e-02L,
> +u9  =  4.17685526755100259316625348933108810e-03L,
> +u10 =  9.06361003550314327144119307810053410e-05L,
> +v1  =  5.15937098592887275994320496999951947e+00L,
> +v2  =  1.14068418766251486777604403304717558e+01L,
> +v3  =  1.41164839437524744055723871839748489e+01L,
> +v4  =  1.07170702656179582805791063277960532e+01L,
> +v5  =  5.14448694179047879915042998453632434e+00L,
> +v6  =  1.55210088094585540637493826431170289e+00L,
> +v7  =  2.82975732849424562719893657416365673e-01L,
> +v8  =  2.86424622754753198010525786005443539e-02L,
> +v9  =  1.35364253570403771005922441442688978e-03L,
> +v10 =  1.91514173702398375346658943749580666e-05L,
> +v11 = -3.25364686890242327944584691466034268e-08L;
> +/*
> + * Domain x in (2, 3], range ~[-1.3341e-36, 1.3536e-36]:
> + * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-120.1
> + * with y = x - 2.
> + */
> +static const long double
> +s0  = -7.72156649015328606065120900824024297e-02L,
> +s1  =  1.23221687850916448903914170805852253e-01L,
> +s2  =  5.43673188699937239808255378293820020e-01L,
> +s3  =  6.31998137119005233383666791176301800e-01L,
> +s4  =  3.75885340179479850993811501596213763e-01L,
> +s5  =  1.31572908743275052623410195011261575e-01L,
> +s6  =  2.82528453299138685507186287149699749e-02L,
> +s7  =  3.70262021550340817867688714880797019e-03L,
> +s8  =  2.83374000312371199625774129290973648e-04L,
> +s9  =  1.15091830239148290758883505582343691e-05L,
> +s10 =  2.04203474281493971326506384646692446e-07L,
> +s11 =  9.79544198078992058548607407635645763e-10L,
> +r1  =  2.58037466655605285937112832039537492e+00L,
> +r2  =  2.86289413392776399262513849911531180e+00L,
> +r3  =  1.78691044735267497452847829579514367e+00L,
> +r4  =  6.89400381446725342846854215600008055e-01L,
> +r5  =  1.70135865462567955867134197595365343e-01L,
> +r6  =  2.68794816183964420375498986152766763e-02L,
> +r7  =  2.64617234244861832870088893332006679e-03L,
> +r8  =  1.52881761239180800640068128681725702e-04L,
> +r9  =  4.63264813762296029824851351257638558e-06L,
> +r10 =  5.89461519146957343083848967333671142e-08L,
> +r11 =  1.79027678176582527798327441636552968e-10L;
> +/*
> + * Domain z in [8, 0x1p70], range ~[-9.8214e-35, 9.8214e-35]:
> + * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-113.0
> + */
> +static const long double
> +w0  =  4.18938533204672741780329736405617738e-01L,
> +w1  =  8.33333333333333333333333333332852026e-02L,
> +w2  = -2.77777777777777777777777727810123528e-03L,
> +w3  =  7.93650793650793650791708939493907380e-04L,
> +w4  = -5.95238095238095234390450004444370959e-04L,
> +w5  =  8.41750841750837633887817658848845695e-04L,
> +w6  = -1.91752691752396849943172337347259743e-03L,
> +w7  =  6.41025640880333069429106541459015557e-03L,
> +w8  = -2.95506530801732133437990433080327074e-02L,
> +w9  =  1.79644237328444101596766586979576927e-01L,
> +w10 = -1.39240539108367641920172649259736394e+00L,
> +w11 =  1.33987701479007233325288857758641761e+01L,
> +w12 = -1.56363596431084279780966590116006255e+02L,
> +w13 =  2.14830978044410267201172332952040777e+03L,
> +w14 = -3.28636067474227378352761516589092334e+04L,
> +w15 =  5.06201257747865138432663574251462485e+05L,
> +w16 = -6.79720123352023636706247599728048344e+06L,
> +w17 =  6.57556601705472106989497289465949255e+07L,
> +w18 = -3.26229058141181783534257632389415580e+08L;
> +
> +static long double
> +sin_pil(long double x)
> +{
> +	volatile long double vz;
> +	long double y,z;
> +	uint64_t lx, n;
> +	uint16_t hx;
> +
> +	y = -x;
> +
> +	vz = y+0x1.p112;
> +	z = vz-0x1.p112;
> +	if (z == y)
> +	    return zero;
> +
> +	vz = y+0x1.p110;
> +	EXTRACT_LDBL128_WORDS(hx,lx,n,vz);
> +	z = vz-0x1.p110;
> +	if (z > y) {
> +	    z -= 0.25;
> +	    n--;
> +	}
> +	n &= 7;
> +	y = y - z + n * 0.25;
> +
> +	switch (n) {
> +	    case 0:   y =  __kernel_sinl(pi*y,zero,0); break;
> +	    case 1:
> +	    case 2:   y =  __kernel_cosl(pi*(0.5-y),zero); break;
> +	    case 3:
> +	    case 4:   y =  __kernel_sinl(pi*(one-y),zero,0); break;
> +	    case 5:
> +	    case 6:   y = -__kernel_cosl(pi*(y-1.5),zero); break;
> +	    default:  y =  __kernel_sinl(pi*(y-2.0),zero,0); break;
> +	    }
> +	return -y;
> +}
> +
> +long double
> +lgammal_r(long double x, int *signgamp)
> +{
> +	long double nadj,p,p1,p2,p3,q,r,t,w,y,z;
> +	uint64_t llx,lx;
> +	int i;
> +	uint16_t hx,ix;
> +
> +	EXTRACT_LDBL128_WORDS(hx,lx,llx,x);
> +
> +    /* purge +-Inf and NaNs */
> +	*signgamp = 1;
> +	ix = hx&0x7fff;
> +	if(ix==0x7fff) return x*x;
> +
> +   /* purge +-0 and tiny arguments */
> +	*signgamp = 1-2*(hx>>15);
> +	if(ix<0x3fff-116) {		/* |x|<2**-(p+3), return -log(|x|) */
> +	    if((ix|lx|llx)==0)
> +		return one/vzero;
> +	    return -logl(fabsl(x));
> +	}
> +
> +    /* purge negative integers and start evaluation for other x < 0 */
> +	if(hx&0x8000) {
> +	    *signgamp = 1;
> +	    if(ix>=0x3fff+112) 		/* |x|>=2**(p-1), must be -integer */
> +		return one/vzero;
> +	    t = sin_pil(x);
> +	    if(t==zero) return one/vzero;
> +	    nadj = logl(pi/fabsl(t*x));
> +	    if(t<zero) *signgamp = -1;
> +	    x = -x;
> +	}
> +
> +    /* purge 1 and 2 */
> +	if((ix==0x3fff || ix==0x4000) && (lx|llx)==0) r = 0;
> +    /* for x < 2.0 */
> +	else if(ix<0x4000) {
> +	    if(x<=8.9999961853027344e-01) {
> +		r = -logl(x);
> +		if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
> +		else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
> +	  	else {y = x; i=2;}
> +	    } else {
> +		r = 0;
> +	        if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
> +	        else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
> +		else {y=x-1;i=2;}
> +	    }
> +	    switch(i) {
> +	      case 0:
> +		z = y*y;
> +		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*(a12+z*(a14+z*(a16+
> +		    z*(a18+z*(a20+z*a22))))))))));
> +		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*(a13+z*(a15+
> +		    z*(a17+z*(a19+z*(a21+z*a23)))))))))));
> +		p  = y*p1+p2;
> +		r  += p-y/2; break;
> +	      case 1:
> +		p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
> +		    y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
> +		    y*(t17+y*(t18+y*(t19+y*(t20+y*(t21+y*(t22+y*(t23+
> +		    y*(t24+y*(t25+y*(t26+y*(t27+y*(t28+y*(t29+y*(t30+
> +		    y*(t31+y*t32))))))))))))))))))))))))))))));
> +		r += tf + p; break;
> +	      case 2:
> +		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*(u6+y*(u7+
> +		    y*(u8+y*(u9+y*u10))))))))));
> +		p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*(v6+y*(v7+
> +		    y*(v8+y*(v9+y*(v10+y*v11))))))))));
> +		r += p1/p2-y/2;
> +	    }
> +	}
> +    /* x < 8.0 */
> +	else if(ix<0x4002) {
> +	    i = x;
> +	    y = x-i;
> +	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*(s6+y*(s7+y*(s8+
> +		y*(s9+y*(s10+y*s11)))))))))));
> +	    q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*(r7+y*(r8+
> +		y*(r9+y*(r10+y*r11))))))))));
> +	    r = y/2+p/q;
> +	    z = 1;	/* lgamma(1+s) = log(s) + lgamma(s) */
> +	    switch(i) {
> +	    case 7: z *= (y+6);		/* FALLTHRU */
> +	    case 6: z *= (y+5);		/* FALLTHRU */
> +	    case 5: z *= (y+4);		/* FALLTHRU */
> +	    case 4: z *= (y+3);		/* FALLTHRU */
> +	    case 3: z *= (y+2);		/* FALLTHRU */
> +		    r += logl(z); break;
> +	    }
> +    /* 8.0 <= x < 2**(p+3) */
> +	} else if (ix<0x3fff+116) {
> +	    t = logl(x);
> +	    z = one/x;
> +	    y = z*z;
> +	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*(w8+
> +		y*(w9+y*(w10+y*(w11+y*(w12+y*(w13+y*(w14+y*(w15+y*(w16+
> +		y*(w17+y*w18)))))))))))))))));
> +	    r = (x-half)*(t-one)+w;
> +    /* 2**(p+3) <= x <= inf */
> +	} else 
> +	    r =  x*(logl(x)-1);
> +	if(hx&0x8000) r = nadj - r;
> +	return r;
> +}
> diff --git a/newlib/libm/ld128/e_powl.c b/newlib/libm/ld128/e_powl.c
> new file mode 100644
> index 000000000..12b92a1a9
> --- /dev/null
> +++ b/newlib/libm/ld128/e_powl.c
> @@ -0,0 +1,443 @@
> +/*-
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +/*
> + * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/* powl(x,y) return x**y
> + *
> + *		      n
> + * Method:  Let x =  2   * (1+f)
> + *	1. Compute and return log2(x) in two pieces:
> + *		log2(x) = w1 + w2,
> + *	   where w1 has 113-53 = 60 bit trailing zeros.
> + *	2. Perform y*log2(x) = n+y' by simulating multi-precision
> + *	   arithmetic, where |y'|<=0.5.
> + *	3. Return x**y = 2**n*exp(y'*log2)
> + *
> + * Special cases:
> + *	1.  (anything) ** 0  is 1
> + *	2.  (anything) ** 1  is itself
> + *	3.  (anything) ** NAN is NAN
> + *	4.  NAN ** (anything except 0) is NAN
> + *	5.  +-(|x| > 1) **  +INF is +INF
> + *	6.  +-(|x| > 1) **  -INF is +0
> + *	7.  +-(|x| < 1) **  +INF is +0
> + *	8.  +-(|x| < 1) **  -INF is +INF
> + *	9.  +-1         ** +-INF is NAN
> + *	10. +0 ** (+anything except 0, NAN)               is +0
> + *	11. -0 ** (+anything except 0, NAN, odd integer)  is +0
> + *	12. +0 ** (-anything except 0, NAN)               is +INF
> + *	13. -0 ** (-anything except 0, NAN, odd integer)  is +INF
> + *	14. -0 ** (odd integer) = -( +0 ** (odd integer) )
> + *	15. +INF ** (+anything except 0,NAN) is +INF
> + *	16. +INF ** (-anything except 0,NAN) is +0
> + *	17. -INF ** (anything)  = -0 ** (-anything)
> + *	18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
> + *	19. (-anything except 0 and inf) ** (non-integer) is NAN
> + *
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <math.h>
> +
> +#include "math_private.h"
> +
> +static const long double bp[] = {
> +  1.0L,
> +  1.5L,
> +};
> +
> +/* log_2(1.5) */
> +static const long double dp_h[] = {
> +  0.0,
> +  5.8496250072115607565592654282227158546448E-1L
> +};
> +
> +/* Low part of log_2(1.5) */
> +static const long double dp_l[] = {
> +  0.0,
> +  1.0579781240112554492329533686862998106046E-16L
> +};
> +
> +static const long double zero = 0.0L,
> +  one = 1.0L,
> +  two = 2.0L,
> +  two113 = 1.0384593717069655257060992658440192E34L,
> +  huge = 1.0e3000L,
> +  tiny = 1.0e-3000L;
> +
> +/* 3/2 log x = 3 z + z^3 + z^3 (z^2 R(z^2))
> +   z = (x-1)/(x+1)
> +   1 <= x <= 1.25
> +   Peak relative error 2.3e-37 */
> +static const long double LN[] =
> +{
> + -3.0779177200290054398792536829702930623200E1L,
> +  6.5135778082209159921251824580292116201640E1L,
> + -4.6312921812152436921591152809994014413540E1L,
> +  1.2510208195629420304615674658258363295208E1L,
> + -9.9266909031921425609179910128531667336670E-1L
> +};
> +static const long double LD[] =
> +{
> + -5.129862866715009066465422805058933131960E1L,
> +  1.452015077564081884387441590064272782044E2L,
> + -1.524043275549860505277434040464085593165E2L,
> +  7.236063513651544224319663428634139768808E1L,
> + -1.494198912340228235853027849917095580053E1L
> +  /* 1.0E0 */
> +};
> +
> +/* exp(x) = 1 + x - x / (1 - 2 / (x - x^2 R(x^2)))
> +   0 <= x <= 0.5
> +   Peak relative error 5.7e-38  */
> +static const long double PN[] =
> +{
> +  5.081801691915377692446852383385968225675E8L,
> +  9.360895299872484512023336636427675327355E6L,
> +  4.213701282274196030811629773097579432957E4L,
> +  5.201006511142748908655720086041570288182E1L,
> +  9.088368420359444263703202925095675982530E-3L,
> +};
> +static const long double PD[] =
> +{
> +  3.049081015149226615468111430031590411682E9L,
> +  1.069833887183886839966085436512368982758E8L,
> +  8.259257717868875207333991924545445705394E5L,
> +  1.872583833284143212651746812884298360922E3L,
> +  /* 1.0E0 */
> +};
> +
> +static const long double
> +  /* ln 2 */
> +  lg2 = 6.9314718055994530941723212145817656807550E-1L,
> +  lg2_h = 6.9314718055994528622676398299518041312695E-1L,
> +  lg2_l = 2.3190468138462996154948554638754786504121E-17L,
> +  ovt = 8.0085662595372944372e-0017L,
> +  /* 2/(3*log(2)) */
> +  cp = 9.6179669392597560490661645400126142495110E-1L,
> +  cp_h = 9.6179669392597555432899980587535537779331E-1L,
> +  cp_l = 5.0577616648125906047157785230014751039424E-17L;
> +
> +long double
> +powl(long double x, long double y)
> +{
> +  long double z, ax, z_h, z_l, p_h, p_l;
> +  long double yy1, t1, t2, r, s, t, u, v, w;
> +  long double s2, s_h, s_l, t_h, t_l;
> +  int32_t i, j, k, yisint, n;
> +  u_int32_t ix, iy;
> +  int32_t hx, hy;
> +  ieee_quad_shape_type o, p, q;
> +
> +  p.value = x;
> +  hx = p.parts32.mswhi;
> +  ix = hx & 0x7fffffff;
> +
> +  q.value = y;
> +  hy = q.parts32.mswhi;
> +  iy = hy & 0x7fffffff;
> +
> +
> +  /* y==zero: x**0 = 1 */
> +  if ((iy | q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
> +    return one;
> +
> +  /* 1.0**y = 1; -1.0**+-Inf = 1 */
> +  if (x == one)
> +    return one;
> +  if (x == -1.0L && iy == 0x7fff0000
> +      && (q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
> +    return one;
> +
> +  /* +-NaN return x+y */
> +  if ((ix > 0x7fff0000)
> +      || ((ix == 0x7fff0000)
> +	  && ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) != 0))
> +      || (iy > 0x7fff0000)
> +      || ((iy == 0x7fff0000)
> +	  && ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) != 0)))
> +    return nan_mix(x, y);
> +
> +  /* determine if y is an odd int when x < 0
> +   * yisint = 0       ... y is not an integer
> +   * yisint = 1       ... y is an odd int
> +   * yisint = 2       ... y is an even int
> +   */
> +  yisint = 0;
> +  if (hx < 0)
> +    {
> +      if (iy >= 0x40700000)	/* 2^113 */
> +	yisint = 2;		/* even integer y */
> +      else if (iy >= 0x3fff0000)	/* 1.0 */
> +	{
> +	  if (floorl (y) == y)
> +	    {
> +	      z = 0.5 * y;
> +	      if (floorl (z) == z)
> +		yisint = 2;
> +	      else
> +		yisint = 1;
> +	    }
> +	}
> +    }
> +
> +  /* special value of y */
> +  if ((q.parts32.mswlo | q.parts32.lswhi | q.parts32.lswlo) == 0)
> +    {
> +      if (iy == 0x7fff0000)	/* y is +-inf */
> +	{
> +	  if (((ix - 0x3fff0000) | p.parts32.mswlo | p.parts32.lswhi |
> +	    p.parts32.lswlo) == 0)
> +	    return y - y;	/* +-1**inf is NaN */
> +	  else if (ix >= 0x3fff0000)	/* (|x|>1)**+-inf = inf,0 */
> +	    return (hy >= 0) ? y : zero;
> +	  else			/* (|x|<1)**-,+inf = inf,0 */
> +	    return (hy < 0) ? -y : zero;
> +	}
> +      if (iy == 0x3fff0000)
> +	{			/* y is  +-1 */
> +	  if (hy < 0)
> +	    return one / x;
> +	  else
> +	    return x;
> +	}
> +      if (hy == 0x40000000)
> +	return x * x;		/* y is  2 */
> +      if (hy == 0x3ffe0000)
> +	{			/* y is  0.5 */
> +	  if (hx >= 0)		/* x >= +0 */
> +	    return sqrtl (x);
> +	}
> +    }
> +
> +  ax = fabsl (x);
> +  /* special value of x */
> +  if ((p.parts32.mswlo | p.parts32.lswhi | p.parts32.lswlo) == 0)
> +    {
> +      if (ix == 0x7fff0000 || ix == 0 || ix == 0x3fff0000)
> +	{
> +	  z = ax;		/*x is +-0,+-inf,+-1 */
> +	  if (hy < 0)
> +	    z = one / z;	/* z = (1/|x|) */
> +	  if (hx < 0)
> +	    {
> +	      if (((ix - 0x3fff0000) | yisint) == 0)
> +		{
> +		  z = (z - z) / (z - z);	/* (-1)**non-int is NaN */
> +		}
> +	      else if (yisint == 1)
> +		z = -z;		/* (x<0)**odd = -(|x|**odd) */
> +	    }
> +	  return z;
> +	}
> +    }
> +
> +  /* (x<0)**(non-int) is NaN */
> +  if (((((u_int32_t) hx >> 31) - 1) | yisint) == 0)
> +    return (x - x) / (x - x);
> +
> +  /* |y| is huge.
> +     2^-16495 = 1/2 of smallest representable value.
> +     If (1 - 1/131072)^y underflows, y > 1.4986e9 */
> +  if (iy > 0x401d654b)
> +    {
> +      /* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
> +      if (iy > 0x407d654b)
> +	{
> +	  if (ix <= 0x3ffeffff)
> +	    return (hy < 0) ? huge * huge : tiny * tiny;
> +	  if (ix >= 0x3fff0000)
> +	    return (hy > 0) ? huge * huge : tiny * tiny;
> +	}
> +      /* over/underflow if x is not close to one */
> +      if (ix < 0x3ffeffff)
> +	return (hy < 0) ? huge * huge : tiny * tiny;
> +      if (ix > 0x3fff0000)
> +	return (hy > 0) ? huge * huge : tiny * tiny;
> +    }
> +
> +  n = 0;
> +  /* take care subnormal number */
> +  if (ix < 0x00010000)
> +    {
> +      ax *= two113;
> +      n -= 113;
> +      o.value = ax;
> +      ix = o.parts32.mswhi;
> +    }
> +  n += ((ix) >> 16) - 0x3fff;
> +  j = ix & 0x0000ffff;
> +  /* determine interval */
> +  ix = j | 0x3fff0000;		/* normalize ix */
> +  if (j <= 0x3988)
> +    k = 0;			/* |x|<sqrt(3/2) */
> +  else if (j < 0xbb67)
> +    k = 1;			/* |x|<sqrt(3)   */
> +  else
> +    {
> +      k = 0;
> +      n += 1;
> +      ix -= 0x00010000;
> +    }
> +
> +  o.value = ax;
> +  o.parts32.mswhi = ix;
> +  ax = o.value;
> +
> +  /* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
> +  u = ax - bp[k];		/* bp[0]=1.0, bp[1]=1.5 */
> +  v = one / (ax + bp[k]);
> +  s = u * v;
> +  s_h = s;
> +
> +  o.value = s_h;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  s_h = o.value;
> +  /* t_h=ax+bp[k] High */
> +  t_h = ax + bp[k];
> +  o.value = t_h;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  t_h = o.value;
> +  t_l = ax - (t_h - bp[k]);
> +  s_l = v * ((u - s_h * t_h) - s_h * t_l);
> +  /* compute log(ax) */
> +  s2 = s * s;
> +  u = LN[0] + s2 * (LN[1] + s2 * (LN[2] + s2 * (LN[3] + s2 * LN[4])));
> +  v = LD[0] + s2 * (LD[1] + s2 * (LD[2] + s2 * (LD[3] + s2 * (LD[4] + s2))));
> +  r = s2 * s2 * u / v;
> +  r += s_l * (s_h + s);
> +  s2 = s_h * s_h;
> +  t_h = 3.0 + s2 + r;
> +  o.value = t_h;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  t_h = o.value;
> +  t_l = r - ((t_h - 3.0) - s2);
> +  /* u+v = s*(1+...) */
> +  u = s_h * t_h;
> +  v = s_l * t_h + t_l * s;
> +  /* 2/(3log2)*(s+...) */
> +  p_h = u + v;
> +  o.value = p_h;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  p_h = o.value;
> +  p_l = v - (p_h - u);
> +  z_h = cp_h * p_h;		/* cp_h+cp_l = 2/(3*log2) */
> +  z_l = cp_l * p_h + p_l * cp + dp_l[k];
> +  /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
> +  t = (long double) n;
> +  t1 = (((z_h + z_l) + dp_h[k]) + t);
> +  o.value = t1;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  t1 = o.value;
> +  t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
> +
> +  /* s (sign of result -ve**odd) = -1 else = 1 */
> +  s = one;
> +  if (((((u_int32_t) hx >> 31) - 1) | (yisint - 1)) == 0)
> +    s = -one;			/* (-ve)**(odd int) */
> +
> +  /* split up y into yy1+y2 and compute (yy1+y2)*(t1+t2) */
> +  yy1 = y;
> +  o.value = yy1;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  yy1 = o.value;
> +  p_l = (y - yy1) * t1 + y * t2;
> +  p_h = yy1 * t1;
> +  z = p_l + p_h;
> +  o.value = z;
> +  j = o.parts32.mswhi;
> +  if (j >= 0x400d0000) /* z >= 16384 */
> +    {
> +      /* if z > 16384 */
> +      if (((j - 0x400d0000) | o.parts32.mswlo | o.parts32.lswhi |
> +	o.parts32.lswlo) != 0)
> +	return s * huge * huge;	/* overflow */
> +      else
> +	{
> +	  if (p_l + ovt > z - p_h)
> +	    return s * huge * huge;	/* overflow */
> +	}
> +    }
> +  else if ((j & 0x7fffffff) >= 0x400d01b9)	/* z <= -16495 */
> +    {
> +      /* z < -16495 */
> +      if (((j - 0xc00d01bc) | o.parts32.mswlo | o.parts32.lswhi |
> +	o.parts32.lswlo)
> +	  != 0)
> +	return s * tiny * tiny;	/* underflow */
> +      else
> +	{
> +	  if (p_l <= z - p_h)
> +	    return s * tiny * tiny;	/* underflow */
> +	}
> +    }
> +  /* compute 2**(p_h+p_l) */
> +  i = j & 0x7fffffff;
> +  k = (i >> 16) - 0x3fff;
> +  n = 0;
> +  if (i > 0x3ffe0000)
> +    {				/* if |z| > 0.5, set n = [z+0.5] */
> +      n = floorl (z + 0.5L);
> +      t = n;
> +      p_h -= t;
> +    }
> +  t = p_l + p_h;
> +  o.value = t;
> +  o.parts32.lswlo = 0;
> +  o.parts32.lswhi &= 0xf8000000;
> +  t = o.value;
> +  u = t * lg2_h;
> +  v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
> +  z = u + v;
> +  w = v - (z - u);
> +  /*  exp(z) */
> +  t = z * z;
> +  u = PN[0] + t * (PN[1] + t * (PN[2] + t * (PN[3] + t * PN[4])));
> +  v = PD[0] + t * (PD[1] + t * (PD[2] + t * (PD[3] + t)));
> +  t1 = z - t * u / v;
> +  r = (z * t1) / (t1 - two) - (w + z * w);
> +  z = one - (r - z);
> +  o.value = z;
> +  j = o.parts32.mswhi;
> +  j += (n << 16);
> +  if ((j >> 16) <= 0)
> +    z = scalbnl (z, n);	/* subnormal output */
> +  else
> +    {
> +      o.parts32.mswhi = j;
> +      z = o.value;
> +    }
> +  return s * z;
> +}
> diff --git a/newlib/libm/ld128/e_rem_pio2l.h b/newlib/libm/ld128/e_rem_pio2l.h
> new file mode 100644
> index 000000000..7516ced49
> --- /dev/null
> +++ b/newlib/libm/ld128/e_rem_pio2l.h
> @@ -0,0 +1,135 @@
> +/* From: @(#)e_rem_pio2.c 1.4 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/* ld128 version of __ieee754_rem_pio2l(x,y)
> + * 
> + * return the remainder of x rem pi/2 in y[0]+y[1] 
> + * use __kernel_rem_pio2()
> + */
> +
> +#include <float.h>
> +
> +#include "math.h"
> +#include "math_private.h"
> +#include "../ld/fpmath.h"
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +/*
> + * XXX need to verify that nonzero integer multiples of pi/2 within the
> + * range get no closer to a long double than 2**-140, or that
> + * ilogb(x) + ilogb(min_delta) < 45 - -140.
> + */
> +/*
> + * invpio2:  113 bits of 2/pi
> + * pio2_1:   first  68 bits of pi/2
> + * pio2_1t:  pi/2 - pio2_1
> + * pio2_2:   second 68 bits of pi/2
> + * pio2_2t:  pi/2 - (pio2_1+pio2_2)
> + * pio2_3:   third  68 bits of pi/2
> + * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
> + */
> +
> +static const double
> +zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
> +two24 =  1.67772160000000000000e+07; /* 0x41700000, 0x00000000 */
> +
> +static const long double
> +invpio2 =  6.3661977236758134307553505349005747e-01L,	/*  0x145f306dc9c882a53f84eafa3ea6a.0p-113 */
> +pio2_1  =  1.5707963267948966192292994253909555e+00L,	/*  0x1921fb54442d18469800000000000.0p-112 */
> +pio2_1t =  2.0222662487959507323996846200947577e-21L,	/*  0x13198a2e03707344a4093822299f3.0p-181 */
> +pio2_2  =  2.0222662487959507323994779168837751e-21L,	/*  0x13198a2e03707344a400000000000.0p-181 */
> +pio2_2t =  2.0670321098263988236496903051604844e-43L,	/*  0x127044533e63a0105df531d89cd91.0p-254 */
> +pio2_3  =  2.0670321098263988236499468110329591e-43L,	/*  0x127044533e63a0105e00000000000.0p-254 */
> +pio2_3t = -2.5650587247459238361625433492959285e-65L;	/* -0x159c4ec64ddaeb5f78671cbfb2210.0p-327 */
> +
> +static inline __always_inline int
> +__ieee754_rem_pio2l(long double x, long double *y)
> +{
> +	union IEEEl2bits u,u1;
> +	long double z,w,t,r,fn;
> +	double tx[5],ty[3];
> +	int64_t n;
> +	int e0,ex,i,j,nx;
> +	int16_t expsign;
> +
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	ex = expsign & 0x7fff;
> +	if (ex < BIAS + 45 || ex == BIAS + 45 &&
> +	    u.bits.manh < 0x921fb54442d1LL) {
> +	    /* |x| ~< 2^45*(pi/2), medium size */
> +	    /* TODO: use only double precision for fn, as in expl(). */
> +	    fn = rnintl(x * invpio2);
> +	    n  = i64rint(fn);
> +	    r  = x-fn*pio2_1;
> +	    w  = fn*pio2_1t;	/* 1st round good to 180 bit */
> +	    {
> +		union IEEEl2bits u2;
> +	        int ex1;
> +	        j  = ex;
> +	        y[0] = r-w; 
> +		u2.e = y[0];
> +		ex1 = u2.xbits.expsign & 0x7fff;
> +	        i = j-ex1;
> +	        if(i>51) {  /* 2nd iteration needed, good to 248 */
> +		    t  = r;
> +		    w  = fn*pio2_2;	
> +		    r  = t-w;
> +		    w  = fn*pio2_2t-((t-r)-w);	
> +		    y[0] = r-w;
> +		    u2.e = y[0];
> +		    ex1 = u2.xbits.expsign & 0x7fff;
> +		    i = j-ex1;
> +		    if(i>119) {	/* 3rd iteration need, 316 bits acc */
> +		    	t  = r;	/* will cover all possible cases */
> +		    	w  = fn*pio2_3;	
> +		    	r  = t-w;
> +		    	w  = fn*pio2_3t-((t-r)-w);	
> +		    	y[0] = r-w;
> +		    }
> +		}
> +	    }
> +	    y[1] = (r-y[0])-w;
> +	    return n;
> +	}
> +    /* 
> +     * all other (large) arguments
> +     */
> +	if(ex==0x7fff) {		/* x is inf or NaN */
> +	    y[0]=y[1]=x-x; return 0;
> +	}
> +    /* set z = scalbn(|x|,ilogb(x)-23) */
> +	u1.e = x;
> +	e0 = ex - BIAS - 23;		/* e0 = ilogb(|x|)-23; */
> +	u1.xbits.expsign = ex - e0;
> +	z = u1.e;
> +	for(i=0;i<4;i++) {
> +		tx[i] = (double)((int32_t)(z));
> +		z     = (z-tx[i])*two24;
> +	}
> +	tx[4] = z;
> +	nx = 5;
> +	while(tx[nx-1]==zero) nx--;	/* skip zero term */
> +	n  =  __kernel_rem_pio2(tx,ty,e0,nx,3);
> +	t = (long double)ty[2] + ty[1];
> +	r = t + ty[0];
> +	w = ty[0] - (r - t);
> +	if(expsign<0) {y[0] = -r; y[1] = -w; return -n;}
> +	y[0] = r; y[1] = w; return n;
> +}
> diff --git a/newlib/libm/ld128/invtrig.c b/newlib/libm/ld128/invtrig.c
> new file mode 100644
> index 000000000..ab93732c8
> --- /dev/null
> +++ b/newlib/libm/ld128/invtrig.c
> @@ -0,0 +1,102 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include "invtrig.h"
> +
> +/*
> + * asinl() and acosl()
> + */
> +const long double
> +pS0 =  1.66666666666666666666666666666700314e-01L,
> +pS1 = -7.32816946414566252574527475428622708e-01L,
> +pS2 =  1.34215708714992334609030036562143589e+00L,
> +pS3 = -1.32483151677116409805070261790752040e+00L,
> +pS4 =  7.61206183613632558824485341162121989e-01L,
> +pS5 = -2.56165783329023486777386833928147375e-01L,
> +pS6 =  4.80718586374448793411019434585413855e-02L,
> +pS7 = -4.42523267167024279410230886239774718e-03L,
> +pS8 =  1.44551535183911458253205638280410064e-04L,
> +pS9 = -2.10558957916600254061591040482706179e-07L,
> +qS1 = -4.84690167848739751544716485245697428e+00L,
> +qS2 =  9.96619113536172610135016921140206980e+00L,
> +qS3 = -1.13177895428973036660836798461641458e+01L,
> +qS4 =  7.74004374389488266169304117714658761e+00L,
> +qS5 = -3.25871986053534084709023539900339905e+00L,
> +qS6 =  8.27830318881232209752469022352928864e-01L,
> +qS7 = -1.18768052702942805423330715206348004e-01L,
> +qS8 =  8.32600764660522313269101537926539470e-03L,
> +qS9 = -1.99407384882605586705979504567947007e-04L;
> +
> +/*
> + * atanl()
> + */
> +const long double atanhi[] = {
> +	 4.63647609000806116214256231461214397e-01L,
> +	 7.85398163397448309615660845819875699e-01L,       
> +	 9.82793723247329067985710611014666038e-01L,       
> +	 1.57079632679489661923132169163975140e+00L,
> +};
> +
> +const long double atanlo[] = {
> +	 4.89509642257333492668618435220297706e-36L,
> +	 2.16795253253094525619926100651083806e-35L,
> +	-2.31288434538183565909319952098066272e-35L,
> +	 4.33590506506189051239852201302167613e-35L,
> +};
> +
> +const long double aT[] = {
> +	 3.33333333333333333333333333333333125e-01L,
> +	-1.99999999999999999999999999999180430e-01L,
> +	 1.42857142857142857142857142125269827e-01L,
> +	-1.11111111111111111111110834490810169e-01L,
> +	 9.09090909090909090908522355708623681e-02L,
> +	-7.69230769230769230696553844935357021e-02L,
> +	 6.66666666666666660390096773046256096e-02L,
> +	-5.88235294117646671706582985209643694e-02L,
> +	 5.26315789473666478515847092020327506e-02L,
> +	-4.76190476189855517021024424991436144e-02L,
> +	 4.34782608678695085948531993458097026e-02L,
> +	-3.99999999632663469330634215991142368e-02L,
> +	 3.70370363987423702891250829918659723e-02L,
> +	-3.44827496515048090726669907612335954e-02L,
> +	 3.22579620681420149871973710852268528e-02L,
> +	-3.03020767654269261041647570626778067e-02L,
> +	 2.85641979882534783223403715930946138e-02L,
> +	-2.69824879726738568189929461383741323e-02L,
> +	 2.54194698498808542954187110873675769e-02L,
> +	-2.35083879708189059926183138130183215e-02L,
> +	 2.04832358998165364349957325067131428e-02L,
> +	-1.54489555488544397858507248612362957e-02L,
> +	 8.64492360989278761493037861575248038e-03L,
> +	-2.58521121597609872727919154569765469e-03L,
> +};
> +
> +const long double pi_lo = 8.67181013012378102479704402604335225e-35L;
> diff --git a/newlib/libm/ld128/invtrig.h b/newlib/libm/ld128/invtrig.h
> new file mode 100644
> index 000000000..423b56847
> --- /dev/null
> +++ b/newlib/libm/ld128/invtrig.h
> @@ -0,0 +1,115 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +
> +#define	BIAS		(LDBL_MAX_EXP - 1)
> +#define	MANH_SIZE	(LDBL_MANH_SIZE + 1)
> +
> +/* Approximation thresholds. */
> +#define	ASIN_LINEAR	(BIAS - 56)	/* 2**-56 */
> +#define	ACOS_CONST	(BIAS - 113)	/* 2**-113 */
> +#define	ATAN_CONST	(BIAS + 113)	/* 2**113 */
> +#define	ATAN_LINEAR	(BIAS - 56)	/* 2**-56 */
> +
> +/* 0.95 */
> +#define	THRESH	((0xe666666666666666ULL>>(64-(MANH_SIZE-1)))|LDBL_NBIT)
> +
> +/* Constants shared by the long double inverse trig functions. */
> +#define	pS0	_ItL_pS0
> +#define	pS1	_ItL_pS1
> +#define	pS2	_ItL_pS2
> +#define	pS3	_ItL_pS3
> +#define	pS4	_ItL_pS4
> +#define	pS5	_ItL_pS5
> +#define	pS6	_ItL_pS6
> +#define	pS7	_ItL_pS7
> +#define	pS8	_ItL_pS8
> +#define	pS9	_ItL_pS9
> +#define	qS1	_ItL_qS1
> +#define	qS2	_ItL_qS2
> +#define	qS3	_ItL_qS3
> +#define	qS4	_ItL_qS4
> +#define	qS5	_ItL_qS5
> +#define	qS6	_ItL_qS6
> +#define	qS7	_ItL_qS7
> +#define	qS8	_ItL_qS8
> +#define	qS9	_ItL_qS9
> +#define	atanhi	_ItL_atanhi
> +#define	atanlo	_ItL_atanlo
> +#define	aT	_ItL_aT
> +#define	pi_lo	_ItL_pi_lo
> +
> +#define	pio2_hi	atanhi[3]
> +#define	pio2_lo	atanlo[3]
> +#define	pio4_hi	atanhi[1]
> +
> +/* Constants shared by the long double inverse trig functions. */
> +extern const long double pS0, pS1, pS2, pS3, pS4, pS5, pS6, pS7, pS8, pS9;
> +extern const long double qS1, qS2, qS3, qS4, qS5, qS6, qS7, qS8, qS9;
> +extern const long double atanhi[], atanlo[], aT[];
> +extern const long double pi_lo;
> +
> +static inline long double
> +P(long double x)
> +{
> +
> +	return (x * (pS0 + x * (pS1 + x * (pS2 + x * (pS3 + x * \
> +		(pS4 + x * (pS5 + x * (pS6 + x * (pS7 + x * (pS8 + x * \
> +		pS9))))))))));
> +}
> +
> +static inline long double
> +Q(long double x)
> +{
> +
> +	return (1.0 + x * (qS1 + x * (qS2 + x * (qS3 + x * (qS4 + x * \
> +		(qS5 + x * (qS6 + x * (qS7 + x * (qS8 + x * qS9)))))))));
> +}
> +
> +static inline long double
> +T_even(long double x)
> +{
> +
> +	return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * \
> +		(aT[8] + x * (aT[10] + x * (aT[12] + x * (aT[14] + x * \
> +		(aT[16] + x * (aT[18] + x * (aT[20] + x * aT[22])))))))))));
> +}
> +
> +static inline long double
> +T_odd(long double x)
> +{
> +
> +	return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * \
> +		(aT[9] + x * (aT[11] + x * (aT[13] + x * (aT[15] + x * \
> +		(aT[17] + x * (aT[19] + x * (aT[21] + x * aT[23])))))))))));
> +}
> diff --git a/newlib/libm/ld128/k_cosl.c b/newlib/libm/ld128/k_cosl.c
> new file mode 100644
> index 000000000..422357bf8
> --- /dev/null
> +++ b/newlib/libm/ld128/k_cosl.c
> @@ -0,0 +1,59 @@
> +/* From: @(#)k_cos.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld128 version of k_cos.c.  See ../src/k_cos.c for most comments.
> + */
> +
> +#include "math_private.h"
> +
> +/*
> + * Domain [-0.7854, 0.7854], range ~[-1.17e-39, 1.19e-39]:
> + * |cos(x) - c(x))| < 2**-129.3
> + *
> + * 113-bit precision requires more care than 64-bit precision, since
> + * simple methods give a minimax polynomial with coefficient for x^2
> + * that is 1 ulp below 0.5, but we want it to be precisely 0.5.  See
> + * ../ld80/k_cosl.c for more details.
> + */
> +static const double
> +one = 1.0;
> +static const long double
> +C1 =  4.16666666666666666666666666666666667e-02L,
> +C2 = -1.38888888888888888888888888888888834e-03L,
> +C3 =  2.48015873015873015873015873015446795e-05L,
> +C4 = -2.75573192239858906525573190949988493e-07L,
> +C5 =  2.08767569878680989792098886701451072e-09L,
> +C6 = -1.14707455977297247136657111139971865e-11L,
> +C7 =  4.77947733238738518870113294139830239e-14L,
> +C8 = -1.56192069685858079920640872925306403e-16L,
> +C9 =  4.11031762320473354032038893429515732e-19L,
> +C10= -8.89679121027589608738005163931958096e-22L,
> +C11=  1.61171797801314301767074036661901531e-24L,
> +C12= -2.46748624357670948912574279501044295e-27L;
> +
> +long double
> +__kernel_cosl(long double x, long double y)
> +{
> +	long double hz,z,r,w;
> +
> +	z  = x*x;
> +	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*(C7+
> +	    z*(C8+z*(C9+z*(C10+z*(C11+z*C12)))))))))));
> +	hz = 0.5*z;
> +	w  = one-hz;
> +	return w + (((one-w)-hz) + (z*r-x*y));
> +}
> diff --git a/newlib/libm/ld128/k_expl.h b/newlib/libm/ld128/k_expl.h
> new file mode 100644
> index 000000000..159338fe3
> --- /dev/null
> +++ b/newlib/libm/ld128/k_expl.h
> @@ -0,0 +1,324 @@
> +/* from: FreeBSD: head/lib/msun/ld128/s_expl.c 251345 2013-06-03 20:09:22Z kargl */
> +
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2009-2013 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld128 version of k_expl.h.  See ../ld80/s_expl.c for most comments.
> + *
> + * See ../src/e_exp.c and ../src/k_exp.h for precision-independent comments
> + * about the secondary kernels.
> + */
> +
> +#define	INTERVALS	128
> +#define	LOG2_INTERVALS	7
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const double
> +/*
> + * ln2/INTERVALS = L1+L2 (hi+lo decomposition for multiplication).  L1 must
> + * have at least 22 (= log2(|LDBL_MIN_EXP-extras|) + log2(INTERVALS)) lowest
> + * bits zero so that multiplication of it by n is exact.
> + */
> +INV_L = 1.8466496523378731e+2,		/*  0x171547652b82fe.0p-45 */
> +L2 = -1.0253670638894731e-29;		/* -0x1.9ff0342542fc3p-97 */
> +static const long double
> +/* 0x1.62e42fefa39ef35793c768000000p-8 */
> +L1 =  5.41521234812457272982212595914567508e-3L;
> +
> +/*
> + * XXX values in hex in comments have been lost (or were never present)
> + * from here.
> + */
> +static const long double
> +/*
> + * Domain [-0.002708, 0.002708], range ~[-2.4021e-38, 2.4234e-38]:
> + * |exp(x) - p(x)| < 2**-124.9
> + * (0.002708 is ln2/(2*INTERVALS) rounded up a little).
> + *
> + * XXX the coeffs aren't very carefully rounded, and I get 3.6 more bits.
> + */
> +A2  =  0.5,
> +A3  =  1.66666666666666666666666666651085500e-1L,
> +A4  =  4.16666666666666666666666666425885320e-2L,
> +A5  =  8.33333333333333333334522877160175842e-3L,
> +A6  =  1.38888888888888888889971139751596836e-3L;
> +
> +static const double
> +A7  =  1.9841269841269470e-4,		/*  0x1.a01a01a019f91p-13 */
> +A8  =  2.4801587301585286e-5,		/*  0x1.71de3ec75a967p-19 */
> +A9  =  2.7557324277411235e-6,		/*  0x1.71de3ec75a967p-19 */
> +A10 =  2.7557333722375069e-7;		/*  0x1.27e505ab56259p-22 */
> +
> +static const struct {
> +	/*
> +	 * hi must be rounded to at most 106 bits so that multiplication
> +	 * by r1 in expm1l() is exact, but it is rounded to 88 bits due to
> +	 * historical accidents.
> +	 *
> +	 * XXX it is wasteful to use long double for both hi and lo.  ld128
> +	 * exp2l() uses only float for lo (in a very differently organized
> +	 * table; ld80 exp2l() is different again.  It uses 2 doubles in a
> +	 * table organized like this one.  1 double and 1 float would
> +	 * suffice).  There are different packing/locality/alignment/caching
> +	 * problems with these methods.
> +	 *
> +	 * XXX C's bad %a format makes the bits unreadable.  They happen
> +	 * to all line up for the hi values 1 before the point and 88
> +	 * in 22 nybbles, but for the low values the nybbles are shifted
> +	 * randomly.
> +	 */
> +	long double	hi;
> +	long double	lo;
> +} tbl[INTERVALS] = {
> +	0x1p0L, 0x0p0L,
> +	0x1.0163da9fb33356d84a66aep0L, 0x3.36dcdfa4003ec04c360be2404078p-92L,
> +	0x1.02c9a3e778060ee6f7cacap0L, 0x4.f7a29bde93d70a2cabc5cb89ba10p-92L,
> +	0x1.04315e86e7f84bd738f9a2p0L, 0xd.a47e6ed040bb4bfc05af6455e9b8p-96L,
> +	0x1.059b0d31585743ae7c548ep0L, 0xb.68ca417fe53e3495f7df4baf84a0p-92L,
> +	0x1.0706b29ddf6ddc6dc403a8p0L, 0x1.d87b27ed07cb8b092ac75e311753p-88L,
> +	0x1.0874518759bc808c35f25cp0L, 0x1.9427fa2b041b2d6829d8993a0d01p-88L,
> +	0x1.09e3ecac6f3834521e060cp0L, 0x5.84d6b74ba2e023da730e7fccb758p-92L,
> +	0x1.0b5586cf9890f6298b92b6p0L, 0x1.1842a98364291408b3ceb0a2a2bbp-88L,
> +	0x1.0cc922b7247f7407b705b8p0L, 0x9.3dc5e8aac564e6fe2ef1d431fd98p-92L,
> +	0x1.0e3ec32d3d1a2020742e4ep0L, 0x1.8af6a552ac4b358b1129e9f966a4p-88L,
> +	0x1.0fb66affed31af232091dcp0L, 0x1.8a1426514e0b627bda694a400a27p-88L,
> +	0x1.11301d0125b50a4ebbf1aep0L, 0xd.9318ceac5cc47ab166ee57427178p-92L,
> +	0x1.12abdc06c31cbfb92bad32p0L, 0x4.d68e2f7270bdf7cedf94eb1cb818p-92L,
> +	0x1.1429aaea92ddfb34101942p0L, 0x1.b2586d01844b389bea7aedd221d4p-88L,
> +	0x1.15a98c8a58e512480d573cp0L, 0x1.d5613bf92a2b618ee31b376c2689p-88L,
> +	0x1.172b83c7d517adcdf7c8c4p0L, 0x1.0eb14a792035509ff7d758693f24p-88L,
> +	0x1.18af9388c8de9bbbf70b9ap0L, 0x3.c2505c97c0102e5f1211941d2840p-92L,
> +	0x1.1a35beb6fcb753cb698f68p0L, 0x1.2d1c835a6c30724d5cfae31b84e5p-88L,
> +	0x1.1bbe084045cd39ab1e72b4p0L, 0x4.27e35f9acb57e473915519a1b448p-92L,
> +	0x1.1d4873168b9aa7805b8028p0L, 0x9.90f07a98b42206e46166cf051d70p-92L,
> +	0x1.1ed5022fcd91cb8819ff60p0L, 0x1.121d1e504d36c47474c9b7de6067p-88L,
> +	0x1.2063b88628cd63b8eeb028p0L, 0x1.50929d0fc487d21c2b84004264dep-88L,
> +	0x1.21f49917ddc962552fd292p0L, 0x9.4bdb4b61ea62477caa1dce823ba0p-92L,
> +	0x1.2387a6e75623866c1fadb0p0L, 0x1.c15cb593b0328566902df69e4de2p-88L,
> +	0x1.251ce4fb2a63f3582ab7dep0L, 0x9.e94811a9c8afdcf796934bc652d0p-92L,
> +	0x1.26b4565e27cdd257a67328p0L, 0x1.d3b249dce4e9186ddd5ff44e6b08p-92L,
> +	0x1.284dfe1f5638096cf15cf0p0L, 0x3.ca0967fdaa2e52d7c8106f2e262cp-92L,
> +	0x1.29e9df51fdee12c25d15f4p0L, 0x1.a24aa3bca890ac08d203fed80a07p-88L,
> +	0x1.2b87fd0dad98ffddea4652p0L, 0x1.8fcab88442fdc3cb6de4519165edp-88L,
> +	0x1.2d285a6e4030b40091d536p0L, 0xd.075384589c1cd1b3e4018a6b1348p-92L,
> +	0x1.2ecafa93e2f5611ca0f45cp0L, 0x1.523833af611bdcda253c554cf278p-88L,
> +	0x1.306fe0a31b7152de8d5a46p0L, 0x3.05c85edecbc27343629f502f1af2p-92L,
> +	0x1.32170fc4cd8313539cf1c2p0L, 0x1.008f86dde3220ae17a005b6412bep-88L,
> +	0x1.33c08b26416ff4c9c8610cp0L, 0x1.96696bf95d1593039539d94d662bp-88L,
> +	0x1.356c55f929ff0c94623476p0L, 0x3.73af38d6d8d6f9506c9bbc93cbc0p-92L,
> +	0x1.371a7373aa9caa7145502ep0L, 0x1.4547987e3e12516bf9c699be432fp-88L,
> +	0x1.38cae6d05d86585a9cb0d8p0L, 0x1.bed0c853bd30a02790931eb2e8f0p-88L,
> +	0x1.3a7db34e59ff6ea1bc9298p0L, 0x1.e0a1d336163fe2f852ceeb134067p-88L,
> +	0x1.3c32dc313a8e484001f228p0L, 0xb.58f3775e06ab66353001fae9fca0p-92L,
> +	0x1.3dea64c12342235b41223ep0L, 0x1.3d773fba2cb82b8244267c54443fp-92L,
> +	0x1.3fa4504ac801ba0bf701aap0L, 0x4.1832fb8c1c8dbdff2c49909e6c60p-92L,
> +	0x1.4160a21f72e29f84325b8ep0L, 0x1.3db61fb352f0540e6ba05634413ep-88L,
> +	0x1.431f5d950a896dc7044394p0L, 0x1.0ccec81e24b0caff7581ef4127f7p-92L,
> +	0x1.44e086061892d03136f408p0L, 0x1.df019fbd4f3b48709b78591d5cb5p-88L,
> +	0x1.46a41ed1d005772512f458p0L, 0x1.229d97df404ff21f39c1b594d3a8p-88L,
> +	0x1.486a2b5c13cd013c1a3b68p0L, 0x1.062f03c3dd75ce8757f780e6ec99p-88L,
> +	0x1.4a32af0d7d3de672d8bcf4p0L, 0x6.f9586461db1d878b1d148bd3ccb8p-92L,
> +	0x1.4bfdad5362a271d4397afep0L, 0xc.42e20e0363ba2e159c579f82e4b0p-92L,
> +	0x1.4dcb299fddd0d63b36ef1ap0L, 0x9.e0cc484b25a5566d0bd5f58ad238p-92L,
> +	0x1.4f9b2769d2ca6ad33d8b68p0L, 0x1.aa073ee55e028497a329a7333dbap-88L,
> +	0x1.516daa2cf6641c112f52c8p0L, 0x4.d822190e718226177d7608d20038p-92L,
> +	0x1.5342b569d4f81df0a83c48p0L, 0x1.d86a63f4e672a3e429805b049465p-88L,
> +	0x1.551a4ca5d920ec52ec6202p0L, 0x4.34ca672645dc6c124d6619a87574p-92L,
> +	0x1.56f4736b527da66ecb0046p0L, 0x1.64eb3c00f2f5ab3d801d7cc7272dp-88L,
> +	0x1.58d12d497c7fd252bc2b72p0L, 0x1.43bcf2ec936a970d9cc266f0072fp-88L,
> +	0x1.5ab07dd48542958c930150p0L, 0x1.91eb345d88d7c81280e069fbdb63p-88L,
> +	0x1.5c9268a5946b701c4b1b80p0L, 0x1.6986a203d84e6a4a92f179e71889p-88L,
> +	0x1.5e76f15ad21486e9be4c20p0L, 0x3.99766a06548a05829e853bdb2b52p-92L,
> +	0x1.605e1b976dc08b076f592ap0L, 0x4.86e3b34ead1b4769df867b9c89ccp-92L,
> +	0x1.6247eb03a5584b1f0fa06ep0L, 0x1.d2da42bb1ceaf9f732275b8aef30p-88L,
> +	0x1.6434634ccc31fc76f8714cp0L, 0x4.ed9a4e41000307103a18cf7a6e08p-92L,
> +	0x1.66238825522249127d9e28p0L, 0x1.b8f314a337f4dc0a3adf1787ff74p-88L,
> +	0x1.68155d44ca973081c57226p0L, 0x1.b9f32706bfe4e627d809a85dcc66p-88L,
> +	0x1.6a09e667f3bcc908b2fb12p0L, 0x1.66ea957d3e3adec17512775099dap-88L,
> +	0x1.6c012750bdabeed76a9980p0L, 0xf.4f33fdeb8b0ecd831106f57b3d00p-96L,
> +	0x1.6dfb23c651a2ef220e2cbep0L, 0x1.bbaa834b3f11577ceefbe6c1c411p-92L,
> +	0x1.6ff7df9519483cf87e1b4ep0L, 0x1.3e213bff9b702d5aa477c12523cep-88L,
> +	0x1.71f75e8ec5f73dd2370f2ep0L, 0xf.0acd6cb434b562d9e8a20adda648p-92L,
> +	0x1.73f9a48a58173bd5c9a4e6p0L, 0x8.ab1182ae217f3a7681759553e840p-92L,
> +	0x1.75feb564267c8bf6e9aa32p0L, 0x1.a48b27071805e61a17b954a2dad8p-88L,
> +	0x1.780694fde5d3f619ae0280p0L, 0x8.58b2bb2bdcf86cd08e35fb04c0f0p-92L,
> +	0x1.7a11473eb0186d7d51023ep0L, 0x1.6cda1f5ef42b66977960531e821bp-88L,
> +	0x1.7c1ed0130c1327c4933444p0L, 0x1.937562b2dc933d44fc828efd4c9cp-88L,
> +	0x1.7e2f336cf4e62105d02ba0p0L, 0x1.5797e170a1427f8fcdf5f3906108p-88L,
> +	0x1.80427543e1a11b60de6764p0L, 0x9.a354ea706b8e4d8b718a672bf7c8p-92L,
> +	0x1.82589994cce128acf88afap0L, 0xb.34a010f6ad65cbbac0f532d39be0p-92L,
> +	0x1.8471a4623c7acce52f6b96p0L, 0x1.c64095370f51f48817914dd78665p-88L,
> +	0x1.868d99b4492ec80e41d90ap0L, 0xc.251707484d73f136fb5779656b70p-92L,
> +	0x1.88ac7d98a669966530bcdep0L, 0x1.2d4e9d61283ef385de170ab20f96p-88L,
> +	0x1.8ace5422aa0db5ba7c55a0p0L, 0x1.92c9bb3e6ed61f2733304a346d8fp-88L,
> +	0x1.8cf3216b5448bef2aa1cd0p0L, 0x1.61c55d84a9848f8c453b3ca8c946p-88L,
> +	0x1.8f1ae991577362b982745cp0L, 0x7.2ed804efc9b4ae1458ae946099d4p-92L,
> +	0x1.9145b0b91ffc588a61b468p0L, 0x1.f6b70e01c2a90229a4c4309ea719p-88L,
> +	0x1.93737b0cdc5e4f4501c3f2p0L, 0x5.40a22d2fc4af581b63e8326efe9cp-92L,
> +	0x1.95a44cbc8520ee9b483694p0L, 0x1.a0fc6f7c7d61b2b3a22a0eab2cadp-88L,
> +	0x1.97d829fde4e4f8b9e920f8p0L, 0x1.1e8bd7edb9d7144b6f6818084cc7p-88L,
> +	0x1.9a0f170ca07b9ba3109b8cp0L, 0x4.6737beb19e1eada6825d3c557428p-92L,
> +	0x1.9c49182a3f0901c7c46b06p0L, 0x1.1f2be58ddade50c217186c90b457p-88L,
> +	0x1.9e86319e323231824ca78ep0L, 0x6.4c6e010f92c082bbadfaf605cfd4p-92L,
> +	0x1.a0c667b5de564b29ada8b8p0L, 0xc.ab349aa0422a8da7d4512edac548p-92L,
> +	0x1.a309bec4a2d3358c171f76p0L, 0x1.0daad547fa22c26d168ea762d854p-88L,
> +	0x1.a5503b23e255c8b424491cp0L, 0xa.f87bc8050a405381703ef7caff50p-92L,
> +	0x1.a799e1330b3586f2dfb2b0p0L, 0x1.58f1a98796ce8908ae852236ca94p-88L,
> +	0x1.a9e6b5579fdbf43eb243bcp0L, 0x1.ff4c4c58b571cf465caf07b4b9f5p-88L,
> +	0x1.ac36bbfd3f379c0db966a2p0L, 0x1.1265fc73e480712d20f8597a8e7bp-88L,
> +	0x1.ae89f995ad3ad5e8734d16p0L, 0x1.73205a7fbc3ae675ea440b162d6cp-88L,
> +	0x1.b0e07298db66590842acdep0L, 0x1.c6f6ca0e5dcae2aafffa7a0554cbp-88L,
> +	0x1.b33a2b84f15faf6bfd0e7ap0L, 0x1.d947c2575781dbb49b1237c87b6ep-88L,
> +	0x1.b59728de559398e3881110p0L, 0x1.64873c7171fefc410416be0a6525p-88L,
> +	0x1.b7f76f2fb5e46eaa7b081ap0L, 0xb.53c5354c8903c356e4b625aacc28p-92L,
> +	0x1.ba5b030a10649840cb3c6ap0L, 0xf.5b47f297203757e1cc6eadc8bad0p-92L,
> +	0x1.bcc1e904bc1d2247ba0f44p0L, 0x1.b3d08cd0b20287092bd59be4ad98p-88L,
> +	0x1.bf2c25bd71e088408d7024p0L, 0x1.18e3449fa073b356766dfb568ff4p-88L,
> +	0x1.c199bdd85529c2220cb12ap0L, 0x9.1ba6679444964a36661240043970p-96L,
> +	0x1.c40ab5fffd07a6d14df820p0L, 0xf.1828a5366fd387a7bdd54cdf7300p-92L,
> +	0x1.c67f12e57d14b4a2137fd2p0L, 0xf.2b301dd9e6b151a6d1f9d5d5f520p-96L,
> +	0x1.c8f6d9406e7b511acbc488p0L, 0x5.c442ddb55820171f319d9e5076a8p-96L,
> +	0x1.cb720dcef90691503cbd1ep0L, 0x9.49db761d9559ac0cb6dd3ed599e0p-92L,
> +	0x1.cdf0b555dc3f9c44f8958ep0L, 0x1.ac51be515f8c58bdfb6f5740a3a4p-88L,
> +	0x1.d072d4a07897b8d0f22f20p0L, 0x1.a158e18fbbfc625f09f4cca40874p-88L,
> +	0x1.d2f87080d89f18ade12398p0L, 0x9.ea2025b4c56553f5cdee4c924728p-92L,
> +	0x1.d5818dcfba48725da05aeap0L, 0x1.66e0dca9f589f559c0876ff23830p-88L,
> +	0x1.d80e316c98397bb84f9d04p0L, 0x8.805f84bec614de269900ddf98d28p-92L,
> +	0x1.da9e603db3285708c01a5ap0L, 0x1.6d4c97f6246f0ec614ec95c99392p-88L,
> +	0x1.dd321f301b4604b695de3cp0L, 0x6.30a393215299e30d4fb73503c348p-96L,
> +	0x1.dfc97337b9b5eb968cac38p0L, 0x1.ed291b7225a944efd5bb5524b927p-88L,
> +	0x1.e264614f5a128a12761fa0p0L, 0x1.7ada6467e77f73bf65e04c95e29dp-88L,
> +	0x1.e502ee78b3ff6273d13014p0L, 0x1.3991e8f49659e1693be17ae1d2f9p-88L,
> +	0x1.e7a51fbc74c834b548b282p0L, 0x1.23786758a84f4956354634a416cep-88L,
> +	0x1.ea4afa2a490d9858f73a18p0L, 0xf.5db301f86dea20610ceee13eb7b8p-92L,
> +	0x1.ecf482d8e67f08db0312fap0L, 0x1.949cef462010bb4bc4ce72a900dfp-88L,
> +	0x1.efa1bee615a27771fd21a8p0L, 0x1.2dac1f6dd5d229ff68e46f27e3dfp-88L,
> +	0x1.f252b376bba974e8696fc2p0L, 0x1.6390d4c6ad5476b5162f40e1d9a9p-88L,
> +	0x1.f50765b6e4540674f84b76p0L, 0x2.862baff99000dfc4352ba29b8908p-92L,
> +	0x1.f7bfdad9cbe138913b4bfep0L, 0x7.2bd95c5ce7280fa4d2344a3f5618p-92L,
> +	0x1.fa7c1819e90d82e90a7e74p0L, 0xb.263c1dc060c36f7650b4c0f233a8p-92L,
> +	0x1.fd3c22b8f71f10975ba4b2p0L, 0x1.2bcf3a5e12d269d8ad7c1a4a8875p-88L
> +};
> +
> +/*
> + * Kernel for expl(x).  x must be finite and not tiny or huge.
> + * "tiny" is anything that would make us underflow (|A6*x^6| < ~LDBL_MIN).
> + * "huge" is anything that would make fn*L1 inexact (|x| > ~2**17*ln2).
> + */
> +static inline void
> +__k_expl(long double x, long double *hip, long double *lop, int *kp)
> +{
> +	long double q, r, r1, t;
> +	double dr, fn, r2;
> +	int n, n2;
> +
> +	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
> +	fn = rnint((double)x * INV_L);
> +	n = irint(fn);
> +	n2 = (unsigned)n % INTERVALS;
> +	/* Depend on the sign bit being propagated: */
> +	*kp = n >> LOG2_INTERVALS;
> +	r1 = x - fn * L1;
> +	r2 = fn * -L2;
> +	r = r1 + r2;
> +
> +	/* Evaluate expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */
> +	dr = r;
> +	q = r2 + r * r * (A2 + r * (A3 + r * (A4 + r * (A5 + r * (A6 +
> +	    dr * (A7 + dr * (A8 + dr * (A9 + dr * A10))))))));
> +	t = tbl[n2].lo + tbl[n2].hi;
> +	*hip = tbl[n2].hi;
> +	*lop = tbl[n2].lo + t * (q + r1);
> +}
> +
> +/*
> + * XXX: the rest of the functions are identical for ld80 and ld128.
> + * However, we should use scalbnl() for ld128, since long double
> + * multiplication was very slow on sparc64 and no new evaluation has
> + * been made for aarch64 and/or riscv.
> + */
> +
> +static inline void
> +k_hexpl(long double x, long double *hip, long double *lop)
> +{
> +	float twopkm1;
> +	int k;
> +
> +	__k_expl(x, hip, lop, &k);
> +	SET_FLOAT_WORD(twopkm1, 0x3f800000 + ((k - 1) << 23));
> +	*hip *= twopkm1;
> +	*lop *= twopkm1;
> +}
> +
> +static inline long double
> +hexpl(long double x)
> +{
> +	long double hi, lo, twopkm2;
> +	int k;
> +
> +	twopkm2 = 1;
> +	__k_expl(x, &hi, &lo, &k);
> +	SET_LDBL_EXPSIGN(twopkm2, BIAS + k - 2);
> +	return (lo + hi) * 2 * twopkm2;
> +}
> +
> +#ifdef _COMPLEX_H
> +/*
> + * See ../src/k_exp.c for details.
> + */
> +static inline long double complex
> +__ldexp_cexpl(long double complex z, int expt)
> +{
> +	long double c, exp_x, hi, lo, s;
> +	long double x, y, scale1, scale2;
> +	int half_expt, k;
> +
> +	x = creall(z);
> +	y = cimagl(z);
> +	__k_expl(x, &hi, &lo, &k);
> +
> +	exp_x = (lo + hi) * 0x1p16382L;
> +	expt += k - 16382;
> +
> +	scale1 = 1;
> +	half_expt = expt / 2;
> +	SET_LDBL_EXPSIGN(scale1, BIAS + half_expt);
> +	scale2 = 1;
> +	SET_LDBL_EXPSIGN(scale2, BIAS + expt - half_expt);
> +
> +	sincosl(y, &s, &c);
> +	return (CMPLXL(c * exp_x * scale1 * scale2,
> +	    s * exp_x * scale1 * scale2));
> +}
> +#endif /* _COMPLEX_H */
> diff --git a/newlib/libm/ld128/k_sinl.c b/newlib/libm/ld128/k_sinl.c
> new file mode 100644
> index 000000000..09472d65f
> --- /dev/null
> +++ b/newlib/libm/ld128/k_sinl.c
> @@ -0,0 +1,59 @@
> +/* From: @(#)k_sin.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld128 version of k_sin.c.  See ../src/k_sin.c for most comments.
> + */
> +
> +#include "math_private.h"
> +
> +static const double
> +half =  0.5;
> +
> +/*
> + * Domain [-0.7854, 0.7854], range ~[-1.53e-37, 1.659e-37]
> + * |sin(x)/x - s(x)| < 2**-122.1
> + *
> + * See ../ld80/k_cosl.c for more details about the polynomial.
> + */
> +static const long double
> +S1 = -0.16666666666666666666666666666666666606732416116558L,
> +S2 =  0.0083333333333333333333333333333331135404851288270047L,
> +S3 = -0.00019841269841269841269841269839935785325638310428717L,
> +S4 =  0.27557319223985890652557316053039946268333231205686e-5L,
> +S5 = -0.25052108385441718775048214826384312253862930064745e-7L,
> +S6 =  0.16059043836821614596571832194524392581082444805729e-9L,
> +S7 = -0.76471637318198151807063387954939213287488216303768e-12L,
> +S8 =  0.28114572543451292625024967174638477283187397621303e-14L;
> +
> +static const double
> +S9  = -0.82206352458348947812512122163446202498005154296863e-17,
> +S10 =  0.19572940011906109418080609928334380560135358385256e-19,
> +S11 = -0.38680813379701966970673724299207480965452616911420e-22,
> +S12 =  0.64038150078671872796678569586315881020659912139412e-25;
> +
> +long double
> +__kernel_sinl(long double x, long double y, int iy)
> +{
> +	long double z,r,v;
> +
> +	z	=  x*x;
> +	v	=  z*x;
> +	r	=  S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*(S8+
> +	    z*(S9+z*(S10+z*(S11+z*S12)))))))));
> +	if(iy==0) return x+v*(S1+z*r);
> +	else      return x-((z*(half*y-v*r)-y)-v*S1);
> +}
> diff --git a/newlib/libm/ld128/s_erfl.c b/newlib/libm/ld128/s_erfl.c
> new file mode 100644
> index 000000000..e29c9691f
> --- /dev/null
> +++ b/newlib/libm/ld128/s_erfl.c
> @@ -0,0 +1,329 @@
> +/* @(#)s_erf.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See s_erf.c for complete comments.
> + *
> + * Converted to long double by Steven G. Kargl.
> + */
> +#include <float.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* XXX Prevent compilers from erroneously constant folding these: */
> +static const volatile long double tiny = 0x1p-10000L;
> +
> +static const double
> +half= 0.5,
> +one = 1,
> +two = 2;
> +/*
> + * In the domain [0, 2**-40], only the first term in the power series
> + * expansion of erf(x) is used.  The magnitude of the first neglected
> + * terms is less than 2**-120.
> + */
> +static const long double
> +efx  =  1.28379167095512573896158903121545167e-01L,	/* 0xecbff6a7, 0x481dd788, 0xb64d21a8, 0xeb06fc3f */
> +efx8 =  1.02703333676410059116927122497236133e+00L,	/* 0xecbff6a7, 0x481dd788, 0xb64d21a8, 0xeb06ff3f */
> +/*
> + * Domain [0, 0.84375], range ~[-1.919e-38, 1.919e-38]:
> + * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-125.29
> + */
> +pp0  =  1.28379167095512573896158903121545167e-01L,	/* 0x3ffc06eb, 0xa8214db6, 0x88d71d48, 0xa7f6bfec */
> +pp1  = -3.14931554396568573802046931159683404e-01L,	/* 0xbffd427d, 0x6ada7263, 0x547eb096, 0x95f37463 */
> +pp2  = -5.27514920282183487103576956956725309e-02L,	/* 0xbffab023, 0xe5a271e3, 0xb0e79b01, 0x2f7ac962 */
> +pp3  = -1.13202828509005281355609495523452713e-02L,	/* 0xbff872f1, 0x6a5023a1, 0xe08b3884, 0x326af20f */
> +pp4  = -9.18626155872522453865998391206048506e-04L,	/* 0xbff4e19f, 0xea5fb024, 0x43247a37, 0xe430b06c */
> +pp5  = -7.87518862406176274922506447157284230e-05L,	/* 0xbff14a4f, 0x31a85fe0, 0x7fff2204, 0x09c49b37 */
> +pp6  = -3.42357944472240436548115331090560881e-06L,	/* 0xbfeccb81, 0x4b43c336, 0xcd2eb6c2, 0x903f2d87 */
> +pp7  = -1.37317432573890412634717890726745428e-07L,	/* 0xbfe826e3, 0x0e915eb6, 0x42aee414, 0xf7e36805 */
> +pp8  = -2.71115170113861755855049008732113726e-09L,	/* 0xbfe2749e, 0x2b94fd00, 0xecb4d166, 0x0efb91f8 */
> +pp9  = -3.37925756196555959454018189718117864e-11L,	/* 0xbfdc293e, 0x1d9060cb, 0xd043204a, 0x314cd7f0 */
> +qq1  =  4.76672625471551170489978555182449450e-01L,	/* 0x3ffde81c, 0xde6531f0, 0x76803bee, 0x526e29e9 */
> +qq2  =  1.06713144672281502058807525850732240e-01L,	/* 0x3ffbb518, 0xd7a6bb74, 0xcd9bdd33, 0x7601eee5 */
> +qq3  =  1.47747613127513761102189201923147490e-02L,	/* 0x3ff8e423, 0xae527e18, 0xf12cb447, 0x723b4749 */
> +qq4  =  1.39939377672028671891148770908874816e-03L,	/* 0x3ff56ed7, 0xba055d84, 0xc21b45c4, 0x388d1812 */
> +qq5  =  9.44302939359455241271983309378738276e-05L,	/* 0x3ff18c11, 0xc18c99a4, 0x86d0fe09, 0x46387b4c */
> +qq6  =  4.56199342312522842161301671745365650e-06L,	/* 0x3fed3226, 0x73421d05, 0x08875300, 0x32fa1432 */
> +qq7  =  1.53019260483764773845294600092361197e-07L,	/* 0x3fe8489b, 0x3a63f627, 0x2b9ad2ce, 0x26516e57 */
> +qq8  =  3.25542691121324805094777901250005508e-09L,	/* 0x3fe2bf6c, 0x26d93a29, 0x9142be7c, 0x9f1dd043 */
> +qq9  =  3.37405581964478060434410167262684979e-11L;	/* 0x3fdc28c8, 0xfb8fa1be, 0x10e57eec, 0xaa19e49f */
> +
> +static const long double
> +erx  =  8.42700792949714894142232424201210961e-01L,	/* 0x3ffeaf76, 0x7a741088, 0xb0000000, 0x00000000 */
> +/*
> + * Domain [0.84375, 1.25], range ~[-2.521e-36, 2.523e-36]:
> + * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-120.15
> + */
> +pa0  = -2.48010117891186017024438233323795897e-17L,	/* 0xbfc7c97f, 0x77812279, 0x6c877f22, 0xef4bfb2e */
> +pa1  =  4.15107497420594680894327969504526489e-01L,	/* 0x3ffda911, 0xf096fbc2, 0x55662005, 0x2337fa64 */
> +pa2  = -3.94180628087084846724448515851892609e-02L,	/* 0xbffa42e9, 0xab54528c, 0xad529da1, 0x6efc2af3 */
> +pa3  =  4.48897599625192107295954790681677462e-02L,	/* 0x3ffa6fbc, 0xa65edba1, 0x0e4cbcea, 0x73ef9a31 */
> +pa4  =  8.02069252143016600110972019232995528e-02L,	/* 0x3ffb4887, 0x0e8b548e, 0x3230b417, 0x11b553b3 */
> +pa5  = -1.02729816533435279443621120242391295e-02L,	/* 0xbff850a0, 0x041de3ee, 0xd5bca6c9, 0x4ef5f9f2 */
> +pa6  =  5.70777694530755634864821094419982095e-03L,	/* 0x3ff77610, 0x9b501e10, 0x4c978382, 0x742df68f */
> +pa7  =  1.22635150233075521018231779267077071e-03L,	/* 0x3ff5417b, 0x0e623682, 0x60327da0, 0x96b9219e */
> +pa8  =  5.36100234820204569428412542856666503e-04L,	/* 0x3ff41912, 0x27ceb4c1, 0x1d3298ec, 0x84ced627 */
> +pa9  = -1.97753571846365167177187858667583165e-04L,	/* 0xbff29eb8, 0x23f5bcf3, 0x15c83c46, 0xe4fda98b */
> +pa10 =  6.19333039900846970674794789568415105e-05L,	/* 0x3ff103c4, 0x60f88e46, 0xc0c9fb02, 0x13cc7fc1 */
> +pa11 = -5.40531400436645861492290270311751349e-06L,	/* 0xbfed6abe, 0x9665f8a8, 0xdd0ad3ba, 0xe5dc0ee3 */
> +qa1  =  9.05041313265490487793231810291907851e-01L,	/* 0x3ffecf61, 0x93340222, 0xe9930620, 0xc4e61168 */
> +qa2  =  6.79848064708886864767240880834868092e-01L,	/* 0x3ffe5c15, 0x0ba858dc, 0xf7900ae9, 0xfea1e09a */
> +qa3  =  4.04720609926471677581066689316516445e-01L,	/* 0x3ffd9e6f, 0x145e9b00, 0x6d8c1749, 0xd2928623 */
> +qa4  =  1.69183273898369996364661075664302225e-01L,	/* 0x3ffc5a7c, 0xc2a363c1, 0xd6c19097, 0xef9b4063 */
> +qa5  =  7.44476185988067992342479750486764248e-02L,	/* 0x3ffb30ef, 0xfc7259ef, 0x1bcbb089, 0x686dd62d */
> +qa6  =  2.02981172725892407200420389604788573e-02L,	/* 0x3ff94c90, 0x7976cb0e, 0x21e1d36b, 0x0f09ca2b */
> +qa7  =  6.94281866271607668268269403102277234e-03L,	/* 0x3ff7c701, 0x2b193250, 0xc5d46ecc, 0x374843d8 */
> +qa8  =  1.12952275469171559611651594706820034e-03L,	/* 0x3ff52818, 0xfd2a7c06, 0xd13e38fd, 0xda4b34f5 */
> +qa9  =  3.13736683241992737197226578597710179e-04L,	/* 0x3ff348fa, 0x0cb48d18, 0x051f849b, 0x135ccf74 */
> +qa10 =  1.17037675204033225470121134087771410e-05L,	/* 0x3fee88b6, 0x98f47704, 0xa5d8f8f2, 0xc6422e11 */
> +qa11 =  4.61312518293853991439362806880973592e-06L,	/* 0x3fed3594, 0xe31db94f, 0x3592b693, 0xed4386b4 */
> +qa12 = -1.02158572037456893687737553657431771e-06L;	/* 0xbfeb123a, 0xd60d9b1e, 0x1f6fdeb9, 0x7dc8410a */
> +/*
> + * Domain [1.25,2.85715], range ~[-2.922e-37,2.922e-37]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-121.36
> + */
> +static const long double
> +ra0  = -9.86494292470069009555706994426014461e-03L,	/* 0xbff84341, 0x239e8709, 0xe941b06a, 0xcb4b6ec5 */
> +ra1  = -1.13580436992565640457579040117568870e+00L,	/* 0xbfff22c4, 0x133f7c0d, 0x72d5e231, 0x2eb1ee3f */
> +ra2  = -4.89744330295291950661185707066921755e+01L,	/* 0xc00487cb, 0xa38b4fc2, 0xc136695b, 0xc1df8047 */
> +ra3  = -1.10766149300215937173768072715352140e+03L,	/* 0xc00914ea, 0x55e6beb3, 0xabc50e07, 0xb6e5664d */
> +ra4  = -1.49991031232170934967642795601952100e+04L,	/* 0xc00cd4b8, 0xd33243e6, 0xffbf6545, 0x3c57ef6e */
> +ra5  = -1.29805749738318462882524181556996692e+05L,	/* 0xc00ffb0d, 0xbfeed9b6, 0x5b2a3ff4, 0xe245bd3c */
> +ra6  = -7.42828497044940065828871976644647850e+05L,	/* 0xc0126ab5, 0x8fe7caca, 0x473352d9, 0xcd4e0c90 */
> +ra7  = -2.85637299581890734287995171242421106e+06L,	/* 0xc0145cad, 0xa7f76fe7, 0x3e358051, 0x1799f927 */
> +ra8  = -7.40674797129824999383748865571026084e+06L,	/* 0xc015c412, 0x6fe29c02, 0x298ad158, 0x7d24e45c */
> +ra9  = -1.28653420911930973914078724204151759e+07L,	/* 0xc016889e, 0x7c2eb0dc, 0x95d5863b, 0x0aa34dc3 */
> +ra10 = -1.47198163599330179552932489109452638e+07L,	/* 0xc016c136, 0x90b84923, 0xf9bcb497, 0x19bbd0f5 */
> +ra11 = -1.07812992258382800318665248311522624e+07L,	/* 0xc0164904, 0xe673a113, 0x35d7f079, 0xe13701f3 */
> +ra12 = -4.83545565681708642630419905537756076e+06L,	/* 0xc0152721, 0xfea094a8, 0x869eb39d, 0x413d6f13 */
> +ra13 = -1.23956521201673964822976917356685286e+06L,	/* 0xc0132ea0, 0xd3646baa, 0x2fe62b0d, 0xbae5ce85 */
> +ra14 = -1.62289333553652417591275333240371812e+05L,	/* 0xc0103cf8, 0xaab1e2d6, 0x4c25e014, 0x248d76ab */
> +ra15 = -8.82890392601176969729168894389833110e+03L,	/* 0xc00c13e7, 0x3b3d8f94, 0x6fbda6f6, 0xe7049a82 */
> +ra16 = -1.22591866337261720023681535568334619e+02L,	/* 0xc005ea5e, 0x12358891, 0xcfa712c5, 0x77f050d4 */
> +sa1  =  6.44508918884710829371852723353794047e+01L,	/* 0x400501cd, 0xb69a6c0f, 0x5716de14, 0x47161af6 */
> +sa2  =  1.76118475473171481523704824327358534e+03L,	/* 0x4009b84b, 0xd305829f, 0xc4c771b0, 0xbf1f7f9b */
> +sa3  =  2.69448346969488374857087646131950188e+04L,	/* 0x400da503, 0x56bacc05, 0x4fdba68d, 0x2cca27e6 */
> +sa4  =  2.56826633369941456778326497384543763e+05L,	/* 0x4010f59d, 0x51124428, 0x69c41de6, 0xbd0d5753 */
> +sa5  =  1.60647413092257206847700054645905859e+06L,	/* 0x40138834, 0xa2184244, 0x557a1bed, 0x68c9d556 */
> +sa6  =  6.76963075165099718574753447122393797e+06L,	/* 0x40159d2f, 0x7b01b0cc, 0x8bac9e95, 0x5d35d56e */
> +sa7  =  1.94295690905361884290986932493647741e+07L,	/* 0x40172878, 0xc1172d61, 0x3068501e, 0x2f3c71da */
> +sa8  =  3.79774781017759149060839255547073541e+07L,	/* 0x401821be, 0xc30d06fe, 0x410563d7, 0x032111fd */
> +sa9  =  5.00659831846029484248302236457727397e+07L,	/* 0x40187df9, 0x1f97a111, 0xc51d6ac2, 0x4b389793 */
> +sa10 =  4.36486287620506484276130525941972541e+07L,	/* 0x40184d03, 0x3a618ae0, 0x2a723357, 0xfa45c60a */
> +sa11 =  2.43779678791333894255510508253951934e+07L,	/* 0x401773fa, 0x6fe10ee2, 0xc467850d, 0xc6b7ff30 */
> +sa12 =  8.30732360384443202039372372212966542e+06L,	/* 0x4015fb09, 0xee6a5631, 0xdd98de7e, 0x8b00461a */
> +sa13 =  1.60160846942050515734192397495105693e+06L,	/* 0x40138704, 0x8782bf13, 0x5b8fb315, 0xa898abe5 */
> +sa14 =  1.54255505242533291014555153757001825e+05L,	/* 0x40102d47, 0xc0abc98e, 0x843c9490, 0xb4352440 */
> +sa15 =  5.87949220002375547561467275493888824e+03L,	/* 0x400b6f77, 0xe00d21d1, 0xec4d41e8, 0x2f8e1673 */
> +sa16 =  4.97272976346793193860385983372237710e+01L;	/* 0x40048dd1, 0x816c1b3f, 0x24f540a6, 0x4cfe03cc */
> +/*
> + * Domain [2.85715,9], range ~[-7.886e-37,7.918e-37]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-120
> + */
> +static const long double
> +rb0  = -9.86494292470008707171371994479162369e-3L, /* 0xbff84341, 0x239e86f4, 0x2f57e561, 0xf4469360 */
> +rb1  = -1.57047326624110727986326503729442830L,    /* 0xbfff920a, 0x8935bf73, 0x8803b894, 0x4656482d */
> +rb2  = -1.03228196364885474342132255440317065e2L,  /* 0xc0059ce9, 0xac4ed0ff, 0x2cff0ff7, 0x5e70d1ab */
> +rb3  = -3.74000570653418227179358710865224376e3L,  /* 0xc00ad380, 0x2ebf7835, 0xf6b07ed2, 0x861242f7 */
> +rb4  = -8.35435477739098044190860390632813956e4L,  /* 0xc00f4657, 0x8c3ae934, 0x3647d7b3, 0x80e76fb7 */
> +rb5  = -1.21398672055223642118716640216747152e6L,  /* 0xc0132862, 0x2b8761c8, 0x27d18c0f, 0x137c9463 */
> +rb6  = -1.17669175877248796101665344873273970e7L,  /* 0xc0166719, 0x0b2cea46, 0x81f14174, 0x11602ea5 */
> +rb7  = -7.66108006086998253606773064264599615e7L,  /* 0xc019243f, 0x3c26f4f0, 0x1cc05241, 0x3b953728 */
> +rb8  = -3.32547117558141845968704725353130804e8L,  /* 0xc01b3d24, 0x42d8ee26, 0x24ef6f3b, 0x604a8c65 */
> +rb9  = -9.41561252426350696802167711221739746e8L,  /* 0xc01cc0f8, 0xad23692a, 0x8ddb2310, 0xe9937145 */
> +rb10 = -1.67157110805390944549427329626281063e9L,  /* 0xc01d8e88, 0x9a903734, 0x09a55fa3, 0xd205c903 */
> +rb11 = -1.74339631004410841337645931421427373e9L,  /* 0xc01d9fa8, 0x77582d2a, 0xc183b8ab, 0x7e00cb05 */
> +rb12 = -9.57655233596934915727573141357471703e8L,  /* 0xc01cc8a5, 0x460cc685, 0xd0271fa0, 0x6a70e3da */
> +rb13 = -2.26320062731339353035254704082495066e8L,  /* 0xc01aafab, 0xd7d76721, 0xc9720e11, 0x6a8bd489 */
> +rb14 = -1.42777302996263256686002973851837039e7L,  /* 0xc016b3b8, 0xc499689f, 0x2b88d965, 0xc32414f9 */
> +sb1  =  1.08512869705594540211033733976348506e2L,  /* 0x4005b20d, 0x2db7528d, 0x00d20dcb, 0x858f6191 */
> +sb2  =  5.02757713761390460534494530537572834e3L,  /* 0x400b3a39, 0x3bf4a690, 0x3025d28d, 0xfd40a891 */
> +sb3  =  1.31019107205412870059331647078328430e5L,  /* 0x400fffcb, 0x1b71d05e, 0x3b28361d, 0x2a3c3690 */
> +sb4  =  2.13021555152296846166736757455018030e6L,  /* 0x40140409, 0x3c6984df, 0xc4491d7c, 0xb04aa08d */
> +sb5  =  2.26649105281820861953868568619768286e7L,  /* 0x401759d6, 0xce8736f0, 0xf28ad037, 0x2a901e0c */
> +sb6  =  1.61071939490875921812318684143076081e8L,  /* 0x401a3338, 0x686fb541, 0x6bd27d06, 0x4f95c9ac */
> +sb7  =  7.66895673844301852676056750497991966e8L,  /* 0x401c6daf, 0x31cec121, 0x54699126, 0x4bd9bf9e */
> +sb8  =  2.41884450436101936436023058196042526e9L,  /* 0x401e2059, 0x46b0b8d7, 0x87b64cbf, 0x78bc296d */
> +sb9  =  4.92403055884071695093305291535107666e9L,  /* 0x401f257e, 0xbe5ed739, 0x39e17346, 0xcadd2e55 */
> +sb10 =  6.18627786365587486459633615573786416e9L,  /* 0x401f70bb, 0x1be7a7e7, 0x6a45b5ae, 0x607c70f0 */
> +sb11 =  4.45898013426501378097430226324743199e9L,  /* 0x401f09c6, 0xa32643d7, 0xf1724620, 0x9ea46c32 */
> +sb12 =  1.63006115763329848117160344854224975e9L,  /* 0x401d84a3, 0x0996887f, 0x65a4f43b, 0x978c1d74 */
> +sb13 =  2.39216717012421697446304015847567721e8L,  /* 0x401ac845, 0x09a065c2, 0x30095da7, 0x9d72d6ae */
> +sb14 =  7.84837329009278694937250358810225609e6L;  /* 0x4015df06, 0xd5290e15, 0x63031fac, 0x4d9c894c */
> +/*
> + * Domain [9,108], range ~[-5.324e-38,5.340e-38]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - r(x)/s(x)| < 2**-124
> + */
> +static const long double
> +rc0  = -9.86494292470008707171367567652935673e-3L, /* 0xbff84341, 0x239e86f4, 0x2f57e55b, 0x1aa10fd3 */
> +rc1  = -1.26229447747315096406518846411562266L,    /* 0xbfff4325, 0xbb1aab28, 0xda395cd9, 0xfb861c15 */
> +rc2  = -6.13742634438922591780742637728666162e1L,  /* 0xc004eafe, 0x7dd51cd8, 0x3c7c5928, 0x751e50cf */
> +rc3  = -1.50455835478908280402912854338421517e3L,  /* 0xc0097823, 0xbc15b9ab, 0x3d60745c, 0x523e80a5 */
> +rc4  = -2.04415631865861549920184039902945685e4L,  /* 0xc00d3f66, 0x40b3fc04, 0x5388f2ec, 0xb009e1f0 */
> +rc5  = -1.57625662981714582753490610560037638e5L,  /* 0xc01033dc, 0xd4dc95b6, 0xfd4da93b, 0xf355b4a9 */
> +rc6  = -6.73473451616752528402917538033283794e5L,  /* 0xc01248d8, 0x2e73a4f9, 0xcded49c5, 0xfa3bfeb7 */
> +rc7  = -1.47433165421387483167186683764364857e6L,  /* 0xc01367f1, 0xba77a8f7, 0xcfdd0dbb, 0x25d554b3 */
> +rc8  = -1.38811981807868828563794929997744139e6L,  /* 0xc01352e5, 0x7d16d9ad, 0xbbdcbf38, 0x38fbc5ea */
> +rc9  = -3.59659700530831825640766479698155060e5L,  /* 0xc0115f3a, 0xecd57f45, 0x21f8ad6c, 0x910a5958 */
> +sc1  =  7.72730753022908298637508998072635696e1L,  /* 0x40053517, 0xa10d52bc, 0xdabb55b6, 0xbd0328cd */
> +sc2  =  2.36825757341694050500333261769082182e3L,  /* 0x400a2808, 0x3e0a9b42, 0x82977842, 0x9c5de29e */
> +sc3  =  3.72210540173034735352888847134073099e4L,  /* 0x400e22ca, 0x1ba827ef, 0xac8390d7, 0x1fc39a41 */
> +sc4  =  3.24136032646418336712461033591393412e5L,  /* 0x40113c8a, 0x0216e100, 0xc59d1e44, 0xf0e68d9d */
> +sc5  =  1.57836135851134393802505823370009175e6L,  /* 0x40138157, 0x95bc7664, 0x17575961, 0xdbe58eeb */
> +sc6  =  4.12881981392063738026679089714182355e6L,  /* 0x4014f801, 0x9e82e8d2, 0xb8b3a70e, 0xfd84185d */
> +sc7  =  5.24438427289213488410596395361544142e6L,  /* 0x40154017, 0x81177109, 0x2aa6c3b0, 0x1f106625 */
> +sc8  =  2.59909544563616121735963429710382149e6L,  /* 0x40143d45, 0xbb90a9b1, 0x12bf9390, 0xa827a700 */
> +sc9  =  2.80930665169282501639651995082335693e5L;  /* 0x40111258, 0xaa92222e, 0xa97e3216, 0xa237fa6c */
> +
> +long double
> +erfl(long double x)
> +{
> +	long double ax,R,S,P,Q,s,y,z,r;
> +	uint64_t lx, llx;
> +	int32_t i;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +
> +	if((hx & 0x7fff) == 0x7fff) {	/* erfl(nan)=nan */
> +		i = (hx>>15)<<1;
> +		return (1-i)+one/x;	/* erfl(+-inf)=+-1 */
> +	}
> +
> +	ax = fabsl(x);
> +	if(ax < 0.84375) {
> +	    if(ax < 0x1p-40L) {
> +	        if(ax < 0x1p-16373L)	
> +		    return (8*x+efx8*x)/8;	/* avoid spurious underflow */
> +		return x + efx*x;
> +	    }
> +	    z = x*x;
> +	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*(pp5+z*(pp6+z*(pp7+
> +		z*(pp8+z*pp9))))))));
> +	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*(qq6+z*(qq7+
> +		z*(qq8+z*qq9))))))));
> +	    y = r/s;
> +	    return x + x*y;
> +	}
> +	if(ax < 1.25) {
> +	    s = ax-one;
> +	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*(pa7+
> +		s*(pa8+s*(pa9+s*(pa10+s*pa11))))))))));
> +	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*(qa7+
> +		s*(qa8+s*(qa9+s*(qa10+s*(qa11+s*qa12)))))))))));
> +	    if(x>=0) return (erx + P/Q); else return (-erx - P/Q);
> +	}
> +	if (ax >= 9) {			/* inf>|x|>= 9 */
> +	    if(x>=0) return (one-tiny); else return (tiny-one);
> +	}
> +	s = one/(ax*ax);
> +	if(ax < 2.85715) {	/* |x| < 2.85715 */
> +	    R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
> +		s*(ra8+s*(ra9+s*(ra10+s*(ra11+s*(ra12+s*(ra13+s*(ra14+
> +		s*(ra15+s*ra16)))))))))))))));
> +	    S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
> +		s*(sa8+s*(sa9+s*(sa10+s*(sa11+s*(sa12+s*(sa13+s*(sa14+
> +		s*(sa15+s*sa16)))))))))))))));
> +	} else {	/* |x| >= 2.85715 */
> +	    R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*(rb7+
> +		s*(rb8+s*(rb9+s*(rb10+s*(rb11+s*(rb12+s*(rb13+
> +		s*rb14)))))))))))));
> +	    S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*(sb7+
> +		s*(sb8+s*(sb9+s*(sb10+s*(sb11+s*(sb12+s*(sb13+
> +		s*sb14)))))))))))));
> +	}
> +	z = (float)ax;
> +	r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
> +	if(x>=0) return (one-r/ax); else return (r/ax-one);
> +}
> +
> +long double
> +erfcl(long double x)
> +{
> +	long double ax,R,S,P,Q,s,y,z,r;
> +	uint64_t lx, llx;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +
> +	if((hx & 0x7fff) == 0x7fff) {	/* erfcl(nan)=nan */
> +					/* erfcl(+-inf)=0,2 */
> +	    return ((hx>>15)<<1)+one/x;
> +	}
> +
> +	ax = fabsl(x);
> +	if(ax < 0.84375L) {
> +	    if(ax < 0x1p-34L)
> +		return one-x;
> +	    z = x*x;
> +	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*(pp5+z*(pp6+z*(pp7+
> +		z*(pp8+z*pp9))))))));
> +	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*(qq6+z*(qq7+
> +		z*(qq8+z*qq9))))))));
> +	    y = r/s;
> +	    if(ax < 0.25L) {  	/* x<1/4 */
> +		return one-(x+x*y);
> +	    } else {
> +		r = x*y;
> +		r += (x-half);
> +	       return half - r;
> +	    }
> +	}
> +	if(ax < 1.25L) {
> +	    s = ax-one;
> +	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*(pa7+
> +		    s*(pa8+s*(pa9+s*(pa10+s*pa11))))))))));
> +	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*(qa7+
> +		    s*(qa8+s*(qa9+s*(qa10+s*(qa11+s*qa12)))))))))));
> +	    if(x>=0) {
> +	        z  = one-erx; return z - P/Q;
> +	    } else {
> +		z = erx+P/Q; return one+z;
> +	    }
> +	}
> +
> +	if(ax < 108) {			/* |x| < 108 */
> + 	    s = one/(ax*ax);
> +	    if(ax < 2.85715) {		/* |x| < 2.85715 */
> +	        R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
> +		    s*(ra8+s*(ra9+s*(ra10+s*(ra11+s*(ra12+s*(ra13+s*(ra14+
> +		    s*(ra15+s*ra16)))))))))))))));
> +	        S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
> +		    s*(sa8+s*(sa9+s*(sa10+s*(sa11+s*(sa12+s*(sa13+s*(sa14+
> +		    s*(sa15+s*sa16)))))))))))))));
> +	    } else if(ax < 9) {
> +		R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*(rb7+
> +		    s*(rb8+s*(rb9+s*(rb10+s*(rb11+s*(rb12+s*(rb13+
> +		    s*rb14)))))))))))));
> +		S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*(sb7+
> +		    s*(sb8+s*(sb9+s*(sb10+s*(sb11+s*(sb12+s*(sb13+
> +		    s*sb14)))))))))))));
> +	    } else {
> +		if(x < -9) return two-tiny;	/* x < -9 */
> +		R=rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*(rc5+s*(rc6+s*(rc7+
> +		    s*(rc8+s*rc9))))))));
> +		S=one+s*(sc1+s*(sc2+s*(sc3+s*(sc4+s*(sc5+s*(sc6+s*(sc7+
> +		    s*(sc8+s*sc9))))))));
> +	    }
> +	    z = (float)ax;
> +	    r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
> +	    if(x>0) return r/ax; else return two-r/ax;
> +	} else {
> +	    if(x>0) return tiny*tiny; else return two-tiny;
> +	}
> +}
> diff --git a/newlib/libm/ld128/s_exp2l.c b/newlib/libm/ld128/s_exp2l.c
> new file mode 100644
> index 000000000..ee3d2c782
> --- /dev/null
> +++ b/newlib/libm/ld128/s_exp2l.c
> @@ -0,0 +1,429 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +
> +#define	TBLBITS	7
> +#define	TBLSIZE	(1 << TBLBITS)
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +#define	EXPMASK	(BIAS + LDBL_MAX_EXP)
> +
> +static volatile long double
> +    huge      = 0x1p10000L,
> +    twom10000 = 0x1p-10000L;
> +
> +static const long double
> +    P1        = 0x1.62e42fefa39ef35793c7673007e6p-1L,
> +    P2	      = 0x1.ebfbdff82c58ea86f16b06ec9736p-3L,
> +    P3        = 0x1.c6b08d704a0bf8b33a762bad3459p-5L,
> +    P4        = 0x1.3b2ab6fba4e7729ccbbe0b4f3fc2p-7L,
> +    P5        = 0x1.5d87fe78a67311071dee13fd11d9p-10L,
> +    P6        = 0x1.430912f86c7876f4b663b23c5fe5p-13L;
> +
> +static const double
> +    P7        = 0x1.ffcbfc588b041p-17,
> +    P8        = 0x1.62c0223a5c7c7p-20,
> +    P9        = 0x1.b52541ff59713p-24,
> +    P10       = 0x1.e4cf56a391e22p-28,
> +    redux     = 0x1.8p112 / TBLSIZE;
> +
> +static const long double tbl[TBLSIZE] = {
> +	0x1.6a09e667f3bcc908b2fb1366dfeap-1L,
> +	0x1.6c012750bdabeed76a99800f4edep-1L,
> +	0x1.6dfb23c651a2ef220e2cbe1bc0d4p-1L,
> +	0x1.6ff7df9519483cf87e1b4f3e1e98p-1L,
> +	0x1.71f75e8ec5f73dd2370f2ef0b148p-1L,
> +	0x1.73f9a48a58173bd5c9a4e68ab074p-1L,
> +	0x1.75feb564267c8bf6e9aa33a489a8p-1L,
> +	0x1.780694fde5d3f619ae02808592a4p-1L,
> +	0x1.7a11473eb0186d7d51023f6ccb1ap-1L,
> +	0x1.7c1ed0130c1327c49334459378dep-1L,
> +	0x1.7e2f336cf4e62105d02ba1579756p-1L,
> +	0x1.80427543e1a11b60de67649a3842p-1L,
> +	0x1.82589994cce128acf88afab34928p-1L,
> +	0x1.8471a4623c7acce52f6b97c6444cp-1L,
> +	0x1.868d99b4492ec80e41d90ac2556ap-1L,
> +	0x1.88ac7d98a669966530bcdf2d4cc0p-1L,
> +	0x1.8ace5422aa0db5ba7c55a192c648p-1L,
> +	0x1.8cf3216b5448bef2aa1cd161c57ap-1L,
> +	0x1.8f1ae991577362b982745c72eddap-1L,
> +	0x1.9145b0b91ffc588a61b469f6b6a0p-1L,
> +	0x1.93737b0cdc5e4f4501c3f2540ae8p-1L,
> +	0x1.95a44cbc8520ee9b483695a0e7fep-1L,
> +	0x1.97d829fde4e4f8b9e920f91e8eb6p-1L,
> +	0x1.9a0f170ca07b9ba3109b8c467844p-1L,
> +	0x1.9c49182a3f0901c7c46b071f28dep-1L,
> +	0x1.9e86319e323231824ca78e64c462p-1L,
> +	0x1.a0c667b5de564b29ada8b8cabbacp-1L,
> +	0x1.a309bec4a2d3358c171f770db1f4p-1L,
> +	0x1.a5503b23e255c8b424491caf88ccp-1L,
> +	0x1.a799e1330b3586f2dfb2b158f31ep-1L,
> +	0x1.a9e6b5579fdbf43eb243bdff53a2p-1L,
> +	0x1.ac36bbfd3f379c0db966a3126988p-1L,
> +	0x1.ae89f995ad3ad5e8734d17731c80p-1L,
> +	0x1.b0e07298db66590842acdfc6fb4ep-1L,
> +	0x1.b33a2b84f15faf6bfd0e7bd941b0p-1L,
> +	0x1.b59728de559398e3881111648738p-1L,
> +	0x1.b7f76f2fb5e46eaa7b081ab53ff6p-1L,
> +	0x1.ba5b030a10649840cb3c6af5b74cp-1L,
> +	0x1.bcc1e904bc1d2247ba0f45b3d06cp-1L,
> +	0x1.bf2c25bd71e088408d7025190cd0p-1L,
> +	0x1.c199bdd85529c2220cb12a0916bap-1L,
> +	0x1.c40ab5fffd07a6d14df820f17deap-1L,
> +	0x1.c67f12e57d14b4a2137fd20f2a26p-1L,
> +	0x1.c8f6d9406e7b511acbc48805c3f6p-1L,
> +	0x1.cb720dcef90691503cbd1e949d0ap-1L,
> +	0x1.cdf0b555dc3f9c44f8958fac4f12p-1L,
> +	0x1.d072d4a07897b8d0f22f21a13792p-1L,
> +	0x1.d2f87080d89f18ade123989ea50ep-1L,
> +	0x1.d5818dcfba48725da05aeb66dff8p-1L,
> +	0x1.d80e316c98397bb84f9d048807a0p-1L,
> +	0x1.da9e603db3285708c01a5b6d480cp-1L,
> +	0x1.dd321f301b4604b695de3c0630c0p-1L,
> +	0x1.dfc97337b9b5eb968cac39ed284cp-1L,
> +	0x1.e264614f5a128a12761fa17adc74p-1L,
> +	0x1.e502ee78b3ff6273d130153992d0p-1L,
> +	0x1.e7a51fbc74c834b548b2832378a4p-1L,
> +	0x1.ea4afa2a490d9858f73a18f5dab4p-1L,
> +	0x1.ecf482d8e67f08db0312fb949d50p-1L,
> +	0x1.efa1bee615a27771fd21a92dabb6p-1L,
> +	0x1.f252b376bba974e8696fc3638f24p-1L,
> +	0x1.f50765b6e4540674f84b762861a6p-1L,
> +	0x1.f7bfdad9cbe138913b4bfe72bd78p-1L,
> +	0x1.fa7c1819e90d82e90a7e74b26360p-1L,
> +	0x1.fd3c22b8f71f10975ba4b32bd006p-1L,
> +	0x1.0000000000000000000000000000p+0L,
> +	0x1.0163da9fb33356d84a66ae336e98p+0L,
> +	0x1.02c9a3e778060ee6f7caca4f7a18p+0L,
> +	0x1.04315e86e7f84bd738f9a20da442p+0L,
> +	0x1.059b0d31585743ae7c548eb68c6ap+0L,
> +	0x1.0706b29ddf6ddc6dc403a9d87b1ep+0L,
> +	0x1.0874518759bc808c35f25d942856p+0L,
> +	0x1.09e3ecac6f3834521e060c584d5cp+0L,
> +	0x1.0b5586cf9890f6298b92b7184200p+0L,
> +	0x1.0cc922b7247f7407b705b893dbdep+0L,
> +	0x1.0e3ec32d3d1a2020742e4f8af794p+0L,
> +	0x1.0fb66affed31af232091dd8a169ep+0L,
> +	0x1.11301d0125b50a4ebbf1aed9321cp+0L,
> +	0x1.12abdc06c31cbfb92bad324d6f84p+0L,
> +	0x1.1429aaea92ddfb34101943b2588ep+0L,
> +	0x1.15a98c8a58e512480d573dd562aep+0L,
> +	0x1.172b83c7d517adcdf7c8c50eb162p+0L,
> +	0x1.18af9388c8de9bbbf70b9a3c269cp+0L,
> +	0x1.1a35beb6fcb753cb698f692d2038p+0L,
> +	0x1.1bbe084045cd39ab1e72b442810ep+0L,
> +	0x1.1d4873168b9aa7805b8028990be8p+0L,
> +	0x1.1ed5022fcd91cb8819ff61121fbep+0L,
> +	0x1.2063b88628cd63b8eeb0295093f6p+0L,
> +	0x1.21f49917ddc962552fd29294bc20p+0L,
> +	0x1.2387a6e75623866c1fadb1c159c0p+0L,
> +	0x1.251ce4fb2a63f3582ab7de9e9562p+0L,
> +	0x1.26b4565e27cdd257a673281d3068p+0L,
> +	0x1.284dfe1f5638096cf15cf03c9fa0p+0L,
> +	0x1.29e9df51fdee12c25d15f5a25022p+0L,
> +	0x1.2b87fd0dad98ffddea46538fca24p+0L,
> +	0x1.2d285a6e4030b40091d536d0733ep+0L,
> +	0x1.2ecafa93e2f5611ca0f45d5239a4p+0L,
> +	0x1.306fe0a31b7152de8d5a463063bep+0L,
> +	0x1.32170fc4cd8313539cf1c3009330p+0L,
> +	0x1.33c08b26416ff4c9c8610d96680ep+0L,
> +	0x1.356c55f929ff0c94623476373be4p+0L,
> +	0x1.371a7373aa9caa7145502f45452ap+0L,
> +	0x1.38cae6d05d86585a9cb0d9bed530p+0L,
> +	0x1.3a7db34e59ff6ea1bc9299e0a1fep+0L,
> +	0x1.3c32dc313a8e484001f228b58cf0p+0L,
> +	0x1.3dea64c12342235b41223e13d7eep+0L,
> +	0x1.3fa4504ac801ba0bf701aa417b9cp+0L,
> +	0x1.4160a21f72e29f84325b8f3dbacap+0L,
> +	0x1.431f5d950a896dc704439410b628p+0L,
> +	0x1.44e086061892d03136f409df0724p+0L,
> +	0x1.46a41ed1d005772512f459229f0ap+0L,
> +	0x1.486a2b5c13cd013c1a3b69062f26p+0L,
> +	0x1.4a32af0d7d3de672d8bcf46f99b4p+0L,
> +	0x1.4bfdad5362a271d4397afec42e36p+0L,
> +	0x1.4dcb299fddd0d63b36ef1a9e19dep+0L,
> +	0x1.4f9b2769d2ca6ad33d8b69aa0b8cp+0L,
> +	0x1.516daa2cf6641c112f52c84d6066p+0L,
> +	0x1.5342b569d4f81df0a83c49d86bf4p+0L,
> +	0x1.551a4ca5d920ec52ec620243540cp+0L,
> +	0x1.56f4736b527da66ecb004764e61ep+0L,
> +	0x1.58d12d497c7fd252bc2b7343d554p+0L,
> +	0x1.5ab07dd48542958c93015191e9a8p+0L,
> +	0x1.5c9268a5946b701c4b1b81697ed4p+0L,
> +	0x1.5e76f15ad21486e9be4c20399d12p+0L,
> +	0x1.605e1b976dc08b076f592a487066p+0L,
> +	0x1.6247eb03a5584b1f0fa06fd2d9eap+0L,
> +	0x1.6434634ccc31fc76f8714c4ee122p+0L,
> +	0x1.66238825522249127d9e29b92ea2p+0L,
> +	0x1.68155d44ca973081c57227b9f69ep+0L,
> +};
> +
> +static const float eps[TBLSIZE] = {
> +	-0x1.5c50p-101,
> +	-0x1.5d00p-106,
> +	 0x1.8e90p-102,
> +	-0x1.5340p-103,
> +	 0x1.1bd0p-102,
> +	-0x1.4600p-105,
> +	-0x1.7a40p-104,
> +	 0x1.d590p-102,
> +	-0x1.d590p-101,
> +	 0x1.b100p-103,
> +	-0x1.0d80p-105,
> +	 0x1.6b00p-103,
> +	-0x1.9f00p-105,
> +	 0x1.c400p-103,
> +	 0x1.e120p-103,
> +	-0x1.c100p-104,
> +	-0x1.9d20p-103,
> +	 0x1.a800p-108,
> +	 0x1.4c00p-106,
> +	-0x1.9500p-106,
> +	 0x1.6900p-105,
> +	-0x1.29d0p-100,
> +	 0x1.4c60p-103,
> +	 0x1.13a0p-102,
> +	-0x1.5b60p-103,
> +	-0x1.1c40p-103,
> +	 0x1.db80p-102,
> +	 0x1.91a0p-102,
> +	 0x1.dc00p-105,
> +	 0x1.44c0p-104,
> +	 0x1.9710p-102,
> +	 0x1.8760p-103,
> +	-0x1.a720p-103,
> +	 0x1.ed20p-103,
> +	-0x1.49c0p-102,
> +	-0x1.e000p-111,
> +	 0x1.86a0p-103,
> +	 0x1.2b40p-103,
> +	-0x1.b400p-108,
> +	 0x1.1280p-99,
> +	-0x1.02d8p-102,
> +	-0x1.e3d0p-103,
> +	-0x1.b080p-105,
> +	-0x1.f100p-107,
> +	-0x1.16c0p-105,
> +	-0x1.1190p-103,
> +	-0x1.a7d2p-100,
> +	 0x1.3450p-103,
> +	-0x1.67c0p-105,
> +	 0x1.4b80p-104,
> +	-0x1.c4e0p-103,
> +	 0x1.6000p-108,
> +	-0x1.3f60p-105,
> +	 0x1.93f0p-104,
> +	 0x1.5fe0p-105,
> +	 0x1.6f80p-107,
> +	-0x1.7600p-106,
> +	 0x1.21e0p-106,
> +	-0x1.3a40p-106,
> +	-0x1.40c0p-104,
> +	-0x1.9860p-105,
> +	-0x1.5d40p-108,
> +	-0x1.1d70p-106,
> +	 0x1.2760p-105,
> +	 0x0.0000p+0,
> +	 0x1.21e2p-104,
> +	-0x1.9520p-108,
> +	-0x1.5720p-106,
> +	-0x1.4810p-106,
> +	-0x1.be00p-109,
> +	 0x1.0080p-105,
> +	-0x1.5780p-108,
> +	-0x1.d460p-105,
> +	-0x1.6140p-105,
> +	 0x1.4630p-104,
> +	 0x1.ad50p-103,
> +	 0x1.82e0p-105,
> +	 0x1.1d3cp-101,
> +	 0x1.6100p-107,
> +	 0x1.ec30p-104,
> +	 0x1.f200p-108,
> +	 0x1.0b40p-103,
> +	 0x1.3660p-102,
> +	 0x1.d9d0p-103,
> +	-0x1.02d0p-102,
> +	 0x1.b070p-103,
> +	 0x1.b9c0p-104,
> +	-0x1.01c0p-103,
> +	-0x1.dfe0p-103,
> +	 0x1.1b60p-104,
> +	-0x1.ae94p-101,
> +	-0x1.3340p-104,
> +	 0x1.b3d8p-102,
> +	-0x1.6e40p-105,
> +	-0x1.3670p-103,
> +	 0x1.c140p-104,
> +	 0x1.1840p-101,
> +	 0x1.1ab0p-102,
> +	-0x1.a400p-104,
> +	 0x1.1f00p-104,
> +	-0x1.7180p-103,
> +	 0x1.4ce0p-102,
> +	 0x1.9200p-107,
> +	-0x1.54c0p-103,
> +	 0x1.1b80p-105,
> +	-0x1.1828p-101,
> +	 0x1.5720p-102,
> +	-0x1.a060p-100,
> +	 0x1.9160p-102,
> +	 0x1.a280p-104,
> +	 0x1.3400p-107,
> +	 0x1.2b20p-102,
> +	 0x1.7800p-108,
> +	 0x1.cfd0p-101,
> +	 0x1.2ef0p-102,
> +	-0x1.2760p-99,
> +	 0x1.b380p-104,
> +	 0x1.0048p-101,
> +	-0x1.60b0p-102,
> +	 0x1.a1ccp-100,
> +	-0x1.a640p-104,
> +	-0x1.08a0p-101,
> +	 0x1.7e60p-102,
> +	 0x1.22c0p-103,
> +	-0x1.7200p-106,
> +	 0x1.f0f0p-102,
> +	 0x1.eb4ep-99,
> +	 0x1.c6e0p-103,
> +};
> +
> +/*
> + * exp2l(x): compute the base 2 exponential of x
> + *
> + * Accuracy: Peak error < 0.502 ulp.
> + *
> + * Method: (accurate tables)
> + *
> + *   Reduce x:
> + *     x = 2**k + y, for integer k and |y| <= 1/2.
> + *     Thus we have exp2(x) = 2**k * exp2(y).
> + *
> + *   Reduce y:
> + *     y = i/TBLSIZE + z - eps[i] for integer i near y * TBLSIZE.
> + *     Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z - eps[i]),
> + *     with |z - eps[i]| <= 2**-8 + 2**-98 for the table used.
> + *
> + *   We compute exp2(i/TBLSIZE) via table lookup and exp2(z - eps[i]) via
> + *   a degree-10 minimax polynomial with maximum error under 2**-120.
> + *   The values in exp2t[] and eps[] are chosen such that
> + *   exp2t[i] = exp2(i/TBLSIZE + eps[i]), and eps[i] is a small offset such
> + *   that exp2t[i] is accurate to 2**-122.
> + *
> + *   Note that the range of i is +-TBLSIZE/2, so we actually index the tables
> + *   by i0 = i + TBLSIZE/2.
> + *
> + *   This method is due to Gal, with many details due to Gal and Bachelis:
> + *
> + *	Gal, S. and Bachelis, B.  An Accurate Elementary Mathematical Library
> + *	for the IEEE Floating Point Standard.  TOMS 17(1), 26-46 (1991).
> + */
> +long double
> +exp2l(long double x)
> +{
> +	union IEEEl2bits u, v;
> +	long double r, t, twopk, twopkp10000, z;
> +	uint32_t hx, ix, i0;
> +	int k;
> +
> +	u.e = x;
> +
> +	/* Filter out exceptional cases. */
> +	hx = u.xbits.expsign;
> +	ix = hx & EXPMASK;
> +	if (ix >= BIAS + 14) {		/* |x| >= 16384 */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (u.xbits.manh != 0
> +			    || u.xbits.manl != 0
> +			    || (hx & 0x8000) == 0)
> +				return (x + x);	/* x is NaN or +Inf */
> +			else 
> +				return (0.0);	/* x is -Inf */
> +		}
> +		if (x >= 16384)
> +			return (huge * huge); /* overflow */
> +		if (x <= -16495)
> +			return (twom10000 * twom10000); /* underflow */
> +	} else if (ix <= BIAS - 115) {		/* |x| < 0x1p-115 */
> +		return (1.0 + x);
> +	}
> +
> +	/*
> +	 * Reduce x, computing z, i0, and k. The low bits of x + redux
> +	 * contain the 16-bit integer part of the exponent (k) followed by
> +	 * TBLBITS fractional bits (i0). We use bit tricks to extract these
> +	 * as integers, then set z to the remainder.
> +	 *
> +	 * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8.
> +	 * Then the low-order word of x + redux is 0x000abc12,
> +	 * We split this into k = 0xabc and i0 = 0x12 (adjusted to
> +	 * index into the table), then we compute z = 0x0.003456p0.
> +	 *
> +	 * XXX If the exponent is negative, the computation of k depends on
> +	 *     '>>' doing sign extension.
> +	 */
> +	u.e = x + redux;
> +	i0 = (u.bits.manl & 0xffffffff) + TBLSIZE / 2;
> +	k = (int)i0 >> TBLBITS;
> +	i0 = i0 & (TBLSIZE - 1);
> +	u.e -= redux;
> +	z = x - u.e;
> +	v.xbits.manh = 0;
> +	v.xbits.manl = 0;
> +	if (k >= LDBL_MIN_EXP) {
> +		v.xbits.expsign = LDBL_MAX_EXP - 1 + k;
> +		twopk = v.e;
> +	} else {
> +		v.xbits.expsign = LDBL_MAX_EXP - 1 + k + 10000;
> +		twopkp10000 = v.e;
> +	}
> +
> +	/* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */
> +	t = tbl[i0];		/* exp2t[i0] */
> +	z -= eps[i0];		/* eps[i0]   */
> +	r = t + t * z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * (P5 + z * (P6
> +	    + z * (P7 + z * (P8 + z * (P9 + z * P10)))))))));
> +
> +	/* Scale by 2**k. */
> +	if(k >= LDBL_MIN_EXP) {
> +		if (k == LDBL_MAX_EXP)
> +			return (r * 2.0 * 0x1p16383L);
> +		return (r * twopk);
> +	} else {
> +		return (r * twopkp10000 * twom10000);
> +	}
> +}
> diff --git a/newlib/libm/ld128/s_expl.c b/newlib/libm/ld128/s_expl.c
> new file mode 100644
> index 000000000..5b786af49
> --- /dev/null
> +++ b/newlib/libm/ld128/s_expl.c
> @@ -0,0 +1,326 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2009-2013 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld128 version of s_expl.c.  See ../ld80/s_expl.c for most comments.
> + */
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +#include "k_expl.h"
> +
> +/* XXX Prevent compilers from erroneously constant folding these: */
> +static const volatile long double
> +huge = 0x1p10000L,
> +tiny = 0x1p-10000L;
> +
> +static const long double
> +twom10000 = 0x1p-10000L;
> +
> +static const long double
> +/* log(2**16384 - 0.5) rounded towards zero: */
> +/* log(2**16384 - 0.5 + 1) rounded towards zero for expm1l() is the same: */
> +o_threshold =  11356.523406294143949491931077970763428L,
> +/* log(2**(-16381-64-1)) rounded towards zero: */
> +u_threshold = -11433.462743336297878837243843452621503L;
> +
> +long double
> +expl(long double x)
> +{
> +	union IEEEl2bits u;
> +	long double hi, lo, t, twopk;
> +	int k;
> +	uint16_t hx, ix;
> +
> +	DOPRINT_START(&x);
> +
> +	/* Filter out exceptional cases. */
> +	u.e = x;
> +	hx = u.xbits.expsign;
> +	ix = hx & 0x7fff;
> +	if (ix >= BIAS + 13) {		/* |x| >= 8192 or x is NaN */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (hx & 0x8000)  /* x is -Inf or -NaN */
> +				RETURNP(-1 / x);
> +			RETURNP(x + x);	/* x is +Inf or +NaN */
> +		}
> +		if (x > o_threshold)
> +			RETURNP(huge * huge);
> +		if (x < u_threshold)
> +			RETURNP(tiny * tiny);
> +	} else if (ix < BIAS - 114) {	/* |x| < 0x1p-114 */
> +		RETURN2P(1, x);		/* 1 with inexact iff x != 0 */
> +	}
> +
> +	ENTERI();
> +
> +	twopk = 1;
> +	__k_expl(x, &hi, &lo, &k);
> +	t = SUM2P(hi, lo);
> +
> +	/* Scale by 2**k. */
> +	/*
> +	 * XXX sparc64 multiplication was so slow that scalbnl() is faster,
> +	 * but performance on aarch64 and riscv hasn't yet been quantified.
> +	 */
> +	if (k >= LDBL_MIN_EXP) {
> +		if (k == LDBL_MAX_EXP)
> +			RETURNI(t * 2 * 0x1p16383L);
> +		SET_LDBL_EXPSIGN(twopk, BIAS + k);
> +		RETURNI(t * twopk);
> +	} else {
> +		SET_LDBL_EXPSIGN(twopk, BIAS + k + 10000);
> +		RETURNI(t * twopk * twom10000);
> +	}
> +}
> +
> +/*
> + * Our T1 and T2 are chosen to be approximately the points where method
> + * A and method B have the same accuracy.  Tang's T1 and T2 are the
> + * points where method A's accuracy changes by a full bit.  For Tang,
> + * this drop in accuracy makes method A immediately less accurate than
> + * method B, but our larger INTERVALS makes method A 2 bits more
> + * accurate so it remains the most accurate method significantly
> + * closer to the origin despite losing the full bit in our extended
> + * range for it.
> + *
> + * Split the interval [T1, T2] into two intervals [T1, T3] and [T3, T2].
> + * Setting T3 to 0 would require the |x| < 0x1p-113 condition to appear
> + * in both subintervals, so set T3 = 2**-5, which places the condition
> + * into the [T1, T3] interval.
> + *
> + * XXX we now do this more to (partially) balance the number of terms
> + * in the C and D polys than to avoid checking the condition in both
> + * intervals.
> + *
> + * XXX these micro-optimizations are excessive.
> + */
> +static const double
> +T1 = -0.1659,				/* ~-30.625/128 * log(2) */
> +T2 =  0.1659,				/* ~30.625/128 * log(2) */
> +T3 =  0.03125;
> +
> +/*
> + * Domain [-0.1659, 0.03125], range ~[2.9134e-44, 1.8404e-37]:
> + * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-122.03
> + *
> + * XXX none of the long double C or D coeffs except C10 is correctly printed.
> + * If you re-print their values in %.35Le format, the result is always
> + * different.  For example, the last 2 digits in C3 should be 59, not 67.
> + * 67 is apparently from rounding an extra-precision value to 36 decimal
> + * places.
> + */
> +static const long double
> +C3  =  1.66666666666666666666666666666666667e-1L,
> +C4  =  4.16666666666666666666666666666666645e-2L,
> +C5  =  8.33333333333333333333333333333371638e-3L,
> +C6  =  1.38888888888888888888888888891188658e-3L,
> +C7  =  1.98412698412698412698412697235950394e-4L,
> +C8  =  2.48015873015873015873015112487849040e-5L,
> +C9  =  2.75573192239858906525606685484412005e-6L,
> +C10 =  2.75573192239858906612966093057020362e-7L,
> +C11 =  2.50521083854417203619031960151253944e-8L,
> +C12 =  2.08767569878679576457272282566520649e-9L,
> +C13 =  1.60590438367252471783548748824255707e-10L;
> +
> +/*
> + * XXX this has 1 more coeff than needed.
> + * XXX can start the double coeffs but not the double mults at C10.
> + * With my coeffs (C10-C17 double; s = best_s):
> + * Domain [-0.1659, 0.03125], range ~[-1.1976e-37, 1.1976e-37]:
> + * |(exp(x)-1-x-x**2/2)/x - p(x)| ~< 2**-122.65
> + */
> +static const double
> +C14 =  1.1470745580491932e-11,		/*  0x1.93974a81dae30p-37 */
> +C15 =  7.6471620181090468e-13,		/*  0x1.ae7f3820adab1p-41 */
> +C16 =  4.7793721460260450e-14,		/*  0x1.ae7cd18a18eacp-45 */
> +C17 =  2.8074757356658877e-15,		/*  0x1.949992a1937d9p-49 */
> +C18 =  1.4760610323699476e-16;		/*  0x1.545b43aabfbcdp-53 */
> +
> +/*
> + * Domain [0.03125, 0.1659], range ~[-2.7676e-37, -1.0367e-38]:
> + * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-121.44
> + */
> +static const long double
> +D3  =  1.66666666666666666666666666666682245e-1L,
> +D4  =  4.16666666666666666666666666634228324e-2L,
> +D5  =  8.33333333333333333333333364022244481e-3L,
> +D6  =  1.38888888888888888888887138722762072e-3L,
> +D7  =  1.98412698412698412699085805424661471e-4L,
> +D8  =  2.48015873015873015687993712101479612e-5L,
> +D9  =  2.75573192239858944101036288338208042e-6L,
> +D10 =  2.75573192239853161148064676533754048e-7L,
> +D11 =  2.50521083855084570046480450935267433e-8L,
> +D12 =  2.08767569819738524488686318024854942e-9L,
> +D13 =  1.60590442297008495301927448122499313e-10L;
> +
> +/*
> + * XXX this has 1 more coeff than needed.
> + * XXX can start the double coeffs but not the double mults at D11.
> + * With my coeffs (D11-D16 double):
> + * Domain [0.03125, 0.1659], range ~[-1.1980e-37, 1.1980e-37]:
> + * |(exp(x)-1-x-x**2/2)/x - p(x)| ~< 2**-122.65
> + */
> +static const double
> +D14 =  1.1470726176204336e-11,		/*  0x1.93971dc395d9ep-37 */
> +D15 =  7.6478532249581686e-13,		/*  0x1.ae892e3D16fcep-41 */
> +D16 =  4.7628892832607741e-14,		/*  0x1.ad00Dfe41feccp-45 */
> +D17 =  3.0524857220358650e-15;		/*  0x1.D7e8d886Df921p-49 */
> +
> +long double
> +expm1l(long double x)
> +{
> +	union IEEEl2bits u, v;
> +	long double hx2_hi, hx2_lo, q, r, r1, t, twomk, twopk, x_hi;
> +	long double x_lo, x2;
> +	double dr, dx, fn, r2;
> +	int k, n, n2;
> +	uint16_t hx, ix;
> +
> +	DOPRINT_START(&x);
> +
> +	/* Filter out exceptional cases. */
> +	u.e = x;
> +	hx = u.xbits.expsign;
> +	ix = hx & 0x7fff;
> +	if (ix >= BIAS + 7) {		/* |x| >= 128 or x is NaN */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (hx & 0x8000)  /* x is -Inf or -NaN */
> +				RETURNP(-1 / x - 1);
> +			RETURNP(x + x);	/* x is +Inf or +NaN */
> +		}
> +		if (x > o_threshold)
> +			RETURNP(huge * huge);
> +		/*
> +		 * expm1l() never underflows, but it must avoid
> +		 * unrepresentable large negative exponents.  We used a
> +		 * much smaller threshold for large |x| above than in
> +		 * expl() so as to handle not so large negative exponents
> +		 * in the same way as large ones here.
> +		 */
> +		if (hx & 0x8000)	/* x <= -128 */
> +			RETURN2P(tiny, -1);	/* good for x < -114ln2 - eps */
> +	}
> +
> +	ENTERI();
> +
> +	if (T1 < x && x < T2) {
> +		x2 = x * x;
> +		dx = x;
> +
> +		if (x < T3) {
> +			if (ix < BIAS - 113) {	/* |x| < 0x1p-113 */
> +				/* x (rounded) with inexact if x != 0: */
> +				RETURNPI(x == 0 ? x :
> +				    (0x1p200 * x + fabsl(x)) * 0x1p-200);
> +			}
> +			q = x * x2 * C3 + x2 * x2 * (C4 + x * (C5 + x * (C6 +
> +			    x * (C7 + x * (C8 + x * (C9 + x * (C10 +
> +			    x * (C11 + x * (C12 + x * (C13 +
> +			    dx * (C14 + dx * (C15 + dx * (C16 +
> +			    dx * (C17 + dx * C18))))))))))))));
> +		} else {
> +			q = x * x2 * D3 + x2 * x2 * (D4 + x * (D5 + x * (D6 +
> +			    x * (D7 + x * (D8 + x * (D9 + x * (D10 +
> +			    x * (D11 + x * (D12 + x * (D13 +
> +			    dx * (D14 + dx * (D15 + dx * (D16 +
> +			    dx * D17)))))))))))));
> +		}
> +
> +		x_hi = (float)x;
> +		x_lo = x - x_hi;
> +		hx2_hi = x_hi * x_hi / 2;
> +		hx2_lo = x_lo * (x + x_hi) / 2;
> +		if (ix >= BIAS - 7)
> +			RETURN2PI(hx2_hi + x_hi, hx2_lo + x_lo + q);
> +		else
> +			RETURN2PI(x, hx2_lo + q + hx2_hi);
> +	}
> +
> +	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
> +	fn = rnint((double)x * INV_L);
> +	n = irint(fn);
> +	n2 = (unsigned)n % INTERVALS;
> +	k = n >> LOG2_INTERVALS;
> +	r1 = x - fn * L1;
> +	r2 = fn * -L2;
> +	r = r1 + r2;
> +
> +	/* Prepare scale factor. */
> +	v.e = 1;
> +	v.xbits.expsign = BIAS + k;
> +	twopk = v.e;
> +
> +	/*
> +	 * Evaluate lower terms of
> +	 * expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2).
> +	 */
> +	dr = r;
> +	q = r2 + r * r * (A2 + r * (A3 + r * (A4 + r * (A5 + r * (A6 +
> +	    dr * (A7 + dr * (A8 + dr * (A9 + dr * A10))))))));
> +
> +	t = tbl[n2].lo + tbl[n2].hi;
> +
> +	if (k == 0) {
> +		t = SUM2P(tbl[n2].hi - 1, tbl[n2].lo * (r1 + 1) + t * q +
> +		    tbl[n2].hi * r1);
> +		RETURNI(t);
> +	}
> +	if (k == -1) {
> +		t = SUM2P(tbl[n2].hi - 2, tbl[n2].lo * (r1 + 1) + t * q +
> +		    tbl[n2].hi * r1);
> +		RETURNI(t / 2);
> +	}
> +	if (k < -7) {
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
> +		RETURNI(t * twopk - 1);
> +	}
> +	if (k > 2 * LDBL_MANT_DIG - 1) {
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
> +		if (k == LDBL_MAX_EXP)
> +			RETURNI(t * 2 * 0x1p16383L - 1);
> +		RETURNI(t * twopk - 1);
> +	}
> +
> +	v.xbits.expsign = BIAS - k;
> +	twomk = v.e;
> +
> +	if (k > LDBL_MANT_DIG - 1)
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo - twomk + t * (q + r1));
> +	else
> +		t = SUM2P(tbl[n2].hi - twomk, tbl[n2].lo + t * (q + r1));
> +	RETURNI(t * twopk);
> +}
> diff --git a/newlib/libm/ld128/s_logl.c b/newlib/libm/ld128/s_logl.c
> new file mode 100644
> index 000000000..4774a271e
> --- /dev/null
> +++ b/newlib/libm/ld128/s_logl.c
> @@ -0,0 +1,740 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007-2013 Bruce D. Evans
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/**
> + * Implementation of the natural logarithm of x for 128-bit format.
> + *
> + * First decompose x into its base 2 representation:
> + *
> + *    log(x) = log(X * 2**k), where X is in [1, 2)
> + *           = log(X) + k * log(2).
> + *
> + * Let X = X_i + e, where X_i is the center of one of the intervals
> + * [-1.0/256, 1.0/256), [1.0/256, 3.0/256), .... [2.0-1.0/256, 2.0+1.0/256)
> + * and X is in this interval.  Then
> + *
> + *    log(X) = log(X_i + e)
> + *           = log(X_i * (1 + e / X_i))
> + *           = log(X_i) + log(1 + e / X_i).
> + *
> + * The values log(X_i) are tabulated below.  Let d = e / X_i and use
> + *
> + *    log(1 + d) = p(d)
> + *
> + * where p(d) = d - 0.5*d*d + ... is a special minimax polynomial of
> + * suitably high degree.
> + *
> + * To get sufficiently small roundoff errors, k * log(2), log(X_i), and
> + * sometimes (if |k| is not large) the first term in p(d) must be evaluated
> + * and added up in extra precision.  Extra precision is not needed for the
> + * rest of p(d).  In the worst case when k = 0 and log(X_i) is 0, the final
> + * error is controlled mainly by the error in the second term in p(d).  The
> + * error in this term itself is at most 0.5 ulps from the d*d operation in
> + * it.  The error in this term relative to the first term is thus at most
> + * 0.5 * |-0.5| * |d| < 1.0/1024 ulps.  We aim for an accumulated error of
> + * at most twice this at the point of the final rounding step.  Thus the
> + * final error should be at most 0.5 + 1.0/512 = 0.5020 ulps.  Exhaustive
> + * testing of a float variant of this function showed a maximum final error
> + * of 0.5008 ulps.  Non-exhaustive testing of a double variant of this
> + * function showed a maximum final error of 0.5078 ulps (near 1+1.0/256).
> + *
> + * We made the maximum of |d| (and thus the total relative error and the
> + * degree of p(d)) small by using a large number of intervals.  Using
> + * centers of intervals instead of endpoints reduces this maximum by a
> + * factor of 2 for a given number of intervals.  p(d) is special only
> + * in beginning with the Taylor coefficients 0 + 1*d, which tends to happen
> + * naturally.  The most accurate minimax polynomial of a given degree might
> + * be different, but then we wouldn't want it since we would have to do
> + * extra work to avoid roundoff error (especially for P0*d instead of d).
> + */
> +
> +#ifdef DEBUG
> +#include <assert.h>
> +#include <fenv.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#ifndef NO_STRUCT_RETURN
> +#define	STRUCT_RETURN
> +#endif
> +#include "math_private.h"
> +
> +#if !defined(NO_UTAB) && !defined(NO_UTABL)
> +#define	USE_UTAB
> +#endif
> +
> +/*
> + * Domain [-0.005280, 0.004838], range ~[-1.1577e-37, 1.1582e-37]:
> + * |log(1 + d)/d - p(d)| < 2**-122.7
> + */
> +static const long double
> +P2 = -0.5L,
> +P3 =  3.33333333333333333333333333333233795e-1L,	/*  0x15555555555555555555555554d42.0p-114L */
> +P4 = -2.49999999999999999999999999941139296e-1L,	/* -0x1ffffffffffffffffffffffdab14e.0p-115L */
> +P5 =  2.00000000000000000000000085468039943e-1L,	/*  0x19999999999999999999a6d3567f4.0p-115L */
> +P6 = -1.66666666666666666666696142372698408e-1L,	/* -0x15555555555555555567267a58e13.0p-115L */
> +P7 =  1.42857142857142857119522943477166120e-1L,	/*  0x1249249249249248ed79a0ae434de.0p-115L */
> +P8 = -1.24999999999999994863289015033581301e-1L;	/* -0x1fffffffffffffa13e91765e46140.0p-116L */
> +/* Double precision gives ~ 53 + log2(P9 * max(|d|)**8) ~= 120 bits. */
> +static const double
> +P9 =  1.1111111111111401e-1,		/*  0x1c71c71c71c7ed.0p-56 */
> +P10 = -1.0000000000040135e-1,		/* -0x199999999a0a92.0p-56 */
> +P11 =  9.0909090728136258e-2,		/*  0x1745d173962111.0p-56 */
> +P12 = -8.3333318851855284e-2,		/* -0x1555551722c7a3.0p-56 */
> +P13 =  7.6928634666404178e-2,		/*  0x13b1985204a4ae.0p-56 */
> +P14 = -7.1626810078462499e-2;		/* -0x12562276cdc5d0.0p-56 */
> +
> +static volatile const double zero = 0;
> +
> +#define	INTERVALS	128
> +#define	LOG2_INTERVALS	7
> +#define	TSIZE		(INTERVALS + 1)
> +#define	G(i)		(T[(i)].G)
> +#define	F_hi(i)		(T[(i)].F_hi)
> +#define	F_lo(i)		(T[(i)].F_lo)
> +#define	ln2_hi		F_hi(TSIZE - 1)
> +#define	ln2_lo		F_lo(TSIZE - 1)
> +#define	E(i)		(U[(i)].E)
> +#define	H(i)		(U[(i)].H)
> +
> +static const struct {
> +	float	G;			/* 1/(1 + i/128) rounded to 8/9 bits */
> +	float	F_hi;			/* log(1 / G_i) rounded (see below) */
> +	/* The compiler will insert 8 bytes of padding here. */
> +	long double F_lo;		/* next 113 bits for log(1 / G_i) */
> +} T[TSIZE] = {
> +	/*
> +	 * ln2_hi and each F_hi(i) are rounded to a number of bits that
> +	 * makes F_hi(i) + dk*ln2_hi exact for all i and all dk.
> +	 *
> +	 * The last entry (for X just below 2) is used to define ln2_hi
> +	 * and ln2_lo, to ensure that F_hi(i) and F_lo(i) cancel exactly
> +	 * with dk*ln2_hi and dk*ln2_lo, respectively, when dk = -1.
> +	 * This is needed for accuracy when x is just below 1.  (To avoid
> +	 * special cases, such x are "reduced" strangely to X just below
> +	 * 2 and dk = -1, and then the exact cancellation is needed
> +	 * because any the error from any non-exactness would be too
> +	 * large).
> +	 *
> +	 * The relevant range of dk is [-16445, 16383].  The maximum number
> +	 * of bits in F_hi(i) that works is very dependent on i but has
> +	 * a minimum of 93.  We only need about 12 bits in F_hi(i) for
> +	 * it to provide enough extra precision.
> +	 *
> +	 * We round F_hi(i) to 24 bits so that it can have type float,
> +	 * mainly to minimize the size of the table.  Using all 24 bits
> +	 * in a float for it automatically satisfies the above constraints.
> +	 */
> +     0x800000.0p-23,  0,               0,
> +     0xfe0000.0p-24,  0x8080ac.0p-30, -0x14ee431dae6674afa0c4bfe16e8fd.0p-144L,
> +     0xfc0000.0p-24,  0x8102b3.0p-29, -0x1db29ee2d83717be918e1119642ab.0p-144L,
> +     0xfa0000.0p-24,  0xc24929.0p-29,  0x1191957d173697cf302cc9476f561.0p-143L,
> +     0xf80000.0p-24,  0x820aec.0p-28,  0x13ce8888e02e78eba9b1113bc1c18.0p-142L,
> +     0xf60000.0p-24,  0xa33577.0p-28, -0x17a4382ce6eb7bfa509bec8da5f22.0p-142L,
> +     0xf48000.0p-24,  0xbc42cb.0p-28, -0x172a21161a107674986dcdca6709c.0p-143L,
> +     0xf30000.0p-24,  0xd57797.0p-28, -0x1e09de07cb958897a3ea46e84abb3.0p-142L,
> +     0xf10000.0p-24,  0xf7518e.0p-28,  0x1ae1eec1b036c484993c549c4bf40.0p-151L,
> +     0xef0000.0p-24,  0x8cb9df.0p-27, -0x1d7355325d560d9e9ab3d6ebab580.0p-141L,
> +     0xed8000.0p-24,  0x999ec0.0p-27, -0x1f9f02d256d5037108f4ec21e48cd.0p-142L,
> +     0xec0000.0p-24,  0xa6988b.0p-27, -0x16fc0a9d12c17a70f7a684c596b12.0p-143L,
> +     0xea0000.0p-24,  0xb80698.0p-27,  0x15d581c1e8da99ded322fb08b8462.0p-141L,
> +     0xe80000.0p-24,  0xc99af3.0p-27, -0x1535b3ba8f150ae09996d7bb4653e.0p-143L,
> +     0xe70000.0p-24,  0xd273b2.0p-27,  0x163786f5251aefe0ded34c8318f52.0p-145L,
> +     0xe50000.0p-24,  0xe442c0.0p-27,  0x1bc4b2368e32d56699c1799a244d4.0p-144L,
> +     0xe38000.0p-24,  0xf1b83f.0p-27,  0x1c6090f684e6766abceccab1d7174.0p-141L,
> +     0xe20000.0p-24,  0xff448a.0p-27, -0x1890aa69ac9f4215f93936b709efb.0p-142L,
> +     0xe08000.0p-24,  0x8673f6.0p-26,  0x1b9985194b6affd511b534b72a28e.0p-140L,
> +     0xdf0000.0p-24,  0x8d515c.0p-26, -0x1dc08d61c6ef1d9b2ef7e68680598.0p-143L,
> +     0xdd8000.0p-24,  0x943a9e.0p-26, -0x1f72a2dac729b3f46662238a9425a.0p-142L,
> +     0xdc0000.0p-24,  0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9691aed4d5e3df94.0p-140L,
> +     0xda8000.0p-24,  0xa2315d.0p-26, -0x11b26121629c46c186384993e1c93.0p-142L,
> +     0xd90000.0p-24,  0xa93f2f.0p-26,  0x1286d633e8e5697dc6a402a56fce1.0p-141L,
> +     0xd78000.0p-24,  0xb05988.0p-26,  0x16128eba9367707ebfa540e45350c.0p-144L,
> +     0xd60000.0p-24,  0xb78094.0p-26,  0x16ead577390d31ef0f4c9d43f79b2.0p-140L,
> +     0xd50000.0p-24,  0xbc4c6c.0p-26,  0x151131ccf7c7b75e7d900b521c48d.0p-141L,
> +     0xd38000.0p-24,  0xc3890a.0p-26, -0x115e2cd714bd06508aeb00d2ae3e9.0p-140L,
> +     0xd20000.0p-24,  0xcad2d7.0p-26, -0x1847f406ebd3af80485c2f409633c.0p-142L,
> +     0xd10000.0p-24,  0xcfb620.0p-26,  0x1c2259904d686581799fbce0b5f19.0p-141L,
> +     0xcf8000.0p-24,  0xd71653.0p-26,  0x1ece57a8d5ae54f550444ecf8b995.0p-140L,
> +     0xce0000.0p-24,  0xde843a.0p-26, -0x1f109d4bc4595412b5d2517aaac13.0p-141L,
> +     0xcd0000.0p-24,  0xe37fde.0p-26,  0x1bc03dc271a74d3a85b5b43c0e727.0p-141L,
> +     0xcb8000.0p-24,  0xeb050c.0p-26, -0x1bf2badc0df841a71b79dd5645b46.0p-145L,
> +     0xca0000.0p-24,  0xf29878.0p-26, -0x18efededd89fbe0bcfbe6d6db9f66.0p-147L,
> +     0xc90000.0p-24,  0xf7ad6f.0p-26,  0x1373ff977baa6911c7bafcb4d84fb.0p-141L,
> +     0xc80000.0p-24,  0xfcc8e3.0p-26,  0x196766f2fb328337cc050c6d83b22.0p-140L,
> +     0xc68000.0p-24,  0x823f30.0p-25,  0x19bd076f7c434e5fcf1a212e2a91e.0p-139L,
> +     0xc58000.0p-24,  0x84d52c.0p-25, -0x1a327257af0f465e5ecab5f2a6f81.0p-139L,
> +     0xc40000.0p-24,  0x88bc74.0p-25,  0x113f23def19c5a0fe396f40f1dda9.0p-141L,
> +     0xc30000.0p-24,  0x8b5ae6.0p-25,  0x1759f6e6b37de945a049a962e66c6.0p-139L,
> +     0xc20000.0p-24,  0x8dfccb.0p-25,  0x1ad35ca6ed5147bdb6ddcaf59c425.0p-141L,
> +     0xc10000.0p-24,  0x90a22b.0p-25,  0x1a1d71a87deba46bae9827221dc98.0p-139L,
> +     0xbf8000.0p-24,  0x94a0d8.0p-25, -0x139e5210c2b730e28aba001a9b5e0.0p-140L,
> +     0xbe8000.0p-24,  0x974f16.0p-25, -0x18f6ebcff3ed72e23e13431adc4a5.0p-141L,
> +     0xbd8000.0p-24,  0x9a00f1.0p-25, -0x1aa268be39aab7148e8d80caa10b7.0p-139L,
> +     0xbc8000.0p-24,  0x9cb672.0p-25, -0x14c8815839c5663663d15faed7771.0p-139L,
> +     0xbb0000.0p-24,  0xa0cda1.0p-25,  0x1eaf46390dbb2438273918db7df5c.0p-141L,
> +     0xba0000.0p-24,  0xa38c6e.0p-25,  0x138e20d831f698298adddd7f32686.0p-141L,
> +     0xb90000.0p-24,  0xa64f05.0p-25, -0x1e8d3c41123615b147a5d47bc208f.0p-142L,
> +     0xb80000.0p-24,  0xa91570.0p-25,  0x1ce28f5f3840b263acb4351104631.0p-140L,
> +     0xb70000.0p-24,  0xabdfbb.0p-25, -0x186e5c0a42423457e22d8c650b355.0p-139L,
> +     0xb60000.0p-24,  0xaeadef.0p-25, -0x14d41a0b2a08a465dc513b13f567d.0p-143L,
> +     0xb50000.0p-24,  0xb18018.0p-25,  0x16755892770633947ffe651e7352f.0p-139L,
> +     0xb40000.0p-24,  0xb45642.0p-25, -0x16395ebe59b15228bfe8798d10ff0.0p-142L,
> +     0xb30000.0p-24,  0xb73077.0p-25,  0x1abc65c8595f088b61a335f5b688c.0p-140L,
> +     0xb20000.0p-24,  0xba0ec4.0p-25, -0x1273089d3dad88e7d353e9967d548.0p-139L,
> +     0xb10000.0p-24,  0xbcf133.0p-25,  0x10f9f67b1f4bbf45de06ecebfaf6d.0p-139L,
> +     0xb00000.0p-24,  0xbfd7d2.0p-25, -0x109fab904864092b34edda19a831e.0p-140L,
> +     0xaf0000.0p-24,  0xc2c2ac.0p-25, -0x1124680aa43333221d8a9b475a6ba.0p-139L,
> +     0xae8000.0p-24,  0xc439b3.0p-25, -0x1f360cc4710fbfe24b633f4e8d84d.0p-140L,
> +     0xad8000.0p-24,  0xc72afd.0p-25, -0x132d91f21d89c89c45003fc5d7807.0p-140L,
> +     0xac8000.0p-24,  0xca20a2.0p-25, -0x16bf9b4d1f8da8002f2449e174504.0p-139L,
> +     0xab8000.0p-24,  0xcd1aae.0p-25,  0x19deb5ce6a6a8717d5626e16acc7d.0p-141L,
> +     0xaa8000.0p-24,  0xd0192f.0p-25,  0x1a29fb48f7d3ca87dabf351aa41f4.0p-139L,
> +     0xaa0000.0p-24,  0xd19a20.0p-25,  0x1127d3c6457f9d79f51dcc73014c9.0p-141L,
> +     0xa90000.0p-24,  0xd49f6a.0p-25, -0x1ba930e486a0ac42d1bf9199188e7.0p-141L,
> +     0xa80000.0p-24,  0xd7a94b.0p-25, -0x1b6e645f31549dd1160bcc45c7e2c.0p-139L,
> +     0xa70000.0p-24,  0xdab7d0.0p-25,  0x1118a425494b610665377f15625b6.0p-140L,
> +     0xa68000.0p-24,  0xdc40d5.0p-25,  0x1966f24d29d3a2d1b2176010478be.0p-140L,
> +     0xa58000.0p-24,  0xdf566d.0p-25, -0x1d8e52eb2248f0c95dd83626d7333.0p-142L,
> +     0xa48000.0p-24,  0xe270ce.0p-25, -0x1ee370f96e6b67ccb006a5b9890ea.0p-140L,
> +     0xa40000.0p-24,  0xe3ffce.0p-25,  0x1d155324911f56db28da4d629d00a.0p-140L,
> +     0xa30000.0p-24,  0xe72179.0p-25, -0x1fe6e2f2f867d8f4d60c713346641.0p-140L,
> +     0xa20000.0p-24,  0xea4812.0p-25,  0x1b7be9add7f4d3b3d406b6cbf3ce5.0p-140L,
> +     0xa18000.0p-24,  0xebdd3d.0p-25,  0x1b3cfb3f7511dd73692609040ccc2.0p-139L,
> +     0xa08000.0p-24,  0xef0b5b.0p-25, -0x1220de1f7301901b8ad85c25afd09.0p-139L,
> +     0xa00000.0p-24,  0xf0a451.0p-25, -0x176364c9ac81cc8a4dfb804de6867.0p-140L,
> +     0x9f0000.0p-24,  0xf3da16.0p-25,  0x1eed6b9aafac8d42f78d3e65d3727.0p-141L,
> +     0x9e8000.0p-24,  0xf576e9.0p-25,  0x1d593218675af269647b783d88999.0p-139L,
> +     0x9d8000.0p-24,  0xf8b47c.0p-25, -0x13e8eb7da053e063714615f7cc91d.0p-144L,
> +     0x9d0000.0p-24,  0xfa553f.0p-25,  0x1c063259bcade02951686d5373aec.0p-139L,
> +     0x9c0000.0p-24,  0xfd9ac5.0p-25,  0x1ef491085fa3c1649349630531502.0p-139L,
> +     0x9b8000.0p-24,  0xff3f8c.0p-25,  0x1d607a7c2b8c5320619fb9433d841.0p-139L,
> +     0x9a8000.0p-24,  0x814697.0p-24, -0x12ad3817004f3f0bdff99f932b273.0p-138L,
> +     0x9a0000.0p-24,  0x821b06.0p-24, -0x189fc53117f9e54e78103a2bc1767.0p-141L,
> +     0x990000.0p-24,  0x83c5f8.0p-24,  0x14cf15a048907b7d7f47ddb45c5a3.0p-139L,
> +     0x988000.0p-24,  0x849c7d.0p-24,  0x1cbb1d35fb82873b04a9af1dd692c.0p-138L,
> +     0x978000.0p-24,  0x864ba6.0p-24,  0x1128639b814f9b9770d8cb6573540.0p-138L,
> +     0x970000.0p-24,  0x87244c.0p-24,  0x184733853300f002e836dfd47bd41.0p-139L,
> +     0x968000.0p-24,  0x87fdaa.0p-24,  0x109d23aef77dd5cd7cc94306fb3ff.0p-140L,
> +     0x958000.0p-24,  0x89b293.0p-24, -0x1a81ef367a59de2b41eeebd550702.0p-138L,
> +     0x950000.0p-24,  0x8a8e20.0p-24, -0x121ad3dbb2f45275c917a30df4ac9.0p-138L,
> +     0x948000.0p-24,  0x8b6a6a.0p-24, -0x1cfb981628af71a89df4e6df2e93b.0p-139L,
> +     0x938000.0p-24,  0x8d253a.0p-24, -0x1d21730ea76cfdec367828734cae5.0p-139L,
> +     0x930000.0p-24,  0x8e03c2.0p-24,  0x135cc00e566f76b87333891e0dec4.0p-138L,
> +     0x928000.0p-24,  0x8ee30d.0p-24, -0x10fcb5df257a263e3bf446c6e3f69.0p-140L,
> +     0x918000.0p-24,  0x90a3ee.0p-24, -0x16e171b15433d723a4c7380a448d8.0p-139L,
> +     0x910000.0p-24,  0x918587.0p-24, -0x1d050da07f3236f330972da2a7a87.0p-139L,
> +     0x908000.0p-24,  0x9267e7.0p-24,  0x1be03669a5268d21148c6002becd3.0p-139L,
> +     0x8f8000.0p-24,  0x942f04.0p-24,  0x10b28e0e26c336af90e00533323ba.0p-139L,
> +     0x8f0000.0p-24,  0x9513c3.0p-24,  0x1a1d820da57cf2f105a89060046aa.0p-138L,
> +     0x8e8000.0p-24,  0x95f950.0p-24, -0x19ef8f13ae3cf162409d8ea99d4c0.0p-139L,
> +     0x8e0000.0p-24,  0x96dfab.0p-24, -0x109e417a6e507b9dc10dac743ad7a.0p-138L,
> +     0x8d0000.0p-24,  0x98aed2.0p-24,  0x10d01a2c5b0e97c4990b23d9ac1f5.0p-139L,
> +     0x8c8000.0p-24,  0x9997a2.0p-24, -0x1d6a50d4b61ea74540bdd2aa99a42.0p-138L,
> +     0x8c0000.0p-24,  0x9a8145.0p-24,  0x1b3b190b83f9527e6aba8f2d783c1.0p-138L,
> +     0x8b8000.0p-24,  0x9b6bbf.0p-24,  0x13a69fad7e7abe7ba81c664c107e0.0p-138L,
> +     0x8b0000.0p-24,  0x9c5711.0p-24, -0x11cd12316f576aad348ae79867223.0p-138L,
> +     0x8a8000.0p-24,  0x9d433b.0p-24,  0x1c95c444b807a246726b304ccae56.0p-139L,
> +     0x898000.0p-24,  0x9f1e22.0p-24, -0x1b9c224ea698c2f9b47466d6123fe.0p-139L,
> +     0x890000.0p-24,  0xa00ce1.0p-24,  0x125ca93186cf0f38b4619a2483399.0p-141L,
> +     0x888000.0p-24,  0xa0fc80.0p-24, -0x1ee38a7bc228b3597043be78eaf49.0p-139L,
> +     0x880000.0p-24,  0xa1ed00.0p-24, -0x1a0db876613d204147dc69a07a649.0p-138L,
> +     0x878000.0p-24,  0xa2de62.0p-24,  0x193224e8516c008d3602a7b41c6e8.0p-139L,
> +     0x870000.0p-24,  0xa3d0a9.0p-24,  0x1fa28b4d2541aca7d5844606b2421.0p-139L,
> +     0x868000.0p-24,  0xa4c3d6.0p-24,  0x1c1b5760fb4571acbcfb03f16daf4.0p-138L,
> +     0x858000.0p-24,  0xa6acea.0p-24,  0x1fed5d0f65949c0a345ad743ae1ae.0p-140L,
> +     0x850000.0p-24,  0xa7a2d4.0p-24,  0x1ad270c9d749362382a7688479e24.0p-140L,
> +     0x848000.0p-24,  0xa899ab.0p-24,  0x199ff15ce532661ea9643a3a2d378.0p-139L,
> +     0x840000.0p-24,  0xa99171.0p-24,  0x1a19e15ccc45d257530a682b80490.0p-139L,
> +     0x838000.0p-24,  0xaa8a28.0p-24, -0x121a14ec532b35ba3e1f868fd0b5e.0p-140L,
> +     0x830000.0p-24,  0xab83d1.0p-24,  0x1aee319980bff3303dd481779df69.0p-139L,
> +     0x828000.0p-24,  0xac7e6f.0p-24, -0x18ffd9e3900345a85d2d86161742e.0p-140L,
> +     0x820000.0p-24,  0xad7a03.0p-24, -0x1e4db102ce29f79b026b64b42caa1.0p-140L,
> +     0x818000.0p-24,  0xae768f.0p-24,  0x17c35c55a04a82ab19f77652d977a.0p-141L,
> +     0x810000.0p-24,  0xaf7415.0p-24,  0x1448324047019b48d7b98c1cf7234.0p-138L,
> +     0x808000.0p-24,  0xb07298.0p-24, -0x1750ee3915a197e9c7359dd94152f.0p-138L,
> +     0x800000.0p-24,  0xb17218.0p-24, -0x105c610ca86c3898cff81a12a17e2.0p-141L,
> +};
> +
> +#ifdef USE_UTAB
> +static const struct {
> +	float	H;			/* 1 + i/INTERVALS (exact) */
> +	float	E;			/* H(i) * G(i) - 1 (exact) */
> +} U[TSIZE] = {
> +	 0x800000.0p-23,  0,
> +	 0x810000.0p-23, -0x800000.0p-37,
> +	 0x820000.0p-23, -0x800000.0p-35,
> +	 0x830000.0p-23, -0x900000.0p-34,
> +	 0x840000.0p-23, -0x800000.0p-33,
> +	 0x850000.0p-23, -0xc80000.0p-33,
> +	 0x860000.0p-23, -0xa00000.0p-36,
> +	 0x870000.0p-23,  0x940000.0p-33,
> +	 0x880000.0p-23,  0x800000.0p-35,
> +	 0x890000.0p-23, -0xc80000.0p-34,
> +	 0x8a0000.0p-23,  0xe00000.0p-36,
> +	 0x8b0000.0p-23,  0x900000.0p-33,
> +	 0x8c0000.0p-23, -0x800000.0p-35,
> +	 0x8d0000.0p-23, -0xe00000.0p-33,
> +	 0x8e0000.0p-23,  0x880000.0p-33,
> +	 0x8f0000.0p-23, -0xa80000.0p-34,
> +	 0x900000.0p-23, -0x800000.0p-35,
> +	 0x910000.0p-23,  0x800000.0p-37,
> +	 0x920000.0p-23,  0x900000.0p-35,
> +	 0x930000.0p-23,  0xd00000.0p-35,
> +	 0x940000.0p-23,  0xe00000.0p-35,
> +	 0x950000.0p-23,  0xc00000.0p-35,
> +	 0x960000.0p-23,  0xe00000.0p-36,
> +	 0x970000.0p-23, -0x800000.0p-38,
> +	 0x980000.0p-23, -0xc00000.0p-35,
> +	 0x990000.0p-23, -0xd00000.0p-34,
> +	 0x9a0000.0p-23,  0x880000.0p-33,
> +	 0x9b0000.0p-23,  0xe80000.0p-35,
> +	 0x9c0000.0p-23, -0x800000.0p-35,
> +	 0x9d0000.0p-23,  0xb40000.0p-33,
> +	 0x9e0000.0p-23,  0x880000.0p-34,
> +	 0x9f0000.0p-23, -0xe00000.0p-35,
> +	 0xa00000.0p-23,  0x800000.0p-33,
> +	 0xa10000.0p-23, -0x900000.0p-36,
> +	 0xa20000.0p-23, -0xb00000.0p-33,
> +	 0xa30000.0p-23, -0xa00000.0p-36,
> +	 0xa40000.0p-23,  0x800000.0p-33,
> +	 0xa50000.0p-23, -0xf80000.0p-35,
> +	 0xa60000.0p-23,  0x880000.0p-34,
> +	 0xa70000.0p-23, -0x900000.0p-33,
> +	 0xa80000.0p-23, -0x800000.0p-35,
> +	 0xa90000.0p-23,  0x900000.0p-34,
> +	 0xaa0000.0p-23,  0xa80000.0p-33,
> +	 0xab0000.0p-23, -0xac0000.0p-34,
> +	 0xac0000.0p-23, -0x800000.0p-37,
> +	 0xad0000.0p-23,  0xf80000.0p-35,
> +	 0xae0000.0p-23,  0xf80000.0p-34,
> +	 0xaf0000.0p-23, -0xac0000.0p-33,
> +	 0xb00000.0p-23, -0x800000.0p-33,
> +	 0xb10000.0p-23, -0xb80000.0p-34,
> +	 0xb20000.0p-23, -0x800000.0p-34,
> +	 0xb30000.0p-23, -0xb00000.0p-35,
> +	 0xb40000.0p-23, -0x800000.0p-35,
> +	 0xb50000.0p-23, -0xe00000.0p-36,
> +	 0xb60000.0p-23, -0x800000.0p-35,
> +	 0xb70000.0p-23, -0xb00000.0p-35,
> +	 0xb80000.0p-23, -0x800000.0p-34,
> +	 0xb90000.0p-23, -0xb80000.0p-34,
> +	 0xba0000.0p-23, -0x800000.0p-33,
> +	 0xbb0000.0p-23, -0xac0000.0p-33,
> +	 0xbc0000.0p-23,  0x980000.0p-33,
> +	 0xbd0000.0p-23,  0xbc0000.0p-34,
> +	 0xbe0000.0p-23,  0xe00000.0p-36,
> +	 0xbf0000.0p-23, -0xb80000.0p-35,
> +	 0xc00000.0p-23, -0x800000.0p-33,
> +	 0xc10000.0p-23,  0xa80000.0p-33,
> +	 0xc20000.0p-23,  0x900000.0p-34,
> +	 0xc30000.0p-23, -0x800000.0p-35,
> +	 0xc40000.0p-23, -0x900000.0p-33,
> +	 0xc50000.0p-23,  0x820000.0p-33,
> +	 0xc60000.0p-23,  0x800000.0p-38,
> +	 0xc70000.0p-23, -0x820000.0p-33,
> +	 0xc80000.0p-23,  0x800000.0p-33,
> +	 0xc90000.0p-23, -0xa00000.0p-36,
> +	 0xca0000.0p-23, -0xb00000.0p-33,
> +	 0xcb0000.0p-23,  0x840000.0p-34,
> +	 0xcc0000.0p-23, -0xd00000.0p-34,
> +	 0xcd0000.0p-23,  0x800000.0p-33,
> +	 0xce0000.0p-23, -0xe00000.0p-35,
> +	 0xcf0000.0p-23,  0xa60000.0p-33,
> +	 0xd00000.0p-23, -0x800000.0p-35,
> +	 0xd10000.0p-23,  0xb40000.0p-33,
> +	 0xd20000.0p-23, -0x800000.0p-35,
> +	 0xd30000.0p-23,  0xaa0000.0p-33,
> +	 0xd40000.0p-23, -0xe00000.0p-35,
> +	 0xd50000.0p-23,  0x880000.0p-33,
> +	 0xd60000.0p-23, -0xd00000.0p-34,
> +	 0xd70000.0p-23,  0x9c0000.0p-34,
> +	 0xd80000.0p-23, -0xb00000.0p-33,
> +	 0xd90000.0p-23, -0x800000.0p-38,
> +	 0xda0000.0p-23,  0xa40000.0p-33,
> +	 0xdb0000.0p-23, -0xdc0000.0p-34,
> +	 0xdc0000.0p-23,  0xc00000.0p-35,
> +	 0xdd0000.0p-23,  0xca0000.0p-33,
> +	 0xde0000.0p-23, -0xb80000.0p-34,
> +	 0xdf0000.0p-23,  0xd00000.0p-35,
> +	 0xe00000.0p-23,  0xc00000.0p-33,
> +	 0xe10000.0p-23, -0xf40000.0p-34,
> +	 0xe20000.0p-23,  0x800000.0p-37,
> +	 0xe30000.0p-23,  0x860000.0p-33,
> +	 0xe40000.0p-23, -0xc80000.0p-33,
> +	 0xe50000.0p-23, -0xa80000.0p-34,
> +	 0xe60000.0p-23,  0xe00000.0p-36,
> +	 0xe70000.0p-23,  0x880000.0p-33,
> +	 0xe80000.0p-23, -0xe00000.0p-33,
> +	 0xe90000.0p-23, -0xfc0000.0p-34,
> +	 0xea0000.0p-23, -0x800000.0p-35,
> +	 0xeb0000.0p-23,  0xe80000.0p-35,
> +	 0xec0000.0p-23,  0x900000.0p-33,
> +	 0xed0000.0p-23,  0xe20000.0p-33,
> +	 0xee0000.0p-23, -0xac0000.0p-33,
> +	 0xef0000.0p-23, -0xc80000.0p-34,
> +	 0xf00000.0p-23, -0x800000.0p-35,
> +	 0xf10000.0p-23,  0x800000.0p-35,
> +	 0xf20000.0p-23,  0xb80000.0p-34,
> +	 0xf30000.0p-23,  0x940000.0p-33,
> +	 0xf40000.0p-23,  0xc80000.0p-33,
> +	 0xf50000.0p-23, -0xf20000.0p-33,
> +	 0xf60000.0p-23, -0xc80000.0p-33,
> +	 0xf70000.0p-23, -0xa20000.0p-33,
> +	 0xf80000.0p-23, -0x800000.0p-33,
> +	 0xf90000.0p-23, -0xc40000.0p-34,
> +	 0xfa0000.0p-23, -0x900000.0p-34,
> +	 0xfb0000.0p-23, -0xc80000.0p-35,
> +	 0xfc0000.0p-23, -0x800000.0p-35,
> +	 0xfd0000.0p-23, -0x900000.0p-36,
> +	 0xfe0000.0p-23, -0x800000.0p-37,
> +	 0xff0000.0p-23, -0x800000.0p-39,
> +	 0x800000.0p-22,  0,
> +};
> +#endif /* USE_UTAB */
> +
> +#ifdef STRUCT_RETURN
> +#define	RETURN1(rp, v) do {	\
> +	(rp)->hi = (v);		\
> +	(rp)->lo_set = 0;	\
> +	return;			\
> +} while (0)
> +
> +#define	RETURN2(rp, h, l) do {	\
> +	(rp)->hi = (h);		\
> +	(rp)->lo = (l);		\
> +	(rp)->lo_set = 1;	\
> +	return;			\
> +} while (0)
> +
> +struct ld {
> +	long double hi;
> +	long double lo;
> +	int	lo_set;
> +};
> +#else
> +#define	RETURN1(rp, v)	RETURNF(v)
> +#define	RETURN2(rp, h, l)	RETURNI((h) + (l))
> +#endif
> +
> +#ifdef STRUCT_RETURN
> +static inline __always_inline void
> +k_logl(long double x, struct ld *rp)
> +#else
> +long double
> +logl(long double x)
> +#endif
> +{
> +	long double d, val_hi, val_lo;
> +	double dd, dk;
> +	uint64_t lx, llx;
> +	int i, k;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +	k = -16383;
> +#if 0 /* Hard to do efficiently.  Don't do it until we support all modes. */
> +	if (x == 1)
> +		RETURN1(rp, 0);		/* log(1) = +0 in all rounding modes */
> +#endif
> +	if (hx == 0 || hx >= 0x8000) {	/* zero, negative or subnormal? */
> +		if (((hx & 0x7fff) | lx | llx) == 0)
> +			RETURN1(rp, -1 / zero);	/* log(+-0) = -Inf */
> +		if (hx != 0)
> +			/* log(neg or NaN) = qNaN: */
> +			RETURN1(rp, (x - x) / zero);
> +		x *= 0x1.0p113;		/* subnormal; scale up x */
> +		EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +		k = -16383 - 113;
> +	} else if (hx >= 0x7fff)
> +		RETURN1(rp, x + x);	/* log(Inf or NaN) = Inf or qNaN */
> +#ifndef STRUCT_RETURN
> +	ENTERI();
> +#endif
> +	k += hx;
> +	dk = k;
> +
> +	/* Scale x to be in [1, 2). */
> +	SET_LDBL_EXPSIGN(x, 0x3fff);
> +
> +	/* 0 <= i <= INTERVALS: */
> +#define	L2I	(49 - LOG2_INTERVALS)
> +	i = (lx + (1LL << (L2I - 2))) >> (L2I - 1);
> +
> +	/*
> +	 * -0.005280 < d < 0.004838.  In particular, the infinite-
> +	 * precision |d| is <= 2**-7.  Rounding of G(i) to 8 bits
> +	 * ensures that d is representable without extra precision for
> +	 * this bound on |d| (since when this calculation is expressed
> +	 * as x*G(i)-1, the multiplication needs as many extra bits as
> +	 * G(i) has and the subtraction cancels 8 bits).  But for
> +	 * most i (107 cases out of 129), the infinite-precision |d|
> +	 * is <= 2**-8.  G(i) is rounded to 9 bits for such i to give
> +	 * better accuracy (this works by improving the bound on |d|,
> +	 * which in turn allows rounding to 9 bits in more cases).
> +	 * This is only important when the original x is near 1 -- it
> +	 * lets us avoid using a special method to give the desired
> +	 * accuracy for such x.
> +	 */
> +	if (0)
> +		d = x * G(i) - 1;
> +	else {
> +#ifdef USE_UTAB
> +		d = (x - H(i)) * G(i) + E(i);
> +#else
> +		long double x_hi;
> +		double x_lo;
> +
> +		/*
> +		 * Split x into x_hi + x_lo to calculate x*G(i)-1 exactly.
> +		 * G(i) has at most 9 bits, so the splitting point is not
> +		 * critical.
> +		 */
> +		INSERT_LDBL128_WORDS(x_hi, 0x3fff, lx,
> +		    llx & 0xffffffffff000000ULL);
> +		x_lo = x - x_hi;
> +		d = x_hi * G(i) - 1 + x_lo * G(i);
> +#endif
> +	}
> +
> +	/*
> +	 * Our algorithm depends on exact cancellation of F_lo(i) and
> +	 * F_hi(i) with dk*ln_2_lo and dk*ln2_hi when k is -1 and i is
> +	 * at the end of the table.  This and other technical complications
> +	 * make it difficult to avoid the double scaling in (dk*ln2) *
> +	 * log(base) for base != e without losing more accuracy and/or
> +	 * efficiency than is gained.
> +	 */
> +	/*
> +	 * Use double precision operations wherever possible, since
> +	 * long double operations are emulated and were very slow on
> +	 * the old sparc64 and unknown on the newer aarch64 and riscv
> +	 * machines.  Also, don't try to improve parallelism by
> +	 * increasing the number of operations, since any parallelism
> +	 * on such machines is needed for the emulation.  Horner's
> +	 * method is good for this, and is also good for accuracy.
> +	 * Horner's method doesn't handle the `lo' term well, either
> +	 * for efficiency or accuracy.  However, for accuracy we
> +	 * evaluate d * d * P2 separately to take advantage of by P2
> +	 * being exact, and this gives a good place to sum the 'lo'
> +	 * term too.
> +	 */
> +	dd = (double)d;
> +	val_lo = d * d * d * (P3 +
> +	    d * (P4 + d * (P5 + d * (P6 + d * (P7 + d * (P8 +
> +	    dd * (P9 + dd * (P10 + dd * (P11 + dd * (P12 + dd * (P13 +
> +	    dd * P14))))))))))) + (F_lo(i) + dk * ln2_lo) + d * d * P2;
> +	val_hi = d;
> +#ifdef DEBUG
> +	if (fetestexcept(FE_UNDERFLOW))
> +		breakpoint();
> +#endif
> +
> +	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
> +	RETURN2(rp, val_hi, val_lo);
> +}
> +
> +long double
> +log1pl(long double x)
> +{
> +	long double d, d_hi, f_lo, val_hi, val_lo;
> +	long double f_hi, twopminusk;
> +	double d_lo, dd, dk;
> +	uint64_t lx, llx;
> +	int i, k;
> +	int16_t ax, hx;
> +
> +	DOPRINT_START(&x);
> +	EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +	if (hx < 0x3fff) {		/* x < 1, or x neg NaN */
> +		ax = hx & 0x7fff;
> +		if (ax >= 0x3fff) {	/* x <= -1, or x neg NaN */
> +			if (ax == 0x3fff && (lx | llx) == 0)
> +				RETURNP(-1 / zero);	/* log1p(-1) = -Inf */
> +			/* log1p(x < 1, or x NaN) = qNaN: */
> +			RETURNP((x - x) / (x - x));
> +		}
> +		if (ax <= 0x3f8d) {	/* |x| < 2**-113 */
> +			if ((int)x == 0)
> +				RETURNP(x);	/* x with inexact if x != 0 */
> +		}
> +		f_hi = 1;
> +		f_lo = x;
> +	} else if (hx >= 0x7fff) {	/* x +Inf or non-neg NaN */
> +		RETURNP(x + x);		/* log1p(Inf or NaN) = Inf or qNaN */
> +	} else if (hx < 0x40e1) {	/* 1 <= x < 2**226 */
> +		f_hi = x;
> +		f_lo = 1;
> +	} else {			/* 2**226 <= x < +Inf */
> +		f_hi = x;
> +		f_lo = 0;		/* avoid underflow of the P3 term */
> +	}
> +	ENTERI();
> +	x = f_hi + f_lo;
> +	f_lo = (f_hi - x) + f_lo;
> +
> +	EXTRACT_LDBL128_WORDS(hx, lx, llx, x);
> +	k = -16383;
> +
> +	k += hx;
> +	dk = k;
> +
> +	SET_LDBL_EXPSIGN(x, 0x3fff);
> +	twopminusk = 1;
> +	SET_LDBL_EXPSIGN(twopminusk, 0x7ffe - (hx & 0x7fff));
> +	f_lo *= twopminusk;
> +
> +	i = (lx + (1LL << (L2I - 2))) >> (L2I - 1);
> +
> +	/*
> +	 * x*G(i)-1 (with a reduced x) can be represented exactly, as
> +	 * above, but now we need to evaluate the polynomial on d =
> +	 * (x+f_lo)*G(i)-1 and extra precision is needed for that.
> +	 * Since x+x_lo is a hi+lo decomposition and subtracting 1
> +	 * doesn't lose too many bits, an inexact calculation for
> +	 * f_lo*G(i) is good enough.
> +	 */
> +	if (0)
> +		d_hi = x * G(i) - 1;
> +	else {
> +#ifdef USE_UTAB
> +		d_hi = (x - H(i)) * G(i) + E(i);
> +#else
> +		long double x_hi;
> +		double x_lo;
> +
> +		INSERT_LDBL128_WORDS(x_hi, 0x3fff, lx,
> +		    llx & 0xffffffffff000000ULL);
> +		x_lo = x - x_hi;
> +		d_hi = x_hi * G(i) - 1 + x_lo * G(i);
> +#endif
> +	}
> +	d_lo = f_lo * G(i);
> +
> +	/*
> +	 * This is _2sumF(d_hi, d_lo) inlined.  The condition
> +	 * (d_hi == 0 || |d_hi| >= |d_lo|) for using _2sumF() is not
> +	 * always satisifed, so it is not clear that this works, but
> +	 * it works in practice.  It works even if it gives a wrong
> +	 * normalized d_lo, since |d_lo| > |d_hi| implies that i is
> +	 * nonzero and d is tiny, so the F(i) term dominates d_lo.
> +	 * In float precision:
> +	 * (By exhaustive testing, the worst case is d_hi = 0x1.bp-25.
> +	 * And if d is only a little tinier than that, we would have
> +	 * another underflow problem for the P3 term; this is also ruled
> +	 * out by exhaustive testing.)
> +	 */
> +	d = d_hi + d_lo;
> +	d_lo = d_hi - d + d_lo;
> +	d_hi = d;
> +
> +	dd = (double)d;
> +	val_lo = d * d * d * (P3 +
> +	    d * (P4 + d * (P5 + d * (P6 + d * (P7 + d * (P8 +
> +	    dd * (P9 + dd * (P10 + dd * (P11 + dd * (P12 + dd * (P13 +
> +	    dd * P14))))))))))) + (F_lo(i) + dk * ln2_lo + d_lo) + d * d * P2;
> +	val_hi = d_hi;
> +#ifdef DEBUG
> +	if (fetestexcept(FE_UNDERFLOW))
> +		breakpoint();
> +#endif
> +
> +	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
> +	RETURN2PI(val_hi, val_lo);
> +}
> +
> +#ifdef STRUCT_RETURN
> +
> +long double
> +logl(long double x)
> +{
> +	struct ld r;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	RETURNSPI(&r);
> +}
> +
> +/*
> + * 29+113 bit decompositions.  The bits are distributed so that the products
> + * of the hi terms are exact in double precision.  The types are chosen so
> + * that the products of the hi terms are done in at least double precision,
> + * without any explicit conversions.  More natural choices would require a
> + * slow long double precision multiplication.
> + */
> +static const double
> +invln10_hi =  4.3429448176175356e-1,		/*  0x1bcb7b15000000.0p-54 */
> +invln2_hi =  1.4426950402557850e0;		/*  0x17154765000000.0p-52 */
> +static const long double
> +invln10_lo =  1.41498268538580090791605082294397000e-10L,	/*  0x137287195355baaafad33dc323ee3.0p-145L */
> +invln2_lo =  6.33178418956604368501892137426645911e-10L,	/*  0x15c17f0bbbe87fed0691d3e88eb57.0p-143L */
> +invln10_lo_plus_hi = invln10_lo + invln10_hi,
> +invln2_lo_plus_hi = invln2_lo + invln2_hi;
> +
> +long double
> +log10l(long double x)
> +{
> +	struct ld r;
> +	long double hi, lo;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	if (!r.lo_set)
> +		RETURNPI(r.hi);
> +	_2sumF(r.hi, r.lo);
> +	hi = (float)r.hi;
> +	lo = r.lo + (r.hi - hi);
> +	RETURN2PI(invln10_hi * hi,
> +	    invln10_lo_plus_hi * lo + invln10_lo * hi);
> +}
> +
> +long double
> +log2l(long double x)
> +{
> +	struct ld r;
> +	long double hi, lo;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	if (!r.lo_set)
> +		RETURNPI(r.hi);
> +	_2sumF(r.hi, r.lo);
> +	hi = (float)r.hi;
> +	lo = r.lo + (r.hi - hi);
> +	RETURN2PI(invln2_hi * hi,
> +	    invln2_lo_plus_hi * lo + invln2_lo * hi);
> +}
> +
> +#endif /* STRUCT_RETURN */
> diff --git a/newlib/libm/ld80/b_expl.c b/newlib/libm/ld80/b_expl.c
> new file mode 100644
> index 000000000..21bacf449
> --- /dev/null
> +++ b/newlib/libm/ld80/b_expl.c
> @@ -0,0 +1,113 @@
> +/*-
> + * SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 1985, 1993
> + *	The Regents of the University of California.  All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the University nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/*
> + * See bsdsrc/b_exp.c for implementation details.
> + *
> + * bsdrc/b_exp.c converted to long double by Steven G. Kargl.
> + */
> +
> +#include "fpmath.h"
> +#include "math_private.h"
> +
> +static const union IEEEl2bits
> +    p0u = LD80C(0xaaaaaaaaaaaaaaab,    -3,  1.66666666666666666671e-01L),
> +    p1u = LD80C(0xb60b60b60b60b59a,    -9, -2.77777777777777775377e-03L),
> +    p2u = LD80C(0x8ab355e008a3cfce,   -14,  6.61375661375629297465e-05L),
> +    p3u = LD80C(0xddebbc994b0c1376,   -20, -1.65343915327882529784e-06L),
> +    p4u = LD80C(0xb354784cb4ef4c41,   -25,  4.17535101591534118469e-08L),
> +    p5u = LD80C(0x913e8a718382ce75,   -30, -1.05679137034774806475e-09L),
> +    p6u = LD80C(0xe8f0042aa134502e,   -36,  2.64819349895429516863e-11L);
> +#define	p1	(p0u.e)
> +#define	p2	(p1u.e)
> +#define	p3	(p2u.e)
> +#define	p4	(p3u.e)
> +#define	p5	(p4u.e)
> +#define	p6	(p5u.e)
> +#define	p7	(p6u.e)
> +
> +/*
> + * lnhuge = (LDBL_MAX_EXP + 9) * log(2.)
> + * lntiny = (LDBL_MIN_EXP - 64 - 10) * log(2.)
> + * invln2 = 1 / log(2.)
> + */
> +static const union IEEEl2bits
> +ln2hiu  = LD80C(0xb17217f700000000,  -1,  6.93147180369123816490e-01L),
> +ln2lou  = LD80C(0xd1cf79abc9e3b398, -33,  1.90821492927058781614e-10L),
> +lnhugeu = LD80C(0xb18b0c0330a8fad9,  13,  1.13627617309191834574e+04L),
> +lntinyu = LD80C(0xb236f28a68bc3bd7,  13, -1.14057368561139000667e+04L),
> +invln2u = LD80C(0xb8aa3b295c17f0bc,   0,  1.44269504088896340739e+00L);
> +#define	ln2hi	(ln2hiu.e)
> +#define ln2lo	(ln2lou.e)
> +#define lnhuge	(lnhugeu.e)
> +#define	lntiny	(lntinyu.e)
> +#define	invln2	(invln2u.e)
> +
> +/* returns exp(r = x + c) for |c| < |x| with no overlap.  */
> +
> +static long double
> +__exp__D(long double x, long double c)
> +{
> +	long double hi, lo, z;
> +	int k;
> +
> +	if (x != x)	/* x is NaN. */
> +		return(x);
> +
> +	if (x <= lnhuge) {
> +		if (x >= lntiny) {
> +			/* argument reduction: x --> x - k*ln2 */
> +			z = invln2 * x;
> +			k = z + copysignl(0.5L, x);
> +
> +		    	/*
> +			 * Express (x + c) - k * ln2 as hi - lo.
> +			 * Let x = hi - lo rounded.
> +			 */
> +			hi = x - k * ln2hi;	/* Exact. */
> +			lo = k * ln2lo - c;
> +			x = hi - lo;
> +
> +			/* Return 2^k*[1+x+x*c/(2+c)]  */
> +			z = x * x;
> +			c = x - z * (p1 + z * (p2 + z * (p3 + z * (p4 +
> +			    z * (p5 + z * (p6 + z * p7))))));
> +			c = (x * c) / (2 - c);
> +
> +			return (ldexpl(1 + (hi - (lo - c)), k));
> +		} else {
> +			/* exp(-INF) is 0. exp(-big) underflows to 0.  */
> +			return (isfinite(x) ? ldexpl(1., -5000) : 0);
> +		}
> +	} else
> +		/* exp(INF) is INF, exp(+big#) overflows to INF */
> +		return (isfinite(x) ? ldexpl(1., 5000) : x);
> +}
> diff --git a/newlib/libm/ld80/b_logl.c b/newlib/libm/ld80/b_logl.c
> new file mode 100644
> index 000000000..b11eacbe1
> --- /dev/null
> +++ b/newlib/libm/ld80/b_logl.c
> @@ -0,0 +1,375 @@
> +/*-
> + * SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 1992, 1993
> + *	The Regents of the University of California.  All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the University nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/*
> + * See bsdsrc/b_log.c for implementation details.
> + *
> + * bsdrc/b_log.c converted to long double by Steven G. Kargl.
> + */
> +
> +#define N 128
> +
> +/*
> + * Coefficients in the polynomial approximation of log(1+f/F).
> + * Domain of x is [0,1./256] with 2**(-84.48) precision.
> + */
> +static const union IEEEl2bits
> +    a1u = LD80C(0xaaaaaaaaaaaaaaab,    -4,  8.33333333333333333356e-02L),
> +    a2u = LD80C(0xcccccccccccccd29,    -7,  1.25000000000000000781e-02L),
> +    a3u = LD80C(0x9249249241ed3764,    -9,  2.23214285711721994134e-03L),
> +    a4u = LD80C(0xe38e959e1e7e01cf,   -12,  4.34030476540000360640e-04L);
> +#define	A1	(a1u.e)
> +#define	A2	(a2u.e)
> +#define	A3	(a3u.e)
> +#define	A4	(a4u.e)
> +
> +/*
> + * Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128.
> + * Used for generation of extend precision logarithms.
> + * The constant 35184372088832 is 2^45, so the divide is exact.
> + * It ensures correct reading of logF_head, even for inaccurate
> + * decimal-to-binary conversion routines.  (Everybody gets the
> + * right answer for integers less than 2^53.)
> + * Values for log(F) were generated using error < 10^-57 absolute
> + * with the bc -l package.
> + */
> +
> +static double logF_head[N+1] = {
> +	0.,
> +	.007782140442060381246,
> +	.015504186535963526694,
> +	.023167059281547608406,
> +	.030771658666765233647,
> +	.038318864302141264488,
> +	.045809536031242714670,
> +	.053244514518837604555,
> +	.060624621816486978786,
> +	.067950661908525944454,
> +	.075223421237524235039,
> +	.082443669210988446138,
> +	.089612158689760690322,
> +	.096729626458454731618,
> +	.103796793681567578460,
> +	.110814366340264314203,
> +	.117783035656430001836,
> +	.124703478501032805070,
> +	.131576357788617315236,
> +	.138402322859292326029,
> +	.145182009844575077295,
> +	.151916042025732167530,
> +	.158605030176659056451,
> +	.165249572895390883786,
> +	.171850256926518341060,
> +	.178407657472689606947,
> +	.184922338493834104156,
> +	.191394852999565046047,
> +	.197825743329758552135,
> +	.204215541428766300668,
> +	.210564769107350002741,
> +	.216873938300523150246,
> +	.223143551314024080056,
> +	.229374101064877322642,
> +	.235566071312860003672,
> +	.241719936886966024758,
> +	.247836163904594286577,
> +	.253915209980732470285,
> +	.259957524436686071567,
> +	.265963548496984003577,
> +	.271933715484010463114,
> +	.277868451003087102435,
> +	.283768173130738432519,
> +	.289633292582948342896,
> +	.295464212893421063199,
> +	.301261330578199704177,
> +	.307025035294827830512,
> +	.312755710004239517729,
> +	.318453731118097493890,
> +	.324119468654316733591,
> +	.329753286372579168528,
> +	.335355541920762334484,
> +	.340926586970454081892,
> +	.346466767346100823488,
> +	.351976423156884266063,
> +	.357455888922231679316,
> +	.362905493689140712376,
> +	.368325561158599157352,
> +	.373716409793814818840,
> +	.379078352934811846353,
> +	.384411698910298582632,
> +	.389716751140440464951,
> +	.394993808240542421117,
> +	.400243164127459749579,
> +	.405465108107819105498,
> +	.410659924985338875558,
> +	.415827895143593195825,
> +	.420969294644237379543,
> +	.426084395310681429691,
> +	.431173464818130014464,
> +	.436236766774527495726,
> +	.441274560805140936281,
> +	.446287102628048160113,
> +	.451274644139630254358,
> +	.456237433481874177232,
> +	.461175715122408291790,
> +	.466089729924533457960,
> +	.470979715219073113985,
> +	.475845904869856894947,
> +	.480688529345570714212,
> +	.485507815781602403149,
> +	.490303988045525329653,
> +	.495077266798034543171,
> +	.499827869556611403822,
> +	.504556010751912253908,
> +	.509261901790523552335,
> +	.513945751101346104405,
> +	.518607764208354637958,
> +	.523248143765158602036,
> +	.527867089620485785417,
> +	.532464798869114019908,
> +	.537041465897345915436,
> +	.541597282432121573947,
> +	.546132437597407260909,
> +	.550647117952394182793,
> +	.555141507540611200965,
> +	.559615787935399566777,
> +	.564070138285387656651,
> +	.568504735352689749561,
> +	.572919753562018740922,
> +	.577315365035246941260,
> +	.581691739635061821900,
> +	.586049045003164792433,
> +	.590387446602107957005,
> +	.594707107746216934174,
> +	.599008189645246602594,
> +	.603290851438941899687,
> +	.607555250224322662688,
> +	.611801541106615331955,
> +	.616029877215623855590,
> +	.620240409751204424537,
> +	.624433288012369303032,
> +	.628608659422752680256,
> +	.632766669570628437213,
> +	.636907462236194987781,
> +	.641031179420679109171,
> +	.645137961373620782978,
> +	.649227946625615004450,
> +	.653301272011958644725,
> +	.657358072709030238911,
> +	.661398482245203922502,
> +	.665422632544505177065,
> +	.669430653942981734871,
> +	.673422675212350441142,
> +	.677398823590920073911,
> +	.681359224807238206267,
> +	.685304003098281100392,
> +	.689233281238557538017,
> +	.693147180560117703862
> +};
> +
> +static double logF_tail[N+1] = {
> +	0.,
> +	-.00000000000000543229938420049,
> +	 .00000000000000172745674997061,
> +	-.00000000000001323017818229233,
> +	-.00000000000001154527628289872,
> +	-.00000000000000466529469958300,
> +	 .00000000000005148849572685810,
> +	-.00000000000002532168943117445,
> +	-.00000000000005213620639136504,
> +	-.00000000000001819506003016881,
> +	 .00000000000006329065958724544,
> +	 .00000000000008614512936087814,
> +	-.00000000000007355770219435028,
> +	 .00000000000009638067658552277,
> +	 .00000000000007598636597194141,
> +	 .00000000000002579999128306990,
> +	-.00000000000004654729747598444,
> +	-.00000000000007556920687451336,
> +	 .00000000000010195735223708472,
> +	-.00000000000017319034406422306,
> +	-.00000000000007718001336828098,
> +	 .00000000000010980754099855238,
> +	-.00000000000002047235780046195,
> +	-.00000000000008372091099235912,
> +	 .00000000000014088127937111135,
> +	 .00000000000012869017157588257,
> +	 .00000000000017788850778198106,
> +	 .00000000000006440856150696891,
> +	 .00000000000016132822667240822,
> +	-.00000000000007540916511956188,
> +	-.00000000000000036507188831790,
> +	 .00000000000009120937249914984,
> +	 .00000000000018567570959796010,
> +	-.00000000000003149265065191483,
> +	-.00000000000009309459495196889,
> +	 .00000000000017914338601329117,
> +	-.00000000000001302979717330866,
> +	 .00000000000023097385217586939,
> +	 .00000000000023999540484211737,
> +	 .00000000000015393776174455408,
> +	-.00000000000036870428315837678,
> +	 .00000000000036920375082080089,
> +	-.00000000000009383417223663699,
> +	 .00000000000009433398189512690,
> +	 .00000000000041481318704258568,
> +	-.00000000000003792316480209314,
> +	 .00000000000008403156304792424,
> +	-.00000000000034262934348285429,
> +	 .00000000000043712191957429145,
> +	-.00000000000010475750058776541,
> +	-.00000000000011118671389559323,
> +	 .00000000000037549577257259853,
> +	 .00000000000013912841212197565,
> +	 .00000000000010775743037572640,
> +	 .00000000000029391859187648000,
> +	-.00000000000042790509060060774,
> +	 .00000000000022774076114039555,
> +	 .00000000000010849569622967912,
> +	-.00000000000023073801945705758,
> +	 .00000000000015761203773969435,
> +	 .00000000000003345710269544082,
> +	-.00000000000041525158063436123,
> +	 .00000000000032655698896907146,
> +	-.00000000000044704265010452446,
> +	 .00000000000034527647952039772,
> +	-.00000000000007048962392109746,
> +	 .00000000000011776978751369214,
> +	-.00000000000010774341461609578,
> +	 .00000000000021863343293215910,
> +	 .00000000000024132639491333131,
> +	 .00000000000039057462209830700,
> +	-.00000000000026570679203560751,
> +	 .00000000000037135141919592021,
> +	-.00000000000017166921336082431,
> +	-.00000000000028658285157914353,
> +	-.00000000000023812542263446809,
> +	 .00000000000006576659768580062,
> +	-.00000000000028210143846181267,
> +	 .00000000000010701931762114254,
> +	 .00000000000018119346366441110,
> +	 .00000000000009840465278232627,
> +	-.00000000000033149150282752542,
> +	-.00000000000018302857356041668,
> +	-.00000000000016207400156744949,
> +	 .00000000000048303314949553201,
> +	-.00000000000071560553172382115,
> +	 .00000000000088821239518571855,
> +	-.00000000000030900580513238244,
> +	-.00000000000061076551972851496,
> +	 .00000000000035659969663347830,
> +	 .00000000000035782396591276383,
> +	-.00000000000046226087001544578,
> +	 .00000000000062279762917225156,
> +	 .00000000000072838947272065741,
> +	 .00000000000026809646615211673,
> +	-.00000000000010960825046059278,
> +	 .00000000000002311949383800537,
> +	-.00000000000058469058005299247,
> +	-.00000000000002103748251144494,
> +	-.00000000000023323182945587408,
> +	-.00000000000042333694288141916,
> +	-.00000000000043933937969737844,
> +	 .00000000000041341647073835565,
> +	 .00000000000006841763641591466,
> +	 .00000000000047585534004430641,
> +	 .00000000000083679678674757695,
> +	-.00000000000085763734646658640,
> +	 .00000000000021913281229340092,
> +	-.00000000000062242842536431148,
> +	-.00000000000010983594325438430,
> +	 .00000000000065310431377633651,
> +	-.00000000000047580199021710769,
> +	-.00000000000037854251265457040,
> +	 .00000000000040939233218678664,
> +	 .00000000000087424383914858291,
> +	 .00000000000025218188456842882,
> +	-.00000000000003608131360422557,
> +	-.00000000000050518555924280902,
> +	 .00000000000078699403323355317,
> +	-.00000000000067020876961949060,
> +	 .00000000000016108575753932458,
> +	 .00000000000058527188436251509,
> +	-.00000000000035246757297904791,
> +	-.00000000000018372084495629058,
> +	 .00000000000088606689813494916,
> +	 .00000000000066486268071468700,
> +	 .00000000000063831615170646519,
> +	 .00000000000025144230728376072,
> +	-.00000000000017239444525614834
> +};
> +/*
> + * Extra precision variant, returning struct {double a, b;};
> + * log(x) = a + b to 63 bits, with 'a' rounded to 24 bits.
> + */
> +static struct Double
> +__log__D(long double x)
> +{
> +	int m, j;
> +	long double F, f, g, q, u, v, u1, u2;
> +	struct Double r;
> +
> +	/*
> +	 * Argument reduction: 1 <= g < 2; x/2^m = g;
> +	 * y = F*(1 + f/F) for |f| <= 2^-8
> +	 */
> +	g = frexpl(x, &m);
> +	g *= 2;
> +	m--;
> +	if (m == DBL_MIN_EXP - 1) {
> +		j = ilogbl(g);
> +		m += j;
> +		g = ldexpl(g, -j);
> +	}
> +	j = N * (g - 1) + 0.5L;
> +	F = (1.L / N) * j + 1;
> +	f = g - F;
> +
> +	g = 1 / (2 * F + f);
> +	u = 2 * f * g;
> +	v = u * u;
> +	q = u * v * (A1 + v * (A2 + v * (A3 + v * A4)));
> +	if (m | j) {
> +		u1 = u + 513;
> +		u1 -= 513;
> +	} else {
> +		u1 = (float)u;
> +	}
> +	u2 = (2 * (f - F * u1) - u1 * f) * g;
> +
> +	u1 += m * (long double)logF_head[N] + logF_head[j];
> +
> +	u2 += logF_tail[j];
> +	u2 += q;
> +	u2 += logF_tail[N] * m;
> +	r.a = (float)(u1 + u2);		/* Only difference is here. */
> +	r.b = (u1 - r.a) + u2;
> +	return (r);
> +}
> diff --git a/newlib/libm/ld80/b_tgammal.c b/newlib/libm/ld80/b_tgammal.c
> new file mode 100644
> index 000000000..121248adb
> --- /dev/null
> +++ b/newlib/libm/ld80/b_tgammal.c
> @@ -0,0 +1,419 @@
> +/*-
> + * SPDX-License-Identifier: BSD-3-Clause
> + *
> + * Copyright (c) 1992, 1993
> + *	The Regents of the University of California.  All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + * 3. Neither the name of the University nor the names of its contributors
> + *    may be used to endorse or promote products derived from this software
> + *    without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +/*
> + * The original code, FreeBSD's old svn r93211, contain the following
> + * attribution:
> + *
> + *    This code by P. McIlroy, Oct 1992;
> + *
> + *    The financial support of UUNET Communications Services is greatfully
> + *    acknowledged.
> + *
> + * bsdrc/b_tgamma.c converted to long double by Steven G. Kargl.
> + */
> +
> +/*
> + * See bsdsrc/t_tgamma.c for implementation details.
> + */
> +
> +#include <float.h>
> +
> +#if LDBL_MAX_EXP != 0x4000
> +#error "Unsupported long double format"
> +#endif
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* Used in b_log.c and below. */
> +struct Double {
> +	long double a;
> +	long double b;
> +};
> +
> +#include "b_logl.c"
> +#include "b_expl.c"
> +
> +static const double zero = 0.;
> +static const volatile double tiny = 1e-300;
> +/*
> + * x >= 6
> + *
> + * Use the asymptotic approximation (Stirling's formula) adjusted for
> + * equal-ripples:
> + *
> + * log(G(x)) ~= (x-0.5)*(log(x)-1) + 0.5(log(2*pi)-1) + 1/x*P(1/(x*x))
> + *
> + * Keep extra precision in multiplying (x-.5)(log(x)-1), to avoid
> + * premature round-off.
> + *
> + * Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
> + */
> +
> +/*
> + * The following is a decomposition of 0.5 * (log(2*pi) - 1) into the
> + * first 12 bits in ln2pi_hi and the trailing 64 bits in ln2pi_lo.  The
> + * variables are clearly misnamed.
> + */
> +static const union IEEEl2bits
> +ln2pi_hiu = LD80C(0xd680000000000000,  -2,  4.18945312500000000000e-01L),
> +ln2pi_lou = LD80C(0xe379b414b596d687, -18, -6.77929532725821967032e-06L);
> +#define	ln2pi_hi	(ln2pi_hiu.e)
> +#define	ln2pi_lo	(ln2pi_lou.e)
> +
> +static const union IEEEl2bits
> +    Pa0u = LD80C(0xaaaaaaaaaaaaaaaa,  -4,  8.33333333333333333288e-02L),
> +    Pa1u = LD80C(0xb60b60b60b5fcd59,  -9, -2.77777777777776516326e-03L),
> +    Pa2u = LD80C(0xd00d00cffbb47014, -11,  7.93650793635429639018e-04L),
> +    Pa3u = LD80C(0x9c09c07c0805343e, -11, -5.95238087960599252215e-04L),
> +    Pa4u = LD80C(0xdca8d31f8e6e5e8f, -11,  8.41749082509607342883e-04L),
> +    Pa5u = LD80C(0xfb4d4289632f1638, -10, -1.91728055205541624556e-03L),
> +    Pa6u = LD80C(0xd15a4ba04078d3f8,  -8,  6.38893788027752396194e-03L),
> +    Pa7u = LD80C(0xe877283110bcad95,  -6, -2.83771309846297590312e-02L),
> +    Pa8u = LD80C(0x8da97eed13717af8,  -3,  1.38341887683837576925e-01L),
> +    Pa9u = LD80C(0xf093b1c1584e30ce,  -2, -4.69876818515470146031e-01L);
> +#define	Pa0	(Pa0u.e)
> +#define	Pa1	(Pa1u.e)
> +#define	Pa2	(Pa2u.e)
> +#define	Pa3	(Pa3u.e)
> +#define	Pa4	(Pa4u.e)
> +#define	Pa5	(Pa5u.e)
> +#define	Pa6	(Pa6u.e)
> +#define	Pa7	(Pa7u.e)
> +#define	Pa8	(Pa8u.e)
> +#define	Pa9	(Pa9u.e)
> +
> +static struct Double
> +large_gam(long double x)
> +{
> +	long double p, z, thi, tlo, xhi, xlo;
> +	long double logx;
> +	struct Double u;
> +
> +	z = 1 / (x * x);
> +	p = Pa0 + z * (Pa1 + z * (Pa2 + z * (Pa3 + z * (Pa4 + z * (Pa5 +
> +	    z * (Pa6 + z * (Pa7 + z * (Pa8 + z * Pa9))))))));
> +	p = p / x;
> +
> +	u = __log__D(x);
> +	u.a -= 1;
> +
> +	/* Split (x - 0.5) in high and low parts. */
> +	x -= 0.5L;
> +	xhi = (float)x;
> +	xlo = x - xhi;
> +
> +	/* Compute  t = (x-.5)*(log(x)-1) in extra precision. */
> +	thi = xhi * u.a;
> +	tlo = xlo * u.a + x * u.b;
> +
> +	/* Compute thi + tlo + ln2pi_hi + ln2pi_lo + p. */
> +	tlo += ln2pi_lo;
> +	tlo += p;
> +	u.a = ln2pi_hi + tlo;
> +	u.a += thi;
> +	u.b = thi - u.a;
> +	u.b += ln2pi_hi;
> +	u.b += tlo;
> +	return (u);
> +}
> +/*
> + * Rational approximation, A0 + x * x * P(x) / Q(x), on the interval
> + * [1.066.., 2.066..] accurate to 4.25e-19.
> + *
> + * Returns r.a + r.b = a0 + (z + c)^2 * p / q, with r.a truncated.
> + */
> +static const union IEEEl2bits
> +    a0_hiu = LD80C(0xe2b6e4153a57746c,  -1, 8.85603194410888700265e-01L),
> +    a0_lou = LD80C(0x851566d40f32c76d, -66, 1.40907742727049706207e-20L);
> +#define	a0_hi	(a0_hiu.e)
> +#define	a0_lo	(a0_lou.e)
> +
> +static const union IEEEl2bits
> +P0u = LD80C(0xdb629fb9bbdc1c1d,    -2,  4.28486815855585429733e-01L),
> +P1u = LD80C(0xe6f4f9f5641aa6be,    -3,  2.25543885805587730552e-01L),
> +P2u = LD80C(0xead1bd99fdaf7cc1,    -6,  2.86644652514293482381e-02L),
> +P3u = LD80C(0x9ccc8b25838ab1e0,    -8,  4.78512567772456362048e-03L),
> +P4u = LD80C(0x8f0c4383ef9ce72a,    -9,  2.18273781132301146458e-03L),
> +P5u = LD80C(0xe732ab2c0a2778da,   -13,  2.20487522485636008928e-04L),
> +P6u = LD80C(0xce70b27ca822b297,   -16,  2.46095923774929264284e-05L),
> +P7u = LD80C(0xa309e2e16fb63663,   -19,  2.42946473022376182921e-06L),
> +P8u = LD80C(0xaf9c110efb2c633d,   -23,  1.63549217667765869987e-07L),
> +Q1u = LD80C(0xd4d7422719f48f15,    -1,  8.31409582658993993626e-01L),
> +Q2u = LD80C(0xe13138ea404f1268,    -5, -5.49785826915643198508e-02L),
> +Q3u = LD80C(0xd1c6cc91989352c0,    -4, -1.02429960435139887683e-01L),
> +Q4u = LD80C(0xa7e9435a84445579,    -7,  1.02484853505908820524e-02L),
> +Q5u = LD80C(0x83c7c34db89b7bda,    -8,  4.02161632832052872697e-03L),
> +Q6u = LD80C(0xbed06bf6e1c14e5b,   -11, -7.27898206351223022157e-04L),
> +Q7u = LD80C(0xef05bf841d4504c0,   -18,  7.12342421869453515194e-06L),
> +Q8u = LD80C(0xf348d08a1ff53cb1,   -19,  3.62522053809474067060e-06L);
> +#define	P0	(P0u.e)
> +#define	P1	(P1u.e)
> +#define	P2	(P2u.e)
> +#define	P3	(P3u.e)
> +#define	P4	(P4u.e)
> +#define	P5	(P5u.e)
> +#define	P6	(P6u.e)
> +#define	P7	(P7u.e)
> +#define	P8	(P8u.e)
> +#define	Q1	(Q1u.e)
> +#define	Q2	(Q2u.e)
> +#define	Q3	(Q3u.e)
> +#define	Q4	(Q4u.e)
> +#define	Q5	(Q5u.e)
> +#define	Q6	(Q6u.e)
> +#define	Q7	(Q7u.e)
> +#define	Q8	(Q8u.e)
> +
> +static struct Double
> +ratfun_gam(long double z, long double c)
> +{
> +	long double p, q, thi, tlo;
> +	struct Double r;
> +
> +	q = 1  + z * (Q1 + z * (Q2 + z * (Q3 + z * (Q4 + z * (Q5 + 
> +	    z * (Q6 + z * (Q7 + z * Q8)))))));
> +	p = P0 + z * (P1 + z * (P2 + z * (P3 + z * (P4 + z * (P5 +
> +	    z * (P6 + z * (P7 + z * P8)))))));
> +	p = p / q;
> +
> +	/* Split z into high and low parts. */
> +	thi = (float)z;
> +	tlo = (z - thi) + c;
> +	tlo *= (thi + z);
> +
> +	/* Split (z+c)^2 into high and low parts. */
> +	thi *= thi;
> +	q = thi;
> +	thi = (float)thi;
> +	tlo += (q - thi);
> +
> +	/* Split p/q into high and low parts. */
> +	r.a = (float)p;
> +	r.b = p - r.a;
> +
> +	tlo = tlo * p + thi * r.b + a0_lo;
> +	thi *= r.a;				/* t = (z+c)^2*(P/Q) */
> +	r.a = (float)(thi + a0_hi);
> +	r.b = ((a0_hi - r.a) + thi) + tlo;
> +	return (r);				/* r = a0 + t */
> +}
> +/*
> + * x < 6
> + *
> + * Use argument reduction G(x+1) = xG(x) to reach the range [1.066124,
> + * 2.066124].  Use a rational approximation centered at the minimum
> + * (x0+1) to ensure monotonicity.
> + *
> + * Good to < 1 ulp.  (provably .90 ulp; .87 ulp on 1,000,000 runs.)
> + * It also has correct monotonicity.
> + */
> +static const union IEEEl2bits
> +  xm1u = LD80C(0xec5b0c6ad7c7edc3, -2, 4.61632144968362341254e-01L);
> +#define	x0	(xm1u.e)
> +
> +static const double
> +    left = -0.3955078125;	/* left boundary for rat. approx */
> +
> +static long double
> +small_gam(long double x)
> +{
> +	long double t, y, ym1;
> +	struct Double yy, r;
> +
> +	y = x - 1;
> +
> +	if (y <= 1 + (left + x0)) {
> +		yy = ratfun_gam(y - x0, 0);
> +		return (yy.a + yy.b);
> +	}
> +
> +	r.a = (float)y;
> +	yy.a = r.a - 1;
> +	y = y - 1 ;
> +	r.b = yy.b = y - yy.a;
> +
> +	/* Argument reduction: G(x+1) = x*G(x) */
> +	for (ym1 = y - 1; ym1 > left + x0; y = ym1--, yy.a--) {
> +		t = r.a * yy.a;
> +		r.b = r.a * yy.b + y * r.b;
> +		r.a = (float)t;
> +		r.b += (t - r.a);
> +	}
> +
> +	/* Return r*tgamma(y). */
> +	yy = ratfun_gam(y - x0, 0);
> +	y = r.b * (yy.a + yy.b) + r.a * yy.b;
> +	y += yy.a * r.a;
> +	return (y);
> +}
> +/*
> + * Good on (0, 1+x0+left].  Accurate to 1 ulp.
> + */
> +static long double
> +smaller_gam(long double x)
> +{
> +	long double d, rhi, rlo, t, xhi, xlo;
> +	struct Double r;
> +
> +	if (x < x0 + left) {
> +		t = (float)x;
> +		d = (t + x) * (x - t);
> +		t *= t;
> +		xhi = (float)(t + x);
> +		xlo = x - xhi;
> +		xlo += t;
> +		xlo += d;
> +		t = 1 - x0;
> +		t += x;
> +		d = 1 - x0;
> +		d -= t;
> +		d += x;
> +		x = xhi + xlo;
> +	} else {
> +		xhi = (float)x;
> +		xlo = x - xhi;
> +		t = x - x0;
> +		d = - x0 - t;
> +		d += x;
> +	}
> +
> +	r = ratfun_gam(t, d);
> +	d = (float)(r.a / x);
> +	r.a -= d * xhi;
> +	r.a -= d * xlo;
> +	r.a += r.b;
> +
> +	return (d + r.a / x);
> +}
> +/*
> + * x < 0
> + *
> + * Use reflection formula, G(x) = pi/(sin(pi*x)*x*G(x)).
> + * At negative integers, return NaN and raise invalid.
> + */
> +static const union IEEEl2bits
> +piu = LD80C(0xc90fdaa22168c235, 1, 3.14159265358979323851e+00L);
> +#define	pi	(piu.e)
> +
> +static long double
> +neg_gam(long double x)
> +{
> +	int sgn = 1;
> +	struct Double lg, lsine;
> +	long double y, z;
> +
> +	y = ceill(x);
> +	if (y == x)		/* Negative integer. */
> +		return ((x - x) / zero);
> +
> +	z = y - x;
> +	if (z > 0.5)
> +		z = 1 - z;
> +
> +	y = y / 2;
> +	if (y == ceill(y))
> +		sgn = -1;
> +
> +	if (z < 0.25)
> +		z = sinpil(z);
> +	else
> +		z = cospil(0.5 - z);
> +
> +	/* Special case: G(1-x) = Inf; G(x) may be nonzero. */
> +	if (x < -1753) {
> +
> +		if (x < -1760)
> +			return (sgn * tiny * tiny);
> +		y = expl(lgammal(x) / 2);
> +		y *= y;
> +		return (sgn < 0 ? -y : y);
> +	}
> +
> +
> +	y = 1 - x;
> +	if (1 - y == x)
> +		y = tgammal(y);
> +	else		/* 1-x is inexact */
> +		y = - x * tgammal(-x);
> +
> +	if (sgn < 0) y = -y;
> +	return (pi / (y * z));
> +}
> +/*
> + * xmax comes from lgamma(xmax) - emax * log(2) = 0.
> + * static const float  xmax = 35.040095f
> + * static const double xmax = 171.624376956302725;
> + * ld80: LD80C(0xdb718c066b352e20, 10, 1.75554834290446291689e+03L),
> + * ld128: 1.75554834290446291700388921607020320e+03L,
> + *
> + * iota is a sloppy threshold to isolate x = 0.
> + */
> +static const double xmax = 1755.54834290446291689;
> +static const double iota = 0x1p-116;
> +
> +long double
> +tgammal(long double x)
> +{
> +	struct Double u;
> +
> +	ENTERI();
> +
> +	if (x >= 6) {
> +		if (x > xmax)
> +			RETURNI(x / zero);
> +		u = large_gam(x);
> +		RETURNI(__exp__D(u.a, u.b));
> +	}
> +
> +	if (x >= 1 + left + x0)
> +		RETURNI(small_gam(x));
> +
> +	if (x > iota)
> +		RETURNI(smaller_gam(x));
> +
> +	if (x > -iota) {
> +		if (x != 0)
> +			u.a = 1 - tiny;	/* raise inexact */
> +		RETURNI(1 / x);
> +	}
> +
> +	if (!isfinite(x))
> +		RETURNI(x - x);		/* x is NaN or -Inf */
> +
> +	RETURNI(neg_gam(x));
> +}
> diff --git a/newlib/libm/ld80/e_lgammal_r.c b/newlib/libm/ld80/e_lgammal_r.c
> new file mode 100644
> index 000000000..f56758b18
> --- /dev/null
> +++ b/newlib/libm/ld80/e_lgammal_r.c
> @@ -0,0 +1,358 @@
> +/* @(#)e_lgamma_r.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See e_lgamma_r.c for complete comments.
> + *
> + * Converted to long double by Steven G. Kargl.
> + */
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const volatile double vzero = 0;
> +
> +static const double
> +zero=  0,
> +half=  0.5,
> +one =  1;
> +
> +static const union IEEEl2bits
> +piu = LD80C(0xc90fdaa22168c235, 1,  3.14159265358979323851e+00L);
> +#define	pi	(piu.e)
> +/*
> + * Domain y in [0x1p-70, 0.27], range ~[-4.5264e-22, 4.5264e-22]:
> + * |(lgamma(2 - y) + y / 2) / y - a(y)| < 2**-70.9
> + */
> +static const union IEEEl2bits
> +a0u = LD80C(0x9e233f1bed863d26, -4,  7.72156649015328606028e-02L),
> +a1u = LD80C(0xa51a6625307d3249, -2,  3.22467033424113218889e-01L),
> +a2u = LD80C(0x89f000d2abafda8c, -4,  6.73523010531979398946e-02L),
> +a3u = LD80C(0xa8991563eca75f26, -6,  2.05808084277991211934e-02L),
> +a4u = LD80C(0xf2027e10634ce6b6, -8,  7.38555102796070454026e-03L),
> +a5u = LD80C(0xbd6eb76dd22187f4, -9,  2.89051035162703932972e-03L),
> +a6u = LD80C(0x9c562ab05e0458ed, -10,  1.19275351624639999297e-03L),
> +a7u = LD80C(0x859baed93ee48e46, -11,  5.09674593842117925320e-04L),
> +a8u = LD80C(0xe9f28a4432949af2, -13,  2.23109648015769155122e-04L),
> +a9u = LD80C(0xd12ad0d9b93c6bb0, -14,  9.97387167479808509830e-05L),
> +a10u= LD80C(0xb7522643c78a219b, -15,  4.37071076331030136818e-05L),
> +a11u= LD80C(0xca024dcdece2cb79, -16,  2.40813493372040143061e-05L),
> +a12u= LD80C(0xbb90fb6968ebdbf9, -19,  2.79495621083634031729e-06L),
> +a13u= LD80C(0xba1c9ffeeae07b37, -17,  1.10931287015513924136e-05L);
> +#define	a0	(a0u.e)
> +#define	a1	(a1u.e)
> +#define	a2	(a2u.e)
> +#define	a3	(a3u.e)
> +#define	a4	(a4u.e)
> +#define	a5	(a5u.e)
> +#define	a6	(a6u.e)
> +#define	a7	(a7u.e)
> +#define	a8	(a8u.e)
> +#define	a9	(a9u.e)
> +#define	a10	(a10u.e)
> +#define	a11	(a11u.e)
> +#define	a12	(a12u.e)
> +#define	a13	(a13u.e)
> +/*
> + * Domain x in [tc-0.24, tc+0.28], range ~[-6.1205e-22, 6.1205e-22]:
> + * |(lgamma(x) - tf) -  t(x - tc)| < 2**-70.5
> + */
> +static const union IEEEl2bits
> +tcu  = LD80C(0xbb16c31ab5f1fb71, 0,  1.46163214496836234128e+00L),
> +tfu  = LD80C(0xf8cdcde61c520e0f, -4, -1.21486290535849608093e-01L),
> +ttu  = LD80C(0xd46ee54b27d4de99, -69, -2.81152980996018785880e-21L),
> +t0u  = LD80C(0x80b9406556a62a6b, -68,  3.40728634996055147231e-21L),
> +t1u  = LD80C(0xc7e9c6f6df3f8c39, -67, -1.05833162742737073665e-20L),
> +t2u  = LD80C(0xf7b95e4771c55d51, -2,  4.83836122723810583532e-01L),
> +t3u  = LD80C(0x97213c6e35e119ff, -3, -1.47587722994530691476e-01L),
> +t4u  = LD80C(0x845a14a6a81dc94b, -4,  6.46249402389135358063e-02L),
> +t5u  = LD80C(0x864d46fa89997796, -5, -3.27885410884846056084e-02L),
> +t6u  = LD80C(0x93373cbd00297438, -6,  1.79706751150707171293e-02L),
> +t7u  = LD80C(0xa8fcfca7eddc8d1d, -7, -1.03142230361450732547e-02L),
> +t8u  = LD80C(0xc7e7015ff4bc45af, -8,  6.10053603296546099193e-03L),
> +t9u  = LD80C(0xf178d2247adc5093, -9, -3.68456964904901200152e-03L),
> +t10u = LD80C(0x94188d58f12e5e9f, -9,  2.25976420273774583089e-03L),
> +t11u = LD80C(0xb7cbaef14e1406f1, -10, -1.40224943666225639823e-03L),
> +t12u = LD80C(0xe63a671e6704ea4d, -11,  8.78250640744776944887e-04L),
> +t13u = LD80C(0x914b6c9cae61783e, -11, -5.54255012657716808811e-04L),
> +t14u = LD80C(0xb858f5bdb79276fe, -12,  3.51614951536825927370e-04L),
> +t15u = LD80C(0xea73e744c34b9591, -13, -2.23591563824520112236e-04L),
> +t16u = LD80C(0x99aeabb0d67ba835, -13,  1.46562869351659194136e-04L),
> +t17u = LD80C(0xd7c6938325db2024, -14, -1.02889866046435680588e-04L),
> +t18u = LD80C(0xe24cb1e3b0474775, -15,  5.39540265505221957652e-05L);
> +#define	tc	(tcu.e)
> +#define	tf	(tfu.e)
> +#define	tt	(ttu.e)
> +#define	t0	(t0u.e)
> +#define	t1	(t1u.e)
> +#define	t2	(t2u.e)
> +#define	t3	(t3u.e)
> +#define	t4	(t4u.e)
> +#define	t5	(t5u.e)
> +#define	t6	(t6u.e)
> +#define	t7	(t7u.e)
> +#define	t8	(t8u.e)
> +#define	t9	(t9u.e)
> +#define	t10	(t10u.e)
> +#define	t11	(t11u.e)
> +#define	t12	(t12u.e)
> +#define	t13	(t13u.e)
> +#define	t14	(t14u.e)
> +#define	t15	(t15u.e)
> +#define	t16	(t16u.e)
> +#define	t17	(t17u.e)
> +#define	t18	(t18u.e)
> +/*
> + * Domain y in [-0.1, 0.232], range ~[-8.1938e-22, 8.3815e-22]:
> + * |(lgamma(1 + y) + 0.5 * y) / y - u(y) / v(y)| < 2**-71.2
> + */
> +static const union IEEEl2bits
> +u0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
> +u1u = LD80C(0x98280ee45e4ddd3d, -1,  5.94361239198682739769e-01L),
> +u2u = LD80C(0xe330c8ead4130733, 0,  1.77492629495841234275e+00L),
> +u3u = LD80C(0xd4a213f1a002ec52, 0,  1.66119622514818078064e+00L),
> +u4u = LD80C(0xa5a9ca6f5bc62163, -1,  6.47122051417476492989e-01L),
> +u5u = LD80C(0xc980e49cd5b019e6, -4,  9.83903751718671509455e-02L),
> +u6u = LD80C(0xff636a8bdce7025b, -9,  3.89691687802305743450e-03L),
> +v1u = LD80C(0xbd109c533a19fbf5, 1,  2.95413883330948556544e+00L),
> +v2u = LD80C(0xd295cbf96f31f099, 1,  3.29039286955665403176e+00L),
> +v3u = LD80C(0xdab8bcfee40496cb, 0,  1.70876276441416471410e+00L),
> +v4u = LD80C(0xd2f2dc3638567e9f, -2,  4.12009126299534668571e-01L),
> +v5u = LD80C(0xa07d9b0851070f41, -5,  3.91822868305682491442e-02L),
> +v6u = LD80C(0xe3cd8318f7adb2c4, -11,  8.68998648222144351114e-04L);
> +#define	u0	(u0u.e)
> +#define	u1	(u1u.e)
> +#define	u2	(u2u.e)
> +#define	u3	(u3u.e)
> +#define	u4	(u4u.e)
> +#define	u5	(u5u.e)
> +#define	u6	(u6u.e)
> +#define	v1	(v1u.e)
> +#define	v2	(v2u.e)
> +#define	v3	(v3u.e)
> +#define	v4	(v4u.e)
> +#define	v5	(v5u.e)
> +#define	v6	(v6u.e)
> +/*
> + * Domain x in (2, 3], range ~[-3.3648e-22, 3.4416e-22]:
> + * |(lgamma(y+2) - 0.5 * y) / y - s(y)/r(y)| < 2**-72.3
> + * with y = x - 2.
> + */
> +static const union IEEEl2bits
> +s0u = LD80C(0x9e233f1bed863d27, -4, -7.72156649015328606095e-02L),
> +s1u = LD80C(0xd3ff0dcc7fa91f94, -3,  2.07027640921219389860e-01L),
> +s2u = LD80C(0xb2bb62782478ef31, -2,  3.49085881391362090549e-01L),
> +s3u = LD80C(0xb49f7438c4611a74, -3,  1.76389518704213357954e-01L),
> +s4u = LD80C(0x9a957008fa27ecf9, -5,  3.77401710862930008071e-02L),
> +s5u = LD80C(0xda9b389a6ca7a7ac, -9,  3.33566791452943399399e-03L),
> +s6u = LD80C(0xbc7a2263faf59c14, -14,  8.98728786745638844395e-05L),
> +r1u = LD80C(0xbf5cff5b11477d4d, 0,  1.49502555796294337722e+00L),
> +r2u = LD80C(0xd9aec89de08e3da6, -1,  8.50323236984473285866e-01L),
> +r3u = LD80C(0xeab7ae5057c443f9, -3,  2.29216312078225806131e-01L),
> +r4u = LD80C(0xf29707d9bd2b1e37, -6,  2.96130326586640089145e-02L),
> +r5u = LD80C(0xd376c2f09736c5a3, -10,  1.61334161411590662495e-03L),
> +r6u = LD80C(0xc985983d0cd34e3d, -16,  2.40232770710953450636e-05L),
> +r7u = LD80C(0xe5c7a4f7fc2ef13d, -25, -5.34997929289167573510e-08L);
> +#define	s0	(s0u.e)
> +#define	s1	(s1u.e)
> +#define	s2	(s2u.e)
> +#define	s3	(s3u.e)
> +#define	s4	(s4u.e)
> +#define	s5	(s5u.e)
> +#define	s6	(s6u.e)
> +#define	r1	(r1u.e)
> +#define	r2	(r2u.e)
> +#define	r3	(r3u.e)
> +#define	r4	(r4u.e)
> +#define	r5	(r5u.e)
> +#define	r6	(r6u.e)
> +#define	r7	(r7u.e)
> +/*
> + * Domain z in [8, 0x1p70], range ~[-3.0235e-22, 3.0563e-22]:
> + * |lgamma(x) - (x - 0.5) * (log(x) - 1) - w(1/x)| < 2**-71.7
> + */
> +static const union IEEEl2bits
> +w0u = LD80C(0xd67f1c864beb4a69, -2,  4.18938533204672741776e-01L),
> +w1u = LD80C(0xaaaaaaaaaaaaaaa1, -4,  8.33333333333333332678e-02L),
> +w2u = LD80C(0xb60b60b60b5491c9, -9, -2.77777777777760927870e-03L),
> +w3u = LD80C(0xd00d00cf58aede4c, -11,  7.93650793490637233668e-04L),
> +w4u = LD80C(0x9c09bf626783d4a5, -11, -5.95238023926039051268e-04L),
> +w5u = LD80C(0xdca7cadc5baa517b, -11,  8.41733700408000822962e-04L),
> +w6u = LD80C(0xfb060e361e1ffd07, -10, -1.91515849570245136604e-03L),
> +w7u = LD80C(0xcbd5101bb58d1f2b, -8,  6.22046743903262649294e-03L),
> +w8u = LD80C(0xad27a668d32c821b, -6, -2.11370706734662081843e-02L);
> +#define	w0	(w0u.e)
> +#define	w1	(w1u.e)
> +#define	w2	(w2u.e)
> +#define	w3	(w3u.e)
> +#define	w4	(w4u.e)
> +#define	w5	(w5u.e)
> +#define	w6	(w6u.e)
> +#define	w7	(w7u.e)
> +#define	w8	(w8u.e)
> +
> +static long double
> +sin_pil(long double x)
> +{
> +	volatile long double vz;
> +	long double y,z;
> +	uint64_t n;
> +	uint16_t hx;
> +
> +	y = -x;
> +
> +	vz = y+0x1p63;
> +	z = vz-0x1p63;
> +	if (z == y)
> +	    return zero;
> +
> +	vz = y+0x1p61;
> +	EXTRACT_LDBL80_WORDS(hx,n,vz);
> +	z = vz-0x1p61;
> +	if (z > y) {
> +	    z -= 0.25;			/* adjust to round down */
> +	    n--;
> +	}
> +	n &= 7;				/* octant of y mod 2 */
> +	y = y - z + n * 0.25;		/* y mod 2 */
> +
> +	switch (n) {
> +	    case 0:   y =  __kernel_sinl(pi*y,zero,0); break;
> +	    case 1:
> +	    case 2:   y =  __kernel_cosl(pi*(0.5-y),zero); break;
> +	    case 3:
> +	    case 4:   y =  __kernel_sinl(pi*(one-y),zero,0); break;
> +	    case 5:
> +	    case 6:   y = -__kernel_cosl(pi*(y-1.5),zero); break;
> +	    default:  y =  __kernel_sinl(pi*(y-2.0),zero,0); break;
> +	    }
> +	return -y;
> +}
> +
> +long double
> +lgammal_r(long double x, int *signgamp)
> +{
> +	long double nadj,p,p1,p2,q,r,t,w,y,z;
> +	uint64_t lx;
> +	int i;
> +	uint16_t hx,ix;
> +
> +	EXTRACT_LDBL80_WORDS(hx,lx,x);
> +
> +    /* purge +-Inf and NaNs */
> +	*signgamp = 1;
> +	ix = hx&0x7fff;
> +	if(ix==0x7fff) return x*x;
> +
> +	ENTERI();
> +
> +    /* purge +-0 and tiny arguments */
> +	*signgamp = 1-2*(hx>>15);
> +	if(ix<0x3fff-67) {		/* |x|<2**-(p+3), return -log(|x|) */
> +	    if((ix|lx)==0)
> +		RETURNI(one/vzero);
> +	    RETURNI(-logl(fabsl(x)));
> +	}
> +
> +    /* purge negative integers and start evaluation for other x < 0 */
> +	if(hx&0x8000) {
> +	    *signgamp = 1;
> +	    if(ix>=0x3fff+63) 		/* |x|>=2**(p-1), must be -integer */
> +		RETURNI(one/vzero);
> +	    t = sin_pil(x);
> +	    if(t==zero) RETURNI(one/vzero); /* -integer */
> +	    nadj = logl(pi/fabsl(t*x));
> +	    if(t<zero) *signgamp = -1;
> +	    x = -x;
> +	}
> +
> +    /* purge 1 and 2 */
> +	if((ix==0x3fff || ix==0x4000) && lx==0x8000000000000000ULL) r = 0;
> +    /* for x < 2.0 */
> +	else if(ix<0x4000) {
> +    /*
> +     * XXX Supposedly, one can use the following information to replace the
> +     * XXX FP rational expressions.  A similar approach is appropriate
> +     * XXX for ld128, but one (may need?) needs to consider llx, too.
> +     *
> +     * 8.9999961853027344e-01 3ffe e666600000000000
> +     * 7.3159980773925781e-01 3ffe bb4a200000000000
> +     * 2.3163998126983643e-01 3ffc ed33080000000000
> +     * 1.7316312789916992e+00 3fff dda6180000000000
> +     * 1.2316322326660156e+00 3fff 9da6200000000000
> +     */
> +	    if(x<8.9999961853027344e-01) {
> +		r = -logl(x);
> +		if(x>=7.3159980773925781e-01) {y = 1-x; i= 0;}
> +		else if(x>=2.3163998126983643e-01) {y= x-(tc-1); i=1;}
> +		else {y = x; i=2;}
> +	    } else {
> +		r = 0;
> +		if(x>=1.7316312789916992e+00) {y=2-x;i=0;}
> +		else if(x>=1.2316322326660156e+00) {y=x-tc;i=1;}
> +		else {y=x-1;i=2;}
> +	    }
> +	    switch(i) {
> +	      case 0:
> +		z = y*y;
> +		p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*(a10+z*a12)))));
> +		p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*(a11+z*a13))))));
> +		p  = y*p1+p2;
> +		r  += p-y/2; break;
> +	      case 1:
> +		p = t0+y*t1+tt+y*y*(t2+y*(t3+y*(t4+y*(t5+y*(t6+y*(t7+y*(t8+
> +		    y*(t9+y*(t10+y*(t11+y*(t12+y*(t13+y*(t14+y*(t15+y*(t16+
> +		    y*(t17+y*t18))))))))))))))));
> +		r += tf + p; break;
> +	      case 2:
> +		p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*(u5+y*u6))))));
> +		p2 = 1+y*(v1+y*(v2+y*(v3+y*(v4+y*(v5+y*v6)))));
> +		r += p1/p2-y/2;
> +	    }
> +	}
> +    /* x < 8.0 */
> +	else if(ix<0x4002) {
> +	    i = x;
> +	    y = x-i;
> +	    p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
> +	    q = 1+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*(r6+y*r7))))));
> +	    r = y/2+p/q;
> +	    z = 1;	/* lgamma(1+s) = log(s) + lgamma(s) */
> +	    switch(i) {
> +	    case 7: z *= (y+6);		/* FALLTHRU */
> +	    case 6: z *= (y+5);		/* FALLTHRU */
> +	    case 5: z *= (y+4);		/* FALLTHRU */
> +	    case 4: z *= (y+3);		/* FALLTHRU */
> +	    case 3: z *= (y+2);		/* FALLTHRU */
> +		    r += logl(z); break;
> +	    }
> +    /* 8.0 <= x < 2**(p+3) */
> +	} else if (ix<0x3fff+67) {
> +	    t = logl(x);
> +	    z = one/x;
> +	    y = z*z;
> +	    w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*(w6+y*(w7+y*w8)))))));
> +	    r = (x-half)*(t-one)+w;
> +    /* 2**(p+3) <= x <= inf */
> +	} else 
> +	    r =  x*(logl(x)-1);
> +	if(hx&0x8000) r = nadj - r;
> +	RETURNI(r);
> +}
> diff --git a/newlib/libm/ld80/e_powl.c b/newlib/libm/ld80/e_powl.c
> new file mode 100644
> index 000000000..ea25354c2
> --- /dev/null
> +++ b/newlib/libm/ld80/e_powl.c
> @@ -0,0 +1,662 @@
> +/*-
> + * Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <math.h>
> +
> +#include "math_private.h"
> +
> +/*
> + * Polynomial evaluator:
> + *  P[0] x^n  +  P[1] x^(n-1)  +  ...  +  P[n]
> + */
> +static inline long double
> +__polevll(long double x, long double *PP, int n)
> +{
> +	long double y;
> +	long double *P;
> +
> +	P = PP;
> +	y = *P++;
> +	do {
> +		y = y * x + *P++;
> +	} while (--n);
> +
> +	return (y);
> +}
> +
> +/*
> + * Polynomial evaluator:
> + *  x^n  +  P[0] x^(n-1)  +  P[1] x^(n-2)  +  ...  +  P[n]
> + */
> +static inline long double
> +__p1evll(long double x, long double *PP, int n)
> +{
> +	long double y;
> +	long double *P;
> +
> +	P = PP;
> +	n -= 1;
> +	y = x + *P++;
> +	do {
> +		y = y * x + *P++;
> +	} while (--n);
> +
> +	return (y);
> +}
> +
> +/*							powl.c
> + *
> + *	Power function, long double precision
> + *
> + *
> + *
> + * SYNOPSIS:
> + *
> + * long double x, y, z, powl();
> + *
> + * z = powl( x, y );
> + *
> + *
> + *
> + * DESCRIPTION:
> + *
> + * Computes x raised to the yth power.  Analytically,
> + *
> + *      x**y  =  exp( y log(x) ).
> + *
> + * Following Cody and Waite, this program uses a lookup table
> + * of 2**-i/32 and pseudo extended precision arithmetic to
> + * obtain several extra bits of accuracy in both the logarithm
> + * and the exponential.
> + *
> + *
> + *
> + * ACCURACY:
> + *
> + * The relative error of pow(x,y) can be estimated
> + * by   y dl ln(2),   where dl is the absolute error of
> + * the internally computed base 2 logarithm.  At the ends
> + * of the approximation interval the logarithm equal 1/32
> + * and its relative error is about 1 lsb = 1.1e-19.  Hence
> + * the predicted relative error in the result is 2.3e-21 y .
> + *
> + *                      Relative error:
> + * arithmetic   domain     # trials      peak         rms
> + *
> + *    IEEE     +-1000       40000      2.8e-18      3.7e-19
> + * .001 < x < 1000, with log(x) uniformly distributed.
> + * -1000 < y < 1000, y uniformly distributed.
> + *
> + *    IEEE     0,8700       60000      6.5e-18      1.0e-18
> + * 0.99 < x < 1.01, 0 < y < 8700, uniformly distributed.
> + *
> + *
> + * ERROR MESSAGES:
> + *
> + *   message         condition      value returned
> + * pow overflow     x**y > MAXNUM      INFINITY
> + * pow underflow   x**y < 1/MAXNUM       0.0
> + * pow domain      x<0 and y noninteger  0.0
> + *
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <math.h>
> +
> +#include "math_private.h"
> +
> +/* Table size */
> +#define NXT 32
> +/* log2(Table size) */
> +#define LNXT 5
> +
> +/* log(1+x) =  x - .5x^2 + x^3 *  P(z)/Q(z)
> + * on the domain  2^(-1/32) - 1  <=  x  <=  2^(1/32) - 1
> + */
> +static long double P[] = {
> + 8.3319510773868690346226E-4L,
> + 4.9000050881978028599627E-1L,
> + 1.7500123722550302671919E0L,
> + 1.4000100839971580279335E0L,
> +};
> +static long double Q[] = {
> +/* 1.0000000000000000000000E0L,*/
> + 5.2500282295834889175431E0L,
> + 8.4000598057587009834666E0L,
> + 4.2000302519914740834728E0L,
> +};
> +/* A[i] = 2^(-i/32), rounded to IEEE long double precision.
> + * If i is even, A[i] + B[i/2] gives additional accuracy.
> + */
> +static long double A[33] = {
> + 1.0000000000000000000000E0L,
> + 9.7857206208770013448287E-1L,
> + 9.5760328069857364691013E-1L,
> + 9.3708381705514995065011E-1L,
> + 9.1700404320467123175367E-1L,
> + 8.9735453750155359320742E-1L,
> + 8.7812608018664974155474E-1L,
> + 8.5930964906123895780165E-1L,
> + 8.4089641525371454301892E-1L,
> + 8.2287773907698242225554E-1L,
> + 8.0524516597462715409607E-1L,
> + 7.8799042255394324325455E-1L,
> + 7.7110541270397041179298E-1L,
> + 7.5458221379671136985669E-1L,
> + 7.3841307296974965571198E-1L,
> + 7.2259040348852331001267E-1L,
> + 7.0710678118654752438189E-1L,
> + 6.9195494098191597746178E-1L,
> + 6.7712777346844636413344E-1L,
> + 6.6261832157987064729696E-1L,
> + 6.4841977732550483296079E-1L,
> + 6.3452547859586661129850E-1L,
> + 6.2092890603674202431705E-1L,
> + 6.0762367999023443907803E-1L,
> + 5.9460355750136053334378E-1L,
> + 5.8186242938878875689693E-1L,
> + 5.6939431737834582684856E-1L,
> + 5.5719337129794626814472E-1L,
> + 5.4525386633262882960438E-1L,
> + 5.3357020033841180906486E-1L,
> + 5.2213689121370692017331E-1L,
> + 5.1094857432705833910408E-1L,
> + 5.0000000000000000000000E-1L,
> +};
> +static long double B[17] = {
> + 0.0000000000000000000000E0L,
> + 2.6176170809902549338711E-20L,
> +-1.0126791927256478897086E-20L,
> + 1.3438228172316276937655E-21L,
> + 1.2207982955417546912101E-20L,
> +-6.3084814358060867200133E-21L,
> + 1.3164426894366316434230E-20L,
> +-1.8527916071632873716786E-20L,
> + 1.8950325588932570796551E-20L,
> + 1.5564775779538780478155E-20L,
> + 6.0859793637556860974380E-21L,
> +-2.0208749253662532228949E-20L,
> + 1.4966292219224761844552E-20L,
> + 3.3540909728056476875639E-21L,
> +-8.6987564101742849540743E-22L,
> +-1.2327176863327626135542E-20L,
> + 0.0000000000000000000000E0L,
> +};
> +
> +/* 2^x = 1 + x P(x),
> + * on the interval -1/32 <= x <= 0
> + */
> +static long double R[] = {
> + 1.5089970579127659901157E-5L,
> + 1.5402715328927013076125E-4L,
> + 1.3333556028915671091390E-3L,
> + 9.6181291046036762031786E-3L,
> + 5.5504108664798463044015E-2L,
> + 2.4022650695910062854352E-1L,
> + 6.9314718055994530931447E-1L,
> +};
> +
> +#define douba(k) A[k]
> +#define doubb(k) B[k]
> +#define MEXP (NXT*16384.0L)
> +/* The following if denormal numbers are supported, else -MEXP: */
> +#define MNEXP (-NXT*(16384.0L+64.0L))
> +/* log2(e) - 1 */
> +#define LOG2EA 0.44269504088896340735992L
> +
> +#define F W
> +#define Fa Wa
> +#define Fb Wb
> +#define G W
> +#define Ga Wa
> +#define Gb u
> +#define H W
> +#define Ha Wb
> +#define Hb Wb
> +
> +static const long double MAXLOGL = 1.1356523406294143949492E4L;
> +static const long double MINLOGL = -1.13994985314888605586758E4L;
> +static const long double LOGE2L = 6.9314718055994530941723E-1L;
> +static volatile long double z;
> +static long double w, W, Wa, Wb, ya, yb, u;
> +static const long double huge = 0x1p10000L;
> +#if 0 /* XXX Prevent gcc from erroneously constant folding this. */
> +static const long double twom10000 = 0x1p-10000L;
> +#else
> +static volatile long double twom10000 = 0x1p-10000L;
> +#endif
> +
> +static long double reducl( long double );
> +static long double powil ( long double, int );
> +
> +long double
> +powl(long double x, long double y)
> +{
> +/* double F, Fa, Fb, G, Ga, Gb, H, Ha, Hb */
> +int i, nflg, iyflg, yoddint;
> +long e;
> +
> +if( y == 0.0L )
> +	return( 1.0L );
> +
> +if( x == 1.0L )
> +	return( 1.0L );
> +
> +if( isnan(x) )
> +	return ( nan_mix(x, y) );
> +if( isnan(y) )
> +	return ( nan_mix(x, y) );
> +
> +if( y == 1.0L )
> +	return( x );
> +
> +if( !isfinite(y) && x == -1.0L )
> +	return( 1.0L );
> +
> +if( y >= LDBL_MAX )
> +	{
> +	if( x > 1.0L )
> +		return( INFINITY );
> +	if( x > 0.0L && x < 1.0L )
> +		return( 0.0L );
> +	if( x < -1.0L )
> +		return( INFINITY );
> +	if( x > -1.0L && x < 0.0L )
> +		return( 0.0L );
> +	}
> +if( y <= -LDBL_MAX )
> +	{
> +	if( x > 1.0L )
> +		return( 0.0L );
> +	if( x > 0.0L && x < 1.0L )
> +		return( INFINITY );
> +	if( x < -1.0L )
> +		return( 0.0L );
> +	if( x > -1.0L && x < 0.0L )
> +		return( INFINITY );
> +	}
> +if( x >= LDBL_MAX )
> +	{
> +	if( y > 0.0L )
> +		return( INFINITY );
> +	return( 0.0L );
> +	}
> +
> +w = floorl(y);
> +/* Set iyflg to 1 if y is an integer.  */
> +iyflg = 0;
> +if( w == y )
> +	iyflg = 1;
> +
> +/* Test for odd integer y.  */
> +yoddint = 0;
> +if( iyflg )
> +	{
> +	ya = fabsl(y);
> +	ya = floorl(0.5L * ya);
> +	yb = 0.5L * fabsl(w);
> +	if( ya != yb )
> +		yoddint = 1;
> +	}
> +
> +if( x <= -LDBL_MAX )
> +	{
> +	if( y > 0.0L )
> +		{
> +		if( yoddint )
> +			return( -INFINITY );
> +		return( INFINITY );
> +		}
> +	if( y < 0.0L )
> +		{
> +		if( yoddint )
> +			return( -0.0L );
> +		return( 0.0 );
> +		}
> +	}
> +
> +
> +nflg = 0;	/* flag = 1 if x<0 raised to integer power */
> +if( x <= 0.0L )
> +	{
> +	if( x == 0.0L )
> +		{
> +		if( y < 0.0 )
> +			{
> +			if( signbit(x) && yoddint )
> +				return( -INFINITY );
> +			return( INFINITY );
> +			}
> +		if( y > 0.0 )
> +			{
> +			if( signbit(x) && yoddint )
> +				return( -0.0L );
> +			return( 0.0 );
> +			}
> +		if( y == 0.0L )
> +			return( 1.0L );  /*   0**0   */
> +		else
> +			return( 0.0L );  /*   0**y   */
> +		}
> +	else
> +		{
> +		if( iyflg == 0 )
> +			return (x - x) / (x - x); /* (x<0)**(non-int) is NaN */
> +		nflg = 1;
> +		}
> +	}
> +
> +/* Integer power of an integer.  */
> +
> +if( iyflg )
> +	{
> +	i = w;
> +	w = floorl(x);
> +	if( (w == x) && (fabsl(y) < 32768.0) )
> +		{
> +		w = powil( x, (int) y );
> +		return( w );
> +		}
> +	}
> +
> +
> +if( nflg )
> +	x = fabsl(x);
> +
> +/* separate significand from exponent */
> +x = frexpl( x, &i );
> +e = i;
> +
> +/* find significand in antilog table A[] */
> +i = 1;
> +if( x <= douba(17) )
> +	i = 17;
> +if( x <= douba(i+8) )
> +	i += 8;
> +if( x <= douba(i+4) )
> +	i += 4;
> +if( x <= douba(i+2) )
> +	i += 2;
> +if( x >= douba(1) )
> +	i = -1;
> +i += 1;
> +
> +
> +/* Find (x - A[i])/A[i]
> + * in order to compute log(x/A[i]):
> + *
> + * log(x) = log( a x/a ) = log(a) + log(x/a)
> + *
> + * log(x/a) = log(1+v),  v = x/a - 1 = (x-a)/a
> + */
> +x -= douba(i);
> +x -= doubb(i/2);
> +x /= douba(i);
> +
> +
> +/* rational approximation for log(1+v):
> + *
> + * log(1+v)  =  v  -  v**2/2  +  v**3 P(v) / Q(v)
> + */
> +z = x*x;
> +w = x * ( z * __polevll( x, P, 3 ) / __p1evll( x, Q, 3 ) );
> +w = w - ldexpl( z, -1 );   /*  w - 0.5 * z  */
> +
> +/* Convert to base 2 logarithm:
> + * multiply by log2(e) = 1 + LOG2EA
> + */
> +z = LOG2EA * w;
> +z += w;
> +z += LOG2EA * x;
> +z += x;
> +
> +/* Compute exponent term of the base 2 logarithm. */
> +w = -i;
> +w = ldexpl( w, -LNXT );	/* divide by NXT */
> +w += e;
> +/* Now base 2 log of x is w + z. */
> +
> +/* Multiply base 2 log by y, in extended precision. */
> +
> +/* separate y into large part ya
> + * and small part yb less than 1/NXT
> + */
> +ya = reducl(y);
> +yb = y - ya;
> +
> +/* (w+z)(ya+yb)
> + * = w*ya + w*yb + z*y
> + */
> +F = z * y  +  w * yb;
> +Fa = reducl(F);
> +Fb = F - Fa;
> +
> +G = Fa + w * ya;
> +Ga = reducl(G);
> +Gb = G - Ga;
> +
> +H = Fb + Gb;
> +Ha = reducl(H);
> +w = ldexpl( Ga+Ha, LNXT );
> +
> +/* Test the power of 2 for overflow */
> +if( w > MEXP )
> +	return (huge * huge);		/* overflow */
> +
> +if( w < MNEXP )
> +	return (twom10000 * twom10000);	/* underflow */
> +
> +e = w;
> +Hb = H - Ha;
> +
> +if( Hb > 0.0L )
> +	{
> +	e += 1;
> +	Hb -= (1.0L/NXT);  /*0.0625L;*/
> +	}
> +
> +/* Now the product y * log2(x)  =  Hb + e/NXT.
> + *
> + * Compute base 2 exponential of Hb,
> + * where -0.0625 <= Hb <= 0.
> + */
> +z = Hb * __polevll( Hb, R, 6 );  /*    z  =  2**Hb - 1    */
> +
> +/* Express e/NXT as an integer plus a negative number of (1/NXT)ths.
> + * Find lookup table entry for the fractional power of 2.
> + */
> +if( e < 0 )
> +	i = 0;
> +else
> +	i = 1;
> +i = e/NXT + i;
> +e = NXT*i - e;
> +w = douba( e );
> +z = w * z;      /*    2**-e * ( 1 + (2**Hb-1) )    */
> +z = z + w;
> +z = ldexpl( z, i );  /* multiply by integer power of 2 */
> +
> +if( nflg )
> +	{
> +/* For negative x,
> + * find out if the integer exponent
> + * is odd or even.
> + */
> +	w = ldexpl( y, -1 );
> +	w = floorl(w);
> +	w = ldexpl( w, 1 );
> +	if( w != y )
> +		z = -z; /* odd exponent */
> +	}
> +
> +return( z );
> +}
> +
> +
> +/* Find a multiple of 1/NXT that is within 1/NXT of x. */
> +static inline long double
> +reducl(long double x)
> +{
> +long double t;
> +
> +t = ldexpl( x, LNXT );
> +t = floorl( t );
> +t = ldexpl( t, -LNXT );
> +return(t);
> +}
> +
> +/*							powil.c
> + *
> + *	Real raised to integer power, long double precision
> + *
> + *
> + *
> + * SYNOPSIS:
> + *
> + * long double x, y, powil();
> + * int n;
> + *
> + * y = powil( x, n );
> + *
> + *
> + *
> + * DESCRIPTION:
> + *
> + * Returns argument x raised to the nth power.
> + * The routine efficiently decomposes n as a sum of powers of
> + * two. The desired power is a product of two-to-the-kth
> + * powers of x.  Thus to compute the 32767 power of x requires
> + * 28 multiplications instead of 32767 multiplications.
> + *
> + *
> + *
> + * ACCURACY:
> + *
> + *
> + *                      Relative error:
> + * arithmetic   x domain   n domain  # trials      peak         rms
> + *    IEEE     .001,1000  -1022,1023  50000       4.3e-17     7.8e-18
> + *    IEEE        1,2     -1022,1023  20000       3.9e-17     7.6e-18
> + *    IEEE     .99,1.01     0,8700    10000       3.6e-16     7.2e-17
> + *
> + * Returns MAXNUM on overflow, zero on underflow.
> + *
> + */
> +
> +static long double
> +powil(long double x, int nn)
> +{
> +long double ww, y;
> +long double s;
> +int n, e, sign, asign, lx;
> +
> +if( x == 0.0L )
> +	{
> +	if( nn == 0 )
> +		return( 1.0L );
> +	else if( nn < 0 )
> +		return( LDBL_MAX );
> +	else
> +		return( 0.0L );
> +	}
> +
> +if( nn == 0 )
> +	return( 1.0L );
> +
> +
> +if( x < 0.0L )
> +	{
> +	asign = -1;
> +	x = -x;
> +	}
> +else
> +	asign = 0;
> +
> +
> +if( nn < 0 )
> +	{
> +	sign = -1;
> +	n = -nn;
> +	}
> +else
> +	{
> +	sign = 1;
> +	n = nn;
> +	}
> +
> +/* Overflow detection */
> +
> +/* Calculate approximate logarithm of answer */
> +s = x;
> +s = frexpl( s, &lx );
> +e = (lx - 1)*n;
> +if( (e == 0) || (e > 64) || (e < -64) )
> +	{
> +	s = (s - 7.0710678118654752e-1L) / (s +  7.0710678118654752e-1L);
> +	s = (2.9142135623730950L * s - 0.5L + lx) * nn * LOGE2L;
> +	}
> +else
> +	{
> +	s = LOGE2L * e;
> +	}
> +
> +if( s > MAXLOGL )
> +	return (huge * huge);		/* overflow */
> +
> +if( s < MINLOGL )
> +	return (twom10000 * twom10000);	/* underflow */
> +/* Handle tiny denormal answer, but with less accuracy
> + * since roundoff error in 1.0/x will be amplified.
> + * The precise demarcation should be the gradual underflow threshold.
> + */
> +if( s < (-MAXLOGL+2.0L) )
> +	{
> +	x = 1.0L/x;
> +	sign = -sign;
> +	}
> +
> +/* First bit of the power */
> +if( n & 1 )
> +	y = x;
> +
> +else
> +	{
> +	y = 1.0L;
> +	asign = 0;
> +	}
> +
> +ww = x;
> +n >>= 1;
> +while( n )
> +	{
> +	ww = ww * ww;	/* arg to the 2-to-the-kth power */
> +	if( n & 1 )	/* if that bit is set, then include in product */
> +		y *= ww;
> +	n >>= 1;
> +	}
> +
> +if( asign )
> +	y = -y; /* odd power of negative number */
> +if( sign < 0 )
> +	y = 1.0L/y;
> +return(y);
> +}
> diff --git a/newlib/libm/ld80/e_rem_pio2l.h b/newlib/libm/ld80/e_rem_pio2l.h
> new file mode 100644
> index 000000000..b7ef5d983
> --- /dev/null
> +++ b/newlib/libm/ld80/e_rem_pio2l.h
> @@ -0,0 +1,143 @@
> +/* From: @(#)e_rem_pio2.c 1.4 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/* ld80 version of __ieee754_rem_pio2l(x,y)
> + * 
> + * return the remainder of x rem pi/2 in y[0]+y[1] 
> + * use __kernel_rem_pio2()
> + */
> +
> +#include <float.h>
> +
> +#include "math.h"
> +#include "math_private.h"
> +#include "../ld/fpmath.h"
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +/*
> + * invpio2:  64 bits of 2/pi
> + * pio2_1:   first  39 bits of pi/2
> + * pio2_1t:  pi/2 - pio2_1
> + * pio2_2:   second 39 bits of pi/2
> + * pio2_2t:  pi/2 - (pio2_1+pio2_2)
> + * pio2_3:   third  39 bits of pi/2
> + * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
> + */
> +
> +static const double
> +zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
> +two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
> +pio2_1  =  1.57079632679597125389e+00,	/* 0x3FF921FB, 0x54444000 */
> +pio2_2  = -1.07463465549783099519e-12,	/* -0x12e7b967674000.0p-92 */
> +pio2_3  =  6.36831716351370313614e-25;	/*  0x18a2e037074000.0p-133 */
> +
> +#if defined(__amd64__) || defined(__i386__)
> +/* Long double constants are slow on these arches, and broken on i386. */
> +static const volatile double
> +invpio2hi =  6.3661977236758138e-01,	/*  0x145f306dc9c883.0p-53 */
> +invpio2lo = -3.9356538861223811e-17,	/* -0x16b00000000000.0p-107 */
> +pio2_1thi = -1.0746346554971943e-12,	/* -0x12e7b9676733af.0p-92 */
> +pio2_1tlo =  8.8451028997905949e-29,	/*  0x1c080000000000.0p-146 */
> +pio2_2thi =  6.3683171635109499e-25,	/*  0x18a2e03707344a.0p-133 */
> +pio2_2tlo =  2.3183081793789774e-41,	/*  0x10280000000000.0p-187 */
> +pio2_3thi = -2.7529965190440717e-37,	/* -0x176b7ed8fbbacc.0p-174 */
> +pio2_3tlo = -4.2006647512740502e-54;	/* -0x19c00000000000.0p-230 */
> +#define	invpio2	((long double)invpio2hi + invpio2lo)
> +#define	pio2_1t	((long double)pio2_1thi + pio2_1tlo)
> +#define	pio2_2t	((long double)pio2_2thi + pio2_2tlo)
> +#define	pio2_3t	((long double)pio2_3thi + pio2_3tlo)
> +#else
> +static const long double
> +invpio2 =  6.36619772367581343076e-01L,	/*  0xa2f9836e4e44152a.0p-64 */
> +pio2_1t = -1.07463465549719416346e-12L,	/* -0x973dcb3b399d747f.0p-103 */
> +pio2_2t =  6.36831716351095013979e-25L,	/*  0xc51701b839a25205.0p-144 */
> +pio2_3t = -2.75299651904407171810e-37L;	/* -0xbb5bf6c7ddd660ce.0p-185 */
> +#endif
> +
> +static inline __always_inline int
> +__ieee754_rem_pio2l(long double x, long double *y)
> +{
> +	union IEEEl2bits u,u1;
> +	long double z,w,t,r,fn;
> +	double tx[3],ty[2];
> +	int e0,ex,i,j,nx,n;
> +	int16_t expsign;
> +
> +	u.e = x;
> +	expsign = u.xbits.expsign;
> +	ex = expsign & 0x7fff;
> +	if (ex < BIAS + 25 || (ex == BIAS + 25 && u.bits.manh < 0xc90fdaa2)) {
> +	    /* |x| ~< 2^25*(pi/2), medium size */
> +	    fn = rnintl(x*invpio2);
> +	    n  = irint(fn);
> +	    r  = x-fn*pio2_1;
> +	    w  = fn*pio2_1t;	/* 1st round good to 102 bit */
> +	    {
> +		union IEEEl2bits u2;
> +	        int ex1;
> +	        j  = ex;
> +	        y[0] = r-w; 
> +		u2.e = y[0];
> +		ex1 = u2.xbits.expsign & 0x7fff;
> +	        i = j-ex1;
> +	        if(i>22) {  /* 2nd iteration needed, good to 141 */
> +		    t  = r;
> +		    w  = fn*pio2_2;	
> +		    r  = t-w;
> +		    w  = fn*pio2_2t-((t-r)-w);	
> +		    y[0] = r-w;
> +		    u2.e = y[0];
> +		    ex1 = u2.xbits.expsign & 0x7fff;
> +		    i = j-ex1;
> +		    if(i>61) {	/* 3rd iteration need, 180 bits acc */
> +		    	t  = r;	/* will cover all possible cases */
> +		    	w  = fn*pio2_3;	
> +		    	r  = t-w;
> +		    	w  = fn*pio2_3t-((t-r)-w);	
> +		    	y[0] = r-w;
> +		    }
> +		}
> +	    }
> +	    y[1] = (r-y[0])-w;
> +	    return n;
> +	}
> +    /* 
> +     * all other (large) arguments
> +     */
> +	if(ex==0x7fff) {		/* x is inf or NaN */
> +	    y[0]=y[1]=x-x; return 0;
> +	}
> +    /* set z = scalbn(|x|,ilogb(x)-23) */
> +	u1.e = x;
> +	e0 = ex - BIAS - 23;		/* e0 = ilogb(|x|)-23; */
> +	u1.xbits.expsign = ex - e0;
> +	z = u1.e;
> +	for(i=0;i<2;i++) {
> +		tx[i] = (double)((int32_t)(z));
> +		z     = (z-tx[i])*two24;
> +	}
> +	tx[2] = z;
> +	nx = 3;
> +	while(tx[nx-1]==zero) nx--;	/* skip zero term */
> +	n  =  __kernel_rem_pio2(tx,ty,e0,nx,2);
> +	r = (long double)ty[0] + ty[1];
> +	w = ty[1] - (r - ty[0]);
> +	if(expsign<0) {y[0] = -r; y[1] = -w; return -n;}
> +	y[0] = r; y[1] = w; return n;
> +}
> diff --git a/newlib/libm/ld80/invtrig.c b/newlib/libm/ld80/invtrig.c
> new file mode 100644
> index 000000000..5c8047857
> --- /dev/null
> +++ b/newlib/libm/ld80/invtrig.c
> @@ -0,0 +1,84 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include "invtrig.h"
> +
> +/*
> + * asinl() and acosl()
> + */
> +const long double
> +pS0 =  1.66666666666666666631e-01L,
> +pS1 = -4.16313987993683104320e-01L,
> +pS2 =  3.69068046323246813704e-01L,
> +pS3 = -1.36213932016738603108e-01L,
> +pS4 =  1.78324189708471965733e-02L,
> +pS5 = -2.19216428382605211588e-04L,
> +pS6 = -7.10526623669075243183e-06L,
> +qS1 = -2.94788392796209867269e+00L,
> +qS2 =  3.27309890266528636716e+00L,
> +qS3 = -1.68285799854822427013e+00L,
> +qS4 =  3.90699412641738801874e-01L,
> +qS5 = -3.14365703596053263322e-02L;
> +
> +/*
> + * atanl()
> + */
> +const long double atanhi[] = {
> +	 4.63647609000806116202e-01L,
> +	 7.85398163397448309628e-01L,
> +	 9.82793723247329067960e-01L,
> +	 1.57079632679489661926e+00L,
> +};
> +
> +const long double atanlo[] = {
> +	 1.18469937025062860669e-20L,
> +	-1.25413940316708300586e-20L,
> +	 2.55232234165405176172e-20L,
> +	-2.50827880633416601173e-20L,
> +};
> +
> +const long double aT[] = {
> +	 3.33333333333333333017e-01L,
> +	-1.99999999999999632011e-01L,
> +	 1.42857142857046531280e-01L,
> +	-1.11111111100562372733e-01L,
> +	 9.09090902935647302252e-02L,
> +	-7.69230552476207730353e-02L,
> +	 6.66661718042406260546e-02L,
> +	-5.88158892835030888692e-02L,
> +	 5.25499891539726639379e-02L,
> +	-4.70119845393155721494e-02L,
> +	 4.03539201366454414072e-02L,
> +	-2.91303858419364158725e-02L,
> +	 1.24822046299269234080e-02L,
> +};
> +
> +const long double pi_lo = -5.01655761266833202345e-20L;
> diff --git a/newlib/libm/ld80/invtrig.h b/newlib/libm/ld80/invtrig.h
> new file mode 100644
> index 000000000..be06a044b
> --- /dev/null
> +++ b/newlib/libm/ld80/invtrig.h
> @@ -0,0 +1,116 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * $FreeBSD$
> + */
> +
> +#include <float.h>
> +
> +#include "fpmath.h"
> +
> +#define	BIAS		(LDBL_MAX_EXP - 1)
> +#define	MANH_SIZE	LDBL_MANH_SIZE
> +
> +/* Approximation thresholds. */
> +#define	ASIN_LINEAR	(BIAS - 32)	/* 2**-32 */
> +#define	ACOS_CONST	(BIAS - 65)	/* 2**-65 */
> +#define	ATAN_CONST	(BIAS + 65)	/* 2**65 */
> +#define	ATAN_LINEAR	(BIAS - 32)	/* 2**-32 */
> +
> +/* 0.95 */
> +#define	THRESH	((0xe666666666666666ULL>>(64-(MANH_SIZE-1)))|LDBL_NBIT)
> +
> +/* Constants shared by the long double inverse trig functions. */
> +#define	pS0	_ItL_pS0
> +#define	pS1	_ItL_pS1
> +#define	pS2	_ItL_pS2
> +#define	pS3	_ItL_pS3
> +#define	pS4	_ItL_pS4
> +#define	pS5	_ItL_pS5
> +#define	pS6	_ItL_pS6
> +#define	qS1	_ItL_qS1
> +#define	qS2	_ItL_qS2
> +#define	qS3	_ItL_qS3
> +#define	qS4	_ItL_qS4
> +#define	qS5	_ItL_qS5
> +#define	atanhi	_ItL_atanhi
> +#define	atanlo	_ItL_atanlo
> +#define	aT	_ItL_aT
> +#define	pi_lo	_ItL_pi_lo
> +
> +#define	pio2_hi	atanhi[3]
> +#define	pio2_lo	atanlo[3]
> +#define	pio4_hi	atanhi[1]
> +
> +#ifdef STRUCT_DECLS
> +typedef struct longdouble {
> +	uint64_t mant;
> +	uint16_t expsign;
> +} LONGDOUBLE;
> +#else
> +typedef long double LONGDOUBLE;
> +#endif
> +
> +extern const LONGDOUBLE pS0, pS1, pS2, pS3, pS4, pS5, pS6;
> +extern const LONGDOUBLE qS1, qS2, qS3, qS4, qS5;
> +extern const LONGDOUBLE atanhi[], atanlo[], aT[];
> +extern const LONGDOUBLE pi_lo;
> +
> +#ifndef STRUCT_DECLS
> +
> +static inline long double
> +P(long double x)
> +{
> +
> +	return (x * (pS0 + x * (pS1 + x * (pS2 + x * (pS3 + x * \
> +		(pS4 + x * (pS5 + x * pS6)))))));
> +}
> +
> +static inline long double
> +Q(long double x)
> +{
> +
> +	return (1.0 + x * (qS1 + x * (qS2 + x * (qS3 + x * (qS4 + x * qS5)))));
> +}
> +
> +static inline long double
> +T_even(long double x)
> +{
> +
> +	return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * \
> +		(aT[8] + x * (aT[10] + x * aT[12]))))));
> +}
> +
> +static inline long double
> +T_odd(long double x)
> +{
> +
> +	return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * \
> +		(aT[9] + x * aT[11])))));
> +}
> +
> +#endif
> diff --git a/newlib/libm/ld80/k_cosl.c b/newlib/libm/ld80/k_cosl.c
> new file mode 100644
> index 000000000..6dde6adad
> --- /dev/null
> +++ b/newlib/libm/ld80/k_cosl.c
> @@ -0,0 +1,78 @@
> +/* From: @(#)k_cos.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld80 version of k_cos.c.  See ../src/k_cos.c for most comments.
> + */
> +
> +#include "math_private.h"
> +
> +/*
> + * Domain [-0.7854, 0.7854], range ~[-2.43e-23, 2.425e-23]:
> + * |cos(x) - c(x)| < 2**-75.1
> + *
> + * The coefficients of c(x) were generated by a pari-gp script using
> + * a Remez algorithm that searches for the best higher coefficients
> + * after rounding leading coefficients to a specified precision.
> + *
> + * Simpler methods like Chebyshev or basic Remez barely suffice for
> + * cos() in 64-bit precision, because we want the coefficient of x^2
> + * to be precisely -0.5 so that multiplying by it is exact, and plain
> + * rounding of the coefficients of a good polynomial approximation only
> + * gives this up to about 64-bit precision.  Plain rounding also gives
> + * a mediocre approximation for the coefficient of x^4, but a rounding
> + * error of 0.5 ulps for this coefficient would only contribute ~0.01
> + * ulps to the final error, so this is unimportant.  Rounding errors in
> + * higher coefficients are even less important.
> + *
> + * In fact, coefficients above the x^4 one only need to have 53-bit
> + * precision, and this is more efficient.  We get this optimization
> + * almost for free from the complications needed to search for the best
> + * higher coefficients.
> + */
> +static const double
> +one = 1.0;
> +
> +#if defined(__amd64__) || defined(__i386__)
> +/* Long double constants are slow on these arches, and broken on i386. */
> +static const volatile double
> +C1hi = 0.041666666666666664,		/*  0x15555555555555.0p-57 */
> +C1lo = 2.2598839032744733e-18;		/*  0x14d80000000000.0p-111 */
> +#define	C1	((long double)C1hi + C1lo)
> +#else
> +static const long double
> +C1 =  0.0416666666666666666136L;	/*  0xaaaaaaaaaaaaaa9b.0p-68 */
> +#endif
> +
> +static const double
> +C2 = -0.0013888888888888874,		/* -0x16c16c16c16c10.0p-62 */
> +C3 =  0.000024801587301571716,		/*  0x1a01a01a018e22.0p-68 */
> +C4 = -0.00000027557319215507120,	/* -0x127e4fb7602f22.0p-74 */
> +C5 =  0.0000000020876754400407278,	/*  0x11eed8caaeccf1.0p-81 */
> +C6 = -1.1470297442401303e-11,		/* -0x19393412bd1529.0p-89 */
> +C7 =  4.7383039476436467e-14;		/*  0x1aac9d9af5c43e.0p-97 */
> +
> +long double
> +__kernel_cosl(long double x, long double y)
> +{
> +	long double hz,z,r,w;
> +
> +	z  = x*x;
> +	r  = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7))))));
> +	hz = 0.5*z;
> +	w  = one-hz;
> +	return w + (((one-w)-hz) + (z*r-x*y));
> +}
> diff --git a/newlib/libm/ld80/k_cospil.h b/newlib/libm/ld80/k_cospil.h
> new file mode 100644
> index 000000000..6e13ef02a
> --- /dev/null
> +++ b/newlib/libm/ld80/k_cospil.h
> @@ -0,0 +1,42 @@
> +/*-
> + * Copyright (c) 2017 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * See ../src/k_cospi.c for implementation details.
> + */
> +
> +static inline long double
> +__kernel_cospil(long double x)
> +{
> +	long double hi, lo;
> +
> +	hi = (float)x;
> +	lo = x - hi;
> +	lo = lo * (pi_lo + pi_hi) + hi * pi_lo;
> +	hi *= pi_hi;
> +	_2sumF(hi, lo);
> +	return (__kernel_cosl(hi, lo));
> +}
> diff --git a/newlib/libm/ld80/k_expl.h b/newlib/libm/ld80/k_expl.h
> new file mode 100644
> index 000000000..a744d2d38
> --- /dev/null
> +++ b/newlib/libm/ld80/k_expl.h
> @@ -0,0 +1,301 @@
> +/* from: FreeBSD: head/lib/msun/ld80/s_expl.c 251343 2013-06-03 19:51:32Z kargl */
> +
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2009-2013 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See s_expl.c for more comments about __k_expl().
> + *
> + * See ../src/e_exp.c and ../src/k_exp.h for precision-independent comments
> + * about the secondary kernels.
> + */
> +
> +#define	INTERVALS	128
> +#define	LOG2_INTERVALS	7
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static const double
> +/*
> + * ln2/INTERVALS = L1+L2 (hi+lo decomposition for multiplication).  L1 must
> + * have at least 22 (= log2(|LDBL_MIN_EXP-extras|) + log2(INTERVALS)) lowest
> + * bits zero so that multiplication of it by n is exact.
> + */
> +INV_L = 1.8466496523378731e+2,		/*  0x171547652b82fe.0p-45 */
> +L1 =  5.4152123484527692e-3,		/*  0x162e42ff000000.0p-60 */
> +L2 = -3.2819649005320973e-13,		/* -0x1718432a1b0e26.0p-94 */
> +/*
> + * Domain [-0.002708, 0.002708], range ~[-5.7136e-24, 5.7110e-24]:
> + * |exp(x) - p(x)| < 2**-77.2
> + * (0.002708 is ln2/(2*INTERVALS) rounded up a little).
> + */
> +A2 =  0.5,
> +A3 =  1.6666666666666119e-1,		/*  0x15555555555490.0p-55 */
> +A4 =  4.1666666666665887e-2,		/*  0x155555555554e5.0p-57 */
> +A5 =  8.3333354987869413e-3,		/*  0x1111115b789919.0p-59 */
> +A6 =  1.3888891738560272e-3;		/*  0x16c16c651633ae.0p-62 */
> +
> +/*
> + * 2^(i/INTERVALS) for i in [0,INTERVALS] is represented by two values where
> + * the first 53 bits of the significand are stored in hi and the next 53
> + * bits are in lo.  Tang's paper states that the trailing 6 bits of hi must
> + * be zero for his algorithm in both single and double precision, because
> + * the table is re-used in the implementation of expm1() where a floating
> + * point addition involving hi must be exact.  Here hi is double, so
> + * converting it to long double gives 11 trailing zero bits.
> + */
> +static const struct {
> +	double	hi;
> +	double	lo;
> +} tbl[INTERVALS] = {
> +	{ 0x1p+0, 0x0p+0 },
> +	/*
> +	 * XXX hi is rounded down, and the formatting is not quite normal.
> +	 * But I rather like both.  The 0x1.*p format is good for 4N+1
> +	 * mantissa bits.  Rounding down makes the lo terms positive,
> +	 * so that the columnar formatting can be simpler.
> +	 */
> +	{ 0x1.0163da9fb3335p+0, 0x1.b61299ab8cdb7p-54 },
> +	{ 0x1.02c9a3e778060p+0, 0x1.dcdef95949ef4p-53 },
> +	{ 0x1.04315e86e7f84p+0, 0x1.7ae71f3441b49p-53 },
> +	{ 0x1.059b0d3158574p+0, 0x1.d73e2a475b465p-55 },
> +	{ 0x1.0706b29ddf6ddp+0, 0x1.8db880753b0f6p-53 },
> +	{ 0x1.0874518759bc8p+0, 0x1.186be4bb284ffp-57 },
> +	{ 0x1.09e3ecac6f383p+0, 0x1.1487818316136p-54 },
> +	{ 0x1.0b5586cf9890fp+0, 0x1.8a62e4adc610bp-54 },
> +	{ 0x1.0cc922b7247f7p+0, 0x1.01edc16e24f71p-54 },
> +	{ 0x1.0e3ec32d3d1a2p+0, 0x1.03a1727c57b53p-59 },
> +	{ 0x1.0fb66affed31ap+0, 0x1.e464123bb1428p-53 },
> +	{ 0x1.11301d0125b50p+0, 0x1.49d77e35db263p-53 },
> +	{ 0x1.12abdc06c31cbp+0, 0x1.f72575a649ad2p-53 },
> +	{ 0x1.1429aaea92ddfp+0, 0x1.66820328764b1p-53 },
> +	{ 0x1.15a98c8a58e51p+0, 0x1.2406ab9eeab0ap-55 },
> +	{ 0x1.172b83c7d517ap+0, 0x1.b9bef918a1d63p-53 },
> +	{ 0x1.18af9388c8de9p+0, 0x1.777ee1734784ap-53 },
> +	{ 0x1.1a35beb6fcb75p+0, 0x1.e5b4c7b4968e4p-55 },
> +	{ 0x1.1bbe084045cd3p+0, 0x1.3563ce56884fcp-53 },
> +	{ 0x1.1d4873168b9aap+0, 0x1.e016e00a2643cp-54 },
> +	{ 0x1.1ed5022fcd91cp+0, 0x1.71033fec2243ap-53 },
> +	{ 0x1.2063b88628cd6p+0, 0x1.dc775814a8495p-55 },
> +	{ 0x1.21f49917ddc96p+0, 0x1.2a97e9494a5eep-55 },
> +	{ 0x1.2387a6e756238p+0, 0x1.9b07eb6c70573p-54 },
> +	{ 0x1.251ce4fb2a63fp+0, 0x1.ac155bef4f4a4p-55 },
> +	{ 0x1.26b4565e27cddp+0, 0x1.2bd339940e9d9p-55 },
> +	{ 0x1.284dfe1f56380p+0, 0x1.2d9e2b9e07941p-53 },
> +	{ 0x1.29e9df51fdee1p+0, 0x1.612e8afad1255p-55 },
> +	{ 0x1.2b87fd0dad98fp+0, 0x1.fbbd48ca71f95p-53 },
> +	{ 0x1.2d285a6e4030bp+0, 0x1.0024754db41d5p-54 },
> +	{ 0x1.2ecafa93e2f56p+0, 0x1.1ca0f45d52383p-56 },
> +	{ 0x1.306fe0a31b715p+0, 0x1.6f46ad23182e4p-55 },
> +	{ 0x1.32170fc4cd831p+0, 0x1.a9ce78e18047cp-55 },
> +	{ 0x1.33c08b26416ffp+0, 0x1.32721843659a6p-54 },
> +	{ 0x1.356c55f929ff0p+0, 0x1.928c468ec6e76p-53 },
> +	{ 0x1.371a7373aa9cap+0, 0x1.4e28aa05e8a8fp-53 },
> +	{ 0x1.38cae6d05d865p+0, 0x1.0b53961b37da2p-53 },
> +	{ 0x1.3a7db34e59ff6p+0, 0x1.d43792533c144p-53 },
> +	{ 0x1.3c32dc313a8e4p+0, 0x1.08003e4516b1ep-53 },
> +	{ 0x1.3dea64c123422p+0, 0x1.ada0911f09ebcp-55 },
> +	{ 0x1.3fa4504ac801bp+0, 0x1.417ee03548306p-53 },
> +	{ 0x1.4160a21f72e29p+0, 0x1.f0864b71e7b6cp-53 },
> +	{ 0x1.431f5d950a896p+0, 0x1.b8e088728219ap-53 },
> +	{ 0x1.44e086061892dp+0, 0x1.89b7a04ef80d0p-59 },
> +	{ 0x1.46a41ed1d0057p+0, 0x1.c944bd1648a76p-54 },
> +	{ 0x1.486a2b5c13cd0p+0, 0x1.3c1a3b69062f0p-56 },
> +	{ 0x1.4a32af0d7d3dep+0, 0x1.9cb62f3d1be56p-54 },
> +	{ 0x1.4bfdad5362a27p+0, 0x1.d4397afec42e2p-56 },
> +	{ 0x1.4dcb299fddd0dp+0, 0x1.8ecdbbc6a7833p-54 },
> +	{ 0x1.4f9b2769d2ca6p+0, 0x1.5a67b16d3540ep-53 },
> +	{ 0x1.516daa2cf6641p+0, 0x1.8225ea5909b04p-53 },
> +	{ 0x1.5342b569d4f81p+0, 0x1.be1507893b0d5p-53 },
> +	{ 0x1.551a4ca5d920ep+0, 0x1.8a5d8c4048699p-53 },
> +	{ 0x1.56f4736b527dap+0, 0x1.9bb2c011d93adp-54 },
> +	{ 0x1.58d12d497c7fdp+0, 0x1.295e15b9a1de8p-55 },
> +	{ 0x1.5ab07dd485429p+0, 0x1.6324c054647adp-54 },
> +	{ 0x1.5c9268a5946b7p+0, 0x1.c4b1b816986a2p-60 },
> +	{ 0x1.5e76f15ad2148p+0, 0x1.ba6f93080e65ep-54 },
> +	{ 0x1.605e1b976dc08p+0, 0x1.60edeb25490dcp-53 },
> +	{ 0x1.6247eb03a5584p+0, 0x1.63e1f40dfa5b5p-53 },
> +	{ 0x1.6434634ccc31fp+0, 0x1.8edf0e2989db3p-53 },
> +	{ 0x1.6623882552224p+0, 0x1.224fb3c5371e6p-53 },
> +	{ 0x1.68155d44ca973p+0, 0x1.038ae44f73e65p-57 },
> +	{ 0x1.6a09e667f3bccp+0, 0x1.21165f626cdd5p-53 },
> +	{ 0x1.6c012750bdabep+0, 0x1.daed533001e9ep-53 },
> +	{ 0x1.6dfb23c651a2ep+0, 0x1.e441c597c3775p-53 },
> +	{ 0x1.6ff7df9519483p+0, 0x1.9f0fc369e7c42p-53 },
> +	{ 0x1.71f75e8ec5f73p+0, 0x1.ba46e1e5de15ap-53 },
> +	{ 0x1.73f9a48a58173p+0, 0x1.7ab9349cd1562p-53 },
> +	{ 0x1.75feb564267c8p+0, 0x1.7edd354674916p-53 },
> +	{ 0x1.780694fde5d3fp+0, 0x1.866b80a02162dp-54 },
> +	{ 0x1.7a11473eb0186p+0, 0x1.afaa2047ed9b4p-53 },
> +	{ 0x1.7c1ed0130c132p+0, 0x1.f124cd1164dd6p-54 },
> +	{ 0x1.7e2f336cf4e62p+0, 0x1.05d02ba15797ep-56 },
> +	{ 0x1.80427543e1a11p+0, 0x1.6c1bccec9346bp-53 },
> +	{ 0x1.82589994cce12p+0, 0x1.159f115f56694p-53 },
> +	{ 0x1.8471a4623c7acp+0, 0x1.9ca5ed72f8c81p-53 },
> +	{ 0x1.868d99b4492ecp+0, 0x1.01c83b21584a3p-53 },
> +	{ 0x1.88ac7d98a6699p+0, 0x1.994c2f37cb53ap-54 },
> +	{ 0x1.8ace5422aa0dbp+0, 0x1.6e9f156864b27p-54 },
> +	{ 0x1.8cf3216b5448bp+0, 0x1.de55439a2c38bp-53 },
> +	{ 0x1.8f1ae99157736p+0, 0x1.5cc13a2e3976cp-55 },
> +	{ 0x1.9145b0b91ffc5p+0, 0x1.114c368d3ed6ep-53 },
> +	{ 0x1.93737b0cdc5e4p+0, 0x1.e8a0387e4a814p-53 },
> +	{ 0x1.95a44cbc8520ep+0, 0x1.d36906d2b41f9p-53 },
> +	{ 0x1.97d829fde4e4fp+0, 0x1.173d241f23d18p-53 },
> +	{ 0x1.9a0f170ca07b9p+0, 0x1.7462137188ce7p-53 },
> +	{ 0x1.9c49182a3f090p+0, 0x1.c7c46b071f2bep-56 },
> +	{ 0x1.9e86319e32323p+0, 0x1.824ca78e64c6ep-56 },
> +	{ 0x1.a0c667b5de564p+0, 0x1.6535b51719567p-53 },
> +	{ 0x1.a309bec4a2d33p+0, 0x1.6305c7ddc36abp-54 },
> +	{ 0x1.a5503b23e255cp+0, 0x1.1684892395f0fp-53 },
> +	{ 0x1.a799e1330b358p+0, 0x1.bcb7ecac563c7p-54 },
> +	{ 0x1.a9e6b5579fdbfp+0, 0x1.0fac90ef7fd31p-54 },
> +	{ 0x1.ac36bbfd3f379p+0, 0x1.81b72cd4624ccp-53 },
> +	{ 0x1.ae89f995ad3adp+0, 0x1.7a1cd345dcc81p-54 },
> +	{ 0x1.b0e07298db665p+0, 0x1.2108559bf8deep-53 },
> +	{ 0x1.b33a2b84f15fap+0, 0x1.ed7fa1cf7b290p-53 },
> +	{ 0x1.b59728de55939p+0, 0x1.1c7102222c90ep-53 },
> +	{ 0x1.b7f76f2fb5e46p+0, 0x1.d54f610356a79p-53 },
> +	{ 0x1.ba5b030a10649p+0, 0x1.0819678d5eb69p-53 },
> +	{ 0x1.bcc1e904bc1d2p+0, 0x1.23dd07a2d9e84p-55 },
> +	{ 0x1.bf2c25bd71e08p+0, 0x1.0811ae04a31c7p-53 },
> +	{ 0x1.c199bdd85529cp+0, 0x1.11065895048ddp-55 },
> +	{ 0x1.c40ab5fffd07ap+0, 0x1.b4537e083c60ap-54 },
> +	{ 0x1.c67f12e57d14bp+0, 0x1.2884dff483cadp-54 },
> +	{ 0x1.c8f6d9406e7b5p+0, 0x1.1acbc48805c44p-56 },
> +	{ 0x1.cb720dcef9069p+0, 0x1.503cbd1e949dbp-56 },
> +	{ 0x1.cdf0b555dc3f9p+0, 0x1.889f12b1f58a3p-53 },
> +	{ 0x1.d072d4a07897bp+0, 0x1.1a1e45e4342b2p-53 },
> +	{ 0x1.d2f87080d89f1p+0, 0x1.15bc247313d44p-53 },
> +	{ 0x1.d5818dcfba487p+0, 0x1.2ed02d75b3707p-55 },
> +	{ 0x1.d80e316c98397p+0, 0x1.7709f3a09100cp-53 },
> +	{ 0x1.da9e603db3285p+0, 0x1.c2300696db532p-54 },
> +	{ 0x1.dd321f301b460p+0, 0x1.2da5778f018c3p-54 },
> +	{ 0x1.dfc97337b9b5ep+0, 0x1.72d195873da52p-53 },
> +	{ 0x1.e264614f5a128p+0, 0x1.424ec3f42f5b5p-53 },
> +	{ 0x1.e502ee78b3ff6p+0, 0x1.39e8980a9cc8fp-55 },
> +	{ 0x1.e7a51fbc74c83p+0, 0x1.2d522ca0c8de2p-54 },
> +	{ 0x1.ea4afa2a490d9p+0, 0x1.0b1ee7431ebb6p-53 },
> +	{ 0x1.ecf482d8e67f0p+0, 0x1.1b60625f7293ap-53 },
> +	{ 0x1.efa1bee615a27p+0, 0x1.dc7f486a4b6b0p-54 },
> +	{ 0x1.f252b376bba97p+0, 0x1.3a1a5bf0d8e43p-54 },
> +	{ 0x1.f50765b6e4540p+0, 0x1.9d3e12dd8a18bp-54 },
> +	{ 0x1.f7bfdad9cbe13p+0, 0x1.1227697fce57bp-53 },
> +	{ 0x1.fa7c1819e90d8p+0, 0x1.74853f3a5931ep-55 },
> +	{ 0x1.fd3c22b8f71f1p+0, 0x1.2eb74966579e7p-57 }
> +};
> +
> +/*
> + * Kernel for expl(x).  x must be finite and not tiny or huge.
> + * "tiny" is anything that would make us underflow (|A6*x^6| < ~LDBL_MIN).
> + * "huge" is anything that would make fn*L1 inexact (|x| > ~2**17*ln2).
> + */
> +static inline void
> +__k_expl(long double x, long double *hip, long double *lop, int *kp)
> +{
> +	long double fn, q, r, r1, r2, t, z;
> +	int n, n2;
> +
> +	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
> +	fn = rnintl(x * INV_L);
> +	r = x - fn * L1 - fn * L2;	/* r = r1 + r2 done independently. */
> +	n = irint(fn);
> +	n2 = (unsigned)n % INTERVALS;
> +	/* Depend on the sign bit being propagated: */
> +	*kp = n >> LOG2_INTERVALS;
> +	r1 = x - fn * L1;
> +	r2 = fn * -L2;
> +
> +	/* Evaluate expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2). */
> +	z = r * r;
> +#if 0
> +	q = r2 + z * (A2 + r * A3) + z * z * (A4 + r * A5) + z * z * z * A6;
> +#else
> +	q = r2 + z * A2 + z * r * (A3 + r * A4 + z * (A5 + r * A6));
> +#endif
> +	t = (long double)tbl[n2].lo + tbl[n2].hi;
> +	*hip = tbl[n2].hi;
> +	*lop = tbl[n2].lo + t * (q + r1);
> +}
> +
> +static inline void
> +k_hexpl(long double x, long double *hip, long double *lop)
> +{
> +	float twopkm1;
> +	int k;
> +
> +	__k_expl(x, hip, lop, &k);
> +	SET_FLOAT_WORD(twopkm1, 0x3f800000 + ((k - 1) << 23));
> +	*hip *= twopkm1;
> +	*lop *= twopkm1;
> +}
> +
> +static inline long double
> +hexpl(long double x)
> +{
> +	long double hi, lo, twopkm2;
> +	int k;
> +
> +	twopkm2 = 1;
> +	__k_expl(x, &hi, &lo, &k);
> +	SET_LDBL_EXPSIGN(twopkm2, BIAS + k - 2);
> +	return (lo + hi) * 2 * twopkm2;
> +}
> +
> +#ifdef _COMPLEX_H
> +/*
> + * See ../src/k_exp.c for details.
> + */
> +static inline long double complex
> +__ldexp_cexpl(long double complex z, int expt)
> +{
> +	long double c, exp_x, hi, lo, s;
> +	long double x, y, scale1, scale2;
> +	int half_expt, k;
> +
> +	x = creall(z);
> +	y = cimagl(z);
> +	__k_expl(x, &hi, &lo, &k);
> +
> +	exp_x = (lo + hi) * 0x1p16382L;
> +	expt += k - 16382;
> +
> +	scale1 = 1;
> +	half_expt = expt / 2;
> +	SET_LDBL_EXPSIGN(scale1, BIAS + half_expt);
> +	scale2 = 1;
> +	SET_LDBL_EXPSIGN(scale2, BIAS + expt - half_expt);
> +
> +	sincosl(y, &s, &c);
> +	return (CMPLXL(c * exp_x * scale1 * scale2,
> +	    s * exp_x * scale1 * scale2));
> +}
> +#endif /* _COMPLEX_H */
> diff --git a/newlib/libm/ld80/k_sinl.c b/newlib/libm/ld80/k_sinl.c
> new file mode 100644
> index 000000000..af5598dba
> --- /dev/null
> +++ b/newlib/libm/ld80/k_sinl.c
> @@ -0,0 +1,62 @@
> +/* From: @(#)k_sin.c 1.3 95/01/18 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + * Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
> + *
> + * Developed at SunSoft, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice 
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * ld80 version of k_sin.c.  See ../src/k_sin.c for most comments.
> + */
> +
> +#include "math_private.h"
> +
> +static const double
> +half =  0.5;
> +
> +/*
> + * Domain [-0.7854, 0.7854], range ~[-1.89e-22, 1.915e-22]
> + * |sin(x)/x - s(x)| < 2**-72.1
> + *
> + * See ../ld80/k_cosl.c for more details about the polynomial.
> + */
> +#if defined(__amd64__) || defined(__i386__)
> +/* Long double constants are slow on these arches, and broken on i386. */
> +static const volatile double
> +S1hi = -0.16666666666666666,		/* -0x15555555555555.0p-55 */
> +S1lo = -9.2563760475949941e-18;		/* -0x15580000000000.0p-109 */
> +#define	S1	((long double)S1hi + S1lo)
> +#else
> +static const long double
> +S1 = -0.166666666666666666671L;		/* -0xaaaaaaaaaaaaaaab.0p-66 */
> +#endif
> +
> +static const double
> +S2 =  0.0083333333333333332,		/*  0x11111111111111.0p-59 */
> +S3 = -0.00019841269841269427,		/* -0x1a01a01a019f81.0p-65 */
> +S4 =  0.0000027557319223597490,		/*  0x171de3a55560f7.0p-71 */
> +S5 = -0.000000025052108218074604,	/* -0x1ae64564f16cad.0p-78 */
> +S6 =  1.6059006598854211e-10,		/*  0x161242b90243b5.0p-85 */
> +S7 = -7.6429779983024564e-13,		/* -0x1ae42ebd1b2e00.0p-93 */
> +S8 =  2.6174587166648325e-15;		/*  0x179372ea0b3f64.0p-101 */
> +
> +long double
> +__kernel_sinl(long double x, long double y, int iy)
> +{
> +	long double z,r,v;
> +
> +	z	=  x*x;
> +	v	=  z*x;
> +	r	=  S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8)))));
> +	if(iy==0) return x+v*(S1+z*r);
> +	else      return x-((z*(half*y-v*r)-y)-v*S1);
> +}
> diff --git a/newlib/libm/ld80/k_sinpil.h b/newlib/libm/ld80/k_sinpil.h
> new file mode 100644
> index 000000000..00241b932
> --- /dev/null
> +++ b/newlib/libm/ld80/k_sinpil.h
> @@ -0,0 +1,42 @@
> +/*-
> + * Copyright (c) 2017 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * See ../src/k_sinpi.c for implementation details.
> + */
> +
> +static inline long double
> +__kernel_sinpil(long double x)
> +{
> +	long double hi, lo;
> +
> +	hi = (float)x;
> +	lo = x - hi;
> +	lo = lo * (pi_lo + pi_hi) + hi * pi_lo;
> +	hi *= pi_hi;
> +	_2sumF(hi, lo);
> +	return (__kernel_sinl(hi, lo, 1));
> +}
> diff --git a/newlib/libm/ld80/s_cospil.c b/newlib/libm/ld80/s_cospil.c
> new file mode 100644
> index 000000000..199479e9e
> --- /dev/null
> +++ b/newlib/libm/ld80/s_cospil.c
> @@ -0,0 +1,129 @@
> +/*-
> + * Copyright (c) 2017 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * See ../src/s_cospi.c for implementation details.
> + */
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const double
> +pi_hi = 3.1415926814079285e+00,	/* 0x400921fb 0x58000000 */
> +pi_lo =-2.7818135228334233e-08;	/* 0xbe5dde97 0x3dcb3b3a */
> +
> +#include "k_cospil.h"
> +#include "k_sinpil.h"
> +
> +volatile static const double vzero = 0;
> +
> +long double
> +cospil(long double x)
> +{
> +	long double ax, c;
> +	uint64_t lx, m;
> +	uint32_t j0;
> +	uint16_t hx, ix;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +	ix = hx & 0x7fff;
> +	INSERT_LDBL80_WORDS(ax, ix, lx);
> +
> +	ENTERI();
> +
> +	if (ix < 0x3fff) {			/* |x| < 1 */
> +		if (ix < 0x3ffd) {		/* |x| < 0.25 */
> +			if (ix < 0x3fdd) {	/* |x| < 0x1p-34 */
> +				if ((int)x == 0)
> +					RETURNI(1);
> +			}
> +			RETURNI(__kernel_cospil(ax));
> +		}
> +
> +		if (ix < 0x3ffe)			/* |x| < 0.5 */
> +			c = __kernel_sinpil(0.5 - ax);
> +		else if (lx < 0xc000000000000000ull) {	/* |x| < 0.75 */
> +			if (ax == 0.5)
> +				RETURNI(0);
> +			c = -__kernel_sinpil(ax - 0.5);
> +		} else
> +			c = -__kernel_cospil(1 - ax);
> +		RETURNI(c);
> +	}
> +
> +	if (ix < 0x403e) {		/* 1 <= |x| < 0x1p63 */
> +		/* Determine integer part of ax. */
> +		j0 = ix - 0x3fff + 1;
> +		if (j0 < 32) {
> +			lx = (lx >> 32) << 32;
> +			lx &= ~(((lx << 32)-1) >> j0);
> +		} else {
> +			m = (uint64_t)-1 >> (j0 + 1);
> +			if (lx & m) lx &= ~m;
> +		}
> +		INSERT_LDBL80_WORDS(x, ix, lx);
> +
> +		ax -= x;
> +		EXTRACT_LDBL80_WORDS(ix, lx, ax);
> +
> +		if (ix < 0x3ffe) {			/* |x| < 0.5 */
> +			if (ix < 0x3ffd)		/* |x| < 0.25 */
> +				c = ix == 0 ? 1 : __kernel_cospil(ax);
> +			else
> +				c = __kernel_sinpil(0.5 - ax);
> +
> +		} else {
> +			if (lx < 0xc000000000000000ull) { /* |x| < 0.75 */
> +				if (ax == 0.5)
> +					RETURNI(0);
> +				c = -__kernel_sinpil(ax - 0.5);
> +			} else
> +				c = -__kernel_cospil(1 - ax);
> +		}
> +
> +		if (j0 > 40)
> +			x -= 0x1p40;
> +		if (j0 > 30)
> +			x -= 0x1p30;
> +		j0 = (uint32_t)x;
> +
> +		RETURNI(j0 & 1 ? -c : c);
> +	}
> +
> +	if (ix >= 0x7fff)
> +		RETURNI(vzero / vzero);
> +
> +	/*
> +	 * |x| >= 0x1p63 is always an even integer, so return 1.
> +	 */
> +	RETURNI(1);
> +}
> diff --git a/newlib/libm/ld80/s_erfl.c b/newlib/libm/ld80/s_erfl.c
> new file mode 100644
> index 000000000..1ae2f9092
> --- /dev/null
> +++ b/newlib/libm/ld80/s_erfl.c
> @@ -0,0 +1,337 @@
> +/* @(#)s_erf.c 5.1 93/09/24 */
> +/*
> + * ====================================================
> + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
> + *
> + * Developed at SunPro, a Sun Microsystems, Inc. business.
> + * Permission to use, copy, modify, and distribute this
> + * software is freely granted, provided that this notice
> + * is preserved.
> + * ====================================================
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/*
> + * See s_erf.c for complete comments.
> + *
> + * Converted to long double by Steven G. Kargl.
> + */
> +#include <float.h>
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +/* XXX Prevent compilers from erroneously constant folding: */
> +static const volatile long double tiny = 0x1p-10000L;
> +
> +static const double
> +half= 0.5,
> +one = 1,
> +two = 2;
> +/*
> + * In the domain [0, 2**-34], only the first term in the power series
> + * expansion of erf(x) is used.  The magnitude of the first neglected
> + * terms is less than 2**-102.
> + */
> +static const union IEEEl2bits
> +efxu  = LD80C(0x8375d410a6db446c, -3,  1.28379167095512573902e-1L),
> +efx8u = LD80C(0x8375d410a6db446c,  0,  1.02703333676410059122e+0L),
> +/*
> + * Domain [0, 0.84375], range ~[-1.423e-22, 1.423e-22]:
> + * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-72.573
> + */
> +pp0u  = LD80C(0x8375d410a6db446c, -3,   1.28379167095512573902e-1L),
> +pp1u  = LD80C(0xa46c7d09ec3d0cec, -2,  -3.21140201054840180596e-1L),
> +pp2u  = LD80C(0x9b31e66325576f86, -5,  -3.78893851760347812082e-2L),
> +pp3u  = LD80C(0x804ac72c9a0b97dd, -7,  -7.83032847030604679616e-3L),
> +pp4u  = LD80C(0x9f42bcbc3d5a601d, -12, -3.03765663857082048459e-4L),
> +pp5u  = LD80C(0x9ec4ad6193470693, -16, -1.89266527398167917502e-5L),
> +qq1u  = LD80C(0xdb4b8eb713188d6b, -2,   4.28310832832310510579e-1L),
> +qq2u  = LD80C(0xa5750835b2459bd1, -4,   8.07896272074540216658e-2L),
> +qq3u  = LD80C(0x8b85d6bd6a90b51c, -7,   8.51579638189385354266e-3L),
> +qq4u  = LD80C(0x87332f82cff4ff96, -11,  5.15746855583604912827e-4L),
> +qq5u  = LD80C(0x83466cb6bf9dca00, -16,  1.56492109706256700009e-5L),
> +qq6u  = LD80C(0xf5bf98c2f996bf63, -24,  1.14435527803073879724e-7L);
> +#define	efx	(efxu.e)
> +#define	efx8	(efx8u.e)
> +#define	pp0	(pp0u.e)
> +#define	pp1	(pp1u.e)
> +#define	pp2	(pp2u.e)
> +#define	pp3	(pp3u.e)
> +#define	pp4	(pp4u.e)
> +#define	pp5	(pp5u.e)
> +#define	qq1	(qq1u.e)
> +#define	qq2	(qq2u.e)
> +#define	qq3	(qq3u.e)
> +#define	qq4	(qq4u.e)
> +#define	qq5	(qq5u.e)
> +#define	qq6	(qq6u.e)
> +static const union IEEEl2bits
> +erxu  = LD80C(0xd7bb3d0000000000, -1,  8.42700779438018798828e-1L),
> +/*
> + * Domain [0.84375, 1.25], range ~[-8.132e-22, 8.113e-22]:
> + * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-71.762
> + */
> +pa0u  = LD80C(0xe8211158da02c692, -27,  1.35116960705131296711e-8L),
> +pa1u  = LD80C(0xd488f89f36988618, -2,   4.15107507167065612570e-1L),
> +pa2u  = LD80C(0xece74f8c63fa3942, -4,  -1.15675565215949226989e-1L),
> +pa3u  = LD80C(0xc8d31e020727c006, -4,   9.80589241379624665791e-2L),
> +pa4u  = LD80C(0x985d5d5fafb0551f, -5,   3.71984145558422368847e-2L),
> +pa5u  = LD80C(0xa5b6c4854d2f5452, -8,  -5.05718799340957673661e-3L),
> +pa6u  = LD80C(0x85c8d58fe3993a47, -8,   4.08277919612202243721e-3L),
> +pa7u  = LD80C(0xddbfbc23677b35cf, -13,  2.11476292145347530794e-4L),
> +qa1u  = LD80C(0xb8a977896f5eff3f, -1,   7.21335860303380361298e-1L),
> +qa2u  = LD80C(0x9fcd662c3d4eac86, -1,   6.24227891731886593333e-1L),
> +qa3u  = LD80C(0x9d0b618eac67ba07, -2,   3.06727455774491855801e-1L),
> +qa4u  = LD80C(0x881a4293f6d6c92d, -3,   1.32912674218195890535e-1L),
> +qa5u  = LD80C(0xbab144f07dea45bf, -5,   4.55792134233613027584e-2L),
> +qa6u  = LD80C(0xa6c34ba438bdc900, -7,   1.01783980070527682680e-2L),
> +qa7u  = LD80C(0x8fa866dc20717a91, -9,   2.19204436518951438183e-3L);
> +#define erx	(erxu.e)
> +#define pa0	(pa0u.e)
> +#define pa1	(pa1u.e)
> +#define pa2	(pa2u.e)
> +#define pa3	(pa3u.e)
> +#define pa4	(pa4u.e)
> +#define pa5	(pa5u.e)
> +#define pa6	(pa6u.e)
> +#define pa7	(pa7u.e)
> +#define qa1	(qa1u.e)
> +#define qa2	(qa2u.e)
> +#define qa3	(qa3u.e)
> +#define qa4	(qa4u.e)
> +#define qa5	(qa5u.e)
> +#define qa6	(qa6u.e)
> +#define qa7	(qa7u.e)
> +static const union IEEEl2bits
> +/*
> + * Domain [1.25,2.85715], range ~[-2.334e-22,2.334e-22]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-71.860
> + */
> +ra0u  = LD80C(0xa1a091e0fb4f335a, -7, -9.86494298915814308249e-3L),
> +ra1u  = LD80C(0xc2b0d045ae37df6b, -1, -7.60510460864878271275e-1L),
> +ra2u  = LD80C(0xf2cec3ee7da636c5, 3,  -1.51754798236892278250e+1L),
> +ra3u  = LD80C(0x813cc205395adc7d, 7,  -1.29237335516455333420e+2L),
> +ra4u  = LD80C(0x8737c8b7b4062c2f, 9,  -5.40871625829510494776e+2L),
> +ra5u  = LD80C(0x8ffe5383c08d4943, 10, -1.15194769466026108551e+3L),
> +ra6u  = LD80C(0x983573e64d5015a9, 10, -1.21767039790249025544e+3L),
> +ra7u  = LD80C(0x92a794e763a6d4db, 9,  -5.86618463370624636688e+2L),
> +ra8u  = LD80C(0xd5ad1fae77c3d9a3, 6,  -1.06838132335777049840e+2L),
> +ra9u  = LD80C(0x934c1a247807bb9c, 2,  -4.60303980944467334806e+0L),
> +sa1u  = LD80C(0xd342f90012bb1189, 4,   2.64077014928547064865e+1L),
> +sa2u  = LD80C(0x839be13d9d5da883, 8,   2.63217811300123973067e+2L),
> +sa3u  = LD80C(0x9f8cba6d1ae1b24b, 10,  1.27639775710344617587e+3L),
> +sa4u  = LD80C(0xcaa83f403713e33e, 11,  3.24251544209971162003e+3L),
> +sa5u  = LD80C(0x8796aff2f3c47968, 12,  4.33883591261332837874e+3L),
> +sa6u  = LD80C(0xb6ef97f9c753157b, 11,  2.92697460344182158454e+3L),
> +sa7u  = LD80C(0xe02aee5f83773d1c, 9,   8.96670799139389559818e+2L),
> +sa8u  = LD80C(0xc82b83855b88e07e, 6,   1.00084987800048510018e+2L),
> +sa9u  = LD80C(0x92f030aefadf28ad, 1,   2.29591004455459083843e+0L);
> +#define ra0	(ra0u.e)
> +#define ra1	(ra1u.e)
> +#define ra2	(ra2u.e)
> +#define ra3	(ra3u.e)
> +#define ra4	(ra4u.e)
> +#define ra5	(ra5u.e)
> +#define ra6	(ra6u.e)
> +#define ra7	(ra7u.e)
> +#define ra8	(ra8u.e)
> +#define ra9	(ra9u.e)
> +#define sa1	(sa1u.e)
> +#define sa2	(sa2u.e)
> +#define sa3	(sa3u.e)
> +#define sa4	(sa4u.e)
> +#define sa5	(sa5u.e)
> +#define sa6	(sa6u.e)
> +#define sa7	(sa7u.e)
> +#define sa8	(sa8u.e)
> +#define sa9	(sa9u.e)
> +/*
> + * Domain [2.85715,7], range ~[-8.323e-22,8.390e-22]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-70.326
> + */
> +static const union IEEEl2bits
> +rb0u = LD80C(0xa1a091cf43abcd26, -7, -9.86494292470284646962e-3L),
> +rb1u = LD80C(0xd19d2df1cbb8da0a, -1, -8.18804618389296662837e-1L),
> +rb2u = LD80C(0x9a4dd1383e5daf5b, 4,  -1.92879967111618594779e+1L),
> +rb3u = LD80C(0xbff0ae9fc0751de6, 7,  -1.91940164551245394969e+2L),
> +rb4u = LD80C(0xdde08465310b472b, 9,  -8.87508080766577324539e+2L),
> +rb5u = LD80C(0xe796e1d38c8c70a9, 10, -1.85271506669474503781e+3L),
> +rb6u = LD80C(0xbaf655a76e0ab3b5, 10, -1.49569795581333675349e+3L),
> +rb7u = LD80C(0x95d21e3e75503c21, 8,  -2.99641547972948019157e+2L),
> +sb1u = LD80C(0x814487ed823c8cbd, 5,   3.23169247732868256569e+1L),
> +sb2u = LD80C(0xbe4bfbb1301304be, 8,   3.80593618534539961773e+2L),
> +sb3u = LD80C(0x809c4ade46b927c7, 11,  2.05776827838541292848e+3L),
> +sb4u = LD80C(0xa55284359f3395a8, 12,  5.29031455540062116327e+3L),
> +sb5u = LD80C(0xbcfa72da9b820874, 12,  6.04730608102312640462e+3L),
> +sb6u = LD80C(0x9d09a35988934631, 11,  2.51260238030767176221e+3L),
> +sb7u = LD80C(0xd675bbe542c159fa, 7,   2.14459898308561015684e+2L);
> +#define rb0	(rb0u.e)
> +#define rb1	(rb1u.e)
> +#define rb2	(rb2u.e)
> +#define rb3	(rb3u.e)
> +#define rb4	(rb4u.e)
> +#define rb5	(rb5u.e)
> +#define rb6	(rb6u.e)
> +#define rb7	(rb7u.e)
> +#define sb1	(sb1u.e)
> +#define sb2	(sb2u.e)
> +#define sb3	(sb3u.e)
> +#define sb4	(sb4u.e)
> +#define sb5	(sb5u.e)
> +#define sb6	(sb6u.e)
> +#define sb7	(sb7u.e)
> +/*
> + * Domain [7,108], range ~[-4.422e-22,4.422e-22]:
> + * |log(x*erfc(x)) + x**2 + 0.5625 - rc(x)/sc(x)| < 2**-70.938
> + */
> +static const union IEEEl2bits
> +/* err = -4.422092275318925082e-22 -70.937689 */
> +rc0u = LD80C(0xa1a091cf437a17ad, -7, -9.86494292470008707260e-3L),
> +rc1u = LD80C(0xbe79c5a978122b00, -1, -7.44045595049165939261e-1L),
> +rc2u = LD80C(0xdb26f9bbe31a2794, 3,  -1.36970155085888424425e+1L),
> +rc3u = LD80C(0xb5f69a38f5747ac8, 6,  -9.09816453742625888546e+1L),
> +rc4u = LD80C(0xd79676d970d0a21a, 7,  -2.15587750997584074147e+2L),
> +rc5u = LD80C(0xfe528153c45ec97c, 6,  -1.27161142938347796666e+2L),
> +sc1u = LD80C(0xc5e8cd46d5604a96, 4,   2.47386727842204312937e+1L),
> +sc2u = LD80C(0xc5f0f5a5484520eb, 7,   1.97941248254913378865e+2L),
> +sc3u = LD80C(0x964e3c7b34db9170, 9,   6.01222441484087787522e+2L),
> +sc4u = LD80C(0x99be1b89faa0596a, 9,   6.14970430845978077827e+2L),
> +sc5u = LD80C(0xf80dfcbf37ffc5ea, 6,   1.24027318931184605891e+2L);
> +#define rc0	(rc0u.e)
> +#define rc1	(rc1u.e)
> +#define rc2	(rc2u.e)
> +#define rc3	(rc3u.e)
> +#define rc4	(rc4u.e)
> +#define rc5	(rc5u.e)
> +#define sc1	(sc1u.e)
> +#define sc2	(sc2u.e)
> +#define sc3	(sc3u.e)
> +#define sc4	(sc4u.e)
> +#define sc5	(sc5u.e)
> +
> +long double
> +erfl(long double x)
> +{
> +	long double ax,R,S,P,Q,s,y,z,r;
> +	uint64_t lx;
> +	int32_t i;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +
> +	if((hx & 0x7fff) == 0x7fff) {	/* erfl(nan)=nan */
> +		i = (hx>>15)<<1;
> +		return (1-i)+one/x;	/* erfl(+-inf)=+-1 */
> +	}
> +
> +	ENTERI();
> +
> +	ax = fabsl(x);
> +	if(ax < 0.84375) {
> +	    if(ax < 0x1p-34L) {
> +	        if(ax < 0x1p-16373L)	
> +		    RETURNI((8*x+efx8*x)/8);	/* avoid spurious underflow */
> +		RETURNI(x + efx*x);
> +	    }
> +	    z = x*x;
> +	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5))));
> +	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6)))));
> +	    y = r/s;
> +	    RETURNI(x + x*y);
> +	}
> +	if(ax < 1.25) {
> +	    s = ax-one;
> +	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7))))));
> +	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7))))));
> +	    if(x>=0) RETURNI(erx + P/Q); else RETURNI(-erx - P/Q);
> +	}
> +	if(ax >= 7) {			/* inf>|x|>= 7 */
> +	    if(x>=0) RETURNI(one-tiny); else RETURNI(tiny-one);
> +	}
> +	s = one/(ax*ax);
> +	if(ax < 2.85715) {	/* |x| < 2.85715 */
> +	    R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
> +		s*(ra8+s*ra9))))))));
> +	    S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
> +		s*(sa8+s*sa9))))))));
> +	} else {	/* |x| >= 2.85715 */
> +	    R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7))))));
> +	    S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))));
> +	}
> +	z=(float)ax;
> +	r=expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
> +	if(x>=0) RETURNI(one-r/ax); else RETURNI(r/ax-one);
> +}
> +
> +long double
> +erfcl(long double x)
> +{
> +	long double ax,R,S,P,Q,s,y,z,r;
> +	uint64_t lx;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +
> +	if((hx & 0x7fff) == 0x7fff) {	/* erfcl(nan)=nan */
> +					/* erfcl(+-inf)=0,2 */
> +	    return ((hx>>15)<<1)+one/x;
> +	}
> +
> +	ENTERI();
> +
> +	ax = fabsl(x);
> +	if(ax < 0.84375L) {
> +	    if(ax < 0x1p-34L)
> +		RETURNI(one-x);
> +	    z = x*x;
> +	    r = pp0+z*(pp1+z*(pp2+z*(pp3+z*(pp4+z*pp5))));
> +	    s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*(qq5+z*qq6)))));
> +	    y = r/s;
> +	    if(ax < 0.25L) {  	/* x<1/4 */
> +		RETURNI(one-(x+x*y));
> +	    } else {
> +		r = x*y;
> +		r += (x-half);
> +	       RETURNI(half - r);
> +	    }
> +	}
> +	if(ax < 1.25L) {
> +	    s = ax-one;
> +	    P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*(pa6+s*pa7))))));
> +	    Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*(qa6+s*qa7))))));
> +	    if(x>=0) {
> +	        z  = one-erx; RETURNI(z - P/Q);
> +	    } else {
> +		z = (erx+P/Q); RETURNI(one+z);
> +	    }
> +	}
> +
> +	if(ax < 108) {			/* |x| < 108 */
> + 	    s = one/(ax*ax);
> +	    if(ax < 2.85715) {		/* |x| < 2.85715 */
> +		R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(ra5+s*(ra6+s*(ra7+
> +		    s*(ra8+s*ra9))))))));
> +		S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(sa5+s*(sa6+s*(sa7+
> +		    s*(sa8+s*sa9))))))));
> +	    } else if(ax < 7) {		/* | |x| < 7 */
> +		R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(rb5+s*(rb6+s*rb7))))));
> +		S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(sb5+s*(sb6+s*sb7))))));
> +	    } else {
> +		if(x < -7) RETURNI(two-tiny);/* x < -7 */
> +		R=rc0+s*(rc1+s*(rc2+s*(rc3+s*(rc4+s*rc5))));
> +		S=one+s*(sc1+s*(sc2+s*(sc3+s*(sc4+s*sc5))));
> +	    }
> +	    z = (float)ax;
> +	    r = expl(-z*z-0.5625)*expl((z-ax)*(z+ax)+R/S);
> +	    if(x>0) RETURNI(r/ax); else RETURNI(two-r/ax);
> +	} else {
> +	    if(x>0) RETURNI(tiny*tiny); else RETURNI(two-tiny);
> +	}
> +}
> diff --git a/newlib/libm/ld80/s_exp2l.c b/newlib/libm/ld80/s_exp2l.c
> new file mode 100644
> index 000000000..421d6e2e0
> --- /dev/null
> +++ b/newlib/libm/ld80/s_exp2l.c
> @@ -0,0 +1,290 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <float.h>
> +#include <stdint.h>
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +#define	TBLBITS	7
> +#define	TBLSIZE	(1 << TBLBITS)
> +
> +#define	BIAS	(LDBL_MAX_EXP - 1)
> +
> +static volatile long double
> +    huge = 0x1p10000L,
> +    twom10000 = 0x1p-10000L;
> +
> +static const union IEEEl2bits
> +P1 = LD80C(0xb17217f7d1cf79ac, -1, 6.93147180559945309429e-1L);
> +
> +static const double
> +redux = 0x1.8p63 / TBLSIZE,
> +/*
> + * Domain [-0.00390625, 0.00390625], range ~[-1.7079e-23, 1.7079e-23]
> + * |exp(x) - p(x)| < 2**-75.6
> + */
> +P2 = 2.4022650695910072e-1,		/*  0x1ebfbdff82c58f.0p-55 */
> +P3 = 5.5504108664816879e-2,		/*  0x1c6b08d7049e1a.0p-57 */
> +P4 = 9.6181291055695180e-3,		/*  0x13b2ab6fa8321a.0p-59 */
> +P5 = 1.3333563089183052e-3,		/*  0x15d8806f67f251.0p-62 */
> +P6 = 1.5413361552277414e-4;		/*  0x1433ddacff3441.0p-65 */
> +
> +static const double tbl[TBLSIZE * 2] = {
> +	0x1.6a09e667f3bcdp-1,	-0x1.bdd3413b2648p-55,
> +	0x1.6c012750bdabfp-1,	-0x1.2895667ff0cp-57,
> +	0x1.6dfb23c651a2fp-1,	-0x1.bbe3a683c88p-58,
> +	0x1.6ff7df9519484p-1,	-0x1.83c0f25860fp-56,
> +	0x1.71f75e8ec5f74p-1,	-0x1.16e4786887bp-56,
> +	0x1.73f9a48a58174p-1,	-0x1.0a8d96c65d5p-55,
> +	0x1.75feb564267c9p-1,	-0x1.0245957316ep-55,
> +	0x1.780694fde5d3fp-1,	 0x1.866b80a0216p-55,
> +	0x1.7a11473eb0187p-1,	-0x1.41577ee0499p-56,
> +	0x1.7c1ed0130c132p-1,	 0x1.f124cd1164ep-55,
> +	0x1.7e2f336cf4e62p-1,	 0x1.05d02ba157ap-57,
> +	0x1.80427543e1a12p-1,	-0x1.27c86626d97p-55,
> +	0x1.82589994cce13p-1,	-0x1.d4c1dd41533p-55,
> +	0x1.8471a4623c7adp-1,	-0x1.8d684a341cep-56,
> +	0x1.868d99b4492edp-1,	-0x1.fc6f89bd4f68p-55,
> +	0x1.88ac7d98a6699p-1,	 0x1.994c2f37cb5p-55,
> +	0x1.8ace5422aa0dbp-1,	 0x1.6e9f156864bp-55,
> +	0x1.8cf3216b5448cp-1,	-0x1.0d55e32e9e4p-57,
> +	0x1.8f1ae99157736p-1,	 0x1.5cc13a2e397p-56,
> +	0x1.9145b0b91ffc6p-1,	-0x1.dd6792e5825p-55,
> +	0x1.93737b0cdc5e5p-1,	-0x1.75fc781b58p-58,
> +	0x1.95a44cbc8520fp-1,	-0x1.64b7c96a5fp-57,
> +	0x1.97d829fde4e5p-1,	-0x1.d185b7c1b86p-55,
> +	0x1.9a0f170ca07bap-1,	-0x1.173bd91cee6p-55,
> +	0x1.9c49182a3f09p-1,	 0x1.c7c46b071f2p-57,
> +	0x1.9e86319e32323p-1,	 0x1.824ca78e64cp-57,
> +	0x1.a0c667b5de565p-1,	-0x1.359495d1cd5p-55,
> +	0x1.a309bec4a2d33p-1,	 0x1.6305c7ddc368p-55,
> +	0x1.a5503b23e255dp-1,	-0x1.d2f6edb8d42p-55,
> +	0x1.a799e1330b358p-1,	 0x1.bcb7ecac564p-55,
> +	0x1.a9e6b5579fdbfp-1,	 0x1.0fac90ef7fdp-55,
> +	0x1.ac36bbfd3f37ap-1,	-0x1.f9234cae76dp-56,
> +	0x1.ae89f995ad3adp-1,	 0x1.7a1cd345dcc8p-55,
> +	0x1.b0e07298db666p-1,	-0x1.bdef54c80e4p-55,
> +	0x1.b33a2b84f15fbp-1,	-0x1.2805e3084d8p-58,
> +	0x1.b59728de5593ap-1,	-0x1.c71dfbbba6ep-55,
> +	0x1.b7f76f2fb5e47p-1,	-0x1.5584f7e54acp-57,
> +	0x1.ba5b030a1064ap-1,	-0x1.efcd30e5429p-55,
> +	0x1.bcc1e904bc1d2p-1,	 0x1.23dd07a2d9fp-56,
> +	0x1.bf2c25bd71e09p-1,	-0x1.efdca3f6b9c8p-55,
> +	0x1.c199bdd85529cp-1,	 0x1.11065895049p-56,
> +	0x1.c40ab5fffd07ap-1,	 0x1.b4537e083c6p-55,
> +	0x1.c67f12e57d14bp-1,	 0x1.2884dff483c8p-55,
> +	0x1.c8f6d9406e7b5p-1,	 0x1.1acbc48805cp-57,
> +	0x1.cb720dcef9069p-1,	 0x1.503cbd1e94ap-57,
> +	0x1.cdf0b555dc3fap-1,	-0x1.dd83b53829dp-56,
> +	0x1.d072d4a07897cp-1,	-0x1.cbc3743797a8p-55,
> +	0x1.d2f87080d89f2p-1,	-0x1.d487b719d858p-55,
> +	0x1.d5818dcfba487p-1,	 0x1.2ed02d75b37p-56,
> +	0x1.d80e316c98398p-1,	-0x1.11ec18bedep-55,
> +	0x1.da9e603db3285p-1,	 0x1.c2300696db5p-55,
> +	0x1.dd321f301b46p-1,	 0x1.2da5778f019p-55,
> +	0x1.dfc97337b9b5fp-1,	-0x1.1a5cd4f184b8p-55,
> +	0x1.e264614f5a129p-1,	-0x1.7b627817a148p-55,
> +	0x1.e502ee78b3ff6p-1,	 0x1.39e8980a9cdp-56,
> +	0x1.e7a51fbc74c83p-1,	 0x1.2d522ca0c8ep-55,
> +	0x1.ea4afa2a490dap-1,	-0x1.e9c23179c288p-55,
> +	0x1.ecf482d8e67f1p-1,	-0x1.c93f3b411ad8p-55,
> +	0x1.efa1bee615a27p-1,	 0x1.dc7f486a4b68p-55,
> +	0x1.f252b376bba97p-1,	 0x1.3a1a5bf0d8e8p-55,
> +	0x1.f50765b6e454p-1,	 0x1.9d3e12dd8a18p-55,
> +	0x1.f7bfdad9cbe14p-1,	-0x1.dbb12d00635p-55,
> +	0x1.fa7c1819e90d8p-1,	 0x1.74853f3a593p-56,
> +	0x1.fd3c22b8f71f1p-1,	 0x1.2eb74966578p-58,
> +	0x1p+0,	 0x0p+0,
> +	0x1.0163da9fb3335p+0,	 0x1.b61299ab8cd8p-54,
> +	0x1.02c9a3e778061p+0,	-0x1.19083535b08p-56,
> +	0x1.04315e86e7f85p+0,	-0x1.0a31c1977c98p-54,
> +	0x1.059b0d3158574p+0,	 0x1.d73e2a475b4p-55,
> +	0x1.0706b29ddf6dep+0,	-0x1.c91dfe2b13cp-55,
> +	0x1.0874518759bc8p+0,	 0x1.186be4bb284p-57,
> +	0x1.09e3ecac6f383p+0,	 0x1.14878183161p-54,
> +	0x1.0b5586cf9890fp+0,	 0x1.8a62e4adc61p-54,
> +	0x1.0cc922b7247f7p+0,	 0x1.01edc16e24f8p-54,
> +	0x1.0e3ec32d3d1a2p+0,	 0x1.03a1727c58p-59,
> +	0x1.0fb66affed31bp+0,	-0x1.b9bedc44ebcp-57,
> +	0x1.11301d0125b51p+0,	-0x1.6c51039449bp-54,
> +	0x1.12abdc06c31ccp+0,	-0x1.1b514b36ca8p-58,
> +	0x1.1429aaea92dep+0,	-0x1.32fbf9af1368p-54,
> +	0x1.15a98c8a58e51p+0,	 0x1.2406ab9eeabp-55,
> +	0x1.172b83c7d517bp+0,	-0x1.19041b9d78ap-55,
> +	0x1.18af9388c8deap+0,	-0x1.11023d1970f8p-54,
> +	0x1.1a35beb6fcb75p+0,	 0x1.e5b4c7b4969p-55,
> +	0x1.1bbe084045cd4p+0,	-0x1.95386352ef6p-54,
> +	0x1.1d4873168b9aap+0,	 0x1.e016e00a264p-54,
> +	0x1.1ed5022fcd91dp+0,	-0x1.1df98027bb78p-54,
> +	0x1.2063b88628cd6p+0,	 0x1.dc775814a85p-55,
> +	0x1.21f49917ddc96p+0,	 0x1.2a97e9494a6p-55,
> +	0x1.2387a6e756238p+0,	 0x1.9b07eb6c7058p-54,
> +	0x1.251ce4fb2a63fp+0,	 0x1.ac155bef4f5p-55,
> +	0x1.26b4565e27cddp+0,	 0x1.2bd339940eap-55,
> +	0x1.284dfe1f56381p+0,	-0x1.a4c3a8c3f0d8p-54,
> +	0x1.29e9df51fdee1p+0,	 0x1.612e8afad12p-55,
> +	0x1.2b87fd0dad99p+0,	-0x1.10adcd6382p-59,
> +	0x1.2d285a6e4030bp+0,	 0x1.0024754db42p-54,
> +	0x1.2ecafa93e2f56p+0,	 0x1.1ca0f45d524p-56,
> +	0x1.306fe0a31b715p+0,	 0x1.6f46ad23183p-55,
> +	0x1.32170fc4cd831p+0,	 0x1.a9ce78e1804p-55,
> +	0x1.33c08b26416ffp+0,	 0x1.327218436598p-54,
> +	0x1.356c55f929ff1p+0,	-0x1.b5cee5c4e46p-55,
> +	0x1.371a7373aa9cbp+0,	-0x1.63aeabf42ebp-54,
> +	0x1.38cae6d05d866p+0,	-0x1.e958d3c99048p-54,
> +	0x1.3a7db34e59ff7p+0,	-0x1.5e436d661f6p-56,
> +	0x1.3c32dc313a8e5p+0,	-0x1.efff8375d2ap-54,
> +	0x1.3dea64c123422p+0,	 0x1.ada0911f09fp-55,
> +	0x1.3fa4504ac801cp+0,	-0x1.7d023f956fap-54,
> +	0x1.4160a21f72e2ap+0,	-0x1.ef3691c309p-58,
> +	0x1.431f5d950a897p+0,	-0x1.1c7dde35f7ap-55,
> +	0x1.44e086061892dp+0,	 0x1.89b7a04ef8p-59,
> +	0x1.46a41ed1d0057p+0,	 0x1.c944bd1648a8p-54,
> +	0x1.486a2b5c13cdp+0,	 0x1.3c1a3b69062p-56,
> +	0x1.4a32af0d7d3dep+0,	 0x1.9cb62f3d1be8p-54,
> +	0x1.4bfdad5362a27p+0,	 0x1.d4397afec42p-56,
> +	0x1.4dcb299fddd0dp+0,	 0x1.8ecdbbc6a78p-54,
> +	0x1.4f9b2769d2ca7p+0,	-0x1.4b309d25958p-54,
> +	0x1.516daa2cf6642p+0,	-0x1.f768569bd94p-55,
> +	0x1.5342b569d4f82p+0,	-0x1.07abe1db13dp-55,
> +	0x1.551a4ca5d920fp+0,	-0x1.d689cefede6p-55,
> +	0x1.56f4736b527dap+0,	 0x1.9bb2c011d938p-54,
> +	0x1.58d12d497c7fdp+0,	 0x1.295e15b9a1ep-55,
> +	0x1.5ab07dd485429p+0,	 0x1.6324c0546478p-54,
> +	0x1.5c9268a5946b7p+0,	 0x1.c4b1b81698p-60,
> +	0x1.5e76f15ad2148p+0,	 0x1.ba6f93080e68p-54,
> +	0x1.605e1b976dc09p+0,	-0x1.3e2429b56de8p-54,
> +	0x1.6247eb03a5585p+0,	-0x1.383c17e40b48p-54,
> +	0x1.6434634ccc32p+0,	-0x1.c483c759d89p-55,
> +	0x1.6623882552225p+0,	-0x1.bb60987591cp-54,
> +	0x1.68155d44ca973p+0,	 0x1.038ae44f74p-57,
> +};
> +
> +/**
> + * Compute the base 2 exponential of x for Intel 80-bit format.
> + *
> + * Accuracy: Peak error < 0.511 ulp.
> + *
> + * Method: (equally-spaced tables)
> + *
> + *   Reduce x:
> + *     x = 2**k + y, for integer k and |y| <= 1/2.
> + *     Thus we have exp2l(x) = 2**k * exp2(y).
> + *
> + *   Reduce y:
> + *     y = i/TBLSIZE + z for integer i near y * TBLSIZE.
> + *     Thus we have exp2(y) = exp2(i/TBLSIZE) * exp2(z),
> + *     with |z| <= 2**-(TBLBITS+1).
> + *
> + *   We compute exp2(i/TBLSIZE) via table lookup and exp2(z) via a
> + *   degree-6 minimax polynomial with maximum error under 2**-75.6.
> + *   The table entries each have 104 bits of accuracy, encoded as
> + *   a pair of double precision values.
> + */
> +long double
> +exp2l(long double x)
> +{
> +	union IEEEl2bits u, v;
> +	long double r, twopk, twopkp10000, z;
> +	uint32_t hx, ix, i0;
> +	int k;
> +
> +	/* Filter out exceptional cases. */
> +	u.e = x;
> +	hx = u.xbits.expsign;
> +	ix = hx & 0x7fff;
> +	if (ix >= BIAS + 14) {		/* |x| >= 16384 or x is NaN */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (hx & 0x8000 && u.xbits.man == 1ULL << 63)
> +				return (0.0L);	/* x is -Inf */
> +			return (x + x); /* x is +Inf, NaN or unsupported */
> +		}
> +		if (x >= 16384)
> +			return (huge * huge);	/* overflow */
> +		if (x <= -16446)
> +			return (twom10000 * twom10000);	/* underflow */
> +	} else if (ix <= BIAS - 66) {	/* |x| < 0x1p-65 (includes pseudos) */
> +		return (1.0L + x);	/* 1 with inexact */
> +	}
> +
> +	ENTERI();
> +
> +	/*
> +	 * Reduce x, computing z, i0, and k. The low bits of x + redux
> +	 * contain the 16-bit integer part of the exponent (k) followed by
> +	 * TBLBITS fractional bits (i0). We use bit tricks to extract these
> +	 * as integers, then set z to the remainder.
> +	 *
> +	 * Example: Suppose x is 0xabc.123456p0 and TBLBITS is 8.
> +	 * Then the low-order word of x + redux is 0x000abc12,
> +	 * We split this into k = 0xabc and i0 = 0x12 (adjusted to
> +	 * index into the table), then we compute z = 0x0.003456p0.
> +	 *
> +	 * XXX If the exponent is negative, the computation of k depends on
> +	 *     '>>' doing sign extension.
> +	 */
> +	u.e = x + redux;
> +	i0 = u.bits.manl + TBLSIZE / 2;
> +	k = (int)i0 >> TBLBITS;
> +	i0 = (i0 & (TBLSIZE - 1)) << 1;
> +	u.e -= redux;
> +	z = x - u.e;
> +	v.xbits.man = 1ULL << 63;
> +	if (k >= LDBL_MIN_EXP) {
> +		v.xbits.expsign = BIAS + k;
> +		twopk = v.e;
> +	} else {
> +		v.xbits.expsign = BIAS + k + 10000;
> +		twopkp10000 = v.e;
> +	}
> +
> +	/* Compute r = exp2l(y) = exp2lt[i0] * p(z). */
> +	long double t_hi = tbl[i0];
> +	long double t_lo = tbl[i0 + 1];
> +	r = t_lo + (t_hi + t_lo) * z * (P1.e + z * (P2 + z * (P3 + z * (P4
> +	    + z * (P5 + z * P6))))) + t_hi;
> +
> +	/* Scale by 2**k. */
> +	if (k >= LDBL_MIN_EXP) {
> +		if (k == LDBL_MAX_EXP)
> +			RETURNI(r * 2.0 * 0x1p16383L);
> +		RETURNI(r * twopk);
> +	} else {
> +		RETURNI(r * twopkp10000 * twom10000);
> +	}
> +}
> diff --git a/newlib/libm/ld80/s_expl.c b/newlib/libm/ld80/s_expl.c
> new file mode 100644
> index 000000000..e46e73f0c
> --- /dev/null
> +++ b/newlib/libm/ld80/s_expl.c
> @@ -0,0 +1,279 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2009-2013 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + * Optimized by Bruce D. Evans.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/**
> + * Compute the exponential of x for Intel 80-bit format.  This is based on:
> + *
> + *   PTP Tang, "Table-driven implementation of the exponential function
> + *   in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 15,
> + *   144-157 (1989).
> + *
> + * where the 32 table entries have been expanded to INTERVALS (see below).
> + */
> +
> +#include <float.h>
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +#include "k_expl.h"
> +
> +/* XXX Prevent compilers from erroneously constant folding these: */
> +static const volatile long double
> +huge = 0x1p10000L,
> +tiny = 0x1p-10000L;
> +
> +static const long double
> +twom10000 = 0x1p-10000L;
> +
> +static const union IEEEl2bits
> +/* log(2**16384 - 0.5) rounded towards zero: */
> +/* log(2**16384 - 0.5 + 1) rounded towards zero for expm1l() is the same: */
> +o_thresholdu = LD80C(0xb17217f7d1cf79ab, 13,  11356.5234062941439488L),
> +#define o_threshold	 (o_thresholdu.e)
> +/* log(2**(-16381-64-1)) rounded towards zero: */
> +u_thresholdu = LD80C(0xb21dfe7f09e2baa9, 13, -11399.4985314888605581L);
> +#define u_threshold	 (u_thresholdu.e)
> +
> +long double
> +expl(long double x)
> +{
> +	union IEEEl2bits u;
> +	long double hi, lo, t, twopk;
> +	int k;
> +	uint16_t hx, ix;
> +
> +	DOPRINT_START(&x);
> +
> +	/* Filter out exceptional cases. */
> +	u.e = x;
> +	hx = u.xbits.expsign;
> +	ix = hx & 0x7fff;
> +	if (ix >= BIAS + 13) {		/* |x| >= 8192 or x is NaN */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (hx & 0x8000)  /* x is -Inf, -NaN or unsupported */
> +				RETURNP(-1 / x);
> +			RETURNP(x + x);	/* x is +Inf, +NaN or unsupported */
> +		}
> +		if (x > o_threshold)
> +			RETURNP(huge * huge);
> +		if (x < u_threshold)
> +			RETURNP(tiny * tiny);
> +	} else if (ix < BIAS - 75) {	/* |x| < 0x1p-75 (includes pseudos) */
> +		RETURN2P(1, x);		/* 1 with inexact iff x != 0 */
> +	}
> +
> +	ENTERI();
> +
> +	twopk = 1;
> +	__k_expl(x, &hi, &lo, &k);
> +	t = SUM2P(hi, lo);
> +
> +	/* Scale by 2**k. */
> +	if (k >= LDBL_MIN_EXP) {
> +		if (k == LDBL_MAX_EXP)
> +			RETURNI(t * 2 * 0x1p16383L);
> +		SET_LDBL_EXPSIGN(twopk, BIAS + k);
> +		RETURNI(t * twopk);
> +	} else {
> +		SET_LDBL_EXPSIGN(twopk, BIAS + k + 10000);
> +		RETURNI(t * twopk * twom10000);
> +	}
> +}
> +
> +/**
> + * Compute expm1l(x) for Intel 80-bit format.  This is based on:
> + *
> + *   PTP Tang, "Table-driven implementation of the Expm1 function
> + *   in IEEE floating-point arithmetic," ACM Trans. Math. Soft., 18,
> + *   211-222 (1992).
> + */
> +
> +/*
> + * Our T1 and T2 are chosen to be approximately the points where method
> + * A and method B have the same accuracy.  Tang's T1 and T2 are the
> + * points where method A's accuracy changes by a full bit.  For Tang,
> + * this drop in accuracy makes method A immediately less accurate than
> + * method B, but our larger INTERVALS makes method A 2 bits more
> + * accurate so it remains the most accurate method significantly
> + * closer to the origin despite losing the full bit in our extended
> + * range for it.
> + */
> +static const double
> +T1 = -0.1659,				/* ~-30.625/128 * log(2) */
> +T2 =  0.1659;				/* ~30.625/128 * log(2) */
> +
> +/*
> + * Domain [-0.1659, 0.1659], range ~[-2.6155e-22, 2.5507e-23]:
> + * |(exp(x)-1-x-x**2/2)/x - p(x)| < 2**-71.6
> + *
> + * XXX the coeffs aren't very carefully rounded, and I get 2.8 more bits,
> + * but unlike for ld128 we can't drop any terms.
> + */
> +static const union IEEEl2bits
> +B3 = LD80C(0xaaaaaaaaaaaaaaab, -3,  1.66666666666666666671e-1L),
> +B4 = LD80C(0xaaaaaaaaaaaaaaac, -5,  4.16666666666666666712e-2L);
> +
> +static const double
> +B5  =  8.3333333333333245e-3,		/*  0x1.111111111110cp-7 */
> +B6  =  1.3888888888888861e-3,		/*  0x1.6c16c16c16c0ap-10 */
> +B7  =  1.9841269841532042e-4,		/*  0x1.a01a01a0319f9p-13 */
> +B8  =  2.4801587302069236e-5,		/*  0x1.a01a01a03cbbcp-16 */
> +B9  =  2.7557316558468562e-6,		/*  0x1.71de37fd33d67p-19 */
> +B10 =  2.7557315829785151e-7,		/*  0x1.27e4f91418144p-22 */
> +B11 =  2.5063168199779829e-8,		/*  0x1.ae94fabdc6b27p-26 */
> +B12 =  2.0887164654459567e-9;		/*  0x1.1f122d6413fe1p-29 */
> +
> +long double
> +expm1l(long double x)
> +{
> +	union IEEEl2bits u, v;
> +	long double fn, hx2_hi, hx2_lo, q, r, r1, r2, t, twomk, twopk, x_hi;
> +	long double x_lo, x2, z;
> +	long double x4;
> +	int k, n, n2;
> +	uint16_t hx, ix;
> +
> +	DOPRINT_START(&x);
> +
> +	/* Filter out exceptional cases. */
> +	u.e = x;
> +	hx = u.xbits.expsign;
> +	ix = hx & 0x7fff;
> +	if (ix >= BIAS + 6) {		/* |x| >= 64 or x is NaN */
> +		if (ix == BIAS + LDBL_MAX_EXP) {
> +			if (hx & 0x8000)  /* x is -Inf, -NaN or unsupported */
> +				RETURNP(-1 / x - 1);
> +			RETURNP(x + x);	/* x is +Inf, +NaN or unsupported */
> +		}
> +		if (x > o_threshold)
> +			RETURNP(huge * huge);
> +		/*
> +		 * expm1l() never underflows, but it must avoid
> +		 * unrepresentable large negative exponents.  We used a
> +		 * much smaller threshold for large |x| above than in
> +		 * expl() so as to handle not so large negative exponents
> +		 * in the same way as large ones here.
> +		 */
> +		if (hx & 0x8000)	/* x <= -64 */
> +			RETURN2P(tiny, -1);	/* good for x < -65ln2 - eps */
> +	}
> +
> +	ENTERI();
> +
> +	if (T1 < x && x < T2) {
> +		if (ix < BIAS - 74) {	/* |x| < 0x1p-74 (includes pseudos) */
> +			/* x (rounded) with inexact if x != 0: */
> +			RETURNPI(x == 0 ? x :
> +			    (0x1p100 * x + fabsl(x)) * 0x1p-100);
> +		}
> +
> +		x2 = x * x;
> +		x4 = x2 * x2;
> +		q = x4 * (x2 * (x4 *
> +		    /*
> +		     * XXX the number of terms is no longer good for
> +		     * pairwise grouping of all except B3, and the
> +		     * grouping is no longer from highest down.
> +		     */
> +		    (x2 *            B12  + (x * B11 + B10)) +
> +		    (x2 * (x * B9 +  B8) +  (x * B7 +  B6))) +
> +			  (x * B5 +  B4.e)) + x2 * x * B3.e;
> +
> +		x_hi = (float)x;
> +		x_lo = x - x_hi;
> +		hx2_hi = x_hi * x_hi / 2;
> +		hx2_lo = x_lo * (x + x_hi) / 2;
> +		if (ix >= BIAS - 7)
> +			RETURN2PI(hx2_hi + x_hi, hx2_lo + x_lo + q);
> +		else
> +			RETURN2PI(x, hx2_lo + q + hx2_hi);
> +	}
> +
> +	/* Reduce x to (k*ln2 + endpoint[n2] + r1 + r2). */
> +	fn = rnintl(x * INV_L);
> +	n = irint(fn);
> +	n2 = (unsigned)n % INTERVALS;
> +	k = n >> LOG2_INTERVALS;
> +	r1 = x - fn * L1;
> +	r2 = fn * -L2;
> +	r = r1 + r2;
> +
> +	/* Prepare scale factor. */
> +	v.e = 1;
> +	v.xbits.expsign = BIAS + k;
> +	twopk = v.e;
> +
> +	/*
> +	 * Evaluate lower terms of
> +	 * expl(endpoint[n2] + r1 + r2) = tbl[n2] * expl(r1 + r2).
> +	 */
> +	z = r * r;
> +	q = r2 + z * (A2 + r * A3) + z * z * (A4 + r * A5) + z * z * z * A6;
> +
> +	t = (long double)tbl[n2].lo + tbl[n2].hi;
> +
> +	if (k == 0) {
> +		t = SUM2P(tbl[n2].hi - 1, tbl[n2].lo * (r1 + 1) + t * q +
> +		    tbl[n2].hi * r1);
> +		RETURNI(t);
> +	}
> +	if (k == -1) {
> +		t = SUM2P(tbl[n2].hi - 2, tbl[n2].lo * (r1 + 1) + t * q +
> +		    tbl[n2].hi * r1);
> +		RETURNI(t / 2);
> +	}
> +	if (k < -7) {
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
> +		RETURNI(t * twopk - 1);
> +	}
> +	if (k > 2 * LDBL_MANT_DIG - 1) {
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo + t * (q + r1));
> +		if (k == LDBL_MAX_EXP)
> +			RETURNI(t * 2 * 0x1p16383L - 1);
> +		RETURNI(t * twopk - 1);
> +	}
> +
> +	v.xbits.expsign = BIAS - k;
> +	twomk = v.e;
> +
> +	if (k > LDBL_MANT_DIG - 1)
> +		t = SUM2P(tbl[n2].hi, tbl[n2].lo - twomk + t * (q + r1));
> +	else
> +		t = SUM2P(tbl[n2].hi - twomk, tbl[n2].lo + t * (q + r1));
> +	RETURNI(t * twopk);
> +}
> diff --git a/newlib/libm/ld80/s_logl.c b/newlib/libm/ld80/s_logl.c
> new file mode 100644
> index 000000000..c74519caf
> --- /dev/null
> +++ b/newlib/libm/ld80/s_logl.c
> @@ -0,0 +1,722 @@
> +/*-
> + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
> + *
> + * Copyright (c) 2007-2013 Bruce D. Evans
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +/**
> + * Implementation of the natural logarithm of x for Intel 80-bit format.
> + *
> + * First decompose x into its base 2 representation:
> + *
> + *    log(x) = log(X * 2**k), where X is in [1, 2)
> + *           = log(X) + k * log(2).
> + *
> + * Let X = X_i + e, where X_i is the center of one of the intervals
> + * [-1.0/256, 1.0/256), [1.0/256, 3.0/256), .... [2.0-1.0/256, 2.0+1.0/256)
> + * and X is in this interval.  Then
> + *
> + *    log(X) = log(X_i + e)
> + *           = log(X_i * (1 + e / X_i))
> + *           = log(X_i) + log(1 + e / X_i).
> + *
> + * The values log(X_i) are tabulated below.  Let d = e / X_i and use
> + *
> + *    log(1 + d) = p(d)
> + *
> + * where p(d) = d - 0.5*d*d + ... is a special minimax polynomial of
> + * suitably high degree.
> + *
> + * To get sufficiently small roundoff errors, k * log(2), log(X_i), and
> + * sometimes (if |k| is not large) the first term in p(d) must be evaluated
> + * and added up in extra precision.  Extra precision is not needed for the
> + * rest of p(d).  In the worst case when k = 0 and log(X_i) is 0, the final
> + * error is controlled mainly by the error in the second term in p(d).  The
> + * error in this term itself is at most 0.5 ulps from the d*d operation in
> + * it.  The error in this term relative to the first term is thus at most
> + * 0.5 * |-0.5| * |d| < 1.0/1024 ulps.  We aim for an accumulated error of
> + * at most twice this at the point of the final rounding step.  Thus the
> + * final error should be at most 0.5 + 1.0/512 = 0.5020 ulps.  Exhaustive
> + * testing of a float variant of this function showed a maximum final error
> + * of 0.5008 ulps.  Non-exhaustive testing of a double variant of this
> + * function showed a maximum final error of 0.5078 ulps (near 1+1.0/256).
> + *
> + * We made the maximum of |d| (and thus the total relative error and the
> + * degree of p(d)) small by using a large number of intervals.  Using
> + * centers of intervals instead of endpoints reduces this maximum by a
> + * factor of 2 for a given number of intervals.  p(d) is special only
> + * in beginning with the Taylor coefficients 0 + 1*d, which tends to happen
> + * naturally.  The most accurate minimax polynomial of a given degree might
> + * be different, but then we wouldn't want it since we would have to do
> + * extra work to avoid roundoff error (especially for P0*d instead of d).
> + */
> +
> +#ifdef DEBUG
> +#include <assert.h>
> +#include <fenv.h>
> +#endif
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#define	i386_SSE_GOOD
> +#ifndef NO_STRUCT_RETURN
> +#define	STRUCT_RETURN
> +#endif
> +#include "math_private.h"
> +
> +#if !defined(NO_UTAB) && !defined(NO_UTABL)
> +#define	USE_UTAB
> +#endif
> +
> +/*
> + * Domain [-0.005280, 0.004838], range ~[-5.1736e-22, 5.1738e-22]:
> + * |log(1 + d)/d - p(d)| < 2**-70.7
> + */
> +static const double
> +P2 = -0.5,
> +P3 =  3.3333333333333359e-1,		/*  0x1555555555555a.0p-54 */
> +P4 = -2.5000000000004424e-1,		/* -0x1000000000031d.0p-54 */
> +P5 =  1.9999999992970016e-1,		/*  0x1999999972f3c7.0p-55 */
> +P6 = -1.6666666072191585e-1,		/* -0x15555548912c09.0p-55 */
> +P7 =  1.4286227413310518e-1,		/*  0x12494f9d9def91.0p-55 */
> +P8 = -1.2518388626763144e-1;		/* -0x1006068cc0b97c.0p-55 */
> +
> +static volatile const double zero = 0;
> +
> +#define	INTERVALS	128
> +#define	LOG2_INTERVALS	7
> +#define	TSIZE		(INTERVALS + 1)
> +#define	G(i)		(T[(i)].G)
> +#define	F_hi(i)		(T[(i)].F_hi)
> +#define	F_lo(i)		(T[(i)].F_lo)
> +#define	ln2_hi		F_hi(TSIZE - 1)
> +#define	ln2_lo		F_lo(TSIZE - 1)
> +#define	E(i)		(U[(i)].E)
> +#define	H(i)		(U[(i)].H)
> +
> +static const struct {
> +	float	G;			/* 1/(1 + i/128) rounded to 8/9 bits */
> +	float	F_hi;			/* log(1 / G_i) rounded (see below) */
> +	double	F_lo;			/* next 53 bits for log(1 / G_i) */
> +} T[TSIZE] = {
> +	/*
> +	 * ln2_hi and each F_hi(i) are rounded to a number of bits that
> +	 * makes F_hi(i) + dk*ln2_hi exact for all i and all dk.
> +	 *
> +	 * The last entry (for X just below 2) is used to define ln2_hi
> +	 * and ln2_lo, to ensure that F_hi(i) and F_lo(i) cancel exactly
> +	 * with dk*ln2_hi and dk*ln2_lo, respectively, when dk = -1.
> +	 * This is needed for accuracy when x is just below 1.  (To avoid
> +	 * special cases, such x are "reduced" strangely to X just below
> +	 * 2 and dk = -1, and then the exact cancellation is needed
> +	 * because any the error from any non-exactness would be too
> +	 * large).
> +	 *
> +	 * We want to share this table between double precision and ld80,
> +	 * so the relevant range of dk is the larger one of ld80
> +	 * ([-16445, 16383]) and the relevant exactness requirement is
> +	 * the stricter one of double precision.  The maximum number of
> +	 * bits in F_hi(i) that works is very dependent on i but has
> +	 * a minimum of 33.  We only need about 12 bits in F_hi(i) for
> +	 * it to provide enough extra precision in double precision (11
> +	 * more than that are required for ld80).
> +	 *
> +	 * We round F_hi(i) to 24 bits so that it can have type float,
> +	 * mainly to minimize the size of the table.  Using all 24 bits
> +	 * in a float for it automatically satisfies the above constraints.
> +	 */
> +	 { 0x800000.0p-23,  0,               0 },
> +	 { 0xfe0000.0p-24,  0x8080ac.0p-30, -0x14ee431dae6675.0p-84 },
> +	 { 0xfc0000.0p-24,  0x8102b3.0p-29, -0x1db29ee2d83718.0p-84 },
> +	 { 0xfa0000.0p-24,  0xc24929.0p-29,  0x1191957d173698.0p-83 },
> +	 { 0xf80000.0p-24,  0x820aec.0p-28,  0x13ce8888e02e79.0p-82 },
> +	 { 0xf60000.0p-24,  0xa33577.0p-28, -0x17a4382ce6eb7c.0p-82 },
> +	 { 0xf48000.0p-24,  0xbc42cb.0p-28, -0x172a21161a1076.0p-83 },
> +	 { 0xf30000.0p-24,  0xd57797.0p-28, -0x1e09de07cb9589.0p-82 },
> +	 { 0xf10000.0p-24,  0xf7518e.0p-28,  0x1ae1eec1b036c5.0p-91 },
> +	 { 0xef0000.0p-24,  0x8cb9df.0p-27, -0x1d7355325d560e.0p-81 },
> +	 { 0xed8000.0p-24,  0x999ec0.0p-27, -0x1f9f02d256d503.0p-82 },
> +	 { 0xec0000.0p-24,  0xa6988b.0p-27, -0x16fc0a9d12c17a.0p-83 },
> +	 { 0xea0000.0p-24,  0xb80698.0p-27,  0x15d581c1e8da9a.0p-81 },
> +	 { 0xe80000.0p-24,  0xc99af3.0p-27, -0x1535b3ba8f150b.0p-83 },
> +	 { 0xe70000.0p-24,  0xd273b2.0p-27,  0x163786f5251af0.0p-85 },
> +	 { 0xe50000.0p-24,  0xe442c0.0p-27,  0x1bc4b2368e32d5.0p-84 },
> +	 { 0xe38000.0p-24,  0xf1b83f.0p-27,  0x1c6090f684e676.0p-81 },
> +	 { 0xe20000.0p-24,  0xff448a.0p-27, -0x1890aa69ac9f42.0p-82 },
> +	 { 0xe08000.0p-24,  0x8673f6.0p-26,  0x1b9985194b6b00.0p-80 },
> +	 { 0xdf0000.0p-24,  0x8d515c.0p-26, -0x1dc08d61c6ef1e.0p-83 },
> +	 { 0xdd8000.0p-24,  0x943a9e.0p-26, -0x1f72a2dac729b4.0p-82 },
> +	 { 0xdc0000.0p-24,  0x9b2fe6.0p-26, -0x1fd4dfd3a0afb9.0p-80 },
> +	 { 0xda8000.0p-24,  0xa2315d.0p-26, -0x11b26121629c47.0p-82 },
> +	 { 0xd90000.0p-24,  0xa93f2f.0p-26,  0x1286d633e8e569.0p-81 },
> +	 { 0xd78000.0p-24,  0xb05988.0p-26,  0x16128eba936770.0p-84 },
> +	 { 0xd60000.0p-24,  0xb78094.0p-26,  0x16ead577390d32.0p-80 },
> +	 { 0xd50000.0p-24,  0xbc4c6c.0p-26,  0x151131ccf7c7b7.0p-81 },
> +	 { 0xd38000.0p-24,  0xc3890a.0p-26, -0x115e2cd714bd06.0p-80 },
> +	 { 0xd20000.0p-24,  0xcad2d7.0p-26, -0x1847f406ebd3b0.0p-82 },
> +	 { 0xd10000.0p-24,  0xcfb620.0p-26,  0x1c2259904d6866.0p-81 },
> +	 { 0xcf8000.0p-24,  0xd71653.0p-26,  0x1ece57a8d5ae55.0p-80 },
> +	 { 0xce0000.0p-24,  0xde843a.0p-26, -0x1f109d4bc45954.0p-81 },
> +	 { 0xcd0000.0p-24,  0xe37fde.0p-26,  0x1bc03dc271a74d.0p-81 },
> +	 { 0xcb8000.0p-24,  0xeb050c.0p-26, -0x1bf2badc0df842.0p-85 },
> +	 { 0xca0000.0p-24,  0xf29878.0p-26, -0x18efededd89fbe.0p-87 },
> +	 { 0xc90000.0p-24,  0xf7ad6f.0p-26,  0x1373ff977baa69.0p-81 },
> +	 { 0xc80000.0p-24,  0xfcc8e3.0p-26,  0x196766f2fb3283.0p-80 },
> +	 { 0xc68000.0p-24,  0x823f30.0p-25,  0x19bd076f7c434e.0p-79 },
> +	 { 0xc58000.0p-24,  0x84d52c.0p-25, -0x1a327257af0f46.0p-79 },
> +	 { 0xc40000.0p-24,  0x88bc74.0p-25,  0x113f23def19c5a.0p-81 },
> +	 { 0xc30000.0p-24,  0x8b5ae6.0p-25,  0x1759f6e6b37de9.0p-79 },
> +	 { 0xc20000.0p-24,  0x8dfccb.0p-25,  0x1ad35ca6ed5148.0p-81 },
> +	 { 0xc10000.0p-24,  0x90a22b.0p-25,  0x1a1d71a87deba4.0p-79 },
> +	 { 0xbf8000.0p-24,  0x94a0d8.0p-25, -0x139e5210c2b731.0p-80 },
> +	 { 0xbe8000.0p-24,  0x974f16.0p-25, -0x18f6ebcff3ed73.0p-81 },
> +	 { 0xbd8000.0p-24,  0x9a00f1.0p-25, -0x1aa268be39aab7.0p-79 },
> +	 { 0xbc8000.0p-24,  0x9cb672.0p-25, -0x14c8815839c566.0p-79 },
> +	 { 0xbb0000.0p-24,  0xa0cda1.0p-25,  0x1eaf46390dbb24.0p-81 },
> +	 { 0xba0000.0p-24,  0xa38c6e.0p-25,  0x138e20d831f698.0p-81 },
> +	 { 0xb90000.0p-24,  0xa64f05.0p-25, -0x1e8d3c41123616.0p-82 },
> +	 { 0xb80000.0p-24,  0xa91570.0p-25,  0x1ce28f5f3840b2.0p-80 },
> +	 { 0xb70000.0p-24,  0xabdfbb.0p-25, -0x186e5c0a424234.0p-79 },
> +	 { 0xb60000.0p-24,  0xaeadef.0p-25, -0x14d41a0b2a08a4.0p-83 },
> +	 { 0xb50000.0p-24,  0xb18018.0p-25,  0x16755892770634.0p-79 },
> +	 { 0xb40000.0p-24,  0xb45642.0p-25, -0x16395ebe59b152.0p-82 },
> +	 { 0xb30000.0p-24,  0xb73077.0p-25,  0x1abc65c8595f09.0p-80 },
> +	 { 0xb20000.0p-24,  0xba0ec4.0p-25, -0x1273089d3dad89.0p-79 },
> +	 { 0xb10000.0p-24,  0xbcf133.0p-25,  0x10f9f67b1f4bbf.0p-79 },
> +	 { 0xb00000.0p-24,  0xbfd7d2.0p-25, -0x109fab90486409.0p-80 },
> +	 { 0xaf0000.0p-24,  0xc2c2ac.0p-25, -0x1124680aa43333.0p-79 },
> +	 { 0xae8000.0p-24,  0xc439b3.0p-25, -0x1f360cc4710fc0.0p-80 },
> +	 { 0xad8000.0p-24,  0xc72afd.0p-25, -0x132d91f21d89c9.0p-80 },
> +	 { 0xac8000.0p-24,  0xca20a2.0p-25, -0x16bf9b4d1f8da8.0p-79 },
> +	 { 0xab8000.0p-24,  0xcd1aae.0p-25,  0x19deb5ce6a6a87.0p-81 },
> +	 { 0xaa8000.0p-24,  0xd0192f.0p-25,  0x1a29fb48f7d3cb.0p-79 },
> +	 { 0xaa0000.0p-24,  0xd19a20.0p-25,  0x1127d3c6457f9d.0p-81 },
> +	 { 0xa90000.0p-24,  0xd49f6a.0p-25, -0x1ba930e486a0ac.0p-81 },
> +	 { 0xa80000.0p-24,  0xd7a94b.0p-25, -0x1b6e645f31549e.0p-79 },
> +	 { 0xa70000.0p-24,  0xdab7d0.0p-25,  0x1118a425494b61.0p-80 },
> +	 { 0xa68000.0p-24,  0xdc40d5.0p-25,  0x1966f24d29d3a3.0p-80 },
> +	 { 0xa58000.0p-24,  0xdf566d.0p-25, -0x1d8e52eb2248f1.0p-82 },
> +	 { 0xa48000.0p-24,  0xe270ce.0p-25, -0x1ee370f96e6b68.0p-80 },
> +	 { 0xa40000.0p-24,  0xe3ffce.0p-25,  0x1d155324911f57.0p-80 },
> +	 { 0xa30000.0p-24,  0xe72179.0p-25, -0x1fe6e2f2f867d9.0p-80 },
> +	 { 0xa20000.0p-24,  0xea4812.0p-25,  0x1b7be9add7f4d4.0p-80 },
> +	 { 0xa18000.0p-24,  0xebdd3d.0p-25,  0x1b3cfb3f7511dd.0p-79 },
> +	 { 0xa08000.0p-24,  0xef0b5b.0p-25, -0x1220de1f730190.0p-79 },
> +	 { 0xa00000.0p-24,  0xf0a451.0p-25, -0x176364c9ac81cd.0p-80 },
> +	 { 0x9f0000.0p-24,  0xf3da16.0p-25,  0x1eed6b9aafac8d.0p-81 },
> +	 { 0x9e8000.0p-24,  0xf576e9.0p-25,  0x1d593218675af2.0p-79 },
> +	 { 0x9d8000.0p-24,  0xf8b47c.0p-25, -0x13e8eb7da053e0.0p-84 },
> +	 { 0x9d0000.0p-24,  0xfa553f.0p-25,  0x1c063259bcade0.0p-79 },
> +	 { 0x9c0000.0p-24,  0xfd9ac5.0p-25,  0x1ef491085fa3c1.0p-79 },
> +	 { 0x9b8000.0p-24,  0xff3f8c.0p-25,  0x1d607a7c2b8c53.0p-79 },
> +	 { 0x9a8000.0p-24,  0x814697.0p-24, -0x12ad3817004f3f.0p-78 },
> +	 { 0x9a0000.0p-24,  0x821b06.0p-24, -0x189fc53117f9e5.0p-81 },
> +	 { 0x990000.0p-24,  0x83c5f8.0p-24,  0x14cf15a048907b.0p-79 },
> +	 { 0x988000.0p-24,  0x849c7d.0p-24,  0x1cbb1d35fb8287.0p-78 },
> +	 { 0x978000.0p-24,  0x864ba6.0p-24,  0x1128639b814f9c.0p-78 },
> +	 { 0x970000.0p-24,  0x87244c.0p-24,  0x184733853300f0.0p-79 },
> +	 { 0x968000.0p-24,  0x87fdaa.0p-24,  0x109d23aef77dd6.0p-80 },
> +	 { 0x958000.0p-24,  0x89b293.0p-24, -0x1a81ef367a59de.0p-78 },
> +	 { 0x950000.0p-24,  0x8a8e20.0p-24, -0x121ad3dbb2f452.0p-78 },
> +	 { 0x948000.0p-24,  0x8b6a6a.0p-24, -0x1cfb981628af72.0p-79 },
> +	 { 0x938000.0p-24,  0x8d253a.0p-24, -0x1d21730ea76cfe.0p-79 },
> +	 { 0x930000.0p-24,  0x8e03c2.0p-24,  0x135cc00e566f77.0p-78 },
> +	 { 0x928000.0p-24,  0x8ee30d.0p-24, -0x10fcb5df257a26.0p-80 },
> +	 { 0x918000.0p-24,  0x90a3ee.0p-24, -0x16e171b15433d7.0p-79 },
> +	 { 0x910000.0p-24,  0x918587.0p-24, -0x1d050da07f3237.0p-79 },
> +	 { 0x908000.0p-24,  0x9267e7.0p-24,  0x1be03669a5268d.0p-79 },
> +	 { 0x8f8000.0p-24,  0x942f04.0p-24,  0x10b28e0e26c337.0p-79 },
> +	 { 0x8f0000.0p-24,  0x9513c3.0p-24,  0x1a1d820da57cf3.0p-78 },
> +	 { 0x8e8000.0p-24,  0x95f950.0p-24, -0x19ef8f13ae3cf1.0p-79 },
> +	 { 0x8e0000.0p-24,  0x96dfab.0p-24, -0x109e417a6e507c.0p-78 },
> +	 { 0x8d0000.0p-24,  0x98aed2.0p-24,  0x10d01a2c5b0e98.0p-79 },
> +	 { 0x8c8000.0p-24,  0x9997a2.0p-24, -0x1d6a50d4b61ea7.0p-78 },
> +	 { 0x8c0000.0p-24,  0x9a8145.0p-24,  0x1b3b190b83f952.0p-78 },
> +	 { 0x8b8000.0p-24,  0x9b6bbf.0p-24,  0x13a69fad7e7abe.0p-78 },
> +	 { 0x8b0000.0p-24,  0x9c5711.0p-24, -0x11cd12316f576b.0p-78 },
> +	 { 0x8a8000.0p-24,  0x9d433b.0p-24,  0x1c95c444b807a2.0p-79 },
> +	 { 0x898000.0p-24,  0x9f1e22.0p-24, -0x1b9c224ea698c3.0p-79 },
> +	 { 0x890000.0p-24,  0xa00ce1.0p-24,  0x125ca93186cf0f.0p-81 },
> +	 { 0x888000.0p-24,  0xa0fc80.0p-24, -0x1ee38a7bc228b3.0p-79 },
> +	 { 0x880000.0p-24,  0xa1ed00.0p-24, -0x1a0db876613d20.0p-78 },
> +	 { 0x878000.0p-24,  0xa2de62.0p-24,  0x193224e8516c01.0p-79 },
> +	 { 0x870000.0p-24,  0xa3d0a9.0p-24,  0x1fa28b4d2541ad.0p-79 },
> +	 { 0x868000.0p-24,  0xa4c3d6.0p-24,  0x1c1b5760fb4572.0p-78 },
> +	 { 0x858000.0p-24,  0xa6acea.0p-24,  0x1fed5d0f65949c.0p-80 },
> +	 { 0x850000.0p-24,  0xa7a2d4.0p-24,  0x1ad270c9d74936.0p-80 },
> +	 { 0x848000.0p-24,  0xa899ab.0p-24,  0x199ff15ce53266.0p-79 },
> +	 { 0x840000.0p-24,  0xa99171.0p-24,  0x1a19e15ccc45d2.0p-79 },
> +	 { 0x838000.0p-24,  0xaa8a28.0p-24, -0x121a14ec532b36.0p-80 },
> +	 { 0x830000.0p-24,  0xab83d1.0p-24,  0x1aee319980bff3.0p-79 },
> +	 { 0x828000.0p-24,  0xac7e6f.0p-24, -0x18ffd9e3900346.0p-80 },
> +	 { 0x820000.0p-24,  0xad7a03.0p-24, -0x1e4db102ce29f8.0p-80 },
> +	 { 0x818000.0p-24,  0xae768f.0p-24,  0x17c35c55a04a83.0p-81 },
> +	 { 0x810000.0p-24,  0xaf7415.0p-24,  0x1448324047019b.0p-78 },
> +	 { 0x808000.0p-24,  0xb07298.0p-24, -0x1750ee3915a198.0p-78 },
> +	 { 0x800000.0p-24,  0xb17218.0p-24, -0x105c610ca86c39.0p-81 },
> +};
> +
> +#ifdef USE_UTAB
> +static const struct {
> +	float	H;			/* 1 + i/INTERVALS (exact) */
> +	float	E;			/* H(i) * G(i) - 1 (exact) */
> +} U[TSIZE] = {
> +	 { 0x800000.0p-23,  0 },
> +	 { 0x810000.0p-23, -0x800000.0p-37 },
> +	 { 0x820000.0p-23, -0x800000.0p-35 },
> +	 { 0x830000.0p-23, -0x900000.0p-34 },
> +	 { 0x840000.0p-23, -0x800000.0p-33 },
> +	 { 0x850000.0p-23, -0xc80000.0p-33 },
> +	 { 0x860000.0p-23, -0xa00000.0p-36 },
> +	 { 0x870000.0p-23,  0x940000.0p-33 },
> +	 { 0x880000.0p-23,  0x800000.0p-35 },
> +	 { 0x890000.0p-23, -0xc80000.0p-34 },
> +	 { 0x8a0000.0p-23,  0xe00000.0p-36 },
> +	 { 0x8b0000.0p-23,  0x900000.0p-33 },
> +	 { 0x8c0000.0p-23, -0x800000.0p-35 },
> +	 { 0x8d0000.0p-23, -0xe00000.0p-33 },
> +	 { 0x8e0000.0p-23,  0x880000.0p-33 },
> +	 { 0x8f0000.0p-23, -0xa80000.0p-34 },
> +	 { 0x900000.0p-23, -0x800000.0p-35 },
> +	 { 0x910000.0p-23,  0x800000.0p-37 },
> +	 { 0x920000.0p-23,  0x900000.0p-35 },
> +	 { 0x930000.0p-23,  0xd00000.0p-35 },
> +	 { 0x940000.0p-23,  0xe00000.0p-35 },
> +	 { 0x950000.0p-23,  0xc00000.0p-35 },
> +	 { 0x960000.0p-23,  0xe00000.0p-36 },
> +	 { 0x970000.0p-23, -0x800000.0p-38 },
> +	 { 0x980000.0p-23, -0xc00000.0p-35 },
> +	 { 0x990000.0p-23, -0xd00000.0p-34 },
> +	 { 0x9a0000.0p-23,  0x880000.0p-33 },
> +	 { 0x9b0000.0p-23,  0xe80000.0p-35 },
> +	 { 0x9c0000.0p-23, -0x800000.0p-35 },
> +	 { 0x9d0000.0p-23,  0xb40000.0p-33 },
> +	 { 0x9e0000.0p-23,  0x880000.0p-34 },
> +	 { 0x9f0000.0p-23, -0xe00000.0p-35 },
> +	 { 0xa00000.0p-23,  0x800000.0p-33 },
> +	 { 0xa10000.0p-23, -0x900000.0p-36 },
> +	 { 0xa20000.0p-23, -0xb00000.0p-33 },
> +	 { 0xa30000.0p-23, -0xa00000.0p-36 },
> +	 { 0xa40000.0p-23,  0x800000.0p-33 },
> +	 { 0xa50000.0p-23, -0xf80000.0p-35 },
> +	 { 0xa60000.0p-23,  0x880000.0p-34 },
> +	 { 0xa70000.0p-23, -0x900000.0p-33 },
> +	 { 0xa80000.0p-23, -0x800000.0p-35 },
> +	 { 0xa90000.0p-23,  0x900000.0p-34 },
> +	 { 0xaa0000.0p-23,  0xa80000.0p-33 },
> +	 { 0xab0000.0p-23, -0xac0000.0p-34 },
> +	 { 0xac0000.0p-23, -0x800000.0p-37 },
> +	 { 0xad0000.0p-23,  0xf80000.0p-35 },
> +	 { 0xae0000.0p-23,  0xf80000.0p-34 },
> +	 { 0xaf0000.0p-23, -0xac0000.0p-33 },
> +	 { 0xb00000.0p-23, -0x800000.0p-33 },
> +	 { 0xb10000.0p-23, -0xb80000.0p-34 },
> +	 { 0xb20000.0p-23, -0x800000.0p-34 },
> +	 { 0xb30000.0p-23, -0xb00000.0p-35 },
> +	 { 0xb40000.0p-23, -0x800000.0p-35 },
> +	 { 0xb50000.0p-23, -0xe00000.0p-36 },
> +	 { 0xb60000.0p-23, -0x800000.0p-35 },
> +	 { 0xb70000.0p-23, -0xb00000.0p-35 },
> +	 { 0xb80000.0p-23, -0x800000.0p-34 },
> +	 { 0xb90000.0p-23, -0xb80000.0p-34 },
> +	 { 0xba0000.0p-23, -0x800000.0p-33 },
> +	 { 0xbb0000.0p-23, -0xac0000.0p-33 },
> +	 { 0xbc0000.0p-23,  0x980000.0p-33 },
> +	 { 0xbd0000.0p-23,  0xbc0000.0p-34 },
> +	 { 0xbe0000.0p-23,  0xe00000.0p-36 },
> +	 { 0xbf0000.0p-23, -0xb80000.0p-35 },
> +	 { 0xc00000.0p-23, -0x800000.0p-33 },
> +	 { 0xc10000.0p-23,  0xa80000.0p-33 },
> +	 { 0xc20000.0p-23,  0x900000.0p-34 },
> +	 { 0xc30000.0p-23, -0x800000.0p-35 },
> +	 { 0xc40000.0p-23, -0x900000.0p-33 },
> +	 { 0xc50000.0p-23,  0x820000.0p-33 },
> +	 { 0xc60000.0p-23,  0x800000.0p-38 },
> +	 { 0xc70000.0p-23, -0x820000.0p-33 },
> +	 { 0xc80000.0p-23,  0x800000.0p-33 },
> +	 { 0xc90000.0p-23, -0xa00000.0p-36 },
> +	 { 0xca0000.0p-23, -0xb00000.0p-33 },
> +	 { 0xcb0000.0p-23,  0x840000.0p-34 },
> +	 { 0xcc0000.0p-23, -0xd00000.0p-34 },
> +	 { 0xcd0000.0p-23,  0x800000.0p-33 },
> +	 { 0xce0000.0p-23, -0xe00000.0p-35 },
> +	 { 0xcf0000.0p-23,  0xa60000.0p-33 },
> +	 { 0xd00000.0p-23, -0x800000.0p-35 },
> +	 { 0xd10000.0p-23,  0xb40000.0p-33 },
> +	 { 0xd20000.0p-23, -0x800000.0p-35 },
> +	 { 0xd30000.0p-23,  0xaa0000.0p-33 },
> +	 { 0xd40000.0p-23, -0xe00000.0p-35 },
> +	 { 0xd50000.0p-23,  0x880000.0p-33 },
> +	 { 0xd60000.0p-23, -0xd00000.0p-34 },
> +	 { 0xd70000.0p-23,  0x9c0000.0p-34 },
> +	 { 0xd80000.0p-23, -0xb00000.0p-33 },
> +	 { 0xd90000.0p-23, -0x800000.0p-38 },
> +	 { 0xda0000.0p-23,  0xa40000.0p-33 },
> +	 { 0xdb0000.0p-23, -0xdc0000.0p-34 },
> +	 { 0xdc0000.0p-23,  0xc00000.0p-35 },
> +	 { 0xdd0000.0p-23,  0xca0000.0p-33 },
> +	 { 0xde0000.0p-23, -0xb80000.0p-34 },
> +	 { 0xdf0000.0p-23,  0xd00000.0p-35 },
> +	 { 0xe00000.0p-23,  0xc00000.0p-33 },
> +	 { 0xe10000.0p-23, -0xf40000.0p-34 },
> +	 { 0xe20000.0p-23,  0x800000.0p-37 },
> +	 { 0xe30000.0p-23,  0x860000.0p-33 },
> +	 { 0xe40000.0p-23, -0xc80000.0p-33 },
> +	 { 0xe50000.0p-23, -0xa80000.0p-34 },
> +	 { 0xe60000.0p-23,  0xe00000.0p-36 },
> +	 { 0xe70000.0p-23,  0x880000.0p-33 },
> +	 { 0xe80000.0p-23, -0xe00000.0p-33 },
> +	 { 0xe90000.0p-23, -0xfc0000.0p-34 },
> +	 { 0xea0000.0p-23, -0x800000.0p-35 },
> +	 { 0xeb0000.0p-23,  0xe80000.0p-35 },
> +	 { 0xec0000.0p-23,  0x900000.0p-33 },
> +	 { 0xed0000.0p-23,  0xe20000.0p-33 },
> +	 { 0xee0000.0p-23, -0xac0000.0p-33 },
> +	 { 0xef0000.0p-23, -0xc80000.0p-34 },
> +	 { 0xf00000.0p-23, -0x800000.0p-35 },
> +	 { 0xf10000.0p-23,  0x800000.0p-35 },
> +	 { 0xf20000.0p-23,  0xb80000.0p-34 },
> +	 { 0xf30000.0p-23,  0x940000.0p-33 },
> +	 { 0xf40000.0p-23,  0xc80000.0p-33 },
> +	 { 0xf50000.0p-23, -0xf20000.0p-33 },
> +	 { 0xf60000.0p-23, -0xc80000.0p-33 },
> +	 { 0xf70000.0p-23, -0xa20000.0p-33 },
> +	 { 0xf80000.0p-23, -0x800000.0p-33 },
> +	 { 0xf90000.0p-23, -0xc40000.0p-34 },
> +	 { 0xfa0000.0p-23, -0x900000.0p-34 },
> +	 { 0xfb0000.0p-23, -0xc80000.0p-35 },
> +	 { 0xfc0000.0p-23, -0x800000.0p-35 },
> +	 { 0xfd0000.0p-23, -0x900000.0p-36 },
> +	 { 0xfe0000.0p-23, -0x800000.0p-37 },
> +	 { 0xff0000.0p-23, -0x800000.0p-39 },
> +	 { 0x800000.0p-22,  0 },
> +};
> +#endif /* USE_UTAB */
> +
> +#ifdef STRUCT_RETURN
> +#define	RETURN1(rp, v) do {	\
> +	(rp)->hi = (v);		\
> +	(rp)->lo_set = 0;	\
> +	return;			\
> +} while (0)
> +
> +#define	RETURN2(rp, h, l) do {	\
> +	(rp)->hi = (h);		\
> +	(rp)->lo = (l);		\
> +	(rp)->lo_set = 1;	\
> +	return;			\
> +} while (0)
> +
> +struct ld {
> +	long double hi;
> +	long double lo;
> +	int	lo_set;
> +};
> +#else
> +#define	RETURN1(rp, v)	RETURNF(v)
> +#define	RETURN2(rp, h, l)	RETURNI((h) + (l))
> +#endif
> +
> +#ifdef STRUCT_RETURN
> +static inline __always_inline void
> +k_logl(long double x, struct ld *rp)
> +#else
> +long double
> +logl(long double x)
> +#endif
> +{
> +	long double d, dk, val_hi, val_lo, z;
> +	uint64_t ix, lx;
> +	int i, k;
> +	uint16_t hx;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +	k = -16383;
> +#if 0 /* Hard to do efficiently.  Don't do it until we support all modes. */
> +	if (x == 1)
> +		RETURN1(rp, 0);		/* log(1) = +0 in all rounding modes */
> +#endif
> +	if (hx == 0 || hx >= 0x8000) {	/* zero, negative or subnormal? */
> +		if (((hx & 0x7fff) | lx) == 0)
> +			RETURN1(rp, -1 / zero);	/* log(+-0) = -Inf */
> +		if (hx != 0)
> +			/* log(neg or [pseudo-]NaN) = qNaN: */
> +			RETURN1(rp, (x - x) / zero);
> +		x *= 0x1.0p65;		/* subnormal; scale up x */
> +					/* including pseudo-subnormals */
> +		EXTRACT_LDBL80_WORDS(hx, lx, x);
> +		k = -16383 - 65;
> +	} else if (hx >= 0x7fff || (lx & 0x8000000000000000ULL) == 0)
> +		RETURN1(rp, x + x);	/* log(Inf or NaN) = Inf or qNaN */
> +					/* log(pseudo-Inf) = qNaN */
> +					/* log(pseudo-NaN) = qNaN */
> +					/* log(unnormal) = qNaN */
> +#ifndef STRUCT_RETURN
> +	ENTERI();
> +#endif
> +	k += hx;
> +	ix = lx & 0x7fffffffffffffffULL;
> +	dk = k;
> +
> +	/* Scale x to be in [1, 2). */
> +	SET_LDBL_EXPSIGN(x, 0x3fff);
> +
> +	/* 0 <= i <= INTERVALS: */
> +#define	L2I	(64 - LOG2_INTERVALS)
> +	i = (ix + (1LL << (L2I - 2))) >> (L2I - 1);
> +
> +	/*
> +	 * -0.005280 < d < 0.004838.  In particular, the infinite-
> +	 * precision |d| is <= 2**-7.  Rounding of G(i) to 8 bits
> +	 * ensures that d is representable without extra precision for
> +	 * this bound on |d| (since when this calculation is expressed
> +	 * as x*G(i)-1, the multiplication needs as many extra bits as
> +	 * G(i) has and the subtraction cancels 8 bits).  But for
> +	 * most i (107 cases out of 129), the infinite-precision |d|
> +	 * is <= 2**-8.  G(i) is rounded to 9 bits for such i to give
> +	 * better accuracy (this works by improving the bound on |d|,
> +	 * which in turn allows rounding to 9 bits in more cases).
> +	 * This is only important when the original x is near 1 -- it
> +	 * lets us avoid using a special method to give the desired
> +	 * accuracy for such x.
> +	 */
> +	if (0)
> +		d = x * G(i) - 1;
> +	else {
> +#ifdef USE_UTAB
> +		d = (x - H(i)) * G(i) + E(i);
> +#else
> +		long double x_hi, x_lo;
> +		float fx_hi;
> +
> +		/*
> +		 * Split x into x_hi + x_lo to calculate x*G(i)-1 exactly.
> +		 * G(i) has at most 9 bits, so the splitting point is not
> +		 * critical.
> +		 */
> +		SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000);
> +		x_hi = fx_hi;
> +		x_lo = x - x_hi;
> +		d = x_hi * G(i) - 1 + x_lo * G(i);
> +#endif
> +	}
> +
> +	/*
> +	 * Our algorithm depends on exact cancellation of F_lo(i) and
> +	 * F_hi(i) with dk*ln_2_lo and dk*ln2_hi when k is -1 and i is
> +	 * at the end of the table.  This and other technical complications
> +	 * make it difficult to avoid the double scaling in (dk*ln2) *
> +	 * log(base) for base != e without losing more accuracy and/or
> +	 * efficiency than is gained.
> +	 */
> +	z = d * d;
> +	val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) +
> +	    (F_lo(i) + dk * ln2_lo + z * d * (d * P4 + P3)) + z * P2;
> +	val_hi = d;
> +#ifdef DEBUG
> +	if (fetestexcept(FE_UNDERFLOW))
> +		breakpoint();
> +#endif
> +
> +	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
> +	RETURN2(rp, val_hi, val_lo);
> +}
> +
> +long double
> +log1pl(long double x)
> +{
> +	long double d, d_hi, d_lo, dk, f_lo, val_hi, val_lo, z;
> +	long double f_hi, twopminusk;
> +	uint64_t ix, lx;
> +	int i, k;
> +	int16_t ax, hx;
> +
> +	DOPRINT_START(&x);
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +	if (hx < 0x3fff) {		/* x < 1, or x neg NaN */
> +		ax = hx & 0x7fff;
> +		if (ax >= 0x3fff) {	/* x <= -1, or x neg NaN */
> +			if (ax == 0x3fff && lx == 0x8000000000000000ULL)
> +				RETURNP(-1 / zero);	/* log1p(-1) = -Inf */
> +			/* log1p(x < 1, or x [pseudo-]NaN) = qNaN: */
> +			RETURNP((x - x) / (x - x));
> +		}
> +		if (ax <= 0x3fbe) {	/* |x| < 2**-64 */
> +			if ((int)x == 0)
> +				RETURNP(x);	/* x with inexact if x != 0 */
> +		}
> +		f_hi = 1;
> +		f_lo = x;
> +	} else if (hx >= 0x7fff) {	/* x +Inf or non-neg NaN */
> +		RETURNP(x + x);		/* log1p(Inf or NaN) = Inf or qNaN */
> +					/* log1p(pseudo-Inf) = qNaN */
> +					/* log1p(pseudo-NaN) = qNaN */
> +					/* log1p(unnormal) = qNaN */
> +	} else if (hx < 0x407f) {	/* 1 <= x < 2**128 */
> +		f_hi = x;
> +		f_lo = 1;
> +	} else {			/* 2**128 <= x < +Inf */
> +		f_hi = x;
> +		f_lo = 0;		/* avoid underflow of the P5 term */
> +	}
> +	ENTERI();
> +	x = f_hi + f_lo;
> +	f_lo = (f_hi - x) + f_lo;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +	k = -16383;
> +
> +	k += hx;
> +	ix = lx & 0x7fffffffffffffffULL;
> +	dk = k;
> +
> +	SET_LDBL_EXPSIGN(x, 0x3fff);
> +	twopminusk = 1;
> +	SET_LDBL_EXPSIGN(twopminusk, 0x7ffe - (hx & 0x7fff));
> +	f_lo *= twopminusk;
> +
> +	i = (ix + (1LL << (L2I - 2))) >> (L2I - 1);
> +
> +	/*
> +	 * x*G(i)-1 (with a reduced x) can be represented exactly, as
> +	 * above, but now we need to evaluate the polynomial on d =
> +	 * (x+f_lo)*G(i)-1 and extra precision is needed for that.
> +	 * Since x+x_lo is a hi+lo decomposition and subtracting 1
> +	 * doesn't lose too many bits, an inexact calculation for
> +	 * f_lo*G(i) is good enough.
> +	 */
> +	if (0)
> +		d_hi = x * G(i) - 1;
> +	else {
> +#ifdef USE_UTAB
> +		d_hi = (x - H(i)) * G(i) + E(i);
> +#else
> +		long double x_hi, x_lo;
> +		float fx_hi;
> +
> +		SET_FLOAT_WORD(fx_hi, (lx >> 40) | 0x3f800000);
> +		x_hi = fx_hi;
> +		x_lo = x - x_hi;
> +		d_hi = x_hi * G(i) - 1 + x_lo * G(i);
> +#endif
> +	}
> +	d_lo = f_lo * G(i);
> +
> +	/*
> +	 * This is _2sumF(d_hi, d_lo) inlined.  The condition
> +	 * (d_hi == 0 || |d_hi| >= |d_lo|) for using _2sumF() is not
> +	 * always satisifed, so it is not clear that this works, but
> +	 * it works in practice.  It works even if it gives a wrong
> +	 * normalized d_lo, since |d_lo| > |d_hi| implies that i is
> +	 * nonzero and d is tiny, so the F(i) term dominates d_lo.
> +	 * In float precision:
> +	 * (By exhaustive testing, the worst case is d_hi = 0x1.bp-25.
> +	 * And if d is only a little tinier than that, we would have
> +	 * another underflow problem for the P3 term; this is also ruled
> +	 * out by exhaustive testing.)
> +	 */
> +	d = d_hi + d_lo;
> +	d_lo = d_hi - d + d_lo;
> +	d_hi = d;
> +
> +	z = d * d;
> +	val_lo = z * d * z * (z * (d * P8 + P7) + (d * P6 + P5)) +
> +	    (F_lo(i) + dk * ln2_lo + d_lo + z * d * (d * P4 + P3)) + z * P2;
> +	val_hi = d_hi;
> +#ifdef DEBUG
> +	if (fetestexcept(FE_UNDERFLOW))
> +		breakpoint();
> +#endif
> +
> +	_3sumF(val_hi, val_lo, F_hi(i) + dk * ln2_hi);
> +	RETURN2PI(val_hi, val_lo);
> +}
> +
> +#ifdef STRUCT_RETURN
> +
> +long double
> +logl(long double x)
> +{
> +	struct ld r;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	RETURNSPI(&r);
> +}
> +
> +/* Use macros since GCC < 8 rejects static const expressions in initializers. */
> +#define	invln10_hi	4.3429448190317999e-1	/*  0x1bcb7b1526e000.0p-54 */
> +#define	invln10_lo	7.1842412889749798e-14	/*  0x1438ca9aadd558.0p-96 */
> +#define	invln2_hi	1.4426950408887933e0	/*  0x171547652b8000.0p-52 */
> +#define	invln2_lo	1.7010652264631490e-13	/*  0x17f0bbbe87fed0.0p-95 */
> +/* Let the compiler pre-calculate this sum to avoid FE_INEXACT at run time. */
> +static const double invln10_lo_plus_hi = invln10_lo + invln10_hi;
> +static const double invln2_lo_plus_hi = invln2_lo + invln2_hi;
> +
> +long double
> +log10l(long double x)
> +{
> +	struct ld r;
> +	long double hi, lo;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	if (!r.lo_set)
> +		RETURNPI(r.hi);
> +	_2sumF(r.hi, r.lo);
> +	hi = (float)r.hi;
> +	lo = r.lo + (r.hi - hi);
> +	RETURN2PI(invln10_hi * hi,
> +	    invln10_lo_plus_hi * lo + invln10_lo * hi);
> +}
> +
> +long double
> +log2l(long double x)
> +{
> +	struct ld r;
> +	long double hi, lo;
> +
> +	ENTERI();
> +	DOPRINT_START(&x);
> +	k_logl(x, &r);
> +	if (!r.lo_set)
> +		RETURNPI(r.hi);
> +	_2sumF(r.hi, r.lo);
> +	hi = (float)r.hi;
> +	lo = r.lo + (r.hi - hi);
> +	RETURN2PI(invln2_hi * hi,
> +	    invln2_lo_plus_hi * lo + invln2_lo * hi);
> +}
> +
> +#endif /* STRUCT_RETURN */
> diff --git a/newlib/libm/ld80/s_sinpil.c b/newlib/libm/ld80/s_sinpil.c
> new file mode 100644
> index 000000000..4cefa9235
> --- /dev/null
> +++ b/newlib/libm/ld80/s_sinpil.c
> @@ -0,0 +1,140 @@
> +/*-
> + * Copyright (c) 2017 Steven G. Kargl
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice unmodified, this list of conditions, and the following
> + *    disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
> + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
> + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
> + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * See ../src/s_sinpi.c for implementation details.
> + */
> +
> +#ifdef __i386__
> +#include <ieeefp.h>
> +#endif
> +#include <stdint.h>
> +
> +#include "fpmath.h"
> +#include "math.h"
> +#include "math_private.h"
> +
> +static const union IEEEl2bits
> +pi_hi_u = LD80C(0xc90fdaa200000000,   1, 3.14159265346825122833e+00L),
> +pi_lo_u = LD80C(0x85a308d313198a2e, -33, 1.21542010130123852029e-10L);
> +#define	pi_hi	(pi_hi_u.e)
> +#define	pi_lo	(pi_lo_u.e)
> +
> +#include "k_cospil.h"
> +#include "k_sinpil.h"
> +
> +volatile static const double vzero = 0;
> +
> +long double
> +sinpil(long double x)
> +{
> +	long double ax, hi, lo, s;
> +	uint64_t lx, m;
> +	uint32_t j0;
> +	uint16_t hx, ix;
> +
> +	EXTRACT_LDBL80_WORDS(hx, lx, x);
> +	ix = hx & 0x7fff;
> +	INSERT_LDBL80_WORDS(ax, ix, lx);
> +
> +	ENTERI();
> +
> +	if (ix < 0x3fff) {			/* |x| < 1 */
> +		if (ix < 0x3ffd) {		/* |x| < 0.25 */
> +			if (ix < 0x3fdd) {	/* |x| < 0x1p-34 */
> +				if (x == 0)
> +					RETURNI(x);
> +				INSERT_LDBL80_WORDS(hi, hx,
> +				    lx & 0xffffffff00000000ull);
> +				hi *= 0x1p63L;
> +				lo = x * 0x1p63L - hi;
> +				s = (pi_lo + pi_hi) * lo + pi_lo * hi +
> +				    pi_hi * hi;
> +				RETURNI(s * 0x1p-63L);
> +			}
> +			s = __kernel_sinpil(ax);
> +			RETURNI((hx & 0x8000) ? -s : s);
> +		}
> +
> +		if (ix < 0x3ffe)			/* |x| < 0.5 */
> +			s = __kernel_cospil(0.5 - ax);
> +		else if (lx < 0xc000000000000000ull)	/* |x| < 0.75 */
> +			s = __kernel_cospil(ax - 0.5);
> +		else
> +			s = __kernel_sinpil(1 - ax);
> +		RETURNI((hx & 0x8000) ? -s : s);
> +	}
> +
> +	if (ix < 0x403e) {		/* 1 <= |x| < 0x1p63 */
> +		/* Determine integer part of ax. */
> +		j0 = ix - 0x3fff + 1;
> +		if (j0 < 32) {
> +			lx = (lx >> 32) << 32;
> +			lx &= ~(((lx << 32)-1) >> j0);
> +		} else {
> +			m = (uint64_t)-1 >> (j0 + 1);
> +			if (lx & m) lx &= ~m;
> +		}
> +		INSERT_LDBL80_WORDS(x, ix, lx);
> +
> +		ax -= x;
> +		EXTRACT_LDBL80_WORDS(ix, lx, ax);
> +
> +		if (ix == 0) {
> +			s = 0;
> +		} else {
> +			if (ix < 0x3ffe) {		/* |x| < 0.5 */
> +				if (ix < 0x3ffd)	/* |x| < 0.25 */
> +					s = __kernel_sinpil(ax);
> +				else 
> +					s = __kernel_cospil(0.5 - ax);
> +			} else {
> +							/* |x| < 0.75 */
> +				if (lx < 0xc000000000000000ull)
> +					s = __kernel_cospil(ax - 0.5);
> +				else
> +					s = __kernel_sinpil(1 - ax);
> +			}
> +
> +			if (j0 > 40)
> +				x -= 0x1p40;
> +			if (j0 > 30)
> +				x -= 0x1p30;
> +			j0 = (uint32_t)x;
> +			if (j0 & 1) s = -s;
> +		}
> +		RETURNI((hx & 0x8000) ? -s : s);
> +	}
> +
> +	/* x = +-inf or nan. */
> +	if (ix >= 0x7fff)
> +		RETURNI(vzero / vzero);
> +
> +	/*
> +	 * |x| >= 0x1p63 is always an integer, so return +-0.
> +	 */
> +	RETURNI(copysignl(0, x));
> +}
> -- 
> 2.31.1


  reply	other threads:[~2023-04-24  8:51 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-20 21:23 [PATCH v2 0/3] Add math support for non LDBL_EQ_DBL architecture Jennifer Averett
2023-04-20 21:23 ` [PATCH v2 1/3] newlib: Add FreeBSD files for non LDBL_EQ_DBL support Jennifer Averett
2023-04-24  8:51   ` Corinna Vinschen [this message]
2023-04-24 12:47     ` Jennifer Averett
2023-04-24 13:03   ` Sebastian Huber
2023-04-27 11:46     ` Jennifer Averett
2023-04-27 11:49       ` Sebastian Huber
2023-04-20 21:23 ` [PATCH v2 2/3] newlib: Add non LDBL_EQ_DBL math support for aarch64, i386, and x86_64 Jennifer Averett
2023-04-20 21:23 ` [PATCH v2 3/3] Regenerated source for adding non LDBL_EQ_DBL Jennifer Averett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZEZDEBZ72SapHnz4@calimero.vinschen.de \
    --to=vinschen@redhat.com \
    --cc=jennifer.averett@oarcorp.com \
    --cc=newlib@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).