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