xref: /openbsd-src/lib/libm/arch/riscv64/fenv.c (revision 2c53affbcc0119d6480b86c18f2790523b6a0aad)
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