1+ /*-
2+ * Copyright (c) 2023 Yifan An <me@anyi.fan>
3+ * All rights reserved.
4+ *
5+ * Redistribution and use in source and binary forms, with or without
6+ * modification, are permitted provided that the following conditions
7+ * are met:
8+ * 1. Redistributions of source code must retain the above copyright
9+ * notice, this list of conditions and the following disclaimer.
10+ * 2. Redistributions in binary form must reproduce the above copyright
11+ * notice, this list of conditions and the following disclaimer in the
12+ * documentation and/or other materials provided with the distribution.
13+ *
14+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24+ * SUCH DAMAGE.
25+ */
26+
27+ #ifndef _FENV_H_
28+ #define _FENV_H_
29+
30+ #include <stdint.h>
31+ #include "cdefs-compat.h"
32+
33+ #ifndef __fenv_static
34+ #define __fenv_static static
35+ #endif
36+
37+ typedef uint32_t fenv_t ;
38+ typedef uint32_t fexcept_t ;
39+
40+ /* Exception flags */
41+ #define FE_INVALID 0x100000
42+ #define FE_DIVBYZERO 0x080000
43+ #define FE_OVERFLOW 0x040000
44+ #define FE_UNDERFLOW 0x020000
45+ #define FE_INEXACT 0x010000
46+ #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
47+ FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
48+
49+ /* Rounding modes */
50+ #define FE_TONEAREST 0x0000
51+ #define FE_TOWARDZERO 0x0100
52+ #define FE_DOWNWARD 0x0200
53+ #define FE_UPWARD 0x0300
54+ #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
55+ FE_UPWARD | FE_TOWARDZERO)
56+
57+ __BEGIN_DECLS
58+
59+ /* Default floating-point environment */
60+ extern const fenv_t __fe_dfl_env ;
61+ #define FE_DFL_ENV (&__fe_dfl_env)
62+
63+ #define _FPU_MASK_V 0x10
64+ #define _FPU_MASK_Z 0x08
65+ #define _FPU_MASK_O 0x04
66+ #define _FPU_MASK_U 0x02
67+ #define _FPU_MASK_I 0x01
68+
69+ #define _FPUSW_SHIFT 16
70+ #define _ENABLE_MASK (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I)
71+
72+ #define __rfs (__fpsr ) __asm __volatile("movfcsr2gr %0,$r0" : "=r"(__fpsr))
73+ #define __wfs (__fpsr ) __asm __volatile("movgr2fcsr $r0,%0" : : "r"(__fpsr))
74+
75+ __fenv_static inline int
76+ feclearexcept (int __excepts )
77+ {
78+ fexcept_t __fpsr ;
79+
80+ __rfs (__fpsr );
81+ __fpsr &= ~__excepts ;
82+ __wfs (__fpsr );
83+ return (0 );
84+ }
85+
86+ __fenv_static inline int
87+ fegetexceptflag (fexcept_t * __flagp , int __excepts )
88+ {
89+ fexcept_t __fpsr ;
90+
91+ __rfs (__fpsr );
92+ * __flagp = __fpsr & __excepts ;
93+ return (0 );
94+ }
95+
96+ __fenv_static inline int
97+ fesetexceptflag (const fexcept_t * __flagp , int __excepts )
98+ {
99+ fexcept_t __fpsr ;
100+
101+ __rfs (__fpsr );
102+ __fpsr &= ~__excepts ;
103+ __fpsr |= * __flagp & __excepts ;
104+ __wfs (__fpsr );
105+ return (0 );
106+ }
107+
108+ __fenv_static inline int
109+ feraiseexcept (int __excepts )
110+ {
111+ fexcept_t __ex = __excepts ;
112+
113+ fesetexceptflag (& __ex , __excepts ); /* XXX */
114+ return (0 );
115+ }
116+
117+ __fenv_static inline int
118+ fetestexcept (int __excepts )
119+ {
120+ fexcept_t __fpsr ;
121+
122+ __rfs (__fpsr );
123+ return (__fpsr & __excepts );
124+ }
125+
126+ __fenv_static inline int
127+ fegetround (void )
128+ {
129+ fexcept_t __fpsr ;
130+
131+ __rfs (__fpsr );
132+ return __fpsr & _ROUND_MASK ;
133+ }
134+
135+ __fenv_static inline int
136+ fesetround (int __round )
137+ {
138+ fexcept_t __fpsr ;
139+ if ((__round & ~_ROUND_MASK ) != 0 )
140+ return 1 ;
141+
142+ __rfs (__fpsr );
143+ __fpsr &= ~_ROUND_MASK ;
144+ __fpsr |= __round ;
145+ __wfs (__fpsr );
146+
147+ return (0 );
148+ }
149+
150+ __fenv_static inline int
151+ fegetenv (fenv_t * __envp )
152+ {
153+ __rfs (* __envp );
154+ return (0 );
155+ }
156+
157+ __fenv_static inline int
158+ feholdexcept (fenv_t * __envp )
159+ {
160+ fenv_t __env ;
161+
162+ __rfs (__env );
163+ * __envp = __env ;
164+ __env &= ~(FE_ALL_EXCEPT | _FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I );
165+ __wfs (__env );
166+ return (0 );
167+ }
168+
169+ __fenv_static inline int
170+ fesetenv (const fenv_t * __envp )
171+ {
172+ __wfs (* __envp );
173+ return (0 );
174+ }
175+
176+ __fenv_static inline int
177+ feupdateenv (const fenv_t * __envp )
178+ {
179+ fexcept_t __fpsr ;
180+
181+ __rfs (__fpsr );
182+ __wfs (* __envp );
183+ feraiseexcept (__fpsr & FE_ALL_EXCEPT );
184+ return (0 );
185+ }
186+
187+ #if __BSD_VISIBLE
188+
189+ static inline int
190+ feenableexcept (int __mask )
191+ {
192+ fenv_t __old_fpsr , __new_fpsr ;
193+
194+ __rfs (__new_fpsr );
195+ __old_fpsr = (__new_fpsr & _ENABLE_MASK ) << _FPUSW_SHIFT ;
196+ __new_fpsr |= (__mask & FE_ALL_EXCEPT ) >> _FPUSW_SHIFT ;
197+ __wfs (__new_fpsr );
198+ return __old_fpsr ;
199+ }
200+
201+ static inline int
202+ fedisableexcept (int __mask )
203+ {
204+ fenv_t __old_fpsr , __new_fpsr ;
205+
206+ __rfs (__new_fpsr );
207+ __old_fpsr = (__new_fpsr & _ENABLE_MASK ) << _FPUSW_SHIFT ;
208+ __new_fpsr &= ~((__mask & FE_ALL_EXCEPT ) >> _FPUSW_SHIFT );
209+ __wfs (__new_fpsr );
210+ return __old_fpsr ;
211+ }
212+
213+ static inline int
214+ fegetexcept (void )
215+ {
216+ fenv_t __fpsr ;
217+
218+ __rfs (__fpsr );
219+ return ((__fpsr & _ENABLE_MASK ) << _FPUSW_SHIFT );
220+ }
221+
222+ #endif /* __BSD_VISIBLE */
223+
224+ __END_DECLS
225+
226+ #endif /* !_FENV_H_ */
0 commit comments