This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Make strtod respect the rounding mode (bug 14518)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]