| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 | /*   Inline floating-point environment handling functions for Hyperstone e1-32X.   Copyright (C) 2002-2003,    George Thanos <george.thanos@gdt.gr>                               Yannis Mitsos <yannis.mitsos@gdt.gr>   Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, see   <http://www.gnu.org/licenses/>.  */#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES/********************************************************** *  --- A small description of the E1-16/32X FP unit. --- * FP exceptions can be enabled and disabled through * <feenableexcept>, <fedisableexcept>. * * - When an enabled exception takes place a SIGFPE signal * is sent to the process by the exception handler. User * can test for the exception that took place through * <fetestexcept>. * feraiseexcept works only for accrued exceptions. * * - When a disabld exception takes place it does not generate * a trap. The user can check if any exception took place after * an FP instruction by issuing an <fetestexcept> command. * User should first clear the G2 register by issuing an * <feclearexcept> function. * The following program is a typical example of how the user * should check for exceptions that did not generate a SIGFPE * signal : * { *   double f; *   int raised; *   feclearexcept (FE_ALL_EXCEPT); *   f = compute (); *   raised = fetestexcept (FE_OVERFLOW | FE_INVALID); *   if (raised & FE_OVERFLOW) {  ...  } *   if (raised & FE_INVALID) {  ...  } *    ... * } ***********************************************************//* Get FPU rounding mode  */#define fegetround()                     \({                                       \	unsigned int tmp;                \	__asm__ __volatile__("mov %0, SR"        \			:"=l"(tmp)       \			:/*no input*/);  \	tmp &= (3<<13);                  \	(tmp);                           \})/* Set FPU rounding mode  */#define fesetround(round)                \({                                       \	unsigned int tmp = (3 << 13);    \	while(1) {                       \	/* Clear SR.FRM field */         \	__asm__ __volatile__("andn SR, %0"       \			:/*no output*/   \			:"l"(tmp) );     \	tmp &= round;                    \                                         \	if(tmp) {                        \		tmp = -1;                \		break;                   \	}                                \                                         \	__asm__ __volatile__("or SR, %0"         \			:/*no input*/    \			:"l"(round) );   \	tmp = 0;                         \	break;                           \	}                                \	(tmp);                           \})/* The following functions test for accrued exceptions. * No trap is generated on an FP exception. */static __inline__ feclearexcept(int __excepts){	unsigned int enabled_excepts, disabled_excepts;	/* Check that __excepts is correctly set */	if( __excepts & (~0x1F00) )		return -1;	__asm__ __volatile__("mov %0, SR"		     :"=l"(enabled_excepts)		     :/*no input*/ );	enabled_excepts  &= 0x1F00;	disabled_excepts = ~enabled_excepts;	disabled_excepts &= 0x1F00;	enabled_excepts  &= __excepts;	disabled_excepts &= __excepts;	/* Clear accrued exceptions */	__asm__ __volatile__("andn G2, %0\n\t"		     "andn G2, %1\n\t"			:/*no output*/			:"l"(enabled_excepts),			 "l"(disabled_excepts >> 8) );	return 0;}/* fetestexcepts tests both for actual and accrued * excepts. You can test for an exception either after * an FP instruction or within a SIGFPE handler */__inline__ int fetestexcept(int __excepts){	unsigned int G2, G2en, G2dis;	unsigned int enabled_excepts, disabled_excepts;	/* Check that __excepts is correctly set */	if( __excepts & (~0x1F00) )		return -1;	__asm__ __volatile__("mov %0, SR"		     :"=l"(enabled_excepts)		     :/*no input*/ );	enabled_excepts &= 0x1F00;	disabled_excepts = ~enabled_excepts;	disabled_excepts &= 0x1F00; 	__asm__ __volatile__("mov %0, G2"		    :"=l"(G2)		    :/*no input*/ );	G2en  = G2 & 0x1F00;	G2dis = G2 & 0x1F;	G2en  &= enabled_excepts;	G2dis &= (disabled_excepts >> 8);	return ( G2en | (G2dis << 8) );}static __inline__ int feraiseexcept(int __excepts){	__asm__ __volatile__("or G2, %0"			:/*no output*/			:"l"( __excepts >> 8  ) );	return 0;}/* The following functions enable/disable individual exceptions. * If enabling an exception trap is going to occur, in case of error. */#define feenableexcept(__excepts)          \({                                         \	int __retval, __pexcepts;          \	int __tmpexcepts = __excepts;      \                                           \	while(1) {                         \	    __asm__ __volatile__("mov %0, SR"      \		     :"=l"(__pexcepts)     \		     :/*no input*/ );      \	    __pexcepts &= 0x1F00;          \	                                   \/* Check if __except values are valid */   \	    if( __tmpexcepts & ~0x1F00 ) { \	        __retval = -1;             \		fprintf(stderr,"Non valid excepts\n");\	        break;                     \	    }                              \	                                   \	    __asm__ __volatile__("or SR, %0"       \			:/*no output*/     \			:"l"(__tmpexcepts) ); \	    __retval = __pexcepts;         \	    break;                         \	}                                  \	(__retval);                        \})#define fedisableexcept(__excepts)         \({                                         \	int __retval, __pexcepts;          \	int __tmpexcepts = __excepts;      \	                                   \	while(1) {                         \	    __asm__ __volatile__("mov %0, SR"      \		     :"=l"(__pexcepts)     \		     :/*no input*/ );      \	    __pexcepts &= 0x1F00;          \	                                   \/* Check if __except values are valid */   \	    if( __tmpexcepts & ~0x1F00 ) { \	        __retval = -1;             \		fprintf(stderr,"Non valid excepts\n");\	        break;                     \	    }                              \	                                   \	    __asm__ __volatile__("andn SR, %0"     \			:/*no output*/     \			:"l"(__tmpexcepts) ); \	    __retval = __pexcepts;         \	    break;                         \	}                                  \	(__retval);                        \})static __inline__ int fegetexcept(int excepts){	unsigned int tmp;	__asm__ __volatile__("mov %0, SR"		    :"=l"(tmp)		    :/*no input*/ );	tmp &= 0x1F00;	return tmp;}static __inline__ int fegetenv(fenv_t *envp){	__asm__ __volatile__("mov %0, SR\n\t		      mov %1, SR\n\t		      mov %2, G2\n\t		      mov %3, G2\n\t"		     :"=l"(envp->round_mode),		      "=l"(envp->trap_enabled),		      "=l"(envp->accrued_except),		      "=l"(envp->actual_except)		     :/*no input*/ );	envp->round_mode &= (3<<13);	envp->trap_enabled &= 0x1F00;	envp->accrued_except &= 0x1F;	envp->accrued_except <<= 8;	envp->actual_except &= 0x1F00;}#define feholdexcept(envp)        \(                                         \	fegetenv(envp);                   \	fedisableexcept(FE_ALL_EXCEPT);   \	feclearexcept(FE_ALL_EXCEPT);     \	(0);                              \)#define fesetenv(envp)                \({                                                  \	/* Clear FRM & FTE field of SR */           \	unsigned long clearSR = ( 127<<8 );         \	__asm__ __volatile__("andn SR, %0\n\t"              \		     "or   SR, %1\n\t"              \		     "or   SR, %2\n\t"              \		     :/*no output*/                 \		     :"l"(clearSR),                 \		      "l"(envp->round_mode),        \		      "l"(envp->trap_enabled) );    \	__asm__ __volatile__("andn G2, 0x1F1F\n\t"          \		     "or   G2, %0\n\t"              \		     "or   G2, %1\n\t"              \		     :/*no output*/                 \		     :"l"( envp->accrued_except >> 8),\		     :"l"( envp->actual_except ) ); \	(0); /* return 0 */                         \})#define feupdateenv(envp)                           \({                                                  \	/* Clear FRM & FTE field of SR */           \	__asm__ __volatile__(/* We dont clear the prev SR*/ \		     "or   SR, %1\n\t"              \		     "or   SR, %2\n\t"              \		     :/*no output*/                 \		     :"l"(clearSR),                 \		      "l"(envp->round_mode),        \		      "l"(envp->accrued_except) );  \	__asm__ __volatile__(/* We dont clear the prev SR*/ \		     "or   G2, %0\n\t"              \		     "or   G2, %1\n\t"              \		     :/*no output*/                 \		     :"l"( envp->accrued_except >> 8),\		     :"l"( envp->actual_except ) ); \	(0); /* return 0 */                         \})#endif /* __GNUC__ && !_SOFT_FLOAT */
 |