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: [PATCH] PowerPC: Extend fpu fenv operations to operate on 64-bit FPSCR


On Tue, 2007-10-30 at 17:18 -0500, Ryan S. Arnold wrote:

> Hi Ulrich,
> 
> This error is due to an overly simplistic test-case expectation on my
> part but the underlying new FPSCR code is still sound.  I found the same
> issue in my new test-powerpc-fenv testcase.
> 
> On the pre-POWER6 series of hardware (POWER5, et al) the high order word
> of the FPSCR 0:31 is 'undefined' after the mffs instruction.  This value
> 0xfff80000 just happens to be what populates the high-order word before
> the _FPU_SETCW.
> 
> Currently fegetenv() will exhibit an undefined high-order word in the
> fenv_t.  Likewise we'll be leaving the high-order 32-bits 'undefined' in
> the unsigned long long int fpu_control_t.  
> 
> I originally tested this on a Power6 with and without -mcpu=power6
> specified where the high-order word of the FPSCR register isn't touched
> by the two operand mtfsf instruction.  I've learned my lesson and will
> make sure to test on completely different hardware next time.
> 
> I'll regenerate and verify a clean make check on different classes of
> POWER hardware.

Okay, I regenerated the patch.  I was able to conditionally exclude the
high order word test on non-POWER6 hardware per the explanation above.

I ran make check successfully across these test cases on POWER5 and
POWER6.

Ryan S. Arnold
IBM Linux Technology Center
Linux Toolchain Development
2007-11-01  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 on POWER6.  Nop
	on non-POWER6 hardware.
	* 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/sysdeps/mach/hurd/powerpc/sigreturn.c	2001-11-09 18:37:47.000000000 -0600
+++ glibc.new/sysdeps/mach/hurd/powerpc/sigreturn.c	2007-10-30 07:33:05.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/sysdeps/powerpc/fpscr.h	1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpscr.h	2007-10-30 07:33:05.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/sysdeps/powerpc/fpu/Implies	1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/Implies	2007-10-30 07:33:05.000000000 -0500
@@ -0,0 +1 @@
+powerpc/math
--- glibc/sysdeps/powerpc/fpu/feholdexcpt.c	2007-05-07 01:21:41.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/feholdexcpt.c	2007-10-30 07:33:05.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/sysdeps/powerpc/fpu/fenv_libc.h	2006-03-16 05:46:34.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/fenv_libc.h	2007-10-30 07:33:05.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/sysdeps/powerpc/fpu/fesetenv.c	2007-05-07 01:22:06.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/fesetenv.c	2007-10-30 07:33:05.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/sysdeps/powerpc/fpu/feupdateenv.c	2007-05-07 01:22:29.000000000 -0500
+++ glibc.new/sysdeps/powerpc/fpu/feupdateenv.c	2007-10-30 07:33:05.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/sysdeps/powerpc/fpu/fpu_control.h	2003-02-27 14:57:06.000000000 -0600
+++ glibc.new/sysdeps/powerpc/fpu/fpu_control.h	2007-10-30 07:33:05.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/sysdeps/powerpc/math/Makefile	1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/math/Makefile	2007-10-30 07:33:05.000000000 -0500
@@ -0,0 +1,3 @@
+ifeq ($(subdir),math)
+libm-tests += test-powerpc-fenv
+endif
--- glibc/sysdeps/powerpc/math/test-fpucw.c	1969-12-31 18:00:00.000000000 -0600
+++ glibc.new/sysdeps/powerpc/math/test-fpucw.c	2007-11-01 14:52:52.000000000 -0500
@@ -0,0 +1,63 @@
+/* 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;
+    }
+#endif
+#endif /* _FPU_GETCW */
+  return 0;
+}
--- glibc/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-11-01 14:53:32.000000000 -0500
@@ -0,0 +1,65 @@
+/* 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)
+{
+#if defined _ARCH_PWR6 || defined _ARCH_PWR6X
+  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();
+
+  /* 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;
+    }
+
+  relax_fenv_state();
+  fe.fenv = fegetenv_register();
+
+  /* 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;
+    }
+#endif
+  return 0;
+}
--- glibc/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-30 07:33:05.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/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-30 07:33:05.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/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-30 07:33:05.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/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-30 07:33:05.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]