1 /*
2 * Copyright (C) 2009 Android Open Source Project, All rights reserved.
3 * Derived from "bionic/libm/arm/fenv.h"
4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
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 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #ifndef _FENV_H_
31 #define _FENV_H_
32
33 #include <stdio.h>
34 #include <sys/types.h>
35
36 typedef uint32_t fenv_t;
37 typedef uint32_t fexcept_t;
38
39 /* Exception flags */
40 #define FE_INVALID 0x0010
41 #define FE_DIVBYZERO 0x0008
42 #define FE_OVERFLOW 0x0004
43 #define FE_UNDERFLOW 0x0002
44 #define FE_INEXACT 0x0001
45 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
46 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
47
48 /* Rounding modes */
49 #define FE_TONEAREST 0x0000
50 #define FE_TOWARDZERO 0x0001
51 #define FE_UPWARD 0x0002 /* not supporetd */
52 #define FE_DOWNWARD 0x0003 /* not supporetd */
53 #define _ROUND_MASK (FE_TONEAREST | FE_DOWNWARD | \
54 FE_UPWARD | FE_TOWARDZERO)
55
56 /* bit shift for FPSCR mapping */
57 #define _FPUE_CAUSE_SHIFT 12
58 #define _FPUE_ENABLE_SHIFT 17
59 #define _FPUE_FLAG_SHIFT 2
60
61 /* bit shifters */
62 #define _FPUE_CAUSE(_EXCS) ((_EXCS) << _FPUE_CAUSE_SHIFT)
63 #define _FPUE_ENABLE(_EXCS) ((_EXCS) << _FPUE_ENABLE_SHIFT)
64 #define _FPUE_FLAG(_EXCS) ((_EXCS) << _FPUE_FLAG_SHIFT)
65
66 #define _GET_FPUE_CAUSE(_FPUE) (((_FPUE) >> _FPUE_CAUSE_SHIFT) & FE_ALL_EXCEPT)
67 #define _GET_FPUE_ENABLE(_FPUE) (((_FPUE) >> _FPUE_ENABLE_SHIFT)& FE_ALL_EXCEPT)
68 #define _GET_FPUE_FLAG(_FPUE) (((_FPUE) >> _FPUE_FLAG_SHIFT) & FE_ALL_EXCEPT)
69
70
71 /* FPSCR register accessors */
72 #ifdef __SH4_NOFPU__
73 #define __read_fpscr(_ptr)
74 #define __write_fpscr(_val)
75 #else
76 #define __read_fpscr(_ptr) __asm __volatile("sts fpscr, %0" : "=r" (*(_ptr)))
77 #define __write_fpscr(_val) __asm __volatile("lds %0, fpscr" : : "r" (_val))
78 #endif
79
80
81 /* functions for libm */
82 static __inline int
feclearexcept(int __excepts)83 feclearexcept(int __excepts)
84 {
85 uint32_t __fpscr;
86
87 __read_fpscr(&__fpscr);
88 __fpscr &= ~_FPUE_FLAG(__excepts);
89 __write_fpscr(__fpscr);
90 return (0);
91 }
92
93 static __inline int
fegetexceptflag(fexcept_t * __flagp,int __excepts)94 fegetexceptflag(fexcept_t *__flagp, int __excepts)
95 {
96 uint32_t __fpscr;
97
98 __read_fpscr(&__fpscr);
99 *__flagp = _GET_FPUE_FLAG(__fpscr) & __excepts;
100 return (0);
101 }
102
103
104 static __inline int
fesetexceptflag(const fexcept_t * __flagp,int __excepts)105 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
106 {
107 uint32_t __fpscr;
108
109 __read_fpscr(&__fpscr);
110 __fpscr &= ~_FPUE_FLAG(__excepts);
111 __fpscr |= ~_FPUE_FLAG(*__flagp & __excepts);
112 __write_fpscr(__fpscr);
113 return (0);
114 }
115
116
117 static __inline int
feraiseexcept(int __excepts)118 feraiseexcept(int __excepts)
119 {
120 fexcept_t __ex = __excepts;
121
122 fesetexceptflag(&__ex, __excepts); /* XXX */
123 return (0);
124 }
125
126
127 static __inline int
fetestexcept(int __excepts)128 fetestexcept(int __excepts)
129 {
130 fexcept_t __ex;
131
132 fegetexceptflag(&__ex, __excepts);
133 return (__ex);
134 }
135
136
137 static __inline int
fegetround(void)138 fegetround(void)
139 {
140 uint32_t __fpscr = 0;
141
142 __read_fpscr(&__fpscr);
143 return (__fpscr & _ROUND_MASK);
144 }
145
146 static __inline int
fesetround(int __round)147 fesetround(int __round)
148 {
149 uint32_t __fpscr = 0;
150
151 if (__round == FE_UPWARD || __round == FE_DOWNWARD) {
152 fprintf(stderr, "libm superh : "
153 "upward/downward rounding not supporetd.\n");
154 return -1;
155 }
156
157 __read_fpscr(&__fpscr);
158 __fpscr &= ~_ROUND_MASK;
159 __fpscr |= (__round & _ROUND_MASK);
160 __write_fpscr(__fpscr);
161 return (0);
162 }
163
164 static __inline int
fegetenv(fenv_t * __envp)165 fegetenv(fenv_t *__envp)
166 {
167 __read_fpscr(__envp);
168 return (0);
169 }
170
171 static __inline int
feholdexcept(fenv_t * __envp)172 feholdexcept(fenv_t *__envp)
173 {
174 uint32_t __fpscr;
175
176 __read_fpscr(&__fpscr);
177 *__envp = __fpscr;
178 __fpscr &= ~_FPUE_FLAG(FE_ALL_EXCEPT);
179 __write_fpscr(__fpscr);
180 return (0);
181 }
182
183
184 static __inline int
fesetenv(const fenv_t * __envp)185 fesetenv(const fenv_t *__envp)
186 {
187 __write_fpscr(*__envp);
188 return (0);
189 }
190
191
192 static __inline int
feupdateenv(const fenv_t * __envp)193 feupdateenv(const fenv_t *__envp)
194 {
195 uint32_t __fpscr;
196
197 __read_fpscr(&__fpscr);
198 __write_fpscr(*__envp);
199 feraiseexcept(_GET_FPUE_FLAG(__fpscr));
200 return (0);
201 }
202
203 #if __BSD_VISIBLE
204
205 static __inline int
feenableexcept(int __mask)206 feenableexcept(int __mask)
207 {
208 uint32_t __old_fpscr, __new_fpscr;
209
210 __read_fpscr(&__old_fpscr);
211 __new_fpscr = __old_fpscr | _FPUE_ENABLE(__mask & FE_ALL_EXCEPT);
212 __write_fpscr(__new_fpscr);
213 return (_GET_FPUE_ENABLE(__old_fpscr));
214 }
215
216 static __inline int
fedisableexcept(int __mask)217 fedisableexcept(int __mask)
218 {
219 uint32_t __old_fpscr, __new_fpscr;
220
221 __read_fpscr(&__old_fpscr);
222 __new_fpscr = __old_fpscr & ~(_FPUE_ENABLE(__mask & FE_ALL_EXCEPT));
223 __write_fpscr(__new_fpscr);
224 return (_GET_FPUE_ENABLE(__old_fpscr));
225 }
226
227 static __inline int
fegetexcept(void)228 fegetexcept(void)
229 {
230 uint32_t __fpscr;
231
232 __read_fpscr(&__fpscr);
233 return (_GET_FPUE_ENABLE(__fpscr));
234 }
235
236 #endif /* __BSD_VISIBLE */
237
238
239 #endif /* _FENV_H_ */
240
241