1/*-
2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3 * Copyright (c) 2015 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 <sys/_types.h>
42
43#ifndef	__fenv_static
44#define	__fenv_static	static
45#endif
46
47typedef	__uint64_t	fenv_t;
48typedef	__uint64_t	fexcept_t;
49
50/* Exception flags */
51#define	FE_INVALID	0x0010
52#define	FE_DIVBYZERO	0x0008
53#define	FE_OVERFLOW	0x0004
54#define	FE_UNDERFLOW	0x0002
55#define	FE_INEXACT	0x0001
56#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
57			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
58
59/*
60 * RISC-V Rounding modes
61 */
62#define	FE_TONEAREST	(0x00 << 5)
63#define	FE_TOWARDZERO	(0x01 << 5)
64#define	FE_DOWNWARD	(0x02 << 5)
65#define	FE_UPWARD	(0x03 << 5)
66#define	_ROUND_SHIFT	5
67#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
68			 FE_UPWARD | FE_TOWARDZERO)
69
70__BEGIN_DECLS
71
72/* Default floating-point environment */
73extern const fenv_t	__fe_dfl_env;
74#define	FE_DFL_ENV	(&__fe_dfl_env)
75
76/* We need to be able to map status flag positions to mask flag positions */
77#define	_FPUSW_SHIFT	0
78#define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
79
80#define	__rfs(__fpsr)	__asm __volatile("csrr %0, fcsr" : "=r" (*(__fpsr)))
81#define	__wfs(__fpsr)	__asm __volatile("csrw fcsr, %0" :: "r" (__fpsr))
82
83__fenv_static inline int
84feclearexcept(int __excepts)
85{
86	fexcept_t __fpsr;
87
88	__rfs(&__fpsr);
89	__fpsr &= ~__excepts;
90	__wfs(__fpsr);
91	return (0);
92}
93
94__fenv_static inline int
95fegetexceptflag(fexcept_t *__flagp, int __excepts)
96{
97	fexcept_t __fpsr;
98
99	__rfs(&__fpsr);
100	*__flagp = __fpsr & __excepts;
101	return (0);
102}
103
104__fenv_static inline int
105fesetexceptflag(const fexcept_t *__flagp, int __excepts)
106{
107	fexcept_t __fpsr;
108
109	__rfs(&__fpsr);
110	__fpsr &= ~__excepts;
111	__fpsr |= *__flagp & __excepts;
112	__wfs(__fpsr);
113	return (0);
114}
115
116__fenv_static inline int
117feraiseexcept(int __excepts)
118{
119	fexcept_t __ex = __excepts;
120
121	fesetexceptflag(&__ex, __excepts);	/* XXX */
122	return (0);
123}
124
125__fenv_static inline int
126fetestexcept(int __excepts)
127{
128	fexcept_t __fpsr;
129
130	__rfs(&__fpsr);
131	return (__fpsr & __excepts);
132}
133
134__fenv_static inline int
135fegetround(void)
136{
137
138	return (-1);
139}
140
141__fenv_static inline int
142fesetround(int __round)
143{
144
145	return (-1);
146}
147
148__fenv_static inline int
149fegetenv(fenv_t *__envp)
150{
151
152	__rfs(__envp);
153	return (0);
154}
155
156__fenv_static inline int
157feholdexcept(fenv_t *__envp)
158{
159	fenv_t __env;
160
161	__rfs(&__env);
162	*__envp = __env;
163	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
164	__wfs(__env);
165	return (0);
166}
167
168__fenv_static inline int
169fesetenv(const fenv_t *__envp)
170{
171
172	__wfs(*__envp);
173	return (0);
174}
175
176__fenv_static inline int
177feupdateenv(const fenv_t *__envp)
178{
179	fexcept_t __fpsr;
180
181	__rfs(&__fpsr);
182	__wfs(*__envp);
183	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
184	return (0);
185}
186
187#if __BSD_VISIBLE
188
189/* We currently provide no external definitions of the functions below. */
190
191static inline int
192feenableexcept(int __mask)
193{
194	fenv_t __old_fpsr;
195	fenv_t __new_fpsr;
196
197	__rfs(&__old_fpsr);
198	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
199	__wfs(__new_fpsr);
200	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
201}
202
203static inline int
204fedisableexcept(int __mask)
205{
206	fenv_t __old_fpsr;
207	fenv_t __new_fpsr;
208
209	__rfs(&__old_fpsr);
210	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
211	__wfs(__new_fpsr);
212	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
213}
214
215static inline int
216fegetexcept(void)
217{
218	fenv_t __fpsr;
219
220	__rfs(&__fpsr);
221	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
222}
223
224#endif /* __BSD_VISIBLE */
225
226__END_DECLS
227
228#endif	/* !_FENV_H_ */
229