2 Inline floating-point environment handling functions for Hyperstone e1-32X.
3 Copyright (C) 2002-2003, George Thanos <george.thanos@gdt.gr>
4 Yannis Mitsos <yannis.mitsos@gdt.gr>
6 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
8 The GNU C Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 The GNU C Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the GNU C Library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES
25 /**********************************************************
26 * --- A small description of the E1-16/32X FP unit. ---
27 * FP exceptions can be enabled and disabled through
28 * <feenableexcept>, <fedisableexcept>.
30 * - When an enabled exception takes place a SIGFPE signal
31 * is sent to the process by the exception handler. User
32 * can test for the exception that took place through
34 * feraiseexcept works only for accrued exceptions.
36 * - When a disabld exception takes place it does not generate
37 * a trap. The user can check if any exception took place after
38 * an FP instruction by issuing an <fetestexcept> command.
39 * User should first clear the G2 register by issuing an
40 * <feclearexcept> function.
41 * The following program is a typical example of how the user
42 * should check for exceptions that did not generate a SIGFPE
47 * feclearexcept (FE_ALL_EXCEPT);
49 * raised = fetestexcept (FE_OVERFLOW | FE_INVALID);
50 * if (raised & FE_OVERFLOW) { ... }
51 * if (raised & FE_INVALID) { ... }
54 ***********************************************************/
56 /* Get FPU rounding mode */
57 #define fegetround() \
60 __asm__ __volatile__("mov %0, SR" \
67 /* Set FPU rounding mode */
68 #define fesetround(round) \
70 unsigned int tmp = (3 << 13); \
72 /* Clear SR.FRM field */ \
73 __asm__ __volatile__("andn SR, %0" \
83 __asm__ __volatile__("or SR, %0" \
92 /* The following functions test for accrued exceptions.
93 * No trap is generated on an FP exception.
95 static inline feclearexcept(int __excepts)
97 unsigned int enabled_excepts, disabled_excepts;
99 /* Check that __excepts is correctly set */
100 if( __excepts & (~0x1F00) )
103 __asm__ __volatile__("mov %0, SR"
104 :"=l"(enabled_excepts)
107 enabled_excepts &= 0x1F00;
108 disabled_excepts = ~enabled_excepts;
109 disabled_excepts &= 0x1F00;
111 enabled_excepts &= __excepts;
112 disabled_excepts &= __excepts;
114 /* Clear accrued exceptions */
115 __asm__ __volatile__("andn G2, %0\n\t"
118 :"l"(enabled_excepts),
119 "l"(disabled_excepts >> 8) );
123 /* fetestexcepts tests both for actual and accrued
124 * excepts. You can test for an exception either after
125 * an FP instruction or within a SIGFPE handler
127 inline int fetestexcept(int __excepts)
129 unsigned int G2, G2en, G2dis;
130 unsigned int enabled_excepts, disabled_excepts;
132 /* Check that __excepts is correctly set */
133 if( __excepts & (~0x1F00) )
136 __asm__ __volatile__("mov %0, SR"
137 :"=l"(enabled_excepts)
140 enabled_excepts &= 0x1F00;
141 disabled_excepts = ~enabled_excepts;
142 disabled_excepts &= 0x1F00;
144 __asm__ __volatile__("mov %0, G2"
150 G2en &= enabled_excepts;
151 G2dis &= (disabled_excepts >> 8);
152 return ( G2en | (G2dis << 8) );
155 static inline int feraiseexcept(int __excepts)
157 __asm__ __volatile__("or G2, %0"
159 :"l"( __excepts >> 8 ) );
163 /* The following functions enable/disable individual exceptions.
164 * If enabling an exception trap is going to occur, in case of error.
166 #define feenableexcept(__excepts) \
168 int __retval, __pexcepts; \
169 int __tmpexcepts = __excepts; \
172 __asm__ __volatile__("mov %0, SR" \
175 __pexcepts &= 0x1F00; \
177 /* Check if __except values are valid */ \
178 if( __tmpexcepts & ~0x1F00 ) { \
180 fprintf(stderr,"Non valid excepts\n");\
184 __asm__ __volatile__("or SR, %0" \
186 :"l"(__tmpexcepts) ); \
187 __retval = __pexcepts; \
194 #define fedisableexcept(__excepts) \
196 int __retval, __pexcepts; \
197 int __tmpexcepts = __excepts; \
200 __asm__ __volatile__("mov %0, SR" \
203 __pexcepts &= 0x1F00; \
205 /* Check if __except values are valid */ \
206 if( __tmpexcepts & ~0x1F00 ) { \
208 fprintf(stderr,"Non valid excepts\n");\
212 __asm__ __volatile__("andn SR, %0" \
214 :"l"(__tmpexcepts) ); \
215 __retval = __pexcepts; \
221 static inline int fegetexcept(int excepts)
224 __asm__ __volatile__("mov %0, SR"
231 static inline int fegetenv(fenv_t *envp)
233 __asm__ __volatile__("mov %0, SR\n\t
237 :"=l"(envp->round_mode),
238 "=l"(envp->trap_enabled),
239 "=l"(envp->accrued_except),
240 "=l"(envp->actual_except)
242 envp->round_mode &= (3<<13);
243 envp->trap_enabled &= 0x1F00;
244 envp->accrued_except &= 0x1F;
245 envp->accrued_except <<= 8;
246 envp->actual_except &= 0x1F00;
249 #define feholdexcept(envp) \
252 fedisableexcept(FE_ALL_EXCEPT); \
253 feclearexcept(FE_ALL_EXCEPT); \
257 #define fesetenv(envp) \
259 /* Clear FRM & FTE field of SR */ \
260 unsigned long clearSR = ( 127<<8 ); \
261 __asm__ __volatile__("andn SR, %0\n\t" \
266 "l"(envp->round_mode), \
267 "l"(envp->trap_enabled) ); \
268 __asm__ __volatile__("andn G2, 0x1F1F\n\t" \
272 :"l"( envp->accrued_except >> 8),\
273 :"l"( envp->actual_except ) ); \
274 (0); /* return 0 */ \
277 #define feupdateenv(envp) \
279 /* Clear FRM & FTE field of SR */ \
280 __asm__ __volatile__(/* We dont clear the prev SR*/ \
285 "l"(envp->round_mode), \
286 "l"(envp->accrued_except) ); \
287 __asm__ __volatile__(/* We dont clear the prev SR*/ \
291 :"l"( envp->accrued_except >> 8),\
292 :"l"( envp->actual_except ) ); \
293 (0); /* return 0 */ \
297 #endif /* __GNUC__ && !_SOFT_FLOAT */