blob: e872f47369f6dc73f85139943e0ba82310775ba4 [file] [log] [blame]
Shin-ichiro KAWASAKId87945b2009-08-31 16:25:42 +09001/*
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
36typedef uint32_t fenv_t;
37typedef 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 */
82static __inline int
83feclearexcept(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
93static __inline int
94fegetexceptflag(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
104static __inline int
105fesetexceptflag(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
117static __inline int
118feraiseexcept(int __excepts)
119{
120 fexcept_t __ex = __excepts;
121
122 fesetexceptflag(&__ex, __excepts); /* XXX */
123 return (0);
124}
125
126
127static __inline int
128fetestexcept(int __excepts)
129{
130 fexcept_t __ex;
131
132 fegetexceptflag(&__ex, __excepts);
133 return (__ex);
134}
135
136
137static __inline int
138fegetround(void)
139{
140 uint32_t __fpscr = 0;
141
142 __read_fpscr(&__fpscr);
143 return (__fpscr & _ROUND_MASK);
144}
145
146static __inline int
147fesetround(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
164static __inline int
165fegetenv(fenv_t *__envp)
166{
167 __read_fpscr(__envp);
168 return (0);
169}
170
171static __inline int
172feholdexcept(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
184static __inline int
185fesetenv(const fenv_t *__envp)
186{
187 __write_fpscr(*__envp);
188 return (0);
189}
190
191
192static __inline int
193feupdateenv(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
205static __inline int
206feenableexcept(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
216static __inline int
217fedisableexcept(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
227static __inline int
228fegetexcept(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