xref: /minix3/lib/libm/arch/arm/fenv.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
184d9c625SLionel Sambuc /*-
284d9c625SLionel Sambuc  * Copyright (c) 2013 The NetBSD Foundation, Inc.
384d9c625SLionel Sambuc  * All rights reserved.
484d9c625SLionel Sambuc  *
584d9c625SLionel Sambuc  * This code is derived from software contributed to The NetBSD Foundation
684d9c625SLionel Sambuc  * by Matt Thomas of 3am Software Foundry.
784d9c625SLionel Sambuc  *
884d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
984d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions
1084d9c625SLionel Sambuc  * are met:
1184d9c625SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1284d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1384d9c625SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1484d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1584d9c625SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1684d9c625SLionel Sambuc  *
1784d9c625SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1884d9c625SLionel Sambuc  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1984d9c625SLionel Sambuc  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2084d9c625SLionel Sambuc  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2184d9c625SLionel Sambuc  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2284d9c625SLionel Sambuc  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2384d9c625SLionel Sambuc  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2484d9c625SLionel Sambuc  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2584d9c625SLionel Sambuc  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2684d9c625SLionel Sambuc  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2784d9c625SLionel Sambuc  * POSSIBILITY OF SUCH DAMAGE.
2884d9c625SLionel Sambuc  */
2984d9c625SLionel Sambuc 
3084d9c625SLionel Sambuc #include <sys/cdefs.h>
31*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: fenv.c,v 1.6 2014/12/29 19:11:13 martin Exp $");
3284d9c625SLionel Sambuc 
3384d9c625SLionel Sambuc #include <sys/types.h>
3484d9c625SLionel Sambuc #include <assert.h>
3584d9c625SLionel Sambuc #include <fenv.h>
3684d9c625SLionel Sambuc #include <string.h>
3784d9c625SLionel Sambuc #include <unistd.h>
3884d9c625SLionel Sambuc #include <inttypes.h>
3984d9c625SLionel Sambuc 
4084d9c625SLionel Sambuc #ifdef __SOFTFP__
4184d9c625SLionel Sambuc #include <ieeefp.h>
4284d9c625SLionel Sambuc #include <sys/signal.h>
4384d9c625SLionel Sambuc #include <sys/siginfo.h>
4484d9c625SLionel Sambuc #else
4584d9c625SLionel Sambuc #include <arm/armreg.h>
4684d9c625SLionel Sambuc #endif
4784d9c625SLionel Sambuc 
4884d9c625SLionel Sambuc #include <arm/vfpreg.h>
4984d9c625SLionel Sambuc 
5084d9c625SLionel Sambuc const fenv_t __fe_dfl_env = VFP_FPSCR_FZ|VFP_FPSCR_DN|VFP_FPSCR_RN;
5184d9c625SLionel Sambuc 
5284d9c625SLionel Sambuc /*
5384d9c625SLionel Sambuc  * The feclearexcept() function shall attempt to clear the supported
5484d9c625SLionel Sambuc  * floating-point exceptions represented by excepts.
5584d9c625SLionel Sambuc  */
5684d9c625SLionel Sambuc int
feclearexcept(int excepts)5784d9c625SLionel Sambuc feclearexcept(int excepts)
5884d9c625SLionel Sambuc {
5984d9c625SLionel Sambuc #ifndef lint
60*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
6184d9c625SLionel Sambuc #endif
6284d9c625SLionel Sambuc #ifdef __SOFTFP__
6384d9c625SLionel Sambuc 	fpsetsticky(fpgetsticky() & ~excepts);
6484d9c625SLionel Sambuc 	return 0;
6584d9c625SLionel Sambuc #else
6684d9c625SLionel Sambuc 	int tmp = armreg_fpscr_read() & ~__SHIFTIN(excepts, VFP_FPSCR_CSUM);
6784d9c625SLionel Sambuc 	armreg_fpscr_write(tmp);
6884d9c625SLionel Sambuc 	return 0;
6984d9c625SLionel Sambuc #endif
7084d9c625SLionel Sambuc }
7184d9c625SLionel Sambuc 
7284d9c625SLionel Sambuc /*
7384d9c625SLionel Sambuc  * The fegetexceptflag() function shall attempt to store an
7484d9c625SLionel Sambuc  * implementation-defined representation of the states of the floating-point
7584d9c625SLionel Sambuc  * status flags indicated by the argument excepts in the object pointed to by
7684d9c625SLionel Sambuc  * the argument flagp.
7784d9c625SLionel Sambuc  */
7884d9c625SLionel Sambuc int
fegetexceptflag(fexcept_t * flagp,int excepts)7984d9c625SLionel Sambuc fegetexceptflag(fexcept_t *flagp, int excepts)
8084d9c625SLionel Sambuc {
81*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
8284d9c625SLionel Sambuc #ifdef __SOFTFP__
8384d9c625SLionel Sambuc 	*flagp = fpgetsticky() & excepts;
8484d9c625SLionel Sambuc #else
8584d9c625SLionel Sambuc 	*flagp = __SHIFTOUT(armreg_fpscr_read(), VFP_FPSCR_CSUM) & excepts;
8684d9c625SLionel Sambuc #endif
8784d9c625SLionel Sambuc 	return 0;
8884d9c625SLionel Sambuc }
8984d9c625SLionel Sambuc 
9084d9c625SLionel Sambuc /*
9184d9c625SLionel Sambuc  * The feraiseexcept() function shall attempt to raise the supported
9284d9c625SLionel Sambuc  * floating-point exceptions represented by the argument excepts. The order
9384d9c625SLionel Sambuc  * in which these floating-point exceptions are raised is unspecified.
9484d9c625SLionel Sambuc  */
9584d9c625SLionel Sambuc int
feraiseexcept(int excepts)9684d9c625SLionel Sambuc feraiseexcept(int excepts)
9784d9c625SLionel Sambuc {
9884d9c625SLionel Sambuc #ifndef lint
99*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
10084d9c625SLionel Sambuc #endif
10184d9c625SLionel Sambuc #if !defined(__minix) /* LSC: No sigqueueinfo on Minix. */
10284d9c625SLionel Sambuc #ifdef __SOFTFP__
10384d9c625SLionel Sambuc 	excepts &= fpgetsticky();
10484d9c625SLionel Sambuc 
10584d9c625SLionel Sambuc 	if (excepts) {
10684d9c625SLionel Sambuc 		siginfo_t info;
10784d9c625SLionel Sambuc 		memset(&info, 0, sizeof info);
10884d9c625SLionel Sambuc 		info.si_signo = SIGFPE;
10984d9c625SLionel Sambuc 		info.si_pid = getpid();
11084d9c625SLionel Sambuc 		info.si_uid = geteuid();
11184d9c625SLionel Sambuc 		if (excepts & FE_UNDERFLOW)
11284d9c625SLionel Sambuc 			info.si_code = FPE_FLTUND;
11384d9c625SLionel Sambuc 		else if (excepts & FE_OVERFLOW)
11484d9c625SLionel Sambuc 			info.si_code = FPE_FLTOVF;
11584d9c625SLionel Sambuc 		else if (excepts & FE_DIVBYZERO)
11684d9c625SLionel Sambuc 			info.si_code = FPE_FLTDIV;
11784d9c625SLionel Sambuc 		else if (excepts & FE_INVALID)
11884d9c625SLionel Sambuc 			info.si_code = FPE_FLTINV;
11984d9c625SLionel Sambuc 		else if (excepts & FE_INEXACT)
12084d9c625SLionel Sambuc 			info.si_code = FPE_FLTRES;
12184d9c625SLionel Sambuc 		sigqueueinfo(getpid(), &info);
12284d9c625SLionel Sambuc 	}
12384d9c625SLionel Sambuc #else
12484d9c625SLionel Sambuc 	int fpscr = armreg_fpscr_read();
12584d9c625SLionel Sambuc 	fpscr = (fpscr & ~VFP_FPSCR_ESUM) | __SHIFTIN(excepts, VFP_FPSCR_ESUM);
12684d9c625SLionel Sambuc 	armreg_fpscr_write(fpscr);
12784d9c625SLionel Sambuc #endif
12884d9c625SLionel Sambuc #endif /* !defined(__minix) */
12984d9c625SLionel Sambuc 	return 0;
13084d9c625SLionel Sambuc }
13184d9c625SLionel Sambuc 
13284d9c625SLionel Sambuc /*
13384d9c625SLionel Sambuc  * The fesetexceptflag() function shall attempt to set the floating-point
13484d9c625SLionel Sambuc  * status flags indicated by the argument excepts to the states stored in the
13584d9c625SLionel Sambuc  * object pointed to by flagp. The value pointed to by flagp shall have been
13684d9c625SLionel Sambuc  * set by a previous call to fegetexceptflag() whose second argument
13784d9c625SLionel Sambuc  * represented at least those floating-point exceptions represented by the
13884d9c625SLionel Sambuc  * argument excepts. This function does not raise floating-point exceptions,
13984d9c625SLionel Sambuc  * but only sets the state of the flags.
14084d9c625SLionel Sambuc  */
14184d9c625SLionel Sambuc int
fesetexceptflag(const fexcept_t * flagp,int excepts)14284d9c625SLionel Sambuc fesetexceptflag(const fexcept_t *flagp, int excepts)
14384d9c625SLionel Sambuc {
14484d9c625SLionel Sambuc #ifndef lint
145*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
14684d9c625SLionel Sambuc #endif
14784d9c625SLionel Sambuc #ifdef __SOFTFP__
14884d9c625SLionel Sambuc 	fpsetsticky((fpgetsticky() & ~excepts) | (excepts & *flagp));
14984d9c625SLionel Sambuc #else
15084d9c625SLionel Sambuc 	int fpscr = armreg_fpscr_read();
15184d9c625SLionel Sambuc 	fpscr &= ~__SHIFTIN(excepts, VFP_FPSCR_CSUM);
15284d9c625SLionel Sambuc 	fpscr |= __SHIFTIN((*flagp & excepts), VFP_FPSCR_CSUM);
15384d9c625SLionel Sambuc 	armreg_fpscr_write(fpscr);
15484d9c625SLionel Sambuc #endif
15584d9c625SLionel Sambuc 	return 0;
15684d9c625SLionel Sambuc }
15784d9c625SLionel Sambuc 
158*0a6a1f1dSLionel Sambuc int
feenableexcept(int excepts)159*0a6a1f1dSLionel Sambuc feenableexcept(int excepts)
160*0a6a1f1dSLionel Sambuc {
161*0a6a1f1dSLionel Sambuc #ifndef lint
162*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
163*0a6a1f1dSLionel Sambuc #endif
164*0a6a1f1dSLionel Sambuc #ifdef __SOFTFP__
165*0a6a1f1dSLionel Sambuc 	int old = fpgetmask();
166*0a6a1f1dSLionel Sambuc 	fpsetmask(old | excepts);
167*0a6a1f1dSLionel Sambuc 	return old;
168*0a6a1f1dSLionel Sambuc #else
169*0a6a1f1dSLionel Sambuc 	int fpscr = armreg_fpscr_read();
170*0a6a1f1dSLionel Sambuc 	armreg_fpscr_write(fpscr | __SHIFTIN((excepts), VFP_FPSCR_ESUM));
171*0a6a1f1dSLionel Sambuc 	return __SHIFTOUT(fpscr, VFP_FPSCR_ESUM) & FE_ALL_EXCEPT;
172*0a6a1f1dSLionel Sambuc #endif
173*0a6a1f1dSLionel Sambuc }
174*0a6a1f1dSLionel Sambuc 
175*0a6a1f1dSLionel Sambuc int
fedisableexcept(int excepts)176*0a6a1f1dSLionel Sambuc fedisableexcept(int excepts)
177*0a6a1f1dSLionel Sambuc {
178*0a6a1f1dSLionel Sambuc #ifndef lint
179*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
180*0a6a1f1dSLionel Sambuc #endif
181*0a6a1f1dSLionel Sambuc #ifdef __SOFTFP__
182*0a6a1f1dSLionel Sambuc 	int old = fpgetmask();
183*0a6a1f1dSLionel Sambuc 	fpsetmask(old & ~excepts);
184*0a6a1f1dSLionel Sambuc 	return old;
185*0a6a1f1dSLionel Sambuc #else
186*0a6a1f1dSLionel Sambuc 	int fpscr = armreg_fpscr_read();
187*0a6a1f1dSLionel Sambuc 	armreg_fpscr_write(fpscr & ~__SHIFTIN((excepts), VFP_FPSCR_ESUM));
188*0a6a1f1dSLionel Sambuc 	return __SHIFTOUT(fpscr, VFP_FPSCR_ESUM) & FE_ALL_EXCEPT;
189*0a6a1f1dSLionel Sambuc #endif
190*0a6a1f1dSLionel Sambuc }
191*0a6a1f1dSLionel Sambuc 
19284d9c625SLionel Sambuc /*
19384d9c625SLionel Sambuc  * The fetestexcept() function shall determine which of a specified subset of
19484d9c625SLionel Sambuc  * the floating-point exception flags are currently set. The excepts argument
19584d9c625SLionel Sambuc  * specifies the floating-point status flags to be queried.
19684d9c625SLionel Sambuc  */
19784d9c625SLionel Sambuc int
fetestexcept(int excepts)19884d9c625SLionel Sambuc fetestexcept(int excepts)
19984d9c625SLionel Sambuc {
200*0a6a1f1dSLionel Sambuc 	_DIAGASSERT((except & ~FE_ALL_EXCEPT) == 0);
20184d9c625SLionel Sambuc #ifdef __SOFTFP__
20284d9c625SLionel Sambuc 	return fpgetsticky() & excepts;
20384d9c625SLionel Sambuc #else
20484d9c625SLionel Sambuc 	return __SHIFTOUT(armreg_fpscr_read(), VFP_FPSCR_CSUM) & excepts;
20584d9c625SLionel Sambuc #endif
20684d9c625SLionel Sambuc }
20784d9c625SLionel Sambuc 
208*0a6a1f1dSLionel Sambuc int
fegetexcept(void)209*0a6a1f1dSLionel Sambuc fegetexcept(void)
210*0a6a1f1dSLionel Sambuc {
211*0a6a1f1dSLionel Sambuc #ifdef __SOFTFP__
212*0a6a1f1dSLionel Sambuc 	return fpgetmask();
213*0a6a1f1dSLionel Sambuc #else
214*0a6a1f1dSLionel Sambuc 	return __SHIFTOUT(armreg_fpscr_read(), VFP_FPSCR_ESUM);
215*0a6a1f1dSLionel Sambuc #endif
216*0a6a1f1dSLionel Sambuc }
217*0a6a1f1dSLionel Sambuc 
21884d9c625SLionel Sambuc /*
21984d9c625SLionel Sambuc  * The fegetround() function shall get the current rounding direction.
22084d9c625SLionel Sambuc  */
22184d9c625SLionel Sambuc int
fegetround(void)22284d9c625SLionel Sambuc fegetround(void)
22384d9c625SLionel Sambuc {
22484d9c625SLionel Sambuc #ifdef __SOFTFP__
22584d9c625SLionel Sambuc 	return fpgetround();
22684d9c625SLionel Sambuc #else
22784d9c625SLionel Sambuc 	return __SHIFTOUT(armreg_fpscr_read(), VFP_FPSCR_RMODE);
22884d9c625SLionel Sambuc #endif
22984d9c625SLionel Sambuc }
23084d9c625SLionel Sambuc 
23184d9c625SLionel Sambuc /*
23284d9c625SLionel Sambuc  * The fesetround() function shall establish the rounding direction represented
23384d9c625SLionel Sambuc  * by its argument round. If the argument is not equal to the value of a
23484d9c625SLionel Sambuc  * rounding direction macro, the rounding direction is not changed.
23584d9c625SLionel Sambuc  */
23684d9c625SLionel Sambuc int
fesetround(int round)23784d9c625SLionel Sambuc fesetround(int round)
23884d9c625SLionel Sambuc {
23984d9c625SLionel Sambuc #ifndef lint
24084d9c625SLionel Sambuc 	_DIAGASSERT(!(round & ~__SHIFTOUT(VFP_FPSCR_RMODE, VFP_FPSCR_RMODE)));
24184d9c625SLionel Sambuc #endif
24284d9c625SLionel Sambuc #ifdef __SOFTFP__
24384d9c625SLionel Sambuc 	(void)fpsetround(round);
24484d9c625SLionel Sambuc #else
24584d9c625SLionel Sambuc 	int fpscr = armreg_fpscr_read() & ~VFP_FPSCR_RMODE;
24684d9c625SLionel Sambuc 	fpscr |= __SHIFTIN(round, VFP_FPSCR_RMODE);
24784d9c625SLionel Sambuc 	armreg_fpscr_write(fpscr);
24884d9c625SLionel Sambuc #endif
24984d9c625SLionel Sambuc 	return 0;
25084d9c625SLionel Sambuc }
25184d9c625SLionel Sambuc 
25284d9c625SLionel Sambuc /*
25384d9c625SLionel Sambuc  * The fegetenv() function shall attempt to store the current floating-point
25484d9c625SLionel Sambuc  * environment in the object pointed to by envp.
25584d9c625SLionel Sambuc  */
25684d9c625SLionel Sambuc int
fegetenv(fenv_t * envp)25784d9c625SLionel Sambuc fegetenv(fenv_t *envp)
25884d9c625SLionel Sambuc {
25984d9c625SLionel Sambuc #ifdef __SOFTFP__
26084d9c625SLionel Sambuc 	*envp = __SHIFTIN(fpgetround(), VFP_FPSCR_RMODE)
26184d9c625SLionel Sambuc 	    | __SHIFTIN(fpgetmask(), VFP_FPSCR_ESUM)
26284d9c625SLionel Sambuc 	    | __SHIFTIN(fpgetsticky(), VFP_FPSCR_CSUM);
26384d9c625SLionel Sambuc #else
26484d9c625SLionel Sambuc 	*envp = armreg_fpscr_read();
26584d9c625SLionel Sambuc #endif
26684d9c625SLionel Sambuc 	return 0;
26784d9c625SLionel Sambuc }
26884d9c625SLionel Sambuc 
26984d9c625SLionel Sambuc /*
27084d9c625SLionel Sambuc  * The feholdexcept() function shall save the current floating-point
27184d9c625SLionel Sambuc  * environment in the object pointed to by envp, clear the floating-point
27284d9c625SLionel Sambuc  * status flags, and then install a non-stop (continue on floating-point
27384d9c625SLionel Sambuc  * exceptions) mode, if available, for all floating-point exceptions.
27484d9c625SLionel Sambuc  */
27584d9c625SLionel Sambuc int
feholdexcept(fenv_t * envp)27684d9c625SLionel Sambuc feholdexcept(fenv_t *envp)
27784d9c625SLionel Sambuc {
27884d9c625SLionel Sambuc #ifdef __SOFTFP__
27984d9c625SLionel Sambuc 	*envp = __SHIFTIN(fpgetround(), VFP_FPSCR_RMODE)
28084d9c625SLionel Sambuc 	    | __SHIFTIN(fpgetmask(), VFP_FPSCR_ESUM)
28184d9c625SLionel Sambuc 	    | __SHIFTIN(fpgetsticky(), VFP_FPSCR_CSUM);
28284d9c625SLionel Sambuc 	fpsetmask(0);
28384d9c625SLionel Sambuc 	fpsetsticky(0);
28484d9c625SLionel Sambuc #else
28584d9c625SLionel Sambuc 	*envp = armreg_fpscr_read();
28684d9c625SLionel Sambuc 	armreg_fpscr_write((*envp) & ~(VFP_FPSCR_ESUM|VFP_FPSCR_CSUM));
28784d9c625SLionel Sambuc #endif
28884d9c625SLionel Sambuc 	return 0;
28984d9c625SLionel Sambuc }
29084d9c625SLionel Sambuc 
29184d9c625SLionel Sambuc /*
29284d9c625SLionel Sambuc  * The fesetenv() function shall attempt to establish the floating-point
29384d9c625SLionel Sambuc  * environment represented by the object pointed to by envp. The fesetenv()
29484d9c625SLionel Sambuc  * function does not raise floating-point exceptions, but only installs the
29584d9c625SLionel Sambuc  * state of the floating-point status flags represented through its argument.
29684d9c625SLionel Sambuc  */
29784d9c625SLionel Sambuc int
fesetenv(const fenv_t * envp)29884d9c625SLionel Sambuc fesetenv(const fenv_t *envp)
29984d9c625SLionel Sambuc {
30084d9c625SLionel Sambuc #ifdef __SOFTFP__
30184d9c625SLionel Sambuc 	(void)fpsetround(__SHIFTIN(*envp, VFP_FPSCR_RMODE));
30284d9c625SLionel Sambuc 	(void)fpsetmask(__SHIFTOUT(*envp, VFP_FPSCR_ESUM));
30384d9c625SLionel Sambuc 	(void)fpsetsticky(__SHIFTOUT(*envp, VFP_FPSCR_CSUM));
30484d9c625SLionel Sambuc #else
30584d9c625SLionel Sambuc 	armreg_fpscr_write(*envp);
30684d9c625SLionel Sambuc #endif
30784d9c625SLionel Sambuc 	return 0;
30884d9c625SLionel Sambuc }
30984d9c625SLionel Sambuc 
31084d9c625SLionel Sambuc /*
31184d9c625SLionel Sambuc  * The feupdateenv() function shall attempt to save the currently raised
31284d9c625SLionel Sambuc  * floating-point exceptions in its automatic storage, attempt to install the
31384d9c625SLionel Sambuc  * floating-point environment represented by the object pointed to by envp,
31484d9c625SLionel Sambuc  * and then attempt to raise the saved floating-point exceptions.
31584d9c625SLionel Sambuc  */
31684d9c625SLionel Sambuc int
feupdateenv(const fenv_t * envp)31784d9c625SLionel Sambuc feupdateenv(const fenv_t *envp)
31884d9c625SLionel Sambuc {
31984d9c625SLionel Sambuc #ifndef lint
32084d9c625SLionel Sambuc 	_DIAGASSERT(envp != NULL);
32184d9c625SLionel Sambuc #endif
32284d9c625SLionel Sambuc #ifdef __SOFTFP__
32384d9c625SLionel Sambuc 	(void)fpsetround(__SHIFTIN(*envp, VFP_FPSCR_RMODE));
32484d9c625SLionel Sambuc 	(void)fpsetmask(fpgetmask() | __SHIFTOUT(*envp, VFP_FPSCR_ESUM));
32584d9c625SLionel Sambuc 	(void)fpsetsticky(fpgetsticky() | __SHIFTOUT(*envp, VFP_FPSCR_CSUM));
32684d9c625SLionel Sambuc #else
32784d9c625SLionel Sambuc 	int fpscr = armreg_fpscr_read() & ~(VFP_FPSCR_ESUM|VFP_FPSCR_CSUM);
32884d9c625SLionel Sambuc 	fpscr |= *envp;
32984d9c625SLionel Sambuc 	armreg_fpscr_write(fpscr);
33084d9c625SLionel Sambuc #endif
33184d9c625SLionel Sambuc 
33284d9c625SLionel Sambuc 	/* Success */
33384d9c625SLionel Sambuc 	return 0;
33484d9c625SLionel Sambuc }
335