Skip to content

Commit 1eeb139

Browse files
authored
aarch64/fenv: fix fenv_t (#319)
* aarch64: copy `aarch64/fenv.h` from FreeBSD https://github.com/freebsd/freebsd-src/blob/de1aa3dab23c06fec962a14da3e7b4755c5880cf/lib/msun/aarch64/fenv.h * aarch64: clean code * arm: remove AARCH64 ifdef
1 parent 5a88ede commit 1eeb139

File tree

3 files changed

+251
-5
lines changed

3 files changed

+251
-5
lines changed

include/openlibm_fenv.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
#include <fenv.h>
33
#else /* !OPENLIBM_USE_HOST_FENV_H */
44

5-
#if defined(__aarch64__) || defined(__arm__)
5+
#if defined(__aarch64__)
6+
#include <openlibm_fenv_aarch64.h>
7+
#elif defined(__arm__)
68
#include <openlibm_fenv_arm.h>
79
#elif defined(__x86_64__)
810
#include <openlibm_fenv_amd64.h>

include/openlibm_fenv_aarch64.h

+247
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/*-
2+
* Copyright (c) 2004-2005 David Schultz <[email protected]>
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+
27+
#ifndef _FENV_H_
28+
#define _FENV_H_
29+
30+
#include <stdint.h>
31+
32+
#include "cdefs-compat.h"
33+
34+
#ifndef __fenv_static
35+
#define __fenv_static static
36+
#endif
37+
38+
/* The high 32 bits contain fpcr, low 32 contain fpsr. */
39+
typedef __uint64_t fenv_t;
40+
typedef __uint64_t fexcept_t;
41+
42+
/* Exception flags */
43+
#define FE_INVALID 0x00000001
44+
#define FE_DIVBYZERO 0x00000002
45+
#define FE_OVERFLOW 0x00000004
46+
#define FE_UNDERFLOW 0x00000008
47+
#define FE_INEXACT 0x00000010
48+
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
49+
FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
50+
51+
/*
52+
* Rounding modes
53+
*
54+
* We can't just use the hardware bit values here, because that would
55+
* make FE_UPWARD and FE_DOWNWARD negative, which is not allowed.
56+
*/
57+
#define FE_TONEAREST 0x0
58+
#define FE_UPWARD 0x1
59+
#define FE_DOWNWARD 0x2
60+
#define FE_TOWARDZERO 0x3
61+
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
62+
FE_UPWARD | FE_TOWARDZERO)
63+
#define _ROUND_SHIFT 22
64+
65+
__BEGIN_DECLS
66+
67+
/* Default floating-point environment */
68+
extern const fenv_t __fe_dfl_env;
69+
#define FE_DFL_ENV (&__fe_dfl_env)
70+
71+
/* We need to be able to map status flag positions to mask flag positions */
72+
#define _FPUSW_SHIFT 8
73+
#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
74+
75+
#define __mrs_fpcr(__r) __asm __volatile("mrs %0, fpcr" : "=r" (__r))
76+
#define __msr_fpcr(__r) __asm __volatile("msr fpcr, %0" : : "r" (__r))
77+
78+
#define __mrs_fpsr(__r) __asm __volatile("mrs %0, fpsr" : "=r" (__r))
79+
#define __msr_fpsr(__r) __asm __volatile("msr fpsr, %0" : : "r" (__r))
80+
81+
82+
__fenv_static inline int
83+
feclearexcept(int __excepts)
84+
{
85+
fexcept_t __r;
86+
87+
__mrs_fpsr(__r);
88+
__r &= ~__excepts;
89+
__msr_fpsr(__r);
90+
return (0);
91+
}
92+
93+
__fenv_static inline int
94+
fegetexceptflag(fexcept_t *__flagp, int __excepts)
95+
{
96+
fexcept_t __r;
97+
98+
__mrs_fpsr(__r);
99+
*__flagp = __r & __excepts;
100+
return (0);
101+
}
102+
103+
__fenv_static inline int
104+
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
105+
{
106+
fexcept_t __r;
107+
108+
__mrs_fpsr(__r);
109+
__r &= ~__excepts;
110+
__r |= *__flagp & __excepts;
111+
__msr_fpsr(__r);
112+
return (0);
113+
}
114+
115+
__fenv_static inline int
116+
feraiseexcept(int __excepts)
117+
{
118+
fexcept_t __r;
119+
120+
__mrs_fpsr(__r);
121+
__r |= __excepts;
122+
__msr_fpsr(__r);
123+
return (0);
124+
}
125+
126+
__fenv_static inline int
127+
fetestexcept(int __excepts)
128+
{
129+
fexcept_t __r;
130+
131+
__mrs_fpsr(__r);
132+
return (__r & __excepts);
133+
}
134+
135+
__fenv_static inline int
136+
fegetround(void)
137+
{
138+
fenv_t __r;
139+
140+
__mrs_fpcr(__r);
141+
return ((__r >> _ROUND_SHIFT) & _ROUND_MASK);
142+
}
143+
144+
__fenv_static inline int
145+
fesetround(int __round)
146+
{
147+
fenv_t __r;
148+
149+
if (__round & ~_ROUND_MASK)
150+
return (-1);
151+
__mrs_fpcr(__r);
152+
__r &= ~(_ROUND_MASK << _ROUND_SHIFT);
153+
__r |= __round << _ROUND_SHIFT;
154+
__msr_fpcr(__r);
155+
return (0);
156+
}
157+
158+
__fenv_static inline int
159+
fegetenv(fenv_t *__envp)
160+
{
161+
__uint64_t fpcr;
162+
__uint64_t fpsr;
163+
164+
__mrs_fpcr(fpcr);
165+
__mrs_fpsr(fpsr);
166+
*__envp = fpsr | (fpcr << 32);
167+
168+
return (0);
169+
}
170+
171+
__fenv_static inline int
172+
feholdexcept(fenv_t *__envp)
173+
{
174+
fenv_t __r;
175+
176+
__mrs_fpcr(__r);
177+
*__envp = __r << 32;
178+
__r &= ~(_ENABLE_MASK);
179+
__msr_fpcr(__r);
180+
181+
__mrs_fpsr(__r);
182+
*__envp |= (__uint32_t)__r;
183+
__r &= ~(_ENABLE_MASK);
184+
__msr_fpsr(__r);
185+
return (0);
186+
}
187+
188+
__fenv_static inline int
189+
fesetenv(const fenv_t *__envp)
190+
{
191+
192+
__msr_fpcr((*__envp) >> 32);
193+
__msr_fpsr((fenv_t)(__uint32_t)*__envp);
194+
return (0);
195+
}
196+
197+
__fenv_static inline int
198+
feupdateenv(const fenv_t *__envp)
199+
{
200+
fexcept_t __r;
201+
202+
__mrs_fpsr(__r);
203+
fesetenv(__envp);
204+
feraiseexcept(__r & FE_ALL_EXCEPT);
205+
return (0);
206+
}
207+
208+
#if __BSD_VISIBLE
209+
210+
/* We currently provide no external definitions of the functions below. */
211+
212+
static inline int
213+
feenableexcept(int __mask)
214+
{
215+
fenv_t __old_r, __new_r;
216+
217+
__mrs_fpcr(__old_r);
218+
__new_r = __old_r | ((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
219+
__msr_fpcr(__new_r);
220+
return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
221+
}
222+
223+
static inline int
224+
fedisableexcept(int __mask)
225+
{
226+
fenv_t __old_r, __new_r;
227+
228+
__mrs_fpcr(__old_r);
229+
__new_r = __old_r & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
230+
__msr_fpcr(__new_r);
231+
return ((__old_r >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
232+
}
233+
234+
static inline int
235+
fegetexcept(void)
236+
{
237+
fenv_t __r;
238+
239+
__mrs_fpcr(__r);
240+
return ((__r & _ENABLE_MASK) >> _FPUSW_SHIFT);
241+
}
242+
243+
#endif /* __BSD_VISIBLE */
244+
245+
__END_DECLS
246+
247+
#endif /* !_FENV_H_ */

include/openlibm_fenv_arm.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,9 @@ extern const fenv_t __fe_dfl_env;
6666
#define _FPUSW_SHIFT 16
6767
#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
6868

69-
#if defined(__aarch64__)
70-
#define __rfs(__fpsr) __asm __volatile("mrs %0,fpsr" : "=r" (*(__fpsr)))
71-
#define __wfs(__fpsr) __asm __volatile("msr fpsr,%0" : : "r" (__fpsr))
7269
/* Test for hardware support for ARM floating point operations, explicitly
7370
checking for float and double support, see "ARM C Language Extensions", 6.5.1 */
74-
#elif defined(__ARM_FP) && (__ARM_FP & 0x0C) != 0
71+
#if defined(__ARM_FP) && (__ARM_FP & 0x0C) != 0
7572
#define __rfs(__fpsr) __asm __volatile("vmrs %0,fpscr" : "=&r" (*(__fpsr)))
7673
#define __wfs(__fpsr) __asm __volatile("vmsr fpscr,%0" : : "r" (__fpsr))
7774
#else

0 commit comments

Comments
 (0)