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

📄 fp_intr.s

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 S
字号:
/*	@(#)fp_intr.s	4.2	(ULTRIX)	10/9/90	*//************************************************************************ *									* *			Copyright (c) 1988 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* ------------------------------------------------------------------ *//* | Copyright Unpublished, MIPS Computer Systems, Inc.  All Rights | *//* | Reserved.  This software contains proprietary and confidential | *//* | information of MIPS and its suppliers.  Use, disclosure or     | *//* | reproduction is prohibited without the prior express written   | *//* | consent of MIPS.                                               | *//* ------------------------------------------------------------------ *//* * fp_intr.s -- floating pointer interrupt handler *//* * Modification history: * * 27-Sep-1990 jaw *	change to rescheduling signals to be more general * * 29-Mar-1990  gmm/woodward *	Change the way signal sent to a process. Instead of calling *	psignal(), schedule one at low ipl through softnet. * * 13-Oct-1989  gmm *	smp changes. Made fpowner a per cpu variable in cpudata. *      Removed the code to allow hardclock interrupt in fpuintr since *	it was interfering with lock strategy. * * 26-Jan-1989	Kong *	In routine fpuintr, changed the code that allows hardclock *	interrupt from hardwired mask to using the mask in "splm" */#include "../machine/cpu.h"#include "../machine/cpu_board.h"#include "../machine/fpu.h"#include "../machine/reg.h"#include "../machine/regdef.h"#include "../machine/asm.h"#include "../machine/pcb.h"#include "../machine/debug.h"#include "assym.h"#include "../machine/softfp.h"#include "../h/signal.h"#include "../h/proc.h"IMPORT(splm,SPLMSIZE*4)		/* extern splm[SPLMSIZE] *//* * Register setup before calling an interrupt handler (from intr() in  * mips/trap.c through the table of routines c0vec_tbl[]): *	a0 -- exception frame pointer * * This routine is called from a 'C' routine thus the registers are * handled accordingly. * * To get to here there must be some form of floating-point coprocessor * hardware to generate the interrupt. * * The pointer to the proc structure which currently owns the floating point * unit is in fpowner.  And the current values of the floating-point registers * are in the floating-point registers in the coprocessor. * * To exit this routine any modified value of a floating-point register * is just left in that register and then a return to the caller is done. *//* * Floating-point coprocessor interrupt handler */#define	FRAME_SIZE	24#define	LOCAL_SIZE	8#define	A0_OFFSET	FRAME_SIZE+4*0#define	A1_OFFSET	FRAME_SIZE+4*1#define	A2_OFFSET	FRAME_SIZE+4*2#define	A3_OFFSET	FRAME_SIZE+4*3#define	RA_OFFSET	FRAME_SIZE-LOCAL_SIZE+4*0#define	V0_OFFSET	FRAME_SIZE-LOCAL_SIZE+4*1NESTED(fpuintr, FRAME_SIZE, ra)	subu	sp,FRAME_SIZE	sw	ra,RA_OFFSET(sp)	sw	a0,A0_OFFSET(sp)	# save exception frame pointer	.mask	0x80000002, -LOCAL_SIZE	lw	a3,u+PCB_CPUPTR		# get cpudata pointer	lw	a3,CPU_FPOWNER(a3)	# current coproc 1 (fp) owner	beq	a3,zero,strayfp_intr	# coproc 1 not currently owned	/*	 * If the p_fp is P_FP_SIGINTR1 then a SIGFPE is genorated on every	 * floating-point interrupt before each instruction and is then set to	 * P_FP_SIGINTR2.  If p_fp is P_FP_SIGINTR2 then no SIGFPE is genorated	 * but p_fp is set to P_FP_SIGINTR1.	 */	lw	a1,P_FP(a3)	beq	a1,zero,2f	bne	a1,P_FP_SIGINTR1,1f	# We are in state 1, so change to state2 and genorate a SIGFPE	li	a1,P_FP_SIGINTR2	sw	a1,P_FP(a3)	b	12f1:	# We are in state 2, so change to state1 and don't genorate a SIGFPE 	li	a1,P_FP_SIGINTR1	sw	a1,P_FP(a3)2:	.set noreorder	nop	mfc0	a1,C0_SR	# enable coproc 1 for the kernel	nop	or	a1,SR_CU1			nop	mtc0	a1,C0_SR	nop	.set reorder	lw	a3,EF_EPC*4(a0)		# load the epc into a3	# Check the fp implementation so to know were to get the instruction	# and then load it into register a1 where softfp() expects it.	lw	a2,fptype_word	bne	a2,IRR_IMP_R2360,2f	# For board implementations the instruction is in the fpc_eir	# floating-point control register.	sw	a3,V0_OFFSET(sp)	# save the resulting pc (board case)#ifdef XPRBUG	lw	a0,xpr_flags	and	a0,XPR_FPINTR	beq	a0,zero,1f	subu	sp,10*4	la	a0,9f	move	a1,a3	cfc1	a2,fpc_eir	cfc1	a3,fpc_csr	jal	xprintf	MSG("epc = 0x%x eir = 0x%x csr = 0x%x\n")	addu	sp,10*4	lw	a0,A0_OFFSET(sp)	lw	a2,fptype_word1:#endif XPRBUG	cfc1	a1,fpc_eir	b	4f2:	# For chip implementations the floating-point instruction that caused	# the interrupt is at the address of the epc as modified by the branch	# delay bit in the cause register.	lw	a1,0(a3)		# load the instr at the epc into a1	lw	v0,EF_CAUSE*4(a0)	# load the cause register into v0	bltz	v0,3f			# check the branch delay bit		# This is not in a branch delay slot (branch delay bit not set) so	# calculate the resulting pc (epc+4) into v0 and continue to softfp().	addu	v0,a3,4	sw	v0,V0_OFFSET(sp)	# save the resulting pc	b	4f3:	# This is in a branch delay slot so the branch will have to be emulated	# to get the resulting pc (done by calling emulate_branch() ).	# The arguments to emulate_branch are:	#	a0 -- ef (exception frame)	#	a1 -- the branch instruction	#	a2 -- the floating-point control and status register	#	cfc1	a2,fpc_csr		# get value of fpc_csr	jal	emulate_branch		# emulate the branch	sw	v0,V0_OFFSET(sp)	# save the resulting pc	lw	a0,A0_OFFSET(sp)	# restore exception frame pointer	lw	a2,fptype_word		# restore a2 with fptype_word value	lw	a3,EF_EPC*4(a0)		# load the epc into a3	# Now load the floating-point instruction in the branch delay slot	# to be emulated by softfp().	lw	a1,4(a3)4:	/*	 * Check to see if the instruction to be emulated is a floating-point	 * instruction.  If it is not then this interrupt must have been caused	 * by writing to the fpc_csr a value which will caused the interrupt.	 * It is possible however that when writing to the fpc_csr the	 * instruction that is to be "emulated" when the interrupt is handled	 * looks like a floating-point instruction and will incorrectly be	 * emulated and a SIGFPE will not be sent.  This is the user's problem	 * because he shouldn't write a value into the fpc_csr which should	 * cause an interrupt.	 */	srl	a3,a1,OPCODE_SHIFT	beq	a3,OPCODE_C1,10f	/*	 * Setup and call setsoftnet() to send a SIGFPE to the current process.	 */12:	lw	a0,u+PCB_CPUPTR		# get cpudata pointer	lw	a1,CPU_FPOWNER(a0)	# get current fpowner	sw	a1,CPU_FPE_EVENT(a0)	lw	a1,CPU_FPE_SENDSIG(a0)	ori	a1,0x80			# send SIGFPE  (or in mask)	sw	a1,CPU_FPE_SENDSIG(a0)	jal	setsoftnet	# We must clear the coprocessor interrupt without looseing fp	# state, we do this by calling checkfp which will unload	# the fp to the pcb and clear the fp csr.  A signal is	# pending, sendsig will clear the csr in the pcb after	# saving the fp state from the pcb into the sigcontext and	# before calling the signal handler	lw	a0,u+PCB_CPUPTR		# get cpudata pointer	lw	a0,CPU_FPOWNER(a0)	# get current fpowner	move	a1,zero	jal	checkfp	b	8f10:	# For now all instructions that cause an interrupt are just handed	# off to softfp() to emulate it and come up with correct result.	# The arguments to softfp() are:	#	a0 -- ef (exception frame)	#	a1 -- floating-point instruction	#	a2 -- fptype_word	#	# What might have be done is for all exceptions for which the trapped	# result is the same as the untrapped result is: turn off the enables,	# re-excute the instruction, restore the enables and then post a SIGFPE.	jal	softfp	beq	v0,zero,5f	# no signal posted	# We must clear the coprocessor interrupt without looseing fp	# state, we do this by calling checkfp which will unload	# the fp to the pcb and clear the fp csr.  A signal is	# pending, sendsig will clear the csr in the pcb after	# saving the fp state from the pcb into the sigcontext and	# before calling the signal handler	lw	a0,u+PCB_CPUPTR		# get cpudata pointer	lw	a0,CPU_FPOWNER(a0)	# get current fpowner	move	a1,zero	jal	checkfp	b	8f5:#ifdef XPRBUG	lw	a0,xpr_flags	and	a0,XPR_INTR	beq	a0,zero,6f	subu	sp,10*4	la	a0,9f	cfc1	a1,fpc_csr	jal	xprintf	MSG("exit fpuintr csr = 0x%x")	addu	sp,10*46:#endif XPRBUG#ifdef ASSERTIONS	/*	 * If going back to user code without posting a signal there must	 * not be any exceptions which could cause an interrupt.	 */	cfc1	a0,fpc_csr	and	a1,a0,CSR_EXCEPT	# isolate the exception bits	and	a0,CSR_ENABLE 		# isolate the enable bits 	or	a0,(UNIMP_EXC >> 5)	# fake an enable for unimplemented	sll	a0,5			# align both bit sets	and	a0,a1			# check for coresponding bits	beq	a0,zero,7f		# if not then ok	PANIC("fpuintr csr exceptions")7:#endif ASSERTIONS	# Enable fp and hardclock interrupts to allow time to be charged	# to kernel instead of user. This is done since fpuintr is	# higher priority than hardclock. Ok because kernel never does	# floating point. Set it just below clock and fpu.	# Removed the code to lower the priority to enable clock interrupt.	# Other than the unknown side effects of lowering the ipl from an	# interrupt routine, hardclock gets timeout lock which could give	# trouble if run queue lock is already held from swtch(). run queue	# lock is got at splclock(). This change means that at the next clock	# tick, time will be chared to the user.	# The instruction was emulated by softfp() without a signal being	# posted so now change the epc to the target pc.  This is a nop if	# this is the board because we stored the epc in V0_OFFSET when we	# started.	lw	a0,A0_OFFSET(sp)	# restore the exception frame pointer	lw	v0,V0_OFFSET(sp)	# get the resulting pc	sw	v0,EF_EPC*4(a0)		# store the resulting pc in the epc8:	lw	ra,RA_OFFSET(sp)	addu	sp,FRAME_SIZE	j	ra/* * At this point there has been an interrupt from the floating-point * coprocessor but no process was using it. */strayfp_intr:	.set	noreorder	mfc0	a2,C0_SR	# enable coproc 1 for the kernel	or	a3,a2,SR_CU1			mtc0	a3,C0_SR	nop			# before we can really use cp1	nop			# before we can really use cp1	ctc1	zero,fpc_csr	# clear interrupt	mtc0	a2,C0_SR	nop	.set	reorder	lw	a0,fpu_inited	beq	a0,zero,7f		# if not inited then don't complain	PRINTF("stray fp interrupt\012")7:	lw	ra,RA_OFFSET(sp)	addu	sp,FRAME_SIZE	j	ra	.end	fpuintr

⌨️ 快捷键说明

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