1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
5 * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include "fenv.h"
31
32 #include <machine/acle-compat.h>
33
34 /* When SOFTFP_ABI is defined we are using the softfp ABI. */
35 #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP)
36 #define SOFTFP_ABI
37 #endif
38
39
40 #ifndef FENV_MANGLE
41 /*
42 * Hopefully the system ID byte is immutable, so it's valid to use
43 * this as a default environment.
44 */
45 const fenv_t __fe_dfl_env = 0;
46 #endif
47
48
49 /* If this is a non-mangled softfp version special processing is required */
50 #if defined(FENV_MANGLE) || !defined(SOFTFP_ABI)
51
52 /*
53 * The following macros map between the softfloat emulator's flags and
54 * the hardware's FPSR. The hardware this file was written for doesn't
55 * have rounding control bits, so we stick those in the system ID byte.
56 */
57 #ifndef __ARM_PCS_VFP
58 #define __set_env(env, flags, mask, rnd) env = ((flags) \
59 | (mask)<<_FPUSW_SHIFT \
60 | (rnd) << 24)
61 #define __env_flags(env) ((env) & FE_ALL_EXCEPT)
62 #define __env_mask(env) (((env) >> _FPUSW_SHIFT) \
63 & FE_ALL_EXCEPT)
64 #define __env_round(env) (((env) >> 24) & _ROUND_MASK)
65 #include "fenv-softfloat.h"
66 #endif
67
68 int
69 (feclearexcept)(int excepts)
70 {
71 return (__feclearexcept_int(excepts));
72 }
73
74 int
75 (fegetexceptflag)(fexcept_t *flagp, int excepts)
76 {
77 return (__fegetexceptflag_int(flagp, excepts));
78 }
79
80 int
81 (fesetexceptflag)(const fexcept_t *flagp, int excepts)
82 {
83 return (__fesetexceptflag_int(flagp, excepts));
84 }
85
86 int
87 (feraiseexcept)(int excepts)
88 {
89 return (__feraiseexcept_int(excepts));
90 }
91
92 int
93 (fetestexcept)(int excepts)
94 {
95 return (__fetestexcept_int(excepts));
96 }
97
98 int
99 (fegetround)(void)
100 {
101 return (__fegetround_int());
102 }
103
104 int
105 (fesetround)(int round)
106 {
107 return (__fesetround_int(round));
108 }
109
110 int
111 (fegetenv)(fenv_t *envp)
112 {
113 return (__fegetenv_int(envp));
114 }
115
116 int
117 (feholdexcept)(fenv_t *envp)
118 {
119 return (__feholdexcept_int(envp));
120 }
121
122 int
123 (fesetenv)(const fenv_t *envp)
124 {
125 return (__fesetenv_int(envp));
126 }
127
128 int
129 (feupdateenv)(const fenv_t *envp)
130 {
131 return (__feupdateenv_int(envp));
132 }
133
134 int
135 (feenableexcept)(int mask)
136 {
137 return (__feenableexcept_int(mask));
138 }
139
140 int
141 (fedisableexcept)(int mask)
142 {
143 return (__fedisableexcept_int(mask));
144 }
145
146 int
147 (fegetexcept)(void)
148 {
149 return (__fegetexcept_int());
150 }
151
152 #else /* !FENV_MANGLE && SOFTFP_ABI */
153 /* Set by libc when the VFP unit is enabled */
154 extern int _libc_arm_fpu_present;
155
156 int __softfp_feclearexcept(int __excepts);
157 int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
158 int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
159 int __softfp_feraiseexcept(int __excepts);
160 int __softfp_fetestexcept(int __excepts);
161 int __softfp_fegetround(void);
162 int __softfp_fesetround(int __round);
163 int __softfp_fegetenv(fenv_t *__envp);
164 int __softfp_feholdexcept(fenv_t *__envp);
165 int __softfp_fesetenv(const fenv_t *__envp);
166 int __softfp_feupdateenv(const fenv_t *__envp);
167 int __softfp_feenableexcept(int __mask);
168 int __softfp_fedisableexcept(int __mask);
169 int __softfp_fegetexcept(void);
170
171 int __vfp_feclearexcept(int __excepts);
172 int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
173 int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
174 int __vfp_feraiseexcept(int __excepts);
175 int __vfp_fetestexcept(int __excepts);
176 int __vfp_fegetround(void);
177 int __vfp_fesetround(int __round);
178 int __vfp_fegetenv(fenv_t *__envp);
179 int __vfp_feholdexcept(fenv_t *__envp);
180 int __vfp_fesetenv(const fenv_t *__envp);
181 int __vfp_feupdateenv(const fenv_t *__envp);
182 int __vfp_feenableexcept(int __mask);
183 int __vfp_fedisableexcept(int __mask);
184 int __vfp_fegetexcept(void);
185
186 static int
__softfp_round_to_vfp(int round)187 __softfp_round_to_vfp(int round)
188 {
189
190 switch (round) {
191 case FE_TONEAREST:
192 default:
193 return VFP_FE_TONEAREST;
194 case FE_TOWARDZERO:
195 return VFP_FE_TOWARDZERO;
196 case FE_UPWARD:
197 return VFP_FE_UPWARD;
198 case FE_DOWNWARD:
199 return VFP_FE_DOWNWARD;
200 }
201 }
202
203 static int
__softfp_round_from_vfp(int round)204 __softfp_round_from_vfp(int round)
205 {
206
207 switch (round) {
208 case VFP_FE_TONEAREST:
209 default:
210 return FE_TONEAREST;
211 case VFP_FE_TOWARDZERO:
212 return FE_TOWARDZERO;
213 case VFP_FE_UPWARD:
214 return FE_UPWARD;
215 case VFP_FE_DOWNWARD:
216 return FE_DOWNWARD;
217 }
218 }
219
220 int
221 (feclearexcept)(int __excepts)
222 {
223
224 if (_libc_arm_fpu_present)
225 __vfp_feclearexcept(__excepts);
226 __softfp_feclearexcept(__excepts);
227
228 return (0);
229 }
230
231 int
232 (fegetexceptflag)(fexcept_t *__flagp, int __excepts)
233 {
234 fexcept_t __vfp_flagp;
235
236 __vfp_flagp = 0;
237 if (_libc_arm_fpu_present)
238 __vfp_fegetexceptflag(&__vfp_flagp, __excepts);
239 __softfp_fegetexceptflag(__flagp, __excepts);
240
241 *__flagp |= __vfp_flagp;
242
243 return (0);
244 }
245
246 int
247 (fesetexceptflag)(const fexcept_t *__flagp, int __excepts)
248 {
249
250 if (_libc_arm_fpu_present)
251 __vfp_fesetexceptflag(__flagp, __excepts);
252 __softfp_fesetexceptflag(__flagp, __excepts);
253
254 return (0);
255 }
256
257 int
258 (feraiseexcept)(int __excepts)
259 {
260
261 if (_libc_arm_fpu_present)
262 __vfp_feraiseexcept(__excepts);
263 __softfp_feraiseexcept(__excepts);
264
265 return (0);
266 }
267
268 int
269 (fetestexcept)(int __excepts)
270 {
271 int __got_excepts;
272
273 __got_excepts = 0;
274 if (_libc_arm_fpu_present)
275 __got_excepts = __vfp_fetestexcept(__excepts);
276 __got_excepts |= __softfp_fetestexcept(__excepts);
277
278 return (__got_excepts);
279 }
280
281 int
282 (fegetround)(void)
283 {
284
285 if (_libc_arm_fpu_present)
286 return __softfp_round_from_vfp(__vfp_fegetround());
287 return __softfp_fegetround();
288 }
289
290 int
291 (fesetround)(int __round)
292 {
293
294 if (_libc_arm_fpu_present)
295 __vfp_fesetround(__softfp_round_to_vfp(__round));
296 __softfp_fesetround(__round);
297
298 return (0);
299 }
300
301 int
302 (fegetenv)(fenv_t *__envp)
303 {
304 fenv_t __vfp_envp;
305
306 __vfp_envp = 0;
307 if (_libc_arm_fpu_present)
308 __vfp_fegetenv(&__vfp_envp);
309 __softfp_fegetenv(__envp);
310 *__envp |= __vfp_envp;
311
312 return (0);
313 }
314
315 int
316 (feholdexcept)(fenv_t *__envp)
317 {
318 fenv_t __vfp_envp;
319
320 __vfp_envp = 0;
321 if (_libc_arm_fpu_present)
322 __vfp_feholdexcept(&__vfp_envp);
323 __softfp_feholdexcept(__envp);
324 *__envp |= __vfp_envp;
325
326 return (0);
327 }
328
329 int
330 (fesetenv)(const fenv_t *__envp)
331 {
332
333 if (_libc_arm_fpu_present)
334 __vfp_fesetenv(__envp);
335 __softfp_fesetenv(__envp);
336
337 return (0);
338 }
339
340 int
341 (feupdateenv)(const fenv_t *__envp)
342 {
343
344 if (_libc_arm_fpu_present)
345 __vfp_feupdateenv(__envp);
346 __softfp_feupdateenv(__envp);
347
348 return (0);
349 }
350
351 int
352 (feenableexcept)(int __mask)
353 {
354 int __unmasked;
355
356 __unmasked = 0;
357 if (_libc_arm_fpu_present)
358 __unmasked = __vfp_feenableexcept(__mask);
359 __unmasked |= __softfp_feenableexcept(__mask);
360
361 return (__unmasked);
362 }
363
364 int
365 (fedisableexcept)(int __mask)
366 {
367 int __unmasked;
368
369 __unmasked = 0;
370 if (_libc_arm_fpu_present)
371 __unmasked = __vfp_fedisableexcept(__mask);
372 __unmasked |= __softfp_fedisableexcept(__mask);
373
374 return (__unmasked);
375 }
376
377 int
378 (fegetexcept)(void)
379 {
380 int __unmasked;
381
382 __unmasked = 0;
383 if (_libc_arm_fpu_present)
384 __unmasked = __vfp_fegetexcept();
385 __unmasked |= __softfp_fegetexcept();
386
387 return (__unmasked);
388 }
389
390 #endif
391