Thumb、ARM指令 狀態(tài)切換 收藏
與ARM指令集相比較,Thumb指令集中的數(shù)據(jù)處理指令的操作數(shù)仍然是32位,指令地址也為32位,但Thumb指令集為實現(xiàn)16位的指令長度,舍棄了ARM指令集的一些特性,如大多數(shù)的Thumb指令是無條件執(zhí)行的,而幾乎所有的ARM指令都是有條件執(zhí)行的;大多數(shù)的Thumb數(shù)據(jù)處理指令的目的寄存器與其中一個源寄存器相同。 由于Thumb指令的長度為16位,即只用ARM指令一半的位數(shù)來實現(xiàn)同樣的功能,所以,要實現(xiàn)特定的程序功能,所需的Thumb指令的條數(shù)較ARM指令多。在一般的情況下,Thumb指令與ARM指令的時間效率和空間效率關系為:
— Thumb代碼所需的存儲空間約為ARM代碼的60%~70%
— Thumb代碼使用的指令數(shù)比ARM代碼多約30%~40%
— 若使用32位的存儲器,ARM代碼比Thumb代碼快約40%
— 若使用16位的存儲器,Thumb代碼比ARM代碼快約40%~50%
— 與ARM代碼相比較,使用Thumb代碼,存儲器的功耗會降低約30%
顯然,ARM指令集和Thumb指令集各有其優(yōu)點,若對系統(tǒng)的性能有較高要求,應使用32位的存儲系統(tǒng)和ARM指令集,若對系統(tǒng)的成本及功耗有較高要求,則應使用16位的存儲系統(tǒng)和Thumb指令集。當然,若兩者結(jié)合使用,充分發(fā)揮其各自的優(yōu)點,會取得更好的效果。
-------------------------------------------- Thumb指令集(16bit) Thumb指令集可以看作是ARM指令壓縮形式的子集,它是為減小代碼量而提出,具有16bit的代碼密度。Thumb指令體系并不完整,只支持通用功能,必要時仍需要使用ARM指令,如進入異常時。其指令的格式與使用方式與ARM指令集類似,而且使用并不頻繁,Thumb指令集作一般了解。 在編寫Thumb指令時,先要使用偽指令CODE16聲明,編寫ARM指令時,則可使用CODE32偽指令聲明。
1、Thumb指令集沒有協(xié)處理器指令、信號量指令、以及訪問CPSR或SPSR的指令,沒有乘加指令及64位乘法指令等,且指令的第二操作數(shù)受到限制;
2、大多數(shù)的Thumb數(shù)據(jù)處理指令采用2地址格式; 3、除了跳轉(zhuǎn)指令B有條件執(zhí)行功能之外,其他指令均為無條件執(zhí)行,而且分支指令的跳轉(zhuǎn)范圍有更多限制;
4、數(shù)據(jù)處理指令是對通用寄存器進行操作,在大多數(shù)情況下,操作的結(jié)果放入其中一個操作數(shù)寄存器中,而不是放入第3個寄存器中;訪問寄存器R8~R15受到一定的限制,除MOV、ADD指令訪問R8~R15外,其他數(shù)據(jù)處理指令總是更新CPSR中ALU狀態(tài)標志,訪問寄存器R8~R15的Thumb數(shù)據(jù)處理指令不能更新CPSR中的ALU狀態(tài)指示。
5、Thumb狀態(tài)下,單寄存器加載和存儲指令只能訪問寄存器R0~R7;
6、LDM、STM指令可以將任何范圍為R0~R7的寄存器子集加載或存儲;
7、PUSH、POP指令使用棧寄存器R13作為基址堆棧操作。
8、The Thumb instruction set format: --------------------------------------- 大多數(shù)ARM數(shù)據(jù)處理指令采用的是3地址格式(除了64位乘法指令外)。
所有異常都會使微處理器返回到ARM模式狀態(tài),并在ARM的編程模式中處理。由于ARM微處理器字傳送地址必須可被4整除(即字對準),半字傳送地址必須可被2整除(即半字對準)。而Thumb指令是2個字節(jié)長,而不是4個字節(jié),所以,由Thumb執(zhí)行狀態(tài)進入異常時其自然偏移與ARM不同。
16位Thumb指令集是從32位ARM指令集提取指令格式的,每條Thumb指令有相同處理器模型所對應的32位ARM指令。
---------------------------------------
只要遵循ATPCS調(diào)用規(guī)則,Thumb子程序和ARM子程序就可以互相調(diào)用。在這種嵌入式系統(tǒng)軟件開發(fā)中,為了增強系統(tǒng)的靈活性以及提高系統(tǒng)的整體性能經(jīng)常需要使用16位的Thumb指令。如何有效、準確地使用ARM/Thumb狀態(tài)切換(Interworking)是關系到整個系統(tǒng)成敗的關鍵環(huán)節(jié),也是在具體項目開發(fā)過程中相對比較難掌握的內(nèi)容。本文主要介紹ARM體系結(jié)構(gòu)中的ARM/Thumb狀態(tài)切換(Interworking)。
1. ARM/Thumb 指令的性能比較
在ARM處理器中,內(nèi)核同時支持32位的ARM指令和16位的Thumb令。對于ARM指令來說,所有的指令長度都是32位,并且執(zhí)行周期大多為單周期,指令都是有條件執(zhí)行的。而THUMB指令的特點如下:
指令執(zhí)行條件經(jīng)常不會使用;
源寄存器與目標寄存器經(jīng)常是相同的; 使用的寄存器數(shù)量比較少; 常數(shù)的值比較??; 內(nèi)核中的桶式移位器(barrel shifter)經(jīng)常是不使用的; 也就是說16位的Thumb指令一般可以完成和32位ARM相同的任務。當用戶使用C程序來處理應用時,如果編譯為Thumb指令,那么它的目標代碼大小只有編譯為ARM指令時的65%左右,這樣就增加了指令密度。從另一方面來看,處理器在這兩種狀態(tài)下的性能是依賴于指令執(zhí)行的存儲器的寬度的。下面的圖一具體說明二者的性能比較??梢钥闯觯诖鎯ζ魇?2位的情況下,ARM性能較好,這時因為同樣的代碼編譯的結(jié)果Thumb指令將會比ARM多,Thumb指令仍舊花費指令周期來從32-bit塊內(nèi)存預取。在16-bit內(nèi)存上,即使有比ARM多的代碼,這時Thumb性能也較好,因為Thumb每一條指令預取需要一個周期而每條ARM指令需要兩個周期。另外在16-bit內(nèi)存上,Thumb的性能降低了;這是因為數(shù)據(jù)去操作和特殊的堆棧操作,即使在Thumb下,堆棧操作仍是32-bit操作,導致低的性能在16-bit內(nèi)存架構(gòu)上。一個改進的方法是提供32-bit的內(nèi)存來放置堆棧。在這種情況下的性能提高到了32-bit內(nèi)存架構(gòu)的水平。主要的差別是因為使用的整型的(32-bit)全局數(shù)據(jù)將仍被存儲在16-bit內(nèi)存上。 另外,與ARM代碼相比較,使用Thumb代碼,存儲器的功耗會降低約30%。
圖一
顯然,ARM指令集和Thumb指令集各有其優(yōu)點,若對系統(tǒng)的執(zhí)行效率有較高的要求,應使用32位的存儲系統(tǒng)和ARM指令集,若對系統(tǒng)的成本及功耗有較高的要求,則應使用16為的存儲系統(tǒng)和Thumb指令集。當然,若兩者結(jié)合使用,充分發(fā)揮其各自的優(yōu)點,會取得更好的效果。
2.切換(Interwoking)的基本概念及切換時的子函數(shù)調(diào)用
在我們的實際系統(tǒng)應用中,因為ARM/Thumb指令具有不同的特點,所以不同的場合開發(fā)人員會有不同的選擇。Thumb指令低密度及在窄存儲器時性能高的特點使得它在大多數(shù)基于C代碼的系統(tǒng)中有非常廣泛的應用,但是有些場合中系統(tǒng)只能使用ARM指令,比如:
如果對于速度有比較高的要求,ARM指令在寬存儲器中會提供更高的性能;
某些功能只能由ARM指令來實現(xiàn),比如:訪問CPSR寄存器來使能/禁止中斷或者改變處理器工作模式;訪問協(xié)處理器CP15;執(zhí)行C代碼不支持的DSP算術指令; 異常中斷(Exception)處理。在進入異常中斷后,內(nèi)核自動切換到ARM狀態(tài)。即在異常中斷處理程序入口的一些指令是ARM指令,然后根據(jù)需要程序可以切換到Thumb狀態(tài),在異常中斷處理程序返回前,程序再切換到ARM狀態(tài)。 ARM處理器總是從ARM狀態(tài)開始執(zhí)行。因而,如果要在調(diào)試器中運行Thumb程序,必須為該Thumb程序添加一個ARM程序頭,然后再切換到Thumb狀態(tài),調(diào)用該Thumb程序。 所以在實際系統(tǒng)中,內(nèi)核狀態(tài)需要經(jīng)常的切換(Interworking)來滿足系統(tǒng)性能需求。具體的切換是通過Branch Exchange—即BX 指令來實現(xiàn)的。指令格式為: Thumb狀態(tài) BX Rn
ARM狀態(tài) BX<condition> Rn
其中Rn可以是寄存器R0—R15中的任意一個。指令可以通過將寄存器Rn的內(nèi)容拷貝到程序計數(shù)器PC來完成在4Gbyte地址空間中的絕對跳轉(zhuǎn),而狀態(tài)切換是由寄存器Rn的最低位來指定的,如果操作數(shù)寄存器的狀態(tài)位Bit0=0,則進入ARM狀態(tài),如果Bit0=1,則進入Thumb狀態(tài),圖二給出了具體得切換過程。
圖二
下面是某系統(tǒng)中使用的程序切換實例。
CODE32 //ARM狀態(tài)下的代碼
LDR R0, =Into_Thumb+1
//產(chǎn)生跳轉(zhuǎn)地址并且設置最低位
BX R0
//Branch Exchange 進入Thumb狀態(tài)
…
CODE16 //Thumb狀態(tài)下的子函數(shù)
…
LDR R3, =Back_to_ARM
//產(chǎn)生字對齊的跳轉(zhuǎn)地址,最低位被清除
BX R3
//Branch Exchange 返回到ARM狀態(tài)
CODE32 //ARM狀態(tài)下的子函數(shù)
Bach_to_ARM
…
在上面的程序中,CODE16/CODE32偽指令告訴匯編編譯器后面的指令序列分別為Thumb/ARM指令。
在非Interworking函數(shù)調(diào)用中,調(diào)用函數(shù)使用BL(Branch with Link)指令,即將返回地址保存在連接寄存器LR中,同時跳轉(zhuǎn)到被調(diào)用的子函數(shù)程序入口。從子函數(shù)返回時執(zhí)行指令 MOV PC, LR(當然也可能是其他形式的指令,如出棧指令)將LR值直接放入PC中,從而返回到調(diào)用函數(shù)中的下一條指令的地址,然后繼續(xù)執(zhí)行程序。
在Interworking函數(shù)的調(diào)用中,需要在編譯時對此函數(shù)所在的源程序指定編譯開關選項:-apcs / interwork ,即保證程序遵守ARM/Thumb程序混合使用的ATPCS規(guī)則。一般來說,這時生成的目標代碼會增加2%左右。這樣在編譯器(compiler)處理這個函數(shù)時就會用BX 指令取代MOV PC,LR指令,而且連接器(linker)會自動的產(chǎn)生一小段代碼(veneers)來改變處理器狀態(tài)(ARM/Thumb),具體過程如圖3所示。
圖三 編譯/連接命令為:
armcc -apcs/interwork arm_code.c –o arm_code.o
tcc -apcs/interwork thumb_code.c –o thumb_code.o
armlink arm_code.o thumb_code.o
對于C/C++程序來說,當編譯時如果增加 –apcs/interwork 選項,那就是告訴連接器自動增加一小段代碼(veneer)來實現(xiàn)函數(shù)調(diào)用時ARM/Thumb的狀態(tài)切換。但是對于使用C程序中的Interwork選項,需要注意的是:
對于一個C /C++源程序中不能同時包含ARM/Thumb指令;
如果C/C++程序間接的調(diào)用另一種指令系統(tǒng)下的子程序,編譯該程序時需要增加-apcs/interwork選項; 如果調(diào)用程序和被調(diào)用程序是不同的指令,而被調(diào)用程序是Non-Interworking代碼,這時不要使用函數(shù)指針來調(diào)用該被調(diào)用程序。 下面的圖四顯示了C/C++程序在增加編譯選項-apcs/interwork時將代碼分別編譯為ARM/THUMB指令時的情況。由于在Thumb狀態(tài)下不能直接使用POP LR,所以使用了暫時寄存器R3。 對于匯編程序來說,如果本代碼是被調(diào)用的函數(shù),則需按照以下步驟處理:
增加 –apcs/interwork 選項;
用BX來返回; EXPORT本函數(shù)名; 如果本代碼是調(diào)用函數(shù),那就只需要用BL指令來實現(xiàn)子函數(shù)的調(diào)用即可,也就是正常的處理。當然,用戶也可以自己來編寫這些狀態(tài)切換程序,這樣執(zhí)行代碼的效率會更高些。 對于C/C++程序和匯編程序的相互調(diào)用同樣需要遵守以上的規(guī)則。另外,在實際應用中,如果要在ARM/Thumb狀態(tài)間來切換程序,最好的辦法是所有的函數(shù)在編譯時都增加 –apcs/interwork選項。
圖四
其中Thumb狀態(tài)下因為不能直接使用POP 、LR指令,所以使用了暫時存儲器r3。
3.V5TE架構(gòu)中的擴展
前面所提到的內(nèi)容是針對ARM微處理器內(nèi)核為V4T架構(gòu)時的切換情況,而對于V5TE架構(gòu)的ARM內(nèi)核,除了完全支持V4T架構(gòu)的代碼(具有veneers)外,代碼在連接時不再增加veneers,而是使用新的指令BLX(Branch and Link with Exchang)來實現(xiàn)狀態(tài)切換。這條指令完成完成的任務是:在跳轉(zhuǎn)時將返回的指令地址保存在LR寄存器中,同時將PC中的最低位的值拷貝到CPSR寄存器中的T位,從而改變處理器狀態(tài)(Exchange)。一般來說,對于調(diào)用函數(shù)使用BLX指令即可,被調(diào)用函數(shù)則與V4T架構(gòu)相同,也是使用BX指令來返回。
-------------------------------------------
ARM/Thumb交互工作
源:http://blog.csdn.net/denlee/archive/2008/05/14/2444318.aspx 在使用T版本的ARM內(nèi)核的處理器時,經(jīng)常要使用ARM/Thum交互工作,總結(jié)了一些需要注意的問題:編寫匯編被調(diào)過程、編譯時應該注意的問題、ARM/Thumb間的相互調(diào)用。
一.編寫匯編被調(diào)過程
如果需要交互工作,則所編寫的函數(shù)應該遵循ATPCS標準。 1.葉函數(shù)(函數(shù)內(nèi)不包括函數(shù)的調(diào)用) 使用BX LR返回。 2.非葉函數(shù) (1)在入口處保護返回地址(lr)以及寄存器(r0-r7,r8-r12(ARM)) (2)返回前恢復保護的寄存器 (3)使用BX返回 二.編譯時應該注意的問題
1.編譯用于交互工作的ARM匯編代碼: armasm -32 -apcs /interwork 2.編譯用戶交互工作的Thumb匯編代碼: armasm -16 -apcs /interwork ***說明:
(1)關于匯編代碼,也可在程序中使用CODE32或CODE16命令明確告知匯編程序下面的代碼是ARM代碼還是Thumb代碼,這樣在匯編時則無需使用-32、-16選項 (2)當然也可在單個匯編原文件中混合使用ARM以及Thumb代碼,這是需要使用CODE32以及CODE16命令,并且需要注意狀態(tài)的切換,使用BX Rn,根據(jù)Rn的Bit[0]來確定目標是ARM代碼還是Thumb代碼 3.編譯用于交互工作的ARM C代碼: armcc -apcs /interwork
4.編譯用于交互工作的Thumb C代碼: tcc -apcs /interwork ***說明:基于ADS1.2
三.ARM/Thumb之間的相互調(diào)用
交互的調(diào)用遵循以下原則: 本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/jamestaosh/archive/2009/07/13/4345548.aspx |
|
來自: 奧古斯都1 > 《profession》