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