[v2,04/22] sim/erc32: Use fenv.h for host FPU access

Message ID 1424385100-15397-5-git-send-email-jiri@gaisler.se
State Committed
Headers

Commit Message

Jiri Gaisler Feb. 19, 2015, 10:31 p.m. UTC
  * float.c (get_accex, clear_accex, set_fsr) Use functions from fenv.h
	instead of custom assembly.
---
 sim/erc32/float.c | 191 +++++++++---------------------------------------------
 1 file changed, 30 insertions(+), 161 deletions(-)
  

Comments

Mike Frysinger Feb. 22, 2015, 4:24 a.m. UTC | #1
On 19 Feb 2015 23:31, Jiri Gaisler wrote:
> +    fexc = fetestexcept(FE_ALL_EXCEPT);

fixed the spacing before the (

> +    feclearexcept(FE_ALL_EXCEPT);

here too

> +     fesetround(fround);

and here

otherwise, i think this makes the file much nicer to work with :).  merged!
-mike
  

Patch

diff --git a/sim/erc32/float.c b/sim/erc32/float.c
index 598b7cc..40c133b 100644
--- a/sim/erc32/float.c
+++ b/sim/erc32/float.c
@@ -28,53 +28,38 @@ 
  * 4. Clear host exception bits
  *
  *
- * This can also be done using ieee_flags() library routine on sun.
  */
 
 #include "config.h"
 #include "sis.h"
+#include <fenv.h>
 
-/* Forward declarations */
-
-extern uint32	_get_sw (void);
-extern uint32	_get_cw (void);
-static void	__setfpucw (unsigned short fpu_control);
-
-/* This host dependent routine should return the accrued exceptions */
+/* This routine should return the accrued exceptions */
 int
 get_accex()
 {
-#ifdef sparc
-    return ((_get_fsr_raw() >> 5) & 0x1F);
-#elif i386
-    uint32 accx;
-
-    accx = _get_sw() & 0x3f;
-    accx = ((accx & 1) << 4) | ((accx & 2) >> 1) | ((accx & 4) >> 1) |
-	   (accx & 8) | ((accx & 16) >> 2) | ((accx & 32) >> 5);
+    int fexc, accx;
+
+    fexc = fetestexcept(FE_ALL_EXCEPT);
+    accx = 0;
+    if (fexc & FE_INEXACT)
+        accx |= 1;
+    if (fexc & FE_DIVBYZERO)
+        accx |= 2;
+    if (fexc & FE_UNDERFLOW)
+        accx |= 4;
+    if (fexc & FE_OVERFLOW)
+        accx |= 8;
+    if (fexc & FE_INVALID)
+        accx |= 0x10;
     return(accx);
-#else
-    return(0);
-#warning no fpu trap support for this target
-#endif
-
 }
 
 /* How to clear the accrued exceptions */
 void
 clear_accex()
 {
-#ifdef sparc
-    set_fsr((_get_fsr_raw() & ~0x3e0));
-#elif i386
-    asm("\n"
-".text\n"
-"	fnclex\n"
-"\n"
-"    ");
-#else
-#warning no fpu trap support for this target
-#endif
+    feclearexcept(FE_ALL_EXCEPT);
 }
 
 /* How to map SPARC FSR onto the host */
@@ -82,138 +67,22 @@  void
 set_fsr(fsr)
 uint32 fsr;
 {
-#ifdef sparc
-	_set_fsr_raw(fsr & ~0x0f800000);
-#elif i386
-     void __setfpucw(unsigned short fpu_control);
-     uint32 rawfsr;
+    int fround;
 
-     fsr >>= 30;
-     switch (fsr) {
+    fsr >>= 30;
+    switch (fsr) {
 	case 0: 
-	case 2:
-	  break;
-
+	    fround = FE_TONEAREST;
+	    break;
 	case 1:
-	  fsr = 3;
-	  break;
-
+	    fround = FE_TOWARDZERO;
+	    break;
+	case 2:
+	    fround = FE_UPWARD;
+	    break;
 	case 3:
-	  fsr = 1;
-	  break;
+	    fround = FE_DOWNWARD;
+	    break;
      }
-     rawfsr = _get_cw();
-     rawfsr |= (fsr << 10) | 0x3ff;
-     __setfpucw(rawfsr);
-#else
-#warning no fpu trap support for this target
-#endif
-}
-
-
-/* Host dependent support functions */
-
-#ifdef sparc
-
-    asm("\n"
-"\n"
-".text\n"
-"        .align 4\n"
-"        .global __set_fsr_raw,_set_fsr_raw\n"
-"__set_fsr_raw:\n"
-"_set_fsr_raw:\n"
-"        save %sp,-104,%sp\n"
-"        st %i0,[%fp+68]\n"
-"        ld [%fp+68], %fsr\n"
-"        mov 0,%i0\n"
-"        ret\n"
-"        restore\n"
-"\n"
-"        .align 4\n"
-"        .global __get_fsr_raw\n"
-"        .global _get_fsr_raw\n"
-"__get_fsr_raw:\n"
-"_get_fsr_raw:\n"
-"        save %sp,-104,%sp\n"
-"        st %fsr,[%fp+68]\n"
-"        ld [%fp+68], %i0\n"
-"        ret\n"
-"        restore\n"
-"\n"
-"    ");
-
-#elif i386
-
-    asm("\n"
-"\n"
-".text\n"
-"        .align 8\n"
-".globl _get_sw,__get_sw\n"
-"__get_sw:\n"
-"_get_sw:\n"
-"        pushl %ebp\n"
-"        movl %esp,%ebp\n"
-"        movl $0,%eax\n"
-"        fnstsw %ax\n"
-"        movl %ebp,%esp\n"
-"        popl %ebp\n"
-"        ret\n"
-"\n"
-"        .align 8\n"
-".globl _get_cw,__get_cw\n"
-"__get_cw:\n"
-"_get_cw:\n"
-"        pushl %ebp\n"
-"        movl %esp,%ebp\n"
-"        subw $2,%esp\n"
-"        fnstcw -2(%ebp)\n"
-"        movw -2(%ebp),%eax\n"
-"        movl %ebp,%esp\n"
-"        popl %ebp\n"
-"        ret\n"
-"\n"
-"\n"
-"    ");
-
-
-#else
-#warning no fpu trap support for this target
-#endif
-
-#if i386
-/* #if defined _WIN32 || defined __GO32__ */
-/* This is so floating exception handling works on NT
-   These definitions are from the linux fpu_control.h, which
-   doesn't exist on NT.
-
-   default to:
-     - extended precision
-     - rounding to nearest
-     - exceptions on overflow, zero divide and NaN
-*/
-#define _FPU_DEFAULT  0x1372 
-#define _FPU_RESERVED 0xF0C0  /* Reserved bits in cw */
-
-static void
-__setfpucw(unsigned short fpu_control)
-{
-  volatile unsigned short cw;
-
-  /* If user supplied _fpu_control, use it ! */
-  if (!fpu_control)
-  { 
-    /* use defaults */
-    fpu_control = _FPU_DEFAULT;
-  }
-  /* Get Control Word */
-  __asm__ volatile ("fnstcw %0" : "=m" (cw) : );
-  
-  /* mask in */
-  cw &= _FPU_RESERVED;
-  cw = cw | (fpu_control & ~_FPU_RESERVED);
-
-  /* set cw */
-  __asm__ volatile ("fldcw %0" :: "m" (cw));
+     fesetround(fround);
 }
-/* #endif */
-#endif