xref: /freebsd/lib/msun/arm/fenv.h (revision 5e53a4f90f82c4345f277dd87cc9292f26e04a29)
119220bc1SDavid Schultz /*-
2*5e53a4f9SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*5e53a4f9SPedro F. Giffuni  *
410b01832SDavid Schultz  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
519220bc1SDavid Schultz  * All rights reserved.
619220bc1SDavid Schultz  *
719220bc1SDavid Schultz  * Redistribution and use in source and binary forms, with or without
819220bc1SDavid Schultz  * modification, are permitted provided that the following conditions
919220bc1SDavid Schultz  * are met:
1019220bc1SDavid Schultz  * 1. Redistributions of source code must retain the above copyright
1119220bc1SDavid Schultz  *    notice, this list of conditions and the following disclaimer.
1219220bc1SDavid Schultz  * 2. Redistributions in binary form must reproduce the above copyright
1319220bc1SDavid Schultz  *    notice, this list of conditions and the following disclaimer in the
1419220bc1SDavid Schultz  *    documentation and/or other materials provided with the distribution.
1519220bc1SDavid Schultz  *
1619220bc1SDavid Schultz  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1719220bc1SDavid Schultz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1819220bc1SDavid Schultz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1919220bc1SDavid Schultz  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2019220bc1SDavid Schultz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2119220bc1SDavid Schultz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2219220bc1SDavid Schultz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2319220bc1SDavid Schultz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2419220bc1SDavid Schultz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2519220bc1SDavid Schultz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2619220bc1SDavid Schultz  * SUCH DAMAGE.
2719220bc1SDavid Schultz  *
2819220bc1SDavid Schultz  * $FreeBSD$
2919220bc1SDavid Schultz  */
3019220bc1SDavid Schultz 
3119220bc1SDavid Schultz #ifndef	_FENV_H_
3219220bc1SDavid Schultz #define	_FENV_H_
3319220bc1SDavid Schultz 
3419220bc1SDavid Schultz #include <sys/_types.h>
3519220bc1SDavid Schultz 
36d78e594bSDavid Schultz #ifndef	__fenv_static
37d78e594bSDavid Schultz #define	__fenv_static	static
38d78e594bSDavid Schultz #endif
39d78e594bSDavid Schultz 
4019220bc1SDavid Schultz typedef	__uint32_t	fenv_t;
4119220bc1SDavid Schultz typedef	__uint32_t	fexcept_t;
4219220bc1SDavid Schultz 
4319220bc1SDavid Schultz /* Exception flags */
4419220bc1SDavid Schultz #define	FE_INVALID	0x0001
4519220bc1SDavid Schultz #define	FE_DIVBYZERO	0x0002
4619220bc1SDavid Schultz #define	FE_OVERFLOW	0x0004
4719220bc1SDavid Schultz #define	FE_UNDERFLOW	0x0008
4819220bc1SDavid Schultz #define	FE_INEXACT	0x0010
49c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
50c9081a6cSAndrew Turner #define	FE_DENORMAL	0x0080
51c9081a6cSAndrew Turner #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
52c9081a6cSAndrew Turner 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
53c9081a6cSAndrew Turner #else
5419220bc1SDavid Schultz #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
5519220bc1SDavid Schultz 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
56c9081a6cSAndrew Turner #endif
5719220bc1SDavid Schultz 
5815d3b4dbSOlivier Houchard /* Rounding modes */
59bb6c193eSAndrew Turner #define	VFP_FE_TONEAREST	0x00000000
60bb6c193eSAndrew Turner #define	VFP_FE_UPWARD		0x00400000
61bb6c193eSAndrew Turner #define	VFP_FE_DOWNWARD		0x00800000
62bb6c193eSAndrew Turner #define	VFP_FE_TOWARDZERO	0x00c00000
63bb6c193eSAndrew Turner 
64c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
65bb6c193eSAndrew Turner #define	FE_TONEAREST	VFP_FE_TONEAREST
66bb6c193eSAndrew Turner #define	FE_UPWARD	VFP_FE_UPWARD
67bb6c193eSAndrew Turner #define	FE_DOWNWARD	VFP_FE_DOWNWARD
68bb6c193eSAndrew Turner #define	FE_TOWARDZERO	VFP_FE_TOWARDZERO
69c9081a6cSAndrew Turner #else
7015d3b4dbSOlivier Houchard #define	FE_TONEAREST	0x0000
7115d3b4dbSOlivier Houchard #define	FE_TOWARDZERO	0x0001
7215d3b4dbSOlivier Houchard #define	FE_UPWARD	0x0002
7315d3b4dbSOlivier Houchard #define	FE_DOWNWARD	0x0003
74c9081a6cSAndrew Turner #endif
7515d3b4dbSOlivier Houchard #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
7615d3b4dbSOlivier Houchard 			 FE_UPWARD | FE_TOWARDZERO)
7719220bc1SDavid Schultz __BEGIN_DECLS
7819220bc1SDavid Schultz 
7919220bc1SDavid Schultz /* Default floating-point environment */
8019220bc1SDavid Schultz extern const fenv_t	__fe_dfl_env;
8119220bc1SDavid Schultz #define	FE_DFL_ENV	(&__fe_dfl_env)
8219220bc1SDavid Schultz 
8319220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */
84c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
8519220bc1SDavid Schultz #define	_FPUSW_SHIFT	16
8619220bc1SDavid Schultz #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
87c9081a6cSAndrew Turner #endif
8819220bc1SDavid Schultz 
89c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
907082a2cfSDavid Schultz 
917082a2cfSDavid Schultz int feclearexcept(int __excepts);
927082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts);
937082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
947082a2cfSDavid Schultz int feraiseexcept(int __excepts);
957082a2cfSDavid Schultz int fetestexcept(int __excepts);
967082a2cfSDavid Schultz int fegetround(void);
977082a2cfSDavid Schultz int fesetround(int __round);
987082a2cfSDavid Schultz int fegetenv(fenv_t *__envp);
997082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp);
1007082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp);
1017082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp);
102bb6c193eSAndrew Turner #if __BSD_VISIBLE
103bb6c193eSAndrew Turner int feenableexcept(int __mask);
104bb6c193eSAndrew Turner int fedisableexcept(int __mask);
105bb6c193eSAndrew Turner int fegetexcept(void);
106bb6c193eSAndrew Turner #endif
1077bde21b1SDavid Schultz 
108c9081a6cSAndrew Turner #else	/* __ARM_PCS_VFP */
1097bde21b1SDavid Schultz 
110c9081a6cSAndrew Turner #define	vmrs_fpscr(__r)	__asm __volatile("vmrs %0, fpscr" : "=&r"(__r))
111c9081a6cSAndrew Turner #define	vmsr_fpscr(__r)	__asm __volatile("vmsr fpscr, %0" : : "r"(__r))
11219220bc1SDavid Schultz 
113a541d15cSAndrew Turner #define _FPU_MASK_SHIFT	8
114a541d15cSAndrew Turner 
115d78e594bSDavid Schultz __fenv_static inline int
11619220bc1SDavid Schultz feclearexcept(int __excepts)
11719220bc1SDavid Schultz {
11819220bc1SDavid Schultz 	fexcept_t __fpsr;
11919220bc1SDavid Schultz 
120c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
12119220bc1SDavid Schultz 	__fpsr &= ~__excepts;
122c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
12319220bc1SDavid Schultz 	return (0);
12419220bc1SDavid Schultz }
12519220bc1SDavid Schultz 
126d78e594bSDavid Schultz __fenv_static inline int
12719220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
12819220bc1SDavid Schultz {
12919220bc1SDavid Schultz 	fexcept_t __fpsr;
13019220bc1SDavid Schultz 
131c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
13219220bc1SDavid Schultz 	*__flagp = __fpsr & __excepts;
13319220bc1SDavid Schultz 	return (0);
13419220bc1SDavid Schultz }
13519220bc1SDavid Schultz 
136d78e594bSDavid Schultz __fenv_static inline int
13719220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
13819220bc1SDavid Schultz {
13919220bc1SDavid Schultz 	fexcept_t __fpsr;
14019220bc1SDavid Schultz 
141c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
14219220bc1SDavid Schultz 	__fpsr &= ~__excepts;
14319220bc1SDavid Schultz 	__fpsr |= *__flagp & __excepts;
144c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
14519220bc1SDavid Schultz 	return (0);
14619220bc1SDavid Schultz }
14719220bc1SDavid Schultz 
148d78e594bSDavid Schultz __fenv_static inline int
14919220bc1SDavid Schultz feraiseexcept(int __excepts)
15019220bc1SDavid Schultz {
15119220bc1SDavid Schultz 	fexcept_t __ex = __excepts;
15219220bc1SDavid Schultz 
15319220bc1SDavid Schultz 	fesetexceptflag(&__ex, __excepts);	/* XXX */
15419220bc1SDavid Schultz 	return (0);
15519220bc1SDavid Schultz }
15619220bc1SDavid Schultz 
157d78e594bSDavid Schultz __fenv_static inline int
15819220bc1SDavid Schultz fetestexcept(int __excepts)
15919220bc1SDavid Schultz {
16019220bc1SDavid Schultz 	fexcept_t __fpsr;
16119220bc1SDavid Schultz 
162c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
16319220bc1SDavid Schultz 	return (__fpsr & __excepts);
16419220bc1SDavid Schultz }
16519220bc1SDavid Schultz 
166d78e594bSDavid Schultz __fenv_static inline int
16719220bc1SDavid Schultz fegetround(void)
16819220bc1SDavid Schultz {
169c9081a6cSAndrew Turner 	fenv_t __fpsr;
17019220bc1SDavid Schultz 
171c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
172c9081a6cSAndrew Turner 	return (__fpsr & _ROUND_MASK);
17319220bc1SDavid Schultz }
17419220bc1SDavid Schultz 
175d78e594bSDavid Schultz __fenv_static inline int
17619220bc1SDavid Schultz fesetround(int __round)
17719220bc1SDavid Schultz {
178c9081a6cSAndrew Turner 	fenv_t __fpsr;
17919220bc1SDavid Schultz 
180c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
181c9081a6cSAndrew Turner 	__fpsr &= ~(_ROUND_MASK);
182c9081a6cSAndrew Turner 	__fpsr |= __round;
183c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
184c9081a6cSAndrew Turner 	return (0);
18519220bc1SDavid Schultz }
18619220bc1SDavid Schultz 
187d78e594bSDavid Schultz __fenv_static inline int
18819220bc1SDavid Schultz fegetenv(fenv_t *__envp)
18919220bc1SDavid Schultz {
19019220bc1SDavid Schultz 
191c9081a6cSAndrew Turner 	vmrs_fpscr(*__envp);
19219220bc1SDavid Schultz 	return (0);
19319220bc1SDavid Schultz }
19419220bc1SDavid Schultz 
195d78e594bSDavid Schultz __fenv_static inline int
19619220bc1SDavid Schultz feholdexcept(fenv_t *__envp)
19719220bc1SDavid Schultz {
19819220bc1SDavid Schultz 	fenv_t __env;
19919220bc1SDavid Schultz 
200c9081a6cSAndrew Turner 	vmrs_fpscr(__env);
20119220bc1SDavid Schultz 	*__envp = __env;
202c9081a6cSAndrew Turner 	__env &= ~(FE_ALL_EXCEPT);
203c9081a6cSAndrew Turner 	vmsr_fpscr(__env);
20419220bc1SDavid Schultz 	return (0);
20519220bc1SDavid Schultz }
20619220bc1SDavid Schultz 
207d78e594bSDavid Schultz __fenv_static inline int
20819220bc1SDavid Schultz fesetenv(const fenv_t *__envp)
20919220bc1SDavid Schultz {
21019220bc1SDavid Schultz 
211c9081a6cSAndrew Turner 	vmsr_fpscr(*__envp);
21219220bc1SDavid Schultz 	return (0);
21319220bc1SDavid Schultz }
21419220bc1SDavid Schultz 
215d78e594bSDavid Schultz __fenv_static inline int
21619220bc1SDavid Schultz feupdateenv(const fenv_t *__envp)
21719220bc1SDavid Schultz {
21819220bc1SDavid Schultz 	fexcept_t __fpsr;
21919220bc1SDavid Schultz 
220c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
221c9081a6cSAndrew Turner 	vmsr_fpscr(*__envp);
22219220bc1SDavid Schultz 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
22319220bc1SDavid Schultz 	return (0);
22419220bc1SDavid Schultz }
22519220bc1SDavid Schultz 
22619220bc1SDavid Schultz #if __BSD_VISIBLE
22719220bc1SDavid Schultz 
228d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */
229d78e594bSDavid Schultz 
230a541d15cSAndrew Turner __fenv_static inline int
23110b01832SDavid Schultz feenableexcept(int __mask)
23219220bc1SDavid Schultz {
23310b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
23419220bc1SDavid Schultz 
235c9081a6cSAndrew Turner 	vmrs_fpscr(__old_fpsr);
236a541d15cSAndrew Turner 	__new_fpsr = __old_fpsr |
237a541d15cSAndrew Turner 	    ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
238c9081a6cSAndrew Turner 	vmsr_fpscr(__new_fpsr);
239a541d15cSAndrew Turner 	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
24019220bc1SDavid Schultz }
24119220bc1SDavid Schultz 
242a541d15cSAndrew Turner __fenv_static inline int
24310b01832SDavid Schultz fedisableexcept(int __mask)
24410b01832SDavid Schultz {
24510b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
24610b01832SDavid Schultz 
247c9081a6cSAndrew Turner 	vmrs_fpscr(__old_fpsr);
248a541d15cSAndrew Turner 	__new_fpsr = __old_fpsr &
249a541d15cSAndrew Turner 	    ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
250c9081a6cSAndrew Turner 	vmsr_fpscr(__new_fpsr);
251a541d15cSAndrew Turner 	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
25210b01832SDavid Schultz }
25310b01832SDavid Schultz 
254a541d15cSAndrew Turner __fenv_static inline int
25510b01832SDavid Schultz fegetexcept(void)
25619220bc1SDavid Schultz {
25719220bc1SDavid Schultz 	fenv_t __fpsr;
25819220bc1SDavid Schultz 
259c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
260c9081a6cSAndrew Turner 	return (__fpsr & FE_ALL_EXCEPT);
26119220bc1SDavid Schultz }
26219220bc1SDavid Schultz 
26319220bc1SDavid Schultz #endif /* __BSD_VISIBLE */
26419220bc1SDavid Schultz 
265c9081a6cSAndrew Turner #endif	/* __ARM_PCS_VFP */
2667bde21b1SDavid Schultz 
26719220bc1SDavid Schultz __END_DECLS
26819220bc1SDavid Schultz 
26919220bc1SDavid Schultz #endif	/* !_FENV_H_ */
270