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