1
+ /*-
2
+ * Copyright (c) 2023 Yifan An <[email protected] >
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