2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
5 * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
35 #include <machine/acle-compat.h>
41 /* When SOFTFP_ABI is defined we are using the softfp ABI. */
42 #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP)
49 * Hopefully the system ID byte is immutable, so it's valid to use
50 * this as a default environment.
52 const fenv_t __fe_dfl_env = 0;
56 /* If this is a non-mangled softfp version special processing is required */
57 #if defined(FENV_MANGLE) || !defined(SOFTFP_ABI) || !defined(FENV_ARMv6)
60 * The following macros map between the softfloat emulator's flags and
61 * the hardware's FPSR. The hardware this file was written for doesn't
62 * have rounding control bits, so we stick those in the system ID byte.
65 #define __set_env(env, flags, mask, rnd) env = ((flags) \
66 | (mask)<<_FPUSW_SHIFT \
68 #define __env_flags(env) ((env) & FE_ALL_EXCEPT)
69 #define __env_mask(env) (((env) >> _FPUSW_SHIFT) \
71 #define __env_round(env) (((env) >> 24) & _ROUND_MASK)
72 #include "fenv-softfloat.h"
75 #ifdef __GNUC_GNU_INLINE__
76 #error "This file must be compiled with C99 'inline' semantics"
79 extern inline int feclearexcept(int __excepts);
80 extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
81 extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
82 extern inline int feraiseexcept(int __excepts);
83 extern inline int fetestexcept(int __excepts);
84 extern inline int fegetround(void);
85 extern inline int fesetround(int __round);
86 extern inline int fegetenv(fenv_t *__envp);
87 extern inline int feholdexcept(fenv_t *__envp);
88 extern inline int fesetenv(const fenv_t *__envp);
89 extern inline int feupdateenv(const fenv_t *__envp);
90 extern inline int feenableexcept(int __mask);
91 extern inline int fedisableexcept(int __mask);
92 extern inline int fegetexcept(void);
94 #else /* !FENV_MANGLE && SOFTFP_ABI */
95 /* Set by libc when the VFP unit is enabled */
96 extern int _libc_arm_fpu_present;
98 int __softfp_feclearexcept(int __excepts);
99 int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
100 int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
101 int __softfp_feraiseexcept(int __excepts);
102 int __softfp_fetestexcept(int __excepts);
103 int __softfp_fegetround(void);
104 int __softfp_fesetround(int __round);
105 int __softfp_fegetenv(fenv_t *__envp);
106 int __softfp_feholdexcept(fenv_t *__envp);
107 int __softfp_fesetenv(const fenv_t *__envp);
108 int __softfp_feupdateenv(const fenv_t *__envp);
109 int __softfp_feenableexcept(int __mask);
110 int __softfp_fedisableexcept(int __mask);
111 int __softfp_fegetexcept(void);
113 int __vfp_feclearexcept(int __excepts);
114 int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
115 int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
116 int __vfp_feraiseexcept(int __excepts);
117 int __vfp_fetestexcept(int __excepts);
118 int __vfp_fegetround(void);
119 int __vfp_fesetround(int __round);
120 int __vfp_fegetenv(fenv_t *__envp);
121 int __vfp_feholdexcept(fenv_t *__envp);
122 int __vfp_fesetenv(const fenv_t *__envp);
123 int __vfp_feupdateenv(const fenv_t *__envp);
124 int __vfp_feenableexcept(int __mask);
125 int __vfp_fedisableexcept(int __mask);
126 int __vfp_fegetexcept(void);
129 __softfp_round_to_vfp(int round)
135 return VFP_FE_TONEAREST;
137 return VFP_FE_TOWARDZERO;
139 return VFP_FE_UPWARD;
141 return VFP_FE_DOWNWARD;
146 __softfp_round_from_vfp(int round)
150 case VFP_FE_TONEAREST:
153 case VFP_FE_TOWARDZERO:
154 return FE_TOWARDZERO;
157 case VFP_FE_DOWNWARD:
162 int feclearexcept(int __excepts)
165 if (_libc_arm_fpu_present)
166 __vfp_feclearexcept(__excepts);
167 __softfp_feclearexcept(__excepts);
172 int fegetexceptflag(fexcept_t *__flagp, int __excepts)
174 fexcept_t __vfp_flagp;
177 if (_libc_arm_fpu_present)
178 __vfp_fegetexceptflag(&__vfp_flagp, __excepts);
179 __softfp_fegetexceptflag(__flagp, __excepts);
181 *__flagp |= __vfp_flagp;
186 int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
189 if (_libc_arm_fpu_present)
190 __vfp_fesetexceptflag(__flagp, __excepts);
191 __softfp_fesetexceptflag(__flagp, __excepts);
196 int feraiseexcept(int __excepts)
199 if (_libc_arm_fpu_present)
200 __vfp_feraiseexcept(__excepts);
201 __softfp_feraiseexcept(__excepts);
206 int fetestexcept(int __excepts)
211 if (_libc_arm_fpu_present)
212 __got_excepts = __vfp_fetestexcept(__excepts);
213 __got_excepts |= __softfp_fetestexcept(__excepts);
215 return (__got_excepts);
221 if (_libc_arm_fpu_present)
222 return __softfp_round_from_vfp(__vfp_fegetround());
223 return __softfp_fegetround();
226 int fesetround(int __round)
229 if (_libc_arm_fpu_present)
230 __vfp_fesetround(__softfp_round_to_vfp(__round));
231 __softfp_fesetround(__round);
236 int fegetenv(fenv_t *__envp)
241 if (_libc_arm_fpu_present)
242 __vfp_fegetenv(&__vfp_envp);
243 __softfp_fegetenv(__envp);
244 *__envp |= __vfp_envp;
249 int feholdexcept(fenv_t *__envp)
254 if (_libc_arm_fpu_present)
255 __vfp_feholdexcept(&__vfp_envp);
256 __softfp_feholdexcept(__envp);
257 *__envp |= __vfp_envp;
262 int fesetenv(const fenv_t *__envp)
265 if (_libc_arm_fpu_present)
266 __vfp_fesetenv(__envp);
267 __softfp_fesetenv(__envp);
272 int feupdateenv(const fenv_t *__envp)
275 if (_libc_arm_fpu_present)
276 __vfp_feupdateenv(__envp);
277 __softfp_feupdateenv(__envp);
282 int feenableexcept(int __mask)
287 if (_libc_arm_fpu_present)
288 __unmasked = __vfp_feenableexcept(__mask);
289 __unmasked |= __softfp_feenableexcept(__mask);
294 int fedisableexcept(int __mask)
299 if (_libc_arm_fpu_present)
300 __unmasked = __vfp_fedisableexcept(__mask);
301 __unmasked |= __softfp_fedisableexcept(__mask);
306 int fegetexcept(void)
311 if (_libc_arm_fpu_present)
312 __unmasked = __vfp_fegetexcept();
313 __unmasked |= __softfp_fegetexcept();