From 2b3e9d9b244e279ef5693a7cf5dacc7903164af5 Mon Sep 17 00:00:00 2001 From: Ralf Corsepius Date: Mon, 22 Jul 2002 09:46:48 +0000 Subject: Remove, moved to cpukit. --- c/src/exec/score/cpu/mips/cpu_asm.S | 1051 ----------------------------------- 1 file changed, 1051 deletions(-) delete mode 100644 c/src/exec/score/cpu/mips/cpu_asm.S (limited to 'c/src/exec/score/cpu/mips/cpu_asm.S') diff --git a/c/src/exec/score/cpu/mips/cpu_asm.S b/c/src/exec/score/cpu/mips/cpu_asm.S deleted file mode 100644 index 9614705e44..0000000000 --- a/c/src/exec/score/cpu/mips/cpu_asm.S +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * This file contains the basic algorithms for all assembly code used - * in an specific CPU port of RTEMS. These algorithms must be implemented - * in assembly language - * - * History: - * Baseline: no_cpu - * 1996: Ported to MIPS64ORION by Craig Lebakken - * COPYRIGHT (c) 1996 by Transition Networks Inc. - * To anyone who acknowledges that the modifications to this file to - * port it to the MIPS64ORION are provided "AS IS" without any - * express or implied warranty: - * permission to use, copy, modify, and distribute this file - * for any purpose is hereby granted without fee, provided that - * the above copyright notice and this notice appears in all - * copies, and that the name of Transition Networks not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Transition - * Networks makes no representations about the suitability - * of this software for any purpose. - * 2000: Reworked by Alan Cudmore to become - * the baseline of the more general MIPS port. - * 2001: Joel Sherrill continued this rework, - * rewriting as much as possible in C and added the JMR3904 BSP - * so testing could be performed on a simulator. - * 2001: Greg Menke , bench tested ISR - * performance, tweaking this code and the isr vectoring routines - * to reduce overhead & latencies. Added optional - * instrumentation as well. - * 2002: Greg Menke , overhauled cpu_asm.S, - * cpu.c and cpu.h to manage FP vs int only tasks, interrupt levels - * and deferred FP contexts. - * 2002: Joel Sherrill enhanced the exception processing - * by increasing the amount of context saved/restored. - * - * COPYRIGHT (c) 1989-2002. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.OARcorp.com/rtems/license.html. - * - * $Id$ - */ - -#include -#include "iregdef.h" -#include "idtcpu.h" - -#define ASSEMBLY_ONLY -#include - - -/* enable debugging shadow writes to misc ram, this is a vestigal -* Mongoose-ism debug tool- but may be handy in the future so we -* left it in... -*/ - -/* #define INSTRUMENT_ISR_VECTORING */ -/* #define INSTRUMENT_EXECUTING_THREAD */ - - - -/* Ifdefs prevent the duplication of code for MIPS ISA Level 3 ( R4xxx ) - * and MIPS ISA Level 1 (R3xxx). - */ - -#if __mips == 3 -/* 64 bit register operations */ -#define NOP -#define ADD dadd -#define STREG sd -#define LDREG ld -#define MFCO dmfc0 -#define MTCO dmtc0 -#define ADDU addu -#define ADDIU addiu -#define R_SZ 8 -#define F_SZ 8 -#define SZ_INT 8 -#define SZ_INT_POW2 3 - -/* XXX if we don't always want 64 bit register ops, then another ifdef */ - -#elif __mips == 1 -/* 32 bit register operations*/ -#define NOP nop -#define ADD add -#define STREG sw -#define LDREG lw -#define MFCO mfc0 -#define MTCO mtc0 -#define ADDU add -#define ADDIU addi -#define R_SZ 4 -#define F_SZ 4 -#define SZ_INT 4 -#define SZ_INT_POW2 2 -#else -#error "mips assembly: what size registers do I deal with?" -#endif - - -#define ISR_VEC_SIZE 4 -#define EXCP_STACK_SIZE (NREGS*R_SZ) - - -#ifdef __GNUC__ -#define ASM_EXTERN(x,size) .extern x,size -#else -#define ASM_EXTERN(x,size) -#endif - -/* NOTE: these constants must match the Context_Control structure in cpu.h */ -#define S0_OFFSET 0 -#define S1_OFFSET 1 -#define S2_OFFSET 2 -#define S3_OFFSET 3 -#define S4_OFFSET 4 -#define S5_OFFSET 5 -#define S6_OFFSET 6 -#define S7_OFFSET 7 -#define SP_OFFSET 8 -#define FP_OFFSET 9 -#define RA_OFFSET 10 -#define C0_SR_OFFSET 11 -#define C0_EPC_OFFSET 12 - -/* NOTE: these constants must match the Context_Control_fp structure in cpu.h */ -#define FP0_OFFSET 0 -#define FP1_OFFSET 1 -#define FP2_OFFSET 2 -#define FP3_OFFSET 3 -#define FP4_OFFSET 4 -#define FP5_OFFSET 5 -#define FP6_OFFSET 6 -#define FP7_OFFSET 7 -#define FP8_OFFSET 8 -#define FP9_OFFSET 9 -#define FP10_OFFSET 10 -#define FP11_OFFSET 11 -#define FP12_OFFSET 12 -#define FP13_OFFSET 13 -#define FP14_OFFSET 14 -#define FP15_OFFSET 15 -#define FP16_OFFSET 16 -#define FP17_OFFSET 17 -#define FP18_OFFSET 18 -#define FP19_OFFSET 19 -#define FP20_OFFSET 20 -#define FP21_OFFSET 21 -#define FP22_OFFSET 22 -#define FP23_OFFSET 23 -#define FP24_OFFSET 24 -#define FP25_OFFSET 25 -#define FP26_OFFSET 26 -#define FP27_OFFSET 27 -#define FP28_OFFSET 28 -#define FP29_OFFSET 29 -#define FP30_OFFSET 30 -#define FP31_OFFSET 31 - - -ASM_EXTERN(__exceptionStackFrame, SZ_INT) - - - -/* - * _CPU_Context_save_fp_context - * - * This routine is responsible for saving the FP context - * at *fp_context_ptr. If the point to load the FP context - * from is changed then the pointer is modified by this routine. - * - * Sometimes a macro implementation of this is in cpu.h which dereferences - * the ** and a similarly named routine in this file is passed something - * like a (Context_Control_fp *). The general rule on making this decision - * is to avoid writing assembly language. - */ - -/* void _CPU_Context_save_fp( - * void **fp_context_ptr - * ); - */ - -#if ( CPU_HARDWARE_FP == TRUE ) -FRAME(_CPU_Context_save_fp,sp,0,ra) - .set noreorder - .set noat - - /* - ** Make sure the FPU is on before we save state. This code - ** is here because the FPU context switch might occur when an - ** integer task is switching out with a FP task switching in. - */ - MFC0 t0,C0_SR - li t2,SR_CU1 - move t1,t0 - or t0,t2 /* turn on the fpu */ -#if __mips == 3 - li t2,SR_EXL | SR_IE -#elif __mips == 1 - li t2,SR_IEC -#endif - not t2 - and t0,t2 /* turn off interrupts */ - MTC0 t0,C0_SR - - ld a1,(a0) - move t0,ra - jal _CPU_Context_save_fp_from_exception - NOP - - /* - ** Reassert the task's state because we've not saved it yet. - */ - MTC0 t1,C0_SR - j t0 - NOP - - .globl _CPU_Context_save_fp_from_exception -_CPU_Context_save_fp_from_exception: - swc1 $f0,FP0_OFFSET*F_SZ(a1) - swc1 $f1,FP1_OFFSET*F_SZ(a1) - swc1 $f2,FP2_OFFSET*F_SZ(a1) - swc1 $f3,FP3_OFFSET*F_SZ(a1) - swc1 $f4,FP4_OFFSET*F_SZ(a1) - swc1 $f5,FP5_OFFSET*F_SZ(a1) - swc1 $f6,FP6_OFFSET*F_SZ(a1) - swc1 $f7,FP7_OFFSET*F_SZ(a1) - swc1 $f8,FP8_OFFSET*F_SZ(a1) - swc1 $f9,FP9_OFFSET*F_SZ(a1) - swc1 $f10,FP10_OFFSET*F_SZ(a1) - swc1 $f11,FP11_OFFSET*F_SZ(a1) - swc1 $f12,FP12_OFFSET*F_SZ(a1) - swc1 $f13,FP13_OFFSET*F_SZ(a1) - swc1 $f14,FP14_OFFSET*F_SZ(a1) - swc1 $f15,FP15_OFFSET*F_SZ(a1) - swc1 $f16,FP16_OFFSET*F_SZ(a1) - swc1 $f17,FP17_OFFSET*F_SZ(a1) - swc1 $f18,FP18_OFFSET*F_SZ(a1) - swc1 $f19,FP19_OFFSET*F_SZ(a1) - swc1 $f20,FP20_OFFSET*F_SZ(a1) - swc1 $f21,FP21_OFFSET*F_SZ(a1) - swc1 $f22,FP22_OFFSET*F_SZ(a1) - swc1 $f23,FP23_OFFSET*F_SZ(a1) - swc1 $f24,FP24_OFFSET*F_SZ(a1) - swc1 $f25,FP25_OFFSET*F_SZ(a1) - swc1 $f26,FP26_OFFSET*F_SZ(a1) - swc1 $f27,FP27_OFFSET*F_SZ(a1) - swc1 $f28,FP28_OFFSET*F_SZ(a1) - swc1 $f29,FP29_OFFSET*F_SZ(a1) - swc1 $f30,FP30_OFFSET*F_SZ(a1) - swc1 $f31,FP31_OFFSET*F_SZ(a1) - j ra - NOP - .set at -ENDFRAME(_CPU_Context_save_fp) -#endif - -/* - * _CPU_Context_restore_fp_context - * - * This routine is responsible for restoring the FP context - * at *fp_context_ptr. If the point to load the FP context - * from is changed then the pointer is modified by this routine. - * - * Sometimes a macro implementation of this is in cpu.h which dereferences - * the ** and a similarly named routine in this file is passed something - * like a (Context_Control_fp *). The general rule on making this decision - * is to avoid writing assembly language. - */ - -/* void _CPU_Context_restore_fp( - * void **fp_context_ptr - * ) - */ - -#if ( CPU_HARDWARE_FP == TRUE ) -FRAME(_CPU_Context_restore_fp,sp,0,ra) - .set noat - .set noreorder - - /* - ** Make sure the FPU is on before we retrieve state. This code - ** is here because the FPU context switch might occur when an - ** integer task is switching out with a FP task switching in. - */ - MFC0 t0,C0_SR - li t2,SR_CU1 - move t1,t0 - or t0,t2 /* turn on the fpu */ -#if __mips == 3 - li t2,SR_EXL | SR_IE -#elif __mips == 1 - li t2,SR_IEC -#endif - not t2 - and t0,t2 /* turn off interrupts */ - MTC0 t0,C0_SR - - ld a1,(a0) - move t0,ra - jal _CPU_Context_restore_fp_from_exception - NOP - - /* - ** Reassert the old task's state because we've not restored the - ** new one yet. - */ - MTC0 t1,C0_SR - j t0 - NOP - - .globl _CPU_Context_restore_fp_from_exception -_CPU_Context_restore_fp_from_exception: - lwc1 $f0,FP0_OFFSET*4(a1) - lwc1 $f1,FP1_OFFSET*4(a1) - lwc1 $f2,FP2_OFFSET*4(a1) - lwc1 $f3,FP3_OFFSET*4(a1) - lwc1 $f4,FP4_OFFSET*4(a1) - lwc1 $f5,FP5_OFFSET*4(a1) - lwc1 $f6,FP6_OFFSET*4(a1) - lwc1 $f7,FP7_OFFSET*4(a1) - lwc1 $f8,FP8_OFFSET*4(a1) - lwc1 $f9,FP9_OFFSET*4(a1) - lwc1 $f10,FP10_OFFSET*4(a1) - lwc1 $f11,FP11_OFFSET*4(a1) - lwc1 $f12,FP12_OFFSET*4(a1) - lwc1 $f13,FP13_OFFSET*4(a1) - lwc1 $f14,FP14_OFFSET*4(a1) - lwc1 $f15,FP15_OFFSET*4(a1) - lwc1 $f16,FP16_OFFSET*4(a1) - lwc1 $f17,FP17_OFFSET*4(a1) - lwc1 $f18,FP18_OFFSET*4(a1) - lwc1 $f19,FP19_OFFSET*4(a1) - lwc1 $f20,FP20_OFFSET*4(a1) - lwc1 $f21,FP21_OFFSET*4(a1) - lwc1 $f22,FP22_OFFSET*4(a1) - lwc1 $f23,FP23_OFFSET*4(a1) - lwc1 $f24,FP24_OFFSET*4(a1) - lwc1 $f25,FP25_OFFSET*4(a1) - lwc1 $f26,FP26_OFFSET*4(a1) - lwc1 $f27,FP27_OFFSET*4(a1) - lwc1 $f28,FP28_OFFSET*4(a1) - lwc1 $f29,FP29_OFFSET*4(a1) - lwc1 $f30,FP30_OFFSET*4(a1) - lwc1 $f31,FP31_OFFSET*4(a1) - j ra - NOP - .set at -ENDFRAME(_CPU_Context_restore_fp) -#endif - -/* _CPU_Context_switch - * - * This routine performs a normal non-FP context switch. - */ - -/* void _CPU_Context_switch( - * Context_Control *run, - * Context_Control *heir - * ) - */ - -FRAME(_CPU_Context_switch,sp,0,ra) - .set noreorder - - MFC0 t0,C0_SR -#if __mips == 3 - li t1,SR_EXL | SR_IE -#elif __mips == 1 - li t1,SR_IEC -#endif - STREG t0,C0_SR_OFFSET*R_SZ(a0) /* save the task's SR */ - not t1 - and t0,t1 /* mask off interrupts while we context switch */ - MTC0 t0,C0_SR - NOP - - STREG ra,RA_OFFSET*R_SZ(a0) /* save current context */ - STREG sp,SP_OFFSET*R_SZ(a0) - STREG fp,FP_OFFSET*R_SZ(a0) - STREG s0,S0_OFFSET*R_SZ(a0) - STREG s1,S1_OFFSET*R_SZ(a0) - STREG s2,S2_OFFSET*R_SZ(a0) - STREG s3,S3_OFFSET*R_SZ(a0) - STREG s4,S4_OFFSET*R_SZ(a0) - STREG s5,S5_OFFSET*R_SZ(a0) - STREG s6,S6_OFFSET*R_SZ(a0) - STREG s7,S7_OFFSET*R_SZ(a0) - - - /* - ** this code grabs the userspace EPC if we're dispatching from - ** an interrupt frame or fakes an address as the EPC if we're - ** not. This is for the gdbstub's benefit so it can know - ** where each thread is running. - ** - ** Its value is only set when calling threadDispatch from - ** the interrupt handler and is cleared immediately when this - ** routine gets it. - */ - - la t0,__exceptionStackFrame /* see if we're coming in from an exception */ - LDREG t1, (t0) - NOP - beqz t1,1f - - STREG zero, (t0) /* and clear it */ - NOP - LDREG t0,R_EPC*R_SZ(t1) /* get the userspace EPC from the frame */ - b 2f - -1: la t0,_Thread_Dispatch /* if ==0, we're switched out */ - -2: STREG t0,C0_EPC_OFFSET*R_SZ(a0) - - -_CPU_Context_switch_restore: - LDREG ra,RA_OFFSET*R_SZ(a1) /* restore context */ - LDREG sp,SP_OFFSET*R_SZ(a1) - LDREG fp,FP_OFFSET*R_SZ(a1) - LDREG s0,S0_OFFSET*R_SZ(a1) - LDREG s1,S1_OFFSET*R_SZ(a1) - LDREG s2,S2_OFFSET*R_SZ(a1) - LDREG s3,S3_OFFSET*R_SZ(a1) - LDREG s4,S4_OFFSET*R_SZ(a1) - LDREG s5,S5_OFFSET*R_SZ(a1) - LDREG s6,S6_OFFSET*R_SZ(a1) - LDREG s7,S7_OFFSET*R_SZ(a1) - - LDREG t0, C0_SR_OFFSET*R_SZ(a1) - -// NOP -//#if __mips == 3 -// andi t0,SR_EXL -// bnez t0,_CPU_Context_1 /* set exception level from restore context */ -// li t0,~SR_EXL -// MFC0 t1,C0_SR -// NOP -// and t1,t0 -// MTC0 t1,C0_SR -// -//#elif __mips == 1 -// -// andi t0,(SR_INTERRUPT_ENABLE_BITS) /* we know 0 disabled */ -// beq t0,$0,_CPU_Context_1 /* set level from restore context */ -// MFC0 t0,C0_SR -// NOP -// or t0,(SR_INTERRUPT_ENABLE_BITS) /* new_sr = old sr with enabled */ -// MTC0 t0,C0_SR /* set with enabled */ -// NOP - - -/* -** Incorporate the new task's FP coprocessor state and interrupt mask/enable -** into the status register. We jump thru the requisite hoops to ensure we -** maintain all other SR bits as global values. -** -** Get the thread's FPU enable, int mask & int enable bits. Although we keep the -** software int enables on a per-task basis, the rtems_task_create -** Interrupt Level & int level manipulation functions cannot enable/disable them, -** so they are automatically enabled for all tasks. To turn them off, a thread -** must itself manipulate the SR register. -** -** Although something of a hack on this processor, we treat the SR register -** int enables as the RTEMS interrupt level. We use the int level -** value as a bitmask, not as any sort of greater than/less than metric. -** Manipulation of a task's interrupt level directly corresponds to manipulation -** of that task's SR bits, as seen in cpu.c -** -** Note, interrupts are disabled before context is saved, though the thread's -** interrupt enable state is recorded. The task swapping in will apply its -** specific SR bits, including interrupt enable. If further task-specific -** SR bits are arranged, it is this code, the cpu.c interrupt level stuff and -** cpu.h task initialization code that will be affected. -*/ - - li t2,SR_CU1 - or t2,SR_IMASK - - /* int enable bits */ -#if __mips == 3 - or t2,SR_EXL + SR_IE -#elif __mips == 1 - or t2,SR_IEC + SR_IEP + SR_IEO /* save current & previous int enable */ -#endif - and t0,t2 /* keep only the per-task bits */ - - MFC0 t1,C0_SR /* grab the current SR */ - not t2 - and t1,t2 /* mask off the old task's bits */ - or t1,t0 /* or in the new task's bits */ - MTC0 t1,C0_SR /* and load the new SR */ - NOP - -/* _CPU_Context_1: */ - j ra - NOP -ENDFRAME(_CPU_Context_switch) - - -/* - * _CPU_Context_restore - * - * This routine is generally used only to restart self in an - * efficient manner. It may simply be a label in _CPU_Context_switch. - * - * NOTE: May be unnecessary to reload some registers. - * - * void _CPU_Context_restore( - * Context_Control *new_context - * ); - */ - -FRAME(_CPU_Context_restore,sp,0,ra) - .set noreorder - move a1,a0 - j _CPU_Context_switch_restore - NOP - -ENDFRAME(_CPU_Context_restore) - - -ASM_EXTERN(_ISR_Nest_level, SZ_INT) -ASM_EXTERN(_Thread_Dispatch_disable_level,SZ_INT) -ASM_EXTERN(_Context_Switch_necessary,SZ_INT) -ASM_EXTERN(_ISR_Signals_to_thread_executing,SZ_INT) -ASM_EXTERN(_Thread_Executing,SZ_INT) - -.extern _Thread_Dispatch -.extern _ISR_Vector_table - - - - - -/* void _DBG_Handler() - * - * This routine services the (at least) MIPS1 debug vector, - * only used the the hardware debugging features. This code, - * while optional, is best located here because its intrinsically - * associated with exceptions in general & thus tied pretty - * closely to _ISR_Handler. - * - */ - - -FRAME(_DBG_Handler,sp,0,ra) - .set noreorder - la k0,_ISR_Handler - j k0 - NOP - .set reorder -ENDFRAME(_DBG_Handler) - - - - - -/* void __ISR_Handler() - * - * This routine provides the RTEMS interrupt management. - * - * void _ISR_Handler() - * - * - * This discussion ignores a lot of the ugly details in a real - * implementation such as saving enough registers/state to be - * able to do something real. Keep in mind that the goal is - * to invoke a user's ISR handler which is written in C and - * uses a certain set of registers. - * - * Also note that the exact order is to a large extent flexible. - * Hardware will dictate a sequence for a certain subset of - * _ISR_Handler while requirements for setting - * - * At entry to "common" _ISR_Handler, the vector number must be - * available. On some CPUs the hardware puts either the vector - * number or the offset into the vector table for this ISR in a - * known place. If the hardware does not give us this information, - * then the assembly portion of RTEMS for this port will contain - * a set of distinct interrupt entry points which somehow place - * the vector number in a known place (which is safe if another - * interrupt nests this one) and branches to _ISR_Handler. - * - */ - -FRAME(_ISR_Handler,sp,0,ra) - .set noreorder - - /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */ - - /* wastes a lot of stack space for context?? */ - ADDIU sp,sp,-EXCP_STACK_SIZE - - STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */ - STREG v0, R_V0*R_SZ(sp) - STREG v1, R_V1*R_SZ(sp) - STREG a0, R_A0*R_SZ(sp) - STREG a1, R_A1*R_SZ(sp) - STREG a2, R_A2*R_SZ(sp) - STREG a3, R_A3*R_SZ(sp) - STREG t0, R_T0*R_SZ(sp) - STREG t1, R_T1*R_SZ(sp) - STREG t2, R_T2*R_SZ(sp) - STREG t3, R_T3*R_SZ(sp) - STREG t4, R_T4*R_SZ(sp) - STREG t5, R_T5*R_SZ(sp) - STREG t6, R_T6*R_SZ(sp) - STREG t7, R_T7*R_SZ(sp) - mflo t0 - STREG t8, R_T8*R_SZ(sp) - STREG t0, R_MDLO*R_SZ(sp) - STREG t9, R_T9*R_SZ(sp) - mfhi t0 - STREG gp, R_GP*R_SZ(sp) - STREG t0, R_MDHI*R_SZ(sp) - STREG fp, R_FP*R_SZ(sp) - - .set noat - STREG AT, R_AT*R_SZ(sp) - .set at - - MFC0 t0,C0_SR - MFC0 t1,C0_EPC - STREG t0,R_SR*R_SZ(sp) - STREG t1,R_EPC*R_SZ(sp) - - -#ifdef INSTRUMENT_EXECUTING_THREAD - lw t2, _Thread_Executing - NOP - sw t2, 0x8001FFF0 -#endif - - /* determine if an interrupt generated this exception */ - - MFC0 t0,C0_CAUSE - NOP - - and t1,t0,CAUSE_EXCMASK - beq t1, 0, _ISR_Handler_1 - -_ISR_Handler_Exception: - - /* - sw t0,0x8001FF00 - sw t1,0x8001FF04 - */ - - /* If we return from the exception, it is assumed nothing - * bad is going on and we can continue to run normally. - * But we want to save the entire CPU context so exception - * handlers can look at it and change it. - * - * NOTE: This is the path the debugger stub will take. - */ - - /* already got t0 = cause in the interrupt test above */ - STREG t0,R_CAUSE*R_SZ(sp) - - STREG sp, R_SP*R_SZ(sp) - - STREG s0,R_S0*R_SZ(sp) /* save s0 - s7 */ - STREG s1,R_S1*R_SZ(sp) - STREG s2,R_S2*R_SZ(sp) - STREG s3,R_S3*R_SZ(sp) - STREG s4,R_S4*R_SZ(sp) - STREG s5,R_S5*R_SZ(sp) - STREG s6,R_S6*R_SZ(sp) - STREG s7,R_S7*R_SZ(sp) - - /* CP0 special registers */ - -#if __mips == 1 - MFC0 t0,C0_TAR -#endif - MFC0 t1,C0_BADVADDR - -#if __mips == 1 - STREG t0,R_TAR*R_SZ(sp) -#else - NOP -#endif - STREG t1,R_BADVADDR*R_SZ(sp) - -#if ( CPU_HARDWARE_FP == TRUE ) - MFC0 t0,C0_SR /* FPU is enabled, save state */ - NOP - srl t0,t0,16 - andi t0,t0,(SR_CU1 >> 16) - beqz t0, 1f - NOP - - la a1,R_F0*R_SZ(sp) - jal _CPU_Context_save_fp_from_exception - NOP - MFC1 t0,C1_REVISION - MFC1 t1,C1_STATUS - STREG t0,R_FEIR*R_SZ(sp) - STREG t1,R_FCSR*R_SZ(sp) - -1: -#endif - - move a0,sp - jal mips_vector_exceptions - NOP - - - /* - ** note, if the exception vector returns, rely on it to have - ** adjusted EPC so we will return to some correct address. If - ** this is not done, we might get stuck in an infinite loop because - ** we'll return to the instruction where the exception occured and - ** it could throw again. - ** - ** It is expected the only code using the exception processing is - ** either the gdb stub or some user code which is either going to - ** panic or do something useful. - */ - - -/* ********************************************************************* - * compute the address of the instruction we'll return to * - - LDREG t1, R_CAUSE*R_SZ(sp) - LDREG t0, R_EPC*R_SZ(sp) - - * first see if the exception happened in the delay slot * - li t3,CAUSE_BD - AND t4,t1,t3 - beqz t4,excnodelay - NOP - - * it did, now see if the branch occured or not * - li t3,CAUSE_BT - AND t4,t1,t3 - beqz t4,excnobranch - NOP - - * branch was taken, we resume at the branch target * - LDREG t0, R_TAR*R_SZ(sp) - j excreturn - NOP - -excnobranch: - ADDU t0,R_SZ - -excnodelay: - ADDU t0,R_SZ - -excreturn: - STREG t0, R_EPC*R_SZ(sp) - NOP -********************************************************************* */ - - - /* if we're returning into mips_break, move to the next instruction */ - - LDREG t0,R_EPC*R_SZ(sp) - la t1,mips_break - xor t2,t0,t1 - bnez t2,3f - - addu t0,R_SZ - STREG t0,R_EPC*R_SZ(sp) - NOP -3: - - - - -#if ( CPU_HARDWARE_FP == TRUE ) - MFC0 t0,C0_SR /* FPU is enabled, restore state */ - NOP - srl t0,t0,16 - andi t0,t0,(SR_CU1 >> 16) - beqz t0, 2f - NOP - - la a1,R_F0*R_SZ(sp) - jal _CPU_Context_restore_fp_from_exception - NOP - LDREG t0,R_FEIR*R_SZ(sp) - LDREG t1,R_FCSR*R_SZ(sp) - MTC1 t0,C1_REVISION - MTC1 t1,C1_STATUS -2: -#endif - LDREG s0,R_S0*R_SZ(sp) /* restore s0 - s7 */ - LDREG s1,R_S1*R_SZ(sp) - LDREG s2,R_S2*R_SZ(sp) - LDREG s3,R_S3*R_SZ(sp) - LDREG s4,R_S4*R_SZ(sp) - LDREG s5,R_S5*R_SZ(sp) - LDREG s6,R_S6*R_SZ(sp) - LDREG s7,R_S7*R_SZ(sp) - - /* do NOT restore the sp as this could mess up the world */ - /* do NOT restore the cause as this could mess up the world */ - - j _ISR_Handler_exit - NOP - -_ISR_Handler_1: - - MFC0 t1,C0_SR - and t0,CAUSE_IPMASK - and t0,t1 - - /* external interrupt not enabled, ignore */ - /* but if it's not an exception or an interrupt, */ - /* Then where did it come from??? */ - - beq t0,zero,_ISR_Handler_exit - - - - - /* - * save some or all context on stack - * may need to save some special interrupt information for exit - * - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * if ( _ISR_Nest_level == 0 ) - * switch to software interrupt stack - * #endif - */ - - /* - * _ISR_Nest_level++; - */ - LDREG t0,_ISR_Nest_level - NOP - ADD t0,t0,1 - STREG t0,_ISR_Nest_level - /* - * _Thread_Dispatch_disable_level++; - */ - LDREG t1,_Thread_Dispatch_disable_level - NOP - ADD t1,t1,1 - STREG t1,_Thread_Dispatch_disable_level - - /* - * Call the CPU model or BSP specific routine to decode the - * interrupt source and actually vector to device ISR handlers. - */ - -#ifdef INSTRUMENT_ISR_VECTORING - NOP - li t1, 1 - sw t1, 0x8001e000 -#endif - - move a0,sp - jal mips_vector_isr_handlers - NOP - -#ifdef INSTRUMENT_ISR_VECTORING - li t1, 0 - sw t1, 0x8001e000 - NOP -#endif - - /* - * --_ISR_Nest_level; - */ - LDREG t2,_ISR_Nest_level - NOP - ADD t2,t2,-1 - STREG t2,_ISR_Nest_level - /* - * --_Thread_Dispatch_disable_level; - */ - LDREG t1,_Thread_Dispatch_disable_level - NOP - ADD t1,t1,-1 - STREG t1,_Thread_Dispatch_disable_level - /* - * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level ) - * goto the label "exit interrupt (simple case)" - */ - or t0,t2,t1 - bne t0,zero,_ISR_Handler_exit - NOP - - - - - /* - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * restore stack - * #endif - * - * if ( !_Context_Switch_necessary && !_ISR_Signals_to_thread_executing ) - * goto the label "exit interrupt (simple case)" - */ - LDREG t0,_Context_Switch_necessary - LDREG t1,_ISR_Signals_to_thread_executing - NOP - or t0,t0,t1 - beq t0,zero,_ISR_Handler_exit - NOP - - - -#ifdef INSTRUMENT_EXECUTING_THREAD - lw t0,_Thread_Executing - NOP - sw t0,0x8001FFF4 -#endif - -/* -** Turn on interrupts before entering Thread_Dispatch which -** will run for a while, thus allowing new interrupts to -** be serviced. Observe the Thread_Dispatch_disable_level interlock -** that prevents recursive entry into Thread_Dispatch. -*/ - - MFC0 t0, C0_SR -#if __mips == 3 - li t1,SR_EXL | SR_IE -#elif __mips == 1 - li t1,SR_IEC -#endif - or t0, t1 - MTC0 t0, C0_SR - NOP - - /* save off our stack frame so the context switcher can get to it */ - la t0,__exceptionStackFrame - STREG sp,(t0) - - jal _Thread_Dispatch - NOP - - /* and make sure its clear in case we didn't dispatch. if we did, its - ** already cleared */ - la t0,__exceptionStackFrame - STREG zero,(t0) - NOP - -/* -** turn interrupts back off while we restore context so -** a badly timed interrupt won't accidentally mess things up -*/ - MFC0 t0, C0_SR -#if __mips == 3 - li t1,SR_EXL | SR_IE -#elif __mips == 1 - /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */ - li t1,SR_IEC | SR_KUP | SR_KUC -#endif - not t1 - and t0, t1 - -#if __mips == 1 - /* make sure previous int enable is on because we're returning from an interrupt - ** which means interrupts have to be enabled - */ - li t1,SR_IEP - or t0,t1 -#endif - MTC0 t0, C0_SR - NOP - -#ifdef INSTRUMENT_EXECUTING_THREAD - lw t0,_Thread_Executing - NOP - sw t0,0x8001FFF8 -#endif - - - /* - * prepare to get out of interrupt - * return from interrupt (maybe to _ISR_Dispatch) - * - * LABEL "exit interrupt (simple case):" - * prepare to get out of interrupt - * return from interrupt - */ - -_ISR_Handler_exit: -/* -** Skip the SR restore because its a global register. _CPU_Context_switch_restore -** adjusts it according to each task's configuration. If we didn't dispatch, the -** SR value isn't changed, so all we need to do is return. -** -*/ - /* restore context from stack */ - -#ifdef INSTRUMENT_EXECUTING_THREAD - lw t0,_Thread_Executing - NOP - sw t0, 0x8001FFFC -#endif - - LDREG t8, R_MDLO*R_SZ(sp) - LDREG t0, R_T0*R_SZ(sp) - mtlo t8 - LDREG t8, R_MDHI*R_SZ(sp) - LDREG t1, R_T1*R_SZ(sp) - mthi t8 - LDREG t2, R_T2*R_SZ(sp) - LDREG t3, R_T3*R_SZ(sp) - LDREG t4, R_T4*R_SZ(sp) - LDREG t5, R_T5*R_SZ(sp) - LDREG t6, R_T6*R_SZ(sp) - LDREG t7, R_T7*R_SZ(sp) - LDREG t8, R_T8*R_SZ(sp) - LDREG t9, R_T9*R_SZ(sp) - LDREG gp, R_GP*R_SZ(sp) - LDREG fp, R_FP*R_SZ(sp) - LDREG ra, R_RA*R_SZ(sp) - LDREG a0, R_A0*R_SZ(sp) - LDREG a1, R_A1*R_SZ(sp) - LDREG a2, R_A2*R_SZ(sp) - LDREG a3, R_A3*R_SZ(sp) - LDREG v1, R_V1*R_SZ(sp) - LDREG v0, R_V0*R_SZ(sp) - - LDREG k1, R_EPC*R_SZ(sp) - - .set noat - LDREG AT, R_AT*R_SZ(sp) - .set at - - ADDIU sp,sp,EXCP_STACK_SIZE - j k1 - rfe - NOP - - .set reorder -ENDFRAME(_ISR_Handler) - - - - -FRAME(mips_break,sp,0,ra) - .set noreorder - break 0x0 /* this statement must be first in this function, assumed so by mips-stub.c */ - NOP - j ra - NOP - .set reorder -ENDFRAME(mips_break) - -- cgit v1.2.3