1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 __declare_fenv_inline(int)
feclearexcept(int excepts)32 feclearexcept(int excepts)
33 {
34 	union __fpscr __r;
35 
36 	if (excepts & FE_INVALID)
37 		excepts |= FE_ALL_INVALID;
38 	__mffs(&__r);
39 	__r.__bits.__reg &= ~excepts;
40 	__mtfsf(__r);
41 	return (0);
42 }
43 
44 
45 __declare_fenv_inline(int)
fegetexceptflag(fexcept_t * flagp,int excepts)46 fegetexceptflag(fexcept_t *flagp, int excepts)
47 {
48 	union __fpscr __r;
49 
50 	__mffs(&__r);
51 	*flagp = __r.__bits.__reg & excepts;
52 	return (0);
53 }
54 
55 __declare_fenv_inline(int)
fesetexceptflag(const fexcept_t * flagp,int excepts)56 fesetexceptflag(const fexcept_t *flagp, int excepts)
57 {
58 	union __fpscr __r;
59 
60 	if (excepts & FE_INVALID)
61 		excepts |= FE_ALL_EXCEPT;
62 	__mffs(&__r);
63 	__r.__bits.__reg &= ~excepts;
64 	__r.__bits.__reg |= *flagp & excepts;
65 	__mtfsf(__r);
66 	return (0);
67 }
68 
69 __declare_fenv_inline(int)
feraiseexcept(int excepts)70 feraiseexcept(int excepts)
71 {
72 	union __fpscr __r;
73 
74 	if (excepts & FE_INVALID)
75 		excepts |= FE_VXSOFT;
76 	__mffs(&__r);
77 	__r.__bits.__reg |= excepts;
78 	__mtfsf(__r);
79 	return (0);
80 }
81 
82 __declare_fenv_inline(int)
fesetexcept(int excepts)83 fesetexcept(int excepts)
84 {
85         return feraiseexcept(excepts);
86 }
87 
88 __declare_fenv_inline(int)
fetestexcept(int excepts)89 fetestexcept(int excepts)
90 {
91 	union __fpscr __r;
92 
93 	__mffs(&__r);
94 	return (__r.__bits.__reg & excepts);
95 }
96 
97 __declare_fenv_inline(int)
fegetround(void)98 fegetround(void)
99 {
100 	union __fpscr __r;
101 
102 	__mffs(&__r);
103 	return (__r.__bits.__reg & _ROUND_MASK);
104 }
105 
106 __declare_fenv_inline(int)
fesetround(int rounding_mode)107 fesetround(int rounding_mode)
108 {
109 	union __fpscr __r;
110 
111 	if (rounding_mode & ~_ROUND_MASK)
112 		return (-1);
113 	__mffs(&__r);
114 	__r.__bits.__reg &= ~_ROUND_MASK;
115 	__r.__bits.__reg |= rounding_mode;
116 	__mtfsf(__r);
117 	return (0);
118 }
119 
120 __declare_fenv_inline(int)
fegetenv(fenv_t * envp)121 fegetenv(fenv_t *envp)
122 {
123 	union __fpscr __r;
124 
125 	__mffs(&__r);
126 	*envp = __r.__bits.__reg;
127 	return (0);
128 }
129 
130 __declare_fenv_inline(int)
feholdexcept(fenv_t * envp)131 feholdexcept(fenv_t *envp)
132 {
133 	union __fpscr __r;
134 
135 	__mffs(&__r);
136 	*envp = __r.__bits.__reg;
137 	__r.__bits.__reg &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
138 	__mtfsf(__r);
139 	return (0);
140 }
141 
142 __declare_fenv_inline(int)
fesetenv(const fenv_t * envp)143 fesetenv(const fenv_t *envp)
144 {
145 	union __fpscr __r;
146 
147 	__r.__bits.__reg = *envp;
148 	__mtfsf(__r);
149 	return (0);
150 }
151 
152 __declare_fenv_inline(int)
feupdateenv(const fenv_t * envp)153 feupdateenv(const fenv_t *envp)
154 {
155 	union __fpscr __r;
156 
157 	__mffs(&__r);
158 	__r.__bits.__reg &= FE_ALL_EXCEPT;
159 	__r.__bits.__reg |= *envp;
160 	__mtfsf(__r);
161 	return (0);
162 }
163 
164 #if __BSD_VISIBLE
165 
166 __declare_fenv_inline(int)
feenableexcept(int __mask)167 feenableexcept(int __mask)
168 {
169 	union __fpscr __r;
170 	fenv_t __oldmask;
171 
172 	__mffs(&__r);
173 	__oldmask = __r.__bits.__reg;
174 	__r.__bits.__reg |= (__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT;
175 	__mtfsf(__r);
176 	return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
177 }
178 
179 __declare_fenv_inline(int)
fedisableexcept(int __mask)180 fedisableexcept(int __mask)
181 {
182 	union __fpscr __r;
183 	fenv_t __oldmask;
184 
185 	__mffs(&__r);
186 	__oldmask = __r.__bits.__reg;
187 	__r.__bits.__reg &= ~((__mask & FE_ALL_EXCEPT) >> _FPUSW_SHIFT);
188 	__mtfsf(__r);
189 	return ((__oldmask & _ENABLE_MASK) << _FPUSW_SHIFT);
190 }
191 
192 __declare_fenv_inline(int)
fegetexcept(void)193 fegetexcept(void)
194 {
195 	union __fpscr __r;
196 
197 	__mffs(&__r);
198 	return ((__r.__bits.__reg & _ENABLE_MASK) << _FPUSW_SHIFT);
199 }
200 
201 #endif /* __BSD_VISIBLE */
202