105a0b428SJohn Marino /* $OpenBSD: fenv.c,v 1.4 2014/04/18 15:09:52 guenther Exp $ */
205a0b428SJohn Marino /* $NetBSD: fenv.c,v 1.1 2010/07/31 21:47:53 joerg Exp $ */
305a0b428SJohn Marino
405a0b428SJohn Marino /*-
505a0b428SJohn Marino * Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
605a0b428SJohn Marino * All rights reserved.
705a0b428SJohn Marino *
805a0b428SJohn Marino * Redistribution and use in source and binary forms, with or without
905a0b428SJohn Marino * modification, are permitted provided that the following conditions
1005a0b428SJohn Marino * are met:
1105a0b428SJohn Marino * 1. Redistributions of source code must retain the above copyright
1205a0b428SJohn Marino * notice, this list of conditions and the following disclaimer.
1305a0b428SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1405a0b428SJohn Marino * notice, this list of conditions and the following disclaimer in the
1505a0b428SJohn Marino * documentation and/or other materials provided with the distribution.
1605a0b428SJohn Marino *
1705a0b428SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1805a0b428SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1905a0b428SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2005a0b428SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2105a0b428SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2205a0b428SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2305a0b428SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2405a0b428SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2505a0b428SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2605a0b428SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2705a0b428SJohn Marino * SUCH DAMAGE.
2805a0b428SJohn Marino */
2905a0b428SJohn Marino
3005a0b428SJohn Marino #include <fenv.h>
3174b7c7a8SJohn Marino #include <machine/npx.h>
3205a0b428SJohn Marino
3305a0b428SJohn Marino /*
3405a0b428SJohn Marino * The following constant represents the default floating-point environment
3505a0b428SJohn Marino * (that is, the one installed at program startup) and has type pointer to
3605a0b428SJohn Marino * const-qualified fenv_t.
3705a0b428SJohn Marino *
3805a0b428SJohn Marino * It can be used as an argument to the functions within the <fenv.h> header
3905a0b428SJohn Marino * that manage the floating-point environment, namely fesetenv() and
4005a0b428SJohn Marino * feupdateenv().
4105a0b428SJohn Marino *
4205a0b428SJohn Marino * x87 fpu registers are 16bit wide. The upper bits, 31-16, are marked as
4305a0b428SJohn Marino * RESERVED.
4405a0b428SJohn Marino */
4505a0b428SJohn Marino fenv_t __fe_dfl_env = {
4605a0b428SJohn Marino {
47*dfbd0943SJohn Marino 0xffff0000 | __INITIAL_FPUCW__, /* Control word register */
4805a0b428SJohn Marino 0xffff0000, /* Status word register */
4905a0b428SJohn Marino 0xffffffff, /* Tag word register */
5005a0b428SJohn Marino {
5105a0b428SJohn Marino 0x00000000,
5205a0b428SJohn Marino 0x00000000,
5305a0b428SJohn Marino 0x00000000,
5405a0b428SJohn Marino 0xffff0000
5505a0b428SJohn Marino }
5605a0b428SJohn Marino },
5705a0b428SJohn Marino __INITIAL_MXCSR__ /* MXCSR register */
5805a0b428SJohn Marino };
5905a0b428SJohn Marino
6005a0b428SJohn Marino
6105a0b428SJohn Marino /*
6205a0b428SJohn Marino * The feclearexcept() function clears the supported floating-point exceptions
6305a0b428SJohn Marino * represented by `excepts'.
6405a0b428SJohn Marino */
6505a0b428SJohn Marino int
feclearexcept(int excepts)6605a0b428SJohn Marino feclearexcept(int excepts)
6705a0b428SJohn Marino {
6805a0b428SJohn Marino fenv_t fenv;
6905a0b428SJohn Marino unsigned int mxcsr;
7005a0b428SJohn Marino
7105a0b428SJohn Marino excepts &= FE_ALL_EXCEPT;
7205a0b428SJohn Marino
7305a0b428SJohn Marino /* Store the current x87 floating-point environment */
7405a0b428SJohn Marino __asm__ volatile ("fnstenv %0" : "=m" (fenv));
7505a0b428SJohn Marino
7605a0b428SJohn Marino /* Clear the requested floating-point exceptions */
7705a0b428SJohn Marino fenv.__x87.__status &= ~excepts;
7805a0b428SJohn Marino
7905a0b428SJohn Marino /* Load the x87 floating-point environent */
8005a0b428SJohn Marino __asm__ volatile ("fldenv %0" : : "m" (fenv));
8105a0b428SJohn Marino
8205a0b428SJohn Marino /* Same for SSE environment */
8305a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
8405a0b428SJohn Marino mxcsr &= ~excepts;
8505a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
8605a0b428SJohn Marino
8705a0b428SJohn Marino return (0);
8805a0b428SJohn Marino }
8905a0b428SJohn Marino
9005a0b428SJohn Marino /*
9105a0b428SJohn Marino * The fegetexceptflag() function stores an implementation-defined
9205a0b428SJohn Marino * representation of the states of the floating-point status flags indicated by
9305a0b428SJohn Marino * the argument excepts in the object pointed to by the argument flagp.
9405a0b428SJohn Marino */
9505a0b428SJohn Marino int
fegetexceptflag(fexcept_t * flagp,int excepts)9605a0b428SJohn Marino fegetexceptflag(fexcept_t *flagp, int excepts)
9705a0b428SJohn Marino {
9805a0b428SJohn Marino unsigned short status;
9905a0b428SJohn Marino unsigned int mxcsr;
10005a0b428SJohn Marino
10105a0b428SJohn Marino excepts &= FE_ALL_EXCEPT;
10205a0b428SJohn Marino
10305a0b428SJohn Marino /* Store the current x87 status register */
10405a0b428SJohn Marino __asm__ volatile ("fnstsw %0" : "=am" (status));
10505a0b428SJohn Marino
10605a0b428SJohn Marino /* Store the MXCSR register */
10705a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
10805a0b428SJohn Marino
10905a0b428SJohn Marino /* Store the results in flagp */
11005a0b428SJohn Marino *flagp = (status | mxcsr) & excepts;
11105a0b428SJohn Marino
11205a0b428SJohn Marino return (0);
11305a0b428SJohn Marino }
11405a0b428SJohn Marino
11505a0b428SJohn Marino /*
11605a0b428SJohn Marino * The feraiseexcept() function raises the supported floating-point exceptions
11705a0b428SJohn Marino * represented by the argument `excepts'.
11805a0b428SJohn Marino *
11905a0b428SJohn Marino * The standard explicitly allows us to execute an instruction that has the
12005a0b428SJohn Marino * exception as a side effect, but we choose to manipulate the status register
12105a0b428SJohn Marino * directly.
12205a0b428SJohn Marino *
12305a0b428SJohn Marino * The validation of input is being deferred to fesetexceptflag().
12405a0b428SJohn Marino */
12505a0b428SJohn Marino int
feraiseexcept(int excepts)12605a0b428SJohn Marino feraiseexcept(int excepts)
12705a0b428SJohn Marino {
12805a0b428SJohn Marino excepts &= FE_ALL_EXCEPT;
12905a0b428SJohn Marino
13005a0b428SJohn Marino fesetexceptflag((fexcept_t *)&excepts, excepts);
13105a0b428SJohn Marino __asm__ volatile ("fwait");
13205a0b428SJohn Marino
13305a0b428SJohn Marino return (0);
13405a0b428SJohn Marino }
13505a0b428SJohn Marino
13605a0b428SJohn Marino /*
13705a0b428SJohn Marino * This function sets the floating-point status flags indicated by the argument
13805a0b428SJohn Marino * `excepts' to the states stored in the object pointed to by `flagp'. It does
13905a0b428SJohn Marino * NOT raise any floating-point exceptions, but only sets the state of the flags.
14005a0b428SJohn Marino */
14105a0b428SJohn Marino int
fesetexceptflag(const fexcept_t * flagp,int excepts)14205a0b428SJohn Marino fesetexceptflag(const fexcept_t *flagp, int excepts)
14305a0b428SJohn Marino {
14405a0b428SJohn Marino fenv_t fenv;
14505a0b428SJohn Marino unsigned int mxcsr;
14605a0b428SJohn Marino
14705a0b428SJohn Marino excepts &= FE_ALL_EXCEPT;
14805a0b428SJohn Marino
14905a0b428SJohn Marino /* Store the current x87 floating-point environment */
15005a0b428SJohn Marino __asm__ volatile ("fnstenv %0" : "=m" (fenv));
15105a0b428SJohn Marino
15205a0b428SJohn Marino /* Set the requested status flags */
15305a0b428SJohn Marino fenv.__x87.__status &= ~excepts;
15405a0b428SJohn Marino fenv.__x87.__status |= *flagp & excepts;
15505a0b428SJohn Marino
15605a0b428SJohn Marino /* Load the x87 floating-point environent */
15705a0b428SJohn Marino __asm__ volatile ("fldenv %0" : : "m" (fenv));
15805a0b428SJohn Marino
15905a0b428SJohn Marino /* Same for SSE environment */
16005a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
16105a0b428SJohn Marino mxcsr &= ~excepts;
16205a0b428SJohn Marino mxcsr |= *flagp & excepts;
16305a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
16405a0b428SJohn Marino
16505a0b428SJohn Marino return (0);
16605a0b428SJohn Marino }
16705a0b428SJohn Marino
16805a0b428SJohn Marino /*
16905a0b428SJohn Marino * The fetestexcept() function determines which of a specified subset of the
17005a0b428SJohn Marino * floating-point exception flags are currently set. The `excepts' argument
17105a0b428SJohn Marino * specifies the floating-point status flags to be queried.
17205a0b428SJohn Marino */
17305a0b428SJohn Marino int
fetestexcept(int excepts)17405a0b428SJohn Marino fetestexcept(int excepts)
17505a0b428SJohn Marino {
17605a0b428SJohn Marino unsigned short status;
17705a0b428SJohn Marino unsigned int mxcsr;
17805a0b428SJohn Marino
17905a0b428SJohn Marino excepts &= FE_ALL_EXCEPT;
18005a0b428SJohn Marino
18105a0b428SJohn Marino /* Store the current x87 status register */
18205a0b428SJohn Marino __asm__ volatile ("fnstsw %0" : "=am" (status));
18305a0b428SJohn Marino
18405a0b428SJohn Marino /* Store the MXCSR register state */
18505a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
18605a0b428SJohn Marino
18705a0b428SJohn Marino return ((status | mxcsr) & excepts);
18805a0b428SJohn Marino }
18905a0b428SJohn Marino
19005a0b428SJohn Marino /*
19105a0b428SJohn Marino * The fegetround() function gets the current rounding direction.
19205a0b428SJohn Marino */
19305a0b428SJohn Marino int
fegetround(void)19405a0b428SJohn Marino fegetround(void)
19505a0b428SJohn Marino {
19605a0b428SJohn Marino unsigned short control;
19705a0b428SJohn Marino
19805a0b428SJohn Marino /*
19905a0b428SJohn Marino * We assume that the x87 and the SSE unit agree on the
20005a0b428SJohn Marino * rounding mode. Reading the control word on the x87 turns
20105a0b428SJohn Marino * out to be about 5 times faster than reading it on the SSE
20205a0b428SJohn Marino * unit on an Opteron 244.
20305a0b428SJohn Marino */
20405a0b428SJohn Marino __asm__ volatile ("fnstcw %0" : "=m" (control));
20505a0b428SJohn Marino
20605a0b428SJohn Marino return (control & _X87_ROUND_MASK);
20705a0b428SJohn Marino }
20805a0b428SJohn Marino
20905a0b428SJohn Marino /*
21005a0b428SJohn Marino * The fesetround() function establishes the rounding direction represented by
21105a0b428SJohn Marino * its argument `round'. If the argument is not equal to the value of a rounding
21205a0b428SJohn Marino * direction macro, the rounding direction is not changed.
21305a0b428SJohn Marino */
21405a0b428SJohn Marino int
fesetround(int round)21505a0b428SJohn Marino fesetround(int round)
21605a0b428SJohn Marino {
21705a0b428SJohn Marino unsigned short control;
21805a0b428SJohn Marino unsigned int mxcsr;
21905a0b428SJohn Marino
22005a0b428SJohn Marino /* Check whether requested rounding direction is supported */
22105a0b428SJohn Marino if (round & ~_X87_ROUND_MASK)
22205a0b428SJohn Marino return (-1);
22305a0b428SJohn Marino
22405a0b428SJohn Marino /* Store the current x87 control word register */
22505a0b428SJohn Marino __asm__ volatile ("fnstcw %0" : "=m" (control));
22605a0b428SJohn Marino
22705a0b428SJohn Marino /* Set the rounding direction */
22805a0b428SJohn Marino control &= ~_X87_ROUND_MASK;
22905a0b428SJohn Marino control |= round;
23005a0b428SJohn Marino
23105a0b428SJohn Marino /* Load the x87 control word register */
23205a0b428SJohn Marino __asm__ volatile ("fldcw %0" : : "m" (control));
23305a0b428SJohn Marino
23405a0b428SJohn Marino /* Same for the SSE environment */
23505a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
23605a0b428SJohn Marino mxcsr &= ~(_X87_ROUND_MASK << _SSE_ROUND_SHIFT);
23705a0b428SJohn Marino mxcsr |= round << _SSE_ROUND_SHIFT;
23805a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
23905a0b428SJohn Marino
24005a0b428SJohn Marino return (0);
24105a0b428SJohn Marino }
24205a0b428SJohn Marino
24305a0b428SJohn Marino /*
24405a0b428SJohn Marino * The fegetenv() function attempts to store the current floating-point
24505a0b428SJohn Marino * environment in the object pointed to by envp.
24605a0b428SJohn Marino */
24705a0b428SJohn Marino int
fegetenv(fenv_t * envp)24805a0b428SJohn Marino fegetenv(fenv_t *envp)
24905a0b428SJohn Marino {
25005a0b428SJohn Marino /* Store the current x87 floating-point environment */
25105a0b428SJohn Marino __asm__ volatile ("fnstenv %0" : "=m" (*envp));
25205a0b428SJohn Marino
25305a0b428SJohn Marino /* Store the MXCSR register state */
25405a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (envp->__mxcsr));
25505a0b428SJohn Marino
25605a0b428SJohn Marino /*
25705a0b428SJohn Marino * When an FNSTENV instruction is executed, all pending exceptions are
25805a0b428SJohn Marino * essentially lost (either the x87 FPU status register is cleared or
25905a0b428SJohn Marino * all exceptions are masked).
26005a0b428SJohn Marino *
26105a0b428SJohn Marino * 8.6 X87 FPU EXCEPTION SYNCHRONIZATION -
26205a0b428SJohn Marino * Intel(R) 64 and IA-32 Architectures Softare Developer's Manual - Vol1
26305a0b428SJohn Marino */
26405a0b428SJohn Marino __asm__ volatile ("fldcw %0" : : "m" (envp->__x87.__control));
26505a0b428SJohn Marino
26605a0b428SJohn Marino return (0);
26705a0b428SJohn Marino }
26805a0b428SJohn Marino
26905a0b428SJohn Marino /*
27005a0b428SJohn Marino * The feholdexcept() function saves the current floating-point environment
27105a0b428SJohn Marino * in the object pointed to by envp, clears the floating-point status flags, and
27205a0b428SJohn Marino * then installs a non-stop (continue on floating-point exceptions) mode, if
27305a0b428SJohn Marino * available, for all floating-point exceptions.
27405a0b428SJohn Marino */
27505a0b428SJohn Marino int
feholdexcept(fenv_t * envp)27605a0b428SJohn Marino feholdexcept(fenv_t *envp)
27705a0b428SJohn Marino {
27805a0b428SJohn Marino unsigned int mxcsr;
27905a0b428SJohn Marino
28005a0b428SJohn Marino /* Store the current x87 floating-point environment */
28105a0b428SJohn Marino __asm__ volatile ("fnstenv %0" : "=m" (*envp));
28205a0b428SJohn Marino
28305a0b428SJohn Marino /* Clear all exception flags in FPU */
28405a0b428SJohn Marino __asm__ volatile ("fnclex");
28505a0b428SJohn Marino
28605a0b428SJohn Marino /* Store the MXCSR register state */
28705a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (envp->__mxcsr));
28805a0b428SJohn Marino
28905a0b428SJohn Marino /* Clear exception flags in MXCSR */
29005a0b428SJohn Marino mxcsr = envp->__mxcsr;
29105a0b428SJohn Marino mxcsr &= ~FE_ALL_EXCEPT;
29205a0b428SJohn Marino
29305a0b428SJohn Marino /* Mask all exceptions */
29405a0b428SJohn Marino mxcsr |= FE_ALL_EXCEPT << _SSE_MASK_SHIFT;
29505a0b428SJohn Marino
29605a0b428SJohn Marino /* Store the MXCSR register */
29705a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
29805a0b428SJohn Marino
29905a0b428SJohn Marino return (0);
30005a0b428SJohn Marino }
30105a0b428SJohn Marino
30205a0b428SJohn Marino /*
30305a0b428SJohn Marino * The fesetenv() function attempts to establish the floating-point environment
30405a0b428SJohn Marino * represented by the object pointed to by envp. The argument `envp' points
30505a0b428SJohn Marino * to an object set by a call to fegetenv() or feholdexcept(), or equal a
30605a0b428SJohn Marino * floating-point environment macro. The fesetenv() function does not raise
30705a0b428SJohn Marino * floating-point exceptions, but only installs the state of the floating-point
30805a0b428SJohn Marino * status flags represented through its argument.
30905a0b428SJohn Marino */
31005a0b428SJohn Marino int
fesetenv(const fenv_t * envp)31105a0b428SJohn Marino fesetenv(const fenv_t *envp)
31205a0b428SJohn Marino {
31305a0b428SJohn Marino /* Load the x87 floating-point environent */
31405a0b428SJohn Marino __asm__ volatile ("fldenv %0" : : "m" (*envp));
31505a0b428SJohn Marino
31605a0b428SJohn Marino /* Store the MXCSR register */
31705a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (envp->__mxcsr));
31805a0b428SJohn Marino
31905a0b428SJohn Marino return (0);
32005a0b428SJohn Marino }
32105a0b428SJohn Marino
32205a0b428SJohn Marino /*
32305a0b428SJohn Marino * The feupdateenv() function saves the currently raised floating-point
32405a0b428SJohn Marino * exceptions in its automatic storage, installs the floating-point environment
32505a0b428SJohn Marino * represented by the object pointed to by `envp', and then raises the saved
32605a0b428SJohn Marino * floating-point exceptions. The argument `envp' shall point to an object set
32705a0b428SJohn Marino * by a call to feholdexcept() or fegetenv(), or equal a floating-point
32805a0b428SJohn Marino * environment macro.
32905a0b428SJohn Marino */
33005a0b428SJohn Marino int
feupdateenv(const fenv_t * envp)33105a0b428SJohn Marino feupdateenv(const fenv_t *envp)
33205a0b428SJohn Marino {
33305a0b428SJohn Marino unsigned short status;
33405a0b428SJohn Marino unsigned int mxcsr;
33505a0b428SJohn Marino
33605a0b428SJohn Marino /* Store the x87 status register */
33705a0b428SJohn Marino __asm__ volatile ("fnstsw %0" : "=am" (status));
33805a0b428SJohn Marino
33905a0b428SJohn Marino /* Store the MXCSR register */
34005a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
34105a0b428SJohn Marino
34205a0b428SJohn Marino /* Install new floating-point environment */
34305a0b428SJohn Marino fesetenv(envp);
34405a0b428SJohn Marino
34505a0b428SJohn Marino /* Raise any previously accumulated exceptions */
34605a0b428SJohn Marino feraiseexcept(status | mxcsr);
34705a0b428SJohn Marino
34805a0b428SJohn Marino return (0);
34905a0b428SJohn Marino }
35005a0b428SJohn Marino
35105a0b428SJohn Marino /*
35205a0b428SJohn Marino * The following functions are extentions to the standard
35305a0b428SJohn Marino */
35405a0b428SJohn Marino int
feenableexcept(int mask)35505a0b428SJohn Marino feenableexcept(int mask)
35605a0b428SJohn Marino {
35705a0b428SJohn Marino unsigned int mxcsr, omask;
35805a0b428SJohn Marino unsigned short control;
35905a0b428SJohn Marino
36005a0b428SJohn Marino mask &= FE_ALL_EXCEPT;
36105a0b428SJohn Marino
36205a0b428SJohn Marino __asm__ volatile ("fnstcw %0" : "=m" (control));
36305a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
36405a0b428SJohn Marino
36505a0b428SJohn Marino omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
36605a0b428SJohn Marino control &= ~mask;
36705a0b428SJohn Marino __asm__ volatile ("fldcw %0" : : "m" (control));
36805a0b428SJohn Marino
36905a0b428SJohn Marino mxcsr &= ~(mask << _SSE_MASK_SHIFT);
37005a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
37105a0b428SJohn Marino
37205a0b428SJohn Marino return (omask);
37305a0b428SJohn Marino }
37405a0b428SJohn Marino
37505a0b428SJohn Marino int
fedisableexcept(int mask)37605a0b428SJohn Marino fedisableexcept(int mask)
37705a0b428SJohn Marino {
37805a0b428SJohn Marino unsigned int mxcsr, omask;
37905a0b428SJohn Marino unsigned short control;
38005a0b428SJohn Marino
38105a0b428SJohn Marino mask &= FE_ALL_EXCEPT;
38205a0b428SJohn Marino
38305a0b428SJohn Marino __asm__ volatile ("fnstcw %0" : "=m" (control));
38405a0b428SJohn Marino __asm__ volatile ("stmxcsr %0" : "=m" (mxcsr));
38505a0b428SJohn Marino
38605a0b428SJohn Marino omask = ~(control | (mxcsr >> _SSE_MASK_SHIFT)) & FE_ALL_EXCEPT;
38705a0b428SJohn Marino control |= mask;
38805a0b428SJohn Marino __asm__ volatile ("fldcw %0" : : "m" (control));
38905a0b428SJohn Marino
39005a0b428SJohn Marino mxcsr |= mask << _SSE_MASK_SHIFT;
39105a0b428SJohn Marino __asm__ volatile ("ldmxcsr %0" : : "m" (mxcsr));
39205a0b428SJohn Marino
39305a0b428SJohn Marino return (omask);
39405a0b428SJohn Marino }
39505a0b428SJohn Marino
39605a0b428SJohn Marino int
fegetexcept(void)39705a0b428SJohn Marino fegetexcept(void)
39805a0b428SJohn Marino {
39905a0b428SJohn Marino unsigned short control;
40005a0b428SJohn Marino
40105a0b428SJohn Marino /*
40205a0b428SJohn Marino * We assume that the masks for the x87 and the SSE unit are
40305a0b428SJohn Marino * the same.
40405a0b428SJohn Marino */
40505a0b428SJohn Marino __asm__ volatile ("fnstcw %0" : "=m" (control));
40605a0b428SJohn Marino
40705a0b428SJohn Marino return (~control & FE_ALL_EXCEPT);
40805a0b428SJohn Marino }
409