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]

[PATCH] PowerPC: Extend fpu fenv operations to operate on 64-bit FPSCR


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)

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