xref: /freebsd/lib/msun/arm/fenv.h (revision 7bde21b1f9dd0d78e077507f9e4ddb055067809a)
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 
67*7bde21b1SDavid Schultz #ifndef	ARM_HARD_FLOAT
68*7bde21b1SDavid Schultz /*
69*7bde21b1SDavid Schultz  * The following macros map between the softfloat emulator's flags and
70*7bde21b1SDavid Schultz  * the hardware's FPSR.  The hardware this file was written for doesn't
71*7bde21b1SDavid Schultz  * have rounding control bits, so we stick those in the system ID byte.
72*7bde21b1SDavid Schultz  */
73*7bde21b1SDavid Schultz #define	__set_env(env, flags, mask, rnd) env = ((flags)			\
74*7bde21b1SDavid Schultz 						| (mask)<<_FPUSW_SHIFT	\
75*7bde21b1SDavid Schultz 						| (rnd) << 24)
76*7bde21b1SDavid Schultz #define	__env_flags(env)		((env) & FE_ALL_EXCEPT)
77*7bde21b1SDavid Schultz #define	__env_mask(env)			(((env) >> _FPUSW_SHIFT)	\
78*7bde21b1SDavid Schultz 						& FE_ALL_EXCEPT)
79*7bde21b1SDavid Schultz #define	__env_round(env)		(((env) >> 24) & _ROUND_MASK)
80*7bde21b1SDavid Schultz #include <fenv-softfloat.h>
81*7bde21b1SDavid Schultz 
82*7bde21b1SDavid Schultz #else	/* ARM_HARD_FLOAT */
83*7bde21b1SDavid Schultz 
84f365db00SDavid Schultz #define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
8560b22cf1SOlivier Houchard #define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
8619220bc1SDavid Schultz 
87d78e594bSDavid Schultz __fenv_static inline int
8819220bc1SDavid Schultz feclearexcept(int __excepts)
8919220bc1SDavid Schultz {
9019220bc1SDavid Schultz 	fexcept_t __fpsr;
9119220bc1SDavid Schultz 
9219220bc1SDavid Schultz 	__rfs(&__fpsr);
9319220bc1SDavid Schultz 	__fpsr &= ~__excepts;
9419220bc1SDavid Schultz 	__wfs(__fpsr);
9519220bc1SDavid Schultz 	return (0);
9619220bc1SDavid Schultz }
9719220bc1SDavid Schultz 
98d78e594bSDavid Schultz __fenv_static inline int
9919220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
10019220bc1SDavid Schultz {
10119220bc1SDavid Schultz 	fexcept_t __fpsr;
10219220bc1SDavid Schultz 
10319220bc1SDavid Schultz 	__rfs(&__fpsr);
10419220bc1SDavid Schultz 	*__flagp = __fpsr & __excepts;
10519220bc1SDavid Schultz 	return (0);
10619220bc1SDavid Schultz }
10719220bc1SDavid Schultz 
108d78e594bSDavid Schultz __fenv_static inline int
10919220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
11019220bc1SDavid Schultz {
11119220bc1SDavid Schultz 	fexcept_t __fpsr;
11219220bc1SDavid Schultz 
11319220bc1SDavid Schultz 	__rfs(&__fpsr);
11419220bc1SDavid Schultz 	__fpsr &= ~__excepts;
11519220bc1SDavid Schultz 	__fpsr |= *__flagp & __excepts;
11619220bc1SDavid Schultz 	__wfs(__fpsr);
11719220bc1SDavid Schultz 	return (0);
11819220bc1SDavid Schultz }
11919220bc1SDavid Schultz 
120d78e594bSDavid Schultz __fenv_static inline int
12119220bc1SDavid Schultz feraiseexcept(int __excepts)
12219220bc1SDavid Schultz {
12319220bc1SDavid Schultz 	fexcept_t __ex = __excepts;
12419220bc1SDavid Schultz 
12519220bc1SDavid Schultz 	fesetexceptflag(&__ex, __excepts);	/* XXX */
12619220bc1SDavid Schultz 	return (0);
12719220bc1SDavid Schultz }
12819220bc1SDavid Schultz 
129d78e594bSDavid Schultz __fenv_static inline int
13019220bc1SDavid Schultz fetestexcept(int __excepts)
13119220bc1SDavid Schultz {
13219220bc1SDavid Schultz 	fexcept_t __fpsr;
13319220bc1SDavid Schultz 
13419220bc1SDavid Schultz 	__rfs(&__fpsr);
13519220bc1SDavid Schultz 	return (__fpsr & __excepts);
13619220bc1SDavid Schultz }
13719220bc1SDavid Schultz 
138d78e594bSDavid Schultz __fenv_static inline int
13919220bc1SDavid Schultz fegetround(void)
14019220bc1SDavid Schultz {
14119220bc1SDavid Schultz 
14219220bc1SDavid Schultz 	/*
14319220bc1SDavid Schultz 	 * Apparently, the rounding mode is specified as part of the
14419220bc1SDavid Schultz 	 * instruction format on ARM, so the dynamic rounding mode is
14519220bc1SDavid Schultz 	 * indeterminate.  Some FPUs may differ.
14619220bc1SDavid Schultz 	 */
14719220bc1SDavid Schultz 	return (-1);
14819220bc1SDavid Schultz }
14919220bc1SDavid Schultz 
150d78e594bSDavid Schultz __fenv_static inline int
15119220bc1SDavid Schultz fesetround(int __round)
15219220bc1SDavid Schultz {
15319220bc1SDavid Schultz 
15419220bc1SDavid Schultz 	return (-1);
15519220bc1SDavid Schultz }
15619220bc1SDavid Schultz 
157d78e594bSDavid Schultz __fenv_static inline int
15819220bc1SDavid Schultz fegetenv(fenv_t *__envp)
15919220bc1SDavid Schultz {
16019220bc1SDavid Schultz 
16119220bc1SDavid Schultz 	__rfs(__envp);
16219220bc1SDavid Schultz 	return (0);
16319220bc1SDavid Schultz }
16419220bc1SDavid Schultz 
165d78e594bSDavid Schultz __fenv_static inline int
16619220bc1SDavid Schultz feholdexcept(fenv_t *__envp)
16719220bc1SDavid Schultz {
16819220bc1SDavid Schultz 	fenv_t __env;
16919220bc1SDavid Schultz 
17019220bc1SDavid Schultz 	__rfs(&__env);
17119220bc1SDavid Schultz 	*__envp = __env;
17219220bc1SDavid Schultz 	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
17319220bc1SDavid Schultz 	__wfs(__env);
17419220bc1SDavid Schultz 	return (0);
17519220bc1SDavid Schultz }
17619220bc1SDavid Schultz 
177d78e594bSDavid Schultz __fenv_static inline int
17819220bc1SDavid Schultz fesetenv(const fenv_t *__envp)
17919220bc1SDavid Schultz {
18019220bc1SDavid Schultz 
18119220bc1SDavid Schultz 	__wfs(*__envp);
18219220bc1SDavid Schultz 	return (0);
18319220bc1SDavid Schultz }
18419220bc1SDavid Schultz 
185d78e594bSDavid Schultz __fenv_static inline int
18619220bc1SDavid Schultz feupdateenv(const fenv_t *__envp)
18719220bc1SDavid Schultz {
18819220bc1SDavid Schultz 	fexcept_t __fpsr;
18919220bc1SDavid Schultz 
19019220bc1SDavid Schultz 	__rfs(&__fpsr);
19119220bc1SDavid Schultz 	__wfs(*__envp);
19219220bc1SDavid Schultz 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
19319220bc1SDavid Schultz 	return (0);
19419220bc1SDavid Schultz }
19519220bc1SDavid Schultz 
19619220bc1SDavid Schultz #if __BSD_VISIBLE
19719220bc1SDavid Schultz 
198d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */
199d78e594bSDavid Schultz 
200d78e594bSDavid Schultz static inline int
20110b01832SDavid Schultz feenableexcept(int __mask)
20219220bc1SDavid Schultz {
20310b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
20419220bc1SDavid Schultz 
20510b01832SDavid Schultz 	__rfs(&__old_fpsr);
20610b01832SDavid Schultz 	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
20710b01832SDavid Schultz 	__wfs(__new_fpsr);
20810b01832SDavid Schultz 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
20919220bc1SDavid Schultz }
21019220bc1SDavid Schultz 
211d78e594bSDavid Schultz static inline int
21210b01832SDavid Schultz fedisableexcept(int __mask)
21310b01832SDavid Schultz {
21410b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
21510b01832SDavid Schultz 
21610b01832SDavid Schultz 	__rfs(&__old_fpsr);
21710b01832SDavid Schultz 	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
21810b01832SDavid Schultz 	__wfs(__new_fpsr);
21910b01832SDavid Schultz 	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
22010b01832SDavid Schultz }
22110b01832SDavid Schultz 
222d78e594bSDavid Schultz static inline int
22310b01832SDavid Schultz fegetexcept(void)
22419220bc1SDavid Schultz {
22519220bc1SDavid Schultz 	fenv_t __fpsr;
22619220bc1SDavid Schultz 
22719220bc1SDavid Schultz 	__rfs(&__fpsr);
22819220bc1SDavid Schultz 	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
22919220bc1SDavid Schultz }
23019220bc1SDavid Schultz 
23119220bc1SDavid Schultz #endif /* __BSD_VISIBLE */
23219220bc1SDavid Schultz 
233*7bde21b1SDavid Schultz #endif	/* ARM_HARD_FLOAT */
234*7bde21b1SDavid Schultz 
23519220bc1SDavid Schultz __END_DECLS
23619220bc1SDavid Schultz 
23719220bc1SDavid Schultz #endif	/* !_FENV_H_ */
238