ARM 微处理器的数据类型

来源:互联网 发布:java date时间差 编辑:程序博客网 时间:2021/12/08 07:51

3.1 ARM 微处理器的数据类型

3.1 ARM 微处理器的数据类型

 

如第2章所述,ARM微处理器支持如下数据类型:

类型

长度

说明

字节(Byte)

8位

有符号和无符号字节数据

半字(HalfWord)

16位

有符号和无符号的半字数据

字(Word)

32位

有符号和无符号的字数据

需要指出的是:字节类型数据是最小的数据存储单位,其可以存储子存储器的任何位置;半字类型数据存储边界必须是两个字节对齐的;字类型数据的存储边界必须是4个字节对齐的。如图3.1所示。

图3.1  字、半字、字节存储格式

另外,采用RISC设计思想的ARM微处理器提供了32位的ARM指令集和16位的Thumb指令集,带有J变种的ARM微处理器还支持执行8位Java字节码的指令集(Jazelle)。ARM指令在存储器中必须按4字节对齐;Thumb指令必须按2字节对齐;Java字节码指令按字节对齐。

当执行ARM指令时ARM微处理器处于ARM状态,当执行Thumb指令时ARM微处理器处于Thumb状态,执行8位的java指令码时微处理器处于Jazelle状态。

3.1 ARM 微处理器的工作模式

ARM微处理器有7种工作模式:如表3.1所示。

表3.1 ARM微处理器支持的工作模式

处理器工作模式

特权模式

异常模式

描述

用户模式(User)

普通程序执行模式,大部分任务执行在这种模式下。

系统模式(System)

使用和User模式相同寄存器集的特权模式。

快速中断模式(FIQ)

当一个高优先级(fast)中断产生时将会进入这种模式。

外部中断模式(IRQ)

当一个低优先级(normal)中断产生时将会进入这种模式。

管理模式(Supervisor)

当复位或软中断指令执行时进入这种模式。

数据访问中止模式(Abort)

当存取异常时将会进入这种模式,用于虚拟存储或存储保护。

未定义指令模式(Undef)

当执行未定义指令时进入这种模式,有时用于通过软件仿真协处理器硬件的工作方式。

如上表所示,除了用户模式和系统模式以外的其它5种模式又称之为异常模式当特定的异常发生时,微处理器就会进入到相应的异常模式中。除了用户模式以外的其它6种处理器模式称为特权模式,在特权模式下程序可以访问所有的系统资源。非特权模式和特权模式之间的区别在于有些操作只能在特权模式下才被允许,如直接改变模式和中断使能等。ARM核中有一个专门的输出信号来表明当前模式是特权模式还是非特权模式。ARM core有一个输出信号(nTRANS on ARM7TDMI, InTRANS, DnTRANS on ARM9, 或被编码成HPROT或BPROT in AMBA)来表明当前模式是特权模式和非特权模式,外设可以使用这些信号。例如,存储器控制器使用这些信号来控制IO操作,使其只能在特权模式下完成等。

处理器模式可以通过软件进行切换,也可以通过外部中断或异常处理过程进行切换。

大多数的用户程序运行在用户模式下。当处理器工作在用户模式时,应用程序不能够访问受操作系统保护的一些系统资源,应用程序也不能直接进行处理器模式切换。当需要进行处理器模式切换时,应用程序可以产生异常处理,在异常处理过程中进行处理器模式切换。这种体系结构可以使操作系统控制整个系统资源的使用。

当应用程序发生异常中断时,处理器进入相应的异常模式。在每一种异常模式中都有一组专用寄存器供相应的异常处理程序使用,这样就可以保证在进入异常模式时用户模式下的寄存器(保存程序运行状态)不被破坏。

在ARM体系结构v4及以上版本中开始有系统模式,没有任何异常能进入到系统模式。系统模式实际上相当于用户模式的特权模式。它和用户模式使用完全相同的寄存器,但是系统模式属于特权模式,可以访问所有的系统资源,也可以直接进行处理器模式切换,它主要供操作系统任务使用。通常操作系统的任务需要访问所有的系统资源,同时该任务仍然使用用户模式的寄存器组而不是异常模式下相应的寄存器组,这样可以保证当异常中断发生时任务状态不被破坏。在后面的异常处理程序一节中我们会看到,可重入异常的处理程序可以通过切换到系统模式来避免重入异常发生时某些寄存器无法保存带来的问题。

 

3.2.1 寄存器概述

ARM微处理器有37个32位长的寄存器,其中包括30个通用寄存器,6个状态寄存器和一个程序计数器寄存器(PC)。
如图3.2所示,ARM微处理器中将这37个寄存器分成不同的组,在ARM微处理器的每种工作模式下只能使用其中一组寄存器。我们知道,ARM微处理器共有7种模式,其中用户模式和系统模式拥有物理空间上完全相同的寄存器,而其它5种异常模式都有一些自己独立的寄存器。从图上可以看出,在用户和系统模式下可以使用R0-R15和CPSR共17个寄存器;在FIQ模式下可以使用R0-R15,CPSR,CPSR共18个寄存器,其中R8-R14以及SPSR寄存器是FIQ模式专有寄存器,其它寄存器和用户模式共用相同的物理寄存器;在IRQ、SVC、Undef、Abort模式下可以使用的寄存器都是18个(R0-R15,CPSR,SPSR),其中R13,R14,CPSR是各个模式专有的,其它和用户模式共用相同的物理寄存器。
可见,ARM内核中一共有37个物理上独立的寄存器,在每一种处理器模式中只能访问一组相应的寄存器。在每组寄存器中:
R13通常用作栈指针寄存器(SP),每一种模式有自己的R13,所以允许每一种异常都有自己的栈指针。
R14用作连接或返回地址寄存器(LR),每一种模式有自己的 R14。
R15用作程序计数器(PC),用来保存读取指令的地址。
CPSR (Current Program Status Register) 存储ARM微处理器当前的状态和模式标志。
SPSR (Saved Program Status Register)异常模式下的CPSR的备份寄存器,当一个异常发生时保存当前的CPSR值。结合连接寄存器可使处理器返回先前的状态。
ARM微处理器这样组织寄存器的好处在于当各种异常发生的时候,每种异常模式都可以保存一些重要的数据,使异常处理程序完成之后返回异常前的程序时不会破坏原有的寄存器或状态。

3.2.2 通用寄存器

通用寄存器包括:未分组寄存器(R0-R7)、分组寄存器(R8-R14)、程序计数器PC(R15)。
(1)未分组寄存器(R0-R7)
在ARM微处理器中寄存器R0-R7是未分组的,在图3.2中我们也看到,R0-R7在物理上只有一组,任何模式下使用R0-R7寄存器指的都是同一个R0-R7物理寄存器。未分组寄存器没有被系统用于特殊的用途,任何可使用通用寄存器的应用场合都可以使用未分组寄存器。在异常中断所引起的处理器模式切换时,要对未分组寄存器加以保护(入栈)以防止破坏寄存器中的数据。R0-R7在Thumb状态下也称为低组寄存器,R8-R15在Thumb状态下也称为高组寄存器。
(2)分组寄存器(R8-R14)
R8-R14是分组寄存器,具体访问哪个物理寄存器取决于当前的处理器模式。R8-R12这组寄存器物理上有两组,FIQ模式下使用自己专有的R8-R12,而其他模式使用同一组R8-R12寄存器。这样的结构设计有利于加快FIQ的处理速度。在ARM体系结构中,R8-R12没有任何指定的其他的用途,所以当FIQ中断到达时,可以不保存这些通用寄存器,也就是说FIQ处理程序在保存和恢复现场时可以少保存和恢复几个寄存器(R8-R12),从而提高中断处理迅速。因此FIQ模式常被用来处理一些时间紧急的任务。
分组寄存器R13和R14,分别对应6个不同的物理寄存器。其中用户模式和系统模式共用一个,5中异常模式中分别有自己的R13和R14。也就是IRQ下的R13、R14与用户模式或其他4种异常模式下的R13、R14是不同的物理寄存器。
R13寄存器在ARM中常用作栈指针,称为SP。因为ARM状态下没有专门的入栈和出栈指令,所以这只是一种习惯用法。也就是,并没有任何ARM指令强制使用R13作为栈指针,用户可以使用其他寄存器作为栈指针。每一种异常模式都有自己的R13,在使用是要分别对其进行初始化,以保证在相应模式下能正确的进行入栈和出栈操作。另外需要注意,在Thumb指令集中,有一些指令强制使用R13作为栈指针,如栈操作指令。R13也可以作为通用寄存器使用。
R14寄存器又被称为连接寄存器(Link Register,LR),在ARM体系结构中R14的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,R14中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据R14的值返回到异常发生前的相应位置继续执行。
当通过BL或BLX指令调用子程序时,硬件自动将子程序返回地址保存在R14寄存器中。在子程序返回时,把R14的值复制到程序计数器PC即可实现子程序返回。如,可以使用MOV  PC, LR或者BX  LR来完成子程序返回。
另外,也可以在在子程序入口处使用下面的指令将LR保存到栈中。
STMFD  SP!, {,LR}
在子程序返回时,使用如下相应的指令做出栈操作,实现从子程序返回。
LDMFD  SP!, {,PC}
R14还用于从异常返回。当异常发生时,该异常模式的寄存器R14被设置成该异常模式的返回地址(R14等于异常放生时PC的值减4(或者减2))。在不同异常模式下,R14保存的值并不是异常返回的真正地址,而是有一个常数的偏移量。例如:FIQ异常可以使用SUBS  PC, LR, #4实现异常返回。
R14也可以作为通用寄存器使用。
(3)程序计数器(R15)
ARM的寄存器R15被用为程序计算器PC。R15可以作为通用寄存器使用,但很多特殊的指令在使用R15时有些限制。当违反了这些指令的使用限制时,指令的执行结果是不可预知的。R15保存微处理器取指的地址,改变R15的值会引起程序执行顺序的改变。
在ARM状态下,ARM指令是32位的、是按字对齐的,所以R15[1:0]=0;在Thumb状态下,Thumb指令是16位的、按2字节对齐的,所以R15[0]=0。
由于ARM的流水线机制,指令读取的R15的值是当前正在执行的指令地址加上8个字节。读PC主要用于快速地对临近的指令或数据进行位置无关寻址,包括程序中的位置无关分支。
需要注意的是,当使用指令STR或STM对R15进行保存时,保存的可能是当前指令地址加8或当前指令地址加12。到底是哪种方式,取决于芯片的具体设计方式。当然,在同一个芯片中,只能采用一种方式。要么保存当前指令地址加8,要么保存当前指令地址加12。程序开发人员应尽量避免使用STR或STM指令来对R15进行操作。当不可避免要使用这种方式时,可以先通过一小段程序来确定所使用的芯片是使用哪种方式实现的。例如:
SUB  R1,PC, #4    ;R1中存放STR指令地址
STR  PC,[R0]      ;用STR指令将PC保存到R0指向的地址单元中,
                            ;PC=STR指令地址+偏移量(偏移量为8或者12)。
LDR  R0,[R0]    ;读取STR指令地址+偏移量的值
SUB  R0,R0,R1    ; STR指令地址+偏移量的值减去STR指令的地址,
                            ;得到偏移量值(8或者12)。
当用指令修改R15的值时,如果修改成功,它将使程序跳转到该地址执行。因为ARM指令是字对齐的,所以写入R15的地址值应满足BIT[1:0]=0b00,具体的规则根据ARM版本的不同也有所不同:
l         对于ARM版本3以及更低的版本,写入R15的地址值bit[1:0]被忽略,即写入R15的地址值将与0xFFFFFFFC做与操作。
l         对于ARM版本4以及更高的版本,程序必须保证写入R15寄存器的地址值的bit[1:0]为0b00,否则将会产生不可预知的结果。
l         对于Thumb指令集来说,指令是半字对齐的。处理器将忽略R15[0],即写入R15寄存器的值在写入前要先和0XFFFFFFFE做与操作。
有些指令对R15的操作有特殊的要求。比如,指令BX利用寄存器BIT[0]来确定需要跳转到的子程序是ARM状态还是Thumb状态。
 

3.2.3 程序状态寄存器

当前程序状态寄存器CPSR(Current Program Status Register)可以在任何微处理器模式下被访问,它包含条件码标志、中断控制、当前处理器模式以及其他状态和控制信息。图3.3显示CPSR的各个位含义。

图3.3  程序状态寄存器

3.2.3.1 条件码标志

CPSR最高4位:N(Negative)、Z(Zero)、C(Carry)和V(oVerflow)称为条件标志位。程序中的算术或逻辑指令可以根据其执行结果修改这些条件标志位,之后的条件执行指令可以根据这些条件标志决定相应的指令是否被执行。各条件标志位的具体含义如下:

(1)N(符号位)

该位设置为当前指令运行结果的BIT[31]的值。当两个由补码表示的有符号整数运算时,N=1表示运算的结果为负数;N=0表示结果为正数或零。

(2)Z(零标志位)

如果指令的运算结果为0,则Z=1(通常用来表示比较的结果为“相等”);否则Z=0。

(3)C(进、借位标志)

表示运算是否有进位、借位等。下面分4种情况讨论C的设置方法。

l         在加法指令中(包括比较指令CMN),当结果产生了进位,则C=1,表示无符号数运算发生上溢出;其他情况下C=0。

l         在减法指令中(包括比较指令CMP),当运算中发生错位(即无符号数运算发生下溢出),则C=0,;其他情况下C=1。

l         对于在操作数中包含移位操作的运算指令(非加/减法指令),C被设置成被移位寄存器最后移出去的位。

l         对于其他非加/减法运算指令,C的值通常不受影响。

(4)V(溢出标志位)

l         对于加/减运算指令,当操作数和运算结果都是以二进制的补码表示的带符号的数时,V=1表示符号位溢出。

l         对于非加/减法指令,通常不改变标志位V的值(具体可参照ARM指令手册)。尽管以上C和V的定义看起来颇为复杂,但使用时在大多数情况下用一个简单的条件测试指令即可,不需要程序员计算出条件码的精确值即可得到需要的结果。

3.2.3.2  Q标志位

在带DSP指令扩展的ARM v5E及更高版本中,CPSR[27]用于指示增强的DSP指令是否发生了溢出或饱和。当 QADD, QDADD, QSUB or QDSUB时发生饱和,或者SMLAxy or SMLAWx的结果超出32-bits时Q位被置位。该位一旦置位就不能使用上述指令来修改标识位,而必须使用MSR 指令写CPSR来清除。

在ARM v5以前的版本及ARM v5的非E系列处理器中未定义Q标志位。

3.2.3.3中断控制位

I=1时,IRQ被禁止;I=0时,IRQ中断使能。

F=1时,FIQ被禁止;F=0时,FIQ中断使能。

在程序中可以通过修改I、F位来禁止或使能IRQ和FIQ。

3.2.3.4状态控制位

T 位是处理器的状态控制位,主要用于ARM体系带T的版本,在非T系列的ARM版本中,T位将始终为0。当T=0时,处理器处于ARM状态(即正在执行32位的ARM指令)。当T=1时,处理器处于Thumb状态(即正在执行16位的Thumb指令)。

不能通过直接修改CPSR的T为来改变处理器的状态,因为直接修改CPSR的T位结果不可预知。必须通过状态切换指令BX、BLX指令来修改T位。

可以使用指令显式的在ARM状态和Thumb状态之间切换;另外异常发生时,处理器会自动的进入到ARM状态,异常发生前是ARM状态还是Thumb状态可以通过SPSR的T位来判断。

CPSR第24位为J位,被支持J变种的ARM微处理器支持,J = 1处理器处于Jazelle状态,执行8位的JAVA字节码指令。在Jazelle状态中,处理器并不是执行8位的指令预取,而是执行32位的高性能预取(4-byte)。另外,在Jazelle状态我们不提及PC,因为‘Jazelle PC’ 被自动保存在r14中。

3.2.3.5模式控制位

M[4∶0]为模式控制位,这些位的组合确定了处理器处于哪种状态。表3.2给出了各个模式对应的M值。只有表中列出的M值组合是有效的,其它组合无效。

表3.2  CPSR/SPSR状态控制位M[4∶0]

M[4∶0]

处理器模式

可以访问的寄存器

0b10000

User

PC,r14~r0,CPSR

0b10001

FIQ

PC,r14_fiq~r8_fiq,r7~r0,CPSR,SPSR_fiq

0b10010

IRQ

PC,r14_irq~r13_irq,r12~r0,CPSR,SPSR_irq

0b10011

Supervisor

PC,r14_svc~r13_svc,r12~r0,CPSR,SPSR_svc

0b10111

Abort

PC,r14_abt~r13_abt,r12~r0,CPSR,SPSR_abt

0b11011

Undefined

PC,r14_und~r13_und,r12~r0,CPSR,SPSR_und

0b11111

System

PC,r14~r0,CPSR(ARM v4及更高版本)

ARM微处理器的每种异常模式都有一个专用的物理寄存器SPSR(Saved Program Status Register),作为程序状态寄存器的备份寄存器。当特定的异常发生时,硬件自动将CPSR寄存器的内容保存到相应异常模式的SPSR寄存器中;当异常处理程序返回时,再将其内容恢复到当前程序状态寄存器。

由于用户模式和系统模式不属于异常中断模式,所以它们没有SPSR寄存器。当在用户模式或系统模式中访问SPSR,将会产生不可预知的结果。

3.2.3.6 CPSR/SPSR寄存器的访问、修改

对于状态寄存器的修改要遵守以下原则:

l         不修改和使用状态寄存器中未定义的位:这些在当前ARM版本中未使用的状态位,在之后的版本中可能会被用作新的用途。如果我们使用了这些位,在新的处理器中程序可能会无法正确运行。所以我们不应该使用状态寄存器中为未定义的位,应该保证这些位不被改变。

l         通常要遵循读取->修改->写会的原则:这个原则保证了我们在修改状态寄存器的某些位是保证其它位不受影响。

如图3.3所示,ARM微处理器中按8位一组,将状态寄存器(CPSR/SPSR)分为4个可分别写的区。各个区的含义如下:

l         控制(c)BIT[0-7]:CPSR的低8位(I、F、T及M[4∶0])统称为控制位。当异常发生时,这些位的值将由硬件自动改变。另外,当在特权模式时,可以通过软件编程来修改这些位的值。

l         扩展(x)BIT[8-15]:保留为将来使用。

l         状态(s)BIT[16-23]:保留为将来使用。

l         标识(f)BIT[24-31]:数据处理指令的运算结果会对CPSR的条件标志位产生影响,如:比较和测试指令(CMN、CMP、TEQ、TST);在算术、逻辑运算和数据传输指令中,目的寄存器不是R15时,可以通过在这些指令末尾加标志“S”来通知处理器指令的执行结果影响标志位。

分为4个可以独立写的区是为了提高修改状态寄存器的效率。前面我们指出对状态寄存器(CPSR/SPSR)的修改应该遵循读取->修改->写回的方法,但这样需要至少3条指令,效率相对较低;分成4个可以独立写的区(即修改其中的一个区而不影响其他24位的值),这样当我们知道某个区是确定的值的时候,修改状态寄存器就可以用一条指令直接修改状态寄存器的这个区,而不必再采用读取->修改->写回的方法了,因此可以提高修改状态寄存器的效率。具体见MSR指令说明。

下面给出几个影响和修改状态寄存器的例子。

(1)当CPSR中Z=0,R1=1时,执行指令:SUBS  R1,R1,#1,指令执行完后R1=0,

CPSR中Z=1。SUB因为指定了“S”标志,所以SUB指令根据运算的结果影响了CPSR的Z位。

(2)数据处理指令的目标寄存器是R15时,如果指定“S”标志,则硬件自动将SPSR寄存器的值复制到CPSR寄存器中,在异常返回时可以使用这种方法。

(3)直接使用MSR指令向CPSR/SPSR写进新值。

(4)MRC协处理器指令的目标寄存器为R15时,可以将协处理器产生的条件标志位的值传送到ARM处理器。

(5)在中断返回时,多寄存器加载指令可以将SPSR的值复制到CPSR中。

0 0