ARM微處理器的編程模型之:ARM寄存器組織
ARM處理器有37個32位長的寄存器。
· 1個用作PC(Program Counter)。
· 1個用作CPSR(Current Program Status Register)。
· 5個用作SPSR(Saved Program Status Registers)。
· 30個用作通用寄存器。
注意
以上37個寄存器中,1個CPSR和5個SPSR通稱為狀態(tài)寄存器,雖然這些寄存器是32位的,但目前只使用了其中的12位。除了這6個狀態(tài)寄存器外,其余的31個寄存器又稱為通用寄存器。
ARM處理器共有7種不同的處理器模式,在每一種處理器模式中有一組相應(yīng)的寄存器組。表3.2顯示了ARM的寄存器組織概要。
表3.2 寄存器組織概要
User
FIQ
IRQ
SVC
Undef
Abort
R0
User mode
R0~R7,R15,and CPSR
User mode
R0~R12,R15
and CPSR
User mode
R0~R12,R15
and CPSR
User mode R0~R12,R15
and CPSR
User mode R0~R12,R15
and CPSR
R1
R2
R3
R4
R5
R6
R7
R8
R8
R9
R9
R10
R10
續(xù)表
User
FIQ
IRQ
SVC
Undef
Abort
R11
R11
R12
R12
R13(SP)
R13(SP)
R13
R13
R13
R13
R14(LR)
R14(LR)
R14
R14
R14
R14
R15(PC)
CPSR
SPSR
SPSR
SPSR
SPSR
SPSR
注意
System模式使用和User模式相同的寄存器集
當(dāng)前處理器的模式?jīng)Q定著哪組寄存器可操作,任何模式都可以存取。
· 相應(yīng)的r0~r12。
· 相應(yīng)的r13(the stack pointer, sp)和r14(the link register, lr)。
· 相應(yīng)的r15(the program counter, pc)。
· 相應(yīng)的CPSR(current program status register, cpsr)。
特權(quán)模式(除System模式)還可以存取。
· 相應(yīng)的SPSR(saved program status register)。
3.3.1 通用寄存器通用寄存器根據(jù)其分組與否和使用目的分為以下3類。
· 未分組寄存器(The unbanked registers),包括r0~r7。
· 分組寄存器(The banked register),包括r8~r14。
· 程序計數(shù)器(Program Counter),即r15。
1.未分組寄存器未分組寄存器包括r0~r7。顧名思義,在所有處理器模式下對于每一個未分組寄存器來說,指的都是同一個物理寄存器。未分組寄存器沒有被系統(tǒng)用于特殊的用途,任何可采用通用寄存器的應(yīng)用場合都可以使用未分組寄存器。但由于其通用性,在異常中斷所引起的處理器模式切換時,其使用的是相同的物理寄存器,所以也就很容易使寄存器中的數(shù)據(jù)被破壞。
2. 分組寄存器r8~r14是分組寄存器,它們每一個訪問的物理寄存器取決于當(dāng)前的處理器模式。
對于這些分組寄存器r8~r12來說,每個寄存器對應(yīng)兩個不同的物理寄存器。一組用于除FIQ模式外的所有處理器模式,而另一組則專門用于FIQ模式。這樣的結(jié)構(gòu)設(shè)計有利于加快FIQ的處理速度。不同模式下寄存器的使用,要使用寄存器名后綴加以區(qū)分,例如,當(dāng)使用FIQ模式下的寄存器時,寄存器r8和寄存器r9分別記做r8_fiq, r9_fiq;當(dāng)使用用戶模式下的寄存器時,寄存器r8和r9分別記做r8_usr, r9_usr等。在ARM體系結(jié)構(gòu)中,r8~r12沒有任何指定的其他的用途,所以當(dāng)FIQ中斷到達時,不用保存這些通用寄存器,也就是說FIQ處理程序可以不必執(zhí)行保存和恢復(fù)中斷現(xiàn)場的指令,從而可以使中斷處理過程非常迅速。所以FIQ模式常被用來處理一些時間緊急的任務(wù),如DMA處理。
對于分組寄存器r13和r14來說,每個寄存器對應(yīng)6個不同的物理寄存器。其中的一個是用戶模式和系統(tǒng)模式公用的,而另外5個分別用于5種異常模式。訪問時需要指定它們的模式。名字形式如下:
· r13_<mode>
· r14_<mode>
其中<mode>可以是以下幾種模式之一:usr、svc、abt、und、irp及fiq。
r13寄存器在ARM中常用作堆棧指針,稱為SP。當(dāng)然,這只是一種習(xí)慣用法,并沒有任何指令強制性的使用r13作為堆棧指針,用戶完全可以使用其他寄存器作為堆棧指針。而在Thumb指令集中,有一些指令強制性的將r13作為堆棧指針,如堆棧操作指令。
每一種異常模式擁有自己的r13。異常處理程序負責(zé)初始化自己的r13,使其指向該異常模式專用的棧地址。在異常處理程序入口處,將用到的其他寄存器的值保存在堆棧中,返回時,重新將這些值加載到寄存器。通過這種保護程序現(xiàn)場的方法,異常不會破壞被其中斷的程序現(xiàn)場。
寄存器r14又被稱為連接寄存器(Link Register,LR),在ARM體系結(jié)構(gòu)中具有下面兩種特殊的作用。
(1)每一種處理器模式用自己的r14存放當(dāng)前子程序的返回地址。當(dāng)通過BL或BLX指令調(diào)用子程序時,r14被設(shè)置成該子程序的返回地址。在子程序返回時,把r14的值復(fù)制到程序計數(shù)器PC。典型的做法是使用下列兩種方法之一。
· 執(zhí)行下面任何一條指令。
MOV PC, LR
BX LR
· 在子程序入口處使用下面的指令將PC保存到堆棧中。
STMFD SP!, {<register>,LR}
在子程序返回時,使用如下相應(yīng)的配套指令返回。
LDMFD SP!, {<register>,PC}
(2)當(dāng)異常中斷發(fā)生時,該異常模式特定的物理寄存器r14被設(shè)置成該異常模式的返回地址,對于有些模式r14的值可能與返回地址有一個常數(shù)的偏移量(如數(shù)據(jù)異常使用SUB PC, LR,#8返回)。具體的返回方式與上面的子程序返回方式基本相同,但使用的指令稍微有些不同,以保證當(dāng)異常出現(xiàn)時正在執(zhí)行的程序的狀態(tài)被完整保存。
R14也可以被用作通用寄存器使用。
注意
當(dāng)嵌套中斷被允許時(即異??芍厝耄?,r13和r14的使用要特別小心。例如,在用戶模式下一個IRQ中斷發(fā)生,這時兩種模式分別使用不同的r13和r14,換句話講,用戶模式使用r13_usr和r14_usr,而IRQ模式使用r13_irq和r14_irq,這樣不會造成寄存器使用沖突。但是,當(dāng)程序運行在IRQ模式下,又有IRQ中斷進入,此時,第二級中斷使用r13_irq和r14_irq,沖掉了第一級IRQ的堆棧指針和返回地址,導(dǎo)致程序異常。
解決辦法是在第二級中斷發(fā)生前,將第一級中斷用到的寄存器壓棧。
3.3.2 程序計數(shù)器r15程序計算器r15又被記為PC。它有時可以被和r0-r14一樣用作通用寄存器,但很多特殊的指令在使用r15時有些限制。當(dāng)違反了這些指令的使用限制時,指令的執(zhí)行結(jié)果是不可預(yù)知的。
程序計數(shù)器在下面兩種情況下用于特殊的目的。
· 讀程序計數(shù)器。
· 寫程序計數(shù)器。
1.程序計數(shù)器讀操作由于ARM的流水線機制,指令讀出的r15的值是指令地址加上8個字節(jié)。由于ARM指令始終是字對齊的,所以讀出的結(jié)果位[1∶0]始終是0(但在Thumb狀態(tài)下,指令為2字節(jié)對齊,bit[0]=0)。
讀PC主要用于快速地對臨近的指令或數(shù)據(jù)進行位置無關(guān)尋址,包括程序中的位置無關(guān)分支。
需要注意的是,當(dāng)使用指令STR或STM對r15進行保存時,保存的可能是當(dāng)前指令地址加8或當(dāng)前指令地址加12。到底是哪種方式,取決于芯片的具體設(shè)計方式。當(dāng)然,在同一個芯片中,要么采用當(dāng)前指令地址加8,要么采用當(dāng)前指令地址加12,不可能有些指令采用當(dāng)前地址加8,有些采用當(dāng)前地址加12。程序開發(fā)人員應(yīng)盡量避免使用STR或STM指令來對r15進行操作。當(dāng)不可避免要使用這種方式時,可以先通過一小段程序來確定所使用的芯片是使用哪種方式實現(xiàn)的。例如:
SUB R1,PC,#4 ;r1中存放STR指令地址
STR PC,[R0] ;將PC=STR地址+offset保存到r0中
LDR R0,[R0]
SUB R0,R0,R1 ;offset=PC-STR地址
2.程序計數(shù)器寫操作當(dāng)指令向r15寫入地址數(shù)據(jù)時,如果指令成功返回,它將使程序跳轉(zhuǎn)到該地址執(zhí)行。由于ARM指令是字對齊的,寫入r15的地址值應(yīng)滿足bit[1:0]=0b00,具體的規(guī)則根據(jù)ARM版本的不同也有所不同:
· 對于ARM版本3以及更低的版本,寫入r15的地址值bit[1:0]被忽略,即寫入r15的地址值將與0xFFFFFFFC做與操作。
· 對于ARM版本4以及更高的版本,程序必須保證寫入r15寄存器的地址值的bit[1:0]為0b00,否則將會產(chǎn)生不可預(yù)知的結(jié)果。
對于Thumb指令集來說,指令是半字對齊的。處理器將忽略bit[0],即寫入r15寄存器的值在寫入前要先和0XFFFFFFFE做與操作。
有些指令對r15的操作有特殊的要求。比如,指令BX利用bit[0]來確定需要跳轉(zhuǎn)到的子程序是ARM狀態(tài)還是Thumb狀態(tài)。
注意
這種讀取PC值和寫入PC值的不對稱操作需要特別注意。
3.3.3 程序狀態(tài)寄存器當(dāng)前程序狀態(tài)寄存器CPSR(Current Program Status Register)可以在任何處理器模式下被訪問,它包含下列內(nèi)容。
· ALU(Arithmetic Logic Unit)狀態(tài)標(biāo)志的備份。
· 當(dāng)前的處理器模式。
· 中斷使能標(biāo)志。
· 設(shè)置處理器的狀態(tài)(只在4T架構(gòu))。
每一種處理器模式下都有一個專用的物理寄存器作備份程序狀態(tài)寄存器SPSR(Saved Program Status Register)。當(dāng)特定的異常中斷發(fā)生時,這個物理寄存器負責(zé)存放當(dāng)前程序狀態(tài)寄存器的內(nèi)容。當(dāng)異常處理程序返回時,再將其內(nèi)容恢復(fù)到當(dāng)前程序狀態(tài)寄存器。
注意
由于用戶模式和系統(tǒng)模式不屬于異常中斷模式,所以它們沒有SPSR。當(dāng)在用戶模式或系統(tǒng)模式中訪問SPSR,將會產(chǎn)生不可預(yù)知的結(jié)果。
CPSR寄存器(和保存它的SPSR寄存器)中的位分配如圖3.4所示。
圖3.4 程序狀態(tài)寄存器格式
1.標(biāo)志位N(Negative)、Z(Zero)、C(Carry)和V(oVerflow)通稱為條件標(biāo)志位。這些條件標(biāo)志位會根據(jù)程序中的算術(shù)或邏輯指令的執(zhí)行結(jié)果進行修改,而且這些條件標(biāo)志位可由大多數(shù)指令檢測以決定指令是否執(zhí)行。
在ARM 4T架構(gòu)中,所有的ARM指令都可以條件執(zhí)行,而Thumb指令卻不能。
各條件標(biāo)志位的具體含義如下。
· N
本位設(shè)置成當(dāng)前指令運行結(jié)果的bit[31]的值。當(dāng)兩個由補碼表示的有符號整數(shù)運算時,N=1表示運算的結(jié)果為負數(shù);N=0表示結(jié)果為正數(shù)或零。
· Z
Z=1表示運算的結(jié)果為零,Z=0表示運算的結(jié)果不為零。
注意
對于CMP指令,Z=1表示進行比較的兩個數(shù)相等。
· C
下面分4種情況討論C的設(shè)置方法。
① 在加法指令中(包括比較指令CMN),當(dāng)結(jié)果產(chǎn)生了進位,則C=1,表示無符號數(shù)運算發(fā)生上溢出;其他情況下C=0。
② 在減法指令中(包括比較指令CMP),當(dāng)運算中發(fā)生錯位(即無符號數(shù)運算發(fā)生下溢出),則C=0,;其他情況下C=1。
③ 對于在操作數(shù)中包含移位操作的運算指令(非加/減法指令),C被設(shè)置成被移位寄存器最后移出去的位。
④ 對于其他非加/減法運算指令,C的值通常不受影響。
· V
下面分兩種情況討論V的設(shè)置方法。
① 對于加/減運算指令,當(dāng)操作數(shù)和運算結(jié)果都是以二進制的補碼表示的帶符號的數(shù)時,V=1表示符號位溢出。
② 對于非加/減法指令,通常不改變標(biāo)志位V的值(具體可參照ARM指令手冊)。
盡管以上C和V的定義看起來頗為復(fù)雜,但使用時在大多數(shù)情況下用一個簡單的條件測試指令即可,不需要程序員計算出條件碼的精確值即可得到需要的結(jié)果。
注意
下面兩種情況會對CPSR的條件標(biāo)志位產(chǎn)生影響。
1.比較指令(CMN、CMP、TEQ、TST)。
2.目的寄存器不是r15的算術(shù)邏輯運算和數(shù)據(jù)傳輸指令。這些指令可以通過在指令末尾加標(biāo)志“S”來通知處理器指令的執(zhí)行結(jié)果影響標(biāo)志位。
【例3.2】
使用SUBS指令從寄存器r1中減去常量1,然后把結(jié)果寫回到r1,其中CPSR的Z位將受到影響。
指令執(zhí)行前:
CPSR中Z=0
r1=0x00000001
SUBS r1,r1,#1
SUB指令執(zhí)行結(jié)束后:
r1=0x0
CPSR中Z=1
目的寄存器是r15的帶“位設(shè)置”的算術(shù)和邏輯運算指令,也可以將SPSR的值復(fù)制到CPSR中,這種操作主要用于從異常中斷程序中返回。
用MSR指令向CPSR/SPSR寫進新值。
目的寄存器位r15的MRC協(xié)處理器指令通過這條指令可以將協(xié)處理器產(chǎn)生的條件標(biāo)志位的值傳送到ARM處理器。
在中斷返回時,使用LDR指令的變種指令可以將SPSR的值復(fù)制到CPSR中。
2.Q標(biāo)志位在帶DSP指令擴展的ARM v5及更高版本中,bit[27]被指定用于指示增強的DAP指令是否發(fā)生了溢出,因此也就被稱為Q標(biāo)志位。同樣,在SPSR中bit[27]也被稱為Q標(biāo)志位,用于在異常中斷發(fā)生時保存和恢復(fù)CPSR中的Q標(biāo)志位。
在ARM v5以前的版本及ARM v5的非E系列處理器中,Q標(biāo)志位沒有被定義。屬于待擴展的位。
3.控制位CPSR的低8位(I、F、T及M[4∶0])統(tǒng)稱為控制位。當(dāng)異常發(fā)生時,這些位的值將發(fā)生相應(yīng)的變化。另外,如果在特權(quán)模式下,也可以通過軟件編程來修改這些位的值。
① 中斷禁止位
I=1,IRQ被禁止。
F=1,F(xiàn)IQ被禁止。
② 狀態(tài)控制位
T位是處理器的狀態(tài)控制位。
T=0,處理器處于ARM狀態(tài)(即正在執(zhí)行32位的ARM指令)。
T=1,處理器處于Thumb狀態(tài)(即正在執(zhí)行16位的Thumb指令)。
當(dāng)然,T位只有在T系列的ARM處理器上才有效,在非T系列的ARM版本中,T位將始終為0。
③ 模式控制位
M[4∶0]作為位模式控制位,這些位的組合確定了處理器處于哪種狀態(tài)。表3.3列出了其具體含義。
只有表中列出的組合是有效的,其他組合無效。
表3.3 狀態(tài)控制位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及更高版本)
注意
由于用戶模式(User)和系統(tǒng)模式(System)是非異常模式,所以沒有單獨的SPSR保存程序狀態(tài)字。在用戶模式或系統(tǒng)模式下,讀SPSR將返回一個不可預(yù)知的值,而寫SPSR將被忽略。