williamr@2: /*-------------------------------------------------------------------- williamr@2: *© Portions copyright (c) 2006 Nokia Corporation. All rights reserved. williamr@2: *-------------------------------------------------------------------- williamr@2: */ williamr@2: /*- williamr@2: * Copyright (c) 2004-2005 David Schultz williamr@2: * All rights reserved. williamr@2: * williamr@2: * Redistribution and use in source and binary forms, with or without williamr@2: * modification, are permitted provided that the following conditions williamr@2: * are met: williamr@2: * 1. Redistributions of source code must retain the above copyright williamr@2: * notice, this list of conditions and the following disclaimer. williamr@2: * 2. Redistributions in binary form must reproduce the above copyright williamr@2: * notice, this list of conditions and the following disclaimer in the williamr@2: * documentation and/or other materials provided with the distribution. williamr@2: * williamr@2: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND williamr@2: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE williamr@2: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE williamr@2: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE williamr@2: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL williamr@2: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS williamr@2: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) williamr@2: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT williamr@2: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY williamr@2: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF williamr@2: * SUCH DAMAGE. williamr@2: * williamr@2: * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $ williamr@2: */ williamr@2: williamr@2: #ifndef _FENV_H_ williamr@2: #define _FENV_H_ williamr@2: williamr@2: #include williamr@2: williamr@2: #ifdef __WINSCW__ williamr@2: /*to supress warnings 'arguments not used in function' williamr@2: This warnings crop up wherever fevn.h is included. So williamr@2: it is desirable to supress it here. The warning arises as a williamr@2: fact that these arguments are used within macros which get williamr@2: get replaced at the time of pre-processing and thus the williamr@2: compiler(s)warning 'argument/variable is not used in function*/ williamr@2: #pragma warn_unusedarg off williamr@2: #endif //__WINSCW__ williamr@2: williamr@2: typedef __uint32_t fenv_t; williamr@2: typedef __uint32_t fexcept_t; williamr@2: williamr@2: /* Exception flags */ williamr@2: #define FE_INVALID 0x0001 williamr@2: #define FE_DIVBYZERO 0x0002 williamr@2: #define FE_OVERFLOW 0x0004 williamr@2: #define FE_UNDERFLOW 0x0008 williamr@2: #define FE_INEXACT 0x0010 williamr@2: #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \ williamr@2: FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW) williamr@2: williamr@2: /* Rounding modes */ williamr@2: #define FE_TONEAREST 0x0000 williamr@2: #define FE_TOWARDZERO 0x0001 williamr@2: #define FE_UPWARD 0x0002 williamr@2: #define FE_DOWNWARD 0x0003 williamr@2: #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \ williamr@2: FE_UPWARD | FE_TOWARDZERO) williamr@2: __BEGIN_DECLS williamr@2: williamr@2: /* Default floating-point environment */ williamr@2: extern const fenv_t __fe_dfl_env; williamr@2: #define FE_DFL_ENV (&__fe_dfl_env) williamr@2: williamr@2: /* We need to be able to map status flag positions to mask flag positions */ williamr@2: #define _FPUSW_SHIFT 16 williamr@2: #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT) williamr@2: williamr@2: #ifdef ARM_HARD_FLOAT williamr@2: #define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr))) williamr@2: #define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr)) williamr@2: #else williamr@2: #define __rfs(__fpsr) williamr@2: #define __wfs(__fpsr) williamr@2: #endif williamr@2: williamr@2: static __inline int williamr@2: feclearexcept(int __excepts) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: __fpsr &= ~__excepts; williamr@2: __wfs(__fpsr); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fegetexceptflag(fexcept_t *__flagp, int __excepts) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: *__flagp = __fpsr & __excepts; williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fesetexceptflag(const fexcept_t *__flagp, int __excepts) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: __fpsr &= ~__excepts; williamr@2: __fpsr |= *__flagp & __excepts; williamr@2: __wfs(__fpsr); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: feraiseexcept(int __excepts) williamr@2: { williamr@2: fexcept_t __ex = __excepts; williamr@2: williamr@2: fesetexceptflag(&__ex, __excepts); /* XXX */ williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fetestexcept(int __excepts) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: return (__fpsr & __excepts); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fegetround(void) williamr@2: { williamr@2: williamr@2: /* williamr@2: * Apparently, the rounding mode is specified as part of the williamr@2: * instruction format on ARM, so the dynamic rounding mode is williamr@2: * indeterminate. Some FPUs may differ. williamr@2: */ williamr@2: return (-1); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fesetround(int __round) williamr@2: { williamr@2: williamr@2: return (-1); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fegetenv(fenv_t *__envp) williamr@2: { williamr@2: williamr@2: __rfs(__envp); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: feholdexcept(fenv_t *__envp) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fenv_t __env = 0; williamr@2: #else williamr@2: fenv_t __env ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__env); williamr@2: *__envp = __env; williamr@2: __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK); williamr@2: __wfs(__env); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fesetenv(const fenv_t *__envp) williamr@2: { williamr@2: williamr@2: __wfs(*__envp); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: feupdateenv(const fenv_t *__envp) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: __wfs(*__envp); williamr@2: feraiseexcept(__fpsr & FE_ALL_EXCEPT); williamr@2: return (0); williamr@2: } williamr@2: williamr@2: #if __BSD_VISIBLE williamr@2: williamr@2: static __inline int williamr@2: feenableexcept(int __mask) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fenv_t __old_fpsr = 0, __new_fpsr= 0; williamr@2: #else williamr@2: fenv_t __old_fpsr, __new_fpsr; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__old_fpsr); williamr@2: __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT; williamr@2: __wfs(__new_fpsr); williamr@2: return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fedisableexcept(int __mask) williamr@2: { williamr@2: williamr@2: #ifdef __SYMBIAN32__ williamr@2: fenv_t __old_fpsr =0, __new_fpsr =0; williamr@2: #else williamr@2: fenv_t __old_fpsr, __new_fpsr; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__old_fpsr); williamr@2: __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT); williamr@2: __wfs(__new_fpsr); williamr@2: return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fegetexcept(void) williamr@2: { williamr@2: #ifdef __SYMBIAN32__ williamr@2: fexcept_t __fpsr = 0; williamr@2: #else williamr@2: fexcept_t __fpsr ; williamr@2: #endif //__SYMBIAN32__ williamr@2: williamr@2: __rfs(&__fpsr); williamr@2: return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT); williamr@2: } williamr@2: williamr@2: #endif /* __BSD_VISIBLE */ williamr@2: williamr@2: __END_DECLS williamr@2: williamr@2: #endif /* !_FENV_H_ */