第十四课(2)CPU的工作模式 / 状态 / 工作模式下的寄存器
参考书:
英文:arm architecture reference manual arm920t
中文:杜春雷 《arm体系结构与编程》
1、CPU的工作模式(Mode):
- usr 用户模式
- sys 系统模式
- 异常模式 5种:
undefined(und) 未定义模式
Supervisor(svc) 管理模式
Abort(abt) 中止模式
IRQ(irq) 中断模式
FIQ(fiq) 快中断模式
==> Abort(abt)终止模式的情况:
指令预取终止
数据访问终止
==>CPU的两种中断模式:
IRQ(irq) 通用中断模式
FIQ(fiq) 快速中断模式
==>不同模式的切换:
系统模式和异常模式,这6种模式为特权模式,可以写随意切换。但是用户模式不可以切换到其他模式, 可以编程操作CPSR直接进入其他模式。
==>有关各个模式下能访问寄存器:
P73
在这张图注意到有些寄存器画有灰色的三角形,表示访问该模式下访问的专属寄存器
比如
mov R0, R8
mov R0, R8
在System 模式下访问的是R0 ~ R8,在所有模式下访问R0都是同一个寄存器
mov R0,R8_fiq
但是在FIQ模式下,访问R8是访问的FIQ模式专属的R8寄存器,不是同一个物理上的寄存器
在这五种异常模式中每个模式都有自己专属的R13 R14寄存器,R13用作SP(栈) R14用作LR(返回地址)
LR是用来保存发生异常时的指令地址.
为什么快中断(FIQ)有那么多专属寄存器?
这些寄存器称为备份寄存器,是因为有自己独有的寄存器,就可以不需要去保存原来用户/系统模式下的寄存器,节省很多时间。(Linux系统里不使用FIQ模式)
保存现场(保存被中断模式的寄存器):
就比如说我们的程序正在系统模式/用户模式下运行,当你发生中断时,需要把R0 ~ R14这些寄存器全部保存下来,然后处理异常,最后恢复这些寄存器
但如果是快中断,那么我就不需要保存 系统/用户模式下的R8 ~ R12这几个寄存器,在FIQ模式下有自己专属的R8 ~ R12寄存器,省略保存寄存器的时间,加快处理速度。
CRSR(Current Program Status Register)当前程序状态寄存器,SPSR(Saved Program Status Register)保存的程序状态寄存器,他们格式如下:
P76
M0~M4 是模式位:
我们可以读取这5位来判断CPU处于哪一种模式,也可以修改模式位;
但是当前处于用户模式下,是没有权限修改这些位的。
M0~M4对应的值,在手册P78
查看其他位
Bit5 State bits表示CPU工作与Thumb State还是ARM State用的指令集是什么
Bit6 FIQ disable当bit6等于1时,FIQ是不工作的
Bit7 IRQ disable当bit5等于1时,禁止所有的IRQ中断,这个位是IRQ的总开关
Bit8 ~ Bit27是保留位
Bite28 ~ Bit31是状态位,
什么是状态位?
比如说执行一条指令
cmp R0, R1
如果R0 等于 R1 那么zero位等于1,这条指令影响 Z 位,如果R0 == R1,则Z = 1
beq跳转到xxx这条指令会判断Bit30是否为1,是1的话则跳转,不是1的话则不会跳转
可知,这些指令是借助状态位实现的。
我们来看看发生异常时CPU是如何协同工作的:进入退出异常的处理流程(硬件)
手册P79
怎么进入异常?(硬件完成的)
1、把下一条指令的地址保存在lr寄存器里
下一条指令的地址为PC+4(ARM)/ PC+2(Thumb)
2、CPSR的值保存在SPSR
3、修改CPSR的模式位(M0~M4),进入异常模式
4、跳到向量表
怎么退出异常?
1、PC = LR_异常 - offset
offset怎么来的(P80 table2-2)
2、恢复CPSR的值,从SPSR里获取
3、如果是中断的话,清中断。其他异常就不用
2、CPU的状态(State)
- ARM state
- Thumb state
ARM状态下用的ARM指令集,每个指令4byte
Thumb状态下用的是Thumb指令,每个指令2byte
==>引入Thumb减少存储空间:
对于同一条指令 mov r0, r1
ARM的机器码为4byte
Thumb的机器码为2byte
==>ARM指令集与Thumb指令集的区别:
Thumb 指令可以看作是 ARM 指令压缩形式的子集,是针对代码密度的问题而提出的,它具有 16 位的代码密度但是它不如ARM指令的效率高 .
Thumb 不是一个完整的体系结构,不能指望处理只执行Thumb 指令而不支持 ARM 指令集.
因此,Thumb 指令只需要支持通用功能,必要时可以借助于完善的 ARM 指令集,比如,所有异常自动进入 ARM 状态.在编写 Thumb 指令时,先要使用伪指令 CODE16 声明,而且在 ARM 指令中要使用 BX指令跳转到 Thumb 指令,以切换处理器状态.编写 ARM 指令时,则可使用伪指令 CODE32声明.