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 #ifndef __riscv_float_abi_double
75 #error only double hard float ABI supported
76 #endif
77
78 #define __rfs(__fcsr) __asm __volatile("csrr %0, fcsr" : "=r" (__fcsr))
79 #define __wfs(__fcsr) __asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
80
81 __fenv_static inline int
feclearexcept(int __excepts)82 feclearexcept(int __excepts)
83 {
84
85 __asm __volatile("csrc fflags, %0" :: "r"(__excepts));
86
87 return (0);
88 }
89
90 __fenv_static inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)91 fegetexceptflag(fexcept_t *__flagp, int __excepts)
92 {
93 fexcept_t __fcsr;
94
95 __rfs(__fcsr);
96 *__flagp = __fcsr & __excepts;
97
98 return (0);
99 }
100
101 __fenv_static inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)102 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
103 {
104 fexcept_t __fcsr;
105
106 __fcsr = *__flagp;
107 __asm __volatile("csrc fflags, %0" :: "r"(__excepts));
108 __asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts));
109
110 return (0);
111 }
112
113 __fenv_static inline int
feraiseexcept(int __excepts)114 feraiseexcept(int __excepts)
115 {
116
117 __asm __volatile("csrs fflags, %0" :: "r"(__excepts));
118
119 return (0);
120 }
121
122 __fenv_static inline int
fetestexcept(int __excepts)123 fetestexcept(int __excepts)
124 {
125 fexcept_t __fcsr;
126
127 __rfs(__fcsr);
128
129 return (__fcsr & __excepts);
130 }
131
132 __fenv_static inline int
fegetround(void)133 fegetround(void)
134 {
135 fexcept_t __fcsr;
136
137 __rfs(__fcsr);
138
139 return (__fcsr & _ROUND_MASK);
140 }
141
142 __fenv_static inline int
fesetround(int __round)143 fesetround(int __round)
144 {
145 fexcept_t __fcsr;
146
147 if (__round & ~_ROUND_MASK)
148 return (-1);
149
150 __rfs(__fcsr);
151 __fcsr &= ~_ROUND_MASK;
152 __fcsr |= __round;
153 __wfs(__fcsr);
154
155 return (0);
156 }
157
158 __fenv_static inline int
fegetenv(fenv_t * __envp)159 fegetenv(fenv_t *__envp)
160 {
161
162 __rfs(*__envp);
163
164 return (0);
165 }
166
167 __fenv_static inline int
feholdexcept(fenv_t * __envp __unused)168 feholdexcept(fenv_t *__envp __unused)
169 {
170
171 /* No exception traps. */
172
173 return (-1);
174 }
175
176 __fenv_static inline int
fesetenv(const fenv_t * __envp)177 fesetenv(const fenv_t *__envp)
178 {
179
180 __wfs(*__envp);
181
182 return (0);
183 }
184
185 __fenv_static inline int
feupdateenv(const fenv_t * __envp)186 feupdateenv(const fenv_t *__envp)
187 {
188 fexcept_t __fcsr;
189
190 __rfs(__fcsr);
191 __wfs(*__envp);
192 feraiseexcept(__fcsr & FE_ALL_EXCEPT);
193
194 return (0);
195 }
196
197 #if __BSD_VISIBLE
198
199 __fenv_static inline int
feenableexcept(int __mask __unused)200 feenableexcept(int __mask __unused)
201 {
202
203 /* No exception traps. */
204
205 return (0);
206 }
207
208 __fenv_static inline int
fedisableexcept(int __mask __unused)209 fedisableexcept(int __mask __unused)
210 {
211
212 /* No exception traps. */
213
214 return (0);
215 }
216
217 /* We currently provide no external definition of fegetexcept(). */
218 static inline int
fegetexcept(void)219 fegetexcept(void)
220 {
221
222 /* No exception traps. */
223
224 return (0);
225 }
226
227 #endif /* __BSD_VISIBLE */
228
229 __END_DECLS
230
231 #endif /* !_FENV_H_ */
232