xref: /freebsd/lib/msun/arm/fenv.h (revision 7082a2cf72f2af64cd8554012cac6427a0c8e641)
119220bc1SDavid Schultz /*-
210b01832SDavid Schultz  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
319220bc1SDavid Schultz  * All rights reserved.
419220bc1SDavid Schultz  *
519220bc1SDavid Schultz  * Redistribution and use in source and binary forms, with or without
619220bc1SDavid Schultz  * modification, are permitted provided that the following conditions
719220bc1SDavid Schultz  * are met:
819220bc1SDavid Schultz  * 1. Redistributions of source code must retain the above copyright
919220bc1SDavid Schultz  *    notice, this list of conditions and the following disclaimer.
1019220bc1SDavid Schultz  * 2. Redistributions in binary form must reproduce the above copyright
1119220bc1SDavid Schultz  *    notice, this list of conditions and the following disclaimer in the
1219220bc1SDavid Schultz  *    documentation and/or other materials provided with the distribution.
1319220bc1SDavid Schultz  *
1419220bc1SDavid Schultz  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1519220bc1SDavid Schultz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1619220bc1SDavid Schultz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1719220bc1SDavid Schultz  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819220bc1SDavid Schultz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1919220bc1SDavid Schultz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2019220bc1SDavid Schultz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2119220bc1SDavid Schultz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2219220bc1SDavid Schultz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319220bc1SDavid Schultz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419220bc1SDavid Schultz  * SUCH DAMAGE.
2519220bc1SDavid Schultz  *
2619220bc1SDavid Schultz  * $FreeBSD$
2719220bc1SDavid Schultz  */
2819220bc1SDavid Schultz 
2919220bc1SDavid Schultz #ifndef	_FENV_H_
3019220bc1SDavid Schultz #define	_FENV_H_
3119220bc1SDavid Schultz 
3219220bc1SDavid Schultz #include <sys/_types.h>
3319220bc1SDavid Schultz 
34d78e594bSDavid Schultz #ifndef	__fenv_static
35d78e594bSDavid Schultz #define	__fenv_static	static
36d78e594bSDavid Schultz #endif
37d78e594bSDavid Schultz 
3819220bc1SDavid Schultz typedef	__uint32_t	fenv_t;
3919220bc1SDavid Schultz typedef	__uint32_t	fexcept_t;
4019220bc1SDavid Schultz 
4119220bc1SDavid Schultz /* Exception flags */
4219220bc1SDavid Schultz #define	FE_INVALID	0x0001
4319220bc1SDavid Schultz #define	FE_DIVBYZERO	0x0002
4419220bc1SDavid Schultz #define	FE_OVERFLOW	0x0004
4519220bc1SDavid Schultz #define	FE_UNDERFLOW	0x0008
4619220bc1SDavid Schultz #define	FE_INEXACT	0x0010
4719220bc1SDavid Schultz #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
4819220bc1SDavid Schultz 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
4919220bc1SDavid Schultz 
5015d3b4dbSOlivier Houchard /* Rounding modes */
5115d3b4dbSOlivier Houchard #define	FE_TONEAREST	0x0000
5215d3b4dbSOlivier Houchard #define	FE_TOWARDZERO	0x0001
5315d3b4dbSOlivier Houchard #define	FE_UPWARD	0x0002
5415d3b4dbSOlivier Houchard #define	FE_DOWNWARD	0x0003
5515d3b4dbSOlivier Houchard #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
5615d3b4dbSOlivier Houchard 			 FE_UPWARD | FE_TOWARDZERO)
5719220bc1SDavid Schultz __BEGIN_DECLS
5819220bc1SDavid Schultz 
5919220bc1SDavid Schultz /* Default floating-point environment */
6019220bc1SDavid Schultz extern const fenv_t	__fe_dfl_env;
6119220bc1SDavid Schultz #define	FE_DFL_ENV	(&__fe_dfl_env)
6219220bc1SDavid Schultz 
6319220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */
6419220bc1SDavid Schultz #define _FPUSW_SHIFT	16
6519220bc1SDavid Schultz #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
6619220bc1SDavid Schultz 
677bde21b1SDavid Schultz #ifndef	ARM_HARD_FLOAT
68*7082a2cfSDavid Schultz 
69*7082a2cfSDavid Schultz int feclearexcept(int __excepts);
70*7082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts);
71*7082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
72*7082a2cfSDavid Schultz int feraiseexcept(int __excepts);
73*7082a2cfSDavid Schultz int fetestexcept(int __excepts);
74*7082a2cfSDavid Schultz int fegetround(void);
75*7082a2cfSDavid Schultz int fesetround(int __round);
76*7082a2cfSDavid Schultz int fegetenv(fenv_t *__envp);
77*7082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp);
78*7082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp);
79*7082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp);
807bde21b1SDavid Schultz 
817bde21b1SDavid Schultz #else	/* ARM_HARD_FLOAT */
827bde21b1SDavid Schultz 
83f365db00SDavid Schultz #define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
8460b22cf1SOlivier Houchard #define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
8519220bc1SDavid Schultz 
86d78e594bSDavid Schultz __fenv_static inline int
8719220bc1SDavid Schultz feclearexcept(int __excepts)
8819220bc1SDavid Schultz {
8919220bc1SDavid Schultz 	fexcept_t __fpsr;
9019220bc1SDavid Schultz 
9119220bc1SDavid Schultz 	__rfs(&__fpsr);
9219220bc1SDavid Schultz 	__fpsr &= ~__excepts;
9319220bc1SDavid Schultz 	__wfs(__fpsr);
9419220bc1SDavid Schultz 	return (0);
9519220bc1SDavid Schultz }
9619220bc1SDavid Schultz 
97d78e594bSDavid Schultz __fenv_static inline int
9819220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
9919220bc1SDavid Schultz {
10019220bc1SDavid Schultz 	fexcept_t __fpsr;
10119220bc1SDavid Schultz 
10219220bc1SDavid Schultz 	__rfs(&__fpsr);
10319220bc1SDavid Schultz 	*__flagp = __fpsr & __excepts;
10419220bc1SDavid Schultz 	return (0);
10519220bc1SDavid Schultz }
10619220bc1SDavid Schultz 
107d78e594bSDavid Schultz __fenv_static inline int
10819220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
10919220bc1SDavid Schultz {
11019220bc1SDavid Schultz 	fexcept_t __fpsr;
11119220bc1SDavid Schultz 
11219220bc1SDavid Schultz 	__rfs(&__fpsr);
11319220bc1SDavid Schultz 	__fpsr &= ~__excepts;
11419220bc1SDavid Schultz 	__fpsr |= *__flagp & __excepts;
11519220bc1SDavid Schultz 	__wfs(__fpsr);
11619220bc1SDavid Schultz 	return (0);
11719220bc1SDavid Schultz }
11819220bc1SDavid Schultz 
119d78e594bSDavid Schultz __fenv_static inline int
12019220bc1SDavid Schultz feraiseexcept(int __excepts)
12119220bc1SDavid Schultz {
12219220bc1SDavid Schultz 	fexcept_t __ex = __excepts;
12319220bc1SDavid Schultz 
12419220bc1SDavid Schultz 	fesetexceptflag(&__ex, __excepts);	/* XXX */
12519220bc1SDavid Schultz 	return (0);
12619220bc1SDavid Schultz }
12719220bc1SDavid Schultz 
128d78e594bSDavid Schultz __fenv_static inline int
12919220bc1SDavid Schultz fetestexcept(int __excepts)
13019220bc1SDavid Schultz {
13119220bc1SDavid Schultz 	fexcept_t __fpsr;
13219220bc1SDavid Schultz 
13319220bc1SDavid Schultz 	__rfs(&__fpsr);
13419220bc1SDavid Schultz 	return (__fpsr & __excepts);
13519220bc1SDavid Schultz }
13619220bc1SDavid Schultz 
137d78e594bSDavid Schultz __fenv_static inline int
13819220bc1SDavid Schultz fegetround(void)
13919220bc1SDavid Schultz {
14019220bc1SDavid Schultz 
14119220bc1SDavid Schultz 	/*
14219220bc1SDavid Schultz 	 * Apparently, the rounding mode is specified as part of the
14319220bc1SDavid Schultz 	 * instruction format on ARM, so the dynamic rounding mode is
14419220bc1SDavid Schultz 	 * indeterminate.  Some FPUs may differ.
14519220bc1SDavid Schultz 	 */
14619220bc1SDavid Schultz 	return (-1);
14719220bc1SDavid Schultz }
14819220bc1SDavid Schultz 
149d78e594bSDavid Schultz __fenv_static inline int
15019220bc1SDavid Schultz fesetround(int __round)
15119220bc1SDavid Schultz {
15219220bc1SDavid Schultz 
15319220bc1SDavid Schultz 	return (-1);
15419220bc1SDavid Schultz }
15519220bc1SDavid Schultz 
156d78e594bSDavid Schultz __fenv_static inline int
15719220bc1SDavid Schultz fegetenv(fenv_t *__envp)
15819220bc1SDavid Schultz {
15919220bc1SDavid Schultz 
16019220bc1SDavid Schultz 	__rfs(__envp);
16119220bc1SDavid Schultz 	return (0);
16219220bc1SDavid Schultz }
16319220bc1SDavid Schultz 
164d78e594bSDavid Schultz __fenv_static inline int
16519220bc1SDavid Schultz feholdexcept(fenv_t *__envp)
16619220bc1SDavid Schultz {
16719220bc1SDavid Schultz 	fenv_t __env;
16819220bc1SDavid Schultz 
16919220bc1SDavid Schultz 	__rfs(&__env);
17019220bc1SDavid Schultz 	*__envp = __env;
17119220bc1SDavid Schultz 	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
17219220bc1SDavid Schultz 	__wfs(__env);
17319220bc1SDavid Schultz 	return (0);
17419220bc1SDavid Schultz }
17519220bc1SDavid Schultz 
176d78e594bSDavid Schultz __fenv_static inline int
17719220bc1SDavid Schultz fesetenv(const fenv_t *__envp)
17819220bc1SDavid Schultz {
17919220bc1SDavid Schultz 
18019220bc1SDavid Schultz 	__wfs(*__envp);
18119220bc1SDavid Schultz 	return (0);
18219220bc1SDavid Schultz }
18319220bc1SDavid Schultz 
184d78e594bSDavid Schultz __fenv_static inline int
18519220bc1SDavid Schultz feupdateenv(const fenv_t *__envp)
18619220bc1SDavid Schultz {
18719220bc1SDavid Schultz 	fexcept_t __fpsr;
18819220bc1SDavid Schultz 
18919220bc1SDavid Schultz 	__rfs(&__fpsr);
19019220bc1SDavid Schultz 	__wfs(*__envp);
19119220bc1SDavid Schultz 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
19219220bc1SDavid Schultz 	return (0);
19319220bc1SDavid Schultz }
19419220bc1SDavid Schultz 
19519220bc1SDavid Schultz #if __BSD_VISIBLE
19619220bc1SDavid Schultz 
197d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */
198d78e594bSDavid Schultz 
199d78e594bSDavid Schultz static inline int
20010b01832SDavid Schultz feenableexcept(int __mask)
20119220bc1SDavid Schultz {
20210b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
20319220bc1SDavid Schultz 
20410b01832SDavid Schultz 	__rfs(&__old_fpsr);
20510b01832SDavid Schultz 	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
20610b01832SDavid Schultz 	__wfs(__new_fpsr);
20710b01832SDavid Schultz 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
20819220bc1SDavid Schultz }
20919220bc1SDavid Schultz 
210d78e594bSDavid Schultz static inline int
21110b01832SDavid Schultz fedisableexcept(int __mask)
21210b01832SDavid Schultz {
21310b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
21410b01832SDavid Schultz 
21510b01832SDavid Schultz 	__rfs(&__old_fpsr);
21610b01832SDavid Schultz 	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
21710b01832SDavid Schultz 	__wfs(__new_fpsr);
21810b01832SDavid Schultz 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
21910b01832SDavid Schultz }
22010b01832SDavid Schultz 
221d78e594bSDavid Schultz static inline int
22210b01832SDavid Schultz fegetexcept(void)
22319220bc1SDavid Schultz {
22419220bc1SDavid Schultz 	fenv_t __fpsr;
22519220bc1SDavid Schultz 
22619220bc1SDavid Schultz 	__rfs(&__fpsr);
22719220bc1SDavid Schultz 	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
22819220bc1SDavid Schultz }
22919220bc1SDavid Schultz 
23019220bc1SDavid Schultz #endif /* __BSD_VISIBLE */
23119220bc1SDavid Schultz 
2327bde21b1SDavid Schultz #endif	/* ARM_HARD_FLOAT */
2337bde21b1SDavid Schultz 
23419220bc1SDavid Schultz __END_DECLS
23519220bc1SDavid Schultz 
23619220bc1SDavid Schultz #endif	/* !_FENV_H_ */
237