1*2c53affbSjmc /* $OpenBSD: fenv.c,v 1.4 2022/12/27 17:10:07 jmc Exp $ */
275e8f644Sdrahn /*-
375e8f644Sdrahn * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
475e8f644Sdrahn * All rights reserved.
575e8f644Sdrahn *
675e8f644Sdrahn * Redistribution and use in source and binary forms, with or without
775e8f644Sdrahn * modification, are permitted provided that the following conditions
875e8f644Sdrahn * are met:
975e8f644Sdrahn * 1. Redistributions of source code must retain the above copyright
1075e8f644Sdrahn * notice, this list of conditions and the following disclaimer.
1175e8f644Sdrahn * 2. Redistributions in binary form must reproduce the above copyright
1275e8f644Sdrahn * notice, this list of conditions and the following disclaimer in the
1375e8f644Sdrahn * documentation and/or other materials provided with the distribution.
1475e8f644Sdrahn *
1575e8f644Sdrahn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1675e8f644Sdrahn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1775e8f644Sdrahn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1875e8f644Sdrahn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1975e8f644Sdrahn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2075e8f644Sdrahn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2175e8f644Sdrahn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2275e8f644Sdrahn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2375e8f644Sdrahn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2475e8f644Sdrahn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2575e8f644Sdrahn * SUCH DAMAGE.
2675e8f644Sdrahn *
2775e8f644Sdrahn * $FreeBSD: head/lib/msun/aarch64/fenv.h 280857 2015-03-30 16:42:08Z emaste $
2875e8f644Sdrahn */
2975e8f644Sdrahn
3075e8f644Sdrahn #include <fenv.h>
3175e8f644Sdrahn #include <machine/ieeefp.h>
3275e8f644Sdrahn
3375e8f644Sdrahn #define __get_fcsr(r) asm volatile("frcsr %0" : "=r" (r))
3475e8f644Sdrahn #define __set_fcsr(r) asm volatile("fscsr %0" : "+r" (r))
3575e8f644Sdrahn #define __get_flags(r) asm volatile("frflags %0" : "=r" (r))
3675e8f644Sdrahn #define __set_flags(r) asm volatile("fsflags %0" : "+r" (r))
3775e8f644Sdrahn #define __get_frm(r) asm volatile("frrm %0" : "=r" (r))
3875e8f644Sdrahn #define __set_frm(r) asm volatile("fsrm %0" : "+r"(r) )
3975e8f644Sdrahn
4075e8f644Sdrahn /*
4175e8f644Sdrahn * The following constant represents the default floating-point environment
4275e8f644Sdrahn * (that is, the one installed at program startup) and has type pointer to
4375e8f644Sdrahn * const-qualified fenv_t.
4475e8f644Sdrahn *
4575e8f644Sdrahn * It can be used as an argument to the functions within the <fenv.h> header
4675e8f644Sdrahn * that manage the floating-point environment, namely fesetenv() and
4775e8f644Sdrahn * feupdateenv().
4875e8f644Sdrahn */
4975e8f644Sdrahn fenv_t __fe_dfl_env = 0;
5075e8f644Sdrahn
5175e8f644Sdrahn /*
5275e8f644Sdrahn * The feclearexcept() function clears the supported floating-point exceptions
5375e8f644Sdrahn * represented by `excepts'.
5475e8f644Sdrahn */
5575e8f644Sdrahn int
feclearexcept(int excepts)5675e8f644Sdrahn feclearexcept(int excepts)
5775e8f644Sdrahn {
5875e8f644Sdrahn fexcept_t r;
5975e8f644Sdrahn
6075e8f644Sdrahn excepts &= FE_ALL_EXCEPT;
6175e8f644Sdrahn __get_flags(r);
6275e8f644Sdrahn r &= ~excepts;
6375e8f644Sdrahn __set_flags(r);
6475e8f644Sdrahn return (0);
6575e8f644Sdrahn }
6675e8f644Sdrahn DEF_STD(feclearexcept);
6775e8f644Sdrahn
6875e8f644Sdrahn /*
6975e8f644Sdrahn * The fegetexceptflag() function stores an implementation-defined
7075e8f644Sdrahn * representation of the states of the floating-point status flags indicated by
7175e8f644Sdrahn * the argument excepts in the object pointed to by the argument flagp.
7275e8f644Sdrahn */
7375e8f644Sdrahn int
fegetexceptflag(fexcept_t * flagp,int excepts)7475e8f644Sdrahn fegetexceptflag(fexcept_t *flagp, int excepts)
7575e8f644Sdrahn {
7675e8f644Sdrahn fexcept_t r;
7775e8f644Sdrahn
7875e8f644Sdrahn excepts &= FE_ALL_EXCEPT;
7975e8f644Sdrahn __get_flags(r);
8075e8f644Sdrahn *flagp = r & excepts;
8175e8f644Sdrahn return (0);
8275e8f644Sdrahn }
8375e8f644Sdrahn
8475e8f644Sdrahn /*
8575e8f644Sdrahn * The feraiseexcept() function raises the supported floating-point exceptions
8675e8f644Sdrahn * represented by the argument `excepts'.
8775e8f644Sdrahn */
8875e8f644Sdrahn int
feraiseexcept(int excepts)8975e8f644Sdrahn feraiseexcept(int excepts)
9075e8f644Sdrahn {
9175e8f644Sdrahn fexcept_t r;
9275e8f644Sdrahn
9375e8f644Sdrahn excepts &= FE_ALL_EXCEPT;
9475e8f644Sdrahn __get_flags(r);
9575e8f644Sdrahn r |= excepts;
9675e8f644Sdrahn __set_flags(r);
9775e8f644Sdrahn return (0);
9875e8f644Sdrahn }
9975e8f644Sdrahn DEF_STD(feraiseexcept);
10075e8f644Sdrahn
10175e8f644Sdrahn /*
10275e8f644Sdrahn * This function sets the floating-point status flags indicated by the argument
10375e8f644Sdrahn * `excepts' to the states stored in the object pointed to by `flagp'. It does
10475e8f644Sdrahn * NOT raise any floating-point exceptions, but only sets the state of the flags.
10575e8f644Sdrahn */
10675e8f644Sdrahn int
fesetexceptflag(const fexcept_t * flagp,int excepts)10775e8f644Sdrahn fesetexceptflag(const fexcept_t *flagp, int excepts)
10875e8f644Sdrahn {
10975e8f644Sdrahn fexcept_t r;
11075e8f644Sdrahn
11175e8f644Sdrahn excepts &= FE_ALL_EXCEPT;
11275e8f644Sdrahn __get_flags(r);
11375e8f644Sdrahn r &= ~excepts;
11475e8f644Sdrahn r |= *flagp & excepts;
11575e8f644Sdrahn __set_flags(r);
11675e8f644Sdrahn return (0);
11775e8f644Sdrahn }
11875e8f644Sdrahn DEF_STD(fesetexceptflag);
11975e8f644Sdrahn
12075e8f644Sdrahn /*
12175e8f644Sdrahn * The fetestexcept() function determines which of a specified subset of the
12275e8f644Sdrahn * floating-point exception flags are currently set. The `excepts' argument
12375e8f644Sdrahn * specifies the floating-point status flags to be queried.
12475e8f644Sdrahn */
12575e8f644Sdrahn int
fetestexcept(int excepts)12675e8f644Sdrahn fetestexcept(int excepts)
12775e8f644Sdrahn {
12875e8f644Sdrahn fexcept_t r;
12975e8f644Sdrahn
13075e8f644Sdrahn excepts &= FE_ALL_EXCEPT;
13175e8f644Sdrahn __get_flags(r);
13275e8f644Sdrahn return (r & excepts);
13375e8f644Sdrahn }
13475e8f644Sdrahn DEF_STD(fetestexcept);
13575e8f644Sdrahn
13675e8f644Sdrahn /*
13775e8f644Sdrahn * The fegetround() function gets the current rounding direction.
13875e8f644Sdrahn */
13975e8f644Sdrahn int
fegetround(void)14075e8f644Sdrahn fegetround(void)
14175e8f644Sdrahn {
14275e8f644Sdrahn fenv_t r;
14375e8f644Sdrahn
14475e8f644Sdrahn __get_frm(r);
145a3d93523Sjsg return (r & _ROUND_MASK);
14675e8f644Sdrahn }
14775e8f644Sdrahn DEF_STD(fegetround);
14875e8f644Sdrahn
14975e8f644Sdrahn /*
15075e8f644Sdrahn * The fesetround() function establishes the rounding direction represented by
15175e8f644Sdrahn * its argument `round'. If the argument is not equal to the value of a rounding
15275e8f644Sdrahn * direction macro, the rounding direction is not changed.
15375e8f644Sdrahn */
15475e8f644Sdrahn int
fesetround(int round)15575e8f644Sdrahn fesetround(int round)
15675e8f644Sdrahn {
15775e8f644Sdrahn fenv_t r;
15875e8f644Sdrahn
15975e8f644Sdrahn if (round & ~_ROUND_MASK)
16075e8f644Sdrahn return (-1);
16175e8f644Sdrahn __set_frm(round);
16275e8f644Sdrahn return (0);
16375e8f644Sdrahn }
16475e8f644Sdrahn DEF_STD(fesetround);
16575e8f644Sdrahn
16675e8f644Sdrahn /*
16775e8f644Sdrahn * The fegetenv() function attempts to store the current floating-point
16875e8f644Sdrahn * environment in the object pointed to by envp.
16975e8f644Sdrahn */
17075e8f644Sdrahn int
fegetenv(fenv_t * envp)17175e8f644Sdrahn fegetenv(fenv_t *envp)
17275e8f644Sdrahn {
17375e8f644Sdrahn fenv_t r;
17475e8f644Sdrahn
17575e8f644Sdrahn __get_fcsr(r);
17675e8f644Sdrahn *envp = r;
17775e8f644Sdrahn
17875e8f644Sdrahn return (0);
17975e8f644Sdrahn }
18075e8f644Sdrahn DEF_STD(fegetenv);
18175e8f644Sdrahn
18275e8f644Sdrahn /*
18375e8f644Sdrahn * The feholdexcept() function saves the current floating-point environment
18475e8f644Sdrahn * in the object pointed to by envp, clears the floating-point status flags, and
18575e8f644Sdrahn * then installs a non-stop (continue on floating-point exceptions) mode, if
18675e8f644Sdrahn * available, for all floating-point exceptions.
18775e8f644Sdrahn */
18875e8f644Sdrahn int
feholdexcept(fenv_t * envp)18975e8f644Sdrahn feholdexcept(fenv_t *envp)
19075e8f644Sdrahn {
19175e8f644Sdrahn fenv_t r;
19275e8f644Sdrahn
19375e8f644Sdrahn __get_fcsr(r);
19475e8f644Sdrahn *envp = r;
1958397e332Sjsg r &= ~FE_ALL_EXCEPT;
19675e8f644Sdrahn __set_fcsr(r);
19775e8f644Sdrahn
19875e8f644Sdrahn return (0);
19975e8f644Sdrahn }
20075e8f644Sdrahn DEF_STD(feholdexcept);
20175e8f644Sdrahn
20275e8f644Sdrahn /*
20375e8f644Sdrahn * The fesetenv() function attempts to establish the floating-point environment
20475e8f644Sdrahn * represented by the object pointed to by envp. The argument `envp' points
20575e8f644Sdrahn * to an object set by a call to fegetenv() or feholdexcept(), or equal a
20675e8f644Sdrahn * floating-point environment macro. The fesetenv() function does not raise
20775e8f644Sdrahn * floating-point exceptions, but only installs the state of the floating-point
20875e8f644Sdrahn * status flags represented through its argument.
20975e8f644Sdrahn */
21075e8f644Sdrahn int
fesetenv(const fenv_t * envp)21175e8f644Sdrahn fesetenv(const fenv_t *envp)
21275e8f644Sdrahn {
21375e8f644Sdrahn
21475e8f644Sdrahn fenv_t r;
21575e8f644Sdrahn r = *envp;
21675e8f644Sdrahn __set_fcsr(r);
21775e8f644Sdrahn return (0);
21875e8f644Sdrahn }
21975e8f644Sdrahn DEF_STD(fesetenv);
22075e8f644Sdrahn
22175e8f644Sdrahn /*
22275e8f644Sdrahn * The feupdateenv() function saves the currently raised floating-point
22375e8f644Sdrahn * exceptions in its automatic storage, installs the floating-point environment
22475e8f644Sdrahn * represented by the object pointed to by `envp', and then raises the saved
22575e8f644Sdrahn * floating-point exceptions. The argument `envp' shall point to an object set
22675e8f644Sdrahn * by a call to feholdexcept() or fegetenv(), or equal a floating-point
22775e8f644Sdrahn * environment macro.
22875e8f644Sdrahn */
22975e8f644Sdrahn int
feupdateenv(const fenv_t * envp)23075e8f644Sdrahn feupdateenv(const fenv_t *envp)
23175e8f644Sdrahn {
23275e8f644Sdrahn fexcept_t r;
23375e8f644Sdrahn
23475e8f644Sdrahn __get_fcsr(r);
23575e8f644Sdrahn fesetenv(envp);
23675e8f644Sdrahn feraiseexcept(r & FE_ALL_EXCEPT);
23775e8f644Sdrahn return (0);
23875e8f644Sdrahn }
23975e8f644Sdrahn DEF_STD(feupdateenv);
24075e8f644Sdrahn
24175e8f644Sdrahn /*
242*2c53affbSjmc * The following functions are extensions to the standard
24375e8f644Sdrahn */
24475e8f644Sdrahn int
feenableexcept(int mask)24575e8f644Sdrahn feenableexcept(int mask)
24675e8f644Sdrahn {
24775e8f644Sdrahn return -1;
24875e8f644Sdrahn }
24975e8f644Sdrahn
25075e8f644Sdrahn int
fedisableexcept(int mask)25175e8f644Sdrahn fedisableexcept(int mask)
25275e8f644Sdrahn {
25375e8f644Sdrahn return 0;
25475e8f644Sdrahn }
25575e8f644Sdrahn
25675e8f644Sdrahn int
fegetexcept(void)25775e8f644Sdrahn fegetexcept(void)
25875e8f644Sdrahn {
25975e8f644Sdrahn return 0;
26075e8f644Sdrahn }
261