blob: da7e69652109bc0064254ffccbbfc217153f61dc [file] [log] [blame]
Shih-wei Liao4e86ebb2012-07-30 20:12:46 -07001/*-
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
Elliott Hughes0f7809d2012-10-31 13:26:46 -070032#include <sys/types.h>
33
34__BEGIN_DECLS
Shih-wei Liao4e86ebb2012-07-30 20:12:46 -070035
36typedef __uint32_t fenv_t;
37typedef __uint32_t fexcept_t;
38
39/* Exception flags */
40#define FE_INVALID 0x0001
41#define FE_DIVBYZERO 0x0002
42#define FE_OVERFLOW 0x0004
43#define FE_UNDERFLOW 0x0008
44#define FE_INEXACT 0x0010
45#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
46 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
47
48/* Rounding modes */
49#define FE_TONEAREST 0x0000
50#define FE_TOWARDZERO 0x0001
51#define FE_UPWARD 0x0002
52#define FE_DOWNWARD 0x0003
53#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
54 FE_UPWARD | FE_TOWARDZERO)
Shih-wei Liao4e86ebb2012-07-30 20:12:46 -070055
56/* Default floating-point environment */
57extern const fenv_t __fe_dfl_env;
58#define FE_DFL_ENV (&__fe_dfl_env)
59
60/* We need to be able to map status flag positions to mask flag positions */
61#define _FPUSW_SHIFT 16
62#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
63
64#ifdef ARM_HARD_FLOAT
65#define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr)))
66#define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr))
67#else
68#define __rfs(__fpsr)
69#define __wfs(__fpsr)
70#endif
71
72static __inline int
73feclearexcept(int __excepts)
74{
75 fexcept_t __fpsr;
76
77 __rfs(&__fpsr);
78 __fpsr &= ~__excepts;
79 __wfs(__fpsr);
80 return (0);
81}
82
83static __inline int
84fegetexceptflag(fexcept_t *__flagp, int __excepts)
85{
86 fexcept_t __fpsr;
87
88 __rfs(&__fpsr);
89 *__flagp = __fpsr & __excepts;
90 return (0);
91}
92
93static __inline int
94fesetexceptflag(const fexcept_t *__flagp, int __excepts)
95{
96 fexcept_t __fpsr;
97
98 __rfs(&__fpsr);
99 __fpsr &= ~__excepts;
100 __fpsr |= *__flagp & __excepts;
101 __wfs(__fpsr);
102 return (0);
103}
104
105static __inline int
106feraiseexcept(int __excepts)
107{
108 fexcept_t __ex = __excepts;
109
110 fesetexceptflag(&__ex, __excepts); /* XXX */
111 return (0);
112}
113
114static __inline int
115fetestexcept(int __excepts)
116{
117 fexcept_t __fpsr;
118
119 __rfs(&__fpsr);
120 return (__fpsr & __excepts);
121}
122
123static __inline int
124fegetround(void)
125{
126
127 /*
128 * Apparently, the rounding mode is specified as part of the
129 * instruction format on ARM, so the dynamic rounding mode is
130 * indeterminate. Some FPUs may differ.
131 */
132 return (-1);
133}
134
135static __inline int
136fesetround(int __round)
137{
138
139 return (-1);
140}
141
142static __inline int
143fegetenv(fenv_t *__envp)
144{
145
146 __rfs(__envp);
147 return (0);
148}
149
150static __inline int
151feholdexcept(fenv_t *__envp)
152{
153 fenv_t __env;
154
155 __rfs(&__env);
156 *__envp = __env;
157 __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
158 __wfs(__env);
159 return (0);
160}
161
162static __inline int
163fesetenv(const fenv_t *__envp)
164{
165
166 __wfs(*__envp);
167 return (0);
168}
169
170static __inline int
171feupdateenv(const fenv_t *__envp)
172{
173 fexcept_t __fpsr;
174
175 __rfs(&__fpsr);
176 __wfs(*__envp);
177 feraiseexcept(__fpsr & FE_ALL_EXCEPT);
178 return (0);
179}
180
181#if __BSD_VISIBLE
182
183static __inline int
184feenableexcept(int __mask)
185{
186 fenv_t __old_fpsr, __new_fpsr;
187
188 __rfs(&__old_fpsr);
189 __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
190 __wfs(__new_fpsr);
191 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
192}
193
194static __inline int
195fedisableexcept(int __mask)
196{
197 fenv_t __old_fpsr, __new_fpsr;
198
199 __rfs(&__old_fpsr);
200 __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
201 __wfs(__new_fpsr);
202 return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
203}
204
205static __inline int
206fegetexcept(void)
207{
208 fenv_t __fpsr;
209
210 __rfs(&__fpsr);
211 return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
212}
213
214#endif /* __BSD_VISIBLE */
215
216__END_DECLS
217
218#endif /* !_FENV_H_ */