xref: /netbsd-src/sys/arch/alpha/include/fenv.h (revision cddc78ea67e20759c213d3f50ea3bd06ade17338)
1*cddc78eaSriastradh /*	$NetBSD: fenv.h,v 1.4 2024/10/30 15:56:10 riastradh Exp $	*/
2253d8526Schristos 
3253d8526Schristos /*-
4253d8526Schristos  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5253d8526Schristos  * All rights reserved.
6253d8526Schristos  *
7253d8526Schristos  * Redistribution and use in source and binary forms, with or without
8253d8526Schristos  * modification, are permitted provided that the following conditions
9253d8526Schristos  * are met:
10253d8526Schristos  * 1. Redistributions of source code must retain the above copyright
11253d8526Schristos  *    notice, this list of conditions and the following disclaimer.
12253d8526Schristos  * 2. Redistributions in binary form must reproduce the above copyright
13253d8526Schristos  *    notice, this list of conditions and the following disclaimer in the
14253d8526Schristos  *    documentation and/or other materials provided with the distribution.
15253d8526Schristos  *
16253d8526Schristos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17253d8526Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18253d8526Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19253d8526Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20253d8526Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21253d8526Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22253d8526Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23253d8526Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24253d8526Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25253d8526Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26253d8526Schristos  * SUCH DAMAGE.
27253d8526Schristos  *
28253d8526Schristos  * $FreeBSD: src/lib/msun/alpha/fenv.h,v 1.3 2005/03/16 19:03:44 das Exp $
29253d8526Schristos  */
30253d8526Schristos 
31253d8526Schristos #ifndef	_ALPHA_FENV_H_
32253d8526Schristos #define	_ALPHA_FENV_H_
33253d8526Schristos 
34*cddc78eaSriastradh #include <sys/featuretest.h>
35253d8526Schristos #include <sys/stdint.h>
36253d8526Schristos 
37253d8526Schristos typedef	__uint64_t	fenv_t;
38253d8526Schristos typedef	__uint16_t	fexcept_t;
39253d8526Schristos 
40253d8526Schristos /* Exception flags */
41a8793139Schristos #define	FE_INVALID	0x01
42a8793139Schristos #define	FE_DIVBYZERO	0x02
43a8793139Schristos #define	FE_OVERFLOW	0x04
44a8793139Schristos #define	FE_UNDERFLOW	0x08
45a8793139Schristos #define	FE_INEXACT	0x10
46a8793139Schristos #define	FE_INTOVF	0x20	/* not maskable */
47253d8526Schristos #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \
48253d8526Schristos 			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
49253d8526Schristos 
50253d8526Schristos /* Rounding modes */
51253d8526Schristos #define	FE_TOWARDZERO	0x00
52253d8526Schristos #define	FE_DOWNWARD	0x01
53253d8526Schristos #define	FE_TONEAREST	0x02
54253d8526Schristos #define	FE_UPWARD	0x03
55253d8526Schristos #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
56253d8526Schristos 			 FE_UPWARD | FE_TOWARDZERO)
57253d8526Schristos #define	_ROUND_SHIFT	58
58253d8526Schristos 
59a8793139Schristos #define	_FPUSW_SHIFT	52
60253d8526Schristos 
61253d8526Schristos #define	__excb()	__asm __volatile("excb")
62253d8526Schristos #define	__mf_fpcr(__cw)	__asm __volatile("mf_fpcr %0" : "=f" (*(__cw)))
63253d8526Schristos #define	__mt_fpcr(__cw)	__asm __volatile("mt_fpcr %0" : : "f" (__cw))
64253d8526Schristos 
65253d8526Schristos union __fpcr {
66253d8526Schristos 	double __d;
67253d8526Schristos 	fenv_t __bits;
68253d8526Schristos };
69253d8526Schristos 
70253d8526Schristos __BEGIN_DECLS
71253d8526Schristos 
72253d8526Schristos /* Default floating-point environment */
73253d8526Schristos extern const fenv_t	__fe_dfl_env;
74253d8526Schristos #define	FE_DFL_ENV	(&__fe_dfl_env)
75253d8526Schristos 
76b97fcb9bSchristos #if __GNUC_PREREQ__(8, 0)
77b97fcb9bSchristos #pragma GCC diagnostic push
78b97fcb9bSchristos #pragma GCC diagnostic ignored "-Wshadow"
79b97fcb9bSchristos #endif
80b97fcb9bSchristos 
81253d8526Schristos static __inline int
82253d8526Schristos feclearexcept(int __excepts)
83253d8526Schristos {
84253d8526Schristos 	union __fpcr __r;
85253d8526Schristos 
86253d8526Schristos 	__excb();
87253d8526Schristos 	__mf_fpcr(&__r.__d);
88253d8526Schristos 	__r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT);
89253d8526Schristos 	__mt_fpcr(__r.__d);
90253d8526Schristos 	__excb();
91253d8526Schristos 	return 0;
92253d8526Schristos }
93253d8526Schristos 
94253d8526Schristos static __inline int
95253d8526Schristos fegetexceptflag(fexcept_t *__flagp, int __excepts)
96253d8526Schristos {
97253d8526Schristos 	union __fpcr __r;
98253d8526Schristos 
99253d8526Schristos 	__excb();
100253d8526Schristos 	__mf_fpcr(&__r.__d);
101253d8526Schristos 	__excb();
102253d8526Schristos 	*__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts;
103253d8526Schristos 	return 0;
104253d8526Schristos }
105253d8526Schristos 
106253d8526Schristos static __inline int
107253d8526Schristos fesetexceptflag(const fexcept_t *__flagp, int __excepts)
108253d8526Schristos {
109253d8526Schristos 	union __fpcr __r;
110253d8526Schristos 	fenv_t __xflag, __xexcepts;
111253d8526Schristos 
112253d8526Schristos 	__xflag = (fenv_t)*__flagp << _FPUSW_SHIFT;
113253d8526Schristos 	__xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT;
114253d8526Schristos 	__excb();
115253d8526Schristos 	__mf_fpcr(&__r.__d);
116253d8526Schristos 	__r.__bits &= ~__xexcepts;
117253d8526Schristos 	__r.__bits |= __xflag & __xexcepts;
118253d8526Schristos 	__mt_fpcr(__r.__d);
119253d8526Schristos 	__excb();
120253d8526Schristos 	return 0;
121253d8526Schristos }
122253d8526Schristos 
123253d8526Schristos static __inline int
124253d8526Schristos feraiseexcept(int __excepts)
125253d8526Schristos {
126253d8526Schristos 
127253d8526Schristos 	/*
128253d8526Schristos 	 * XXX Generating exceptions this way does not actually invoke
129253d8526Schristos 	 * a userland trap handler when enabled, but neither do
130253d8526Schristos 	 * arithmetic operations as far as I can tell.  Perhaps there
131253d8526Schristos 	 * are more bugs in the kernel trap handler.
132253d8526Schristos 	 */
133253d8526Schristos 	fexcept_t __ex = __excepts;
134253d8526Schristos 	fesetexceptflag(&__ex, __excepts);
135253d8526Schristos 	return 0;
136253d8526Schristos }
137253d8526Schristos 
138253d8526Schristos static __inline int
139253d8526Schristos fetestexcept(int __excepts)
140253d8526Schristos {
141253d8526Schristos 	union __fpcr __r;
142253d8526Schristos 
143253d8526Schristos 	__excb();
144253d8526Schristos 	__mf_fpcr(&__r.__d);
145253d8526Schristos 	__excb();
146253d8526Schristos 	return (__r.__bits >> _FPUSW_SHIFT) & __excepts;
147253d8526Schristos }
148253d8526Schristos 
149253d8526Schristos static __inline int
150253d8526Schristos fegetround(void)
151253d8526Schristos {
152253d8526Schristos 	union __fpcr __r;
153253d8526Schristos 
154253d8526Schristos 	/*
155253d8526Schristos 	 * No exception barriers should be required here if we assume
156253d8526Schristos 	 * that only fesetround() can change the rounding mode.
157253d8526Schristos 	 */
158253d8526Schristos 	__mf_fpcr(&__r.__d);
159253d8526Schristos 	return (int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK;
160253d8526Schristos }
161253d8526Schristos 
162253d8526Schristos static __inline int
163253d8526Schristos fesetround(int __round)
164253d8526Schristos {
165253d8526Schristos 	union __fpcr __r;
166253d8526Schristos 
167253d8526Schristos 	if (__round & ~_ROUND_MASK)
168253d8526Schristos 		return (-1);
169253d8526Schristos 	__excb();
170253d8526Schristos 	__mf_fpcr(&__r.__d);
171253d8526Schristos 	__r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT);
172253d8526Schristos 	__r.__bits |= (fenv_t)__round << _ROUND_SHIFT;
173253d8526Schristos 	__mt_fpcr(__r.__d);
174253d8526Schristos 	__excb();
175253d8526Schristos 	return 0;
176253d8526Schristos }
177253d8526Schristos 
178b97fcb9bSchristos #if __GNUC_PREREQ__(8, 0)
179b97fcb9bSchristos #pragma GCC diagnostic pop
180b97fcb9bSchristos #endif
181b97fcb9bSchristos 
182253d8526Schristos int	fegetenv(fenv_t *);
183253d8526Schristos int	feholdexcept(fenv_t *);
184253d8526Schristos int	fesetenv(const fenv_t *);
185253d8526Schristos int	feupdateenv(const fenv_t *);
186253d8526Schristos 
187253d8526Schristos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
188253d8526Schristos int	feenableexcept(int);
189253d8526Schristos int	fedisableexcept(int);
190253d8526Schristos int	fegetexcept(void);
191253d8526Schristos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
192253d8526Schristos 
193253d8526Schristos 
194253d8526Schristos __END_DECLS
195253d8526Schristos 
196253d8526Schristos #endif	/* !_ALPHA_FENV_H_ */
197