revert between 56095 -> 55830 in arch
[AROS.git] / arch / i386-all / stdc / fenv.c
blob2b475b689f0eaee19434e7741cd9a2363c86463c
1 /*-
2 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/lib/msun/i387/fenv.c,v 1.3 2007/01/05 07:15:26 das Exp $
29 #define __BSD_VISIBLE 1
30 #include "fenv.h"
32 #define __INITIAL_FPUCW_I386__ 0x127F
33 #define __INITIAL_NPXCW__ __INITIAL_FPUCW_I386__
35 const fenv_t __fe_dfl_env = {
36 __INITIAL_NPXCW__,
37 0x0000,
38 0x0000,
39 0x1f80,
40 0xffffffff,
41 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
45 extern inline int feclearexcept(int __excepts);
46 extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
48 int
49 fesetexceptflag(const fexcept_t *flagp, int excepts)
51 fenv_t env;
52 uint32_t mxcsr;
54 __fnstenv(&env);
55 env.__status &= ~excepts;
56 env.__status |= *flagp & excepts;
57 __fldenv(env);
59 if (__HAS_SSE()) {
60 __stmxcsr(&mxcsr);
61 mxcsr &= ~excepts;
62 mxcsr |= *flagp & excepts;
63 __ldmxcsr(mxcsr);
66 return (0);
69 int
70 feraiseexcept(int excepts)
72 fexcept_t ex = excepts;
74 fesetexceptflag(&ex, excepts);
75 __fwait();
76 return (0);
79 extern inline int fetestexcept(int __excepts);
80 extern inline int fegetround(void);
81 extern inline int fesetround(int __round);
83 int
84 fegetenv(fenv_t *envp)
86 uint32_t mxcsr;
88 __fnstenv(envp);
90 * fnstenv masks all exceptions, so we need to restore
91 * the old control word to avoid this side effect.
93 __fldcw(envp->__control);
94 if (__HAS_SSE()) {
95 __stmxcsr(&mxcsr);
96 __set_mxcsr(*envp, mxcsr);
98 return (0);
102 feholdexcept(fenv_t *envp)
104 uint32_t mxcsr;
106 __fnstenv(envp);
107 __fnclex();
108 if (__HAS_SSE()) {
109 __stmxcsr(&mxcsr);
110 __set_mxcsr(*envp, mxcsr);
111 mxcsr &= ~FE_ALL_EXCEPT;
112 mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
113 __ldmxcsr(mxcsr);
115 return (0);
118 extern inline int fesetenv(const fenv_t *__envp);
121 feupdateenv(const fenv_t *envp)
123 uint32_t mxcsr;
124 uint16_t status;
126 __fnstsw(&status);
127 if (__HAS_SSE())
128 __stmxcsr(&mxcsr);
129 else
130 mxcsr = 0;
131 fesetenv(envp);
132 feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
133 return (0);
137 __feenableexcept(int mask)
139 uint32_t mxcsr, omask;
140 uint16_t control;
142 mask &= FE_ALL_EXCEPT;
143 __fnstcw(&control);
144 if (__HAS_SSE())
145 __stmxcsr(&mxcsr);
146 else
147 mxcsr = 0;
148 omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
149 control &= ~mask;
150 __fldcw(control);
151 if (__HAS_SSE()) {
152 mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
153 __ldmxcsr(mxcsr);
155 return (omask);
159 __fedisableexcept(int mask)
161 uint32_t mxcsr, omask;
162 uint16_t control;
164 mask &= FE_ALL_EXCEPT;
165 __fnstcw(&control);
166 if (__HAS_SSE())
167 __stmxcsr(&mxcsr);
168 else
169 mxcsr = 0;
170 omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
171 control |= mask;
172 __fldcw(control);
173 if (__HAS_SSE()) {
174 mxcsr |= mask << _SSE_EMASK_SHIFT;
175 __ldmxcsr(mxcsr);
177 return (omask);
180 AROS_MAKE_ASM_SYM(typeof(feenableexcept), feenableexcept, AROS_CSYM_FROM_ASM_NAME(feenableexcept), AROS_CSYM_FROM_ASM_NAME(__feenableexcept));
181 AROS_EXPORT_ASM_SYM(AROS_CSYM_FROM_ASM_NAME(feenableexcept));
183 AROS_MAKE_ASM_SYM(typeof(fedisableexcept), fedisableexcept, AROS_CSYM_FROM_ASM_NAME(fedisableexcept), AROS_CSYM_FROM_ASM_NAME(__fedisableexcept));
184 AROS_EXPORT_ASM_SYM(AROS_CSYM_FROM_ASM_NAME(fedisableexcept));