This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] PowerPC: Extend fpu fenv operations to operate on 64-bit FPSCR
- From: "Ryan S. Arnold" <rsa at us dot ibm dot com>
- To: libc-alpha <libc-alpha at sourceware dot org>
- Date: Mon, 22 Oct 2007 10:26:22 -0500
- Subject: [PATCH] PowerPC: Extend fpu fenv operations to operate on 64-bit FPSCR
- Reply-to: rsa at us dot ibm dot com
Greetings,
The included patch provides the following changes to extend the FPSCR
(floating point status and control register) to 64-bits for PowerPC
POWER6 and POWER6x:
o For PowerPC in general it redefines fpu_control_t from an unsigned
long int to an unsigned long long int so that the entire 64-bit FPSCR on
POWER6 can be saved/restored. On non-POWER6 hardware the high-order
32-bits are simply discarded/ignored for all operations.
It is necessary to change it for all PowerPC because the loader is
built as the default PowerPC arch (i.e. non-POWER6) and uses the
rtld_global_ro struct which contains an fpu_control_t and therefore must
be able to load a libc built for POWER6 or non-POWER6 (which also uses
the rtld_global_ro struct).
Any difference in size of fpu_control_t between the loader and libc
will cause libc to access rtld_global_ro struct members at the wrong
offsets from where the structure was populated by the loader.
The impact is minimal since currently the fpu_control_t is initially
populated from a double anyway and the fpu_control_t type is not used
dynamically in any external function and thus, no symbol versioning is
required.
o Provides a conditional implementation of _FPU_GETCW and _FPU_SETCW
which operate on either the entire 64-bit FPSCR on POWER6[x] or simply
the low-order 32-bits of the fpu_control_t on non-POWER6[x].
o Provides granular control over the high order 32 bits of the FPSCR
that aren't reserved.
o Provides an overridden sysdeps/powerpc/math/test-fpucw that verifies
that the high-order word is saved to the FPSCR and restored using the
_FPU_[GET|SET]CW macros. It also verifies that there are no deleterious
effects on non-POWER6 systems.
o Provides conditional definitions of the PowerPC fenv helper macros
(fesetenv_register & fegetenv_register) which are used by the fenv
functions to set/get the contents of the FPSCR.
o Provides sysdeps/powerpc/math/test-powerpc-fenv which tests the
high-order word save/restore using the fe[set|get]env_register
functions.
o Replaces the FPSCR restore with a macro which will provide a 64-bit
restore on POWER6 for swapcontext and setcontext.
o Replaces some of the magic number fenv masks in the fenv functions
with a define that better describes what the magic number means.
I successfully executed build and runtime tests (make check) on POWER5
(32-bit FPSCR) as well as POWER6 (64-bit FPSCR).
Ryan S. Arnold
IBM Linux Technology Center
Linux Toolchain Development
2007-10-22 Ryan S. Arnold <rsa@us.ibm.com>
* sysdeps/mach/hurd/powerpc/sigreturn.c: Enable 64-bit FPSCR restore
on POWER6.
* sysdeps/powerpc/fpscr.h: (_RESTORE_FPSCR) New file that adds a
macro which will either use the default two operand mtfsf instruction
or the new four operand mtfsf instruction (on POWER6 and POWER6x).
* sysdeps/powerpc/fpu/Implies: Add sysdeps/powerpc/math as an Implies
file in order to add it to the search path to be able to override
math/test-fpucw.c for PowerPC.
* sysdeps/powerpc/fpu/feholdexcpt.c (_FPU_MASK_ALL): provide macro to
eliminate magic number (0x000000F8) which represents a mask of all of
the floating point exception enable bits.
* sysdeps/powerpc/fpu/fenv_libc.h (fesetenv_register): Provides a
_ARCH_PWR6 || _ARCH_PWR6X conditional macro to restore the entire
64-bit FPSCR on POWER6.
(relax_fenv_state): Provides a _ARCH_PWR6 || _ARCH_PWR6X conditional
macro to return the decimal rounding mode to the default 'round to
nearest, ties to zero' on POWER6[X] per the POWER ISA.
(FPSCR_NI FPSCR_29): Conditionaly replace FPSCR_NI bit definition
with FPSCR_29 for _ARCH_PWR6 || _ARCH_PWR6X since non-IEEE is not
supported on POWER6 and POWER6X (i.e. it is marked Reserved).
* sysdeps/powerpc/fpu/fesetenv.c (_FPU_MASK_ALL): provide macro to
eliminate magic number (0x000000F8) which represents a mask of all of
the floating point exception enable bits.
* sysdeps/powerpc/fpu/feupdateenv.c (_FPU_MASK_ALL): provide macro to
eliminate magic number (0x000000F8) which represents a mask of all of
the floating point exception enable bits.
* sysdeps/powerpc/fpu/fpu_control.h (_FPU_DEC_RC_*): Add bit masks to
allow the setting of the decimal rounding modes per POWER6 ISA 2.05 in
the high-order 32-bits of the 64-bit FPSCR.
(fpu_control_t): Redefine fpu_control_t unsigned long long int and
double word align it for all PowerPC.
(_FPU_GETCW _FPU_SETCW): Provides an _ARCH_PWR6 || _ARCH_PWR6X
conditional macro for _FPU_GETCW and _FPU_SETCW to get and set the
entire 64-bit FPSCR on POWER6.
(_FPU_MASK_NI): Conditionally defines _FPU_MASK_NI as 0x0 on POWER6
and POWER6X because it isn't supported by the architecture.
(_FPU_RESERVED): Conditionally defines _FPU_RESERVED on POWER6 and
POWER6X to reserve bits 0:29 of the high order word as well as the
normal reserved bits in the low order word of the FPSCR.
* sysdeps/powerpc/math/Makefile: Add new test 'test-powerpc-fenv' to
libm-tests.
* sysdeps/powerpc/math/test-fpucw.c: Provides a PowerPC based override
test which allows for an unsigned long long int control word mask.
Also provides test of _FPU_GETCW and _FPUSETCW working against a
64-bit or 32-bit FPSCR.
* sysdeps/powerpc/math/test-powerpc-fenv.c: New test to verify the
efficacy of fesetenv_register() and fegetenv_register() in getting
and setting the high-order word of the 64-bit FPSCR, or in ignoring the
high-order word when acting against the 32-bit FPSCR.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S
(__CONTEXT_FUNC_NAME) : replace mtfsf insn with _RESTORE_FPSCR macro
which will conditionally operate on 32-bit or 64-bit FPSCR.
* sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S
(__CONTEXT_FUNC_NAME) : replace mtfsf insn with _RESTORE_FPSCR macro
which will conditionally operate on 32-bit or 64-bit FPSCR.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
(__novec_setcontext __setcontext) : replace mtfsf insns with
_RESTORE_FPSCR macro which will conditionally operate on 32-bit or
64-bit FPSCR.
* sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
(__novec_swapcontext __swapcontext) : replace mtfsf insns with
_RESTORE_FPSCR macro which will conditionally operate on 32-bit or
64-bit FPSCR.
--- glibc.orig/sysdeps/mach/hurd/powerpc/sigreturn.c 2001-11-09 18:37:47.000000000 -0600
+++ glibc.new/sysdeps/mach/hurd/powerpc/sigreturn.c 2007-10-09 12:14:06.000000000 -0500
@@ -1,5 +1,5 @@
/* Return from signal handler for Hurd. PowerPC version.
- Copyright (C) 1996,97,98,2001 Free Software Foundation, Inc.
+ Copyright (C) 1996,97,98,2001,2007 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
@@ -91,7 +91,11 @@
/* Restore the floating-point control/status register. */
asm volatile ("lfd 0,256(31)");
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ asm volatile ("mtfsf 0xff,0,1,0");
+#else
asm volatile ("mtfsf 0xff,0");
+#endif
/* Restore floating-point registers. */
restore_fpr (0);
--- glibc.orig/sysdeps/powerpc/fpscr.h 1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpscr.h 2007-10-02 21:23:59.000000000 -0500
@@ -0,0 +1,30 @@
+/* Macro to restore the entire FPSCR, short and long form.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by IBM Corporation,
+ Author(s): Ryan S. Arnold <rsa@us.ibm.com>
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ /* On Power6[x] four operands are required with the 'L' field
+ * equal to '1' in order to copy the entirety of 'reg' into the
+ * full 64-bit wide FPSCR. The field mask and 'W' field are
+ * ignored when L is '1'. */
+ #define _RESTORE_FPSCR(reg) mtfsf 0xff, (reg), 1, 0
+#else
+ #define _RESTORE_FPSCR(reg) mtfsf 0xff, (reg)
+#endif
--- glibc.orig/sysdeps/powerpc/fpu/Implies 1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/Implies 2007-10-05 12:22:03.000000000 -0500
@@ -0,0 +1 @@
+powerpc/math
--- glibc.orig/sysdeps/powerpc/fpu/feholdexcpt.c 2007-05-07 01:21:41.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/feholdexcpt.c 2007-10-09 12:06:18.000000000 -0500
@@ -1,5 +1,5 @@
/* Store current floating-point environment and clear exceptions.
- Copyright (C) 1997, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2005, 2007 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
@@ -18,6 +18,8 @@
02111-1307 USA. */
#include <fenv_libc.h>
+#include <fpu_control.h>
+#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
int
feholdexcept (fenv_t *envp)
@@ -35,7 +37,7 @@
/* If the old env had any eabled exceptions, then mask SIGFPE in the
MSR FE0/FE1 bits. This may allow the FPU to run faster because it
always takes the default action and can not generate SIGFPE. */
- if ((old.l[1] & 0x000000F8) != 0)
+ if ((old.l[1] & _FPU_MASK_ALL) != 0)
(void)__fe_mask_env ();
/* Put the new state in effect. */
--- glibc.orig/sysdeps/powerpc/fpu/fenv_libc.h 2006-03-16 05:46:34.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/fenv_libc.h 2007-10-08 13:15:59.000000000 -0500
@@ -1,5 +1,5 @@
/* Internal libc stuff for floating point environment routines.
- Copyright (C) 1997, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2006, 2007 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
@@ -30,9 +30,15 @@
#define fegetenv_register() \
({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; })
+/* Power6[x] provides a 64-bit FPSCR. */
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+#define fesetenv_register(env) \
+ ({ double d = (env); asm volatile ("mtfsf 0xff,%0,1,0" : : "f" (d)); })
+#else
/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */
#define fesetenv_register(env) \
({ double d = (env); asm volatile ("mtfsf 0xff,%0" : : "f" (d)); })
+#endif
/* This very handy macro:
- Sets the rounding mode to 'round to nearest';
@@ -40,7 +46,13 @@
- Prevents exceptions from being raised for inexact results.
These things happen to be exactly what you need for typical elementary
functions. */
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+/* - Sets the decimal rounding mode to 'round to nearest'; */
+#define relax_fenv_state() \
+ ({ asm ("mtfsfi 7,0,1"); asm("mtfsfi 7,0"); })
+#else
#define relax_fenv_state() asm ("mtfsfi 7,0")
+#endif
/* Set/clear a particular FPSCR bit (for instance,
reset_fpscr_bit(FPSCR_VE);
@@ -120,7 +132,11 @@
FPSCR_UE, /* underflow exception enable */
FPSCR_ZE, /* zero divide exception enable */
FPSCR_XE, /* inexact exception enable */
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ FPSCR_29, /* Reserved */
+#else
FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */
+#endif
/* the remaining two least-significant bits keep the rounding mode */
};
--- glibc.orig/sysdeps/powerpc/fpu/fesetenv.c 2007-05-07 01:22:06.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/fesetenv.c 2007-10-08 14:09:12.000000000 -0500
@@ -18,8 +18,11 @@
02111-1307 USA. */
#include <fenv_libc.h>
+#include <fpu_control.h>
#include <bp-sym.h>
+#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
+
int
__fesetenv (const fenv_t *envp)
{
@@ -29,18 +32,18 @@
new.fenv = *envp;
old.fenv = fegetenv_register ();
- /* If the old env has no eabled exceptions and the new env has any enabled
- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put
- the hardware into "precise mode" and may cause the FPU to run slower on
- some hardware. */
- if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
+ /* If the old env has no enabled exceptions and the new env has any enabled
+ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the
+ hardware into "precise mode" and may cause the FPU to run slower on some
+ hardware. */
+ if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0)
(void)__fe_nomask_env ();
/* If the old env had any eabled exceptions and the new env has no enabled
exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
FPU to run faster because it always takes the default action and can not
generate SIGFPE. */
- if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
+ if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0)
(void)__fe_mask_env ();
fesetenv_register (*envp);
--- glibc.orig/sysdeps/powerpc/fpu/feupdateenv.c 2007-05-07 01:22:29.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/feupdateenv.c 2007-10-08 14:37:04.000000000 -0500
@@ -19,8 +19,11 @@
02111-1307 USA. */
#include <fenv_libc.h>
+#include <fpu_control.h>
#include <bp-sym.h>
+#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM)
+
int
__feupdateenv (const fenv_t *envp)
{
@@ -39,14 +42,14 @@
exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put
the hardware into "precise mode" and may cause the FPU to run slower on
some hardware. */
- if ((old.l[1] & 0x000000F8) == 0 && (new.l[1] & 0x000000F8) != 0)
+ if ((old.l[1] & _FPU_MASK_ALL) == 0 && (new.l[1] & _FPU_MASK_ALL) != 0)
(void)__fe_nomask_env ();
/* If the old env had any eabled exceptions and the new env has no enabled
exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the
FPU to run faster because it always takes the default action and can not
generate SIGFPE. */
- if ((old.l[1] & 0x000000F8) != 0 && (new.l[1] & 0x000000F8) == 0)
+ if ((old.l[1] & _FPU_MASK_ALL) != 0 && (new.l[1] & _FPU_MASK_ALL) == 0)
(void)__fe_mask_env ();
/* Atomically enable and raise (if appropriate) exceptions set in `new'. */
--- glibc.orig/sysdeps/powerpc/fpu/fpu_control.h 2003-02-27 14:57:06.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/fpu_control.h 2007-10-08 14:43:02.000000000 -0500
@@ -1,5 +1,5 @@
/* FPU control word definitions. PowerPC version.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 2007 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
@@ -20,14 +20,12 @@
#ifndef _FPU_CONTROL_H
#define _FPU_CONTROL_H
-/* rounding control */
+/* binary float rounding control */
#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */
#define _FPU_RC_DOWN 0x03
#define _FPU_RC_UP 0x02
#define _FPU_RC_ZERO 0x01
-#define _FPU_MASK_NI 0x04 /* non-ieee mode */
-
/* masking of interrupts */
#define _FPU_MASK_ZM 0x10 /* zero divide */
#define _FPU_MASK_OM 0x40 /* overflow */
@@ -35,33 +33,76 @@
#define _FPU_MASK_XM 0x08 /* inexact */
#define _FPU_MASK_IM 0x80 /* invalid operation */
-#define _FPU_RESERVED 0xffffff00 /* These bits are reserved are not changed. */
+/* decimal float rounding control */
+#define _FPU_DEC_RC_NEAREST 0x0000000000000000ULL
+#define _FPU_DEC_RC_TOWARDZERO 0x0000000100000000ULL
+#define _FPU_DEC_RC_UPWARD 0x0000000200000000ULL
+#define _FPU_DEC_RC_DOWNWARD 0x0000000300000000ULL
+#define _FPU_DEC_RC_NEARESTFROMZERO 0x0000000400000000ULL
+
+/* The following Decimal Rounding Modes are supported by Power6[x] hardware
+ * but don't have corresponding C-Spec rounding modes. */
+#define _FPU_DEC_RC_NEARESTTOWARDZERO 0x0000000500000000ULL
+#define _FPU_DEC_RC_FROMZERO 0x0000000600000000ULL
+#define _FPU_DEC_RC_PREPAREFORSHORTERPRECISION 0x0000000700000000ULL
/* The fdlibm code requires no interrupts for exceptions. */
-#define _FPU_DEFAULT 0x00000000 /* Default value. */
+#define _FPU_DEFAULT 0x0000000000000000ULL /* Default value. */
-/* IEEE: same as above, but (some) exceptions;
+/* IEEE: same as above, but (some) exceptions enabled;
we leave the 'inexact' exception off.
*/
-#define _FPU_IEEE 0x000000f0
+#define _FPU_IEEE 0x00000000000000f0ULL
+
+/* Type of the control word. The __DI__ mode is here to force alignment. */
+typedef unsigned long long fpu_control_t __attribute__ ((__mode__ (__DI__)));
+
+/* Power6[x] provides a 64-bit FPSCR with decimal rounding modes. */
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+
+/* Not available on Power6[x]. We no-op it for forward porting
+ * compatibility since it is valid on some PowerPC processors. */
+#define _FPU_MASK_NI 0x0000000000000000ULL /* non-ieee mode */
+
+/* Note: The Non-IEEE Mode is NOT available on Power6. */
+#define _FPU_RESERVED 0xfffffff8ffffff04ULL
+
+/* Macros for accessing the hardware control word on Power6[x]. */
+#define _FPU_GETCW(__cw) ({ \
+ union { double d; fpu_control_t cw; } \
+ tmp __attribute__ ((__aligned__(8))); \
+ __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
+ (__cw)=tmp.cw; \
+})
+#define _FPU_SETCW(__cw) ({ \
+ union { double d; fpu_control_t cw; } \
+ tmp __attribute__ ((__aligned__(8))); \
+ tmp.cw = __cw; \
+ /* Set the entire 64-bit FPSCR. */ \
+ __asm__ ("lfd%U0 0,%0; mtfsf 255,0,1,0" : : "m" (tmp.d) : "fr0"); \
+})
+#else
+
+#define _FPU_MASK_NI 0x04 /* non-ieee mode */
-/* Type of the control word. */
-typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
+/* Bits 29:31 left un-reserved for soft-decimal float rounding direction. */
+#define _FPU_RESERVED 0xfffffff8ffffff00ULL
/* Macros for accessing the hardware control word. */
-#define _FPU_GETCW(__cw) ( { \
- union { double d; fpu_control_t cw[2]; } \
- tmp __attribute__ ((__aligned__(8))); \
- __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
- (__cw)=tmp.cw[1]; \
- tmp.cw[1]; } )
-#define _FPU_SETCW(__cw) { \
- union { double d; fpu_control_t cw[2]; } \
- tmp __attribute__ ((__aligned__(8))); \
- tmp.cw[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \
- tmp.cw[1] = __cw; \
- __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \
-}
+#define _FPU_GETCW(__cw) ({ \
+ union { double d; fpu_control_t cw; } \
+ tmp __attribute__ ((__aligned__(8))); \
+ __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \
+ (__cw)=tmp.cw; \
+})
+#define _FPU_SETCW(__cw) ({ \
+ union { double d; fpu_control_t cw; } \
+ tmp __attribute__ ((__aligned__(8))); \
+ tmp.cw = __cw; \
+ /* Effectively ignores the high 32 bits. */ \
+ __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \
+})
+#endif
/* Default control word set at startup. */
extern fpu_control_t __fpu_control;
--- glibc.orig/sysdeps/powerpc/math/Makefile 1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/math/Makefile 2007-10-08 14:50:54.000000000 -0500
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+libm-tests = test-powerpc-fenv
+endif
--- glibc.orig/sysdeps/powerpc/math/test-fpucw.c 1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/math/test-fpucw.c 2007-10-08 15:08:39.000000000 -0500
@@ -0,0 +1,76 @@
+/* Test to verify proper save and restore of 64-bit fpu control word.
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by IBM Corporation, 2007.
+ Author(s): Ryan S. Arnold <rsa@us.ibm.com>
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fpu_control.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+#ifdef _FPU_GETCW
+ fpu_control_t cw;
+ _FPU_GETCW (cw);
+
+ cw &= ~_FPU_RESERVED;
+
+ if (cw != (_FPU_DEFAULT & ~_FPU_RESERVED))
+ {
+ printf ("control word is 0x%.16llx but should be 0x%.16llx.\n",
+ (unsigned long long int) cw,
+ (unsigned long long int) (_FPU_DEFAULT & ~_FPU_RESERVED));
+ return 1;
+ }
+
+ cw |= (_FPU_DEC_RC_TOWARDZERO | _FPU_RC_DOWN);
+ _FPU_SETCW(cw);
+ _FPU_GETCW(cw);
+
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ /* Make sure the high order bits are saved and restored. */
+ if (cw != ((_FPU_DEFAULT & ~_FPU_RESERVED)
+ | _FPU_DEC_RC_TOWARDZERO
+ | _FPU_RC_DOWN))
+ {
+ printf ("control word is 0x%.16llx but should be 0x%.16llx.\n",
+ (unsigned long long int) cw,
+ (unsigned long long int) ((_FPU_DEFAULT & ~_FPU_RESERVED)
+ | _FPU_DEC_RC_TOWARDZERO
+ | _FPU_RC_DOWN));
+ return 1;
+ }
+#else
+ /* Make sure the high order bits are discarded. */
+ if (cw != ((_FPU_DEFAULT & ~_FPU_RESERVED & ~_FPU_DEC_RC_TOWARDZERO)
+ | _FPU_RC_DOWN))
+ {
+ printf ("control word is 0x%.16llx but should be 0x%.16llx.\n",
+ (unsigned long long int) cw,
+ (unsigned long long int) ((_FPU_DEFAULT
+ & ~_FPU_RESERVED
+ & ~_FPU_DEC_RC_TOWARDZERO)
+ | _FPU_RC_DOWN));
+ return 1;
+ }
+#endif
+#endif /* _FPU_GETCW */
+ return 0;
+}
--- glibc.orig/sysdeps/powerpc/math/test-powerpc-fenv.c 1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/math/test-powerpc-fenv.c 2007-10-09 11:57:54.000000000 -0500
@@ -0,0 +1,85 @@
+/* Tests to verify proper behavior of internal fenv functions which operate
+ directly upon the 32 or 64 bit FPSCR.
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by IBM Corporation, 2007.
+ Author(s): Ryan S. Arnold <rsa@us.ibm.com>
+
+ 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fenv_libc.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+ fenv_union_t fe;
+ fenv_union_t orig;
+ orig.fenv = fegetenv_register();
+ fe.fenv = fegetenv_register();
+
+ /* Set a decimal float rounding mode in the high order word. */
+ fe.l[0] |= 0x01;
+
+ fesetenv_register(fe.fenv);
+ fe.fenv = fegetenv_register();
+
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ /* Make sure the high order bits are saved to the FPSCR and restored. */
+ if (fe.l[0] != (orig.l[0] | 0x01))
+ {
+ printf ("fenv_t highword is 0x%.8x but should be 0x%.8x.\n",
+ (unsigned int) fe.l[0],
+ (unsigned int) (orig.l[0] | 0x01));
+ return 1;
+ }
+#else
+ /* Make sure the high order bits are discarded. */
+ if (fe.l[0] != (orig.l[0] & ~0x01))
+ {
+ printf ("fenv_t highword is 0x%.8x but should be 0x%.8x.\n",
+ (unsigned int) fe.l[0],
+ (unsigned int) (orig.l[0] & ~0x01));
+ return 1;
+ }
+#endif
+
+ relax_fenv_state();
+ fe.fenv = fegetenv_register();
+
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+ /* Make sure the decimal rounding mode triple is 0x0 since '000' is decimal
+ * round to nearest. */
+ if (fe.l[0] != 0x00)
+ {
+ printf ("fenv_t highword is 0x%.8x but should be 0x%.8x.\n",
+ (unsigned int) fe.l[0],
+ (unsigned int) 0x0);
+ return 1;
+ }
+#else
+ /* Make sure the high order word is empty. */
+ if (fe.l[0] != 0x0)
+ {
+ printf ("fenv_t highword is 0x%.8x but should be 0x%.8x.\n",
+ (unsigned int) fe.l[0],
+ (unsigned int) 0x0);
+ return 1;
+ }
+#endif
+ return 0;
+}
--- glibc.orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S 2006-03-16 05:48:55.000000000 -0600
+++ glibc.new/sysdeps/unix/sysv/linux/powerpc/powerpc32/setcontext-common.S 2007-10-09 12:08:40.000000000 -0500
@@ -1,5 +1,5 @@
/* Jump to a new context powerpc32 common.
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007 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
@@ -27,6 +27,8 @@
Any archecture that implements the Vector unit is assumed to also
implement the floating unit. */
+#include <fpscr.h>
+
/* Stack frame offsets. */
#define _FRAME_BACKCHAIN 0
#define _FRAME_LR_SAVE 4
@@ -199,7 +201,7 @@
/* Restore the floating-point registers */
lfd fp31,_UC_FREGS+(32*8)(r31)
lfd fp0,_UC_FREGS+(0*8)(r31)
- mtfsf 0xff,fp31
+ _RESTORE_FPSCR (fp31)
lfd fp1,_UC_FREGS+(1*8)(r31)
lfd fp2,_UC_FREGS+(2*8)(r31)
lfd fp3,_UC_FREGS+(3*8)(r31)
--- glibc.orig/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S 2006-01-06 21:56:26.000000000 -0600
+++ glibc.new/sysdeps/unix/sysv/linux/powerpc/powerpc32/swapcontext-common.S 2007-10-09 12:08:50.000000000 -0500
@@ -1,5 +1,5 @@
/* Save current context and jump to a new context.
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007 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
@@ -27,6 +27,8 @@
Any archecture that implements the Vector unit is assumed to also
implement the floating unit. */
+#include <fpscr.h>
+
/* Stack frame offsets. */
#define _FRAME_BACKCHAIN 0
#define _FRAME_LR_SAVE 4
@@ -425,7 +427,7 @@
/* Restore the floating-point registers */
lfd fp31,_UC_FREGS+(32*8)(r31)
lfd fp0,_UC_FREGS+(0*8)(r31)
- mtfsf 0xff,fp31
+ _RESTORE_FPSCR (fp31)
lfd fp1,_UC_FREGS+(1*8)(r31)
lfd fp2,_UC_FREGS+(2*8)(r31)
lfd fp3,_UC_FREGS+(3*8)(r31)
--- glibc.orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S 2006-03-16 05:48:54.000000000 -0600
+++ glibc.new/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S 2007-10-09 12:09:25.000000000 -0500
@@ -1,5 +1,5 @@
/* Switch to context.
- Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 04, 05, 06, 07 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
@@ -27,6 +27,8 @@
#include "ucontext_i.h"
#include <asm/errno.h>
+#include <fpscr.h>
+
#if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
ENTRY(__novec_setcontext)
CALL_MCOUNT 1
@@ -65,7 +67,7 @@
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
- mtfsf 0xff,fp0
+ _RESTORE_FPSCR (fp0)
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
@@ -346,7 +348,7 @@
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
- mtfsf 0xff,fp0
+ _RESTORE_FPSCR (fp0)
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
--- glibc.orig/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S 2006-03-16 05:48:54.000000000 -0600
+++ glibc.new/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S 2007-10-09 12:09:39.000000000 -0500
@@ -1,5 +1,5 @@
/* Save current context and install the given one.
- Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 04, 05, 06, 07 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
@@ -27,6 +27,8 @@
#include "ucontext_i.h"
#include <asm/errno.h>
+#include <fpscr.h>
+
#if SHLIB_COMPAT (libc, GLIBC_2_3, GLIBC_2_3_4)
ENTRY(__novec_swapcontext)
CALL_MCOUNT 2
@@ -160,7 +162,7 @@
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
- mtfsf 0xff,fp0
+ _RESTORE_FPSCR (fp0)
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)
@@ -646,7 +648,7 @@
lfd fp0,(SIGCONTEXT_FP_REGS+(32*8))(r31)
lfd fp31,(SIGCONTEXT_FP_REGS+(PT_R31*8))(r31)
lfd fp30,(SIGCONTEXT_FP_REGS+(PT_R30*8))(r31)
- mtfsf 0xff,fp0
+ _RESTORE_FPSCR (fp0)
lfd fp29,(SIGCONTEXT_FP_REGS+(PT_R29*8))(r31)
lfd fp28,(SIGCONTEXT_FP_REGS+(PT_R28*8))(r31)
lfd fp27,(SIGCONTEXT_FP_REGS+(PT_R27*8))(r31)