fenv.h revision 1.4 1 /* $NetBSD: fenv.h,v 1.4 2017/03/22 23:11:09 chs Exp $ */
2
3 /*-
4 * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $
29 */
30
31 #ifndef _MIPS_FENV_H_
32 #define _MIPS_FENV_H_
33
34 #include <sys/stdint.h>
35
36 /* Exception flags */
37 #define FE_INEXACT 0x0004
38 #define FE_UNDERFLOW 0x0008
39 #define FE_OVERFLOW 0x0010
40 #define FE_DIVBYZERO 0x0020
41 #define FE_INVALID 0x0040
42 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
43 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
44
45 /* Rounding modes */
46 #define FE_TONEAREST 0x0000
47 #define FE_TOWARDZERO 0x0001
48 #define FE_UPWARD 0x0002
49 #define FE_DOWNWARD 0x0003
50 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
51 FE_UPWARD | FE_TOWARDZERO)
52
53 #ifndef __mips_soft_float
54
55 #ifndef __fenv_static
56 #define __fenv_static static
57 #endif
58
59 typedef uint32_t fpu_control_t __attribute__((__mode__(__SI__)));
60 typedef fpu_control_t fenv_t;
61 typedef fpu_control_t fexcept_t;
62
63 __BEGIN_DECLS
64
65 /* Default floating-point environment */
66 extern const fenv_t __fe_dfl_env;
67 #define FE_DFL_ENV (&__fe_dfl_env)
68
69 /* We need to be able to map status flag positions to mask flag positions */
70 #define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
71 #define _ENABLE_SHIFT 5
72
73 static inline fpu_control_t
74 __rfs(void)
75 {
76 fpu_control_t __fpsr;
77
78 __asm __volatile("cfc1 %0,$31" : "=r" (__fpsr));
79 return __fpsr;
80 }
81
82 static inline void
83 __wfs(fpu_control_t __fpsr)
84 {
85
86 __asm __volatile("ctc1 %0,$31" : : "r" (__fpsr));
87 }
88
89 __fenv_static inline int
90 feclearexcept(int __excepts)
91 {
92 fexcept_t __fpsr;
93
94 __excepts &= FE_ALL_EXCEPT;
95 __fpsr = __rfs();
96 __fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT));
97 __wfs(__fpsr);
98 return 0;
99 }
100
101 __fenv_static inline int
102 fegetexceptflag(fexcept_t *__flagp, int __excepts)
103 {
104 fexcept_t __fpsr;
105
106 __fpsr = __rfs();
107 *__flagp = __fpsr & __excepts;
108 return (0);
109 }
110
111 __fenv_static inline int
112 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
113 {
114 fexcept_t __fpsr;
115
116 __fpsr = __rfs();
117 __fpsr &= ~__excepts;
118 __fpsr |= *__flagp & __excepts;
119 __wfs(__fpsr);
120 return (0);
121 }
122
123 __fenv_static inline int
124 feraiseexcept(int __excepts)
125 {
126 fexcept_t __ex = __excepts;
127
128 fesetexceptflag(&__ex, __excepts); /* XXX */
129 return (0);
130 }
131
132 __fenv_static inline int
133 fetestexcept(int __excepts)
134 {
135 fexcept_t __fpsr;
136
137 __fpsr = __rfs();
138 return (__fpsr & __excepts);
139 }
140
141 __fenv_static inline int
142 fegetround(void)
143 {
144 fexcept_t __fpsr;
145
146 __fpsr = __rfs();
147 return __fpsr & _ROUND_MASK;
148 }
149
150 __fenv_static inline int
151 fesetround(int __round)
152 {
153 fexcept_t __fpsr;
154
155 if (__round & ~_ROUND_MASK)
156 return 1;
157 __fpsr = __rfs();
158 __fpsr &= ~_ROUND_MASK;
159 __fpsr |= __round;
160 __wfs(__fpsr);
161
162 return 0;
163 }
164
165 __fenv_static inline int
166 fegetenv(fenv_t *__envp)
167 {
168
169 *__envp = __rfs();
170 return (0);
171 }
172
173 __fenv_static inline int
174 feholdexcept(fenv_t *__envp)
175 {
176 fenv_t __env;
177
178 __env = __rfs();
179 *__envp = __env;
180 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
181 __wfs(__env);
182 return (0);
183 }
184
185 __fenv_static inline int
186 fesetenv(const fenv_t *__envp)
187 {
188
189 __wfs(*__envp);
190 return (0);
191 }
192
193 __fenv_static inline int
194 feupdateenv(const fenv_t *__envp)
195 {
196 fexcept_t __fpsr;
197
198 __fpsr = __rfs();
199 __wfs(*__envp);
200 feraiseexcept(__fpsr & FE_ALL_EXCEPT);
201 return (0);
202 }
203
204 #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
205
206 __fenv_static inline int
207 feenableexcept(int __excepts)
208 {
209 fenv_t __old_fpsr, __new_fpsr;
210
211 __new_fpsr = __rfs();
212 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
213 __excepts &= FE_ALL_EXCEPT;
214 __new_fpsr |= __excepts << _ENABLE_SHIFT;
215 __wfs(__new_fpsr);
216 return __old_fpsr;
217 }
218
219 __fenv_static inline int
220 fedisableexcept(int __excepts)
221 {
222 fenv_t __old_fpsr, __new_fpsr;
223
224 __new_fpsr = __rfs();
225 __old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
226 __excepts &= FE_ALL_EXCEPT;
227 __new_fpsr &= ~(__excepts << _ENABLE_SHIFT);
228 __wfs(__new_fpsr);
229 return __old_fpsr;
230 }
231
232 __fenv_static inline int
233 fegetexcept(void)
234 {
235 fenv_t __fpsr;
236
237 __fpsr = __rfs();
238 return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT);
239 }
240
241 #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
242
243 __END_DECLS
244
245 #endif /* __mips_soft_float */
246
247 #endif /* !_FENV_H_ */
248