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: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
27 */
28
29 /*
30 Rewritten for Android.
31 */
32
33 /* MIPS FPU floating point control register bits.
34 *
35 * 31-25 -> floating point conditions code bits set by FP compare
36 * instructions
37 * 24 -> flush denormalized results to zero instead of
38 * causing unimplemented operation exception.
39 * 23 -> Condition bit
40 * 22 -> In conjunction with FS detects denormalized
41 * operands and replaces them internally with 0.
42 * 21 -> In conjunction with FS forces denormalized operands
43 * to the closest normalized value.
44 * 20-18 -> reserved (read as 0, write with 0)
45 * 17 -> cause bit for unimplemented operation
46 * 16 -> cause bit for invalid exception
47 * 15 -> cause bit for division by zero exception
48 * 14 -> cause bit for overflow exception
49 * 13 -> cause bit for underflow exception
50 * 12 -> cause bit for inexact exception
51 * 11 -> enable exception for invalid exception
52 * 10 -> enable exception for division by zero exception
53 * 9 -> enable exception for overflow exception
54 * 8 -> enable exception for underflow exception
55 * 7 -> enable exception for inexact exception
56 * 6 -> flag invalid exception
57 * 5 -> flag division by zero exception
58 * 4 -> flag overflow exception
59 * 3 -> flag underflow exception
60 * 2 -> flag inexact exception
61 * 1-0 -> rounding control
62 *
63 *
64 * Rounding Control:
65 * 00 - rounding to nearest (RN)
66 * 01 - rounding toward zero (RZ)
67 * 10 - rounding (up) toward plus infinity (RP)
68 * 11 - rounding (down)toward minus infinity (RM)
69 */
70
71 #ifndef _FENV_H_
72 #define _FENV_H_
73
74 #include <machine/fenv.h>
75 #include <sys/types.h>
76
77 __BEGIN_DECLS
78
79 #define _FCSR_CAUSE_SHIFT 10
80 #define _ENABLE_SHIFT 5
81 #define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
82
83 #define _FCSR_RMODE_SHIFT 0
84 #define _FCSR_RMASK 0x3
85
86 /* Default floating-point environment */
87 extern const fenv_t __fe_dfl_env;
88 #define FE_DFL_ENV (&__fe_dfl_env)
89
fegetenv(fenv_t * __envp)90 static __inline int fegetenv(fenv_t* __envp) {
91 fenv_t _fcsr = 0;
92 #ifdef __mips_hard_float
93 __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
94 #endif
95 *__envp = _fcsr;
96 return 0;
97 }
98
fesetenv(const fenv_t * __envp)99 static __inline int fesetenv(const fenv_t* __envp) {
100 fenv_t _fcsr = *__envp;
101 #ifdef __mips_hard_float
102 __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
103 #endif
104 return 0;
105 }
106
feclearexcept(int __excepts)107 static __inline int feclearexcept(int __excepts) {
108 fexcept_t __fcsr;
109 fegetenv(&__fcsr);
110 __excepts &= FE_ALL_EXCEPT;
111 __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
112 fesetenv(&__fcsr);
113 return 0;
114 }
115
fegetexceptflag(fexcept_t * __flagp,int __excepts)116 static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
117 fexcept_t __fcsr;
118 fegetenv(&__fcsr);
119 *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
120 return 0;
121 }
122
fesetexceptflag(const fexcept_t * __flagp,int __excepts)123 static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
124 fexcept_t __fcsr;
125 fegetenv(&__fcsr);
126 /* Ensure that flags are all legal */
127 __excepts &= FE_ALL_EXCEPT;
128 __fcsr &= ~__excepts;
129 __fcsr |= *__flagp & __excepts;
130 fesetenv(&__fcsr);
131 return 0;
132 }
133
feraiseexcept(int __excepts)134 static __inline int feraiseexcept(int __excepts) {
135 fexcept_t __fcsr;
136 fegetenv(&__fcsr);
137 /* Ensure that flags are all legal */
138 __excepts &= FE_ALL_EXCEPT;
139 /* Cause bit needs to be set as well for generating the exception*/
140 __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
141 fesetenv(&__fcsr);
142 return 0;
143 }
144
fetestexcept(int __excepts)145 static __inline int fetestexcept(int __excepts) {
146 fexcept_t __FCSR;
147 fegetenv(&__FCSR);
148 return (__FCSR & __excepts & FE_ALL_EXCEPT);
149 }
150
fegetround(void)151 static __inline int fegetround(void) {
152 fenv_t _fcsr;
153 fegetenv(&_fcsr);
154 return (_fcsr & _FCSR_RMASK);
155 }
156
fesetround(int __round)157 static __inline int fesetround(int __round) {
158 fenv_t _fcsr;
159 fegetenv(&_fcsr);
160 _fcsr &= ~_FCSR_RMASK;
161 _fcsr |= (__round & _FCSR_RMASK ) ;
162 fesetenv(&_fcsr);
163 return 0;
164 }
165
feholdexcept(fenv_t * __envp)166 static __inline int feholdexcept(fenv_t* __envp) {
167 fenv_t __env;
168 fegetenv(&__env);
169 *__envp = __env;
170 __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
171 fesetenv(&__env);
172 return 0;
173 }
174
feupdateenv(const fenv_t * __envp)175 static __inline int feupdateenv(const fenv_t* __envp) {
176 fexcept_t __fcsr;
177 fegetenv(&__fcsr);
178 fesetenv(__envp);
179 feraiseexcept(__fcsr & FE_ALL_EXCEPT);
180 return 0;
181 }
182
183 #if __BSD_VISIBLE
184
feenableexcept(int __mask)185 static __inline int feenableexcept(int __mask) {
186 fenv_t __old_fcsr, __new_fcsr;
187 fegetenv(&__old_fcsr);
188 __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
189 fesetenv(&__new_fcsr);
190 return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
191 }
192
fedisableexcept(int __mask)193 static __inline int fedisableexcept(int __mask) {
194 fenv_t __old_fcsr, __new_fcsr;
195 fegetenv(&__old_fcsr);
196 __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
197 fesetenv(&__new_fcsr);
198 return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
199 }
200
fegetexcept(void)201 static __inline int fegetexcept(void) {
202 fenv_t __fcsr;
203 fegetenv(&__fcsr);
204 return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT);
205 }
206
207 #endif /* __BSD_VISIBLE */
208
209 __END_DECLS
210
211 #endif /* !_FENV_H_ */
212