about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--math/Makefile3
-rw-r--r--math/test-nearbyint-except-2.c72
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S6
-rw-r--r--sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S6
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S6
-rw-r--r--sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S6
7 files changed, 104 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 51faaed4c2..b23297b29b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2015-11-10  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #19228]
+	* sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S (__nearbyint): Save
+	and restore full floating-point state.
+	* sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S (__nearbyintf):
+	Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S (__nearbyint):
+	Likewise.
+	* sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S (__nearbyintf):
+	Likewise.
+	* math/test-nearbyint-except-2.c: New file.
+	* math/Makefile (tests): Add test-nearbyint-except-2.
+
 2015-11-10  H.J. Lu  <hongjiu.lu@intel.com>
 
 	[BZ #19178]
diff --git a/math/Makefile b/math/Makefile
index ec9e6b29d1..06412f3980 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -109,7 +109,8 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
 	test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \
 	test-fenv-tls test-fenv-preserve test-fenv-return test-fenvinline \
 	test-nearbyint-except test-fenv-clear test-signgam-finite \
-	test-signgam-finite-c99 test-signgam-finite-c11 $(tests-static)
+	test-signgam-finite-c99 test-signgam-finite-c11 \
+	test-nearbyint-except-2 $(tests-static)
 tests-static = test-fpucw-static test-fpucw-ieee-static
 # We do the `long double' tests only if this data type is available and
 # distinct from `double'.
diff --git a/math/test-nearbyint-except-2.c b/math/test-nearbyint-except-2.c
new file mode 100644
index 0000000000..04faac309d
--- /dev/null
+++ b/math/test-nearbyint-except-2.c
@@ -0,0 +1,72 @@
+/* Test nearbyint functions do not disable exception traps (bug 19228).
+   Copyright (C) 2015 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 <fenv.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifndef FE_INEXACT
+# define FE_INEXACT 0
+#endif
+
+#define TEST_FUNC(NAME, FLOAT, SUFFIX)					\
+static int								\
+NAME (void)								\
+{									\
+  int result = 0;							\
+  volatile FLOAT a, b __attribute__ ((unused));				\
+  a = 1.5;								\
+  /* nearbyint must work when traps on "inexact" are enabled.  */	\
+  b = nearbyint ## SUFFIX (a);						\
+  /* And it must have left those traps enabled.  */			\
+  if (fegetexcept () == FE_INEXACT)					\
+    puts ("PASS: " #FLOAT);						\
+  else									\
+    {									\
+      puts ("FAIL: " #FLOAT);						\
+      result = 1;							\
+    }									\
+  return result;							\
+}
+
+TEST_FUNC (float_test, float, f)
+TEST_FUNC (double_test, double, )
+#ifndef NO_LONG_DOUBLE
+TEST_FUNC (ldouble_test, long double, l)
+#endif
+
+static int
+do_test (void)
+{
+  if (feenableexcept (FE_INEXACT) == -1)
+    {
+      puts ("enabling FE_INEXACT traps failed, cannot test");
+      return 77;
+    }
+  int result = float_test ();
+  feenableexcept (FE_INEXACT);
+  result |= double_test ();
+#ifndef NO_LONG_DOUBLE
+  feenableexcept (FE_INEXACT);
+  result |= ldouble_test ();
+#endif
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S b/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
index cee4c7b239..27673b67e1 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
@@ -52,19 +52,21 @@ ENTRY (__nearbyint)
 	bgelr	cr7
 	fcmpu	cr7,fp1,fp12	/* if (x > 0.0 */
 	ble	cr7,L(lessthanzero)
+	mffs	fp11
 	mtfsb0	4*cr7+lt	/* Disable FE_INEXACT exception */
 	fadd	fp1,fp1,fp13	/* x += TWO52 */
 	fsub	fp1,fp1,fp13	/* x -= TWO52 */
 	fabs	fp1,fp1		/* if (x == 0.0 */
-	mtfsb0	4*cr1+eq	/* Clear any FE_INEXACT exception */
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr
 L(lessthanzero):
 	bgelr	cr7
+	mffs	fp11
 	mtfsb0	4*cr7+lt	/* Disable FE_INEXACT exception */
 	fsub	fp1,fp1,fp13	/* x -= TWO52 */
 	fadd	fp1,fp1,fp13	/* x += TWO52 */
 	fnabs	fp1,fp1		/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq	/* Clear any FE_INEXACT exception */
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr
 END (__nearbyint)
 
diff --git a/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S b/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
index 96a39c673d..a5084b2615 100644
--- a/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
+++ b/sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
@@ -51,19 +51,21 @@ ENTRY (__nearbyintf)
 	bgelr	cr7
 	fcmpu	cr7,fp1,fp12		/* if (x > 0.0 */
 	ble	cr7,L(lessthanzero)
+	mffs	fp11
 	mtfsb0	4*cr7+lt		/* Disable FE_INEXACT exception */
 	fadds	fp1,fp1,fp13		/* x += TWO23 */
 	fsubs	fp1,fp1,fp13		/* x -= TWO23 */
 	fabs	fp1,fp1			/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq		/* Clear any FE_INEXACT exception */
+	mtfsf	0xff,fp11		/* Restore FE_INEXACT state.  */
 	blr
 L(lessthanzero):
 	bgelr	cr7
+	mffs	fp11
 	mtfsb0	4*cr7+lt		/* Disable FE_INEXACT exception */
 	fsubs	fp1,fp1,fp13		/* x -= TWO23 */
 	fadds	fp1,fp1,fp13		/* x += TWO23 */
 	fnabs	fp1,fp1			/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq		/* Clear any FE_INEXACT exception */
+	mtfsf	0xff,fp11		/* Restore FE_INEXACT state.  */
 	blr
 END (__nearbyintf)
 
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S b/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
index 6654840f7f..9c87596cc4 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
@@ -40,19 +40,21 @@ EALIGN (__nearbyint, 4, 0)
 	fsub	fp12,fp13,fp13	/* generate 0.0 */
 	fcmpu	cr7,fp1,fp12	/* if (x > 0.0) */
 	ble	cr7, L(lessthanzero)
+	mffs	fp11
 	mtfsb0	4*cr7+lt	/* Disable FE_INEXACT exception */
 	fadd	fp1,fp1,fp13	/* x+= TWO52 */
 	fsub	fp1,fp1,fp13	/* x-= TWO52 */
 	fabs	fp1,fp1		/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq	/* Clear any FE_INEXACT exception */
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr			/* x = 0.0; */
 L(lessthanzero):
 	bgelr	cr7		/* if (x < 0.0) */
+	mffs	fp11
 	mtfsb0	4*cr7+lt
 	fsub	fp1,fp1,fp13	/* x -= TWO52 */
 	fadd	fp1,fp1,fp13	/* x += TWO52 */
 	fnabs	fp1,fp1		/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr			/* x = -0.0; */
 END (__nearbyint)
 
diff --git a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
index 041dfeb46e..9dfbce6b9c 100644
--- a/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
+++ b/sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S
@@ -41,19 +41,21 @@ EALIGN (__nearbyintf, 4, 0)
 	fsubs	fp12,fp13,fp13	/* generate 0.0 */
 	fcmpu	cr7,fp1,fp12	/* if (x > 0.0)  */
 	ble	cr7, L(lessthanzero)
+	mffs	fp11
 	mtfsb0	4*cr7+lt	/* Disable FE_INEXACT exception */
 	fadds	fp1,fp1,fp13	/* x += TWO23 */
 	fsubs	fp1,fp1,fp13	/* x -= TWO23 */
 	fabs	fp1,fp1		/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq	/* Clear pending FE_INEXACT exception */
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr			/* x = 0.0; */
 L(lessthanzero):
 	bgelr	cr7		/* if (x < 0.0) */
+	mffs	fp11
 	mtfsb0	4*cr7+lt	/* Disable FE_INEXACT exception */
 	fsubs	fp1,fp1,fp13	/* x -= TWO23 */
 	fadds	fp1,fp1,fp13	/* x += TWO23 */
 	fnabs	fp1,fp1		/* if (x == 0.0) */
-	mtfsb0	4*cr1+eq	/* Clear pending FE_INEXACT exception */
+	mtfsf	0xff,fp11	/* Restore FE_INEXACT state.  */
 	blr			/* x = -0.0; */
 END (__nearbyintf)