⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode_exc.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
字号:
/* * Linux/PA-RISC Project (http://www.parisc-linux.org/) * * Floating-point emulation code *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org> * *    This program is free software; you can redistribute it and/or modify *    it under the terms of the GNU General Public License as published by *    the Free Software Foundation; either version 2, or (at your option) *    any later version. * *    This program 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 General Public License for more details. * *    You should have received a copy of the GNU General Public License *    along with this program; if not, write to the Free Software *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * BEGIN_DESC * *  File: *	@(#)	pa/fp/decode_exc.c		$ Revision: $ * *  Purpose: *	<<please update with a synopsis of the functionality provided by this file>> * *  External Interfaces: *	<<the following list was autogenerated, please review>> *	decode_fpu(Fpu_register, trap_counts) * *  Internal Interfaces: *	<<please update>> * *  Theory: *	<<please update with a overview of the operation of this file>> * * END_DESC*/#include "float.h"#include "sgl_float.h"#include "dbl_float.h"#include "cnv_float.h"/* #include "types.h" */#include <asm/signal.h>#include <asm/siginfo.h>/* #include <machine/sys/mdep_private.h> */#undef Fpustatus_register#define Fpustatus_register Fpu_register[0]/* General definitions */#define DOESTRAP 1#define NOTRAP 0#define SIGNALCODE(signal, code) ((signal) << 24 | (code));#define copropbit	1<<31-2	/* bit position 2 */#define opclass		9	/* bits 21 & 22 */#define fmt		11	/* bits 19 & 20 */#define df		13	/* bits 17 & 18 */#define twobits		3	/* mask low-order 2 bits */#define fivebits	31	/* mask low-order 5 bits */#define MAX_EXCP_REG	7	/* number of excpeption registers to check *//* Exception register definitions */#define Excp_type(index) Exceptiontype(Fpu_register[index])#define Excp_instr(index) Instructionfield(Fpu_register[index])#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0#define Excp_format() \    (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)/* Miscellaneous definitions */#define Fpu_sgl(index) Fpu_register[index*2]#define Fpu_dblp1(index) Fpu_register[index*2]#define Fpu_dblp2(index) Fpu_register[(index*2)+1]#define Fpu_quadp1(index) Fpu_register[index*2]#define Fpu_quadp2(index) Fpu_register[(index*2)+1]#define Fpu_quadp3(index) Fpu_register[(index*2)+2]#define Fpu_quadp4(index) Fpu_register[(index*2)+3]/* Single precision floating-point definitions */#ifndef Sgl_decrement# define Sgl_decrement(sgl_value) Sall(sgl_value)--#endif/* Double precision floating-point definitions */#ifndef Dbl_decrement# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \    if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- #endif#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) {	\	aflags=(Fpu_register[0])>>27;	/* assumes zero fill. 32 bit */	\	Fpu_register[0] |= bflags;					\}u_intdecode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[]){    unsigned int current_ir, excp;    int target, exception_index = 1;    boolean inexact;    unsigned int aflags;    unsigned int bflags;    unsigned int excptype;    /* Keep stats on how many floating point exceptions (based on type)     * that happen.  Want to keep this overhead low, but still provide     * some information to the customer.  All exits from this routine     * need to restore Fpu_register[0]    */    bflags=(Fpu_register[0] & 0xf8000000);    Fpu_register[0] &= 0x07ffffff;    /* exception_index is used to index the exception register queue.  It     *   always points at the last register that contains a valid exception.  A     *   zero value implies no exceptions (also the initialized value).  Setting     *   the T-bit resets the exception_index to zero.     */    /*     * Check for reserved-op exception.  A reserved-op exception does not      * set any exception registers nor does it set the T-bit.  If the T-bit     * is not set then a reserved-op exception occurred.     *     * At some point, we may want to report reserved op exceptions as     * illegal instructions.     */        if (!Is_tbit_set()) {	update_trap_counts(Fpu_register, aflags, bflags, trap_counts);	return SIGNALCODE(SIGILL, ILL_COPROC);    }    /*      * Is a coprocessor op.      *     * Now we need to determine what type of exception occurred.     */    for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {	current_ir = Excp_instr(exception_index);	  /*	   * On PA89: there are 5 different unimplemented exception	   * codes: 0x1, 0x9, 0xb, 0x3, and 0x23.  PA-RISC 2.0 adds	   * another, 0x2b.  Only these have the low order bit set.	   */	excptype = Excp_type(exception_index);	if (excptype & UNIMPLEMENTEDEXCEPTION) {		/*		 * Clear T-bit and exception register so that		 * we can tell if a trap really occurs while 		 * emulating the instruction.		 */		Clear_tbit();		Clear_excp_register(exception_index);		/*		 * Now emulate this instruction.  If a trap occurs,		 * fpudispatch will return a non-zero number 		 */		excp = fpudispatch(current_ir,excptype,0,Fpu_register);		/* accumulate the status flags, don't lose them as in hpux */		if (excp) {			/*			 * We now need to make sure that the T-bit and the			 * exception register contain the correct values			 * before continuing.			 */			/*			 * Set t-bit since it might still be needed for a			 * subsequent real trap (I don't understand fully -PB)			 */			Set_tbit();			/* some of the following code uses			 * Excp_type(exception_index) so fix that up */			Set_exceptiontype_and_instr_field(excp,current_ir,			 Fpu_register[exception_index]);			if (excp == UNIMPLEMENTEDEXCEPTION) {				/*			 	 * it is really unimplemented, so restore the			 	 * TIMEX extended unimplemented exception code			 	 */				excp = excptype;				update_trap_counts(Fpu_register, aflags, bflags, 					   trap_counts);				return SIGNALCODE(SIGILL, ILL_COPROC);			}			/* some of the following code uses excptype, so			 * fix that up too */			excptype = excp;		}		/* handle exceptions other than the real UNIMPLIMENTED the		 * same way as if the hardware had caused them */		if (excp == NOEXCEPTION)			/* For now use 'break', should technically be 'continue' */			break;	}	  /*	   * In PA89, the underflow exception has been extended to encode	   * additional information.  The exception looks like pp01x0,	   * where x is 1 if inexact and pp represent the inexact bit (I)	   * and the round away bit (RA)	   */	if (excptype & UNDERFLOWEXCEPTION) {		/* check for underflow trap enabled */		if (Is_underflowtrap_enabled()) {			update_trap_counts(Fpu_register, aflags, bflags, 					   trap_counts);			return SIGNALCODE(SIGFPE, FPE_FLTUND);		} else {		    /*		     * Isn't a real trap; we need to 		     * return the default value.		     */		    target = current_ir & fivebits;#ifndef lint		    if (Ibit(Fpu_register[exception_index])) inexact = TRUE;		    else inexact = FALSE;#endif		    switch (Excp_format()) {		      case SGL:		        /*		         * If ra (round-away) is set, will 		         * want to undo the rounding done		         * by the hardware.		         */		        if (Rabit(Fpu_register[exception_index])) 				Sgl_decrement(Fpu_sgl(target));			/* now denormalize */			sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());		    	break;		      case DBL:		    	/*		    	 * If ra (round-away) is set, will 		    	 * want to undo the rounding done		    	 * by the hardware.		    	 */		    	if (Rabit(Fpu_register[exception_index])) 				Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));			/* now denormalize */			dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),			  &inexact,Rounding_mode());		    	break;		    }		    if (inexact) Set_underflowflag();		    /* 		     * Underflow can generate an inexact		     * exception.  If inexact trap is enabled,		     * want to do an inexact trap, otherwise 		     * set inexact flag.		     */		    if (inexact && Is_inexacttrap_enabled()) {		    	/*		    	 * Set exception field of exception register		    	 * to inexact, parm field to zero.			 * Underflow bit should be cleared.		    	 */		    	Set_exceptiontype(Fpu_register[exception_index],			 INEXACTEXCEPTION);			Set_parmfield(Fpu_register[exception_index],0);			update_trap_counts(Fpu_register, aflags, bflags, 					   trap_counts);			return SIGNALCODE(SIGFPE, FPE_FLTRES);		    }		    else {		    	/*		    	 * Exception register needs to be cleared.  			 * Inexact flag needs to be set if inexact.		    	 */		    	Clear_excp_register(exception_index);		    	if (inexact) Set_inexactflag();		    }		}		continue;	}	switch(Excp_type(exception_index)) {	  case OVERFLOWEXCEPTION:	  case OVERFLOWEXCEPTION | INEXACTEXCEPTION:		/* check for overflow trap enabled */			update_trap_counts(Fpu_register, aflags, bflags, 					   trap_counts);		if (Is_overflowtrap_enabled()) {			update_trap_counts(Fpu_register, aflags, bflags, 					   trap_counts);			return SIGNALCODE(SIGFPE, FPE_FLTOVF);		} else {			/*			 * Isn't a real trap; we need to 			 * return the default value.			 */			target = current_ir & fivebits;			switch (Excp_format()) {			  case SGL: 				Sgl_setoverflow(Fpu_sgl(target));				break;			  case DBL:				Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));				break;			}			Set_overflowflag();			/* 			 * Overflow always generates an inexact			 * exception.  If inexact trap is enabled,			 * want to do an inexact trap, otherwise 			 * set inexact flag.			 */			if (Is_inexacttrap_enabled()) {				/*				 * Set exception field of exception				 * register to inexact.  Overflow				 * bit should be cleared.				 */				Set_exceptiontype(Fpu_register[exception_index],				 INEXACTEXCEPTION);				update_trap_counts(Fpu_register, aflags, bflags,					   trap_counts);				return SIGNALCODE(SIGFPE, FPE_FLTRES);			}			else {				/*				 * Exception register needs to be cleared.  				 * Inexact flag needs to be set.				 */				Clear_excp_register(exception_index);				Set_inexactflag();			}		}		break;	  case INVALIDEXCEPTION:		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);		return SIGNALCODE(SIGFPE, FPE_FLTINV);	  case DIVISIONBYZEROEXCEPTION:		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);	  case INEXACTEXCEPTION:		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);		return SIGNALCODE(SIGFPE, FPE_FLTRES);	  default:		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);		printk(__FILE__ "(%d) Unknown FPU exception 0x%x\n",			__LINE__, Excp_type(exception_index));		return SIGNALCODE(SIGILL, ILL_COPROC);	  case NOEXCEPTION:	/* no exception */		/*		 * Clear exception register in case 		 * other fields are non-zero.		 */		Clear_excp_register(exception_index);		break;	}    }    /*     * No real exceptions occurred.     */    Clear_tbit();    update_trap_counts(Fpu_register, aflags, bflags, trap_counts);    return(NOTRAP);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -