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