• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * The ARM FPSCR is described here:
33  * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344b/Chdfafia.html
34  */
35 
36 #ifndef _FENV_H_
37 #define _FENV_H_
38 
39 #include <sys/types.h>
40 
41 __BEGIN_DECLS
42 
43 typedef __uint32_t fenv_t;
44 typedef __uint32_t fexcept_t;
45 
46 /* Exception flags. */
47 #define FE_INVALID    0x01
48 #define FE_DIVBYZERO  0x02
49 #define FE_OVERFLOW   0x04
50 #define FE_UNDERFLOW  0x08
51 #define FE_INEXACT    0x10
52 #define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
53 #define _FPSCR_ENABLE_SHIFT 8
54 #define _FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << _FPSCR_ENABLE_SHIFT)
55 
56 /* Rounding modes. */
57 #define FE_TONEAREST  0x0
58 #define FE_UPWARD     0x1
59 #define FE_DOWNWARD   0x2
60 #define FE_TOWARDZERO 0x3
61 #define _FPSCR_RMODE_SHIFT 22
62 
63 /* Default floating-point environment. */
64 extern const fenv_t __fe_dfl_env;
65 #define FE_DFL_ENV (&__fe_dfl_env)
66 
fegetenv(fenv_t * __envp)67 static __inline int fegetenv(fenv_t* __envp) {
68   fenv_t _fpscr;
69 #if !defined(__SOFTFP__)
70   #if !defined(__thumb__) || defined(__thumb2__)
71   __asm__ __volatile__("vmrs %0,fpscr" : "=r" (_fpscr));
72   #else
73    /* Switching from thumb1 to arm, do vmrs, then switch back */
74   __asm__ __volatile__(
75     ".balign 4           \n\t"
76     "mov     ip, pc      \n\t"
77     "bx      ip          \n\t"
78     ".arm                \n\t"
79     "vmrs    %0, fpscr   \n\t"
80     "add     ip, pc, #1  \n\t"
81     "bx      ip          \n\t"
82     ".thumb              \n\t"
83     : "=r" (_fpscr) : : "ip");
84   #endif
85 #else
86   _fpscr = 0;
87 #endif
88   *__envp = _fpscr;
89   return 0;
90 }
91 
fesetenv(const fenv_t * __envp)92 static __inline int fesetenv(const fenv_t* __envp) {
93   fenv_t _fpscr = *__envp;
94 #if !defined(__SOFTFP__)
95   #if !defined(__thumb__) || defined(__thumb2__)
96   __asm__ __volatile__("vmsr fpscr,%0" : :"ri" (_fpscr));
97   #else
98    /* Switching from thumb1 to arm, do vmsr, then switch back */
99   __asm__ __volatile__(
100     ".balign 4           \n\t"
101     "mov     ip, pc      \n\t"
102     "bx      ip          \n\t"
103     ".arm                \n\t"
104     "vmsr    fpscr, %0   \n\t"
105     "add     ip, pc, #1  \n\t"
106     "bx      ip          \n\t"
107     ".thumb              \n\t"
108     : : "ri" (_fpscr) : "ip");
109   #endif
110 #else
111   _fpscr = _fpscr;
112 #endif
113   return 0;
114 }
115 
feclearexcept(int __excepts)116 static __inline int feclearexcept(int __excepts) {
117   fexcept_t __fpscr;
118   fegetenv(&__fpscr);
119   __fpscr &= ~__excepts;
120   fesetenv(&__fpscr);
121   return 0;
122 }
123 
fegetexceptflag(fexcept_t * __flagp,int __excepts)124 static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
125   fexcept_t __fpscr;
126   fegetenv(&__fpscr);
127   *__flagp = __fpscr & __excepts;
128   return 0;
129 }
130 
fesetexceptflag(const fexcept_t * __flagp,int __excepts)131 static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
132   fexcept_t __fpscr;
133   fegetenv(&__fpscr);
134   __fpscr &= ~__excepts;
135   __fpscr |= *__flagp & __excepts;
136   fesetenv(&__fpscr);
137   return 0;
138 }
139 
feraiseexcept(int __excepts)140 static __inline int feraiseexcept(int __excepts) {
141   fexcept_t __ex = __excepts;
142   fesetexceptflag(&__ex, __excepts);
143   return 0;
144 }
145 
fetestexcept(int __excepts)146 static __inline int fetestexcept(int __excepts) {
147   fexcept_t __fpscr;
148   fegetenv(&__fpscr);
149   return (__fpscr & __excepts);
150 }
151 
fegetround(void)152 static __inline int fegetround(void) {
153   fenv_t _fpscr;
154   fegetenv(&_fpscr);
155   return ((_fpscr >> _FPSCR_RMODE_SHIFT) & 0x3);
156 }
157 
fesetround(int __round)158 static __inline int fesetround(int __round) {
159   fenv_t _fpscr;
160   fegetenv(&_fpscr);
161   _fpscr &= ~(0x3 << _FPSCR_RMODE_SHIFT);
162   _fpscr |= (__round << _FPSCR_RMODE_SHIFT);
163   fesetenv(&_fpscr);
164   return 0;
165 }
166 
feholdexcept(fenv_t * __envp)167 static __inline int feholdexcept(fenv_t* __envp) {
168   fenv_t __env;
169   fegetenv(&__env);
170   *__envp = __env;
171   __env &= ~(FE_ALL_EXCEPT | _FPSCR_ENABLE_MASK);
172   fesetenv(&__env);
173   return 0;
174 }
175 
feupdateenv(const fenv_t * __envp)176 static __inline int feupdateenv(const fenv_t* __envp) {
177   fexcept_t __fpscr;
178   fegetenv(&__fpscr);
179   fesetenv(__envp);
180   feraiseexcept(__fpscr & FE_ALL_EXCEPT);
181   return 0;
182 }
183 
184 #if __BSD_VISIBLE
185 
feenableexcept(int __mask)186 static __inline int feenableexcept(int __mask) {
187   fenv_t __old_fpscr, __new_fpscr;
188   fegetenv(&__old_fpscr);
189   __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT;
190   fesetenv(&__new_fpscr);
191   return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
192 }
193 
fedisableexcept(int __mask)194 static __inline int fedisableexcept(int __mask) {
195   fenv_t __old_fpscr, __new_fpscr;
196   fegetenv(&__old_fpscr);
197   __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << _FPSCR_ENABLE_SHIFT);
198   fesetenv(&__new_fpscr);
199   return ((__old_fpscr >> _FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
200 }
201 
fegetexcept(void)202 static __inline int fegetexcept(void) {
203   fenv_t __fpscr;
204   fegetenv(&__fpscr);
205   return ((__fpscr & _FPSCR_ENABLE_MASK) >> _FPSCR_ENABLE_SHIFT);
206 }
207 
208 #endif /* __BSD_VISIBLE */
209 
210 __END_DECLS
211 
212 #endif /* !_FENV_H_ */
213