sim/erc32: Use fenv.h for host FPU access
authorJiri Gaisler <jiri@gaisler.se>
Thu, 19 Feb 2015 22:31:22 +0000 (23:31 +0100)
committerMike Frysinger <vapier@gentoo.org>
Sun, 22 Feb 2015 04:20:09 +0000 (23:20 -0500)
sim/erc32/ChangeLog
sim/erc32/float.c

index 38c3a322870e95427a83f3a1d2d90dab2e6b6208..f50bdbffcb1e3431205742c153f8425e1f906c48 100644 (file)
@@ -1,3 +1,8 @@
+2015-02-21  Jiri Gaisler  <jiri@gaisler.se>
+
+       * float.c (get_accex, clear_accex, set_fsr): Use functions from fenv.h
+       instead of custom assembly.
+
 2015-02-21  Jiri Gaisler  <jiri@gaisler.se>
 
        * erc32.c (mec_read): Allow simulator memory size to be read
index 598b7cce0daf3cc126a55ac2c2c19bcd3f1b5162..e8807fbbbd06da2e5c08a254179dfd5c1f4cad7b 100644 (file)
  * 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