• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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