119220bc1SDavid Schultz /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni *
410b01832SDavid Schultz * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
519220bc1SDavid Schultz * All rights reserved.
619220bc1SDavid Schultz *
719220bc1SDavid Schultz * Redistribution and use in source and binary forms, with or without
819220bc1SDavid Schultz * modification, are permitted provided that the following conditions
919220bc1SDavid Schultz * are met:
1019220bc1SDavid Schultz * 1. Redistributions of source code must retain the above copyright
1119220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer.
1219220bc1SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright
1319220bc1SDavid Schultz * notice, this list of conditions and the following disclaimer in the
1419220bc1SDavid Schultz * documentation and/or other materials provided with the distribution.
1519220bc1SDavid Schultz *
1619220bc1SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1719220bc1SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1819220bc1SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1919220bc1SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2019220bc1SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2119220bc1SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2219220bc1SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2319220bc1SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2419220bc1SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2519220bc1SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2619220bc1SDavid Schultz * SUCH DAMAGE.
2719220bc1SDavid Schultz */
2819220bc1SDavid Schultz
2919220bc1SDavid Schultz #ifndef _FENV_H_
3019220bc1SDavid Schultz #define _FENV_H_
3119220bc1SDavid Schultz
3219220bc1SDavid Schultz #include <sys/_types.h>
3319220bc1SDavid Schultz
34d78e594bSDavid Schultz #ifndef __fenv_static
35d78e594bSDavid Schultz #define __fenv_static static
36d78e594bSDavid Schultz #endif
37d78e594bSDavid Schultz
3819220bc1SDavid Schultz typedef __uint32_t fenv_t;
3919220bc1SDavid Schultz typedef __uint32_t fexcept_t;
4019220bc1SDavid Schultz
4119220bc1SDavid Schultz /* Exception flags */
4219220bc1SDavid Schultz #define FE_INVALID 0x0001
4319220bc1SDavid Schultz #define FE_DIVBYZERO 0x0002
4419220bc1SDavid Schultz #define FE_OVERFLOW 0x0004
4519220bc1SDavid Schultz #define FE_UNDERFLOW 0x0008
4619220bc1SDavid Schultz #define FE_INEXACT 0x0010
47c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
48c9081a6cSAndrew Turner #define FE_DENORMAL 0x0080
49c9081a6cSAndrew Turner #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
50c9081a6cSAndrew Turner FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
51c9081a6cSAndrew Turner #else
5219220bc1SDavid Schultz #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
5319220bc1SDavid Schultz FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
54c9081a6cSAndrew Turner #endif
5519220bc1SDavid Schultz
5615d3b4dbSOlivier Houchard /* Rounding modes */
57bb6c193eSAndrew Turner #define VFP_FE_TONEAREST 0x00000000
58bb6c193eSAndrew Turner #define VFP_FE_UPWARD 0x00400000
59bb6c193eSAndrew Turner #define VFP_FE_DOWNWARD 0x00800000
60bb6c193eSAndrew Turner #define VFP_FE_TOWARDZERO 0x00c00000
61bb6c193eSAndrew Turner
62c9081a6cSAndrew Turner #ifdef __ARM_PCS_VFP
63bb6c193eSAndrew Turner #define FE_TONEAREST VFP_FE_TONEAREST
64bb6c193eSAndrew Turner #define FE_UPWARD VFP_FE_UPWARD
65bb6c193eSAndrew Turner #define FE_DOWNWARD VFP_FE_DOWNWARD
66bb6c193eSAndrew Turner #define FE_TOWARDZERO VFP_FE_TOWARDZERO
67c9081a6cSAndrew Turner #else
6815d3b4dbSOlivier Houchard #define FE_TONEAREST 0x0000
6915d3b4dbSOlivier Houchard #define FE_TOWARDZERO 0x0001
7015d3b4dbSOlivier Houchard #define FE_UPWARD 0x0002
7115d3b4dbSOlivier Houchard #define FE_DOWNWARD 0x0003
72c9081a6cSAndrew Turner #endif
7315d3b4dbSOlivier Houchard #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
7415d3b4dbSOlivier Houchard FE_UPWARD | FE_TOWARDZERO)
7519220bc1SDavid Schultz __BEGIN_DECLS
7619220bc1SDavid Schultz
7719220bc1SDavid Schultz /* Default floating-point environment */
7819220bc1SDavid Schultz extern const fenv_t __fe_dfl_env;
7919220bc1SDavid Schultz #define FE_DFL_ENV (&__fe_dfl_env)
8019220bc1SDavid Schultz
8119220bc1SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */
82c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
8319220bc1SDavid Schultz #define _FPUSW_SHIFT 16
8419220bc1SDavid Schultz #define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
85c9081a6cSAndrew Turner #endif
8619220bc1SDavid Schultz
87c9081a6cSAndrew Turner #ifndef __ARM_PCS_VFP
887082a2cfSDavid Schultz
897082a2cfSDavid Schultz int feclearexcept(int __excepts);
907082a2cfSDavid Schultz int fegetexceptflag(fexcept_t *__flagp, int __excepts);
917082a2cfSDavid Schultz int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
927082a2cfSDavid Schultz int feraiseexcept(int __excepts);
937082a2cfSDavid Schultz int fetestexcept(int __excepts);
947082a2cfSDavid Schultz int fegetround(void);
957082a2cfSDavid Schultz int fesetround(int __round);
967082a2cfSDavid Schultz int fegetenv(fenv_t *__envp);
977082a2cfSDavid Schultz int feholdexcept(fenv_t *__envp);
987082a2cfSDavid Schultz int fesetenv(const fenv_t *__envp);
997082a2cfSDavid Schultz int feupdateenv(const fenv_t *__envp);
100bb6c193eSAndrew Turner #if __BSD_VISIBLE
101bb6c193eSAndrew Turner int feenableexcept(int __mask);
102bb6c193eSAndrew Turner int fedisableexcept(int __mask);
103bb6c193eSAndrew Turner int fegetexcept(void);
104bb6c193eSAndrew Turner #endif
1057bde21b1SDavid Schultz
106c9081a6cSAndrew Turner #else /* __ARM_PCS_VFP */
1077bde21b1SDavid Schultz
108c9081a6cSAndrew Turner #define vmrs_fpscr(__r) __asm __volatile("vmrs %0, fpscr" : "=&r"(__r))
109c9081a6cSAndrew Turner #define vmsr_fpscr(__r) __asm __volatile("vmsr fpscr, %0" : : "r"(__r))
11019220bc1SDavid Schultz
111a541d15cSAndrew Turner #define _FPU_MASK_SHIFT 8
112a541d15cSAndrew Turner
113d78e594bSDavid Schultz __fenv_static inline int
feclearexcept(int __excepts)11419220bc1SDavid Schultz feclearexcept(int __excepts)
11519220bc1SDavid Schultz {
11619220bc1SDavid Schultz fexcept_t __fpsr;
11719220bc1SDavid Schultz
118c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
11919220bc1SDavid Schultz __fpsr &= ~__excepts;
120c9081a6cSAndrew Turner vmsr_fpscr(__fpsr);
12119220bc1SDavid Schultz return (0);
12219220bc1SDavid Schultz }
12319220bc1SDavid Schultz
124d78e594bSDavid Schultz __fenv_static inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)12519220bc1SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
12619220bc1SDavid Schultz {
12719220bc1SDavid Schultz fexcept_t __fpsr;
12819220bc1SDavid Schultz
129c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
13019220bc1SDavid Schultz *__flagp = __fpsr & __excepts;
13119220bc1SDavid Schultz return (0);
13219220bc1SDavid Schultz }
13319220bc1SDavid Schultz
134d78e594bSDavid Schultz __fenv_static inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)13519220bc1SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
13619220bc1SDavid Schultz {
13719220bc1SDavid Schultz fexcept_t __fpsr;
13819220bc1SDavid Schultz
139c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
14019220bc1SDavid Schultz __fpsr &= ~__excepts;
14119220bc1SDavid Schultz __fpsr |= *__flagp & __excepts;
142c9081a6cSAndrew Turner vmsr_fpscr(__fpsr);
14319220bc1SDavid Schultz return (0);
14419220bc1SDavid Schultz }
14519220bc1SDavid Schultz
146d78e594bSDavid Schultz __fenv_static inline int
feraiseexcept(int __excepts)14719220bc1SDavid Schultz feraiseexcept(int __excepts)
14819220bc1SDavid Schultz {
14919220bc1SDavid Schultz fexcept_t __ex = __excepts;
15019220bc1SDavid Schultz
15119220bc1SDavid Schultz fesetexceptflag(&__ex, __excepts); /* XXX */
15219220bc1SDavid Schultz return (0);
15319220bc1SDavid Schultz }
15419220bc1SDavid Schultz
155d78e594bSDavid Schultz __fenv_static inline int
fetestexcept(int __excepts)15619220bc1SDavid Schultz fetestexcept(int __excepts)
15719220bc1SDavid Schultz {
15819220bc1SDavid Schultz fexcept_t __fpsr;
15919220bc1SDavid Schultz
160c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
16119220bc1SDavid Schultz return (__fpsr & __excepts);
16219220bc1SDavid Schultz }
16319220bc1SDavid Schultz
164d78e594bSDavid Schultz __fenv_static inline int
fegetround(void)16519220bc1SDavid Schultz fegetround(void)
16619220bc1SDavid Schultz {
167c9081a6cSAndrew Turner fenv_t __fpsr;
16819220bc1SDavid Schultz
169c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
170c9081a6cSAndrew Turner return (__fpsr & _ROUND_MASK);
17119220bc1SDavid Schultz }
17219220bc1SDavid Schultz
173d78e594bSDavid Schultz __fenv_static inline int
fesetround(int __round)17419220bc1SDavid Schultz fesetround(int __round)
17519220bc1SDavid Schultz {
176c9081a6cSAndrew Turner fenv_t __fpsr;
17719220bc1SDavid Schultz
178c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
179c9081a6cSAndrew Turner __fpsr &= ~(_ROUND_MASK);
180c9081a6cSAndrew Turner __fpsr |= __round;
181c9081a6cSAndrew Turner vmsr_fpscr(__fpsr);
182c9081a6cSAndrew Turner return (0);
18319220bc1SDavid Schultz }
18419220bc1SDavid Schultz
185d78e594bSDavid Schultz __fenv_static inline int
fegetenv(fenv_t * __envp)18619220bc1SDavid Schultz fegetenv(fenv_t *__envp)
18719220bc1SDavid Schultz {
18819220bc1SDavid Schultz
189c9081a6cSAndrew Turner vmrs_fpscr(*__envp);
19019220bc1SDavid Schultz return (0);
19119220bc1SDavid Schultz }
19219220bc1SDavid Schultz
193d78e594bSDavid Schultz __fenv_static inline int
feholdexcept(fenv_t * __envp)19419220bc1SDavid Schultz feholdexcept(fenv_t *__envp)
19519220bc1SDavid Schultz {
19619220bc1SDavid Schultz fenv_t __env;
19719220bc1SDavid Schultz
198c9081a6cSAndrew Turner vmrs_fpscr(__env);
19919220bc1SDavid Schultz *__envp = __env;
200c9081a6cSAndrew Turner __env &= ~(FE_ALL_EXCEPT);
201c9081a6cSAndrew Turner vmsr_fpscr(__env);
20219220bc1SDavid Schultz return (0);
20319220bc1SDavid Schultz }
20419220bc1SDavid Schultz
205d78e594bSDavid Schultz __fenv_static inline int
fesetenv(const fenv_t * __envp)20619220bc1SDavid Schultz fesetenv(const fenv_t *__envp)
20719220bc1SDavid Schultz {
20819220bc1SDavid Schultz
209c9081a6cSAndrew Turner vmsr_fpscr(*__envp);
21019220bc1SDavid Schultz return (0);
21119220bc1SDavid Schultz }
21219220bc1SDavid Schultz
213d78e594bSDavid Schultz __fenv_static inline int
feupdateenv(const fenv_t * __envp)21419220bc1SDavid Schultz feupdateenv(const fenv_t *__envp)
21519220bc1SDavid Schultz {
21619220bc1SDavid Schultz fexcept_t __fpsr;
21719220bc1SDavid Schultz
218c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
219c9081a6cSAndrew Turner vmsr_fpscr(*__envp);
22019220bc1SDavid Schultz feraiseexcept(__fpsr & FE_ALL_EXCEPT);
22119220bc1SDavid Schultz return (0);
22219220bc1SDavid Schultz }
22319220bc1SDavid Schultz
22419220bc1SDavid Schultz #if __BSD_VISIBLE
22519220bc1SDavid Schultz
226d78e594bSDavid Schultz /* We currently provide no external definitions of the functions below. */
227d78e594bSDavid Schultz
228a541d15cSAndrew Turner __fenv_static inline int
feenableexcept(int __mask)22910b01832SDavid Schultz feenableexcept(int __mask)
23019220bc1SDavid Schultz {
23110b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr;
23219220bc1SDavid Schultz
233c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr);
234a541d15cSAndrew Turner __new_fpsr = __old_fpsr |
235a541d15cSAndrew Turner ((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
236c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr);
237a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
23819220bc1SDavid Schultz }
23919220bc1SDavid Schultz
240a541d15cSAndrew Turner __fenv_static inline int
fedisableexcept(int __mask)24110b01832SDavid Schultz fedisableexcept(int __mask)
24210b01832SDavid Schultz {
24310b01832SDavid Schultz fenv_t __old_fpsr, __new_fpsr;
24410b01832SDavid Schultz
245c9081a6cSAndrew Turner vmrs_fpscr(__old_fpsr);
246a541d15cSAndrew Turner __new_fpsr = __old_fpsr &
247a541d15cSAndrew Turner ~((__mask & FE_ALL_EXCEPT) << _FPU_MASK_SHIFT);
248c9081a6cSAndrew Turner vmsr_fpscr(__new_fpsr);
249a541d15cSAndrew Turner return ((__old_fpsr >> _FPU_MASK_SHIFT) & FE_ALL_EXCEPT);
25010b01832SDavid Schultz }
25110b01832SDavid Schultz
252a541d15cSAndrew Turner __fenv_static inline int
fegetexcept(void)25310b01832SDavid Schultz fegetexcept(void)
25419220bc1SDavid Schultz {
25519220bc1SDavid Schultz fenv_t __fpsr;
25619220bc1SDavid Schultz
257c9081a6cSAndrew Turner vmrs_fpscr(__fpsr);
258c9081a6cSAndrew Turner return (__fpsr & FE_ALL_EXCEPT);
25919220bc1SDavid Schultz }
26019220bc1SDavid Schultz
26119220bc1SDavid Schultz #endif /* __BSD_VISIBLE */
26219220bc1SDavid Schultz
263c9081a6cSAndrew Turner #endif /* __ARM_PCS_VFP */
2647bde21b1SDavid Schultz
26519220bc1SDavid Schultz __END_DECLS
26619220bc1SDavid Schultz
26719220bc1SDavid Schultz #endif /* !_FENV_H_ */
268