119220bc1SDavid Schultz /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni *
419220bc1SDavid Schultz * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
5bb6c193eSAndrew Turner * Copyright (c) 2013 Andrew Turner <andrew@FreeBSD.ORG>
619220bc1SDavid Schultz * All rights reserved.
719220bc1SDavid Schultz *
819220bc1SDavid Schultz * Redistribution and use in source and binary forms, with or without
919220bc1SDavid Schultz * modification, are permitted provided that the following conditions
1019220bc1SDavid Schultz * are met:
1119220bc1SDavid Schultz * 1. Redistributions of source code must retain the above copyright
1219220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer.
1319220bc1SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright
1419220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer in the
1519220bc1SDavid Schultz * documentation and/or other materials provided with the distribution.
1619220bc1SDavid Schultz *
1719220bc1SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1819220bc1SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1919220bc1SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2019220bc1SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2119220bc1SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2219220bc1SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2319220bc1SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2419220bc1SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2519220bc1SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2619220bc1SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2719220bc1SDavid Schultz * SUCH DAMAGE.
2819220bc1SDavid Schultz */
2919220bc1SDavid Schultz
30d78e594bSDavid Schultz #define __fenv_static
315d9fefacSDavid Schultz #include "fenv.h"
3219220bc1SDavid Schultz
33161fedb9SWarner Losh #include <machine/acle-compat.h>
34161fedb9SWarner Losh
35bb6c193eSAndrew Turner /* When SOFTFP_ABI is defined we are using the softfp ABI. */
36bb6c193eSAndrew Turner #if defined(__VFP_FP__) && !defined(__ARM_PCS_VFP)
37bb6c193eSAndrew Turner #define SOFTFP_ABI
38bb6c193eSAndrew Turner #endif
39bb6c193eSAndrew Turner
40bb6c193eSAndrew Turner
41bb6c193eSAndrew Turner #ifndef FENV_MANGLE
42bb6c193eSAndrew Turner /*
43bb6c193eSAndrew Turner * Hopefully the system ID byte is immutable, so it's valid to use
44bb6c193eSAndrew Turner * this as a default environment.
45bb6c193eSAndrew Turner */
46bb6c193eSAndrew Turner const fenv_t __fe_dfl_env = 0;
47bb6c193eSAndrew Turner #endif
48bb6c193eSAndrew Turner
49bb6c193eSAndrew Turner
50bb6c193eSAndrew Turner /* If this is a non-mangled softfp version special processing is required */
51*b8a496dfSAndrew Turner #if defined(FENV_MANGLE) || !defined(SOFTFP_ABI)
52bb6c193eSAndrew Turner
537082a2cfSDavid Schultz /*
547082a2cfSDavid Schultz * The following macros map between the softfloat emulator's flags and
557082a2cfSDavid Schultz * the hardware's FPSR. The hardware this file was written for doesn't
567082a2cfSDavid Schultz * have rounding control bits, so we stick those in the system ID byte.
577082a2cfSDavid Schultz */
58bb6c193eSAndrew Turner #ifndef __ARM_PCS_VFP
597082a2cfSDavid Schultz #define __set_env(env, flags, mask, rnd) env = ((flags) \
607082a2cfSDavid Schultz | (mask)<<_FPUSW_SHIFT \
617082a2cfSDavid Schultz | (rnd) << 24)
627082a2cfSDavid Schultz #define __env_flags(env) ((env) & FE_ALL_EXCEPT)
637082a2cfSDavid Schultz #define __env_mask(env) (((env) >> _FPUSW_SHIFT) \
647082a2cfSDavid Schultz & FE_ALL_EXCEPT)
657082a2cfSDavid Schultz #define __env_round(env) (((env) >> 24) & _ROUND_MASK)
667082a2cfSDavid Schultz #include "fenv-softfloat.h"
67bb6c193eSAndrew Turner #endif
687082a2cfSDavid Schultz
69d78e594bSDavid Schultz #ifdef __GNUC_GNU_INLINE__
70d78e594bSDavid Schultz #error "This file must be compiled with C99 'inline' semantics"
71d78e594bSDavid Schultz #endif
72d78e594bSDavid Schultz
73d78e594bSDavid Schultz extern inline int feclearexcept(int __excepts);
74d78e594bSDavid Schultz extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
75d78e594bSDavid Schultz extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
76d78e594bSDavid Schultz extern inline int feraiseexcept(int __excepts);
77d78e594bSDavid Schultz extern inline int fetestexcept(int __excepts);
78d78e594bSDavid Schultz extern inline int fegetround(void);
79d78e594bSDavid Schultz extern inline int fesetround(int __round);
80d78e594bSDavid Schultz extern inline int fegetenv(fenv_t *__envp);
81d78e594bSDavid Schultz extern inline int feholdexcept(fenv_t *__envp);
82d78e594bSDavid Schultz extern inline int fesetenv(const fenv_t *__envp);
83d78e594bSDavid Schultz extern inline int feupdateenv(const fenv_t *__envp);
84bb6c193eSAndrew Turner extern inline int feenableexcept(int __mask);
85bb6c193eSAndrew Turner extern inline int fedisableexcept(int __mask);
86bb6c193eSAndrew Turner extern inline int fegetexcept(void);
87bb6c193eSAndrew Turner
88bb6c193eSAndrew Turner #else /* !FENV_MANGLE && SOFTFP_ABI */
89bb6c193eSAndrew Turner /* Set by libc when the VFP unit is enabled */
90bb6c193eSAndrew Turner extern int _libc_arm_fpu_present;
91bb6c193eSAndrew Turner
92bb6c193eSAndrew Turner int __softfp_feclearexcept(int __excepts);
93bb6c193eSAndrew Turner int __softfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
94bb6c193eSAndrew Turner int __softfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
95bb6c193eSAndrew Turner int __softfp_feraiseexcept(int __excepts);
96bb6c193eSAndrew Turner int __softfp_fetestexcept(int __excepts);
97bb6c193eSAndrew Turner int __softfp_fegetround(void);
98bb6c193eSAndrew Turner int __softfp_fesetround(int __round);
99bb6c193eSAndrew Turner int __softfp_fegetenv(fenv_t *__envp);
100bb6c193eSAndrew Turner int __softfp_feholdexcept(fenv_t *__envp);
101bb6c193eSAndrew Turner int __softfp_fesetenv(const fenv_t *__envp);
102bb6c193eSAndrew Turner int __softfp_feupdateenv(const fenv_t *__envp);
103bb6c193eSAndrew Turner int __softfp_feenableexcept(int __mask);
104bb6c193eSAndrew Turner int __softfp_fedisableexcept(int __mask);
105bb6c193eSAndrew Turner int __softfp_fegetexcept(void);
106bb6c193eSAndrew Turner
107bb6c193eSAndrew Turner int __vfp_feclearexcept(int __excepts);
108bb6c193eSAndrew Turner int __vfp_fegetexceptflag(fexcept_t *__flagp, int __excepts);
109bb6c193eSAndrew Turner int __vfp_fesetexceptflag(const fexcept_t *__flagp, int __excepts);
110bb6c193eSAndrew Turner int __vfp_feraiseexcept(int __excepts);
111bb6c193eSAndrew Turner int __vfp_fetestexcept(int __excepts);
112bb6c193eSAndrew Turner int __vfp_fegetround(void);
113bb6c193eSAndrew Turner int __vfp_fesetround(int __round);
114bb6c193eSAndrew Turner int __vfp_fegetenv(fenv_t *__envp);
115bb6c193eSAndrew Turner int __vfp_feholdexcept(fenv_t *__envp);
116bb6c193eSAndrew Turner int __vfp_fesetenv(const fenv_t *__envp);
117bb6c193eSAndrew Turner int __vfp_feupdateenv(const fenv_t *__envp);
118bb6c193eSAndrew Turner int __vfp_feenableexcept(int __mask);
119bb6c193eSAndrew Turner int __vfp_fedisableexcept(int __mask);
120bb6c193eSAndrew Turner int __vfp_fegetexcept(void);
121bb6c193eSAndrew Turner
122bb6c193eSAndrew Turner static int
__softfp_round_to_vfp(int round)123bb6c193eSAndrew Turner __softfp_round_to_vfp(int round)
124bb6c193eSAndrew Turner {
125bb6c193eSAndrew Turner
126bb6c193eSAndrew Turner switch (round) {
127bb6c193eSAndrew Turner case FE_TONEAREST:
128bb6c193eSAndrew Turner default:
129bb6c193eSAndrew Turner return VFP_FE_TONEAREST;
130bb6c193eSAndrew Turner case FE_TOWARDZERO:
131bb6c193eSAndrew Turner return VFP_FE_TOWARDZERO;
132bb6c193eSAndrew Turner case FE_UPWARD:
133bb6c193eSAndrew Turner return VFP_FE_UPWARD;
134bb6c193eSAndrew Turner case FE_DOWNWARD:
135bb6c193eSAndrew Turner return VFP_FE_DOWNWARD;
136bb6c193eSAndrew Turner }
137bb6c193eSAndrew Turner }
138bb6c193eSAndrew Turner
139bb6c193eSAndrew Turner static int
__softfp_round_from_vfp(int round)140bb6c193eSAndrew Turner __softfp_round_from_vfp(int round)
141bb6c193eSAndrew Turner {
142bb6c193eSAndrew Turner
143bb6c193eSAndrew Turner switch (round) {
144bb6c193eSAndrew Turner case VFP_FE_TONEAREST:
145bb6c193eSAndrew Turner default:
146bb6c193eSAndrew Turner return FE_TONEAREST;
147bb6c193eSAndrew Turner case VFP_FE_TOWARDZERO:
148bb6c193eSAndrew Turner return FE_TOWARDZERO;
149bb6c193eSAndrew Turner case VFP_FE_UPWARD:
150bb6c193eSAndrew Turner return FE_UPWARD;
151bb6c193eSAndrew Turner case VFP_FE_DOWNWARD:
152bb6c193eSAndrew Turner return FE_DOWNWARD;
153bb6c193eSAndrew Turner }
154bb6c193eSAndrew Turner }
155bb6c193eSAndrew Turner
feclearexcept(int __excepts)156bb6c193eSAndrew Turner int feclearexcept(int __excepts)
157bb6c193eSAndrew Turner {
158bb6c193eSAndrew Turner
159bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
160bb6c193eSAndrew Turner __vfp_feclearexcept(__excepts);
161bb6c193eSAndrew Turner __softfp_feclearexcept(__excepts);
162bb6c193eSAndrew Turner
163bb6c193eSAndrew Turner return (0);
164bb6c193eSAndrew Turner }
165bb6c193eSAndrew Turner
fegetexceptflag(fexcept_t * __flagp,int __excepts)166bb6c193eSAndrew Turner int fegetexceptflag(fexcept_t *__flagp, int __excepts)
167bb6c193eSAndrew Turner {
168bb6c193eSAndrew Turner fexcept_t __vfp_flagp;
169bb6c193eSAndrew Turner
170bb6c193eSAndrew Turner __vfp_flagp = 0;
171bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
172bb6c193eSAndrew Turner __vfp_fegetexceptflag(&__vfp_flagp, __excepts);
173bb6c193eSAndrew Turner __softfp_fegetexceptflag(__flagp, __excepts);
174bb6c193eSAndrew Turner
175bb6c193eSAndrew Turner *__flagp |= __vfp_flagp;
176bb6c193eSAndrew Turner
177bb6c193eSAndrew Turner return (0);
178bb6c193eSAndrew Turner }
179bb6c193eSAndrew Turner
fesetexceptflag(const fexcept_t * __flagp,int __excepts)180bb6c193eSAndrew Turner int fesetexceptflag(const fexcept_t *__flagp, int __excepts)
181bb6c193eSAndrew Turner {
182bb6c193eSAndrew Turner
183bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
184bb6c193eSAndrew Turner __vfp_fesetexceptflag(__flagp, __excepts);
185bb6c193eSAndrew Turner __softfp_fesetexceptflag(__flagp, __excepts);
186bb6c193eSAndrew Turner
187bb6c193eSAndrew Turner return (0);
188bb6c193eSAndrew Turner }
189bb6c193eSAndrew Turner
feraiseexcept(int __excepts)190bb6c193eSAndrew Turner int feraiseexcept(int __excepts)
191bb6c193eSAndrew Turner {
192bb6c193eSAndrew Turner
193bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
194bb6c193eSAndrew Turner __vfp_feraiseexcept(__excepts);
195bb6c193eSAndrew Turner __softfp_feraiseexcept(__excepts);
196bb6c193eSAndrew Turner
197bb6c193eSAndrew Turner return (0);
198bb6c193eSAndrew Turner }
199bb6c193eSAndrew Turner
fetestexcept(int __excepts)200bb6c193eSAndrew Turner int fetestexcept(int __excepts)
201bb6c193eSAndrew Turner {
202bb6c193eSAndrew Turner int __got_excepts;
203bb6c193eSAndrew Turner
204bb6c193eSAndrew Turner __got_excepts = 0;
205bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
206bb6c193eSAndrew Turner __got_excepts = __vfp_fetestexcept(__excepts);
207bb6c193eSAndrew Turner __got_excepts |= __softfp_fetestexcept(__excepts);
208bb6c193eSAndrew Turner
209bb6c193eSAndrew Turner return (__got_excepts);
210bb6c193eSAndrew Turner }
211bb6c193eSAndrew Turner
fegetround(void)212bb6c193eSAndrew Turner int fegetround(void)
213bb6c193eSAndrew Turner {
214bb6c193eSAndrew Turner
215bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
216bb6c193eSAndrew Turner return __softfp_round_from_vfp(__vfp_fegetround());
217bb6c193eSAndrew Turner return __softfp_fegetround();
218bb6c193eSAndrew Turner }
219bb6c193eSAndrew Turner
fesetround(int __round)220bb6c193eSAndrew Turner int fesetround(int __round)
221bb6c193eSAndrew Turner {
222bb6c193eSAndrew Turner
223bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
224bb6c193eSAndrew Turner __vfp_fesetround(__softfp_round_to_vfp(__round));
225bb6c193eSAndrew Turner __softfp_fesetround(__round);
226bb6c193eSAndrew Turner
227bb6c193eSAndrew Turner return (0);
228bb6c193eSAndrew Turner }
229bb6c193eSAndrew Turner
fegetenv(fenv_t * __envp)230bb6c193eSAndrew Turner int fegetenv(fenv_t *__envp)
231bb6c193eSAndrew Turner {
232bb6c193eSAndrew Turner fenv_t __vfp_envp;
233bb6c193eSAndrew Turner
234bb6c193eSAndrew Turner __vfp_envp = 0;
235bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
236bb6c193eSAndrew Turner __vfp_fegetenv(&__vfp_envp);
237bb6c193eSAndrew Turner __softfp_fegetenv(__envp);
238bb6c193eSAndrew Turner *__envp |= __vfp_envp;
239bb6c193eSAndrew Turner
240bb6c193eSAndrew Turner return (0);
241bb6c193eSAndrew Turner }
242bb6c193eSAndrew Turner
feholdexcept(fenv_t * __envp)243bb6c193eSAndrew Turner int feholdexcept(fenv_t *__envp)
244bb6c193eSAndrew Turner {
245bb6c193eSAndrew Turner fenv_t __vfp_envp;
246bb6c193eSAndrew Turner
247bb6c193eSAndrew Turner __vfp_envp = 0;
248bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
249bb6c193eSAndrew Turner __vfp_feholdexcept(&__vfp_envp);
250bb6c193eSAndrew Turner __softfp_feholdexcept(__envp);
251bb6c193eSAndrew Turner *__envp |= __vfp_envp;
252bb6c193eSAndrew Turner
253bb6c193eSAndrew Turner return (0);
254bb6c193eSAndrew Turner }
255bb6c193eSAndrew Turner
fesetenv(const fenv_t * __envp)256bb6c193eSAndrew Turner int fesetenv(const fenv_t *__envp)
257bb6c193eSAndrew Turner {
258bb6c193eSAndrew Turner
259bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
260bb6c193eSAndrew Turner __vfp_fesetenv(__envp);
261bb6c193eSAndrew Turner __softfp_fesetenv(__envp);
262bb6c193eSAndrew Turner
263bb6c193eSAndrew Turner return (0);
264bb6c193eSAndrew Turner }
265bb6c193eSAndrew Turner
feupdateenv(const fenv_t * __envp)266bb6c193eSAndrew Turner int feupdateenv(const fenv_t *__envp)
267bb6c193eSAndrew Turner {
268bb6c193eSAndrew Turner
269bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
270bb6c193eSAndrew Turner __vfp_feupdateenv(__envp);
271bb6c193eSAndrew Turner __softfp_feupdateenv(__envp);
272bb6c193eSAndrew Turner
273bb6c193eSAndrew Turner return (0);
274bb6c193eSAndrew Turner }
275bb6c193eSAndrew Turner
feenableexcept(int __mask)276bb6c193eSAndrew Turner int feenableexcept(int __mask)
277bb6c193eSAndrew Turner {
278bb6c193eSAndrew Turner int __unmasked;
279bb6c193eSAndrew Turner
280bb6c193eSAndrew Turner __unmasked = 0;
281bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
282bb6c193eSAndrew Turner __unmasked = __vfp_feenableexcept(__mask);
283bb6c193eSAndrew Turner __unmasked |= __softfp_feenableexcept(__mask);
284bb6c193eSAndrew Turner
285bb6c193eSAndrew Turner return (__unmasked);
286bb6c193eSAndrew Turner }
287bb6c193eSAndrew Turner
fedisableexcept(int __mask)288bb6c193eSAndrew Turner int fedisableexcept(int __mask)
289bb6c193eSAndrew Turner {
290bb6c193eSAndrew Turner int __unmasked;
291bb6c193eSAndrew Turner
292bb6c193eSAndrew Turner __unmasked = 0;
293bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
294bb6c193eSAndrew Turner __unmasked = __vfp_fedisableexcept(__mask);
295bb6c193eSAndrew Turner __unmasked |= __softfp_fedisableexcept(__mask);
296bb6c193eSAndrew Turner
297bb6c193eSAndrew Turner return (__unmasked);
298bb6c193eSAndrew Turner }
299bb6c193eSAndrew Turner
fegetexcept(void)300bb6c193eSAndrew Turner int fegetexcept(void)
301bb6c193eSAndrew Turner {
302bb6c193eSAndrew Turner int __unmasked;
303bb6c193eSAndrew Turner
304bb6c193eSAndrew Turner __unmasked = 0;
305bb6c193eSAndrew Turner if (_libc_arm_fpu_present)
306bb6c193eSAndrew Turner __unmasked = __vfp_fegetexcept();
307bb6c193eSAndrew Turner __unmasked |= __softfp_fegetexcept();
308bb6c193eSAndrew Turner
309bb6c193eSAndrew Turner return (__unmasked);
310bb6c193eSAndrew Turner }
311bb6c193eSAndrew Turner
312bb6c193eSAndrew Turner #endif
313bb6c193eSAndrew Turner
314