This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: Make strtod respect the rounding mode (bug 14518)
- From: Richard Henderson <rth at twiddle dot net>
- To: "Joseph S. Myers" <joseph at codesourcery dot com>
- Cc: libc-alpha at sourceware dot org, libc-ports at sourceware dot org, Andreas Krebbel <krebbel at linux dot vnet dot ibm dot com>,"Ryan S. Arnold" <ryan dot arnold at gmail dot com>, Mike Frysinger <vapier at gentoo dot org>,Carlos O'Donell <carlos at systemhalted dot org>
- Date: Thu, 30 Aug 2012 12:56:10 -0700
- Subject: Re: Make strtod respect the rounding mode (bug 14518)
- References: <Pine.LNX.4.64.1208292343190.30000@digraph.polyomino.org.uk>
On 08/29/2012 04:45 PM, Joseph S. Myers wrote:
> * This patch does not update the alpha port. alpha maintainers may
> wish to add a definition of _FPU_GETCW to fpu_control.h, or to add
> bits/rounding-mode.h for alpha (I don't know why its fpu_control.h
> doesn't define _FPU_GETCW when it has the other macros needed).
I'm not sure why we implement as much of fpu_control.h as we do.
It's somewhat unfortunate that it exists in its current form at
all, because it's all very biased toward binary compatibility with
the x86 fpcr format.
While I *could* commit a patch like the following, I'd like an
opinion on whether the existing defines could be trashed and the
file re-imagined as something more friendly for native. Given
of course that at present there cannot be any users since the
actual _FPU_G/SETCW macros do not exist.
Or whether the file should be trashed and I'll just implement
bits/rounding-mode.h. Which honestly seems like it'd be the
most efficient for the use in question.
r~
>From 6a480a617d97dec79140ff449197773c45714024 Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@twiddle.net>
Date: Thu, 30 Aug 2012 12:06:05 -0700
Subject: [PATCH] alpha: Implement _FPU_GETCW and _FPU_SETCW
---
ports/ChangeLog.alpha | 6 +++
ports/sysdeps/alpha/Makefile | 1 +
ports/sysdeps/alpha/fpu/Versions | 4 ++
ports/sysdeps/alpha/fpu/fpu_control.h | 15 ++++++-
ports/sysdeps/alpha/fpu/fpucw.c | 77 +++++++++++++++++++++++++++++++++++
5 files changed, 101 insertions(+), 2 deletions(-)
create mode 100644 ports/sysdeps/alpha/fpu/fpucw.c
diff --git a/ports/ChangeLog.alpha b/ports/ChangeLog.alpha
index 9589dd3..12bc4fb 100644
--- a/ports/ChangeLog.alpha
+++ b/ports/ChangeLog.alpha
@@ -1,5 +1,11 @@
2012-08-30 Richard Henderson <rth@redhat.com>
+ * sysdeps/alpha/fpu/fpucw.c: New file.
+ * sysdeps/alpha/Makefile [math] (sysdep_routines): Add it.
+ * sysdeps/alpha/fpu/fpu_control.h (__fpu_getcw): Declare.
+ (__fpu_setcw, _FPU_GETCW, _FPU_SETCW): Declare
+ * sysdeps/alpha/fpu/Versions (__fpu_getcw, __fpu_setcw): Add for 2.17.
+
* sysdeps/alpha/fpu/s_isnan.c: Define all aliases in terms of
the original __isnan symbol.
diff --git a/ports/sysdeps/alpha/Makefile b/ports/sysdeps/alpha/Makefile
index 1a80db8..75ad30e 100644
--- a/ports/sysdeps/alpha/Makefile
+++ b/ports/sysdeps/alpha/Makefile
@@ -43,6 +43,7 @@ CFLAGS-s_fma.c = -mieee-with-inexact
CFLAGS-s_fmaf.c = -mieee-with-inexact
# This test tries to check for inexact being raised by arithmetic.
CFLAGS-test-misc.c += -mieee-with-inexact
+sysdep_routines += fpucw
endif
# Build everything with full IEEE math support, and with dynamic rounding;
diff --git a/ports/sysdeps/alpha/fpu/Versions b/ports/sysdeps/alpha/fpu/Versions
index c9b0e03..ad4eae6 100644
--- a/ports/sysdeps/alpha/fpu/Versions
+++ b/ports/sysdeps/alpha/fpu/Versions
@@ -3,6 +3,10 @@ libc {
# functions used in other libraries
__ieee_get_fp_control; __ieee_set_fp_control;
}
+ GLIBC_2.17 {
+ # functions implementing fpu_control.h
+ __fpu_getcw; __fpu_setcw;
+ }
}
libm {
GLIBC_2.3.4 {
diff --git a/ports/sysdeps/alpha/fpu/fpu_control.h b/ports/sysdeps/alpha/fpu/fpu_control.h
index 4027300..68f06ef 100644
--- a/ports/sysdeps/alpha/fpu/fpu_control.h
+++ b/ports/sysdeps/alpha/fpu/fpu_control.h
@@ -1,5 +1,5 @@
/* FPU control word bits. Alpha-mapped-to-Intel version.
- Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Olaf Flebbe.
@@ -80,7 +80,6 @@
#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */
-
/* Now two recommended cw */
/* Linux default:
@@ -102,4 +101,16 @@ typedef unsigned int fpu_control_t;
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
+/* Internal functions for accessing the hardware control word. */
+extern fpu_control_t __fpu_getcw(void);
+extern void __fpu_setcw(fpu_control_t);
+
+/* The "standard" macros for accessing the hardware control word.
+ The x86 port which we are emulating uses __asm__ in these macros,
+ which implies the macro is syntactically a statement and not an
+ expression. Mirror this restriction here by wrapping the calls
+ within a do/while statement. */
+#define _FPU_GETCW(cw) do { (cw) = __fpu_getcw(); } while (0)
+#define _FPU_SETCW(cw) do { __fpu_setcw(cw); } while (0)
+
#endif /* _ALPHA_FPU_CONTROL */
diff --git a/ports/sysdeps/alpha/fpu/fpucw.c b/ports/sysdeps/alpha/fpu/fpucw.c
new file mode 100644
index 0000000..bcab24a
--- /dev/null
+++ b/ports/sysdeps/alpha/fpu/fpucw.c
@@ -0,0 +1,77 @@
+/* Manipulate the fpu environment in an x86 compatible way.
+ Copyright (C) 2012 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 <fpu_control.h>
+#include <fenv_libc.h>
+
+
+#define REPLACE(S, F, T) \
+ ((F) > (T) \
+ ? ((S) >> __builtin_ctzl((F) / (T))) & (T) \
+ : ((S) & (F)) << __builtin_ctzl((T) / (F)))
+
+fpu_control_t
+__fpu_getcw(void)
+{
+ unsigned long int fpcr, swcr, retl;
+
+ /* Get status from software and hardware. Note that we don't need an
+ excb because the callsys is an implied trap barrier. */
+ swcr = __ieee_get_fp_control ();
+ __asm__ __volatile__ ("mf_fpcr %0" : "=f" (fpcr));
+
+ /* Extract the rounding mode. */
+ retl = ((fpcr >> FPCR_ROUND_SHIFT) & 3) << 10;
+
+ /* Extract the Alpha "enabled" exceptions to x86 "masked" exceptions. */
+ retl |= REPLACE(~swcr, FE_INVALID >> SWCR_ENABLE_SHIFT, _FPU_MASK_IM);
+ retl |= REPLACE(~swcr, FE_DENORMAL >> SWCR_ENABLE_SHIFT, _FPU_MASK_DM);
+ retl |= REPLACE(~swcr, FE_DIVBYZERO >> SWCR_ENABLE_SHIFT, _FPU_MASK_ZM);
+ retl |= REPLACE(~swcr, FE_OVERFLOW >> SWCR_ENABLE_SHIFT, _FPU_MASK_OM);
+ retl |= REPLACE(~swcr, FE_UNDERFLOW >> SWCR_ENABLE_SHIFT, _FPU_MASK_UM);
+ retl |= REPLACE(~swcr, FE_INEXACT >> SWCR_ENABLE_SHIFT, _FPU_MASK_PM);
+
+ return retl;
+}
+
+void
+__fpu_setcw(fpu_control_t cw)
+{
+ unsigned long int fpcr, swcr, cwl = cw;
+
+ /* Get status from software and hardware. Note that we don't need an
+ excb because the callsys is an implied trap barrier. */
+ swcr = __ieee_get_fp_control ();
+ __asm__ __volatile__ ("mf_fpcr %0" : "=f" (fpcr));
+
+ fpcr &= ~FPCR_ROUND_MASK;
+ fpcr |= ((cwl >> 10) & 3ul) << FPCR_ROUND_SHIFT;
+
+ swcr &= ~SWCR_ENABLE_MASK;
+ swcr |= REPLACE(~cwl, _FPU_MASK_IM, FE_INVALID >> SWCR_ENABLE_SHIFT);
+ swcr |= REPLACE(~cwl, _FPU_MASK_DM, FE_DENORMAL >> SWCR_ENABLE_SHIFT);
+ swcr |= REPLACE(~cwl, _FPU_MASK_ZM, FE_DIVBYZERO >> SWCR_ENABLE_SHIFT);
+ swcr |= REPLACE(~cwl, _FPU_MASK_OM, FE_OVERFLOW >> SWCR_ENABLE_SHIFT);
+ swcr |= REPLACE(~cwl, _FPU_MASK_UM, FE_UNDERFLOW >> SWCR_ENABLE_SHIFT);
+ swcr |= REPLACE(~cwl, _FPU_MASK_PM, FE_INEXACT >> SWCR_ENABLE_SHIFT);
+
+ /* Install the new rounding mode and exception enable mask. Note that
+ the system call is the implied trap barrier for our modification. */
+ __asm__ __volatile__ ("mt_fpcr %0" : : "f" (fpcr));
+ __ieee_set_fp_control (swcr);
+}
--
1.7.11.4