这是一个默认的中断处理模式,CPU收到一启动异常的时候,内核进入这种模式。在这种模式中,中断是非向量的,中断会被分派到异常向量偏移0x180的位置处(Cause IV=0),或者0x200的位置(Cause IV = 1).当以下的任何一个条件成立时,这种模式有效:
Cause IV=0
Status BEV=1
IntCtl VS =0(当VI模式不存在或者禁止时)
compatibility mode的中断处理程序例子:
/*
* 解设:
* - CauseIV = 1 (如果为0,当中断到达这里之前,这个中断不会被这个处理程序处理)
* - GPRs k0 和k1 寄存器可以被使用(因为这这种模式里没有提供shadow 寄存器)
* - 优先级设置为:IP7..IP0 (HW5..HW0, SW1..SW0)
*
* 位置: Offset 0x200 */
IVexception:
mfc0 k0, C0_Cause /* Read Cause register for IP bits */
mfc0 k1, C0_Status /* and Status register for IM bits */
andi k0, k0, M_CauseIM /* Keep only IP bits from Cause */
and k0, k0, k1 /* and mask with IM bits */
beq k0, zero, Dismiss /* no bits set - spurious interrupt */
clz k0, k0 /* Find first bit set, IP7..IP0; k0 = 16..23 */
xori k0, k0, 0x17 /* 16..23 => 7..0 */
sll k0, k0, VS /* Shift to emulate software IntCtlVS */
la k1, VectorBase /* Get base of 8 interrupt vectors */
addu k0, k0, k1 /* Compute target from base and offset */
jr k0 /* Jump to specific exception routine */
nop
/*每一个中断处理程序都会处理一个特定的中断,类似与VI或者EIC这些中断模式,
由于每一种中断都会有一个自己的中断信号,他们有自己的中断标志进行识别,
如果多个中断使用同一个中断信号,每一个中断处理程序都需要判断实际中断源,
通过优先级高低来判断。*/
SimpleInterrupt:
/*这里需要清除中断,有一些寄存器需要保存或者恢复,之后使用eret指令返回被中断的代码中*/
eret /* Return to interrupted code */
NestedException:
/*对于嵌套中断,通常需要保存EPC和状态寄存器,保存GPRs,通过IM位禁止当前中断来避免进入中断死循环,
设置处理器进入kernel模式,重新允许中断,下面是简单的例子代码*/
mfc0 k0, C0_EPC /* Get restart address */
sw k0, EPCSave /* Save in memory */
mfc0 k0, C0_Status /* Get Status value */
sw k0, StatusSave /* Save in memory */
li k1, ~IMbitsToClear /* Get IM bits to clear for this interrupt */
/* this must include at least the IM bit */
/* for the current interrupt, and may include */
/* others */
and k0, k0, k1 /* Clear bits in copy of Status */
ins k0, zero, S_StatusEXL, (W_StatusKSU+W_StatusERL+W_StatusEXL)
/* Clear KSU, ERL, EXL bits in k0 */
mtc0 k0, C0_Status /* Modify mask, switch to kernel mode, */
/* re-enable interrupts */
/*
* Process interrupt here, including clearing device interrupt.
* In some environments this may be done with a thread running in
* kernel or user mode. Such an environment is well beyond the scope of
* this example.
*/
/*这里进行中断处理*/
/*完成处理之后,重新允许中断*/
/*
* To complete interrupt processing, the saved values must be restored
* and the original interrupted code restarted.
*/
di /* Disable interrupts - may not be required */
lw k0, StatusSave /* Get saved Status (including EXL set) */
l k1, EPCSave /* and EPC */
mtc0 k0, C0_Status /* Restore the original value */
mtc0 k1, C0_EPC /* and EPC */
/* Restore GPRs and software state */
eret /* Dismiss the interrupt */