xref: /freebsd/lib/msun/arm/fenv.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
119220bc1SDavid Schultz /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro 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 
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
47c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
48c9081a6cSAndrew Turner #define	FE_DENORMAL	0x0080
49c9081a6cSAndrew Turner #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
50c9081a6cSAndrew Turner 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
51c9081a6cSAndrew Turner #else
5219220bc1SDavid Schultz #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
5319220bc1SDavid Schultz 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
54c9081a6cSAndrew Turner #endif
5519220bc1SDavid Schultz 
5615d3b4dbSOlivier Houchard /* Rounding modes */
57bb6c193eSAndrew Turner #define	VFP_FE_TONEAREST	0x00000000
58bb6c193eSAndrew Turner #define	VFP_FE_UPWARD		0x00400000
59bb6c193eSAndrew Turner #define	VFP_FE_DOWNWARD		0x00800000
60bb6c193eSAndrew Turner #define	VFP_FE_TOWARDZERO	0x00c00000
61bb6c193eSAndrew Turner 
62c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
63bb6c193eSAndrew Turner #define	FE_TONEAREST	VFP_FE_TONEAREST
64bb6c193eSAndrew Turner #define	FE_UPWARD	VFP_FE_UPWARD
65bb6c193eSAndrew Turner #define	FE_DOWNWARD	VFP_FE_DOWNWARD
66bb6c193eSAndrew Turner #define	FE_TOWARDZERO	VFP_FE_TOWARDZERO
67c9081a6cSAndrew Turner #else
6815d3b4dbSOlivier Houchard #define	FE_TONEAREST	0x0000
6915d3b4dbSOlivier Houchard #define	FE_TOWARDZERO	0x0001
7015d3b4dbSOlivier Houchard #define	FE_UPWARD	0x0002
7115d3b4dbSOlivier Houchard #define	FE_DOWNWARD	0x0003
72c9081a6cSAndrew Turner #endif
7315d3b4dbSOlivier Houchard #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
7415d3b4dbSOlivier Houchard 			 FE_UPWARD | FE_TOWARDZERO)
7519220bc1SDavid Schultz __BEGIN_DECLS
7619220bc1SDavid Schultz 
7719220bc1SDavid Schultz /* Default floating-point environment */
7819220bc1SDavid Schultz extern const fenv_t	__fe_dfl_env;
7919220bc1SDavid Schultz #define	FE_DFL_ENV	(&__fe_dfl_env)
8019220bc1SDavid Schultz 
8119220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */
82c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
8319220bc1SDavid Schultz #define	_FPUSW_SHIFT	16
8419220bc1SDavid Schultz #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
85c9081a6cSAndrew Turner #endif
8619220bc1SDavid Schultz 
87c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
887082a2cfSDavid Schultz 
897082a2cfSDavid Schultz int feclearexcept(int __excepts);
907082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts);
917082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
927082a2cfSDavid Schultz int feraiseexcept(int __excepts);
937082a2cfSDavid Schultz int fetestexcept(int __excepts);
947082a2cfSDavid Schultz int fegetround(void);
957082a2cfSDavid Schultz int fesetround(int __round);
967082a2cfSDavid Schultz int fegetenv(fenv_t *__envp);
977082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp);
987082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp);
997082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp);
100bb6c193eSAndrew Turner #if __BSD_VISIBLE
101bb6c193eSAndrew Turner int feenableexcept(int __mask);
102bb6c193eSAndrew Turner int fedisableexcept(int __mask);
103bb6c193eSAndrew Turner int fegetexcept(void);
104bb6c193eSAndrew Turner #endif
1057bde21b1SDavid Schultz 
106c9081a6cSAndrew Turner #else	/* __ARM_PCS_VFP */
1077bde21b1SDavid Schultz 
108c9081a6cSAndrew Turner #define	vmrs_fpscr(__r)	__asm __volatile("vmrs %0, fpscr" : "=&r"(__r))
109c9081a6cSAndrew Turner #define	vmsr_fpscr(__r)	__asm __volatile("vmsr fpscr, %0" : : "r"(__r))
11019220bc1SDavid Schultz 
111a541d15cSAndrew Turner #define _FPU_MASK_SHIFT	8
112a541d15cSAndrew Turner 
113d78e594bSDavid Schultz __fenv_static inline int
feclearexcept(int __excepts)11419220bc1SDavid Schultz feclearexcept(int __excepts)
11519220bc1SDavid Schultz {
11619220bc1SDavid Schultz 	fexcept_t __fpsr;
11719220bc1SDavid Schultz 
118c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
11919220bc1SDavid Schultz 	__fpsr &= ~__excepts;
120c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
12119220bc1SDavid Schultz 	return (0);
12219220bc1SDavid Schultz }
12319220bc1SDavid Schultz 
124d78e594bSDavid Schultz __fenv_static inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)12519220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
12619220bc1SDavid Schultz {
12719220bc1SDavid Schultz 	fexcept_t __fpsr;
12819220bc1SDavid Schultz 
129c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
13019220bc1SDavid Schultz 	*__flagp = __fpsr & __excepts;
13119220bc1SDavid Schultz 	return (0);
13219220bc1SDavid Schultz }
13319220bc1SDavid Schultz 
134d78e594bSDavid Schultz __fenv_static inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)13519220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
13619220bc1SDavid Schultz {
13719220bc1SDavid Schultz 	fexcept_t __fpsr;
13819220bc1SDavid Schultz 
139c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
14019220bc1SDavid Schultz 	__fpsr &= ~__excepts;
14119220bc1SDavid Schultz 	__fpsr |= *__flagp & __excepts;
142c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
14319220bc1SDavid Schultz 	return (0);
14419220bc1SDavid Schultz }
14519220bc1SDavid Schultz 
146d78e594bSDavid Schultz __fenv_static inline int
feraiseexcept(int __excepts)14719220bc1SDavid Schultz feraiseexcept(int __excepts)
14819220bc1SDavid Schultz {
14919220bc1SDavid Schultz 	fexcept_t __ex = __excepts;
15019220bc1SDavid Schultz 
15119220bc1SDavid Schultz 	fesetexceptflag(&__ex, __excepts);	/* XXX */
15219220bc1SDavid Schultz 	return (0);
15319220bc1SDavid Schultz }
15419220bc1SDavid Schultz 
155d78e594bSDavid Schultz __fenv_static inline int
fetestexcept(int __excepts)15619220bc1SDavid Schultz fetestexcept(int __excepts)
15719220bc1SDavid Schultz {
15819220bc1SDavid Schultz 	fexcept_t __fpsr;
15919220bc1SDavid Schultz 
160c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
16119220bc1SDavid Schultz 	return (__fpsr & __excepts);
16219220bc1SDavid Schultz }
16319220bc1SDavid Schultz 
164d78e594bSDavid Schultz __fenv_static inline int
fegetround(void)16519220bc1SDavid Schultz fegetround(void)
16619220bc1SDavid Schultz {
167c9081a6cSAndrew Turner 	fenv_t __fpsr;
16819220bc1SDavid Schultz 
169c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
170c9081a6cSAndrew Turner 	return (__fpsr & _ROUND_MASK);
17119220bc1SDavid Schultz }
17219220bc1SDavid Schultz 
173d78e594bSDavid Schultz __fenv_static inline int
fesetround(int __round)17419220bc1SDavid Schultz fesetround(int __round)
17519220bc1SDavid Schultz {
176c9081a6cSAndrew Turner 	fenv_t __fpsr;
17719220bc1SDavid Schultz 
178c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
179c9081a6cSAndrew Turner 	__fpsr &= ~(_ROUND_MASK);
180c9081a6cSAndrew Turner 	__fpsr |= __round;
181c9081a6cSAndrew Turner 	vmsr_fpscr(__fpsr);
182c9081a6cSAndrew Turner 	return (0);
18319220bc1SDavid Schultz }
18419220bc1SDavid Schultz 
185d78e594bSDavid Schultz __fenv_static inline int
fegetenv(fenv_t * __envp)18619220bc1SDavid Schultz fegetenv(fenv_t *__envp)
18719220bc1SDavid Schultz {
18819220bc1SDavid Schultz 
189c9081a6cSAndrew Turner 	vmrs_fpscr(*__envp);
19019220bc1SDavid Schultz 	return (0);
19119220bc1SDavid Schultz }
19219220bc1SDavid Schultz 
193d78e594bSDavid Schultz __fenv_static inline int
feholdexcept(fenv_t * __envp)19419220bc1SDavid Schultz feholdexcept(fenv_t *__envp)
19519220bc1SDavid Schultz {
19619220bc1SDavid Schultz 	fenv_t __env;
19719220bc1SDavid Schultz 
198c9081a6cSAndrew Turner 	vmrs_fpscr(__env);
19919220bc1SDavid Schultz 	*__envp = __env;
200c9081a6cSAndrew Turner 	__env &= ~(FE_ALL_EXCEPT);
201c9081a6cSAndrew Turner 	vmsr_fpscr(__env);
20219220bc1SDavid Schultz 	return (0);
20319220bc1SDavid Schultz }
20419220bc1SDavid Schultz 
205d78e594bSDavid Schultz __fenv_static inline int
fesetenv(const fenv_t * __envp)20619220bc1SDavid Schultz fesetenv(const fenv_t *__envp)
20719220bc1SDavid Schultz {
20819220bc1SDavid Schultz 
209c9081a6cSAndrew Turner 	vmsr_fpscr(*__envp);
21019220bc1SDavid Schultz 	return (0);
21119220bc1SDavid Schultz }
21219220bc1SDavid Schultz 
213d78e594bSDavid Schultz __fenv_static inline int
feupdateenv(const fenv_t * __envp)21419220bc1SDavid Schultz feupdateenv(const fenv_t *__envp)
21519220bc1SDavid Schultz {
21619220bc1SDavid Schultz 	fexcept_t __fpsr;
21719220bc1SDavid Schultz 
218c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
219c9081a6cSAndrew Turner 	vmsr_fpscr(*__envp);
22019220bc1SDavid Schultz 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
22119220bc1SDavid Schultz 	return (0);
22219220bc1SDavid Schultz }
22319220bc1SDavid Schultz 
22419220bc1SDavid Schultz #if __BSD_VISIBLE
22519220bc1SDavid Schultz 
226d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */
227d78e594bSDavid Schultz 
228a541d15cSAndrew Turner __fenv_static inline int
feenableexcept(int __mask)22910b01832SDavid Schultz feenableexcept(int __mask)
23019220bc1SDavid Schultz {
23110b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
23219220bc1SDavid Schultz 
233c9081a6cSAndrew Turner 	vmrs_fpscr(__old_fpsr);
234a541d15cSAndrew Turner 	__new_fpsr = __old_fpsr |
235a541d15cSAndrew Turner 	    ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
236c9081a6cSAndrew Turner 	vmsr_fpscr(__new_fpsr);
237a541d15cSAndrew Turner 	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
23819220bc1SDavid Schultz }
23919220bc1SDavid Schultz 
240a541d15cSAndrew Turner __fenv_static inline int
fedisableexcept(int __mask)24110b01832SDavid Schultz fedisableexcept(int __mask)
24210b01832SDavid Schultz {
24310b01832SDavid Schultz 	fenv_t __old_fpsr, __new_fpsr;
24410b01832SDavid Schultz 
245c9081a6cSAndrew Turner 	vmrs_fpscr(__old_fpsr);
246a541d15cSAndrew Turner 	__new_fpsr = __old_fpsr &
247a541d15cSAndrew Turner 	    ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
248c9081a6cSAndrew Turner 	vmsr_fpscr(__new_fpsr);
249a541d15cSAndrew Turner 	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
25010b01832SDavid Schultz }
25110b01832SDavid Schultz 
252a541d15cSAndrew Turner __fenv_static inline int
fegetexcept(void)25310b01832SDavid Schultz fegetexcept(void)
25419220bc1SDavid Schultz {
25519220bc1SDavid Schultz 	fenv_t __fpsr;
25619220bc1SDavid Schultz 
257c9081a6cSAndrew Turner 	vmrs_fpscr(__fpsr);
258c9081a6cSAndrew Turner 	return (__fpsr & FE_ALL_EXCEPT);
25919220bc1SDavid Schultz }
26019220bc1SDavid Schultz 
26119220bc1SDavid Schultz #endif /* __BSD_VISIBLE */
26219220bc1SDavid Schultz 
263c9081a6cSAndrew Turner #endif	/* __ARM_PCS_VFP */
2647bde21b1SDavid Schultz 
26519220bc1SDavid Schultz __END_DECLS
26619220bc1SDavid Schultz 
26719220bc1SDavid Schultz #endif	/* !_FENV_H_ */
268