ctx->fcr31 = value; /* copy new rounding mode and flush bit to ieee library state! */ ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0; ieee754_csr.rm = ieee_rm[value & 0x3]; 
value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); /* convert to ieee library modes */ ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3]; 
static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx){	mips_instruction ir;	void * emulpc, *contpc;	unsigned int cond;	if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) {		fpuemuprivate.stats.errors++;		return SIGBUS;	}	/* XXX NEC Vr54xx bug workaround */	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))		xcp->cp0_cause &= ~CAUSEF_BD;	if (xcp->cp0_cause & CAUSEF_BD) {		/*		 * The instruction to be emulated is in a branch delay slot		 * which means that we have to  emulate the branch instruction		 * BEFORE we do the cop1 instruction.		 *		 * This branch could be a COP1 branch, but in that case we		 * would have had a trap for that instruction, and would not		 * come through this route.		 *		 * Linux MIPS branch emulator operates on context, updating the		 * cp0_epc.		 */		emulpc = (void *) (xcp->cp0_epc + 4);	/* Snapshot emulation target */		if (__compute_return_epc(xcp)) {#ifdef CP1DBG			printk("failed to emulate branch at %p\n",				(void *) (xcp->cp0_epc));#endif			return SIGILL;		}		if (get_user(ir, (mips_instruction *) emulpc)) {			fpuemuprivate.stats.errors++;			return SIGBUS;		}		/* __compute_return_epc() will have updated cp0_epc */		contpc = (void *)  xcp->cp0_epc;		/* In order not to confuse ptrace() et al, tweak context */		xcp->cp0_epc = (unsigned long) emulpc - 4;	} else {		emulpc = (void *)  xcp->cp0_epc;		contpc = (void *) (xcp->cp0_epc + 4);	}      emul:	fpuemuprivate.stats.emulated++;	switch (MIPSInst_OPCODE(ir)) {#ifndef SINGLE_ONLY_FPU	case ldc1_op:{		u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +			MIPSInst_SIMM(ir));		u64 val;		fpuemuprivate.stats.loads++;		if (get_user(val, va)) {			fpuemuprivate.stats.errors++;			return SIGBUS;		}		DITOREG(val, MIPSInst_RT(ir));		break;	}	case sdc1_op:{		u64 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +			MIPSInst_SIMM(ir));		u64 val;		fpuemuprivate.stats.stores++;		DIFROMREG(val, MIPSInst_RT(ir));		if (put_user(val, va)) {			fpuemuprivate.stats.errors++;			return SIGBUS;		}		break;	}#endif	case lwc1_op:{		u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +			MIPSInst_SIMM(ir));		u32 val;		fpuemuprivate.stats.loads++;		if (get_user(val, va)) {			fpuemuprivate.stats.errors++;			return SIGBUS;		}#ifdef SINGLE_ONLY_FPU		if (MIPSInst_RT(ir) & 1) {			/* illegal register in single-float mode */			return SIGILL;		}#endif		SITOREG(val, MIPSInst_RT(ir));		break;	}	case swc1_op:{		u32 *va = (void *) (xcp->regs[MIPSInst_RS(ir)] +			MIPSInst_SIMM(ir));		u32 val;		fpuemuprivate.stats.stores++;#ifdef SINGLE_ONLY_FPU		if (MIPSInst_RT(ir) & 1) {			/* illegal register in single-float mode */			return SIGILL;		}#endif		SIFROMREG(val, MIPSInst_RT(ir));		if (put_user(val, va)) {			fpuemuprivate.stats.errors++;			return SIGBUS;		}		break;	}	case cop1_op:		switch (MIPSInst_RS(ir)) {#if defined(__mips64) && !defined(SINGLE_ONLY_FPU)		case dmfc_op:			/* copregister fs -> gpr[rt] */			if (MIPSInst_RT(ir) != 0) {				DIFROMREG(xcp->regs[MIPSInst_RT(ir)],					MIPSInst_RD(ir));			}			break;		case dmtc_op:			/* copregister fs <- rt */			DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));			break;#endif		case mfc_op:			/* copregister rd -> gpr[rt] */#ifdef SINGLE_ONLY_FPU			if (MIPSInst_RD(ir) & 1) {				/* illegal register in single-float mode */				return SIGILL;			}#endif			if (MIPSInst_RT(ir) != 0) {				SIFROMREG(xcp->regs[MIPSInst_RT(ir)],					MIPSInst_RD(ir));			}			break;		case mtc_op:			/* copregister rd <- rt */#ifdef SINGLE_ONLY_FPU			if (MIPSInst_RD(ir) & 1) {				/* illegal register in single-float mode */				return SIGILL;			}#endif			SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));			break;		case cfc_op:{			/* cop control register rd -> gpr[rt] */			u32 value;			if (ir == CP1UNDEF) {				return do_dsemulret(xcp);			}			if (MIPSInst_RD(ir) == FPCREG_CSR) {				value = ctx->fcr31;#ifdef CSRTRACE				printk("%p gpr[%d]<-csr=%08x\n",					(void *) (xcp->cp0_epc),					MIPSInst_RT(ir), value);#endif			}			else if (MIPSInst_RD(ir) == FPCREG_RID)				value = 0;			else				value = 0;			if (MIPSInst_RT(ir))				xcp->regs[MIPSInst_RT(ir)] = value;			break;		}		case ctc_op:{			/* copregister rd <- rt */			u32 value;			if (MIPSInst_RT(ir) == 0)				value = 0;			else				value = xcp->regs[MIPSInst_RT(ir)];			/* we only have one writable control reg			 */			if (MIPSInst_RD(ir) == FPCREG_CSR) {#ifdef CSRTRACE				printk("%p gpr[%d]->csr=%08x\n",					(void *) (xcp->cp0_epc),					MIPSInst_RT(ir), value);#endif				ctx->fcr31 = value;				/* copy new rounding mode and				   flush bit to ieee library state! */				ieee754_csr.nod = (ctx->fcr31 & 0x1000000) != 0;				ieee754_csr.rm = ieee_rm[value & 0x3];			}			if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {				return SIGFPE;			}			break;		}		case bc_op:{			int likely = 0;			if (xcp->cp0_cause & CAUSEF_BD)				return SIGILL;#if __mips >= 4			cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];#else			cond = ctx->fcr31 & FPU_CSR_COND;#endif			switch (MIPSInst_RT(ir) & 3) {			case bcfl_op:				likely = 1;			case bcf_op:				cond = !cond;				break;			case bctl_op:				likely = 1;			case bct_op:				break;			default:				/* thats an illegal instruction */				return SIGILL;			}			xcp->cp0_cause |= CAUSEF_BD;			if (cond) {				/* branch taken: emulate dslot				 * instruction				 */				xcp->cp0_epc += 4;				contpc = (void *)					(xcp->cp0_epc +					(MIPSInst_SIMM(ir) << 2));				if (get_user(ir, (mips_instruction *)						(void *)  xcp->cp0_epc)) {					fpuemuprivate.stats.errors++;					return SIGBUS;				}				switch (MIPSInst_OPCODE(ir)) {				case lwc1_op:				case swc1_op:#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)				case ldc1_op:				case sdc1_op:#endif				case cop1_op:#if __mips >= 4 && __mips != 32				case cop1x_op:#endif					/* its one of ours */					goto emul;#if __mips >= 4				case spec_op:					if (MIPSInst_FUNC(ir) == movc_op)						goto emul;					break;#endif				}				/*				 * Single step the non-cp1				 * instruction in the dslot				 */				return mips_dsemul(xcp, ir, (unsigned long) contpc);			}			else {				/* branch not taken */				if (likely) {					/*					 * branch likely nullifies					 * dslot if not taken					 */					xcp->cp0_epc += 4;					contpc += 4;					/*					 * else continue & execute					 * dslot as normal insn					 */				}			}			break;		}		default:			if (!(MIPSInst_RS(ir) & 0x10))				return SIGILL;			{				int sig;				/* a real fpu computation instruction */				if ((sig = fpu_emu(xcp, ctx, ir)))					return sig;			}		}		break;#if __mips >= 4 && __mips != 32	case cop1x_op:{		int sig;		if ((sig = fpux_emu(xcp, ctx, ir)))			return sig;		break;	}#endif#if __mips >= 4	case spec_op:		if (MIPSInst_FUNC(ir) != movc_op)			return SIGILL;		cond = fpucondbit[MIPSInst_RT(ir) >> 2];		if (((ctx->fcr31 & cond) != 0) == ((MIPSInst_RT(ir) & 1) != 0))			xcp->regs[MIPSInst_RD(ir)] =				xcp->regs[MIPSInst_RS(ir)];		break;#endif	default:		return SIGILL;	}	/* we did it !! */	xcp->cp0_epc = (unsigned long) contpc;	xcp->cp0_cause &= ~CAUSEF_BD;	return 0;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/cd21dfcfbb5c43de54f6be795dde07397da2bc2f/cp1emu.c/buggy/arch/mips/math-emu/cp1emu.c