fenv.h revision 435483c91cf16117fc2b864cb6994435ad669bc6
1/*-
2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
27 */
28
29#ifndef	_FENV_H_
30#define	_FENV_H_
31
32#include <sys/_types.h>
33
34typedef	__uint32_t	fenv_t;
35typedef	__uint32_t	fexcept_t;
36
37/* Exception flags */
38#define	FE_INVALID	0x0001
39#define	FE_DIVBYZERO	0x0002
40#define	FE_OVERFLOW	0x0004
41#define	FE_UNDERFLOW	0x0008
42#define	FE_INEXACT	0x0010
43#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
44			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
45
46/* Rounding modes */
47#define	FE_TONEAREST	0x0000
48#define	FE_TOWARDZERO	0x0001
49#define	FE_UPWARD	0x0002
50#define	FE_DOWNWARD	0x0003
51#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
52			 FE_UPWARD | FE_TOWARDZERO)
53__BEGIN_DECLS
54
55/* Default floating-point environment */
56extern const fenv_t	__fe_dfl_env;
57#define	FE_DFL_ENV	(&__fe_dfl_env)
58
59/* We need to be able to map status flag positions to mask flag positions */
60#define _FPUSW_SHIFT	16
61#define	_ENABLE_MASK	(FE_ALL_EXCEPT << _FPUSW_SHIFT)
62
63#ifdef	ARM_HARD_FLOAT
64#define	__rfs(__fpsr)	__asm __volatile("rfs %0" : "=r" (*(__fpsr)))
65#define	__wfs(__fpsr)	__asm __volatile("wfs %0" : : "r" (__fpsr))
66#else
67#define __rfs(__fpsr)
68#define __wfs(__fpsr)
69#endif
70
71static __inline int
72feclearexcept(int __excepts)
73{
74	fexcept_t __fpsr;
75
76	__rfs(&__fpsr);
77	__fpsr &= ~__excepts;
78	__wfs(__fpsr);
79	return (0);
80}
81
82static __inline int
83fegetexceptflag(fexcept_t *__flagp, int __excepts)
84{
85	fexcept_t __fpsr;
86
87	__rfs(&__fpsr);
88	*__flagp = __fpsr & __excepts;
89	return (0);
90}
91
92static __inline int
93fesetexceptflag(const fexcept_t *__flagp, int __excepts)
94{
95	fexcept_t __fpsr;
96
97	__rfs(&__fpsr);
98	__fpsr &= ~__excepts;
99	__fpsr |= *__flagp & __excepts;
100	__wfs(__fpsr);
101	return (0);
102}
103
104static __inline int
105feraiseexcept(int __excepts)
106{
107	fexcept_t __ex = __excepts;
108
109	fesetexceptflag(&__ex, __excepts);	/* XXX */
110	return (0);
111}
112
113static __inline int
114fetestexcept(int __excepts)
115{
116	fexcept_t __fpsr;
117
118	__rfs(&__fpsr);
119	return (__fpsr & __excepts);
120}
121
122static __inline int
123fegetround(void)
124{
125
126	/*
127	 * Apparently, the rounding mode is specified as part of the
128	 * instruction format on ARM, so the dynamic rounding mode is
129	 * indeterminate.  Some FPUs may differ.
130	 */
131	return (-1);
132}
133
134static __inline int
135fesetround(int __round)
136{
137
138	return (-1);
139}
140
141static __inline int
142fegetenv(fenv_t *__envp)
143{
144
145	__rfs(__envp);
146	return (0);
147}
148
149static __inline int
150feholdexcept(fenv_t *__envp)
151{
152	fenv_t __env;
153
154	__rfs(&__env);
155	*__envp = __env;
156	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
157	__wfs(__env);
158	return (0);
159}
160
161static __inline int
162fesetenv(const fenv_t *__envp)
163{
164
165	__wfs(*__envp);
166	return (0);
167}
168
169static __inline int
170feupdateenv(const fenv_t *__envp)
171{
172	fexcept_t __fpsr;
173
174	__rfs(&__fpsr);
175	__wfs(*__envp);
176	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
177	return (0);
178}
179
180#if __BSD_VISIBLE
181
182static __inline int
183feenableexcept(int __mask)
184{
185	fenv_t __old_fpsr, __new_fpsr;
186
187	__rfs(&__old_fpsr);
188	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
189	__wfs(__new_fpsr);
190	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
191}
192
193static __inline int
194fedisableexcept(int __mask)
195{
196	fenv_t __old_fpsr, __new_fpsr;
197
198	__rfs(&__old_fpsr);
199	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
200	__wfs(__new_fpsr);
201	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
202}
203
204static __inline int
205fegetexcept(void)
206{
207	fenv_t __fpsr;
208
209	__rfs(&__fpsr);
210	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
211}
212
213#endif /* __BSD_VISIBLE */
214
215__END_DECLS
216
217#endif	/* !_FENV_H_ */
218