📄 irq_a.s
字号:
/************************************************************* * File: irq_a.s * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 961208 Created * 961228 Enabled code to enable nested ints * 980622 There seems to be a prob w the "disable me and lower.." */#include <mips.h>#ifdef R4KEXCEPTIONS#define IRQTrap IRQTrap4k#define eret .word 0x42000018 /* could use -mips2 sw */#endif#ifndef SR_ISHIFT /* just in case you don't have this yet */#define SR_ISHIFT 8#endif#define RFE_REG k0 /* reg used during rfe */#define E_EPC 0#define E_AT 1#define E_V0 2#define E_V1 3#define E_A0 4#define E_A1 5#define E_A2 6#define E_A3 7#define E_T0 8#define E_T1 9#define E_T2 10#define E_T3 11#define E_T4 12#define E_T5 13#define E_T6 14#define E_T7 15#define E_S0 16#define E_S1 17#define E_S2 18#define E_S3 19#define E_S4 20#define E_S5 21#define E_S6 22#define E_S7 23#define E_T8 24#define E_T9 25#define E_HI 26#define E_LO 27#define E_CAUSE 28#define E_SR 29#define E_S8 30#define E_RA 31#define E_SIZE 32 /* must be even *//************************************************************** IRQTrap - IRQ trap handler** Wrapper to service the trap and call a high-level handler.*/ .globl IRQTrap .ent IRQTrap .set noatIRQTrap: # At this points IRQs are disabled, so we know that the EPC # register will not be trashed by another interrupt. # save all registers subu sp,E_SIZE*4 sw AT,E_AT*4(sp) .set at sw ra,E_RA*4(sp) sw v0,E_V0*4(sp) sw v1,E_V1*4(sp) sw t0,E_T0*4(sp) sw t1,E_T1*4(sp) # save SR so we can restore it properly .set noreorder mfc0 t1,C0_EPC nop sw t1,E_EPC*4(sp) # save EPC mfc0 t1,C0_SR nop sw t1,E_SR*4(sp) # save SR mfc0 t0,C0_CAUSE nop sw t0,E_CAUSE*4(sp) # save CAUSE .set reorder # see if it is a sw or hw exception and t1,t0,CAUSE_EXCMASK bne t1,zero,swexception # must be a hwexception # compute possible requestors, i.e. those not masked lw t1,E_SR*4(sp) # get SR and t0,t1 # CAUSE is still in t0, SR in t0 and t0,SR_IMASK # determine highest priority requestor srl t0,SR_ISHIFT # move sw0 in LS position la t1,pri_table addu t0,t1 # compute entry address lbu ra,(t0) # get int# from table # int# of highest priority int (1..8) is now in ra # 1=sw0=low 8=int5=high # use int# (1..8) in ra to index into vector table la v0,IRQVector # base address of vect table subu t0,ra,1 # zero based table sll t0,2 # word sized entries addu v0,t0 # compute entry addr lw v0,(v0) # pick up addr from table # is this exception implemented? beq v0,zero,unimpl # no handler in table#if 0 /* 980622 this does not seem to work. */ /* It runs for a while and then crashes */ # disable me and lower priorities # convert int# to mask li t0,SR_IMASK1 sll t0,ra and t0,SR_IMASK # clear other bits # mask now in t0 # load new mask into SR and enable ints lw t1,E_SR*4(sp) # get current SR value (iec=0) and v1,t1,SR_IMASK # get current IM field and t0,v1 # qual new mask w/ IM field li v1,~SR_IMASK and t1,v1 # clear IM field or t1,t0 # load new mask value#else /* this works */ # just disable me lw t1,E_SR*4(sp) # get current SR value (iec=0) li v1,(1<<(SR_ISHIFT-1)) # -1 because int# is 1-8 sll v1,ra not v1 and t1,v1#endif .set noreorder mtc0 t1,C0_SR # update SR nop # give it time nop # ... or t1,SR_IEC # now enable ints mtc0 t1,C0_SR # update SR nop .set reorder # ints now enabledgo_handler: /* save the remaining registers */ sw a0,E_A0*4(sp) ; sw a1,E_A1*4(sp) sw a2,E_A2*4(sp) ; sw a3,E_A3*4(sp) sw t2,E_T2*4(sp) ; sw t3,E_T3*4(sp) sw t4,E_T4*4(sp) ; sw t5,E_T5*4(sp) sw t6,E_T6*4(sp) ; sw t7,E_T7*4(sp) sw t8,E_T8*4(sp) ; sw t9,E_T9*4(sp) sw s0,E_S0*4(sp) ; sw s1,E_S1*4(sp) sw s2,E_S2*4(sp) ; sw s3,E_S3*4(sp) sw s4,E_S4*4(sp) ; sw s5,E_S5*4(sp) sw s6,E_S6*4(sp) ; sw s7,E_S7*4(sp) sw s8,E_S8*4(sp) mfhi t0 sw t0,E_HI*4(sp) mflo t0 sw t0,E_LO*4(sp) # pass base address of save area move a0,sp # call high-level handler subu sp,24 jal v0 addu sp,24 # restore SR because it may have been changed by the # high-level handler. This also disables ints. .set noreorder mfc0 t1,C0_SR nop and t0,t1,~SR_IEC mtc0 t0,C0_SR nop nop nop lw t0,E_SR*4(sp) nop mtc0 t0,C0_SR nop nop nop .set reorder # restore registers lw t0,E_HI*4(sp) mthi t0 lw t0,E_LO*4(sp) mtlo t0 lw a0,E_A0*4(sp) lw a1,E_A1*4(sp) ; lw a2,E_A2*4(sp) lw a3,E_A3*4(sp) ; lw t2,E_T2*4(sp) lw t3,E_T3*4(sp) ; lw t4,E_T4*4(sp) lw t5,E_T5*4(sp) ; lw t6,E_T6*4(sp) lw t7,E_T7*4(sp) ; lw t8,E_T8*4(sp) lw t9,E_T9*4(sp) ; lw s0,E_S0*4(sp) lw s1,E_S1*4(sp) ; lw s2,E_S2*4(sp) lw s3,E_S3*4(sp) ; lw s4,E_S4*4(sp) lw s5,E_S5*4(sp) ; lw s6,E_S6*4(sp) lw s7,E_S7*4(sp) ; lw s8,E_S8*4(sp) # did we handle it? beq v0,zero,unimpl # brif no lw ra,E_RA*4(sp) lw v1,E_V1*4(sp) lw v0,E_V0*4(sp) lw t1,E_T1*4(sp) lw t0,E_T0*4(sp) .set noat lw AT,E_AT*4(sp) # return to the interrupted thread .set noreorder#ifdef R4KEXCEPTIONS lw t0,E_EPC*4(sp) addu sp,E_SIZE*4 mtc0 t0,C0_EPC # I don't know exactly how many nops you need here. But is # certainly more than one. nop nop nop nop nop eret nop#else lw RFE_REG,E_EPC*4(sp) addu sp,E_SIZE*4 j RFE_REG rfe#endif .set reorder .set at .end IRQTrap/**************************************************************/ .globl swexception .ent swexceptionswexception: # get handler address, CAUSE is in t0 and t1,t0,CAUSE_EXCMASK la v0,IRQVector+(8*4) addu v0,t1 lw v0,(v0) # is it impl? bne v0,zero,go_handler # brif yes # fall thru .end swexception/**************************************************************/ .globl unimpl .ent unimplunimpl: lw ra,E_RA*4(sp) lw v0,E_V0*4(sp) lw v1,E_V1*4(sp) lw t0,E_T0*4(sp) lw t1,E_T1*4(sp) .set noat lw AT,E_AT*4(sp) addu sp,E_SIZE*4 li RFE_REG,0xbfc00180 j RFE_REG .set at .end unimpl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -