about summary refs log tree commit diff
path: root/sysdeps/ieee754
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ieee754')
-rw-r--r--sysdeps/ieee754/dbl-64/s_fromfp.c7
-rw-r--r--sysdeps/ieee754/dbl-64/s_fromfp_main.c82
-rw-r--r--sysdeps/ieee754/dbl-64/s_fromfpx.c7
-rw-r--r--sysdeps/ieee754/dbl-64/s_ufromfp.c7
-rw-r--r--sysdeps/ieee754/dbl-64/s_ufromfpx.c7
-rw-r--r--sysdeps/ieee754/flt-32/s_fromfpf.c4
-rw-r--r--sysdeps/ieee754/flt-32/s_fromfpf_main.c82
-rw-r--r--sysdeps/ieee754/flt-32/s_fromfpxf.c4
-rw-r--r--sysdeps/ieee754/flt-32/s_ufromfpf.c4
-rw-r--r--sysdeps/ieee754/flt-32/s_ufromfpxf.c4
-rw-r--r--sysdeps/ieee754/ldbl-128/s_fromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128/s_fromfpl_main.c90
-rw-r--r--sysdeps/ieee754/ldbl-128/s_fromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128/s_ufromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128/s_ufromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_fromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_fromfpl_main.c147
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_fromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_ufromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_ufromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/s_fromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/s_fromfpl_main.c84
-rw-r--r--sysdeps/ieee754/ldbl-96/s_fromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/s_ufromfpl.c4
-rw-r--r--sysdeps/ieee754/ldbl-96/s_ufromfpxl.c4
-rw-r--r--sysdeps/ieee754/ldbl-opt/Makefile6
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-compat.h1
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-fromfp.c26
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-fromfpx.c26
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-ufromfp.c26
-rw-r--r--sysdeps/ieee754/ldbl-opt/nldbl-ufromfpx.c26
31 files changed, 687 insertions, 1 deletions
diff --git a/sysdeps/ieee754/dbl-64/s_fromfp.c b/sysdeps/ieee754/dbl-64/s_fromfp.c
new file mode 100644
index 0000000000..92fbe0c162
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/s_fromfp.c
@@ -0,0 +1,7 @@
+#define UNSIGNED 0
+#define INEXACT 0
+#define FUNC fromfp
+#include <s_fromfp_main.c>
+#ifdef NO_LONG_DOUBLE
+weak_alias (fromfp, fromfpl)
+#endif
diff --git a/sysdeps/ieee754/dbl-64/s_fromfp_main.c b/sysdeps/ieee754/dbl-64/s_fromfp_main.c
new file mode 100644
index 0000000000..c0cd271ad5
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/s_fromfp_main.c
@@ -0,0 +1,82 @@
+/* Round to integer type.  dbl-64 version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define BIAS 0x3ff
+#define MANT_DIG 53
+
+#if UNSIGNED
+# define RET_TYPE uintmax_t
+#else
+# define RET_TYPE intmax_t
+#endif
+
+#include <fromfp.h>
+
+RET_TYPE
+FUNC (double x, int round, unsigned int width)
+{
+  if (width > INTMAX_WIDTH)
+    width = INTMAX_WIDTH;
+  uint64_t ix;
+  EXTRACT_WORDS64 (ix, x);
+  bool negative = (ix & 0x8000000000000000ULL) != 0;
+  if (width == 0)
+    return fromfp_domain_error (negative, width);
+  ix &= 0x7fffffffffffffffULL;
+  if (ix == 0)
+    return 0;
+  int exponent = ix >> (MANT_DIG - 1);
+  exponent -= BIAS;
+  int max_exponent = fromfp_max_exponent (negative, width);
+  if (exponent > max_exponent)
+    return fromfp_domain_error (negative, width);
+
+  ix &= ((1ULL << (MANT_DIG - 1)) - 1);
+  ix |= 1ULL << (MANT_DIG - 1);
+  uintmax_t uret;
+  bool half_bit, more_bits;
+  if (exponent >= MANT_DIG - 1)
+    {
+      uret = ix;
+      uret <<= exponent - (MANT_DIG - 1);
+      half_bit = false;
+      more_bits = false;
+    }
+  else if (exponent >= -1)
+    {
+      uint64_t h = 1ULL << (MANT_DIG - 2 - exponent);
+      half_bit = (ix & h) != 0;
+      more_bits = (ix & (h - 1)) != 0;
+      uret = ix >> (MANT_DIG - 1 - exponent);
+    }
+  else
+    {
+      uret = 0;
+      half_bit = false;
+      more_bits = true;
+    }
+  return fromfp_round_and_return (negative, uret, half_bit, more_bits, round,
+				  exponent, max_exponent, width);
+}
diff --git a/sysdeps/ieee754/dbl-64/s_fromfpx.c b/sysdeps/ieee754/dbl-64/s_fromfpx.c
new file mode 100644
index 0000000000..bbfb969813
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/s_fromfpx.c
@@ -0,0 +1,7 @@
+#define UNSIGNED 0
+#define INEXACT 1
+#define FUNC fromfpx
+#include <s_fromfp_main.c>
+#ifdef NO_LONG_DOUBLE
+weak_alias (fromfpx, fromfpxl)
+#endif
diff --git a/sysdeps/ieee754/dbl-64/s_ufromfp.c b/sysdeps/ieee754/dbl-64/s_ufromfp.c
new file mode 100644
index 0000000000..c3d9047930
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/s_ufromfp.c
@@ -0,0 +1,7 @@
+#define UNSIGNED 1
+#define INEXACT 0
+#define FUNC ufromfp
+#include <s_fromfp_main.c>
+#ifdef NO_LONG_DOUBLE
+weak_alias (ufromfp, ufromfpl)
+#endif
diff --git a/sysdeps/ieee754/dbl-64/s_ufromfpx.c b/sysdeps/ieee754/dbl-64/s_ufromfpx.c
new file mode 100644
index 0000000000..dee607f8c0
--- /dev/null
+++ b/sysdeps/ieee754/dbl-64/s_ufromfpx.c
@@ -0,0 +1,7 @@
+#define UNSIGNED 1
+#define INEXACT 1
+#define FUNC ufromfpx
+#include <s_fromfp_main.c>
+#ifdef NO_LONG_DOUBLE
+weak_alias (ufromfpx, ufromfpxl)
+#endif
diff --git a/sysdeps/ieee754/flt-32/s_fromfpf.c b/sysdeps/ieee754/flt-32/s_fromfpf.c
new file mode 100644
index 0000000000..68d4c80a17
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_fromfpf.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 0
+#define FUNC fromfpf
+#include <s_fromfpf_main.c>
diff --git a/sysdeps/ieee754/flt-32/s_fromfpf_main.c b/sysdeps/ieee754/flt-32/s_fromfpf_main.c
new file mode 100644
index 0000000000..e1205edcb9
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_fromfpf_main.c
@@ -0,0 +1,82 @@
+/* Round to integer type.  flt-32 version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define BIAS 0x7f
+#define MANT_DIG 24
+
+#if UNSIGNED
+# define RET_TYPE uintmax_t
+#else
+# define RET_TYPE intmax_t
+#endif
+
+#include <fromfp.h>
+
+RET_TYPE
+FUNC (float x, int round, unsigned int width)
+{
+  if (width > INTMAX_WIDTH)
+    width = INTMAX_WIDTH;
+  uint32_t ix;
+  GET_FLOAT_WORD (ix, x);
+  bool negative = (ix & 0x80000000) != 0;
+  if (width == 0)
+    return fromfp_domain_error (negative, width);
+  ix &= 0x7fffffff;
+  if (ix == 0)
+    return 0;
+  int exponent = ix >> (MANT_DIG - 1);
+  exponent -= BIAS;
+  int max_exponent = fromfp_max_exponent (negative, width);
+  if (exponent > max_exponent)
+    return fromfp_domain_error (negative, width);
+
+  ix &= ((1U << (MANT_DIG - 1)) - 1);
+  ix |= 1U << (MANT_DIG - 1);
+  uintmax_t uret;
+  bool half_bit, more_bits;
+  if (exponent >= MANT_DIG - 1)
+    {
+      uret = ix;
+      uret <<= exponent - (MANT_DIG - 1);
+      half_bit = false;
+      more_bits = false;
+    }
+  else if (exponent >= -1)
+    {
+      uint32_t h = 1U << (MANT_DIG - 2 - exponent);
+      half_bit = (ix & h) != 0;
+      more_bits = (ix & (h - 1)) != 0;
+      uret = ix >> (MANT_DIG - 1 - exponent);
+    }
+  else
+    {
+      uret = 0;
+      half_bit = false;
+      more_bits = true;
+    }
+  return fromfp_round_and_return (negative, uret, half_bit, more_bits, round,
+				  exponent, max_exponent, width);
+}
diff --git a/sysdeps/ieee754/flt-32/s_fromfpxf.c b/sysdeps/ieee754/flt-32/s_fromfpxf.c
new file mode 100644
index 0000000000..9d0fcbc8cc
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_fromfpxf.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 1
+#define FUNC fromfpxf
+#include <s_fromfpf_main.c>
diff --git a/sysdeps/ieee754/flt-32/s_ufromfpf.c b/sysdeps/ieee754/flt-32/s_ufromfpf.c
new file mode 100644
index 0000000000..e6ffdf3374
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_ufromfpf.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 0
+#define FUNC ufromfpf
+#include <s_fromfpf_main.c>
diff --git a/sysdeps/ieee754/flt-32/s_ufromfpxf.c b/sysdeps/ieee754/flt-32/s_ufromfpxf.c
new file mode 100644
index 0000000000..97aa6890f0
--- /dev/null
+++ b/sysdeps/ieee754/flt-32/s_ufromfpxf.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 1
+#define FUNC ufromfpxf
+#include <s_fromfpf_main.c>
diff --git a/sysdeps/ieee754/ldbl-128/s_fromfpl.c b/sysdeps/ieee754/ldbl-128/s_fromfpl.c
new file mode 100644
index 0000000000..e323b4c25b
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/s_fromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 0
+#define FUNC fromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128/s_fromfpl_main.c b/sysdeps/ieee754/ldbl-128/s_fromfpl_main.c
new file mode 100644
index 0000000000..cfff2c697f
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/s_fromfpl_main.c
@@ -0,0 +1,90 @@
+/* Round to integer type.  ldbl-128 version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define BIAS 0x3fff
+#define MANT_DIG 113
+
+#if UNSIGNED
+# define RET_TYPE uintmax_t
+#else
+# define RET_TYPE intmax_t
+#endif
+
+#include <fromfp.h>
+
+RET_TYPE
+FUNC (_Float128 x, int round, unsigned int width)
+{
+  if (width > INTMAX_WIDTH)
+    width = INTMAX_WIDTH;
+  uint64_t hx, lx;
+  GET_LDOUBLE_WORDS64 (hx, lx, x);
+  bool negative = (hx & 0x8000000000000000ULL) != 0;
+  if (width == 0)
+    return fromfp_domain_error (negative, width);
+  hx &= 0x7fffffffffffffffULL;
+  if ((hx | lx) == 0)
+    return 0;
+  int exponent = hx >> (MANT_DIG - 1 - 64);
+  exponent -= BIAS;
+  int max_exponent = fromfp_max_exponent (negative, width);
+  if (exponent > max_exponent)
+    return fromfp_domain_error (negative, width);
+
+  hx &= ((1ULL << (MANT_DIG - 1 - 64)) - 1);
+  hx |= 1ULL << (MANT_DIG - 1 - 64);
+  uintmax_t uret;
+  bool half_bit, more_bits;
+  /* The exponent is at most 63, so we are shifting right by at least
+     49 bits.  */
+  if (exponent >= -1)
+    {
+      int shift = MANT_DIG - 1 - exponent;
+      if (shift <= 64)
+	{
+	  uint64_t h = 1ULL << (shift - 1);
+	  half_bit = (lx & h) != 0;
+	  more_bits = (lx & (h - 1)) != 0;
+	  uret = hx << (64 - shift);
+	  if (shift != 64)
+	    uret |= lx >> shift;
+	}
+      else
+	{
+	  uint64_t h = 1ULL << (shift - 1 - 64);
+	  half_bit = (hx & h) != 0;
+	  more_bits = ((hx & (h - 1)) | lx) != 0;
+	  uret = hx >> (shift - 64);
+	}
+    }
+  else
+    {
+      uret = 0;
+      half_bit = false;
+      more_bits = true;
+    }
+  return fromfp_round_and_return (negative, uret, half_bit, more_bits, round,
+				  exponent, max_exponent, width);
+}
diff --git a/sysdeps/ieee754/ldbl-128/s_fromfpxl.c b/sysdeps/ieee754/ldbl-128/s_fromfpxl.c
new file mode 100644
index 0000000000..2f3189d7de
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/s_fromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 1
+#define FUNC fromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128/s_ufromfpl.c b/sysdeps/ieee754/ldbl-128/s_ufromfpl.c
new file mode 100644
index 0000000000..c686daa4a7
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/s_ufromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 0
+#define FUNC ufromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128/s_ufromfpxl.c b/sysdeps/ieee754/ldbl-128/s_ufromfpxl.c
new file mode 100644
index 0000000000..906066c83c
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128/s_ufromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 1
+#define FUNC ufromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fromfpl.c b/sysdeps/ieee754/ldbl-128ibm/s_fromfpl.c
new file mode 100644
index 0000000000..e323b4c25b
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 0
+#define FUNC fromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fromfpl_main.c b/sysdeps/ieee754/ldbl-128ibm/s_fromfpl_main.c
new file mode 100644
index 0000000000..99c5882e82
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fromfpl_main.c
@@ -0,0 +1,147 @@
+/* Round to integer type.  ldbl-128ibm version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define BIAS 0x3ff
+#define MANT_DIG 53
+
+#if UNSIGNED
+# define RET_TYPE uintmax_t
+#else
+# define RET_TYPE intmax_t
+#endif
+
+#include <fromfp.h>
+
+RET_TYPE
+FUNC (long double x, int round, unsigned int width)
+{
+  double hi, lo;
+  if (width > INTMAX_WIDTH)
+    width = INTMAX_WIDTH;
+  uint64_t hx, lx;
+  ldbl_unpack (x, &hi, &lo);
+  EXTRACT_WORDS64 (hx, hi);
+  EXTRACT_WORDS64 (lx, lo);
+  bool negative = (hx & 0x8000000000000000ULL) != 0;
+  bool lo_negative = (lx & 0x8000000000000000ULL) != 0;
+  if (width == 0)
+    return fromfp_domain_error (negative, width);
+  hx &= 0x7fffffffffffffffULL;
+  lx &= 0x7fffffffffffffffULL;
+  if ((hx | lx) == 0)
+    return 0;
+  int hi_exponent = hx >> (MANT_DIG - 1);
+  hi_exponent -= BIAS;
+  int exponent = hi_exponent;
+  hx &= ((1ULL << (MANT_DIG - 1)) - 1);
+  if (hx == 0 && lx != 0 && lo_negative != negative)
+    exponent--;
+  int max_exponent = fromfp_max_exponent (negative, width);
+  if (exponent > max_exponent)
+    return fromfp_domain_error (negative, width);
+  int lo_exponent = lx >> (MANT_DIG - 1);
+  lo_exponent -= BIAS;
+
+  /* Convert the high part to integer.  */
+  hx |= 1ULL << (MANT_DIG - 1);
+  uintmax_t uret;
+  bool half_bit, more_bits;
+  if (hi_exponent >= MANT_DIG - 1)
+    {
+      uret = hx;
+      uret <<= hi_exponent - (MANT_DIG - 1);
+      half_bit = false;
+      more_bits = false;
+    }
+  else if (hi_exponent >= -1)
+    {
+      uint64_t h = 1ULL << (MANT_DIG - 2 - hi_exponent);
+      half_bit = (hx & h) != 0;
+      more_bits = (hx & (h - 1)) != 0;
+      uret = hx >> (MANT_DIG - 1 - hi_exponent);
+    }
+  else
+    {
+      uret = 0;
+      half_bit = false;
+      more_bits = true;
+    }
+
+  /* Likewise, the low part.  */
+  if (lx != 0)
+    {
+      uintmax_t lo_uret;
+      bool lo_half_bit, lo_more_bits;
+      lx &= ((1ULL << (MANT_DIG - 1)) - 1);
+      lx |= 1ULL << (MANT_DIG - 1);
+      /* The high part exponent is at most 64, so the low part
+	 exponent is at most 11.  */
+      if (lo_exponent >= -1)
+	{
+	  uint64_t h = 1ULL << (MANT_DIG - 2 - lo_exponent);
+	  lo_half_bit = (lx & h) != 0;
+	  lo_more_bits = (lx & (h - 1)) != 0;
+	  lo_uret = lx >> (MANT_DIG - 1 - lo_exponent);
+	}
+      else
+	{
+	  lo_uret = 0;
+	  lo_half_bit = false;
+	  lo_more_bits = true;
+	}
+      if (lo_negative == negative)
+	{
+	  uret += lo_uret;
+	  half_bit |= lo_half_bit;
+	  more_bits |= lo_more_bits;
+	}
+      else
+	{
+	  uret -= lo_uret;
+	  if (lo_half_bit)
+	    {
+	      uret--;
+	      half_bit = true;
+	    }
+	  if (lo_more_bits && !more_bits)
+	    {
+	      if (half_bit)
+		{
+		  half_bit = false;
+		  more_bits = true;
+		}
+	      else
+		{
+		  uret--;
+		  half_bit = true;
+		  more_bits = true;
+		}
+	    }
+	}
+    }
+
+  return fromfp_round_and_return (negative, uret, half_bit, more_bits, round,
+				  exponent, max_exponent, width);
+}
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_fromfpxl.c b/sysdeps/ieee754/ldbl-128ibm/s_fromfpxl.c
new file mode 100644
index 0000000000..2f3189d7de
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/s_fromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 1
+#define FUNC fromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_ufromfpl.c b/sysdeps/ieee754/ldbl-128ibm/s_ufromfpl.c
new file mode 100644
index 0000000000..c686daa4a7
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/s_ufromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 0
+#define FUNC ufromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_ufromfpxl.c b/sysdeps/ieee754/ldbl-128ibm/s_ufromfpxl.c
new file mode 100644
index 0000000000..906066c83c
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-128ibm/s_ufromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 1
+#define FUNC ufromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-96/s_fromfpl.c b/sysdeps/ieee754/ldbl-96/s_fromfpl.c
new file mode 100644
index 0000000000..e323b4c25b
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/s_fromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 0
+#define FUNC fromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-96/s_fromfpl_main.c b/sysdeps/ieee754/ldbl-96/s_fromfpl_main.c
new file mode 100644
index 0000000000..4ae6c81a7c
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/s_fromfpl_main.c
@@ -0,0 +1,84 @@
+/* Round to integer type.  ldbl-96 version.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#define BIAS 0x3fff
+#define MANT_DIG 64
+
+#if UNSIGNED
+# define RET_TYPE uintmax_t
+#else
+# define RET_TYPE intmax_t
+#endif
+
+#include <fromfp.h>
+
+RET_TYPE
+FUNC (long double x, int round, unsigned int width)
+{
+  if (width > INTMAX_WIDTH)
+    width = INTMAX_WIDTH;
+  uint16_t se;
+  uint32_t hx, lx;
+  GET_LDOUBLE_WORDS (se, hx, lx, x);
+  bool negative = (se & 0x8000) != 0;
+  if (width == 0)
+    return fromfp_domain_error (negative, width);
+  if ((hx | lx) == 0)
+    return 0;
+  int exponent = se & 0x7fff;
+  exponent -= BIAS;
+  int max_exponent = fromfp_max_exponent (negative, width);
+  if (exponent > max_exponent)
+    return fromfp_domain_error (negative, width);
+
+  uint64_t ix = (((uint64_t) hx) << 32) | lx;
+  uintmax_t uret;
+  bool half_bit, more_bits;
+  if (exponent >= MANT_DIG - 1)
+    {
+      uret = ix;
+      /* Exponent 63; no shifting required.  */
+      half_bit = false;
+      more_bits = false;
+    }
+  else if (exponent >= -1)
+    {
+      uint64_t h = 1ULL << (MANT_DIG - 2 - exponent);
+      half_bit = (ix & h) != 0;
+      more_bits = (ix & (h - 1)) != 0;
+      if (exponent == -1)
+	uret = 0;
+      else
+	uret = ix >> (MANT_DIG - 1 - exponent);
+    }
+  else
+    {
+      uret = 0;
+      half_bit = false;
+      more_bits = true;
+    }
+  return fromfp_round_and_return (negative, uret, half_bit, more_bits, round,
+				  exponent, max_exponent, width);
+}
diff --git a/sysdeps/ieee754/ldbl-96/s_fromfpxl.c b/sysdeps/ieee754/ldbl-96/s_fromfpxl.c
new file mode 100644
index 0000000000..2f3189d7de
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/s_fromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 0
+#define INEXACT 1
+#define FUNC fromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-96/s_ufromfpl.c b/sysdeps/ieee754/ldbl-96/s_ufromfpl.c
new file mode 100644
index 0000000000..c686daa4a7
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/s_ufromfpl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 0
+#define FUNC ufromfpl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-96/s_ufromfpxl.c b/sysdeps/ieee754/ldbl-96/s_ufromfpxl.c
new file mode 100644
index 0000000000..906066c83c
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-96/s_ufromfpxl.c
@@ -0,0 +1,4 @@
+#define UNSIGNED 1
+#define INEXACT 1
+#define FUNC ufromfpxl
+#include <s_fromfpl_main.c>
diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile
index 006d0d59ee..81429d0ddd 100644
--- a/sysdeps/ieee754/ldbl-opt/Makefile
+++ b/sysdeps/ieee754/ldbl-opt/Makefile
@@ -44,7 +44,7 @@ libnldbl-calls = asprintf dprintf fprintf fscanf fwprintf fwscanf iovfscanf \
 		 isoc99_vwscanf isoc99_vfwscanf isoc99_vswscanf \
 		 nextup nextdown totalorder totalordermag getpayload \
 		 canonicalize setpayload setpayloadsig llogb fmaxmag fminmag \
-		 roundeven
+		 roundeven fromfp ufromfp fromfpx ufromfpx
 libnldbl-routines = $(libnldbl-calls:%=nldbl-%)
 libnldbl-inhibit-o = $(object-suffixes)
 libnldbl-static-only-routines = $(libnldbl-routines)
@@ -103,6 +103,8 @@ CFLAGS-nldbl-fmin.c = -fno-builtin-fminl
 CFLAGS-nldbl-fminmag.c = -fno-builtin-fminmagl
 CFLAGS-nldbl-fmod.c = -fno-builtin-fmodl
 CFLAGS-nldbl-frexp.c = -fno-builtin-frexpl
+CFLAGS-nldbl-fromfp.c = -fno-builtin-fromfpl
+CFLAGS-nldbl-fromfpx.c = -fno-builtin-fromfpxl
 CFLAGS-nldbl-gamma.c = -fno-builtin-gammal
 CFLAGS-nldbl-getpayload.c = -fno-builtin-getpayloadl
 CFLAGS-nldbl-hypot.c = -fno-builtin-hypotl
@@ -156,6 +158,8 @@ CFLAGS-nldbl-tgamma.c = -fno-builtin-tgammal
 CFLAGS-nldbl-totalorder.c = -fno-builtin-totalorderl
 CFLAGS-nldbl-totalordermag.c = -fno-builtin-totalordermagl
 CFLAGS-nldbl-trunc.c = -fno-builtin-truncl
+CFLAGS-nldbl-ufromfp.c = -fno-builtin-ufromfpl
+CFLAGS-nldbl-ufromfpx.c = -fno-builtin-ufromfpxl
 CFLAGS-nldbl-y0.c = -fno-builtin-y0l
 CFLAGS-nldbl-y1.c = -fno-builtin-y1l
 CFLAGS-nldbl-yn.c = -fno-builtin-ynl
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
index 0c3c5ad24d..b6cd2993bf 100644
--- a/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-compat.h
@@ -24,6 +24,7 @@
 #define __NO_LONG_DOUBLE_MATH	1
 #include <stdarg.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <printf.h>
 #include <wchar.h>
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-fromfp.c b/sysdeps/ieee754/ldbl-opt/nldbl-fromfp.c
new file mode 100644
index 0000000000..a05f1b3462
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-fromfp.c
@@ -0,0 +1,26 @@
+/* Compatibility routine for IEEE double as long double for fromfp.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "nldbl-compat.h"
+
+intmax_t
+attribute_hidden
+fromfpl (double x, int round, unsigned int width)
+{
+  return fromfp (x, round, width);
+}
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-fromfpx.c b/sysdeps/ieee754/ldbl-opt/nldbl-fromfpx.c
new file mode 100644
index 0000000000..198e1203d5
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-fromfpx.c
@@ -0,0 +1,26 @@
+/* Compatibility routine for IEEE double as long double for fromfpx.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "nldbl-compat.h"
+
+intmax_t
+attribute_hidden
+fromfpxl (double x, int round, unsigned int width)
+{
+  return fromfpx (x, round, width);
+}
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-ufromfp.c b/sysdeps/ieee754/ldbl-opt/nldbl-ufromfp.c
new file mode 100644
index 0000000000..b20a972537
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-ufromfp.c
@@ -0,0 +1,26 @@
+/* Compatibility routine for IEEE double as long double for ufromfp.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "nldbl-compat.h"
+
+uintmax_t
+attribute_hidden
+ufromfpl (double x, int round, unsigned int width)
+{
+  return ufromfp (x, round, width);
+}
diff --git a/sysdeps/ieee754/ldbl-opt/nldbl-ufromfpx.c b/sysdeps/ieee754/ldbl-opt/nldbl-ufromfpx.c
new file mode 100644
index 0000000000..e1b4cead5a
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/nldbl-ufromfpx.c
@@ -0,0 +1,26 @@
+/* Compatibility routine for IEEE double as long double for ufromfpx.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "nldbl-compat.h"
+
+uintmax_t
+attribute_hidden
+ufromfpxl (double x, int round, unsigned int width)
+{
+  return ufromfpx (x, round, width);
+}