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

📄 fpintr.s

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 S
字号:
/* fpIntr.s - floating point interrupt handler *//* Copyright 1984-2001 Wind River Systems, Inc. */	.data	.globl	copyright_wind_river/* * This file has been developed or significantly modified by the * MIPS Center of Excellence Dedicated Engineering Staff. * This notice is as per the MIPS Center of Excellence Master Partner * Agreement, do not remove this notice without checking first with * WR/Platforms MIPS Center of Excellence engineering management. *//*modification history--------------------01r,17may02,pes  SPR #72943: Corrected Unimplemented Operation exception                 behavior.01q,01aug01,mem  Diab integration01p,16jul01,ros  add CofE comment01o,05sep00,dra  Updated FP emulation, added 32 FP support.01n,13jun00,dra  correct cdf file discrepancies01m,01nov99,dra  Fixed handling of stray FP exceptions when SR_CU1 bit is                 clear.01l,16aug99,dra  updated for vxWorks6.01k,12aug98,kkk  fixed bug in saving FPCSR in fpIntr, now it's saved		 in excStub. (SPR# 20669)01j,08mar97,kkk  took out saving of registers in fpIntr() for R3000.01i,10dec96,tam  replaced CPU_R3XXX macros.01h,02feb96,mem  Added decoding of FPU exception cause.  Fixed forwarding	         of exceptions.01g,18oct93,cd   added R4000 support.01f,01sep93,yao  removed ifdef.  changed not to read fpcsr when fpu		 is not available.  redefined stack offset constants.01e,05jun92,ajm  ifdef'd out unused code for now01d,26may92,rrr  the tree shuffle		  -changed includes to have absolute path from h/01c,04oct91,rrr  passed through the ansification filter		  -fixed #else and #endif		  -changed ASMLANGUAGE to _ASMLANGUAGE		  -changed copyright notice01b,29aug91,wmd   moved to r3k/math directory, chg'd softFp.h->fpSoft.h.01a,22jul91,ajm   wrs-ized from MIPS code*//* * |-----------------------------------------------------------| * | Copyright (c) 1990 MIPS Computer Systems, Inc.            | * | All Rights Reserved                                       | * |-----------------------------------------------------------| * |          Restricted Rights Legend                         | * | Use, duplication, or disclosure by the Government is      | * | subject to restrictions as set forth in                   | * | subparagraph (c)(1)(ii) of the Rights in Technical        | * | Data and Computer Software Clause of DFARS 52.227-7013.   | * |         MIPS Computer Systems, Inc.                       | * |         950 DeGuigne Drive                                | * |         Sunnyvale, CA 94086                               | * |-----------------------------------------------------------| *//*DESCRIPTIONThis library contains the MIPS floating point interrupt handler.To get to into this library there must be some form of floating-pointcoprocessor hardware to generate the interrupt/exception.  Because floatingpoint operations should not be executed at interrupt level, FPA exceptionsshould always come from the current executing task, and taskIdCurrentwill contain the TID of the task executing the FPA instruction.  Thehandler clears the FPA exception and decides whether to ignore theexception, signal on the condition, or emulate the FPA instruction.The current values of the floating-point registers are in the floatingpoint registers in the coprocessor.The register state on entry to this routine is:    a0 - vector number    a1 - exception stack pointerUpon exit of this routine any modified value of a floating-point registeris just left in that register and then a return to the caller is done.The caller is the routine excIntStub which will restore the processor stateand call the kernel.  If the kernel decides it is necessary to reschedule,the FPA switch hook routines will save and restore the new FPA state for thecurrent process.*/#define _ASMLANGUAGE#include "vxWorks.h"#include "esf.h"#include "fppLib.h"#include "arch/mips/archMips.h"#include "arch/mips/excMipsLib.h"#include "private/taskLibP.h"#include "arch/mips/fpSoft.h"#include "asm.h"#include "iv.h"#ifndef WIND_TCB_OPTIONS#include "taskLib.h"#define WIND_TCB_OPTIONS	0x38#define WIND_TCB_PFPCONTEXT	0xc0#endif	/* defines */#define DEBUG#define VX_FP_TASK              0x0008		/* XXX */#define	FRAMETID(routine)	FRAMER0(routine)#define	FRAMEEPC(routine)	FRAMER1(routine)	.globl	GTEXT(excExcHandle)		/* exc handler */	.text	.set	reorder/******************************************************************************* fpIntr - Interrupt handler for MIPS floating point unit** On entry:*  a0:	vecNum*  a1:	ESFMIPS **  a2:	REG_SET **/	.globl	GTEXT(fpIntr)	.ent	fpIntrFUNC_LABEL(fpIntr)	SETFRAME(fpIntr,2)	.frame	sp, FRAMESZ(fpIntr), ra	subu	sp, FRAMESZ(fpIntr)	SW	ra, FRAMERA(fpIntr)(sp)	sw	a0, FRAMEA0(fpIntr)(sp)	/* save vector */	sw	a1, FRAMEA1(fpIntr)(sp)	/* save pEsf *//*	.mask	0x80000002, -LOCAL_SIZE */	lw	t0, taskIdCurrent	move	t1, a0			/* save vector */	sw	t0, FRAMETID(fpIntr)(sp) /* save taskIdCurrent */	move	a0, a1			/* a0 becomes pEsf */#if FALSE#if	(CPU == R3000)    /*    *  Save regs that excIntStub would not have.  This is necessary    *  for branch emulation, and signals.    */	sw	zero, E_STK_ZERO(a0)		/* save zero  reg */	sw	s0, E_STK_S0(a0)		/* save saved reg 0 */	sw	s1, E_STK_S1(a0)		/* save saved reg 1 */	sw	s2, E_STK_S2(a0)		/* save saved reg 2 */	sw	s3, E_STK_S3(a0)		/* save saved reg 3 */	sw	s4, E_STK_S4(a0)		/* save saved reg 4 */	sw	s5, E_STK_S5(a0)		/* save saved reg 5 */	sw	s6, E_STK_S6(a0)		/* save saved reg 6 */	sw	s7, E_STK_S7(a0)		/* save saved reg 7 */	sw	s8, E_STK_FP(a0)		/* save frame pointer */	sw	gp, E_STK_GP(a0)		/* save global pointer */#endif	/* CPU == R3000 */#endif /* FALSE */	subu	t1, t1, EXC_CODE_FPU		/* get exception type */	sw	t1, FRAMEA2(fpIntr)(sp)		/* save exception type */	beq	t1, zero, noFpu	lw	t0, E_STK_FPCSR(a0)             /* load FPCSR from stack */#ifdef DEBUG	/* At this point, t0 holds the unmodified fpscr reg value. */	.comm	_fp_fpscr, 4	sw	t0, _fp_fpscr#endif		/*	 * The following doesn't seem to handle well the case on the R4000	 * where the SR_FR bit in the task's status register was clear	 * and the task referenced an odd floating point register.	 */		/* check for unimplemented operation */	li	t1, FP_EXC_E	and	t1, t0, t1	bnez	t1, noFpu		/*	 * If the cause of the FP exception was something other than a	 * unimplemented operation exception, divert the exception to the	 * proper exception handler.	 */		/* check for inexact operation */	li	a0, EXC_CODE_FPE_INEXACT	li	t1, FP_EXC_I	and	t1, t0, t1	bnez	t1, fpuForwardExc		/* check for underflow */	li	a0, EXC_CODE_FPE_UNDERFLOW	li	t1, FP_EXC_U	and	t1, t0, t1	bnez	t1, fpuForwardExc		/* check for overflow */	li	a0, EXC_CODE_FPE_OVERFLOW	li	t1, FP_EXC_O	and	t1, t0, t1	bnez	t1, fpuForwardExc		/* check for divide by zero */	li	a0, EXC_CODE_FPE_DIV0	li	t1, FP_EXC_Z	and	t1, t0, t1	bnez	t1, fpuForwardExc		/* check for invalid operation */	li	a0, EXC_CODE_FPE_INVALID	li	t1, FP_EXC_V	and	t1, t0, t1	bnez	t1, fpuForwardExc		/* shouldn't get here */	li	a0, EXC_CODE_RI	b	fpuForwardExc	noFpu:	lw	a3, E_STK_SR(a0)	/* SR at time of exception */	and	a3, SR_CU1		/* FPU usable bit */	beq	a3, zero, 0f		/* FPU off - no FP allowed */	lw	a3, FRAMETID(fpIntr)(sp)/* get current excecuting task */	lw	a2, WIND_TCB_OPTIONS(a3)/* read options field */	andi	a2, VX_FP_TASK		/* mask all but VX_FP_TASK bit */	bnez	a2, 1f			/* are we allowed to use fp unit */0:	/*	 * At this point there has been an exception from the floating-point	 * coprocessor but the current task was not allowed to use it.	 * This isn't really good enough, the task probably *is* using floating	 * point but the kernel won't be saving its state...	 */		la	a0, strayString	jal	logMsg			/* let us know about strays */		li	a0, IV_CPU_VEC		/* translates to SIGILL */	b	send_signal1:	lw	a0, FRAMEA1(fpIntr)(sp)	/* pEsf to a0 */ 	lw	a3, E_STK_EPC(a0)	/* load the epc into a3 */	lw	a1, 0(a3)		/* load the instr at the epc into a1 */	lw	v0, E_STK_CAUSE(a0)	/* load the cause register into v0 */	#ifdef DEBUG	/* count of number of exceptions seen */	.comm	_fp_epc, 4	.comm	_fp_cause, 4	sw	a3, _fp_epc	sw	v0, _fp_cause#endif		bltz	v0, 3f			/* in branch delay slot ? */	/*	 * 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, FRAMEEPC(fpIntr)(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 emulateBranch() ).	 * The arguments to emulateBranch are:	 *     a0 - pEsf (exception stack)	 *     a1 - the branch instruction	 *     a2 - the floating-point control and status register	 */	lw	a2, E_STK_FPCSR(a0)	/* get value of C1_SR */	jal	fppEmulateBranch	/* emulate the branch */	bne	v0, 1, emulateOk		/* failed to emulate branch correctly */	li      a0, IV_CPU_VEC		/* translates to SIGILL */	b	send_signalemulateOk:	sw	v0, FRAMEEPC(fpIntr)(sp)	/* save the resulting pc */	lw	a0, FRAMEA1(fpIntr)(sp)	/* restore exception stack pointer */	lw	a3, E_STK_EPC(a0)	/* load the epc into a3 */	lw	a1,4(a3)	/* get instruction to be emulated from BD slot */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 C1_SR a value which will cause an interrupt.	 * It is possible however that when writing to the C1_SR 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 SIGILL will not be sent.  This is the user's problem	 * because he shouldn't write a value into the C1_SR which should	 * cause an interrupt.	 *	 * 5/20/2002 pes - We can also get to this point if we are trying to	 * emulate an opcode other than OPCODE_C1. Given that we don't know	 * whether the software FP emulator can handle other opcodes,	 * it is now deemed more likely for the problem to be unimplemented	 * opcodes than generating an interrupt with a value written to C1_SR.	 *	 */	srl	a3,a1,OPCODE_SHIFT	beq	a3,OPCODE_C1,10f	/*	 * Assume the emulator can't handle any opcode other than OPCODE_C1.	 * Report as Unimplemented FPA operation.	 */	li	a0, IV_FPA_UNIMP_VEC	b	send_signal10:	/*	 * 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 - pEsf (exception stack)	 *	a1 - floating-point instruction	 *	a2 - fpuIsAlive	 *	a3 - taskIdCurrent	 *	 * 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.	 */	lw	a2, FRAMEA2(fpIntr)(sp)	/* load exception type */	lw	t0, FRAMETID(fpIntr)(sp)/* get current excecuting task */	lw	a3, WIND_TCB_PFPCONTEXT(t0)	/* read pFpContext - FIX */	jal	softFp			/* emulate away */	bne	v0,zero,8f		/* signal posted */#ifdef ASSERTIONS	/*	 * If going back to user code without posting a signal there must	 * not be any exceptions which could cause an interrupt.	 */	lw	a0, E_STK_FPCSR(a0)	/* get fp status reg   */	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 corresponding bits */	beq	a0,zero,7f		/* if not then ok */	PANIC("fpIntr csr exceptions")7:#endif	/* ASSERTIONS */	/*	 * The instruction was emulated by softFp() without a signal being	 * posted so now change the epc to the target pc.	 */	lw	a0, FRAMEA1(fpIntr)(sp)	 /* restore the exception stack pointer */	lw	v0, FRAMEEPC(fpIntr)(sp) /* get the resulting pc */	sw	v0, E_STK_EPC(a0)	/* store the resulting pc in the epc */	b	8fstrayFpExc:	8:	LW	ra,FRAMERA(fpIntr)(sp)	addu	sp,FRAMESZ(fpIntr)	j	ra	send_signal:fpuForwardExc:	/* Force coprocessor unusable exceptions to excExcHandle */	la	v0, IV_CPU_VEC	beq	a0, v0, fpuForceExc		/*	 * An FPU exception that we can't handle, forward to the	 * exception vector entered in excBsrTbl[].	 *	a0 - vector #	 * Simply load up the vector from excBsrTbl[] and jump to fpuExc.	 */	sll	v0, a0, 2	la	t0, excBsrTbl	addu	t0, v0	lw	v0, (t0)	b	fpuExc	fpuForceExc:	/*	 * An FPU exception that we can't handle, force a call	 * to excExcHandle, do not use the excBsrTbl[] exception table.	 */	la	v0, excExcHandle	fpuExc:	/*	 * Undo our frame and call the specified exception handler	 * exception vector entered in excBsrTbl[].	 *	a0 - vector #	 *	v0 - exception handler to call.	 */#ifdef DEBUG	.comm	_fp_exc, 4	sw	a0, _fp_exc		.comm	_fp_exc_vec, 4	sw	v0, _fp_exc_vec#endif		lw	a1, FRAMEA1(fpIntr)(sp) /* pEsf to a1 */ 	la	a2, E_STK_SR(a1)	/* pass general register ptr */		/* undo our stack frame */	LW	ra,FRAMERA(fpIntr)(sp)	addu	sp,FRAMESZ(fpIntr)		/* tail call to the exception handler, we don't return here. */	jr	v0		.end	fpIntr/******************************************************************************** strayString -**/	.rdatastrayString:	.ascii	"Stray fp exception\n"	.byte	0

⌨️ 快捷键说明

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