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

📄 fpudispatch.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
						&local_status);					update_status_cbit(status,local_status,						fpu_type_flags, subop);					return(retval);				    case 1:					retval = dbl_fcmp(&fpregs[r1],						&fpregs[r2],extru(ir,fptpos,5),						&local_status);					update_status_cbit(status,local_status,						fpu_type_flags, subop);					return(retval);				}			}		}  /* end of if for PA2.0 */		else {  /* PA1.0 & PA1.1 */		    switch (subop) {			case 1:			case 2:			case 3:			case 4:			case 5:			case 6:			case 7:				return(MAJOR_0E_EXCP);			case 0: /* FCMP */				switch (fmt) {				    /*				     * fmt is only 1 bit long				     */				    case 0:					retval = sgl_fcmp(&fpregs[r1],						&fpregs[r2],extru(ir,fptpos,5),						&local_status);					update_status_cbit(status,local_status,						fpu_type_flags, subop);					return(retval);				    case 1:					retval = dbl_fcmp(&fpregs[r1],						&fpregs[r2],extru(ir,fptpos,5),						&local_status);					update_status_cbit(status,local_status,						fpu_type_flags, subop);					return(retval);				}		    } /* end of switch subop */		} /* end of else for PA1.0 & PA1.1 */	case 3: /* class 3 */		/*		 * Be careful out there.		 * Crashme can generate cases where FR31R is specified		 * as the source or target of a double precision operation.		 * Since we just pass the address of the floating-point		 * register to the emulation routines, this can cause		 * corruption of fpzeroreg.		 */		if (fmt == DBL)			r2 = (extru(ir,fpr2pos,5)<<1);		else			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));		if (r2 == 0)			r2 = fpzeroreg;		switch (subop) {			case 5:			case 6:			case 7:				return(MAJOR_0E_EXCP);						/*			 * Note that fmt is only 1 bit for class 3 */			case 0: /* FADD */				switch (fmt) {				    case 0:					return(sgl_fadd(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				    case 1:					return(dbl_fadd(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				}			case 1: /* FSUB */				switch (fmt) {				    case 0:					return(sgl_fsub(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				    case 1:					return(dbl_fsub(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				}			case 2: /* FMPY or XMPYU */				/*				 * check for integer multiply (x bit set)				 */				if (extru(ir,fpxpos,1)) {				    /*				     * emulate XMPYU				     */				    switch (fmt) {					case 0:					    /*					     * bad instruction if t specifies					     * the right half of a register					     */					    if (t & 1)						return(MAJOR_0E_EXCP);					    BUG();					    /* unsupported					     * impyu(&fpregs[r1],&fpregs[r2],						 * &fpregs[t]);					     */					    return(NOEXCEPTION);					case 1:						return(MAJOR_0E_EXCP);				    }				}				else { /* FMPY */				    switch (fmt) {				        case 0:					    return(sgl_fmpy(&fpregs[r1],					       &fpregs[r2],&fpregs[t],status));				        case 1:					    return(dbl_fmpy(&fpregs[r1],					       &fpregs[r2],&fpregs[t],status));				    }				}			case 3: /* FDIV */				switch (fmt) {				    case 0:					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				    case 1:					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				}			case 4: /* FREM */				switch (fmt) {				    case 0:					return(sgl_frem(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				    case 1:					return(dbl_frem(&fpregs[r1],&fpregs[r2],						&fpregs[t],status));				}		} /* end of class 3 switch */	} /* end of switch(class) */	/* If we get here, something is really wrong! */	return(MAJOR_0E_EXCP);}/* * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction */static u_intdecode_06(ir,fpregs)u_int ir;u_int fpregs[];{	u_int rm1, rm2, tm, ra, ta; /* operands */	u_int fmt;	u_int error = 0;	u_int status;	u_int fpu_type_flags;	union {		double dbl;		float flt;		struct { u_int i1; u_int i2; } ints;	} mtmp, atmp;	status = fpregs[0];		/* use a local copy of status reg */	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */	if (fmt == 0) { /* DBL */		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);		if (rm1 == 0)			rm1 = fpzeroreg;		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);		if (rm2 == 0)			rm2 = fpzeroreg;		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);		if (tm == 0)			return(MAJOR_06_EXCP);		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);		if (ta == 0)			return(MAJOR_06_EXCP);		if  (fpu_type_flags & TIMEX_ROLEX_FPU_MASK)  {			if (ra == 0) {			 	/* special case FMPYCFXT, see sgl case below */				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],					&mtmp.ints.i1,&status))					error = 1;				if (dbl_to_sgl_fcnvfxt(&fpregs[ta],					&atmp.ints.i1,&atmp.ints.i1,&status))					error = 1;				}			else {			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,					&status))				error = 1;			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,					&status))				error = 1;				}			}		else			{			if (ra == 0)				ra = fpzeroreg;			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,					&status))				error = 1;			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,					&status))				error = 1;			}		if (error)			return(MAJOR_06_EXCP);		else {			/* copy results */			fpregs[tm] = mtmp.ints.i1;			fpregs[tm+1] = mtmp.ints.i2;			fpregs[ta] = atmp.ints.i1;			fpregs[ta+1] = atmp.ints.i2;			fpregs[0] = status;			return(NOEXCEPTION);		}	}	else { /* SGL */		/*		 * calculate offsets for single precision numbers		 * See table 6-14 in PA-89 architecture for mapping		 */		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */		ra |= extru(ir,fprapos-4,1);	/* add right word offset */		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */		ta |= extru(ir,fptapos-4,1);	/* add right word offset */				if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {			/* special case FMPYCFXT (really 0)			  * This instruction is only present on the Timex and			  * Rolex fpu's in so if it is the special case and			  * one of these fpu's we run the FMPYCFXT instruction			  */			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,					&status))				error = 1;			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,				&atmp.ints.i1,&status))				error = 1;		}		else {			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,					&status))				error = 1;			if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,					&status))				error = 1;		}		if (error)			return(MAJOR_06_EXCP);		else {			/* copy results */			fpregs[tm] = mtmp.ints.i1;			fpregs[ta] = atmp.ints.i1;			fpregs[0] = status;			return(NOEXCEPTION);		}	}}/* * routine to decode the 26 (FMPYSUB) instruction */static u_intdecode_26(ir,fpregs)u_int ir;u_int fpregs[];{	u_int rm1, rm2, tm, ra, ta; /* operands */	u_int fmt;	u_int error = 0;	u_int status;	union {		double dbl;		float flt;		struct { u_int i1; u_int i2; } ints;	} mtmp, atmp;	status = fpregs[0];	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */	if (fmt == 0) { /* DBL */		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);		if (rm1 == 0)			rm1 = fpzeroreg;		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);		if (rm2 == 0)			rm2 = fpzeroreg;		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);		if (tm == 0)			return(MAJOR_26_EXCP);		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);		if (ra == 0)			return(MAJOR_26_EXCP);		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);		if (ta == 0)			return(MAJOR_26_EXCP);				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))			error = 1;		if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))			error = 1;		if (error)			return(MAJOR_26_EXCP);		else {			/* copy results */			fpregs[tm] = mtmp.ints.i1;			fpregs[tm+1] = mtmp.ints.i2;			fpregs[ta] = atmp.ints.i1;			fpregs[ta+1] = atmp.ints.i2;			fpregs[0] = status;			return(NOEXCEPTION);		}	}	else { /* SGL */		/*		 * calculate offsets for single precision numbers		 * See table 6-14 in PA-89 architecture for mapping		 */		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */		ra |= extru(ir,fprapos-4,1);	/* add right word offset */		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */		ta |= extru(ir,fptapos-4,1);	/* add right word offset */				if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))			error = 1;		if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))			error = 1;		if (error)			return(MAJOR_26_EXCP);		else {			/* copy results */			fpregs[tm] = mtmp.ints.i1;			fpregs[ta] = atmp.ints.i1;			fpregs[0] = status;			return(NOEXCEPTION);		}	}}/* * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions */static u_intdecode_2e(ir,fpregs)u_int ir;u_int fpregs[];{	u_int rm1, rm2, ra, t; /* operands */	u_int fmt;	fmt = extru(ir,fpfmtpos,1);	/* get fmt completer */	if (fmt == DBL) { /* DBL */		rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);		if (rm1 == 0)			rm1 = fpzeroreg;		rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);		if (rm2 == 0)			rm2 = fpzeroreg;		ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *		     sizeof(double)/sizeof(u_int);		if (ra == 0)			ra = fpzeroreg;		t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);		if (t == 0)			return(MAJOR_2E_EXCP);		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */			return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],					&fpregs[ra], &fpregs[0], &fpregs[t]));		} else {			return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],					&fpregs[ra], &fpregs[0], &fpregs[t]));		}	} /* end DBL */	else { /* SGL */		rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));		if (rm1 == 0)			rm1 = fpzeroreg;		rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));		if (rm2 == 0)			rm2 = fpzeroreg;		ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);		if (ra == 0)			ra = fpzeroreg;		t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));		if (t == 0)			return(MAJOR_2E_EXCP);		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */			return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],					&fpregs[ra], &fpregs[0], &fpregs[t]));		} else {			return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],					&fpregs[ra], &fpregs[0], &fpregs[t]));		}	} /* end SGL */}/* * update_status_cbit * *	This routine returns the correct FP status register value in *	*status, based on the C-bit & V-bit returned by the FCMP *	emulation routine in new_status.  The architecture type *	(PA83, PA89 or PA2.0) is available in fpu_type.  The y_field *	and the architecture type are used to determine what flavor *	of FCMP is being emulated. */static voidupdate_status_cbit(status, new_status, fpu_type, y_field)u_int *status, new_status;u_int fpu_type;u_int y_field;{	/*	 * For PA89 FPU's which implement the Compare Queue and	 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,	 * otherwise update the specified bit in the Compare Array.	 * Note that the y-field will always be 0 for non-PA2.0 FPU's.	 */	if ((fpu_type & TIMEX_EXTEN_FLAG) || 	    (fpu_type & ROLEX_EXTEN_FLAG) ||	    (fpu_type & PA2_0_FPU_FLAG)) {		if (y_field == 0) {			*status = ((*status & 0x04000000) >> 5) | /* old Cbit */				  ((*status & 0x003ff000) >> 1) | /* old CQ   */				  (new_status & 0xffc007ff); /* all other bits*/		} else {			*status = (*status & 0x04000000) |     /* old Cbit */				  ((new_status & 0x04000000) >> (y_field+4)) |				  (new_status & ~0x04000000 &  /* other bits */				   ~(0x04000000 >> (y_field+4)));		}	}	/* if PA83, just update the C-bit */	else {		*status = new_status;	}}

⌨️ 快捷键说明

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