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
 45typedef	__uint64_t	fenv_t;
 46typedef	__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 */
 71extern 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
 88int feclearexcept(int __excepts);
 89int fegetexceptflag(fexcept_t *__flagp, int __excepts);
 90int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
 91int feraiseexcept(int __excepts);
 92int fetestexcept(int __excepts);
 93int fegetround(void);
 94int fesetround(int __round);
 95int fegetenv(fenv_t *__envp);
 96int feholdexcept(fenv_t *__envp);
 97int fesetenv(const fenv_t *__envp);
 98int feupdateenv(const fenv_t *__envp);
 99#else
100__fenv_static inline int
101feclearexcept(int __excepts)
102{
103
104	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
105
106	return (0);
107}
108
109__fenv_static inline int
110fegetexceptflag(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
121fesetexceptflag(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
133feraiseexcept(int __excepts)
134{
135
136	__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
137
138	return (0);
139}
140
141__fenv_static inline int
142fetestexcept(int __excepts)
143{
144	fexcept_t __fcsr;
145
146	__rfs(__fcsr);
147
148	return (__fcsr & __excepts);
149}
150
151__fenv_static inline int
152fegetround(void)
153{
154	fexcept_t __fcsr;
155
156	__rfs(__fcsr);
157
158	return (__fcsr & _ROUND_MASK);
159}
160
161__fenv_static inline int
162fesetround(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
178fegetenv(fenv_t *__envp)
179{
180
181	__rfs(*__envp);
182
183	return (0);
184}
185
186__fenv_static inline int
187feholdexcept(fenv_t *__envp __unused)
188{
189
190	/* No exception traps. */
191
192	return (-1);
193}
194
195__fenv_static inline int
196fesetenv(const fenv_t *__envp)
197{
198
199	__wfs(*__envp);
200
201	return (0);
202}
203
204__fenv_static inline int
205feupdateenv(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#ifdef __riscv_float_abi_soft
220int feenableexcept(int __mask);
221int fedisableexcept(int __mask);
222int fegetexcept(void);
223#else
224__fenv_static inline int
225feenableexcept(int __mask __unused)
226{
227
228	/* No exception traps. */
229
230	return (0);
231}
232
233__fenv_static inline int
234fedisableexcept(int __mask __unused)
235{
236
237	/* No exception traps. */
238
239	return (0);
240}
241
242/* We currently provide no external definition of fegetexcept(). */
243static inline int
244fegetexcept(void)
245{
246
247	/* No exception traps. */
248
249	return (0);
250}
251#endif /* !__riscv_float_abi_soft */
252
253#endif /* __BSD_VISIBLE */
254
255__END_DECLS
256
257#endif	/* !_FENV_H_ */