xref: /openbsd/lib/libm/arch/riscv64/fenv.c (revision 2c53affb)
1 /* $OpenBSD: fenv.c,v 1.4 2022/12/27 17:10:07 jmc Exp $ */
2 /*-
3  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: head/lib/msun/aarch64/fenv.h 280857 2015-03-30 16:42:08Z emaste $
28  */
29 
30 #include <fenv.h>
31 #include <machine/ieeefp.h>
32 
33 #define	__get_fcsr(r)	asm volatile("frcsr %0" : "=r" (r))
34 #define	__set_fcsr(r)	asm volatile("fscsr %0" : "+r" (r))
35 #define	__get_flags(r)	asm volatile("frflags %0" : "=r" (r))
36 #define	__set_flags(r)	asm volatile("fsflags %0" : "+r" (r))
37 #define	__get_frm(r)	asm volatile("frrm %0" : "=r" (r))
38 #define	__set_frm(r)	asm volatile("fsrm %0" : "+r"(r) )
39 
40 /*
41  * The following constant represents the default floating-point environment
42  * (that is, the one installed at program startup) and has type pointer to
43  * const-qualified fenv_t.
44  *
45  * It can be used as an argument to the functions within the <fenv.h> header
46  * that manage the floating-point environment, namely fesetenv() and
47  * feupdateenv().
48  */
49 fenv_t __fe_dfl_env = 0;
50 
51 /*
52  * The feclearexcept() function clears the supported floating-point exceptions
53  * represented by `excepts'.
54  */
55 int
feclearexcept(int excepts)56 feclearexcept(int excepts)
57 {
58 	fexcept_t r;
59 
60 	excepts &= FE_ALL_EXCEPT;
61 	__get_flags(r);
62 	r &= ~excepts;
63 	__set_flags(r);
64 	return (0);
65 }
66 DEF_STD(feclearexcept);
67 
68 /*
69  * The fegetexceptflag() function stores an implementation-defined
70  * representation of the states of the floating-point status flags indicated by
71  * the argument excepts in the object pointed to by the argument flagp.
72  */
73 int
fegetexceptflag(fexcept_t * flagp,int excepts)74 fegetexceptflag(fexcept_t *flagp, int excepts)
75 {
76 	fexcept_t r;
77 
78 	excepts &= FE_ALL_EXCEPT;
79 	__get_flags(r);
80 	*flagp = r & excepts;
81 	return (0);
82 }
83 
84 /*
85  * The feraiseexcept() function raises the supported floating-point exceptions
86  * represented by the argument `excepts'.
87  */
88 int
feraiseexcept(int excepts)89 feraiseexcept(int excepts)
90 {
91 	fexcept_t r;
92 
93 	excepts &= FE_ALL_EXCEPT;
94 	__get_flags(r);
95 	r |= excepts;
96 	__set_flags(r);
97 	return (0);
98 }
99 DEF_STD(feraiseexcept);
100 
101 /*
102  * This function sets the floating-point status flags indicated by the argument
103  * `excepts' to the states stored in the object pointed to by `flagp'. It does
104  * NOT raise any floating-point exceptions, but only sets the state of the flags.
105  */
106 int
fesetexceptflag(const fexcept_t * flagp,int excepts)107 fesetexceptflag(const fexcept_t *flagp, int excepts)
108 {
109 	fexcept_t r;
110 
111 	excepts &= FE_ALL_EXCEPT;
112 	__get_flags(r);
113 	r &= ~excepts;
114 	r |= *flagp & excepts;
115 	__set_flags(r);
116 	return (0);
117 }
118 DEF_STD(fesetexceptflag);
119 
120 /*
121  * The fetestexcept() function determines which of a specified subset of the
122  * floating-point exception flags are currently set. The `excepts' argument
123  * specifies the floating-point status flags to be queried.
124  */
125 int
fetestexcept(int excepts)126 fetestexcept(int excepts)
127 {
128 	fexcept_t r;
129 
130 	excepts &= FE_ALL_EXCEPT;
131 	__get_flags(r);
132 	return (r & excepts);
133 }
134 DEF_STD(fetestexcept);
135 
136 /*
137  * The fegetround() function gets the current rounding direction.
138  */
139 int
fegetround(void)140 fegetround(void)
141 {
142 	fenv_t r;
143 
144 	__get_frm(r);
145 	return (r & _ROUND_MASK);
146 }
147 DEF_STD(fegetround);
148 
149 /*
150  * The fesetround() function establishes the rounding direction represented by
151  * its argument `round'. If the argument is not equal to the value of a rounding
152  * direction macro, the rounding direction is not changed.
153  */
154 int
fesetround(int round)155 fesetround(int round)
156 {
157 	fenv_t r;
158 
159 	if (round & ~_ROUND_MASK)
160 		return (-1);
161 	__set_frm(round);
162 	return (0);
163 }
164 DEF_STD(fesetround);
165 
166 /*
167  * The fegetenv() function attempts to store the current floating-point
168  * environment in the object pointed to by envp.
169  */
170 int
fegetenv(fenv_t * envp)171 fegetenv(fenv_t *envp)
172 {
173 	fenv_t r;
174 
175 	__get_fcsr(r);
176 	*envp = r;
177 
178 	return (0);
179 }
180 DEF_STD(fegetenv);
181 
182 /*
183  * The feholdexcept() function saves the current floating-point environment
184  * in the object pointed to by envp, clears the floating-point status flags, and
185  * then installs a non-stop (continue on floating-point exceptions) mode, if
186  * available, for all floating-point exceptions.
187  */
188 int
feholdexcept(fenv_t * envp)189 feholdexcept(fenv_t *envp)
190 {
191 	fenv_t r;
192 
193 	__get_fcsr(r);
194 	*envp  = r;
195 	r &= ~FE_ALL_EXCEPT;
196 	__set_fcsr(r);
197 
198 	return (0);
199 }
200 DEF_STD(feholdexcept);
201 
202 /*
203  * The fesetenv() function attempts to establish the floating-point environment
204  * represented by the object pointed to by envp. The argument `envp' points
205  * to an object set by a call to fegetenv() or feholdexcept(), or equal a
206  * floating-point environment macro. The fesetenv() function does not raise
207  * floating-point exceptions, but only installs the state of the floating-point
208  * status flags represented through its argument.
209  */
210 int
fesetenv(const fenv_t * envp)211 fesetenv(const fenv_t *envp)
212 {
213 
214 	fenv_t r;
215 	r = *envp;
216 	__set_fcsr(r);
217 	return (0);
218 }
219 DEF_STD(fesetenv);
220 
221 /*
222  * The feupdateenv() function saves the currently raised floating-point
223  * exceptions in its automatic storage, installs the floating-point environment
224  * represented by the object pointed to by `envp', and then raises the saved
225  * floating-point exceptions. The argument `envp' shall point to an object set
226  * by a call to feholdexcept() or fegetenv(), or equal a floating-point
227  * environment macro.
228  */
229 int
feupdateenv(const fenv_t * envp)230 feupdateenv(const fenv_t *envp)
231 {
232 	fexcept_t r;
233 
234 	__get_fcsr(r);
235 	fesetenv(envp);
236 	feraiseexcept(r & FE_ALL_EXCEPT);
237 	return (0);
238 }
239 DEF_STD(feupdateenv);
240 
241 /*
242  * The following functions are extensions to the standard
243  */
244 int
feenableexcept(int mask)245 feenableexcept(int mask)
246 {
247 	return -1;
248 }
249 
250 int
fedisableexcept(int mask)251 fedisableexcept(int mask)
252 {
253 	return 0;
254 }
255 
256 int
fegetexcept(void)257 fegetexcept(void)
258 {
259 	return 0;
260 }
261