Skip to content

Commit d078203

Browse files
committed
Rename the fenv headers.
I guess the idea would be to eventually also install all of the openlibm*.h headers, instead of just openlibm.h. Make openlibm_fenv.h suitable for this purpose by moving all of the $ARCH/fenv.h headers next to it. We actually need this change to make OPENLIBM_USE_HOST_FENV_H work. Right now it's still broken, because the "#include <fenv.h>" performed by openlibm_fenv.h still pulls in $ARCH/fenv.h as $ARCH/ is added to the compiler include path.
1 parent 9ab9db3 commit d078203

7 files changed

Lines changed: 709 additions & 3 deletions

File tree

File renamed without changes.
File renamed without changes.
File renamed without changes.

src/openlibm_fenv.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#else /* !OPENLIBM_USE_HOST_FENV_H */
44

55
#if defined(__arm__)
6-
#include "../arm/fenv.h"
6+
#include <openlibm_fenv_arm.h>
77
#elif defined(__x86_64__)
8-
#include "../amd64/fenv.h"
8+
#include <openlibm_fenv_amd64.h>
99
#elif defined(__i386__)
10-
#include "../i387/fenv.h"
10+
#include <openlibm_fenv_i387.h>
1111
#else
1212
#error "Unsupported platform"
1313
#endif

src/openlibm_fenv_amd64.h

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
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/amd64/fenv.h,v 1.8 2011/10/10 15:43:09 das Exp $
27+
*/
28+
29+
#ifndef _FENV_H_
30+
#define _FENV_H_
31+
32+
#include "cdefs-compat.h"
33+
#include "types-compat.h"
34+
35+
#include "math_private.h"
36+
37+
#ifndef __fenv_static
38+
#define __fenv_static static
39+
#endif
40+
41+
typedef struct {
42+
struct {
43+
uint32_t __control;
44+
uint32_t __status;
45+
uint32_t __tag;
46+
char __other[16];
47+
} __x87;
48+
uint32_t __mxcsr;
49+
} fenv_t;
50+
51+
typedef uint16_t fexcept_t;
52+
53+
/* Exception flags */
54+
#define FE_INVALID 0x01
55+
#define FE_DENORMAL 0x02
56+
#define FE_DIVBYZERO 0x04
57+
#define FE_OVERFLOW 0x08
58+
#define FE_UNDERFLOW 0x10
59+
#define FE_INEXACT 0x20
60+
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_DENORMAL | FE_INEXACT | \
61+
FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
62+
63+
/* Rounding modes */
64+
#define FE_TONEAREST 0x0000
65+
#define FE_DOWNWARD 0x0400
66+
#define FE_UPWARD 0x0800
67+
#define FE_TOWARDZERO 0x0c00
68+
#define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
69+
FE_UPWARD | FE_TOWARDZERO)
70+
71+
/*
72+
* As compared to the x87 control word, the SSE unit's control word
73+
* has the rounding control bits offset by 3 and the exception mask
74+
* bits offset by 7.
75+
*/
76+
#define _SSE_ROUND_SHIFT 3
77+
#define _SSE_EMASK_SHIFT 7
78+
79+
__BEGIN_DECLS
80+
81+
/* Default floating-point environment */
82+
extern const fenv_t __fe_dfl_env;
83+
#define FE_DFL_ENV (&__fe_dfl_env)
84+
85+
#define __fldcw(__cw) __asm __volatile("fldcw %0" : : "m" (__cw))
86+
#define __fldenv(__env) __asm __volatile("fldenv %0" : : "m" (__env))
87+
#define __fldenvx(__env) __asm __volatile("fldenv %0" : : "m" (__env) \
88+
: "st", "st(1)", "st(2)", "st(3)", "st(4)", \
89+
"st(5)", "st(6)", "st(7)")
90+
#define __fnclex() __asm __volatile("fnclex")
91+
#define __fnstenv(__env) __asm __volatile("fnstenv %0" : "=m" (*(__env)))
92+
#define __fnstcw(__cw) __asm __volatile("fnstcw %0" : "=m" (*(__cw)))
93+
#define __fnstsw(__sw) __asm __volatile("fnstsw %0" : "=am" (*(__sw)))
94+
#define __fwait() __asm __volatile("fwait")
95+
#define __ldmxcsr(__csr) __asm __volatile("ldmxcsr %0" : : "m" (__csr))
96+
#define __stmxcsr(__csr) __asm __volatile("stmxcsr %0" : "=m" (*(__csr)))
97+
98+
__fenv_static __attribute__((always_inline)) DLLEXPORT inline int
99+
feclearexcept(int __excepts)
100+
{
101+
fenv_t __env;
102+
103+
if (__excepts == FE_ALL_EXCEPT) {
104+
__fnclex();
105+
} else {
106+
__fnstenv(&__env.__x87);
107+
__env.__x87.__status &= ~__excepts;
108+
__fldenv(__env.__x87);
109+
}
110+
__stmxcsr(&__env.__mxcsr);
111+
__env.__mxcsr &= ~__excepts;
112+
__ldmxcsr(__env.__mxcsr);
113+
return (0);
114+
}
115+
116+
__fenv_static DLLEXPORT inline int
117+
fegetexceptflag(fexcept_t *__flagp, int __excepts)
118+
{
119+
uint32_t __mxcsr;
120+
uint16_t __status;
121+
122+
__stmxcsr(&__mxcsr);
123+
__fnstsw(&__status);
124+
*__flagp = (__mxcsr | __status) & __excepts;
125+
return (0);
126+
}
127+
128+
DLLEXPORT int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
129+
DLLEXPORT int feraiseexcept(int __excepts);
130+
131+
__fenv_static __attribute__((always_inline)) DLLEXPORT inline int
132+
fetestexcept(int __excepts)
133+
{
134+
uint32_t __mxcsr;
135+
uint16_t __status;
136+
137+
__stmxcsr(&__mxcsr);
138+
__fnstsw(&__status);
139+
return ((__status | __mxcsr) & __excepts);
140+
}
141+
142+
__fenv_static DLLEXPORT inline int
143+
fegetround(void)
144+
{
145+
uint16_t __control;
146+
147+
/*
148+
* We assume that the x87 and the SSE unit agree on the
149+
* rounding mode. Reading the control word on the x87 turns
150+
* out to be about 5 times faster than reading it on the SSE
151+
* unit on an Opteron 244.
152+
*/
153+
__fnstcw(&__control);
154+
return (__control & _ROUND_MASK);
155+
}
156+
157+
__fenv_static DLLEXPORT inline int
158+
fesetround(int __round)
159+
{
160+
uint32_t __mxcsr;
161+
uint16_t __control;
162+
163+
if (__round & ~_ROUND_MASK)
164+
return (-1);
165+
166+
__fnstcw(&__control);
167+
__control &= ~_ROUND_MASK;
168+
__control |= __round;
169+
__fldcw(__control);
170+
171+
__stmxcsr(&__mxcsr);
172+
__mxcsr &= ~(_ROUND_MASK << _SSE_ROUND_SHIFT);
173+
__mxcsr |= __round << _SSE_ROUND_SHIFT;
174+
__ldmxcsr(__mxcsr);
175+
176+
return (0);
177+
}
178+
179+
DLLEXPORT int fegetenv(fenv_t *__envp);
180+
DLLEXPORT int feholdexcept(fenv_t *__envp);
181+
182+
__fenv_static DLLEXPORT inline int
183+
fesetenv(const fenv_t *__envp)
184+
{
185+
186+
/*
187+
* XXX Using fldenvx() instead of fldenv() tells the compiler that this
188+
* instruction clobbers the i387 register stack. This happens because
189+
* we restore the tag word from the saved environment. Normally, this
190+
* would happen anyway and we wouldn't care, because the ABI allows
191+
* function calls to clobber the i387 regs. However, fesetenv() is
192+
* inlined, so we need to be more careful.
193+
*/
194+
__fldenvx(__envp->__x87);
195+
__ldmxcsr(__envp->__mxcsr);
196+
return (0);
197+
}
198+
199+
DLLEXPORT int feupdateenv(const fenv_t *__envp);
200+
201+
#if __BSD_VISIBLE
202+
203+
DLLEXPORT int feenableexcept(int __mask);
204+
DLLEXPORT int fedisableexcept(int __mask);
205+
206+
/* We currently provide no external definition of fegetexcept(). */
207+
static inline DLLEXPORT int
208+
fegetexcept(void)
209+
{
210+
uint16_t __control;
211+
212+
/*
213+
* We assume that the masks for the x87 and the SSE unit are
214+
* the same.
215+
*/
216+
__fnstcw(&__control);
217+
return (~__control & FE_ALL_EXCEPT);
218+
}
219+
220+
#endif /* __BSD_VISIBLE */
221+
222+
__END_DECLS
223+
224+
#endif /* !_FENV_H_ */

0 commit comments

Comments
 (0)