summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--NEWS20
-rw-r--r--config.h.in3
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/configure27
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/configure.ac16
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_llrint.c31
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_llrintf.c22
7 files changed, 123 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 00e1cc5827..fe606d6134 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2015-10-13 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #16422]
+ * sysdeps/powerpc/powerpc32/fpu/configure.ac (libc_cv_ppc_fctidz):
+ New configure test.
+ * sysdeps/powerpc/powerpc32/fpu/configure: Regenerated.
+ * config.h.in [_LIBC] (HAVE_PPC_FCTIDZ): New macro.
+ * sysdeps/powerpc/powerpc32/fpu/s_llrint.c: Include <limits.h>,
+ <math_private.h> and <stdint.h>.
+ (__llrint): Avoid conversions to long long int where those might
+ raise spurious exceptions.
+ * sysdeps/powerpc/powerpc32/fpu/s_llrintf.c: Include
+ <math_private.h> and <stdint.h>.
+ (__llrintf): Avoid conversions to long long int where those might
+ raise spurious exceptions.
+
2015-10-12 Andreas Schwab <schwab@suse.de>
[BZ #18969]
diff --git a/NEWS b/NEWS
index 512b338492..478ed2dadb 100644
--- a/NEWS
+++ b/NEWS
@@ -10,16 +10,16 @@ Version 2.23
* The following bugs are resolved with this release:
887, 2542, 2543, 2558, 2898, 4404, 6803, 10432, 14341, 14912, 15367,
- 15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415, 16517,
- 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118, 17243, 17244,
- 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086, 18240, 18265,
- 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618, 18647, 18661,
- 18674, 18675, 18681, 18724, 18757, 18778, 18781, 18787, 18789, 18790,
- 18795, 18796, 18803, 18820, 18823, 18824, 18825, 18857, 18863, 18870,
- 18872, 18873, 18875, 18887, 18921, 18951, 18952, 18956, 18961, 18966,
- 18967, 18969, 18970, 18977, 18980, 18981, 18985, 19003, 19012, 19016,
- 19018, 19032, 19046, 19049, 19050, 19059, 19071, 19076, 19077, 19078,
- 19079, 19085, 19086, 19088, 19094, 19095.
+ 15384, 15470, 15786, 15918, 16141, 16296, 16347, 16399, 16415, 16422,
+ 16517, 16519, 16520, 16521, 16620, 16734, 16973, 16985, 17118, 17243,
+ 17244, 17250, 17441, 17787, 17886, 17887, 17905, 18084, 18086, 18240,
+ 18265, 18370, 18421, 18480, 18525, 18595, 18589, 18610, 18618, 18647,
+ 18661, 18674, 18675, 18681, 18724, 18757, 18778, 18781, 18787, 18789,
+ 18790, 18795, 18796, 18803, 18820, 18823, 18824, 18825, 18857, 18863,
+ 18870, 18872, 18873, 18875, 18887, 18921, 18951, 18952, 18956, 18961,
+ 18966, 18967, 18969, 18970, 18977, 18980, 18981, 18985, 19003, 19012,
+ 19016, 19018, 19032, 19046, 19049, 19050, 19059, 19071, 19076, 19077,
+ 19078, 19079, 19085, 19086, 19088, 19094, 19095.
* The obsolete header <regexp.h> has been removed. Programs that require
this header must be updated to use <regex.h> instead.
diff --git a/config.h.in b/config.h.in
index 7c851c97fe..5fd4897428 100644
--- a/config.h.in
+++ b/config.h.in
@@ -251,4 +251,7 @@
/* PowerPC32 uses fcfid for integer to floating point conversions. */
#define HAVE_PPC_FCFID 0
+/* PowerPC32 uses fctidz for floating point to long long conversions. */
+#define HAVE_PPC_FCTIDZ 0
+
#endif
diff --git a/sysdeps/powerpc/powerpc32/fpu/configure b/sysdeps/powerpc/powerpc32/fpu/configure
index 69a151b2c0..98c6f30ca3 100644
--- a/sysdeps/powerpc/powerpc32/fpu/configure
+++ b/sysdeps/powerpc/powerpc32/fpu/configure
@@ -27,3 +27,30 @@ if test $libc_cv_ppc_fcfid = yes; then
$as_echo "#define HAVE_PPC_FCFID 1" >>confdefs.h
fi
+
+# Test whether floating point to long long conversions use fctidz.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fctidz use" >&5
+$as_echo_n "checking for fctidz use... " >&6; }
+if ${libc_cv_ppc_fctidz+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ echo 'long long int foo (double x) { return (long long int) x; }' > conftest.c
+libc_cv_ppc_fctidz=no
+if { ac_try='${CC-cc} -S $CFLAGS conftest.c -o conftest.s 1>&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ if grep '[ ]fctidz' conftest.s > /dev/null 2>&1; then
+ libc_cv_ppc_fctidz=yes
+ fi
+fi
+rm -rf conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ppc_fctidz" >&5
+$as_echo "$libc_cv_ppc_fctidz" >&6; }
+if test $libc_cv_ppc_fctidz = yes; then
+ $as_echo "#define HAVE_PPC_FCTIDZ 1" >>confdefs.h
+
+fi
diff --git a/sysdeps/powerpc/powerpc32/fpu/configure.ac b/sysdeps/powerpc/powerpc32/fpu/configure.ac
index e596e793ae..1899705aab 100644
--- a/sysdeps/powerpc/powerpc32/fpu/configure.ac
+++ b/sysdeps/powerpc/powerpc32/fpu/configure.ac
@@ -16,3 +16,19 @@ rm -rf conftest*])
if test $libc_cv_ppc_fcfid = yes; then
AC_DEFINE([HAVE_PPC_FCFID])
fi
+
+# Test whether floating point to long long conversions use fctidz.
+AC_CACHE_CHECK([for fctidz use], [libc_cv_ppc_fctidz], [dnl
+echo 'long long int foo (double x) { return (long long int) x; }' > conftest.c
+libc_cv_ppc_fctidz=no
+if AC_TRY_COMMAND(${CC-cc} -S $CFLAGS conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then
+changequote(,)dnl
+ if grep '[ ]fctidz' conftest.s > /dev/null 2>&1; then
+ libc_cv_ppc_fctidz=yes
+ fi
+changequote([,])dnl
+fi
+rm -rf conftest*])
+if test $libc_cv_ppc_fctidz = yes; then
+ AC_DEFINE([HAVE_PPC_FCTIDZ])
+fi
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_llrint.c b/sysdeps/powerpc/powerpc32/fpu/s_llrint.c
index 48af9eb726..bb12272461 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_llrint.c
+++ b/sysdeps/powerpc/powerpc32/fpu/s_llrint.c
@@ -16,13 +16,42 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <limits.h>
#include <math.h>
#include <math_ldbl_opt.h>
+#include <math_private.h>
+#include <stdint.h>
long long int
__llrint (double x)
{
- return (long long int) __rint (x);
+ double rx = __rint (x);
+ if (HAVE_PPC_FCTIDZ || rx != x)
+ return (long long int) rx;
+ else
+ {
+ /* Avoid incorrect exceptions from libgcc conversions (as of GCC
+ 5): <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>. */
+ if (fabs (rx) < 0x1p31)
+ return (long long int) (long int) rx;
+ uint64_t i0;
+ EXTRACT_WORDS64 (i0, rx);
+ int exponent = ((i0 >> 52) & 0x7ff) - 0x3ff;
+ if (exponent < 63)
+ {
+ unsigned long long int mant
+ = (i0 & ((1ULL << 52) - 1)) | (1ULL << 52);
+ if (exponent < 52)
+ mant >>= 52 - exponent;
+ else
+ mant <<= exponent - 52;
+ return (long long int) ((i0 & (1ULL << 63)) != 0 ? -mant : mant);
+ }
+ else if (rx == (double) LLONG_MIN)
+ return LLONG_MIN;
+ else
+ return (long long int) (long int) rx << 32;
+ }
}
weak_alias (__llrint, llrint)
#ifdef NO_LONG_DOUBLE
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_llrintf.c b/sysdeps/powerpc/powerpc32/fpu/s_llrintf.c
index 205df4e03a..bcee02020a 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_llrintf.c
+++ b/sysdeps/powerpc/powerpc32/fpu/s_llrintf.c
@@ -17,10 +17,30 @@
<http://www.gnu.org/licenses/>. */
#include <math.h>
+#include <math_private.h>
+#include <stdint.h>
long long int
__llrintf (float x)
{
- return (long long int) __rintf (x);
+ float rx = __rintf (x);
+ if (HAVE_PPC_FCTIDZ || rx != x)
+ return (long long int) rx;
+ else
+ {
+ float arx = fabsf (rx);
+ /* Avoid incorrect exceptions from libgcc conversions (as of GCC
+ 5): <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59412>. */
+ if (arx < 0x1p31f)
+ return (long long int) (long int) rx;
+ else if (!(arx < 0x1p55f))
+ return (long long int) (long int) (rx * 0x1p-32f) << 32;
+ uint32_t i0;
+ GET_FLOAT_WORD (i0, rx);
+ int exponent = ((i0 >> 23) & 0xff) - 0x7f;
+ unsigned long long int mant = (i0 & 0x7fffff) | 0x800000;
+ mant <<= exponent - 23;
+ return (long long int) ((i0 & 0x80000000) != 0 ? -mant : mant);
+ }
}
weak_alias (__llrintf, llrintf)