aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c109
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_rintl.c14
-rw-r--r--sysdeps/powerpc/fpu/fenv_private.h4
4 files changed, 32 insertions, 109 deletions
diff --git a/ChangeLog b/ChangeLog
index 73a49a06e0..a6be76213e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2016-03-09 Joseph Myers <joseph@codesourcery.com>
+
+ [BZ #19790]
+ * sysdeps/ieee754/ldbl-128ibm/s_rintl.c [USE_AS_NEARBYINTL]
+ (rintl): Define as macro.
+ [USE_AS_NEARBYINTL] (__rintl): Likewise.
+ (__rintl) [USE_AS_NEARBYINTL]: Use SET_RESTORE_ROUND_NOEX instead
+ of fesetround. Ensure results are evaluated before end of scope.
+ * sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c: Define
+ USE_AS_NEARBYINTL and include s_rintl.c.
+ * sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc):
+ Disable exception traps in new environment.
+ (libc_feholdsetround_ppc_ctx): Likewise.
+
2016-03-08 Roland McGrath <roland@hack.frob.com>
* sysdeps/x86_64/tst-audit10.c: #include <cpu-features.h>.
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
index 08134edd10..dfdefe3f02 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_nearbyintl.c
@@ -17,110 +17,5 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-/* This has been coded in assembler because GCC makes such a mess of it
- when it's coded in C. */
-
-#include <math.h>
-#include <math_private.h>
-#include <fenv.h>
-#include <math_ldbl_opt.h>
-#include <float.h>
-#include <ieee754.h>
-
-
-long double
-__nearbyintl (long double x)
-{
- fenv_t env;
- static const long double TWO52 = 4503599627370496.0L;
- union ibm_extended_long_double u;
- u.ld = x;
-
- if (!isfinite (u.d[0].d))
- return x;
- else if (fabs (u.d[0].d) < TWO52)
- {
- double xh = u.d[0].d;
- double high = u.d[0].d;
- feholdexcept (&env);
- if (high > 0.0)
- {
- high += TWO52;
- high -= TWO52;
- if (high == -0.0) high = 0.0;
- }
- else if (high < 0.0)
- {
- high -= TWO52;
- high += TWO52;
- if (high == 0.0) high = -0.0;
- }
- if (u.d[1].d > 0.0 && (xh - high == 0.5))
- high += 1.0;
- else if (u.d[1].d < 0.0 && (-(xh - high) == 0.5))
- high -= 1.0;
- u.d[0].d = high;
- u.d[1].d = 0.0;
- math_force_eval (u.d[0]);
- math_force_eval (u.d[1]);
- fesetenv (&env);
- }
- else if (fabs (u.d[1].d) < TWO52 && u.d[1].d != 0.0)
- {
- double high = u.d[0].d, low = u.d[1].d, tau;
- /* In this case we have to round the low double and handle any
- adjustment to the high double that may be caused by rounding
- (up). This is complicated by the fact that the high double
- may already be rounded and the low double may have the
- opposite sign to compensate. */
- feholdexcept (&env);
- if (u.d[0].d > 0.0)
- {
- if (u.d[1].d > 0.0)
- {
- /* If the high/low doubles are the same sign then simply
- round the low double. */
- }
- else if (u.d[1].d < 0.0)
- {
- /* Else the high double is pre rounded and we need to
- adjust for that. */
-
- tau = __nextafter (u.d[0].d, 0.0);
- tau = (u.d[0].d - tau) * 2.0;
- high -= tau;
- low += tau;
- }
- low += TWO52;
- low -= TWO52;
- }
- else if (u.d[0].d < 0.0)
- {
- if (u.d[1].d < 0.0)
- {
- /* If the high/low doubles are the same sign then simply
- round the low double. */
- }
- else if (u.d[1].d > 0.0)
- {
- /* Else the high double is pre rounded and we need to
- adjust for that. */
- tau = __nextafter (u.d[0].d, 0.0);
- tau = (u.d[0].d - tau) * 2.0;
- high -= tau;
- low += tau;
- }
- low = TWO52 - low;
- low = -(low - TWO52);
- }
- u.d[0].d = high + low;
- u.d[1].d = high - u.d[0].d + low;
- math_force_eval (u.d[0]);
- math_force_eval (u.d[1]);
- fesetenv (&env);
- }
-
- return u.ld;
-}
-
-long_double_symbol (libm, __nearbyintl, nearbyintl);
+#define USE_AS_NEARBYINTL
+#include "s_rintl.c"
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_rintl.c b/sysdeps/ieee754/ldbl-128ibm/s_rintl.c
index 8c51ded1d6..e4af01c9a0 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_rintl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_rintl.c
@@ -26,6 +26,11 @@
#include <float.h>
#include <ieee754.h>
+#ifdef USE_AS_NEARBYINTL
+# define rintl nearbyintl
+# define __rintl __nearbyintl
+#endif
+
long double
__rintl (long double x)
@@ -44,7 +49,11 @@ __rintl (long double x)
/* Long double arithmetic, including the canonicalisation below,
only works in round-to-nearest mode. */
+#ifdef USE_AS_NEARBYINTL
+ SET_RESTORE_ROUND_NOEX (FE_TONEAREST);
+#else
fesetround (FE_TONEAREST);
+#endif
/* Convert the high double to integer. */
orig_xh = xh;
@@ -103,7 +112,12 @@ __rintl (long double x)
if (orig_xh < 0.0)
xh = -__builtin_fabs (xh);
+#ifdef USE_AS_NEARBYINTL
+ math_force_eval (xh);
+ math_force_eval (xl);
+#else
fesetround (save_round);
+#endif
}
return ldbl_pack (xh, xl);
diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h
index e1b02a3f80..02ac980909 100644
--- a/sysdeps/powerpc/fpu/fenv_private.h
+++ b/sysdeps/powerpc/fpu/fenv_private.h
@@ -146,7 +146,7 @@ libc_feholdsetround_ppc (fenv_t *e, int r)
old.fenv = fegetenv_register ();
/* Clear current precision and set newer one. */
- new.l = (old.l & ~0x3) | r;
+ new.l = (old.l & ~0x3 & ~_FPU_MASK_ALL) | r;
*e = old.fenv;
if ((old.l & _FPU_MASK_ALL) != 0)
@@ -240,7 +240,7 @@ libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r)
fenv_union_t old, new;
old.fenv = fegetenv_register ();
- new.l = (old.l & ~0x3) | r;
+ new.l = (old.l & ~0x3 & ~_FPU_MASK_ALL) | r;
ctx->env = old.fenv;
if (__glibc_unlikely (new.l != old.l))
{