xref: /netbsd-src/sys/arch/mips/include/fenv.h (revision cddc78ea67e20759c213d3f50ea3bd06ade17338)
1*cddc78eaSriastradh /*	$NetBSD: fenv.h,v 1.7 2024/10/30 15:56:11 riastradh Exp $	*/
2257ef94eSchristos 
3257ef94eSchristos /*-
4257ef94eSchristos  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5257ef94eSchristos  * All rights reserved.
6257ef94eSchristos  *
7257ef94eSchristos  * Redistribution and use in source and binary forms, with or without
8257ef94eSchristos  * modification, are permitted provided that the following conditions
9257ef94eSchristos  * are met:
10257ef94eSchristos  * 1. Redistributions of source code must retain the above copyright
11257ef94eSchristos  *    notice, this list of conditions and the following disclaimer.
12257ef94eSchristos  * 2. Redistributions in binary form must reproduce the above copyright
13257ef94eSchristos  *    notice, this list of conditions and the following disclaimer in the
14257ef94eSchristos  *    documentation and/or other materials provided with the distribution.
15257ef94eSchristos  *
16257ef94eSchristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17257ef94eSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18257ef94eSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19257ef94eSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20257ef94eSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21257ef94eSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22257ef94eSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23257ef94eSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24257ef94eSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25257ef94eSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26257ef94eSchristos  * SUCH DAMAGE.
27257ef94eSchristos  *
28257ef94eSchristos  * $FreeBSD: head/lib/msun/mips/fenv.h 226218 2011-10-10 15:43:09Z das $
29257ef94eSchristos  */
30257ef94eSchristos 
31257ef94eSchristos #ifndef	_MIPS_FENV_H_
32257ef94eSchristos #define	_MIPS_FENV_H_
33257ef94eSchristos 
34*cddc78eaSriastradh #include <sys/featuretest.h>
35257ef94eSchristos #include <sys/stdint.h>
36257ef94eSchristos 
37257ef94eSchristos /* Exception flags */
380905c615Schristos #define	FE_INEXACT	0x0004
39257ef94eSchristos #define	FE_UNDERFLOW	0x0008
400905c615Schristos #define	FE_OVERFLOW	0x0010
410905c615Schristos #define	FE_DIVBYZERO	0x0020
420905c615Schristos #define	FE_INVALID	0x0040
43257ef94eSchristos #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
44257ef94eSchristos 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
45257ef94eSchristos 
46257ef94eSchristos /* Rounding modes */
47257ef94eSchristos #define	FE_TONEAREST	0x0000
48257ef94eSchristos #define	FE_TOWARDZERO	0x0001
49257ef94eSchristos #define	FE_UPWARD	0x0002
50257ef94eSchristos #define	FE_DOWNWARD	0x0003
51257ef94eSchristos #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
52257ef94eSchristos 			 FE_UPWARD | FE_TOWARDZERO)
537e30e943Schs 
547e30e943Schs #ifndef __mips_soft_float
557e30e943Schs 
567e30e943Schs #ifndef	__fenv_static
577e30e943Schs #define	__fenv_static	static
587e30e943Schs #endif
597e30e943Schs 
607e30e943Schs typedef	uint32_t 	fpu_control_t __attribute__((__mode__(__SI__)));
617e30e943Schs typedef	fpu_control_t	fenv_t;
627e30e943Schs typedef	fpu_control_t	fexcept_t;
637e30e943Schs 
64257ef94eSchristos __BEGIN_DECLS
65257ef94eSchristos 
66257ef94eSchristos /* Default floating-point environment */
67257ef94eSchristos extern const fenv_t	__fe_dfl_env;
68257ef94eSchristos #define	FE_DFL_ENV	(&__fe_dfl_env)
69257ef94eSchristos 
70257ef94eSchristos /* We need to be able to map status flag positions to mask flag positions */
710905c615Schristos #define	_ENABLE_MASK	(FE_ALL_EXCEPT << _ENABLE_SHIFT)
720905c615Schristos #define	_ENABLE_SHIFT    5
73257ef94eSchristos 
74ec9b26b9Schs static inline fpu_control_t
75ec9b26b9Schs __rfs(void)
76ec9b26b9Schs {
77ec9b26b9Schs 	fpu_control_t __fpsr;
780905c615Schristos 
79ec9b26b9Schs 	__asm __volatile("cfc1 %0,$31" : "=r" (__fpsr));
80ec9b26b9Schs 	return __fpsr;
81ec9b26b9Schs }
82ec9b26b9Schs 
83ec9b26b9Schs static inline void
84ec9b26b9Schs __wfs(fpu_control_t __fpsr)
85ec9b26b9Schs {
86ec9b26b9Schs 
87ec9b26b9Schs 	__asm __volatile("ctc1 %0,$31" : : "r" (__fpsr));
88ec9b26b9Schs }
89257ef94eSchristos 
90afd5a45cSchristos #if __GNUC_PREREQ__(8, 0)
91afd5a45cSchristos #pragma GCC diagnostic push
92afd5a45cSchristos #pragma GCC diagnostic ignored "-Wshadow"
93afd5a45cSchristos #endif
94afd5a45cSchristos 
95257ef94eSchristos __fenv_static inline int
96257ef94eSchristos feclearexcept(int __excepts)
97257ef94eSchristos {
98257ef94eSchristos 	fexcept_t __fpsr;
99257ef94eSchristos 
1000905c615Schristos 	__excepts &= FE_ALL_EXCEPT;
101ec9b26b9Schs 	__fpsr = __rfs();
1020905c615Schristos 	__fpsr &= ~(__excepts | (__excepts << _ENABLE_SHIFT));
103257ef94eSchristos 	__wfs(__fpsr);
1040905c615Schristos 	return 0;
105257ef94eSchristos }
106257ef94eSchristos 
107257ef94eSchristos __fenv_static inline int
108257ef94eSchristos fegetexceptflag(fexcept_t *__flagp, int __excepts)
109257ef94eSchristos {
110257ef94eSchristos 	fexcept_t __fpsr;
111257ef94eSchristos 
112ec9b26b9Schs 	__fpsr = __rfs();
113257ef94eSchristos 	*__flagp = __fpsr & __excepts;
114257ef94eSchristos 	return (0);
115257ef94eSchristos }
116257ef94eSchristos 
117257ef94eSchristos __fenv_static inline int
118257ef94eSchristos fesetexceptflag(const fexcept_t *__flagp, int __excepts)
119257ef94eSchristos {
120257ef94eSchristos 	fexcept_t __fpsr;
121257ef94eSchristos 
122ec9b26b9Schs 	__fpsr = __rfs();
123257ef94eSchristos 	__fpsr &= ~__excepts;
124257ef94eSchristos 	__fpsr |= *__flagp & __excepts;
125257ef94eSchristos 	__wfs(__fpsr);
126257ef94eSchristos 	return (0);
127257ef94eSchristos }
128257ef94eSchristos 
129257ef94eSchristos __fenv_static inline int
130257ef94eSchristos feraiseexcept(int __excepts)
131257ef94eSchristos {
132257ef94eSchristos 	fexcept_t __ex = __excepts;
133257ef94eSchristos 
134257ef94eSchristos 	fesetexceptflag(&__ex, __excepts);	/* XXX */
135257ef94eSchristos 	return (0);
136257ef94eSchristos }
137257ef94eSchristos 
138257ef94eSchristos __fenv_static inline int
139257ef94eSchristos fetestexcept(int __excepts)
140257ef94eSchristos {
141257ef94eSchristos 	fexcept_t __fpsr;
142257ef94eSchristos 
143ec9b26b9Schs 	__fpsr = __rfs();
144257ef94eSchristos 	return (__fpsr & __excepts);
145257ef94eSchristos }
146257ef94eSchristos 
147257ef94eSchristos __fenv_static inline int
148257ef94eSchristos fegetround(void)
149257ef94eSchristos {
1500905c615Schristos 	fexcept_t __fpsr;
151257ef94eSchristos 
152ec9b26b9Schs 	__fpsr = __rfs();
1530905c615Schristos 	return __fpsr & _ROUND_MASK;
154257ef94eSchristos }
155257ef94eSchristos 
156257ef94eSchristos __fenv_static inline int
157257ef94eSchristos fesetround(int __round)
158257ef94eSchristos {
1590905c615Schristos 	fexcept_t __fpsr;
160257ef94eSchristos 
1610905c615Schristos 	if (__round & ~_ROUND_MASK)
1620905c615Schristos 		return 1;
163ec9b26b9Schs 	__fpsr = __rfs();
1640905c615Schristos 	__fpsr &= ~_ROUND_MASK;
1650905c615Schristos 	__fpsr |= __round;
166ec9b26b9Schs 	__wfs(__fpsr);
1670905c615Schristos 
1680905c615Schristos 	return 0;
169257ef94eSchristos }
170257ef94eSchristos 
171257ef94eSchristos __fenv_static inline int
172257ef94eSchristos fegetenv(fenv_t *__envp)
173257ef94eSchristos {
174257ef94eSchristos 
175ec9b26b9Schs 	*__envp = __rfs();
176257ef94eSchristos 	return (0);
177257ef94eSchristos }
178257ef94eSchristos 
179257ef94eSchristos __fenv_static inline int
180257ef94eSchristos feholdexcept(fenv_t *__envp)
181257ef94eSchristos {
182257ef94eSchristos 	fenv_t __env;
183257ef94eSchristos 
184ec9b26b9Schs 	__env = __rfs();
185257ef94eSchristos 	*__envp = __env;
186257ef94eSchristos 	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
187257ef94eSchristos 	__wfs(__env);
188257ef94eSchristos 	return (0);
189257ef94eSchristos }
190257ef94eSchristos 
191257ef94eSchristos __fenv_static inline int
192257ef94eSchristos fesetenv(const fenv_t *__envp)
193257ef94eSchristos {
194257ef94eSchristos 
195257ef94eSchristos 	__wfs(*__envp);
196257ef94eSchristos 	return (0);
197257ef94eSchristos }
198257ef94eSchristos 
199257ef94eSchristos __fenv_static inline int
200257ef94eSchristos feupdateenv(const fenv_t *__envp)
201257ef94eSchristos {
202257ef94eSchristos 	fexcept_t __fpsr;
203257ef94eSchristos 
204ec9b26b9Schs 	__fpsr = __rfs();
205257ef94eSchristos 	__wfs(*__envp);
206257ef94eSchristos 	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
207257ef94eSchristos 	return (0);
208257ef94eSchristos }
209257ef94eSchristos 
210afd5a45cSchristos #if __GNUC_PREREQ__(8, 0)
211afd5a45cSchristos #pragma GCC diagnostic pop
212afd5a45cSchristos #endif
213afd5a45cSchristos 
214257ef94eSchristos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
215257ef94eSchristos 
2167e30e943Schs __fenv_static inline int
2170905c615Schristos feenableexcept(int __excepts)
218257ef94eSchristos {
219257ef94eSchristos 	fenv_t __old_fpsr, __new_fpsr;
220257ef94eSchristos 
221ec9b26b9Schs 	__new_fpsr = __rfs();
2220905c615Schristos 	__old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
2230905c615Schristos 	__excepts &= FE_ALL_EXCEPT;
2240905c615Schristos 	__new_fpsr |= __excepts << _ENABLE_SHIFT;
225257ef94eSchristos 	__wfs(__new_fpsr);
2260905c615Schristos 	return __old_fpsr;
227257ef94eSchristos }
228257ef94eSchristos 
2297e30e943Schs __fenv_static inline int
2300905c615Schristos fedisableexcept(int __excepts)
231257ef94eSchristos {
232257ef94eSchristos 	fenv_t __old_fpsr, __new_fpsr;
233257ef94eSchristos 
234ec9b26b9Schs 	__new_fpsr = __rfs();
2350905c615Schristos 	__old_fpsr = (__new_fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT;
2360905c615Schristos 	__excepts &= FE_ALL_EXCEPT;
2370905c615Schristos 	__new_fpsr &= ~(__excepts << _ENABLE_SHIFT);
238257ef94eSchristos 	__wfs(__new_fpsr);
2390905c615Schristos 	return __old_fpsr;
240257ef94eSchristos }
241257ef94eSchristos 
2427e30e943Schs __fenv_static inline int
243257ef94eSchristos fegetexcept(void)
244257ef94eSchristos {
245257ef94eSchristos 	fenv_t __fpsr;
246257ef94eSchristos 
247ec9b26b9Schs 	__fpsr = __rfs();
2480905c615Schristos 	return ((__fpsr & _ENABLE_MASK) >> _ENABLE_SHIFT);
249257ef94eSchristos }
250257ef94eSchristos 
251257ef94eSchristos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
252257ef94eSchristos 
253257ef94eSchristos __END_DECLS
254257ef94eSchristos 
2557e30e943Schs #endif /* __mips_soft_float */
2567e30e943Schs 
257257ef94eSchristos #endif	/* !_FENV_H_ */
258