1.10 寄存器组织
ARM处理器有如下40个32位长的寄存器。
(1)33个通用寄存器。
(2)6个状态寄存器:1个CPSR(Current Program Status Register,当前程序状态寄存器),6个SPSR(Saved Program Status Register,备份程序状态寄存器)。
(3)1个PC(Program Counter,程序计数器)。
ARM处理器共有7种不同的处理器模式,在每一种处理器模式中都有一组相应的寄存器组,图1-6列出了ARM处理器的寄存器组织概要。
图1-6 寄存器列表
当前处理器的模式决定着哪组寄存器可操作,任何模式都可以存取下列寄存器。
(1)相应的R0~R12。
(2)相应的R13(Stack Pointer,SP,栈指向)和R14(the Link Register,LR,链路寄存器)。
(3)相应的R15(PC)。
(4)相应的CPSR。
特权模式(除System模式外)还可以存取相应的SPSR。
通用寄存器根据其分组与否可分为以下两类。
(1)未分组寄存器(Unbanked Register),包括R0~R7。
(2)分组寄存器(Banked Register),包括R8~R14。
1.未分组寄存器
未分组寄存器包括R0~R7。顾名思义,在所有处理器模式下对于每一个未分组寄存器来说,指的都是同一个物理寄存器。未分组寄存器没有被系统用于特殊的用途,任何可采用通用寄存器的应用场合都可以使用未分组寄存器。但由于其通用性,在异常中断所引起的处理器模式切换时,其使用的是相同的物理寄存器,因此也就很容易使寄存器中的数据被破坏。
2.分组寄存器
R8~R14是分组寄存器,它们每一个访问的物理寄存器取决于当前的处理器模式。
对于分组寄存器R8~R12来说,每个寄存器对应两个不同的物理寄存器。一组用于除FIQ模式外的所有处理器模式,而另一组则专门用于FIQ模式。这样的结构设计有利于加快FIQ的处理速度。不同模式下寄存器的使用,要使用寄存器名后缀加以区分。例如,当使用FIQ模式下的寄存器时,寄存器R8和寄存器R9分别记为R8_fiq、R9_fiq;当使用用户模式下的寄存器时,寄存器R8和R9分别记为R8_usr、R9_usr等。在ARM体系结构中,R8~R12没有任何指定的其他的用途,所以当FIQ中断到达时,不用保存这些通用寄存器,也就是说,FIQ 处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程非常迅速。所以FIQ模式常被用来处理一些时间紧急的任务,如DMA处理。
对于分组寄存器R13和R14来说,每个寄存器对应6个不同的物理寄存器。其中的一个是用户模式和系统模式公用的,而另外5个分别用于5种异常模式。访问时需要指定它们的模式。名字形式如下。
(1)R13_<mode>
(2)R14_<mode>
其中,<mode>可以是以下几种模式之一:usr、svc、abt、und、irp、fiq及mon。
R13寄存器在ARM处理器中常用做堆栈指针,称为SP。当然,这只是一种习惯用法,并没有任何指令强制性地使用R13作为堆栈指针,用户完全可以使用其他寄存器作为堆栈指针。而在Thumb指令集中,有一些指令强制性地将R13作为堆栈指针,如堆栈操作指令。
每一种异常模式拥有自己的R13。异常处理程序负责初始化自己的R13,使其指向该异常模式专用的栈地址。在异常处理程序入口处,将用到的其他寄存器的值保存在堆栈中,返回时,重新将这些值加载到寄存器。通过这种保护程序现场的方法,异常不会破坏被其中断的程序现场。
寄存器R14又被称为连接寄存器(Link Register,LR),它在ARM体系结构中具有下面两种特殊的作用。
每一种处理器模式用自己的R14存放当前子程序的返回地址。当通过BL或BLX指令调用子程序时, R14被设置成该子程序的返回地址。在子程序返回时,把R14的值复制到程序计数器(PC)。典型的做法是使用下列两种方法之一。
① 执行下面任何一条指令。
MOV PC,LR
BX LR
② 在子程序入口处使用下面的指令将PC保存到堆栈中。
STMFD SP!,{<register>,LR}
在子程序返回时,使用如下相应的配套指令返回。
LDMFD SP!,{<register>,PC}
(3)当异常中断发生时,该异常模式特定的物理寄存器R14被设置成该异常模式的返回地址,对于有些模式R14的值可能与返回地址有一个常数的偏移量(如数据异常使用SUB PC,LR,#8返回)。具体的返回方式与上面的子程序返回方式基本相同,但使用的指令稍微有些不同,以保证当异常出现时正在执行的程序的状态被完整保存。
R14也可以被用做通用寄存器使用。