xref: /freebsd/lib/msun/riscv/fenv.h (revision 315ee00f)
1 /*-
2  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3  * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
4  * All rights reserved.
5  *
6  * Portions of this software were developed by SRI International and the
7  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
8  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
9  *
10  * Portions of this software were developed by the University of Cambridge
11  * Computer Laboratory as part of the CTSRD Project, with support from the
12  * UK Higher Education Innovation Fund (HEIF).
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef	_FENV_H_
37 #define	_FENV_H_
38 
39 #include <sys/_types.h>
40 
41 #ifndef	__fenv_static
42 #define	__fenv_static	static
43 #endif
44 
45 typedef	__uint64_t	fenv_t;
46 typedef	__uint64_t	fexcept_t;
47 
48 /* Exception flags */
49 #define	FE_INVALID	0x0010
50 #define	FE_DIVBYZERO	0x0008
51 #define	FE_OVERFLOW	0x0004
52 #define	FE_UNDERFLOW	0x0002
53 #define	FE_INEXACT	0x0001
54 #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
55 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
56 
57 /*
58  * RISC-V Rounding modes
59  */
60 #define	_ROUND_SHIFT	5
61 #define	FE_TONEAREST	(0x00 << _ROUND_SHIFT)
62 #define	FE_TOWARDZERO	(0x01 << _ROUND_SHIFT)
63 #define	FE_DOWNWARD	(0x02 << _ROUND_SHIFT)
64 #define	FE_UPWARD	(0x03 << _ROUND_SHIFT)
65 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
66 			 FE_UPWARD | FE_TOWARDZERO)
67 
68 __BEGIN_DECLS
69 
70 /* Default floating-point environment */
71 extern const fenv_t	__fe_dfl_env;
72 #define	FE_DFL_ENV	(&__fe_dfl_env)
73 
74 #if !defined(__riscv_float_abi_soft) && !defined(__riscv_float_abi_double)
75 #if defined(__riscv_float_abi_single)
76 #error single precision floating point ABI not supported
77 #else
78 #error compiler did not set soft/hard float macros
79 #endif
80 #endif
81 
82 #ifndef __riscv_float_abi_soft
83 #define	__rfs(__fcsr)	__asm __volatile("csrr %0, fcsr" : "=r" (__fcsr))
84 #define	__wfs(__fcsr)	__asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
85 #endif
86 
87 #ifdef __riscv_float_abi_soft
88 int feclearexcept(int __excepts);
89 int fegetexceptflag(fexcept_t *__flagp, int __excepts);
90 int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
91 int feraiseexcept(int __excepts);
92 int fetestexcept(int __excepts);
93 int fegetround(void);
94 int fesetround(int __round);
95 int fegetenv(fenv_t *__envp);
96 int feholdexcept(fenv_t *__envp);
97 int fesetenv(const fenv_t *__envp);
98 int feupdateenv(const fenv_t *__envp);
99 #else
100 __fenv_static inline int
101 feclearexcept(int __excepts)
102 {
103 
104 	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
105 
106 	return (0);
107 }
108 
109 __fenv_static inline int
110 fegetexceptflag(fexcept_t *__flagp, int __excepts)
111 {
112 	fexcept_t __fcsr;
113 
114 	__rfs(__fcsr);
115 	*__flagp = __fcsr & __excepts;
116 
117 	return (0);
118 }
119 
120 __fenv_static inline int
121 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
122 {
123 	fexcept_t __fcsr;
124 
125 	__fcsr = *__flagp;
126 	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
127 	__asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts));
128 
129 	return (0);
130 }
131 
132 __fenv_static inline int
133 feraiseexcept(int __excepts)
134 {
135 
136 	__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
137 
138 	return (0);
139 }
140 
141 __fenv_static inline int
142 fetestexcept(int __excepts)
143 {
144 	fexcept_t __fcsr;
145 
146 	__rfs(__fcsr);
147 
148 	return (__fcsr & __excepts);
149 }
150 
151 __fenv_static inline int
152 fegetround(void)
153 {
154 	fexcept_t __fcsr;
155 
156 	__rfs(__fcsr);
157 
158 	return (__fcsr & _ROUND_MASK);
159 }
160 
161 __fenv_static inline int
162 fesetround(int __round)
163 {
164 	fexcept_t __fcsr;
165 
166 	if (__round & ~_ROUND_MASK)
167 		return (-1);
168 
169 	__rfs(__fcsr);
170 	__fcsr &= ~_ROUND_MASK;
171 	__fcsr |= __round;
172 	__wfs(__fcsr);
173 
174 	return (0);
175 }
176 
177 __fenv_static inline int
178 fegetenv(fenv_t *__envp)
179 {
180 
181 	__rfs(*__envp);
182 
183 	return (0);
184 }
185 
186 __fenv_static inline int
187 feholdexcept(fenv_t *__envp __unused)
188 {
189 
190 	/* No exception traps. */
191 
192 	return (-1);
193 }
194 
195 __fenv_static inline int
196 fesetenv(const fenv_t *__envp)
197 {
198 
199 	__wfs(*__envp);
200 
201 	return (0);
202 }
203 
204 __fenv_static inline int
205 feupdateenv(const fenv_t *__envp)
206 {
207 	fexcept_t __fcsr;
208 
209 	__rfs(__fcsr);
210 	__wfs(*__envp);
211 	feraiseexcept(__fcsr & FE_ALL_EXCEPT);
212 
213 	return (0);
214 }
215 #endif /* !__riscv_float_abi_soft */
216 
217 #if __BSD_VISIBLE
218 
219 /* We currently provide no external definitions of the functions below. */
220 
221 #ifdef __riscv_float_abi_soft
222 int feenableexcept(int __mask);
223 int fedisableexcept(int __mask);
224 int fegetexcept(void);
225 #else
226 static inline int
227 feenableexcept(int __mask __unused)
228 {
229 
230 	/* No exception traps. */
231 
232 	return (0);
233 }
234 
235 static inline int
236 fedisableexcept(int __mask __unused)
237 {
238 
239 	/* No exception traps. */
240 
241 	return (0);
242 }
243 
244 static inline int
245 fegetexcept(void)
246 {
247 
248 	/* No exception traps. */
249 
250 	return (0);
251 }
252 #endif /* !__riscv_float_abi_soft */
253 
254 #endif /* __BSD_VISIBLE */
255 
256 __END_DECLS
257 
258 #endif	/* !_FENV_H_ */
259