fenv.h revision 1.4.2.2 1 1.4.2.2 jdolecek /* $NetBSD: fenv.h,v 1.4.2.2 2017/12/03 11:36:37 jdolecek Exp $ */
2 1.4.2.2 jdolecek
3 1.4.2.2 jdolecek /*-
4 1.4.2.2 jdolecek * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
5 1.4.2.2 jdolecek * All rights reserved.
6 1.4.2.2 jdolecek *
7 1.4.2.2 jdolecek * Redistribution and use in source and binary forms, with or without
8 1.4.2.2 jdolecek * modification, are permitted provided that the following conditions
9 1.4.2.2 jdolecek * are met:
10 1.4.2.2 jdolecek * 1. Redistributions of source code must retain the above copyright
11 1.4.2.2 jdolecek * notice, this list of conditions and the following disclaimer.
12 1.4.2.2 jdolecek * 2. Redistributions in binary form must reproduce the above copyright
13 1.4.2.2 jdolecek * notice, this list of conditions and the following disclaimer in the
14 1.4.2.2 jdolecek * documentation and/or other materials provided with the distribution.
15 1.4.2.2 jdolecek *
16 1.4.2.2 jdolecek * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 1.4.2.2 jdolecek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1.4.2.2 jdolecek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1.4.2.2 jdolecek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 1.4.2.2 jdolecek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 1.4.2.2 jdolecek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 1.4.2.2 jdolecek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 1.4.2.2 jdolecek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 1.4.2.2 jdolecek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.4.2.2 jdolecek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.4.2.2 jdolecek * SUCH DAMAGE.
27 1.4.2.2 jdolecek *
28 1.4.2.2 jdolecek * $FreeBSD: head/lib/msun/powerpc/fenv.h 226218 2011-10-10 15:43:09Z das $
29 1.4.2.2 jdolecek */
30 1.4.2.2 jdolecek
31 1.4.2.2 jdolecek #ifndef _POWERPC_FENV_H_
32 1.4.2.2 jdolecek #define _POWERPC_FENV_H_
33 1.4.2.2 jdolecek
34 1.4.2.2 jdolecek #include <sys/stdint.h>
35 1.4.2.2 jdolecek
36 1.4.2.2 jdolecek /* Exception flags */
37 1.4.2.2 jdolecek #define FE_INEXACT 0x02000000
38 1.4.2.2 jdolecek #define FE_DIVBYZERO 0x04000000
39 1.4.2.2 jdolecek #define FE_UNDERFLOW 0x08000000
40 1.4.2.2 jdolecek #define FE_OVERFLOW 0x10000000
41 1.4.2.2 jdolecek #define FE_INVALID 0x20000000 /* all types of invalid FP ops */
42 1.4.2.2 jdolecek
43 1.4.2.2 jdolecek /*
44 1.4.2.2 jdolecek * The PowerPC architecture has extra invalid flags that indicate the
45 1.4.2.2 jdolecek * specific type of invalid operation occurred. These flags may be
46 1.4.2.2 jdolecek * tested, set, and cleared---but not masked---separately. All of
47 1.4.2.2 jdolecek * these bits are cleared when FE_INVALID is cleared, but only
48 1.4.2.2 jdolecek * FE_VXSOFT is set when FE_INVALID is explicitly set in software.
49 1.4.2.2 jdolecek */
50 1.4.2.2 jdolecek #define FE_VXCVI 0x00000100 /* invalid integer convert */
51 1.4.2.2 jdolecek #define FE_VXSQRT 0x00000200 /* square root of a negative */
52 1.4.2.2 jdolecek #define FE_VXSOFT 0x00000400 /* software-requested exception */
53 1.4.2.2 jdolecek #define FE_VXVC 0x00080000 /* ordered comparison involving NaN */
54 1.4.2.2 jdolecek #define FE_VXIMZ 0x00100000 /* inf * 0 */
55 1.4.2.2 jdolecek #define FE_VXZDZ 0x00200000 /* 0 / 0 */
56 1.4.2.2 jdolecek #define FE_VXIDI 0x00400000 /* inf / inf */
57 1.4.2.2 jdolecek #define FE_VXISI 0x00800000 /* inf - inf */
58 1.4.2.2 jdolecek #define FE_VXSNAN 0x01000000 /* operation on a signalling NaN */
59 1.4.2.2 jdolecek #define FE_ALL_INVALID (FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \
60 1.4.2.2 jdolecek FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \
61 1.4.2.2 jdolecek FE_VXSNAN | FE_INVALID)
62 1.4.2.2 jdolecek #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
63 1.4.2.2 jdolecek FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
64 1.4.2.2 jdolecek
65 1.4.2.2 jdolecek /* Rounding modes */
66 1.4.2.2 jdolecek #define FE_TONEAREST 0x0000
67 1.4.2.2 jdolecek #define FE_TOWARDZERO 0x0001
68 1.4.2.2 jdolecek #define FE_UPWARD 0x0002
69 1.4.2.2 jdolecek #define FE_DOWNWARD 0x0003
70 1.4.2.2 jdolecek #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
71 1.4.2.2 jdolecek FE_UPWARD | FE_TOWARDZERO)
72 1.4.2.2 jdolecek
73 1.4.2.2 jdolecek #ifndef _SOFT_FLOAT
74 1.4.2.2 jdolecek
75 1.4.2.2 jdolecek #ifndef __fenv_static
76 1.4.2.2 jdolecek #define __fenv_static static
77 1.4.2.2 jdolecek #endif
78 1.4.2.2 jdolecek
79 1.4.2.2 jdolecek typedef uint32_t fenv_t;
80 1.4.2.2 jdolecek typedef uint32_t fexcept_t;
81 1.4.2.2 jdolecek
82 1.4.2.2 jdolecek #ifndef _KERNEL
83 1.4.2.2 jdolecek __BEGIN_DECLS
84 1.4.2.2 jdolecek
85 1.4.2.2 jdolecek /* Default floating-point environment */
86 1.4.2.2 jdolecek extern const fenv_t __fe_dfl_env;
87 1.4.2.2 jdolecek #define FE_DFL_ENV (&__fe_dfl_env)
88 1.4.2.2 jdolecek
89 1.4.2.2 jdolecek /* We need to be able to map status flag positions to mask flag positions */
90 1.4.2.2 jdolecek #define _FPUSW_SHIFT 22
91 1.4.2.2 jdolecek #define _ENABLE_MASK ((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
92 1.4.2.2 jdolecek FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)
93 1.4.2.2 jdolecek
94 1.4.2.2 jdolecek #ifndef _SOFT_FLOAT
95 1.4.2.2 jdolecek #define __mffs(__env) __asm __volatile("mffs %0" : "=f" (*(__env)))
96 1.4.2.2 jdolecek #define __mtfsf(__env) __asm __volatile("mtfsf 255,%0" : : "f" (__env))
97 1.4.2.2 jdolecek
98 1.4.2.2 jdolecek static inline uint32_t
99 1.4.2.2 jdolecek __mfmsr(void)
100 1.4.2.2 jdolecek {
101 1.4.2.2 jdolecek uint32_t __msr;
102 1.4.2.2 jdolecek
103 1.4.2.2 jdolecek __asm volatile ("mfmsr %0" : "=r"(__msr));
104 1.4.2.2 jdolecek return __msr;
105 1.4.2.2 jdolecek }
106 1.4.2.2 jdolecek
107 1.4.2.2 jdolecek static inline void
108 1.4.2.2 jdolecek __mtmsr(uint32_t __msr)
109 1.4.2.2 jdolecek {
110 1.4.2.2 jdolecek
111 1.4.2.2 jdolecek __asm volatile ("mtmsr %0" : : "r"(__msr));
112 1.4.2.2 jdolecek }
113 1.4.2.2 jdolecek
114 1.4.2.2 jdolecek #define __MSR_FE_MASK (0x00000800 | 0x00000100)
115 1.4.2.2 jdolecek #define __MSR_FE_DIS (0)
116 1.4.2.2 jdolecek #define __MSR_FE_PREC (0x00000800 | 0x00000100)
117 1.4.2.2 jdolecek
118 1.4.2.2 jdolecek static inline void
119 1.4.2.2 jdolecek __updatemsr(uint32_t __reg)
120 1.4.2.2 jdolecek {
121 1.4.2.2 jdolecek uint32_t __msr;
122 1.4.2.2 jdolecek
123 1.4.2.2 jdolecek __msr = __mfmsr() & ~__MSR_FE_MASK;
124 1.4.2.2 jdolecek if (__reg != 0) {
125 1.4.2.2 jdolecek __msr |= __MSR_FE_PREC;
126 1.4.2.2 jdolecek } else {
127 1.4.2.2 jdolecek __msr |= __MSR_FE_DIS;
128 1.4.2.2 jdolecek }
129 1.4.2.2 jdolecek __mtmsr(__msr);
130 1.4.2.2 jdolecek }
131 1.4.2.2 jdolecek
132 1.4.2.2 jdolecek #else
133 1.4.2.2 jdolecek #define __mffs(__env)
134 1.4.2.2 jdolecek #define __mtfsf(__env)
135 1.4.2.2 jdolecek #define __updatemsr(__reg)
136 1.4.2.2 jdolecek #endif
137 1.4.2.2 jdolecek
138 1.4.2.2 jdolecek union __fpscr {
139 1.4.2.2 jdolecek double __d;
140 1.4.2.2 jdolecek struct {
141 1.4.2.2 jdolecek uint32_t __junk;
142 1.4.2.2 jdolecek fenv_t __reg;
143 1.4.2.2 jdolecek } __bits;
144 1.4.2.2 jdolecek };
145 1.4.2.2 jdolecek
146 1.4.2.2 jdolecek __fenv_static inline int
147 1.4.2.2 jdolecek feclearexcept(int __excepts)
148 1.4.2.2 jdolecek {
149 1.4.2.2 jdolecek union __fpscr __r;
150 1.4.2.2 jdolecek
151 1.4.2.2 jdolecek if (__excepts & FE_INVALID)
152 1.4.2.2 jdolecek __excepts |= FE_ALL_INVALID;
153 1.4.2.2 jdolecek __mffs(&__r.__d);
154 1.4.2.2 jdolecek __r.__bits.__reg &= ~__excepts;
155 1.4.2.2 jdolecek __mtfsf(__r.__d);
156 1.4.2.2 jdolecek return (0);
157 1.4.2.2 jdolecek }
158 1.4.2.2 jdolecek
159 1.4.2.2 jdolecek __fenv_static inline int
160 1.4.2.2 jdolecek fegetexceptflag(fexcept_t *__flagp, int __excepts)
161 1.4.2.2 jdolecek {
162 1.4.2.2 jdolecek union __fpscr __r;
163 1.4.2.2 jdolecek
164 1.4.2.2 jdolecek __mffs(&__r.__d);
165 1.4.2.2 jdolecek *__flagp = __r.__bits.__reg & __excepts;
166 1.4.2.2 jdolecek return (0);
167 1.4.2.2 jdolecek }
168 1.4.2.2 jdolecek
169 1.4.2.2 jdolecek __fenv_static inline int
170 1.4.2.2 jdolecek fesetexceptflag(const fexcept_t *__flagp, int __excepts)
171 1.4.2.2 jdolecek {
172 1.4.2.2 jdolecek union __fpscr __r;
173 1.4.2.2 jdolecek
174 1.4.2.2 jdolecek if (__excepts & FE_INVALID)
175 1.4.2.2 jdolecek __excepts |= FE_ALL_EXCEPT;
176 1.4.2.2 jdolecek __mffs(&__r.__d);
177 1.4.2.2 jdolecek __r.__bits.__reg &= ~__excepts;
178 1.4.2.2 jdolecek __r.__bits.__reg |= *__flagp & __excepts;
179 1.4.2.2 jdolecek __mtfsf(__r.__d);
180 1.4.2.2 jdolecek return (0);
181 1.4.2.2 jdolecek }
182 1.4.2.2 jdolecek
183 1.4.2.2 jdolecek __fenv_static inline int
184 1.4.2.2 jdolecek feraiseexcept(int __excepts)
185 1.4.2.2 jdolecek {
186 1.4.2.2 jdolecek union __fpscr __r;
187 1.4.2.2 jdolecek
188 1.4.2.2 jdolecek if (__excepts & FE_INVALID)
189 1.4.2.2 jdolecek __excepts |= FE_VXSOFT;
190 1.4.2.2 jdolecek __mffs(&__r.__d);
191 1.4.2.2 jdolecek __r.__bits.__reg |= __excepts;
192 1.4.2.2 jdolecek __mtfsf(__r.__d);
193 1.4.2.2 jdolecek return (0);
194 1.4.2.2 jdolecek }
195 1.4.2.2 jdolecek
196 1.4.2.2 jdolecek __fenv_static inline int
197 1.4.2.2 jdolecek fetestexcept(int __excepts)
198 1.4.2.2 jdolecek {
199 1.4.2.2 jdolecek union __fpscr __r;
200 1.4.2.2 jdolecek
201 1.4.2.2 jdolecek __mffs(&__r.__d);
202 1.4.2.2 jdolecek return (__r.__bits.__reg & __excepts);
203 1.4.2.2 jdolecek }
204 1.4.2.2 jdolecek
205 1.4.2.2 jdolecek __fenv_static inline int
206 1.4.2.2 jdolecek fegetround(void)
207 1.4.2.2 jdolecek {
208 1.4.2.2 jdolecek union __fpscr __r;
209 1.4.2.2 jdolecek
210 1.4.2.2 jdolecek __mffs(&__r.__d);
211 1.4.2.2 jdolecek return (__r.__bits.__reg & _ROUND_MASK);
212 1.4.2.2 jdolecek }
213 1.4.2.2 jdolecek
214 1.4.2.2 jdolecek __fenv_static inline int
215 1.4.2.2 jdolecek fesetround(int __round)
216 1.4.2.2 jdolecek {
217 1.4.2.2 jdolecek union __fpscr __r;
218 1.4.2.2 jdolecek
219 1.4.2.2 jdolecek if (__round & ~_ROUND_MASK)
220 1.4.2.2 jdolecek return (-1);
221 1.4.2.2 jdolecek __mffs(&__r.__d);
222 1.4.2.2 jdolecek __r.__bits.__reg &= ~_ROUND_MASK;
223 1.4.2.2 jdolecek __r.__bits.__reg |= __round;
224 1.4.2.2 jdolecek __mtfsf(__r.__d);
225 1.4.2.2 jdolecek return (0);
226 1.4.2.2 jdolecek }
227 1.4.2.2 jdolecek
228 1.4.2.2 jdolecek __fenv_static inline int
229 1.4.2.2 jdolecek fegetenv(fenv_t *__envp)
230 1.4.2.2 jdolecek {
231 1.4.2.2 jdolecek union __fpscr __r;
232 1.4.2.2 jdolecek
233 1.4.2.2 jdolecek __mffs(&__r.__d);
234 1.4.2.2 jdolecek *__envp = __r.__bits.__reg;
235 1.4.2.2 jdolecek return (0);
236 1.4.2.2 jdolecek }
237 1.4.2.2 jdolecek
238 1.4.2.2 jdolecek __fenv_static inline int
239 1.4.2.2 jdolecek feholdexcept(fenv_t *__envp)
240 1.4.2.2 jdolecek {
241 1.4.2.2 jdolecek union __fpscr __r;
242 1.4.2.2 jdolecek uint32_t msr;
243 1.4.2.2 jdolecek
244 1.4.2.2 jdolecek __mffs(&__r.__d);
245 1.4.2.2 jdolecek *__envp = __r.__bits.__reg;
246 1.4.2.2 jdolecek __r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
247 1.4.2.2 jdolecek __mtfsf(__r.__d);
248 1.4.2.2 jdolecek __updatemsr(__r.__bits.__reg);
249 1.4.2.2 jdolecek return (0);
250 1.4.2.2 jdolecek }
251 1.4.2.2 jdolecek
252 1.4.2.2 jdolecek __fenv_static inline int
253 1.4.2.2 jdolecek fesetenv(const fenv_t *__envp)
254 1.4.2.2 jdolecek {
255 1.4.2.2 jdolecek union __fpscr __r;
256 1.4.2.2 jdolecek
257 1.4.2.2 jdolecek __r.__bits.__reg = *__envp;
258 1.4.2.2 jdolecek __mtfsf(__r.__d);
259 1.4.2.2 jdolecek __updatemsr(__r.__bits.__reg);
260 1.4.2.2 jdolecek return (0);
261 1.4.2.2 jdolecek }
262 1.4.2.2 jdolecek
263 1.4.2.2 jdolecek __fenv_static inline int
264 1.4.2.2 jdolecek feupdateenv(const fenv_t *__envp)
265 1.4.2.2 jdolecek {
266 1.4.2.2 jdolecek union __fpscr __r;
267 1.4.2.2 jdolecek
268 1.4.2.2 jdolecek __mffs(&__r.__d);
269 1.4.2.2 jdolecek __r.__bits.__reg &= FE_ALL_EXCEPT;
270 1.4.2.2 jdolecek __r.__bits.__reg |= *__envp;
271 1.4.2.2 jdolecek __mtfsf(__r.__d);
272 1.4.2.2 jdolecek __updatemsr(__r.__bits.__reg);
273 1.4.2.2 jdolecek return (0);
274 1.4.2.2 jdolecek }
275 1.4.2.2 jdolecek
276 1.4.2.2 jdolecek #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
277 1.4.2.2 jdolecek
278 1.4.2.2 jdolecek __fenv_static inline int
279 1.4.2.2 jdolecek feenableexcept(int __mask)
280 1.4.2.2 jdolecek {
281 1.4.2.2 jdolecek union __fpscr __r;
282 1.4.2.2 jdolecek fenv_t __oldmask;
283 1.4.2.2 jdolecek
284 1.4.2.2 jdolecek __mffs(&__r.__d);
285 1.4.2.2 jdolecek __oldmask = __r.__bits.__reg;
286 1.4.2.2 jdolecek __r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
287 1.4.2.2 jdolecek __mtfsf(__r.__d);
288 1.4.2.2 jdolecek __updatemsr(__r.__bits.__reg);
289 1.4.2.2 jdolecek return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
290 1.4.2.2 jdolecek }
291 1.4.2.2 jdolecek
292 1.4.2.2 jdolecek __fenv_static inline int
293 1.4.2.2 jdolecek fedisableexcept(int __mask)
294 1.4.2.2 jdolecek {
295 1.4.2.2 jdolecek union __fpscr __r;
296 1.4.2.2 jdolecek fenv_t __oldmask;
297 1.4.2.2 jdolecek
298 1.4.2.2 jdolecek __mffs(&__r.__d);
299 1.4.2.2 jdolecek __oldmask = __r.__bits.__reg;
300 1.4.2.2 jdolecek __r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
301 1.4.2.2 jdolecek __mtfsf(__r.__d);
302 1.4.2.2 jdolecek __updatemsr(__r.__bits.__reg);
303 1.4.2.2 jdolecek return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
304 1.4.2.2 jdolecek }
305 1.4.2.2 jdolecek
306 1.4.2.2 jdolecek __fenv_static inline int
307 1.4.2.2 jdolecek fegetexcept(void)
308 1.4.2.2 jdolecek {
309 1.4.2.2 jdolecek union __fpscr __r;
310 1.4.2.2 jdolecek
311 1.4.2.2 jdolecek __mffs(&__r.__d);
312 1.4.2.2 jdolecek return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
313 1.4.2.2 jdolecek }
314 1.4.2.2 jdolecek
315 1.4.2.2 jdolecek #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
316 1.4.2.2 jdolecek
317 1.4.2.2 jdolecek __END_DECLS
318 1.4.2.2 jdolecek
319 1.4.2.2 jdolecek #endif
320 1.4.2.2 jdolecek #endif /* _SOFT_FLOAT */
321 1.4.2.2 jdolecek
322 1.4.2.2 jdolecek #endif /* !_POWERPC_FENV_H_ */
323