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

📄 fpu.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/*	@(#)fpu.c 1.1 92/07/30 SMI;	*/#include <sys/types.h>#include <machine/reg.h>#include <machine/psl.h>#include <machine/buserr.h>#include <machine/trap.h>#include <sun/fault.h>#include <sys/param.h>#include <sys/systm.h>#include <sys/time.h>#include <sys/file.h>#include <sys/proc.h>#include <sys/map.h>#include <sys/user.h>#include <sys/core.h>#include <sys/ptrace.h>#include <machine/fpu/fpu_simulator.h>#include <machine/fpu/globals.h>/* * the global pointer to the current floating point context */#ifdef MULTIPROCESSORextern struct fpu *fp_ctxp;#else MULTIPROCESSORstruct fpu *fp_ctxp = (struct fpu *)0;#endif MULTIPROCESSORstruct fpu *fpu_ctxalloc(){	register struct fpu *fp;	register int i;	fp = (struct fpu *)new_kmem_alloc(sizeof (*fp), KMEM_SLEEP);	fp->fpu_fsr = 0;	/* zero fsr */	i = -1;	fp->fpu_regs[0] = i;	/* initialize registers to NAN */	fp->fpu_regs[1] = i;	fp->fpu_regs[2] = i;	fp->fpu_regs[3] = i;	fp->fpu_regs[4] = i;	fp->fpu_regs[5] = i;	fp->fpu_regs[6] = i;	fp->fpu_regs[7] = i;	fp->fpu_regs[8] = i;	fp->fpu_regs[9] = i;	fp->fpu_regs[10] = i;	fp->fpu_regs[11] = i;	fp->fpu_regs[12] = i;	fp->fpu_regs[13] = i;	fp->fpu_regs[14] = i;	fp->fpu_regs[15] = i;	fp->fpu_regs[16] = i;	fp->fpu_regs[17] = i;	fp->fpu_regs[18] = i;	fp->fpu_regs[19] = i;	fp->fpu_regs[20] = i;	fp->fpu_regs[21] = i;	fp->fpu_regs[22] = i;	fp->fpu_regs[23] = i;	fp->fpu_regs[24] = i;	fp->fpu_regs[25] = i;	fp->fpu_regs[26] = i;	fp->fpu_regs[27] = i;	fp->fpu_regs[28] = i;	fp->fpu_regs[29] = i;	fp->fpu_regs[30] = i;	fp->fpu_regs[31] = i;	return (fp);}fpu_ctxfree(){	register struct pcb *pcb;	pcb = &u.u_pcb;	if (pcb->pcb_fpctxp) {		if (fp_ctxp == pcb->pcb_fpctxp)			fp_ctxp = 0;		kmem_free((caddr_t)pcb->pcb_fpctxp, sizeof (struct fpu));		pcb->pcb_fpctxp = (struct fpu *) 0;	}}/* ARGSUSED */fpu_fork_context(p2, nfp, new_context)struct proc *p2;struct file **nfp;int *new_context;{	register struct fpu *fp;	register struct pcb *pcb;	/*	 * if the current process is using the fpu,	 * allocate a new fp context and initialize it	 * with the current fp context state.	 *	 */	pcb = &u.u_pcb;	if (pcb->pcb_fpctxp) 	{	 	/* we are forking fpu context due to users fork() call.		 * At this time the fpu chip registers belong to the 		 * parent. First dump the registers to the fpu context.		 * then copy the context to the child's context.		 * 	 	 * Child runs first and therefore the fp_ctxp should		 * point to childs fp context. However, the child may not		 * started due to other errors during the rest of the fork.		 * therefore shutoff PSR_EF for the parent and this will be		 * copied to the child in fork(). THen make fp_ctxp 0.		 * This will ensure the child and parent have different 		 * fpu contexts. 		 */		fp_dumpregs((caddr_t)pcb->pcb_fpctxp);			fp = fpu_ctxalloc();		*new_context = (int)fp;		bcopy((caddr_t)pcb->pcb_fpctxp, (caddr_t)fp, sizeof *fp);		u.u_ar0[PS] = u.u_ar0[PS] & ~PSR_EF;		fp_ctxp = 0;	/* current loaded context does not belong				 * to anyone.				 */	}	return (1);}fpu_ofile(){}/* ARGSUSED */fpu_newproc(nfp, new_context, childu)struct file *nfp;int new_context;struct user *childu;{	/*	 * initialize the fp context pointer in the new procs	 * uarea, it was allocated above in fpu_fork_context	 */	childu->u_pcb.pcb_fpctxp = (struct fpu *)new_context;}fpu_core(corep)struct core *corep;{	if (u.u_pcb.pcb_fpctxp)		bcopy((caddr_t)u.u_pcb.pcb_fpctxp, (caddr_t)&corep->c_fpu,			sizeof (struct fpu));}fpu_ptrace(req, p, ipc)enum ptracereq req;struct proc *p;struct ipc *ipc;{	switch (req) {	case PTRACE_GETFPREGS:		runchild(p);		if (copyout((caddr_t)&(ipc->ip_fpu), ipc->ip_addr,		    sizeof (struct fpu)) != 0) {			ipc->ip_error = 1;		}		break;	case PTRACE_SETFPREGS:		if (copyin(ipc->ip_addr, (caddr_t)&ipc->ip_fpu,		    sizeof (struct fpu)) != 0) {			ipc->ip_error = 1;		}		runchild(p);		break;	}}fpu_procxmt(req, ipc)enum ptracereq req;struct ipc *ipc;{	register struct pcb *pcb = &u.u_pcb;	extern int fpu_exists;	extern struct fpu *fpu_ctxalloc();	switch (req) {	case PTRACE_GETFPREGS:		if (pcb->pcb_fpctxp)			bcopy((caddr_t)pcb->pcb_fpctxp, (caddr_t)&ipc->ip_fpu,				sizeof (struct fpu));		break;	case PTRACE_SETFPREGS:		if (fpu_exists && pcb->pcb_fpctxp) {			register u_int i;			for (i = 0; i < 32; i++) {				_fp_write_pfreg((FPU_REGS_TYPE *)&ipc->ip_fpu.fpu_regs[i], i);			}			_fp_write_pfsr(&ipc->ip_fpu.fpu_fsr);		} else {			if (pcb->pcb_fpctxp == (struct fpu *) 0) {				pcb->pcb_fpctxp = fpu_ctxalloc();			}			bcopy((caddr_t)&ipc->ip_fpu, (caddr_t)pcb->pcb_fpctxp,				sizeof (struct fpu));			pcb->pcb_fpflags &= ~FP_UNINITIALIZED;			if (!fpu_exists)				pcb->pcb_fpflags |= FP_DISABLE;		}		break;	default:		return (-1);	}	return (1);}/* * Handle floaing point traps generated by simulation/emulation. */voidfp_traps(pfpsd, ftt, rp)	fp_simd_type	*pfpsd;		/* Pointer to simulator data */	register enum ftt_type ftt;	/* trap type */	register struct regs *rp;	/* ptr to regs fro trap */{	extern void trap();	extern u_int beval;		/* beval is set in trap.c for 					   specific architectures  */	struct regs *saved_fptraprp = 0;	/*	 * If we take a user's exception in kernel mode, we want to trap	 * with the user's registers.  Clear fptraprp in case we don't	 * return from trap.	 */	saved_fptraprp = fptraprp;	if (fptraprp != 0) {		rp = fptraprp;		fptraprp = 0;	}	switch (ftt) {	case ftt_ieee:		trap(T_FP_EXCEPTION, rp, pfpsd->fp_trapaddr,		    pfpsd->fp_trapcode, 0);		break;	case ftt_fault:		trap(T_DATA_FAULT, rp, pfpsd->fp_trapaddr, beval, pfpsd->fp_traprw);		break;	case ftt_alignment:		trap(T_ALIGNMENT, rp, pfpsd->fp_trapaddr, 0, 0);		break;	case ftt_unimplemented:		trap(T_UNIMP_INSTR, rp, pfpsd->fp_trapaddr, 0, 0);		break;	default:		/*		 * We don't expect any of the other types here.		 */		panic("fp_traps: bad ftt");	}	fptraprp = saved_fptraprp;}/* * floating point unit disabled: * One of two possibilities *	1. There is no fpu in the confguration. If so, emulate in SW. * 	2. THere is a FPU in config., however, this is the first time the *   	   process doing a fp op. If so, allocate a fpu context and  *	   turn on the EF bit in the PSR and let the proc go. */fp_is_disabled(rp)struct regs *rp;{     struct fpu *fp;     enum ftt_type ftt;          if (u.u_pcb.pcb_fpctxp == 0) {	  fp = fpu_ctxalloc();	       /* allocate a fpu context */	  uunix->u_pcb.pcb_fpctxp = fp;     }     else 	fp = uunix->u_pcb.pcb_fpctxp;     fp_ctxp = fp;          if (fpu_exists) {	/* there is a fpu, go ahead and enable the fpu */	  if (rp->r_psr&PSR_EF) {	       panic("fp_disabled: no FPU but EF bit set");	       /* NOT REACHED */	  }	  else  {			/* turn on enable fpu bit in the PSR and let the proc go */		rp->r_psr |= PSR_EF;		fp_enable(fp);	  }     } else {		/* no fpu, emulate the instruction */	  fp_simd_type fpsd;	  	  flush_user_windows_to_stack();	  if (ftt = fp_emulator(&fpsd, (fp_inst_type *)rp->r_pc,				rp, (struct rwindow *)rp->r_sp,				(struct fpu *) &fp->fpu_regs[0]))	       fp_traps(&fpsd, ftt, rp);     }}/* * Process the floating point queue * * Each entry in the floating point queue is processed in turn. * If processing an entry results in an exception fp_traps() is called to * handle the exception - this usually results in the generation of a signal * to be delivered to the user. There are 2 possible outcomes to this (note * that hardware generated signals cannot be held!): * *   1. If the signal is being ignored we continue to process the rest *	of the entries in the queue. * *   2. If arrangements have been made for return to a user signal handler, *	sendsig() will have copied the floating point queue onto the user's *	signal stack and zero'ed the queue count in the u_pcb. Note that *	this has the side effect of terminating fp_runq's processing loop. *	We will re-run the floating point queue on return from the user *	signal handler if necessary as part of normal setcontext processing. */voidfp_runq(rp)	register struct regs *rp;	/* ptr to regs for trap */{	register struct fpu *fp =	u.u_pcb.pcb_fpctxp;	register struct fq *fqp =	fp->fpu_q;	fp_simd_type			fpsd;	extern int 			fpu_exists;	/*	 * don't preempt while manipulating the queue	 */	while (fp->fpu_qcnt) {		enum ftt_type fptrap;		fptrap = fpu_simulator((fp_simd_type *)&fpsd,					(fp_inst_type *)fqp->FQu.fpq.addr,					(fsr_type *)&fp->fpu_fsr,					fqp->FQu.fpq.instr);		if (fptrap) {			/*			 * fpu_simulator uses the fp registers directly but it			 * uses the software copy of the fsr. We need to write			 * that back to fpu so that fpu's state is current for			 * ucontext.			 */			if (fpu_exists)				_fp_write_pfsr(&fp->fpu_fsr);			/* post signal */			fp_traps(&fpsd, fptrap, rp);			/*			 * Break from loop to allow signal to be sent.			 */			break;		}		fp->fpu_qcnt--;		fqp++;	}	/*	 * fpu_simulator uses the fp registers directly, so we have	 * to update the pcb copies to keep current, but it uses the	 * software copy of the fsr, so we write that back to fpu	 */	if (fpu_exists) {		register u_int i;		for (i = 0; i < 32; i++)			_fp_read_pfreg((FPU_REGS_TYPE *)&fp->fpu_regs[i], i);		_fp_write_pfsr((FPU_FSR_TYPE *)&fp->fpu_fsr);	}}

⌨️ 快捷键说明

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