about summary refs log tree commit diff
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)