xref: /freebsd-src/lib/msun/powerpc/fenv.h (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
1122e1380SDavid Schultz /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
35e53a4f9SPedro F. Giffuni  *
410b01832SDavid Schultz  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5122e1380SDavid Schultz  * All rights reserved.
6122e1380SDavid Schultz  *
7122e1380SDavid Schultz  * Redistribution and use in source and binary forms, with or without
8122e1380SDavid Schultz  * modification, are permitted provided that the following conditions
9122e1380SDavid Schultz  * are met:
10122e1380SDavid Schultz  * 1. Redistributions of source code must retain the above copyright
11122e1380SDavid Schultz  *    notice, this list of conditions and the following disclaimer.
12122e1380SDavid Schultz  * 2. Redistributions in binary form must reproduce the above copyright
13122e1380SDavid Schultz  *    notice, this list of conditions and the following disclaimer in the
14122e1380SDavid Schultz  *    documentation and/or other materials provided with the distribution.
15122e1380SDavid Schultz  *
16122e1380SDavid Schultz  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17122e1380SDavid Schultz  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18122e1380SDavid Schultz  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19122e1380SDavid Schultz  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20122e1380SDavid Schultz  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21122e1380SDavid Schultz  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22122e1380SDavid Schultz  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23122e1380SDavid Schultz  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24122e1380SDavid Schultz  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25122e1380SDavid Schultz  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26122e1380SDavid Schultz  * SUCH DAMAGE.
27122e1380SDavid Schultz  */
28122e1380SDavid Schultz 
29122e1380SDavid Schultz #ifndef	_FENV_H_
30122e1380SDavid Schultz #define	_FENV_H_
31122e1380SDavid Schultz 
32122e1380SDavid Schultz #include <sys/_types.h>
334f9ed315SBrandon Bergren #include <machine/endian.h>
34122e1380SDavid Schultz 
35d78e594bSDavid Schultz #ifndef	__fenv_static
36d78e594bSDavid Schultz #define	__fenv_static	static
37d78e594bSDavid Schultz #endif
38d78e594bSDavid Schultz 
39122e1380SDavid Schultz typedef	__uint32_t	fenv_t;
40122e1380SDavid Schultz typedef	__uint32_t	fexcept_t;
41122e1380SDavid Schultz 
42122e1380SDavid Schultz /* Exception flags */
4366405796SJustin Hibbits #ifdef __SPE__
4466405796SJustin Hibbits #define FE_OVERFLOW	0x00000100
4566405796SJustin Hibbits #define FE_UNDERFLOW	0x00000200
4666405796SJustin Hibbits #define FE_DIVBYZERO	0x00000400
4766405796SJustin Hibbits #define FE_INVALID	0x00000800
4866405796SJustin Hibbits #define FE_INEXACT	0x00001000
4966405796SJustin Hibbits 
5066405796SJustin Hibbits #define	FE_ALL_INVALID	FE_INVALID
5166405796SJustin Hibbits 
5266405796SJustin Hibbits #define	_FPUSW_SHIFT	6
5366405796SJustin Hibbits #else
54122e1380SDavid Schultz #define	FE_INEXACT	0x02000000
55122e1380SDavid Schultz #define	FE_DIVBYZERO	0x04000000
56122e1380SDavid Schultz #define	FE_UNDERFLOW	0x08000000
57122e1380SDavid Schultz #define	FE_OVERFLOW	0x10000000
58122e1380SDavid Schultz #define	FE_INVALID	0x20000000	/* all types of invalid FP ops */
59122e1380SDavid Schultz 
60122e1380SDavid Schultz /*
61122e1380SDavid Schultz  * The PowerPC architecture has extra invalid flags that indicate the
62122e1380SDavid Schultz  * specific type of invalid operation occurred.  These flags may be
63122e1380SDavid Schultz  * tested, set, and cleared---but not masked---separately.  All of
64122e1380SDavid Schultz  * these bits are cleared when FE_INVALID is cleared, but only
65122e1380SDavid Schultz  * FE_VXSOFT is set when FE_INVALID is explicitly set in software.
66122e1380SDavid Schultz  */
67122e1380SDavid Schultz #define	FE_VXCVI	0x00000100	/* invalid integer convert */
68122e1380SDavid Schultz #define	FE_VXSQRT	0x00000200	/* square root of a negative */
69122e1380SDavid Schultz #define	FE_VXSOFT	0x00000400	/* software-requested exception */
70122e1380SDavid Schultz #define	FE_VXVC		0x00080000	/* ordered comparison involving NaN */
71122e1380SDavid Schultz #define	FE_VXIMZ	0x00100000	/* inf * 0 */
72122e1380SDavid Schultz #define	FE_VXZDZ	0x00200000	/* 0 / 0 */
73122e1380SDavid Schultz #define	FE_VXIDI	0x00400000	/* inf / inf */
74122e1380SDavid Schultz #define	FE_VXISI	0x00800000	/* inf - inf */
75122e1380SDavid Schultz #define	FE_VXSNAN	0x01000000	/* operation on a signalling NaN */
76122e1380SDavid Schultz #define	FE_ALL_INVALID	(FE_VXCVI | FE_VXSQRT | FE_VXSOFT | FE_VXVC | \
77122e1380SDavid Schultz 			 FE_VXIMZ | FE_VXZDZ | FE_VXIDI | FE_VXISI | \
78122e1380SDavid Schultz 			 FE_VXSNAN | FE_INVALID)
7966405796SJustin Hibbits 
8066405796SJustin Hibbits #define	_FPUSW_SHIFT	22
8166405796SJustin Hibbits #endif
82122e1380SDavid Schultz #define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
83122e1380SDavid Schultz 			 FE_ALL_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
84122e1380SDavid Schultz 
85122e1380SDavid Schultz /* Rounding modes */
86122e1380SDavid Schultz #define	FE_TONEAREST	0x0000
87122e1380SDavid Schultz #define	FE_TOWARDZERO	0x0001
88122e1380SDavid Schultz #define	FE_UPWARD	0x0002
89122e1380SDavid Schultz #define	FE_DOWNWARD	0x0003
90122e1380SDavid Schultz #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
91122e1380SDavid Schultz 			 FE_UPWARD | FE_TOWARDZERO)
92122e1380SDavid Schultz 
93122e1380SDavid Schultz __BEGIN_DECLS
94122e1380SDavid Schultz 
95122e1380SDavid Schultz /* Default floating-point environment */
96122e1380SDavid Schultz extern const fenv_t	__fe_dfl_env;
97122e1380SDavid Schultz #define	FE_DFL_ENV	(&__fe_dfl_env)
98122e1380SDavid Schultz 
99122e1380SDavid Schultz /* We need to be able to map status flag positions to mask flag positions */
100122e1380SDavid Schultz #define	_ENABLE_MASK	((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
101122e1380SDavid Schultz 			 FE_OVERFLOW | FE_UNDERFLOW) >> _FPUSW_SHIFT)
102122e1380SDavid Schultz 
10356ae1bedSRafal Jaworowski #ifndef _SOFT_FLOAT
104dc9b124dSJustin Hibbits #ifdef __SPE__
1054f9ed315SBrandon Bergren #define	__mffs(__env) \
1064f9ed315SBrandon Bergren 	__asm __volatile("mfspr %0, 512" : "=r" ((__env)->__bits.__reg))
1074f9ed315SBrandon Bergren #define	__mtfsf(__env) \
1084f9ed315SBrandon Bergren 	__asm __volatile("mtspr 512,%0;isync" :: "r" ((__env).__bits.__reg))
109dc9b124dSJustin Hibbits #else
1104f9ed315SBrandon Bergren #define	__mffs(__env) \
1114f9ed315SBrandon Bergren 	__asm __volatile("mffs %0" : "=f" ((__env)->__d))
1124f9ed315SBrandon Bergren #define	__mtfsf(__env) \
1134f9ed315SBrandon Bergren 	__asm __volatile("mtfsf 255,%0" :: "f" ((__env).__d))
114dc9b124dSJustin Hibbits #endif
11556ae1bedSRafal Jaworowski #else
11656ae1bedSRafal Jaworowski #define	__mffs(__env)
11756ae1bedSRafal Jaworowski #define	__mtfsf(__env)
11856ae1bedSRafal Jaworowski #endif
119122e1380SDavid Schultz 
120122e1380SDavid Schultz union __fpscr {
121122e1380SDavid Schultz 	double __d;
122122e1380SDavid Schultz 	struct {
123f0e6a4d3SNathan Whitehorn #if _BYTE_ORDER == _LITTLE_ENDIAN
124f0e6a4d3SNathan Whitehorn 		fenv_t __reg;
125f0e6a4d3SNathan Whitehorn 		__uint32_t __junk;
126f0e6a4d3SNathan Whitehorn #else
127122e1380SDavid Schultz 		__uint32_t __junk;
128122e1380SDavid Schultz 		fenv_t __reg;
129f0e6a4d3SNathan Whitehorn #endif
130122e1380SDavid Schultz 	} __bits;
131122e1380SDavid Schultz };
132122e1380SDavid Schultz 
133d78e594bSDavid Schultz __fenv_static inline int
feclearexcept(int __excepts)134122e1380SDavid Schultz feclearexcept(int __excepts)
135122e1380SDavid Schultz {
136122e1380SDavid Schultz 	union __fpscr __r;
137122e1380SDavid Schultz 
138122e1380SDavid Schultz 	if (__excepts & FE_INVALID)
139122e1380SDavid Schultz 		__excepts |= FE_ALL_INVALID;
1404f9ed315SBrandon Bergren 	__mffs(&__r);
141122e1380SDavid Schultz 	__r.__bits.__reg &= ~__excepts;
1424f9ed315SBrandon Bergren 	__mtfsf(__r);
143122e1380SDavid Schultz 	return (0);
144122e1380SDavid Schultz }
145122e1380SDavid Schultz 
146d78e594bSDavid Schultz __fenv_static inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)147122e1380SDavid Schultz fegetexceptflag(fexcept_t *__flagp, int __excepts)
148122e1380SDavid Schultz {
149122e1380SDavid Schultz 	union __fpscr __r;
150122e1380SDavid Schultz 
1514f9ed315SBrandon Bergren 	__mffs(&__r);
152122e1380SDavid Schultz 	*__flagp = __r.__bits.__reg & __excepts;
153122e1380SDavid Schultz 	return (0);
154122e1380SDavid Schultz }
155122e1380SDavid Schultz 
156d78e594bSDavid Schultz __fenv_static inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)157122e1380SDavid Schultz fesetexceptflag(const fexcept_t *__flagp, int __excepts)
158122e1380SDavid Schultz {
159122e1380SDavid Schultz 	union __fpscr __r;
160122e1380SDavid Schultz 
161122e1380SDavid Schultz 	if (__excepts & FE_INVALID)
162e7bd4f84SAlfredo Dal'Ava Junior 		__excepts |= FE_ALL_INVALID;
1634f9ed315SBrandon Bergren 	__mffs(&__r);
164122e1380SDavid Schultz 	__r.__bits.__reg &= ~__excepts;
165122e1380SDavid Schultz 	__r.__bits.__reg |= *__flagp & __excepts;
1664f9ed315SBrandon Bergren 	__mtfsf(__r);
167122e1380SDavid Schultz 	return (0);
168122e1380SDavid Schultz }
169122e1380SDavid Schultz 
17066405796SJustin Hibbits #ifdef __SPE__
17166405796SJustin Hibbits extern int	feraiseexcept(int __excepts);
17266405796SJustin Hibbits #else
173d78e594bSDavid Schultz __fenv_static inline int
feraiseexcept(int __excepts)174122e1380SDavid Schultz feraiseexcept(int __excepts)
175122e1380SDavid Schultz {
176122e1380SDavid Schultz 	union __fpscr __r;
177122e1380SDavid Schultz 
178122e1380SDavid Schultz 	if (__excepts & FE_INVALID)
179122e1380SDavid Schultz 		__excepts |= FE_VXSOFT;
1804f9ed315SBrandon Bergren 	__mffs(&__r);
181122e1380SDavid Schultz 	__r.__bits.__reg |= __excepts;
1824f9ed315SBrandon Bergren 	__mtfsf(__r);
183122e1380SDavid Schultz 	return (0);
184122e1380SDavid Schultz }
18566405796SJustin Hibbits #endif
186122e1380SDavid Schultz 
187d78e594bSDavid Schultz __fenv_static inline int
fetestexcept(int __excepts)188122e1380SDavid Schultz fetestexcept(int __excepts)
189122e1380SDavid Schultz {
190122e1380SDavid Schultz 	union __fpscr __r;
191122e1380SDavid Schultz 
1924f9ed315SBrandon Bergren 	__mffs(&__r);
193122e1380SDavid Schultz 	return (__r.__bits.__reg & __excepts);
194122e1380SDavid Schultz }
195122e1380SDavid Schultz 
196d78e594bSDavid Schultz __fenv_static inline int
fegetround(void)197122e1380SDavid Schultz fegetround(void)
198122e1380SDavid Schultz {
199122e1380SDavid Schultz 	union __fpscr __r;
200122e1380SDavid Schultz 
2014f9ed315SBrandon Bergren 	__mffs(&__r);
202122e1380SDavid Schultz 	return (__r.__bits.__reg & _ROUND_MASK);
203122e1380SDavid Schultz }
204122e1380SDavid Schultz 
205d78e594bSDavid Schultz __fenv_static inline int
fesetround(int __round)206122e1380SDavid Schultz fesetround(int __round)
207122e1380SDavid Schultz {
208122e1380SDavid Schultz 	union __fpscr __r;
209122e1380SDavid Schultz 
210122e1380SDavid Schultz 	if (__round & ~_ROUND_MASK)
211122e1380SDavid Schultz 		return (-1);
2124f9ed315SBrandon Bergren 	__mffs(&__r);
213122e1380SDavid Schultz 	__r.__bits.__reg &= ~_ROUND_MASK;
214122e1380SDavid Schultz 	__r.__bits.__reg |= __round;
2154f9ed315SBrandon Bergren 	__mtfsf(__r);
216122e1380SDavid Schultz 	return (0);
217122e1380SDavid Schultz }
218122e1380SDavid Schultz 
219d78e594bSDavid Schultz __fenv_static inline int
fegetenv(fenv_t * __envp)220122e1380SDavid Schultz fegetenv(fenv_t *__envp)
221122e1380SDavid Schultz {
222122e1380SDavid Schultz 	union __fpscr __r;
223122e1380SDavid Schultz 
2244f9ed315SBrandon Bergren 	__mffs(&__r);
225122e1380SDavid Schultz 	*__envp = __r.__bits.__reg;
226122e1380SDavid Schultz 	return (0);
227122e1380SDavid Schultz }
228122e1380SDavid Schultz 
229d78e594bSDavid Schultz __fenv_static inline int
feholdexcept(fenv_t * __envp)230122e1380SDavid Schultz feholdexcept(fenv_t *__envp)
231122e1380SDavid Schultz {
232122e1380SDavid Schultz 	union __fpscr __r;
233122e1380SDavid Schultz 
2344f9ed315SBrandon Bergren 	__mffs(&__r);
235469026a8SBrandon Bergren 	*__envp = __r.__bits.__reg;
236122e1380SDavid Schultz 	__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
2374f9ed315SBrandon Bergren 	__mtfsf(__r);
238122e1380SDavid Schultz 	return (0);
239122e1380SDavid Schultz }
240122e1380SDavid Schultz 
241d78e594bSDavid Schultz __fenv_static inline int
fesetenv(const fenv_t * __envp)242122e1380SDavid Schultz fesetenv(const fenv_t *__envp)
243122e1380SDavid Schultz {
244122e1380SDavid Schultz 	union __fpscr __r;
245122e1380SDavid Schultz 
246122e1380SDavid Schultz 	__r.__bits.__reg = *__envp;
2474f9ed315SBrandon Bergren 	__mtfsf(__r);
248122e1380SDavid Schultz 	return (0);
249122e1380SDavid Schultz }
250122e1380SDavid Schultz 
251d78e594bSDavid Schultz __fenv_static inline int
feupdateenv(const fenv_t * __envp)252122e1380SDavid Schultz feupdateenv(const fenv_t *__envp)
253122e1380SDavid Schultz {
254122e1380SDavid Schultz 	union __fpscr __r;
255122e1380SDavid Schultz 
2564f9ed315SBrandon Bergren 	__mffs(&__r);
257122e1380SDavid Schultz 	__r.__bits.__reg &= FE_ALL_EXCEPT;
258122e1380SDavid Schultz 	__r.__bits.__reg |= *__envp;
2594f9ed315SBrandon Bergren 	__mtfsf(__r);
260122e1380SDavid Schultz 	return (0);
261122e1380SDavid Schultz }
262122e1380SDavid Schultz 
263122e1380SDavid Schultz #if __BSD_VISIBLE
264122e1380SDavid Schultz 
265448c505cSJustin Hibbits __fenv_static inline int
feenableexcept(int __mask)26610b01832SDavid Schultz feenableexcept(int __mask)
267122e1380SDavid Schultz {
268122e1380SDavid Schultz 	union __fpscr __r;
269122e1380SDavid Schultz 	fenv_t __oldmask;
270122e1380SDavid Schultz 
2714f9ed315SBrandon Bergren 	__mffs(&__r);
272122e1380SDavid Schultz 	__oldmask = __r.__bits.__reg;
27310b01832SDavid Schultz 	__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
2744f9ed315SBrandon Bergren 	__mtfsf(__r);
275122e1380SDavid Schultz 	return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
276122e1380SDavid Schultz }
277122e1380SDavid Schultz 
278448c505cSJustin Hibbits __fenv_static inline int
fedisableexcept(int __mask)27910b01832SDavid Schultz fedisableexcept(int __mask)
28010b01832SDavid Schultz {
28110b01832SDavid Schultz 	union __fpscr __r;
28210b01832SDavid Schultz 	fenv_t __oldmask;
28310b01832SDavid Schultz 
2844f9ed315SBrandon Bergren 	__mffs(&__r);
28510b01832SDavid Schultz 	__oldmask = __r.__bits.__reg;
28610b01832SDavid Schultz 	__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
2874f9ed315SBrandon Bergren 	__mtfsf(__r);
28810b01832SDavid Schultz 	return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
28910b01832SDavid Schultz }
29010b01832SDavid Schultz 
291448c505cSJustin Hibbits /* We currently provide no external definition of fegetexcept(). */
292d78e594bSDavid Schultz static inline int
fegetexcept(void)29310b01832SDavid Schultz fegetexcept(void)
294122e1380SDavid Schultz {
295122e1380SDavid Schultz 	union __fpscr __r;
296122e1380SDavid Schultz 
2974f9ed315SBrandon Bergren 	__mffs(&__r);
298122e1380SDavid Schultz 	return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
299122e1380SDavid Schultz }
300122e1380SDavid Schultz 
301122e1380SDavid Schultz #endif /* __BSD_VISIBLE */
302122e1380SDavid Schultz 
303122e1380SDavid Schultz __END_DECLS
304122e1380SDavid Schultz 
305122e1380SDavid Schultz #endif	/* !_FENV_H_ */
306