xref: /netbsd-src/sys/arch/mips/include/fenv.h (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
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@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