ARM的状态寄存器与中断详解
CPSR & SPSR
- CPSR: current program status register
- SPSR: saved program status register
CPU中只有一个全局的CPSR寄存器,但对应每一个异常中断模式(usr和sys不是异常中断模式,所以没有SPSR)都有一个独立的SPSR,用于在CPU切换至其他mode时对当前的CPSR进行备份。
由于CPSR的特殊性,不同于r0~r15,它只能通过msr
与mrs
指令进行读写。其中s表示status register,即CPSR,而r表示register,即普通寄存器。这两个指令中的sr和rs按照从右向左的顺序表示着数据移动的方向。msr表示数据从r移动至s,即将r中的内容写入s,mrs则为从s移动至r,即从s中读取数据至r。
msr cpsr, r0 // write cpsr mrs r0, cpsr // read cpsr
而作为备份寄存器,SPSR就单纯得多。
当中断引起mode转变时,ARM将通过硬件替我们完成一系列工作来确保mode顺利切换,其中就包含将当前的CPSR保存至SPSR的操作。
!CPSR中的mode位改变的瞬间才是CPU真正切换mode的一刻,因此CPSR必须在被改变之前就保存至目标mode的SPSR,所以只能由硬件完成。
不仅如此,ARM还有一个特殊设计:当目标寄存器为pc时,后缀s修改的将不是NZCV,而是将当前SPSR中的内容写入CPSR。
因此我们只需要在ISR(interrupt service routine)结束后,使用以下指令即可同时复原CPSR:
movs pc, lr // pc = lr_mode && cpsr = spsr_mode adds pc, lr, #0xff // pc = lr_mode + 0xff && cpsr = spsr_mode subs pc, lr, #4 // pc = lr_mode - 4 && cpsr = spsr_mode
!pc与cpsr是同时被修改的。
作为信息量超大的状态寄存器,CPSR中的每一个bit都至关重要,因此常常需要在保持其他bit不变的前提下对其中的个别bit进行读写,此时若使用普通的指令就会非常繁琐。因此ARM额外提供了一系列专门用于访问CPSR的特别指令 to make our life easier:
cps
Change Processor Status(修改CPSR[4:0])cps #0x1f // change CPU to SYS mode cps #0x11 // change CPU to FIQ mode cps #0x10 // change CPU to USR mode
cpsIE
/cpsID
Interrupt Enable / Disable(修改A、I、F位)cpsIE a // enable ABT interrupt (cpsr_a = 0) cpsIE i // enable IRQ interrupt (cpsr_i = 0) cpsID f, #0x10 // disable FIQ interrupt (cpsr_f = 1) and change to USR mode
!disables when the bit is set.
Interrupt
// 待续