This is the mail archive of the libc-alpha@sources.redhat.com 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] fix hppa fpu environment


libc-alpha,

There were various glaring errors in hppa's fenv functions. In
particular this cleans up confusion about "enable exception bits" versus
"raised exception bits."

Removes test-fenv failures.

a. feclearexcept should shift the value of FE_ALL_EXCEPT to the right
   place before complimenting.

b. fegetenv should explicitly use the ,ma completer instead of falling
   back on the default action. Condense the assembly expression with +r.

c. feholdexcept should use the ,ma completer, removes the need for a
   magical "&clear + 1"  since the address is correct. Condense the
   assembly with +r.

d. fesetenv should use the ,ma completer, removes the need for a magical
   "&temp + 1" adjustment.

e. feupdateenv should get raised exception bits (status), not the
   enable bits. The currently raised exceptions are OR'd with those in
   the environment and this is passed to fesetenv, there is no need to
   raise them manually after.

f. feraiseexcept is largely rewritten, 

	o Delayed exceptions in the FPU are flushed with stores to the
	  stack "fldd 0(%%sr0,%%sp),%0"
	o FE_UNDERFLOW is changed to calculate DBL_MIN/3.0 instead of 
	  DBL_MIN/69.69 for clarity, we don't want to indicate that we
	  are trying to trigger FE_INEXACT.
	o FE_INEXACT is changed to M_PI/69.69 and converted to single
	  precision, this triggers the appropriate FE_INEXACT on PA 1.0
	  and PA 2.0

f. fesetexceptflag should set the enable bits not the status.


Cheers,
Carlos.

---
 sysdeps/hppa/fpu/fclrexcpt.c    |    2 
 sysdeps/hppa/fpu/fegetenv.c     |   10 +--
 sysdeps/hppa/fpu/feholdexcpt.c  |   34 ++++------
 sysdeps/hppa/fpu/fesetenv.c     |   31 +++------
 sysdeps/hppa/fpu/feupdateenv.c  |    8 --
 sysdeps/hppa/fpu/fraiseexcpt.c  |   63 +++++++++++--------
 sysdeps/hppa/fpu/fsetexcptflg.c |    3 
 7 files changed, 75 insertions(+), 76 deletions(-)
---

2003-12-17  Carlos O'Donell  <carlos@baldric.uwo.ca>

	* sysdeps/hppa/fpu/fclrexcpt.c (feclearexcept): Right shift
	FE_ALL_EXCEPT before complimenting.
	* sysdeps/hppa/fpu/fegetenv.c (fegetenv): use asm 'ma,' completer,
	and gcc '+r' constraint.
	* sysdeps/hppa/fpu/feholdexcpt.c (feholdexcept): Likewise.
	* sysdeps/hppa/fpu/fesetenv.c (fesetenv): Likewise.
	* sysdeps/hppa/fpu/feupdateenv.c (feupdateenv): Read raised
	exception bits, OR with envp, pass to fesetenv.
	* sysdeps/hppa/fpu/fraiseexcpt.c (feraiseexcept): Add delayed
	exception flushing, FE_UNDERFLOW is DBL_MIN/3.0, FE_INEXACT is
	triggered by M_PI/69.69 converted to single precision.
	* sysdeps/hppa/fpu/fsetexcptflg.c (fesetexceptflag): Set enable
	bits not raised exception bits.

Index: sysdeps/hppa/fpu//fclrexcpt.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/fclrexcpt.c,v
retrieving revision 1.3
diff -u -p -r1.3 fclrexcpt.c
--- sysdeps/hppa/fpu//fclrexcpt.c	6 Jul 2001 04:55:52 -0000	1.3
+++ sysdeps/hppa/fpu//fclrexcpt.c	18 Dec 2003 02:39:59 -0000
@@ -29,7 +29,7 @@ feclearexcept (int excepts)
   __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
 
   /* Clear all the relevant bits. */
-  sw[0] &= ~(excepts & FE_ALL_EXCEPT) << 27;
+  sw[0] &= ~((excepts & FE_ALL_EXCEPT) << 27);
   __asm__ ("fldd 0(%0),%%fr0" : : "r" (sw));
 
   /* Success.  */
Index: sysdeps/hppa/fpu//fegetenv.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/fegetenv.c,v
retrieving revision 1.2
diff -u -p -r1.2 fegetenv.c
--- sysdeps/hppa/fpu//fegetenv.c	6 Jul 2001 04:55:52 -0000	1.2
+++ sysdeps/hppa/fpu//fegetenv.c	18 Dec 2003 02:39:59 -0000
@@ -24,10 +24,10 @@ int
 fegetenv (fenv_t *envp)
 {
   __asm__ (
-	   "fstd %%fr0,0(%2)\n"
-	   "fstd,ma %%fr1,8(%2)\n"
-	   "fstd,ma %%fr2,8(%2)\n"
-	   "fstd %%fr3,0(%2)\n"
-	   : "=m" (*envp), "=r" (envp) : "1" (envp));
+	   "fstd,ma %%fr0,8(%1)\n"
+	   "fstd,ma %%fr1,8(%1)\n"
+	   "fstd,ma %%fr2,8(%1)\n"
+	   "fstd %%fr3,0(%1)\n"
+	   : "=m" (*envp), "+r" (envp));
   return 0;
 }
Index: sysdeps/hppa/fpu//feholdexcpt.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/feholdexcpt.c,v
retrieving revision 1.2
diff -u -p -r1.2 feholdexcpt.c
--- sysdeps/hppa/fpu//feholdexcpt.c	6 Jul 2001 04:55:52 -0000	1.2
+++ sysdeps/hppa/fpu//feholdexcpt.c	18 Dec 2003 02:39:59 -0000
@@ -25,18 +25,16 @@ int
 feholdexcept (fenv_t *envp)
 {
   fenv_t clear;
+  fenv_t * _regs = envp;
 
   /* Store the environment.  */
-  {
-    fenv_t * _regs = envp;
-    __asm__ (
-	     "fstd %%fr0,0(%2)\n"
-	     "fstd,ma %%fr1,8(%2)\n"
-	     "fstd,ma %%fr2,8(%2)\n"
-	     "fstd %%fr3,0(%2)\n"
-	     : "=m" (*_regs), "=r" (_regs) : "1" (_regs));
-    memcpy (&clear, envp, sizeof (clear));
-  }
+  __asm__ (
+	   "fstd,ma %%fr0,8(%1)\n"
+	   "fstd,ma %%fr1,8(%1)\n"
+	   "fstd,ma %%fr2,8(%1)\n"
+	   "fstd %%fr3,0(%1)\n"
+	   : "=m" (*_regs), "+r" (_regs));
+  memcpy (&clear, envp, sizeof (clear));
 
   /* Now clear all exceptions.  */
   clear.__status_word &= ~(FE_ALL_EXCEPT << 27);
@@ -46,15 +44,13 @@ feholdexcept (fenv_t *envp)
   clear.__status_word &= ~FE_ALL_EXCEPT;
 
   /* Load the new environment. */
-  {
-    fenv_t * _regs = &clear + 1;
-    __asm__ (
-	     "fldd,mb -8(%2),%%fr3\n"
-	     "fldd,mb -8(%2),%%fr2\n"
-	     "fldd,mb -8(%2),%%fr1\n"
-	     "fldd -8(%2),%%fr0\n"
-	     : "=m" (*_regs), "=r" (_regs) : "1" (_regs));
-  }
+  _regs = &clear;
+  __asm__ (
+	   "fldd,ma -8(%1),%%fr3\n"
+	   "fldd,ma -8(%1),%%fr2\n"
+	   "fldd,ma -8(%1),%%fr1\n"
+	   "fldd 0(%1),%%fr0\n"
+	   : "=m" (*_regs), "+r" (_regs));
 
   return 0;
 }
Index: sysdeps/hppa/fpu//fesetenv.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/fesetenv.c,v
retrieving revision 1.3
diff -u -p -r1.3 fesetenv.c
--- sysdeps/hppa/fpu//fesetenv.c	10 Sep 2002 01:26:37 -0000	1.3
+++ sysdeps/hppa/fpu//fesetenv.c	18 Dec 2003 02:39:59 -0000
@@ -26,20 +26,18 @@ int
 fesetenv (const fenv_t *envp)
 {
   fenv_t temp;
+  fenv_t * _regs = &temp;
 
   /* Install the environment specified by ENVP.  But there are a few
      values which we do not want to come from the saved environment.
      Therefore, we get the current environment and replace the values
      we want to use from the environment specified by the parameter.  */
-  {
-    fenv_t * _regs = &temp;
-    __asm__ (
-	     "fstd %%fr0,0(%2)\n"
-	     "fstd,ma %%fr1,8(%2)\n"
-	     "fstd,ma %%fr2,8(%2)\n"
-	     "fstd %%fr3,0(%2)\n"
-	     : "=m" (*_regs), "=r" (_regs) : "1" (_regs));
-  }
+  __asm__ (
+	   "fstd,ma %%fr0,8(%1)\n"
+	   "fstd,ma %%fr1,8(%1)\n"
+	   "fstd,ma %%fr2,8(%1)\n"
+	   "fstd %%fr3,0(%1)\n"
+	   : "=m" (*_regs), "+r" (_regs));
 
   temp.__status_word &= ~(FE_ALL_EXCEPT
 			  | (FE_ALL_EXCEPT << 27)
@@ -55,15 +53,12 @@ fesetenv (const fenv_t *envp)
 			      | (FE_ALL_EXCEPT << 27)));
 
   /* Load the new environment. */
-  {
-    fenv_t * _regs = &temp + 1;
-    __asm__ (
-	     "fldd,mb -8(%2),%%fr3\n"
-	     "fldd,mb -8(%2),%%fr2\n"
-	     "fldd,mb -8(%2),%%fr1\n"
-	     "fldd -8(%2),%%fr0\n"
-	     : "=m" (*_regs), "=r" (_regs) : "1" (_regs));
-  }
+  __asm__ (
+	   "fldd,ma -8(%1),%%fr3\n"
+	   "fldd,ma -8(%1),%%fr2\n"
+	   "fldd,ma -8(%1),%%fr1\n"
+	   "fldd 0(%1),%%fr0\n"
+	   : "=m" (*_regs), "+r" (_regs));
 
   /* Success.  */
   return 0;
Index: sysdeps/hppa/fpu//feupdateenv.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/feupdateenv.c,v
retrieving revision 1.2
diff -u -p -r1.2 feupdateenv.c
--- sysdeps/hppa/fpu//feupdateenv.c	6 Jul 2001 04:55:52 -0000	1.2
+++ sysdeps/hppa/fpu//feupdateenv.c	18 Dec 2003 02:39:59 -0000
@@ -27,13 +27,11 @@ feupdateenv (const fenv_t *envp)
 
   /* Get the current exception status. */
   __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
-  sw[0] &= (FE_ALL_EXCEPT << 27);
-
+  sw[0] &= FE_ALL_EXCEPT;
+  envp->__status_word = envp->__status_word | sw[0];
+  
   /* Install new environment.  */
   fesetenv (envp);
-
-  /* Raise the saved exception. */
-  feraiseexcept (sw[0] >> 27);
 
   /* Success.  */
   return 0;
Index: sysdeps/hppa/fpu//fraiseexcpt.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/fraiseexcpt.c,v
retrieving revision 1.4
diff -u -p -r1.4 fraiseexcpt.c
--- sysdeps/hppa/fpu//fraiseexcpt.c	10 Sep 2002 01:26:37 -0000	1.4
+++ sysdeps/hppa/fpu//fraiseexcpt.c	18 Dec 2003 02:39:59 -0000
@@ -22,6 +22,9 @@
 #include <float.h>
 #include <math.h>
 
+/* Please see section 10, 
+   page 10-5 "Delayed Trapping" in the PA-RISC 2.0 Architecture manual */
+
 int
 feraiseexcept (int excepts)
 {
@@ -33,56 +36,64 @@ feraiseexcept (int excepts)
 
   /* We do these bits in assembly to be certain GCC doesn't optimize
      away something important, and so we can force delayed traps to
-     occur.  */
-
-  /* FIXME: These all need verification! */
+     occur. */
 
-  /* First: invalid exception.  */
+  /* We use "fldd 0(%%sr0,%%sp),%0" to flush the delayed exception */
+	
+  /* First: Invalid exception.  */
   if (excepts & FE_INVALID)
     {
       /* One example of a invalid operation is 0 * Infinity.  */
       double d = HUGE_VAL;
-      __asm__ __volatile__ ("fmpy,dbl %1,%%fr0,%0\n\t"
-			    /* FIXME: is this a proper trap barrier? */
-			    "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
+      __asm__ __volatile__ (
+		"	fcpy,dbl %%fr0,%%fr22\n"
+		"	fmpy,dbl %0,%%fr22,%0\n"
+		"	fldd 0(%%sr0,%%sp),%0"
+		: "+f" (d) : : "%fr22" );
     }
 
-  /* Next: division by zero.  */
+  /* Second: Division by zero.  */
   if (excepts & FE_DIVBYZERO)
     {
       double d = 1.0;
-      __asm__ __volatile__ ("fdiv,dbl %1,%%fr0,%0\n\t"
-			    "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
+      __asm__ __volatile__ (
+		"	fcpy,dbl %%fr0,%%fr22\n"
+		"	fdiv,dbl %0,%%fr22,%0\n"
+		"	fldd 0(%%sr0,%%sp),%0"
+		: "+f" (d) : : "%fr22" );
     }
 
-  /* Next: overflow.  */
-  /* FIXME: Compare with IA-64 - do we have the same problem? */
+  /* Third: Overflow.  */
   if (excepts & FE_OVERFLOW)
     {
       double d = DBL_MAX;
-
-      __asm__ __volatile__ ("fmpy,dbl %1,%1,%0\n\t"
-			    "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d));
+      __asm__ __volatile__ (
+		"	fadd,dbl %0,%0,%0\n"
+		"	fldd 0(%%sr0,%%sp),%0"
+		: "+f" (d) );
     }
 
-  /* Next: underflow.  */
+  /* Fourth: Underflow.  */
   if (excepts & FE_UNDERFLOW)
     {
       double d = DBL_MIN;
-      double e = 69.69;
-
-      __asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t"
-			    "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e));
+      double e = 3.0;
+      __asm__ __volatile__ (
+		"	fdiv,dbl %0,%1,%0\n"
+		"	fldd 0(%%sr0,%%sp),%0"
+		: "+f" (d) : "f" (e) );
     }
 
-  /* Last: inexact.  */
+  /* Fifth: Inexact */
   if (excepts & FE_INEXACT)
     {
-      double d = 1.0;
-      double e = M_PI;
-
-      __asm__ __volatile__ ("fdiv,dbl %1,%2,%0\n\t"
-			    "fcpy,dbl %%fr0,%%fr0" : "=f" (d) : "0" (d), "f" (e));
+      double d = M_PI;
+      double e = 69.69;
+      __asm__ __volatile__ (
+		"	fdiv,dbl %0,%1,%%fr22\n"
+		"	fcnvfxt,dbl,sgl %%fr22,%%fr22L\n"
+		"	fldd 0(%%sr0,%%sp),%%fr22"
+		: : "f" (d), "f" (e) : "%fr22" );
     }
 
   /* Success.  */
Index: sysdeps/hppa/fpu//fsetexcptflg.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/hppa/fpu/fsetexcptflg.c,v
retrieving revision 1.2
diff -u -p -r1.2 fsetexcptflg.c
--- sysdeps/hppa/fpu//fsetexcptflg.c	6 Jul 2001 04:55:52 -0000	1.2
+++ sysdeps/hppa/fpu//fsetexcptflg.c	18 Dec 2003 02:39:59 -0000
@@ -29,8 +29,7 @@ fesetexceptflag (const fexcept_t *flagp,
   /* Get the current status word. */
   __asm__ ("fstd %%fr0,0(%1)" : "=m" (*sw) : "r" (sw));
 
-  /* Install the new exception flags bits.  */
-  sw[0] &= ~(excepts & (FE_ALL_EXCEPT >> 27));
+  /* Install new enable trap bits  */
   sw[0] |= (*flagp & excepts & FE_ALL_EXCEPT) << 27;
 
   /* Store the new status word.  */


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