xref: /freebsd/lib/msun/riscv/fenv.h (revision 1947a9383ec3a048e334022365aa199a6ae55289)
11fdcc5e5SRuslan Bukin /*-
21fdcc5e5SRuslan Bukin  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
37804dd52SRuslan Bukin  * Copyright (c) 2015-2016 Ruslan Bukin <br@bsdpad.com>
41fdcc5e5SRuslan Bukin  * All rights reserved.
51fdcc5e5SRuslan Bukin  *
61fdcc5e5SRuslan Bukin  * Portions of this software were developed by SRI International and the
71fdcc5e5SRuslan Bukin  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
81fdcc5e5SRuslan Bukin  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
91fdcc5e5SRuslan Bukin  *
101fdcc5e5SRuslan Bukin  * Portions of this software were developed by the University of Cambridge
111fdcc5e5SRuslan Bukin  * Computer Laboratory as part of the CTSRD Project, with support from the
121fdcc5e5SRuslan Bukin  * UK Higher Education Innovation Fund (HEIF).
131fdcc5e5SRuslan Bukin  *
141fdcc5e5SRuslan Bukin  * Redistribution and use in source and binary forms, with or without
151fdcc5e5SRuslan Bukin  * modification, are permitted provided that the following conditions
161fdcc5e5SRuslan Bukin  * are met:
171fdcc5e5SRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
181fdcc5e5SRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
191fdcc5e5SRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
201fdcc5e5SRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
211fdcc5e5SRuslan Bukin  *    documentation and/or other materials provided with the distribution.
221fdcc5e5SRuslan Bukin  *
231fdcc5e5SRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
241fdcc5e5SRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251fdcc5e5SRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261fdcc5e5SRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
271fdcc5e5SRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281fdcc5e5SRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291fdcc5e5SRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
301fdcc5e5SRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311fdcc5e5SRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321fdcc5e5SRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331fdcc5e5SRuslan Bukin  * SUCH DAMAGE.
341fdcc5e5SRuslan Bukin  */
351fdcc5e5SRuslan Bukin 
361fdcc5e5SRuslan Bukin #ifndef	_FENV_H_
371fdcc5e5SRuslan Bukin #define	_FENV_H_
381fdcc5e5SRuslan Bukin 
391fdcc5e5SRuslan Bukin #include <sys/_types.h>
401fdcc5e5SRuslan Bukin 
411fdcc5e5SRuslan Bukin #ifndef	__fenv_static
421fdcc5e5SRuslan Bukin #define	__fenv_static	static
431fdcc5e5SRuslan Bukin #endif
441fdcc5e5SRuslan Bukin 
451fdcc5e5SRuslan Bukin typedef	__uint64_t	fenv_t;
461fdcc5e5SRuslan Bukin typedef	__uint64_t	fexcept_t;
471fdcc5e5SRuslan Bukin 
481fdcc5e5SRuslan Bukin /* Exception flags */
491fdcc5e5SRuslan Bukin #define	FE_INVALID	0x0010
501fdcc5e5SRuslan Bukin #define	FE_DIVBYZERO	0x0008
511fdcc5e5SRuslan Bukin #define	FE_OVERFLOW	0x0004
521fdcc5e5SRuslan Bukin #define	FE_UNDERFLOW	0x0002
531fdcc5e5SRuslan Bukin #define	FE_INEXACT	0x0001
541fdcc5e5SRuslan Bukin #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
551fdcc5e5SRuslan Bukin 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
561fdcc5e5SRuslan Bukin 
571fdcc5e5SRuslan Bukin /*
581fdcc5e5SRuslan Bukin  * RISC-V Rounding modes
591fdcc5e5SRuslan Bukin  */
601fdcc5e5SRuslan Bukin #define	_ROUND_SHIFT	5
617804dd52SRuslan Bukin #define	FE_TONEAREST	(0x00 << _ROUND_SHIFT)
627804dd52SRuslan Bukin #define	FE_TOWARDZERO	(0x01 << _ROUND_SHIFT)
637804dd52SRuslan Bukin #define	FE_DOWNWARD	(0x02 << _ROUND_SHIFT)
647804dd52SRuslan Bukin #define	FE_UPWARD	(0x03 << _ROUND_SHIFT)
651fdcc5e5SRuslan Bukin #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
661fdcc5e5SRuslan Bukin 			 FE_UPWARD | FE_TOWARDZERO)
671fdcc5e5SRuslan Bukin 
681fdcc5e5SRuslan Bukin __BEGIN_DECLS
691fdcc5e5SRuslan Bukin 
701fdcc5e5SRuslan Bukin /* Default floating-point environment */
711fdcc5e5SRuslan Bukin extern const fenv_t	__fe_dfl_env;
721fdcc5e5SRuslan Bukin #define	FE_DFL_ENV	(&__fe_dfl_env)
731fdcc5e5SRuslan Bukin 
743b05ffafSBrooks Davis #if !defined(__riscv_float_abi_soft) && !defined(__riscv_float_abi_double)
753b05ffafSBrooks Davis #if defined(__riscv_float_abi_single)
763b05ffafSBrooks Davis #error single precision floating point ABI not supported
773b05ffafSBrooks Davis #else
783b05ffafSBrooks Davis #error compiler did not set soft/hard float macros
793b05ffafSBrooks Davis #endif
803b05ffafSBrooks Davis #endif
813b05ffafSBrooks Davis 
823b05ffafSBrooks Davis #ifndef __riscv_float_abi_soft
837804dd52SRuslan Bukin #define	__rfs(__fcsr)	__asm __volatile("csrr %0, fcsr" : "=r" (__fcsr))
847804dd52SRuslan Bukin #define	__wfs(__fcsr)	__asm __volatile("csrw fcsr, %0" :: "r" (__fcsr))
857804dd52SRuslan Bukin #endif
861fdcc5e5SRuslan Bukin 
873b05ffafSBrooks Davis #ifdef __riscv_float_abi_soft
887804dd52SRuslan Bukin int feclearexcept(int __excepts);
897804dd52SRuslan Bukin int fegetexceptflag(fexcept_t *__flagp, int __excepts);
907804dd52SRuslan Bukin int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
917804dd52SRuslan Bukin int feraiseexcept(int __excepts);
927804dd52SRuslan Bukin int fetestexcept(int __excepts);
937804dd52SRuslan Bukin int fegetround(void);
947804dd52SRuslan Bukin int fesetround(int __round);
957804dd52SRuslan Bukin int fegetenv(fenv_t *__envp);
967804dd52SRuslan Bukin int feholdexcept(fenv_t *__envp);
977804dd52SRuslan Bukin int fesetenv(const fenv_t *__envp);
987804dd52SRuslan Bukin int feupdateenv(const fenv_t *__envp);
997804dd52SRuslan Bukin #else
1001fdcc5e5SRuslan Bukin __fenv_static inline int
1011fdcc5e5SRuslan Bukin feclearexcept(int __excepts)
1021fdcc5e5SRuslan Bukin {
1031fdcc5e5SRuslan Bukin 
1047804dd52SRuslan Bukin 	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
1057804dd52SRuslan Bukin 
1061fdcc5e5SRuslan Bukin 	return (0);
1071fdcc5e5SRuslan Bukin }
1081fdcc5e5SRuslan Bukin 
1091fdcc5e5SRuslan Bukin __fenv_static inline int
1101fdcc5e5SRuslan Bukin fegetexceptflag(fexcept_t *__flagp, int __excepts)
1111fdcc5e5SRuslan Bukin {
1127804dd52SRuslan Bukin 	fexcept_t __fcsr;
1131fdcc5e5SRuslan Bukin 
1147804dd52SRuslan Bukin 	__rfs(__fcsr);
1157804dd52SRuslan Bukin 	*__flagp = __fcsr & __excepts;
1167804dd52SRuslan Bukin 
1171fdcc5e5SRuslan Bukin 	return (0);
1181fdcc5e5SRuslan Bukin }
1191fdcc5e5SRuslan Bukin 
1201fdcc5e5SRuslan Bukin __fenv_static inline int
1211fdcc5e5SRuslan Bukin fesetexceptflag(const fexcept_t *__flagp, int __excepts)
1221fdcc5e5SRuslan Bukin {
1237804dd52SRuslan Bukin 	fexcept_t __fcsr;
1241fdcc5e5SRuslan Bukin 
1257804dd52SRuslan Bukin 	__fcsr = *__flagp;
1267804dd52SRuslan Bukin 	__asm __volatile("csrc fflags, %0" :: "r"(__excepts));
1277804dd52SRuslan Bukin 	__asm __volatile("csrs fflags, %0" :: "r"(__fcsr & __excepts));
1287804dd52SRuslan Bukin 
1291fdcc5e5SRuslan Bukin 	return (0);
1301fdcc5e5SRuslan Bukin }
1311fdcc5e5SRuslan Bukin 
1321fdcc5e5SRuslan Bukin __fenv_static inline int
1331fdcc5e5SRuslan Bukin feraiseexcept(int __excepts)
1341fdcc5e5SRuslan Bukin {
1351fdcc5e5SRuslan Bukin 
1367804dd52SRuslan Bukin 	__asm __volatile("csrs fflags, %0" :: "r"(__excepts));
1377804dd52SRuslan Bukin 
1381fdcc5e5SRuslan Bukin 	return (0);
1391fdcc5e5SRuslan Bukin }
1401fdcc5e5SRuslan Bukin 
1411fdcc5e5SRuslan Bukin __fenv_static inline int
1421fdcc5e5SRuslan Bukin fetestexcept(int __excepts)
1431fdcc5e5SRuslan Bukin {
1447804dd52SRuslan Bukin 	fexcept_t __fcsr;
1451fdcc5e5SRuslan Bukin 
1467804dd52SRuslan Bukin 	__rfs(__fcsr);
1477804dd52SRuslan Bukin 
1487804dd52SRuslan Bukin 	return (__fcsr & __excepts);
1491fdcc5e5SRuslan Bukin }
1501fdcc5e5SRuslan Bukin 
1511fdcc5e5SRuslan Bukin __fenv_static inline int
1521fdcc5e5SRuslan Bukin fegetround(void)
1531fdcc5e5SRuslan Bukin {
1547804dd52SRuslan Bukin 	fexcept_t __fcsr;
1551fdcc5e5SRuslan Bukin 
1567804dd52SRuslan Bukin 	__rfs(__fcsr);
1577804dd52SRuslan Bukin 
1587804dd52SRuslan Bukin 	return (__fcsr & _ROUND_MASK);
1591fdcc5e5SRuslan Bukin }
1601fdcc5e5SRuslan Bukin 
1611fdcc5e5SRuslan Bukin __fenv_static inline int
1621fdcc5e5SRuslan Bukin fesetround(int __round)
1631fdcc5e5SRuslan Bukin {
1647804dd52SRuslan Bukin 	fexcept_t __fcsr;
1651fdcc5e5SRuslan Bukin 
1667804dd52SRuslan Bukin 	if (__round & ~_ROUND_MASK)
1671fdcc5e5SRuslan Bukin 		return (-1);
1687804dd52SRuslan Bukin 
1697804dd52SRuslan Bukin 	__rfs(__fcsr);
1707804dd52SRuslan Bukin 	__fcsr &= ~_ROUND_MASK;
1717804dd52SRuslan Bukin 	__fcsr |= __round;
1727804dd52SRuslan Bukin 	__wfs(__fcsr);
1737804dd52SRuslan Bukin 
1747804dd52SRuslan Bukin 	return (0);
1751fdcc5e5SRuslan Bukin }
1761fdcc5e5SRuslan Bukin 
1771fdcc5e5SRuslan Bukin __fenv_static inline int
1781fdcc5e5SRuslan Bukin fegetenv(fenv_t *__envp)
1791fdcc5e5SRuslan Bukin {
1801fdcc5e5SRuslan Bukin 
1817804dd52SRuslan Bukin 	__rfs(*__envp);
1827804dd52SRuslan Bukin 
1831fdcc5e5SRuslan Bukin 	return (0);
1841fdcc5e5SRuslan Bukin }
1851fdcc5e5SRuslan Bukin 
1861fdcc5e5SRuslan Bukin __fenv_static inline int
18715211f19SAlex Richardson feholdexcept(fenv_t *__envp __unused)
1881fdcc5e5SRuslan Bukin {
1891fdcc5e5SRuslan Bukin 
1907804dd52SRuslan Bukin 	/* No exception traps. */
1917804dd52SRuslan Bukin 
1927804dd52SRuslan Bukin 	return (-1);
1931fdcc5e5SRuslan Bukin }
1941fdcc5e5SRuslan Bukin 
1951fdcc5e5SRuslan Bukin __fenv_static inline int
1961fdcc5e5SRuslan Bukin fesetenv(const fenv_t *__envp)
1971fdcc5e5SRuslan Bukin {
1981fdcc5e5SRuslan Bukin 
1991fdcc5e5SRuslan Bukin 	__wfs(*__envp);
2007804dd52SRuslan Bukin 
2011fdcc5e5SRuslan Bukin 	return (0);
2021fdcc5e5SRuslan Bukin }
2031fdcc5e5SRuslan Bukin 
2041fdcc5e5SRuslan Bukin __fenv_static inline int
2051fdcc5e5SRuslan Bukin feupdateenv(const fenv_t *__envp)
2061fdcc5e5SRuslan Bukin {
2077804dd52SRuslan Bukin 	fexcept_t __fcsr;
2081fdcc5e5SRuslan Bukin 
2097804dd52SRuslan Bukin 	__rfs(__fcsr);
2101fdcc5e5SRuslan Bukin 	__wfs(*__envp);
2117804dd52SRuslan Bukin 	feraiseexcept(__fcsr & FE_ALL_EXCEPT);
2127804dd52SRuslan Bukin 
2131fdcc5e5SRuslan Bukin 	return (0);
2141fdcc5e5SRuslan Bukin }
2153b05ffafSBrooks Davis #endif /* !__riscv_float_abi_soft */
2161fdcc5e5SRuslan Bukin 
2171fdcc5e5SRuslan Bukin #if __BSD_VISIBLE
2181fdcc5e5SRuslan Bukin 
2193b05ffafSBrooks Davis #ifdef __riscv_float_abi_soft
2207804dd52SRuslan Bukin int feenableexcept(int __mask);
2217804dd52SRuslan Bukin int fedisableexcept(int __mask);
2227804dd52SRuslan Bukin int fegetexcept(void);
2237804dd52SRuslan Bukin #else
224*1947a938SBrooks Davis __fenv_static inline int
22515211f19SAlex Richardson feenableexcept(int __mask __unused)
2261fdcc5e5SRuslan Bukin {
2271fdcc5e5SRuslan Bukin 
2287804dd52SRuslan Bukin 	/* No exception traps. */
2297804dd52SRuslan Bukin 
230dd5ed53aSAlex Richardson 	return (0);
2311fdcc5e5SRuslan Bukin }
2321fdcc5e5SRuslan Bukin 
233*1947a938SBrooks Davis __fenv_static inline int
23415211f19SAlex Richardson fedisableexcept(int __mask __unused)
2351fdcc5e5SRuslan Bukin {
2361fdcc5e5SRuslan Bukin 
2377804dd52SRuslan Bukin 	/* No exception traps. */
2387804dd52SRuslan Bukin 
2397804dd52SRuslan Bukin 	return (0);
2401fdcc5e5SRuslan Bukin }
2411fdcc5e5SRuslan Bukin 
242*1947a938SBrooks Davis /* We currently provide no external definition of fegetexcept(). */
2431fdcc5e5SRuslan Bukin static inline int
2441fdcc5e5SRuslan Bukin fegetexcept(void)
2451fdcc5e5SRuslan Bukin {
2461fdcc5e5SRuslan Bukin 
2477804dd52SRuslan Bukin 	/* No exception traps. */
2487804dd52SRuslan Bukin 
2497804dd52SRuslan Bukin 	return (0);
2501fdcc5e5SRuslan Bukin }
2513b05ffafSBrooks Davis #endif /* !__riscv_float_abi_soft */
2521fdcc5e5SRuslan Bukin 
2531fdcc5e5SRuslan Bukin #endif /* __BSD_VISIBLE */
2541fdcc5e5SRuslan Bukin 
2551fdcc5e5SRuslan Bukin __END_DECLS
2561fdcc5e5SRuslan Bukin 
2571fdcc5e5SRuslan Bukin #endif	/* !_FENV_H_ */
258