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 * $FreeBSD$
36 */
37
38 #ifndef _FENV_H_
39 #define _FENV_H_
40
41 #include <stdint.h>
42 #include <sys/cdefs.h>
43 #include <sys/types.h>
44
45 #ifndef __fenv_static
46 #define __fenv_static static
47 #endif
48
49 typedef uint64_t fenv_t;
50 typedef uint64_t fexcept_t;
51
52 /* Exception flags */
53 #define FE_INVALID 0x0010
54 #define FE_DIVBYZERO 0x0008
55 #define FE_OVERFLOW 0x0004
56 #define FE_UNDERFLOW 0x0002
57 #define FE_INEXACT 0x0001
58 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
59 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
60
61 /*
62 * RISC-V Rounding modes
63 */
64 #define _ROUND_SHIFT 5
65 #define FE_TONEAREST (0x00 << _ROUND_SHIFT)
66 #define FE_TOWARDZERO (0x01 << _ROUND_SHIFT)
67 #define FE_DOWNWARD (0x02 << _ROUND_SHIFT)
68 #define FE_UPWARD (0x03 << _ROUND_SHIFT)
69 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
70 FE_UPWARD | FE_TOWARDZERO)
71
72 __BEGIN_DECLS
73
74 /* Default floating-point environment */
75 extern const fenv_t __fe_dfl_env;
76 #define FE_DFL_ENV (&__fe_dfl_env)
77
78 #if !defined(__riscv_float_abi_soft) && !defined(__riscv_float_abi_double)
79 #if defined(__riscv_float_abi_single)
80 #error single precision floating point ABI not supported
81 #else
82 #error compiler did not set soft/hard float macros
83 #endif
84 #endif
85
86 #ifndef __riscv_float_abi_soft
87 #define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr))
88 #define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
89 #endif
90
91 #ifdef __riscv_float_abi_soft
92 int feclearexcept(int __excepts);
93 int fegetexceptflag(fexcept_t *__flagp, int __excepts);
94 int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
95 int feraiseexcept(int __excepts);
96 int fetestexcept(int __excepts);
97 int fegetround(void);
98 int fesetround(int __round);
99 int fegetenv(fenv_t *__envp);
100 int feholdexcept(fenv_t *__envp);
101 int fesetenv(const fenv_t *__envp);
102 int feupdateenv(const fenv_t *__envp);
103 #else
104 __fenv_static inline int
feclearexcept(int __excepts)105 feclearexcept(int __excepts)
106 {
107
108 __asm __volatile("csrc fflags, %0" :: "r"(__excepts));
109
110 return (0);
111 }
112
113 __fenv_static inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)114 fegetexceptflag(fexcept_t *__flagp, int __excepts)
115 {
116 fexcept_t __fcsr;
117
118 __rfs(__fcsr);
119 *__flagp = __fcsr & __excepts;
120
121 return (0);
122 }
123
124 __fenv_static inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)125 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
126 {
127 fexcept_t __fcsr;
128
129 __fcsr = *__flagp;
130 __asm __volatile("csrc fflags, %0" :: "r"(__excepts));
131 __asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts));
132
133 return (0);
134 }
135
136 __fenv_static inline int
feraiseexcept(int __excepts)137 feraiseexcept(int __excepts)
138 {
139
140 __asm __volatile("csrs fflags, %0" :: "r"(__excepts));
141
142 return (0);
143 }
144
145 __fenv_static inline int
fetestexcept(int __excepts)146 fetestexcept(int __excepts)
147 {
148 fexcept_t __fcsr;
149
150 __rfs(__fcsr);
151
152 return (__fcsr & __excepts);
153 }
154
155 __fenv_static inline int
fegetround(void)156 fegetround(void)
157 {
158 fexcept_t __fcsr;
159
160 __rfs(__fcsr);
161
162 return (__fcsr & _ROUND_MASK);
163 }
164
165 __fenv_static inline int
fesetround(int __round)166 fesetround(int __round)
167 {
168 fexcept_t __fcsr;
169
170 if (__round & ~_ROUND_MASK)
171 return (-1);
172
173 __rfs(__fcsr);
174 __fcsr &= ~_ROUND_MASK;
175 __fcsr |= __round;
176 __wfs(__fcsr);
177
178 return (0);
179 }
180
181 __fenv_static inline int
fegetenv(fenv_t * __envp)182 fegetenv(fenv_t *__envp)
183 {
184
185 __rfs(*__envp);
186
187 return (0);
188 }
189
190 __fenv_static inline int
feholdexcept(fenv_t * __envp)191 feholdexcept(fenv_t *__envp)
192 {
193
194 /* No exception traps. */
195
196 return (-1);
197 }
198
199 __fenv_static inline int
fesetenv(const fenv_t * __envp)200 fesetenv(const fenv_t *__envp)
201 {
202
203 __wfs(*__envp);
204
205 return (0);
206 }
207
208 __fenv_static inline int
feupdateenv(const fenv_t * __envp)209 feupdateenv(const fenv_t *__envp)
210 {
211 fexcept_t __fcsr;
212
213 __rfs(__fcsr);
214 __wfs(*__envp);
215 feraiseexcept(__fcsr & FE_ALL_EXCEPT);
216
217 return (0);
218 }
219 #endif /* !__riscv_float_abi_soft */
220
221 #if __BSD_VISIBLE
222
223 /* We currently provide no external definitions of the functions below. */
224
225 #ifdef __riscv_float_abi_soft
226 int feenableexcept(int __mask);
227 int fedisableexcept(int __mask);
228 int fegetexcept(void);
229 #else
230 static inline int
feenableexcept(int __mask)231 feenableexcept(int __mask)
232 {
233
234 /* No exception traps. */
235
236 return (-1);
237 }
238
239 static inline int
fedisableexcept(int __mask)240 fedisableexcept(int __mask)
241 {
242
243 /* No exception traps. */
244
245 return (0);
246 }
247
248 static inline int
fegetexcept(void)249 fegetexcept(void)
250 {
251
252 /* No exception traps. */
253
254 return (0);
255 }
256 #endif /* !__riscv_float_abi_soft */
257
258 #endif /* __BSD_VISIBLE */
259
260 __END_DECLS
261
262 #endif /* !_FENV_H_ */
263