From 7002592cb4072303c6a286e1c6479df99ae151b3 Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Thu, 19 Feb 2015 22:14:36 +0100 Subject: [PATCH 04/23] sim/erc32: Use fenv.h for host FPU access * 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(-) 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 -/* 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 -- 1.9.1