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
49typedef	uint64_t	fenv_t;
50typedef	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 */
75extern 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
92int feclearexcept(int __excepts);
93int fegetexceptflag(fexcept_t *__flagp, int __excepts);
94int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
95int feraiseexcept(int __excepts);
96int fetestexcept(int __excepts);
97int fegetround(void);
98int fesetround(int __round);
99int fegetenv(fenv_t *__envp);
100int feholdexcept(fenv_t *__envp);
101int fesetenv(const fenv_t *__envp);
102int feupdateenv(const fenv_t *__envp);
103#else
104__fenv_static inline int
105feclearexcept(int __excepts)
106{
107
108	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
109
110	return (0);
111}
112
113__fenv_static inline int
114fegetexceptflag(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
125fesetexceptflag(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
137feraiseexcept(int __excepts)
138{
139
140	__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
141
142	return (0);
143}
144
145__fenv_static inline int
146fetestexcept(int __excepts)
147{
148	fexcept_t __fcsr;
149
150	__rfs(__fcsr);
151
152	return (__fcsr & __excepts);
153}
154
155__fenv_static inline int
156fegetround(void)
157{
158	fexcept_t __fcsr;
159
160	__rfs(__fcsr);
161
162	return (__fcsr & _ROUND_MASK);
163}
164
165__fenv_static inline int
166fesetround(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
182fegetenv(fenv_t *__envp)
183{
184
185	__rfs(*__envp);
186
187	return (0);
188}
189
190__fenv_static inline int
191feholdexcept(fenv_t *__envp)
192{
193
194	/* No exception traps. */
195
196	return (-1);
197}
198
199__fenv_static inline int
200fesetenv(const fenv_t *__envp)
201{
202
203	__wfs(*__envp);
204
205	return (0);
206}
207
208__fenv_static inline int
209feupdateenv(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
226int feenableexcept(int __mask);
227int fedisableexcept(int __mask);
228int fegetexcept(void);
229#else
230static inline int
231feenableexcept(int __mask)
232{
233
234	/* No exception traps. */
235
236	return (-1);
237}
238
239static inline int
240fedisableexcept(int __mask)
241{
242
243	/* No exception traps. */
244
245	return (0);
246}
247
248static inline int
249fegetexcept(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