fenv.h revision 266133
1/*-
2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: stable/10/lib/msun/arm/fenv.h 266133 2014-05-15 15:02:48Z ian $
27 */
28
29#ifndef	_FENV_H_
30#define	_FENV_H_
31
32#include <sys/_types.h>
33
34#ifndef	__fenv_static
35#define	__fenv_static	static
36#endif
37
38typedef	__uint32_t	fenv_t;
39typedef	__uint32_t	fexcept_t;
40
41/* Exception flags */
42#define	FE_INVALID	0x0001
43#define	FE_DIVBYZERO	0x0002
44#define	FE_OVERFLOW	0x0004
45#define	FE_UNDERFLOW	0x0008
46#define	FE_INEXACT	0x0010
47#ifdef __ARM_PCS_VFP
48#define	FE_DENORMAL	0x0080
49#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
50			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
51#else
52#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
53			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
54#endif
55
56/* Rounding modes */
57#ifdef __ARM_PCS_VFP
58#define	FE_TONEAREST	0x00000000
59#define	FE_UPWARD	0x00400000
60#define	FE_DOWNWARD	0x00800000
61#define	FE_TOWARDZERO	0x00c00000
62#else
63#define	FE_TONEAREST	0x0000
64#define	FE_TOWARDZERO	0x0001
65#define	FE_UPWARD	0x0002
66#define	FE_DOWNWARD	0x0003
67#endif
68#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
69			 FE_UPWARD | FE_TOWARDZERO)
70__BEGIN_DECLS
71
72/* Default floating-point environment */
73extern const fenv_t	__fe_dfl_env;
74#define	FE_DFL_ENV	(&__fe_dfl_env)
75
76/* We need to be able to map status flag positions to mask flag positions */
77#ifndef __ARM_PCS_VFP
78#define	_FPUSW_SHIFT	16
79#define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
80#endif
81
82#ifndef __ARM_PCS_VFP
83
84int feclearexcept(int __excepts);
85int fegetexceptflag(fexcept_t *__flagp, int __excepts);
86int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
87int feraiseexcept(int __excepts);
88int fetestexcept(int __excepts);
89int fegetround(void);
90int fesetround(int __round);
91int fegetenv(fenv_t *__envp);
92int feholdexcept(fenv_t *__envp);
93int fesetenv(const fenv_t *__envp);
94int feupdateenv(const fenv_t *__envp);
95
96#else	/* __ARM_PCS_VFP */
97
98#define	vmrs_fpscr(__r)	__asm __volatile("vmrs %0, fpscr" : "=&r"(__r))
99#define	vmsr_fpscr(__r)	__asm __volatile("vmsr fpscr, %0" : : "r"(__r))
100
101#define _FPU_MASK_SHIFT	8
102
103__fenv_static inline int
104feclearexcept(int __excepts)
105{
106	fexcept_t __fpsr;
107
108	vmrs_fpscr(__fpsr);
109	__fpsr &= ~__excepts;
110	vmsr_fpscr(__fpsr);
111	return (0);
112}
113
114__fenv_static inline int
115fegetexceptflag(fexcept_t *__flagp, int __excepts)
116{
117	fexcept_t __fpsr;
118
119	vmrs_fpscr(__fpsr);
120	*__flagp = __fpsr & __excepts;
121	return (0);
122}
123
124__fenv_static inline int
125fesetexceptflag(const fexcept_t *__flagp, int __excepts)
126{
127	fexcept_t __fpsr;
128
129	vmrs_fpscr(__fpsr);
130	__fpsr &= ~__excepts;
131	__fpsr |= *__flagp & __excepts;
132	vmsr_fpscr(__fpsr);
133	return (0);
134}
135
136__fenv_static inline int
137feraiseexcept(int __excepts)
138{
139	fexcept_t __ex = __excepts;
140
141	fesetexceptflag(&__ex, __excepts);	/* XXX */
142	return (0);
143}
144
145__fenv_static inline int
146fetestexcept(int __excepts)
147{
148	fexcept_t __fpsr;
149
150	vmrs_fpscr(__fpsr);
151	return (__fpsr & __excepts);
152}
153
154__fenv_static inline int
155fegetround(void)
156{
157	fenv_t __fpsr;
158
159	vmrs_fpscr(__fpsr);
160	return (__fpsr & _ROUND_MASK);
161}
162
163__fenv_static inline int
164fesetround(int __round)
165{
166	fenv_t __fpsr;
167
168	vmrs_fpscr(__fpsr);
169	__fpsr &= ~(_ROUND_MASK);
170	__fpsr |= __round;
171	vmsr_fpscr(__fpsr);
172	return (0);
173}
174
175__fenv_static inline int
176fegetenv(fenv_t *__envp)
177{
178
179	vmrs_fpscr(*__envp);
180	return (0);
181}
182
183__fenv_static inline int
184feholdexcept(fenv_t *__envp)
185{
186	fenv_t __env;
187
188	vmrs_fpscr(__env);
189	*__envp = __env;
190	__env &= ~(FE_ALL_EXCEPT);
191	vmsr_fpscr(__env);
192	return (0);
193}
194
195__fenv_static inline int
196fesetenv(const fenv_t *__envp)
197{
198
199	vmsr_fpscr(*__envp);
200	return (0);
201}
202
203__fenv_static inline int
204feupdateenv(const fenv_t *__envp)
205{
206	fexcept_t __fpsr;
207
208	vmrs_fpscr(__fpsr);
209	vmsr_fpscr(*__envp);
210	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
211	return (0);
212}
213
214#if __BSD_VISIBLE
215
216/* We currently provide no external definitions of the functions below. */
217
218__fenv_static inline int
219feenableexcept(int __mask)
220{
221	fenv_t __old_fpsr, __new_fpsr;
222
223	vmrs_fpscr(__old_fpsr);
224	__new_fpsr = __old_fpsr |
225	    ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
226	vmsr_fpscr(__new_fpsr);
227	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
228}
229
230__fenv_static inline int
231fedisableexcept(int __mask)
232{
233	fenv_t __old_fpsr, __new_fpsr;
234
235	vmrs_fpscr(__old_fpsr);
236	__new_fpsr = __old_fpsr &
237	    ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
238	vmsr_fpscr(__new_fpsr);
239	return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
240}
241
242__fenv_static inline int
243fegetexcept(void)
244{
245	fenv_t __fpsr;
246
247	vmrs_fpscr(__fpsr);
248	return (__fpsr & FE_ALL_EXCEPT);
249}
250
251#endif /* __BSD_VISIBLE */
252
253#endif	/* __ARM_PCS_VFP */
254
255__END_DECLS
256
257#endif	/* !_FENV_H_ */
258