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

📄 cp1emu.c

📁 MIPS YAMON, a famous monitor inc. source, make file and PDF manuals.
💻 C
📖 第 1 页 / 共 3 页
字号:
		switch (MIPSInst_FUNC(ir)) {			/* binary ops */		case fadd_op:			handler.b = ieee754sp_add;			goto scopbop;		case fsub_op:			handler.b = ieee754sp_sub;			goto scopbop;		case fmul_op:			handler.b = ieee754sp_mul;			goto scopbop;		case fdiv_op:			handler.b = ieee754sp_div;			goto scopbop;			/* unary  ops */#if __mips >= 2 || __mips64		case fsqrt_op:			handler.u = ieee754sp_sqrt;			goto scopuop;#endif#if __mips >= 4 && __mips != 32		case frsqrt_op:			handler.u = fpemu_sp_rsqrt;			goto scopuop;		case frecip_op:			handler.u = fpemu_sp_recip;			goto scopuop;#endif#if __mips >= 4		case fmovc_op:			cond = fpucondbit[MIPSInst_FT(ir) >> 2];			if (((ctx->sr & cond) != 0) !=			    ((MIPSInst_FT(ir) & 1) != 0))				return 0;			SPFROMREG(rv.s, MIPSInst_FS(ir));			break;		case fmovz_op:			if (xcp->regs[MIPSInst_FT(ir)] != 0)				return 0;			SPFROMREG(rv.s, MIPSInst_FS(ir));			break;		case fmovn_op:			if (xcp->regs[MIPSInst_FT(ir)] == 0)				return 0;			SPFROMREG(rv.s, MIPSInst_FS(ir));			break;#endif		case fabs_op:			handler.u = ieee754sp_abs;			goto scopuop;		case fneg_op:			handler.u = ieee754sp_neg;			goto scopuop;		case fmov_op:			/* an easy one */			SPFROMREG(rv.s, MIPSInst_FS(ir));			goto copcsr;			/* binary op on handler */scopbop:			{				ieee754sp fs, ft;				SPFROMREG(fs, MIPSInst_FS(ir));				SPFROMREG(ft, MIPSInst_FT(ir));				rv.s = (*handler.b) (fs, ft);				goto copcsr;			}scopuop:			{				ieee754sp fs;				SPFROMREG(fs, MIPSInst_FS(ir));				rv.s = (*handler.u) (fs);				goto copcsr;			}copcsr:			if (ieee754_cxtest(IEEE754_INEXACT))				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;			if (ieee754_cxtest(IEEE754_UNDERFLOW))				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;			if (ieee754_cxtest(IEEE754_OVERFLOW))				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;			if (ieee754_cxtest				(IEEE754_INVALID_OPERATION)) rcsr |=					    FPU_CSR_INV_X | FPU_CSR_INV_S;				break;				/* unary conv ops */		case fcvts_op:			return SIGILL;	/* not defined */		case fcvtd_op: {#ifdef SINGLE_ONLY_FPU			return SIGILL;	/* not defined */#else			ieee754sp fs;			SPFROMREG(fs, MIPSInst_FS(ir));			rv.d = ieee754dp_fsp(fs);			rfmt = d_fmt;			goto copcsr;		}#endif		case fcvtw_op: {			ieee754sp fs;			SPFROMREG(fs, MIPSInst_FS(ir));			rv.w = ieee754sp_tint(fs);			rfmt = w_fmt;			goto copcsr;		}#if __mips >= 2 || __mips64		case fround_op:		case ftrunc_op:		case fceil_op:		case ffloor_op: {			unsigned int oldrm = ieee754_csr.rm;			ieee754sp fs;			SPFROMREG(fs, MIPSInst_FS(ir));			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];			rv.w = ieee754sp_tint(fs);			ieee754_csr.rm = oldrm;			rfmt = w_fmt;			goto copcsr;		}#endif /* __mips >= 2 */#if __mips64 && !defined(SINGLE_ONLY_FPU)		case fcvtl_op: {			ieee754sp fs;			SPFROMREG(fs, MIPSInst_FS(ir));			rv.l = ieee754sp_tlong(fs);			rfmt = l_fmt;			goto copcsr;		}		case froundl_op:		case ftruncl_op:		case fceill_op:		case ffloorl_op: {			unsigned int oldrm = ieee754_csr.rm;			ieee754sp fs;			SPFROMREG(fs, MIPSInst_FS(ir));			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];			rv.l = ieee754sp_tlong(fs);			ieee754_csr.rm = oldrm;			rfmt = l_fmt;			goto copcsr;		}#endif /* __mips64 && !fpu(single) */		default:			if (MIPSInst_FUNC(ir) >= fcmp_op) {				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;				ieee754sp fs, ft;				SPFROMREG(fs, MIPSInst_FS(ir));				SPFROMREG(ft, MIPSInst_FT(ir));				rv.w = ieee754sp_cmp (fs, ft,					cmptab[cmpop & 0x7], cmpop & 0x8);				rfmt = -1;				if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;				else					goto copcsr;			} else {				return SIGILL;			}			break;		}		break;	}#if !defined(SINGLE_ONLY_FPU)	case d_fmt: {		union {			ieee754dp (*b)(ieee754dp, ieee754dp);			ieee754dp (*u)(ieee754dp);		} handler;		switch (MIPSInst_FUNC(ir)) {			/* binary ops */		case fadd_op:			handler.b = ieee754dp_add;			goto dcopbop;		case fsub_op:			handler.b = ieee754dp_sub;			goto dcopbop;		case fmul_op:			handler.b = ieee754dp_mul;			goto dcopbop;		case fdiv_op:			handler.b = ieee754dp_div;			goto dcopbop;			/* unary  ops */#if __mips >= 2 || __mips64		case fsqrt_op:			handler.u = ieee754dp_sqrt;			goto dcopuop;#endif#if __mips >= 4 && __mips != 32		case frsqrt_op:			handler.u = fpemu_dp_rsqrt;			goto dcopuop;		case frecip_op:			handler.u = fpemu_dp_recip;			goto dcopuop;#endif#if __mips >= 4		case fmovc_op:			cond = fpucondbit[MIPSInst_FT(ir) >> 2];			if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))				return 0;			DPFROMREG(rv.d, MIPSInst_FS(ir));			break;		case fmovz_op:			if (xcp->regs[MIPSInst_FT(ir)] != 0)				return 0;			DPFROMREG(rv.d, MIPSInst_FS(ir));			break;		case fmovn_op:			if (xcp->regs[MIPSInst_FT(ir)] == 0)				return 0;			DPFROMREG(rv.d, MIPSInst_FS(ir));			break;#endif		case fabs_op:			handler.u = ieee754dp_abs;			goto dcopuop;		case fneg_op:			handler.u = ieee754dp_neg;			goto dcopuop;		case fmov_op:			/* an easy one */			DPFROMREG(rv.d, MIPSInst_FS(ir));			goto copcsr;			/* binary op on handler */dcopbop:			{				ieee754dp fs, ft;				DPFROMREG(fs, MIPSInst_FS(ir));				DPFROMREG(ft, MIPSInst_FT(ir));				rv.d = (*handler.b) (fs, ft);				goto copcsr;			}dcopuop:			{				ieee754dp fs;				DPFROMREG(fs, MIPSInst_FS(ir));				rv.d = (*handler.u) (fs);				goto copcsr;			}		/* unary conv ops */		case fcvts_op: {			ieee754dp fs;			DPFROMREG(fs, MIPSInst_FS(ir));			rv.s = ieee754sp_fdp(fs);			rfmt = s_fmt;			goto copcsr;		}		case fcvtd_op:			return SIGILL;	/* not defined */		case fcvtw_op: {			ieee754dp fs;			DPFROMREG(fs, MIPSInst_FS(ir));			rv.w = ieee754dp_tint(fs);	/* wrong */			rfmt = w_fmt;			goto copcsr;		}#if __mips >= 2 || __mips64		case fround_op:		case ftrunc_op:		case fceil_op:		case ffloor_op: {			unsigned int oldrm = ieee754_csr.rm;			ieee754dp fs;			DPFROMREG(fs, MIPSInst_FS(ir));			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];			rv.w = ieee754dp_tint(fs);			ieee754_csr.rm = oldrm;			rfmt = w_fmt;			goto copcsr;		}#endif#if __mips64 && !defined(SINGLE_ONLY_FPU)		case fcvtl_op: {			ieee754dp fs;			DPFROMREG(fs, MIPSInst_FS(ir));			rv.l = ieee754dp_tlong(fs);			rfmt = l_fmt;			goto copcsr;		}		case froundl_op:		case ftruncl_op:		case fceill_op:		case ffloorl_op: {			unsigned int oldrm = ieee754_csr.rm;			ieee754dp fs;			DPFROMREG(fs, MIPSInst_FS(ir));			ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];			rv.l = ieee754dp_tlong(fs);			ieee754_csr.rm = oldrm;			rfmt = l_fmt;			goto copcsr;		}#endif /* __mips >= 3 && !fpu(single) */		default:			if (MIPSInst_FUNC(ir) >= fcmp_op) {				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;				ieee754dp fs, ft;				DPFROMREG(fs, MIPSInst_FS(ir));				DPFROMREG(ft, MIPSInst_FT(ir));				rv.w = ieee754dp_cmp (fs, ft, cmptab[cmpop & 0x7], cmpop & 0x8);				rfmt = -1;				if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;				else					goto copcsr;			} else {				return SIGILL;			}			break;		}		break;	}#endif /* !defined(SINGLE_ONLY_FPU) */	case w_fmt: {		ieee754sp fs;		switch (MIPSInst_FUNC(ir)) {		case fcvts_op:			/* convert word to single precision real */			SPFROMREG(fs, MIPSInst_FS(ir));			rv.s = ieee754sp_fint(fs.bits);			rfmt = s_fmt;			goto copcsr;#if !defined(SINGLE_ONLY_FPU)		case fcvtd_op:			/* convert word to double precision real */			SPFROMREG(fs, MIPSInst_FS(ir));			rv.d = ieee754dp_fint(fs.bits);			rfmt = d_fmt;			goto copcsr;#endif		default:			return SIGILL;		}		break;	}#if __mips64 && !defined(SINGLE_ONLY_FPU)	case l_fmt: {		switch (MIPSInst_FUNC(ir)) {		case fcvts_op:			/* convert long to single precision real */			rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);			rfmt = s_fmt;			goto copcsr;		case fcvtd_op:			/* convert long to double precision real */			rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);			rfmt = d_fmt;			goto copcsr;		default:			return SIGILL;		}		break;	}#endif	default:		return SIGILL;	}	/*	 * Update the fpu CSR register for this operation.	 * If an exception is required, generate a tidy SIGFPE exception,	 * without updating the result register.	 * Note: cause exception bits do not accumulate, they are rewritten	 * for each op; only the flag/sticky bits accumulate.	 */	ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;	if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */		return SIGFPE;	}	/* 	 * Now we can safely write the result back to the register file.	 */	switch (rfmt) {	case -1: {#if __mips >= 4		cond = fpucondbit[MIPSInst_FD(ir) >> 2];#else		cond = FPU_CSR_COND;#endif		if (rv.w)			ctx->sr |= cond;		else			ctx->sr &= ~cond;		break;	}#if !defined(SINGLE_ONLY_FPU)	case d_fmt:		DPTOREG(rv.d, MIPSInst_FD(ir));		break;#endif	case s_fmt:		SPTOREG(rv.s, MIPSInst_FD(ir));		break;	case w_fmt:		SITOREG(rv.w, MIPSInst_FD(ir));		break;#if __mips64 && !defined(SINGLE_ONLY_FPU)	case l_fmt:		DITOREG(rv.l, MIPSInst_FD(ir));		break;#endif	default:		return SIGILL;	}	return 0;}int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp,       	struct mips_fpu_soft_struct *ctx){        gpreg_t oldepc, prevepc;        mips_instruction insn, *insnp;        int sig = 0;        oldepc = xcp->cp0_epc;        do {                prevepc = xcp->cp0_epc;                /*                 * This is a braindead way to do it but the only sane way I                 * found to keep the 64-bit egcs 1.1.2 from crashing.                 */                insnp = (mips_instruction *) REG_TO_VA xcp->cp0_epc;                if (verify_area(VERIFY_READ, insnp, 4) ||                    __get_user(insn, insnp)) {                        fpuemuprivate.stats.errors++;                        return SIGBUS;                }                if (insn == 0)                        xcp->cp0_epc += 4;      /* skip nops */                else {                        /* Update ieee754_csr. Only relevant if we have a                           h/w FPU */                        ieee754_csr.nod = (ctx->sr & 0x1000000) != 0;                        ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];                        ieee754_csr.cx = (ctx->sr >> 12) & 0x1f;                        sig = cop1Emulate(xcp, ctx);                }                if (sig)                        break;#ifdef STANDALONE_EMULATOR		if (xcptno == EX_FPE)			break;#else                if (mips_cpu.options & MIPS_CPU_FPU)                        break;                if (current->need_resched)                        schedule();#endif        } while (xcp->cp0_epc > prevepc);        /* SIGILL indicates a non-fpu instruction */        if (sig == SIGILL && xcp->cp0_epc != oldepc) {                /* but if epc has advanced, then ignore it */	        fpuemuprivate.stats.emulated--;                sig = 0;	}        return sig;}

⌨️ 快捷键说明

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