新聞中心

ARM Thumb Thumb-2指令集

作者: 時間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
32位RISC芯片ARM 體系結(jié)構(gòu)支持兩種指令集:32位的ARM指令集執(zhí)行效率高,對ARM體系架構(gòu)所有功能的完整支持;16位的Thumb指令集是ARM指令集的子集并以良好的代碼密度著稱。如果拋開預(yù)取指令時間不計,ARM指令相對Thumb指令將有更好的運(yùn)行性能(預(yù)取指令時需要根據(jù)指令地址偏移量來取指, ARM支持更大的地址偏移量而比較耗時)。最近ARM公司推出的的Thumb-2/Thumb2指令集據(jù)稱是上述兩種特性的綜合,是ARM指令集的性能和Thumb指令集的代碼密度的折中。號稱達(dá)到98%的ARM性能而又能降低代碼密度達(dá)30%。在目前的大多數(shù)ARM應(yīng)用中依然采用ARM + Thumb代碼的混雜模式。ARM code對應(yīng)的CPU(ARM處理器)工作狀態(tài)稱為ARM State,Thumb對應(yīng)的稱之為Thumb State,這兩種狀態(tài)的不同主要通過CPSR[bit 5]區(qū)別。CPSR(當(dāng)前程序狀態(tài)寄存器)保存了處理器的當(dāng)前工作狀態(tài),[bit 5]也被稱為T bit。對于所有帶有J標(biāo)志的處理器核,比如ARM926EJ-S和ARM1136J-S,J(Jazelle)代表ARM核中集成了Jazelle技 術(shù)。CPSR[bit24]則被成為J bit,如果這位為1,則代表當(dāng)前CPU工作在Java State下而CPU的取指和解碼都是直接操作Java操作數(shù)棧。當(dāng)然要生成Jazelle支持的字節(jié)碼需要特殊的Java編譯器和JVM,一般由第三方 平臺軟件廠商提供,比如日本的Aplix公司。在ARM處理器的運(yùn)行過程中,匯編指令BX以及BLX可以完成ARM State和Thumb State之間的切換(BXJ和BLXJ完成ARM/Thumb State和Java State之間的切換)。但如果程序有一部分工作在ARM工作狀態(tài)下,一部分工作在Thumb工作狀態(tài)下,而這兩段代碼卻有交互調(diào)用,則在編譯C/C++和匯編源文件時要 加上 -apcs /interwork選項。ARM公司的ADS(ARM Developer Suite,-apcs /interwork)和RealView的RVDS(RealView Developer Suite,--apcs /interwork) 都支持這樣的編譯選項,他們會在鏈接時自動檢測函數(shù)之間的調(diào)用關(guān)系和工作狀態(tài)提供粘合劑(Veneers)以便程序能夠在不同的工作狀態(tài)下切換。arm-linux-gcc編譯器個別版本不支持這個選項,所以在開發(fā)ARM + Linux平臺下使用的程序時應(yīng)該注意到這個問題。最后比較了arm-linux-gcc編譯器下ARM(armv7-a)、Thumb-1、Thumb-2指令集以及armv5te、Cortex-A9與Cortex-A8的tune選項效率性能和代碼密度。

本文引用地址:http://2s4d.com/article/201611/317419.htm

圖1. ARM體系結(jié)構(gòu)演進(jìn)圖

ARM指令集(A32)

ARM指令集為32位指令集,指令地址必須對齊在4字節(jié)邊界,可以實現(xiàn)ARM架構(gòu)下所有功能。大多數(shù)ARM數(shù)據(jù)處理指令采用的是3地址格式(除了64位乘法指令外),即兩個源操作數(shù)和一個結(jié)果操作數(shù)。

控制比特含義

代號

N(Negative)

當(dāng)為負(fù)數(shù)時,設(shè)為1

Z(Zero)

當(dāng)為0時設(shè)為1

C(Carry)

當(dāng)結(jié)果帶進(jìn)位時設(shè)為1

V(Overflow)

當(dāng)結(jié)果溢出時設(shè)為1

ARM指令分為以下幾種:

一、ARM 存儲器訪問指令
助記符 說明 操作 條件碼位置
LDR Rd,addressing 加載字?jǐn)?shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}
LDRB Rd,addressing 加載無符字節(jié)數(shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}B
LDRT Rd,addressing 以用戶模式加載字?jǐn)?shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}T
LDRBT Rd,addressing 以用戶模式加載無符號字?jǐn)?shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}BT
LDRH Rd,addressing 加載無符半字?jǐn)?shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}H
LDRSB Rd,addressing 加載有符字節(jié)數(shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}SB
LDRSH Rd,addressing 加載有符半字?jǐn)?shù)據(jù) Rd←[addressing],addressing 索引 LDR{cond}SH
STR Rd,addressing 存儲字?jǐn)?shù)據(jù) [addressing]←Rd,addressing 索引 STR{cond}
STRB Rd,addressing 存儲字節(jié)數(shù)據(jù) [addressing]←Rd,addressing 索引 STR{cond}B
STRT Rd,addressing 以用戶模式存儲字?jǐn)?shù)據(jù) [addressing]←Rd,addressing 索引 STR{cond}T
SRTBT Rd,addressing 以用戶模式存儲字節(jié)數(shù)據(jù) [addressing]←Rd,addressing 索引 STR{cond}BT
STRH Rd,addressing 存儲半字?jǐn)?shù)據(jù) [addressing]←Rd,addressing 索引 STR{cond}H
LDM{mode} Rn{!},reglist 批量(寄存器)加載 reglist←[Rn…],Rn 回存等 LDM{cond}{more}
STM{mode} Rn{!},rtglist 批量(寄存器)存儲 [Rn…]← reglist,Rn 回存等 STM{cond}{more}
SWP Rd,Rm,Rn 寄存器和存儲器字?jǐn)?shù)據(jù)交換 Rd←[Rd],[Rn]←[Rm](Rn≠Rd 或 Rm) SWP{cond}
SWPB Rd,Rm,Rn 寄存器和存儲器字節(jié)數(shù)據(jù)交換 Rd←[Rd],[Rn]←[Rm](Rn≠Rd 或 Rm) SWP{cond}B

二、ARM 數(shù)據(jù)處理指令
助記符號 說明 操作 條件碼位置
MOV Rd ,operand2 數(shù)據(jù)轉(zhuǎn)送 Rd←operand2 MOV {cond}{S}
MVN Rd ,operand2 數(shù)據(jù)非轉(zhuǎn)送 Rd←(operand2) MVN {cond}{S}
ADD Rd,Rn operand2 加法運(yùn)算指令 Rd←Rn+operand2 ADD {cond}{S}
SUB Rd,Rn operand2 減法運(yùn)算指令 Rd←Rn-operand2 SUB {cond}{S}
RSB Rd,Rn operand2 逆向減法指令 Rd←operand2-Rn RSB {cond}{S}
ADC Rd,Rn operand2 帶進(jìn)位加法 Rd←Rn+operand2+carry ADC {cond}{S}
SBC Rd,Rn operand2 帶進(jìn)位減法指令 Rd←Rn-operand2-(NOT)Carry SBC {cond}{S}
RSC Rd,Rn operand2 帶進(jìn)位逆向減法指令 Rd←operand2-Rn-(NOT)Carry RSC {cond}{S}
AND Rd,Rn operand2 邏輯與操作指令 Rd←Rn&operand2 AND {cond}{S}
ORR Rd,Rn operand2 邏輯或操作指令 Rd←Rn|operand2 ORR {cond}{S}
EOR Rd,Rn operand2 邏輯異或操作指令 Rd←Rn^operand2 EOR {cond}{S}
BIC Rd,Rn operand2 位清除指令 Rd←Rn&(~operand2) BIC {cond}{S}
CMP Rn,operand2 比較指令 標(biāo)志 N、Z、C、V←Rn-operand2 CMP {cond}
CMN Rn,operand2 負(fù)數(shù)比較指令 標(biāo)志 N、Z、C、V←Rn+operand2 CMN {cond}
TST Rn,operand2 位測試指令 標(biāo)志 N、Z、C、V←Rn&operand2 TST {cond}
TEQ Rn,operand2 相等測試指令 標(biāo)志 N、Z、C、V←Rn^operand2 TEQ {cond}

三、乘法指令
具有 32×32 乘法指令,32×32 乘加指令,32×32 結(jié)果為 64 位的乘/乘法指令.
助記符 說明 操作 條件碼位置
MUL Rd,Rm,Rs 32 位乘法指令 Rd←Rm*Rs (Rd≠Rm) MUL{cond}{S}
MLA Rd,Rm,Rs,Rn 32 位乘加指令 Rd←Rm*Rs+Rn (Rd≠Rm) MLA{cond}{S}
UMULL RdLo,RdHi,Rm,Rs 64 位無符號乘法指令 (RdLo,RdHi)←Rm*Rs UMULL{cond}{S}
UMLAL RdLo,RdHi,Rm,Rs 64 位無符號乘加指令 (RdLo,RdHi)←Rm*Rs+(RdLo,RdHi) UMLAL{cond}{S}
SMULL RdLo,RdHi,Rm,Rs 64 位有符號乘法指令 (RdLo,RdHi)←Rm*Rs SMULL{cond}{S}
SMLAL RdLo,RdHi,Rm,Rs 64 位有符號乘加指令 (RdLo,RdHi)←Rm*Rs+(RdLo,RdHi) SMLAL{cond}{S}

四、跳轉(zhuǎn)指令
在 ARM 中有兩種方式可以實現(xiàn)程序的跳轉(zhuǎn),一種是使用跳轉(zhuǎn)指令直接跳轉(zhuǎn),另一種則是直接向 PC 寄存器賦值實現(xiàn)跳轉(zhuǎn).

助記符 說明 操作 條件碼位置
B label 跳轉(zhuǎn)指令 Pc←label B{cond}
BL label 帶鏈接的跳轉(zhuǎn)指令 LR←PC-4, PC←label BL{cond}
BX Rm 帶狀態(tài)切換的跳轉(zhuǎn)指令 PC←label,切換處理狀態(tài) BX{cond}

五、ARM協(xié)處理器指令
ARM 支持協(xié)處理器操作,協(xié)處理器的控制要通過協(xié)處理器命令實現(xiàn).
助記符 說明 操作 條件碼位置
CDP
coproc,opcodel,CRd,CRn,CRm{,opcode2} 協(xié)處理器數(shù)據(jù)操作指令 取決于協(xié)處理器 CDP{cond}
LDC{L} coproc,CRd〈地址〉 協(xié)處理器數(shù)據(jù)讀取指令 取決于協(xié)處理器 LDC{cond}{L}
STC{L} coproc,CRd,〈地址〉 協(xié)處理器數(shù)據(jù)寫入指令 取決于協(xié)處理器 STC{cond}{L}
ARM 寄存器到協(xié)處理器
MCR coproc, opcodel,Rd,CRn,{,opcode2} 寄存器的數(shù)據(jù)傳送指令 取決于協(xié)處理器 MCR{cond}
協(xié)處理器寄存器到 ARM
MRC coproc, opcodel,Rd,CRn,{,opcode2} 寄存器到數(shù)據(jù)傳送指令 取決于協(xié)處理器MCR{cond}

五、ARM 雜項指令
助記符 說明 操作 條件碼位置
SWI immed_24 軟中斷指令 產(chǎn)生軟中斷,處理器進(jìn)入管理模式 SWI{cond}
MRS Rd,psr 讀狀態(tài)寄存器指令 Rd←psr,psr 為 CPSR 或 SPSR MRS{cond}
MSR psr_fields,Rd/#immed_8r 寫狀態(tài)寄存器指令 psr_fields←Rd/#immed_8r,psr 為 CPSR 或 SPSR MSR{cond}

所有異常都會使微處理器返回到ARM模式狀態(tài),并在ARM的編程模式中處理。由于ARM微處理器字傳送地址必須可被4整除(即字對準(zhǔn)),半字傳送地址必須可被2整除(即半字對準(zhǔn))。而Thumb指令是2個字節(jié)長,而不是4個字節(jié),所以,由Thumb執(zhí)行狀態(tài)進(jìn)入異常時其自然偏移與ARM不同。

Thumb指令集

對于ARM指令來說,所有的指令長度都是32位,并且執(zhí)行周期大多為單周期,指令都是有條件執(zhí)行的。每條Thumb指令有相同處理器模型所對應(yīng)的32位ARM指令。而THUMB 指令的特點(diǎn)如下:

  • 不會經(jīng)常條件執(zhí)行使用指令:除了跳轉(zhuǎn)指令 B 有條件執(zhí)行功能外,其它指令均為無條件執(zhí)行
  • 源寄存器與目標(biāo)寄存器經(jīng)常是相同的以減少操作數(shù)
  • 可用寄存器數(shù)量少
  • 常數(shù)的值比較小
  • 不經(jīng)常用內(nèi)核中的桶式移位器(barrel shifter)

Thumb指令集是對32位ARM指令集的擴(kuò)充,它的目標(biāo)是為了實現(xiàn)更高的代碼密度。Thumb指令集實現(xiàn)的功能只是32位ARM指令集的子集,它僅僅把常用的ARM指令壓縮成16位的指令編碼方式。在指令的執(zhí)行階段,16位的指令被重新解碼,完成對等的32位指令所實現(xiàn)的功能。與全部用ARM指令集的方式相比,使用Thumb指令可以在代碼密度方面改善大約30%。但是,這種改進(jìn)是以代碼的效率為代價的。盡管每個Thumb指令都有相對應(yīng)的ARM指令,但是,相同的功能需要更多的Thumb指令才能完成。因此,當(dāng)指令預(yù)取需要的時間沒有區(qū)別時,ARM指令相對Thumb指令具有更好的性能。與ARM指令集相比較,Thumb指令集中的數(shù)據(jù)處理指令的操作數(shù)仍然是32位,指令地址也為32位,但Thumb指令集為實現(xiàn)16位的指令長度,舍棄了ARM指令集的一些特性,若使用32位的存儲器,ARM代碼比Thumb代碼快約40%,若使用16位的存儲器,Thumb代碼比ARM代碼快約40%~50%.顯然,ARM指令集和Thumb指令集各有其優(yōu)點(diǎn),若對系統(tǒng)的性能有較高要求,應(yīng)使用32位的存儲系統(tǒng)和ARM指令集,若對系統(tǒng)的成本及功耗有較高要求,則應(yīng)使用16位的存儲系統(tǒng)和Thumb指令集。當(dāng)然,若兩者結(jié)合使用,充分發(fā)揮其各自的優(yōu)點(diǎn),會取得更好的效果。

在編寫Thumb指令時,先要使用偽指令CODE16聲明,編寫ARM指令時,則可使用CODE32偽指令聲明。Thumb 指令集沒有協(xié)處理器指令,信號量指令以及訪問 CPSR 或 SPSR 的指令,沒有乘加指令及 64 位乘法指令等,且指令的第二操作數(shù)受到限制;大多數(shù) Thumb 數(shù)據(jù)處理指令采用2地址格式.Thumb指令集與 ARM 指令的區(qū)別一般有如下幾點(diǎn):
跳轉(zhuǎn)指令
程序相對轉(zhuǎn)移,特別是條件跳轉(zhuǎn)與 ARM 代碼下的跳轉(zhuǎn)相比,在范圍上有更多的限制,轉(zhuǎn)向子程序是無條件的轉(zhuǎn)移.
數(shù)據(jù)處理指令
數(shù)據(jù)處理指令是對通用寄存器進(jìn)行操作,在大多數(shù)情況下,操作的結(jié)果須放入其中一個操作數(shù)寄存器中,而不是第 3 個寄存器中.數(shù)據(jù)處理操作比 ARM 狀態(tài)的更少,訪問寄存器 R8~R15 受到一定限制.除 MOV 和 ADD 指令訪問器 R8~R15 外,其它數(shù)據(jù)處理指令總是更新 CPSR 中的 ALU 狀態(tài)標(biāo)志.訪問寄存器 R8~R15 的 Thumb 數(shù)據(jù)處理指令不能更新 CPSR 中的 ALU 狀態(tài)標(biāo)志.
單寄存器加載和存儲指令
在 Thumb 狀態(tài)下,單寄存器加載和存儲指令只能訪問寄存器 R0~R7
批量寄存器加載和存儲指令
LDM 和 STM 指令可以將任何范圍為 R0~R7 的寄存器子集加載或存儲. PUSH 和 POP 指令使用堆棧指令 R13 作為基址實現(xiàn)滿遞減堆棧.除 R0~R7 外,PUSH 指令還可以存儲鏈接寄存器 R14,并且 POP 指令可以加載程序指令PC

Thumb-2指令集(T32)

THUMB-2指令集是介紹ARM CPU中的THUMB的擴(kuò)展,新指令對性能和代碼密度的改進(jìn),從而提供低功耗,高性能的最優(yōu)設(shè)計,更好的平衡代碼性能和系統(tǒng)成本,Thumb-2是混合的16-bit和32-bit指令格式,其16位指令在運(yùn)行時被轉(zhuǎn)換為32-bit指令執(zhí)行。Thumb-2指令集在Thumb指令的基礎(chǔ)上做了如下的擴(kuò)充:增加了一些新的16位Thumb指令來改進(jìn)程序的執(zhí)行流程,增加了一些新的32位Thumb指令以實現(xiàn)一些ARM指令的專有功能32位的ARM 指令也得到了擴(kuò)充,增加了一些新的指令來改善代碼性能和數(shù)據(jù)處理的效率給Thumb指令集增加32位指令就解決了之前Thumb指令集不能訪問協(xié)處理器、特權(quán)指令和特殊功能指令的局限。新的Thumb指令集現(xiàn)在可以實現(xiàn)所有的功能,這樣就不需要在ARM/Thumb狀態(tài)之間反復(fù)切換了,代碼密度和性能得到顯著的提高。Thumb-2的出現(xiàn)使開發(fā)者只使用一套指令集就享有高性能、高代碼密度,不再需要在不同指令之間反復(fù)切換了。開發(fā)者只需要關(guān)注對整體性能影響最大的那部分代碼,其他的部分可以使用缺省的編譯配置就可以了。

新的Thumb-2技術(shù)可以帶來很多好處:
  可以實現(xiàn)ARM指令的所有功能
  增加了12條新指令,可以改進(jìn)代碼性能和代碼密度之間的平衡
  代碼性能達(dá)到了純ARM代碼性能的98%
  相對ARM代碼,Thumb-2代碼的大小僅有其74%
  代碼密度比現(xiàn)有的Thumb指令集更高:代碼大小平均降低5%;代碼速度平均提高2-3%

為了提高處理壓縮數(shù)據(jù)結(jié)構(gòu)的效率,新的ARM架構(gòu)為Thumb-2指令集和ARM指令集增加了一些新的指令來實現(xiàn)比特位的插入和抽取。為了增加處理常數(shù)的靈活性,新架構(gòu)中為Thumb-2指令集和ARM指令集增加了兩條新的指令。MOVW可以把一個16-bit常數(shù)加載到寄存器中,并用0填充高比特位;另一條指令MOVT可以把一個16-bit常數(shù)加載到寄存器高16比特中。這兩條指令組合使用就可以把一個32-bit常數(shù)加載到寄存器中。通常在訪問外設(shè)寄存器之前會把外設(shè)的基址加載到寄存器中,這時就會需要把32-bit常數(shù)加載到寄存器中。在之前的架構(gòu)中需要通過literal pools來完成這樣的操作,對32位常量的訪問一般通過PC相對尋址來實現(xiàn)。Literal pools可以保存常量并簡化訪問這些常量的代碼,但是,在Harvard架構(gòu)的處理器中會引起額外的開銷。這些開銷來自于需要額外的時鐘周期來使數(shù)據(jù)端 口能夠?qū)χ噶盍鬟M(jìn)行訪問;這種訪問可能是需要把指令流加載的數(shù)據(jù)緩存中,或者從數(shù)據(jù)端口直接訪問指令存儲器。將32位常量分成16比特的兩個部分保存在兩條指令中,意味著數(shù)據(jù)直接在指令流中,不再需要通過數(shù)據(jù)端口來訪問了。相對于literal pool方式,這種解決辦法可以消除通過數(shù)據(jù)端口訪問指令流的額外開銷,進(jìn)而提高性能,降低功耗。

ARM/Thumb狀態(tài)切換

在基于ARM 處理器的嵌入式開發(fā)中,為了增強(qiáng)系統(tǒng)的靈活性以及提高系統(tǒng)的整體性能經(jīng)常需要使用16 位的Thumb 指令,所以需要在ARM 和Thumb 狀態(tài)之間來切換(Interworking)微處理器狀態(tài)。只要遵循ATPCS調(diào)用規(guī)則,Thumb子程序和ARM子程序就可以互相調(diào)用。首先介紹切換(Interwoking)的基本概念及切換時的子函數(shù)調(diào)用。

ARM處理器總是從ARM狀態(tài)開始執(zhí)行。因而,如果要在調(diào)試器中運(yùn)行Thumb程序,必須為該Thumb程序添加一個ARM程序頭,然后再切換到Thumb狀態(tài),調(diào)用該Thumb程序。

  • Thumb狀態(tài) BX Rn
  • ARM狀態(tài) BX Rn

其中Rn可以是寄存器R0—R15中的任意一個。指令可以通過將寄存器Rn的內(nèi)容拷貝到程序計數(shù)器PC來完成在4Gbyte地址空間中的絕對跳轉(zhuǎn),而狀態(tài)切換是由寄存器Rn的最低位來指定的,如果操作數(shù)寄存器的狀態(tài)位Bit0=0,則進(jìn)入ARM狀態(tài),如果Bit0=1,則進(jìn)入Thumb狀態(tài)。在非Interworking函數(shù)調(diào)用中,調(diào)用函數(shù)使用BL(Branch with Link)指令,即將返回地址保存在連接寄存器LR中,同時跳轉(zhuǎn)到被調(diào)用的子函數(shù)程序入口。從子函數(shù)返回時執(zhí)行指令 MOV PC, LR(當(dāng)然也可能是其他形式的指令,如出棧指令)將LR值直接放入PC中,從而返回到調(diào)用函數(shù)中的下一條指令的地址,然后繼續(xù)執(zhí)行程序。在Interworking函數(shù)的調(diào)用中,需要在編譯時對此函數(shù)所在的源程序指定編譯開關(guān)選項:-apcs / interwork ,即保證程序遵守ARM/Thumb程序混合使用的ATPCS規(guī)則。一般來說,這時生成的目標(biāo)代碼會增加2%左右。這樣在編譯器(compiler)處理這個函數(shù)時就會用BX 指令取代MOV PC,LR指令,而且連接器(linker)會自動的產(chǎn)生一小段代碼(veneers)來改變處理器狀態(tài)(ARM/Thumb),對于C/C++程序來說,當(dāng)編譯時如果增加 –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選項;
    • 編譯用于交互工作的ARM C代碼: armcc -apcs/interwork
    • 編譯用于交互工作的Thumb C代碼:tcc -apcs/interwork
  • 如果調(diào)用程序和被調(diào)用程序是不同的指令,而被調(diào)用程序是Non-Interworking代碼,這時不要使用函數(shù)指針來調(diào)用該被調(diào)用程序。

對于匯編程序來說,如果本代碼是被調(diào)用的函數(shù),則需按照以下步驟處理:

  • 編譯時增加-apcs/interwork 選項;ARM匯編armasm -32 -apcs /interwork;Thumb匯編代碼:armasm -16 -apcs /interwork;
  • 在入口處保護(hù)返回地址(lr)以及寄存器(r0-r7,r8-r12(ARM))
  • 返回前恢復(fù)保護(hù)的寄存器
  • 用BX來返回;
  • EXPORT本函數(shù)名;

如果本代碼是調(diào)用函數(shù),那就只需要用BL指令來實現(xiàn)子函數(shù)的調(diào)用即可,也就是正常的處理。當(dāng)然,用戶也可以自己來編寫這些狀態(tài)切換程序,這樣執(zhí)行代碼的效率會更高些。對于C/C++程序和匯編程序的相互調(diào)用同樣需要遵守以上的規(guī)則。另外,在實際應(yīng)用中,如果要在ARM/Thumb狀態(tài)間來切換程序,最好的辦法是所有的函數(shù)在編譯時都增加 -apcs/interwork選項。關(guān)于匯編代碼,也可在程序中使用CODE32或CODE16命令明確告知匯編程序下面的代碼是ARM代碼還是Thumb代碼,這樣在匯編時則無需使用-32、-16選項;當(dāng)然也可在單個匯編原文件中混合使用ARM以及Thumb代碼,這是需要使用CODE32以及CODE16命令,并且需要注意狀態(tài)的切換,使用BX Rn,根據(jù)Rn的Bit[0]來確定目標(biāo)是ARM代碼還是Thumb代碼。如AREA Init,CODE,READONLY CODE32;通知編譯器其后的指令為32位的ARM指令。

前面所提到的內(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)切換。這條指令完成完成的任務(wù)是:在跳轉(zhuǎn)時將返回的指令地址保存在LR寄存器中,同時將PC中的最低位的值拷貝到CPSR寄存器中的T位,從而改變處理器狀態(tài)(Exchange)。一般來說,對于調(diào)用函數(shù)使用BLX指令即可,被調(diào)用函數(shù)則與V4T架構(gòu)相同,也是使用BX指令來返回。
ARM/Thumb代碼性能比較

前面提到Thumb代碼所需的存儲空間約為ARM代碼的60%~70%;Thumb代碼使用的指令數(shù)比ARM代碼少約30%~40%;若使用32位的存儲器,ARM代碼比Thumb代碼速約40%;若使用16位的存儲器,Thumb代碼比ARM代碼速約40%~50%;與ARM代碼相比,使用Thumb代碼,存儲器的過耗會下降約30%。下面是arm-linux-gcc編譯器采用不同的編譯選擇對armv7-a,、thumb-2 和thumb-1指令集編譯CoreMark的測試結(jié)果,結(jié)果如下:

  • 最好的編譯選項:-O3 -funroll-loops -marm -march=armv5te -mtune=cortex-a8
  • armv7-a指令集最好的編譯選項:-O3 -funroll-loops -marm -march=armv7-a -mtune=cortex-a8 95.2%
  • Thumb-2指令集最好的編譯選項:-O3 -funroll-loops -mthumb -march=armv7-a -mtune=cortex-a888.7%
  • Thumb-1指令集最好的編譯選項:-O2 -mthumb -march=armv5te -mtune=cortex-a8 66.4%
  • Cortex-A9是Cortex-A8的tune的99.5%
  • 默認(rèn)選項-O2 -mthumb -march=armv7-a 性能比為80.8%

Top of Form

Score

Optimisation

Unroll?

ISA

Arch

Tune

% of best

5634.6

-O3

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a8

100.0%

5607.7

-O3

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a9

99.5%

5601.5

-O2

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a9

99.4%

5580.0

-O3

-marm

-march=armv5te

-mtune=cortex-a8

99.0%

5548.6

-O3

-marm

-march=armv5te

-mtune=cortex-a9

98.5%

5505.1

-O2

-marm

-march=armv5te

-mtune=cortex-a8

97.7%

5427.4

-O2

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a8

96.3%

5386.5

-O3

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a9

95.6%

5364.4

-O3

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a8

95.2%

5332.3

-O2

-marm

-march=armv5te

-mtune=cortex-a9

94.6%

5330.8

-O3

-marm

-march=armv7-a

-mtune=cortex-a8

94.6%

5283.7

-O3

-marm

-march=armv7-a

-mtune=cortex-a9

93.8%

5253.5

-O2

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a9

93.2%

5066.5

-O2

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a8

89.9%

4996.6

-O3

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a8

88.7%

4995.6

-O3

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a9

88.7%

4947.2

-O3

-mthumb

-march=armv7-a

-mtune=cortex-a8

87.8%

4858.3

-O2

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a9

86.2%

4774.8

-O2

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a8

84.7%

4763.8

-O2

-marm

-march=armv7-a

-mtune=cortex-a9

84.5%

4737.8

-Os

-marm

-march=armv5te

-mtune=cortex-a8

84.1%

4731.1

-O2

-marm

-march=armv7-a

-mtune=cortex-a8

84.0%

4688.6

-O3

-mthumb

-march=armv7-a

-mtune=cortex-a9

83.2%

4665.6

-Os

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a8

82.8%

4630.7

-Os

-marm

-march=armv5te

-mtune=cortex-a9

82.2%

4595.6

-Os

-funroll-loops

-marm

-march=armv5te

-mtune=cortex-a9

81.6%

4562.7

-Os

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a8

81.0%

4551.7

-O2

-mthumb

-march=armv7-a

-mtune=cortex-a8

80.8%

4521.5

-Os

-funroll-loops

-marm

-march=armv7-a

-mtune=cortex-a9

80.2%

4519.8

-Os

-marm

-march=armv7-a

-mtune=cortex-a8

80.2%

4500.8

-Os

-marm

-march=armv7-a

-mtune=cortex-a9

79.9%

4237.6

-O2

-mthumb

-march=armv7-a

-mtune=cortex-a9

75.2%

3739.7

-O2

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a8

66.4%

3730.6

-O2

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a9

66.2%

3658.8

-Os

-mthumb

-march=armv7-a

-mtune=cortex-a8

64.9%

3657.0

-Os

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a8

64.9%

3629.3

-O2

-mthumb

-march=armv5te

-mtune=cortex-a8

64.4%

3585.1

-Os

-mthumb

-march=armv7-a

-mtune=cortex-a9

63.6%

3580.8

-Os

-funroll-loops

-mthumb

-march=armv7-a

-mtune=cortex-a9

63.6%

3522.2

-O3

-mthumb

-march=armv5te

-mtune=cortex-a8

62.5%

3473.0

-O2

-mthumb

-march=armv5te

-mtune=cortex-a9

61.6%

3338.9

-O3

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a8

59.3%

3219.1

-O3

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a9

57.1%

3170.6

-O3

-mthumb

-march=armv5te

-mtune=cortex-a9

56.3%

2753.7

-Os

-mthumb

-march=armv5te

-mtune=cortex-a8

48.9%

2748.6

-Os

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a8

48.8%

2747.4

-Os

-mthumb

-march=armv5te

-mtune=cortex-a9

48.8%

2743.7

-Os

-funroll-loops

-mthumb

-march=armv5te

-mtune=cortex-a9

48.7%

Bottom of Form

http://lion3875.blog.51cto.com/2911026/532719

http://www.cnx-software.com/2011/04/22/compile-with-arm-thumb2-reduce-memory-footprint-and-improve-performance/#ixzz1qTCwHRc4

https://wiki.linaro.org/MichaelHope/Sandbox/CoreMark1

http://blog.csdn.net/itismine/archive/2009/11/01/4753701.aspx

http://hi.baidu.com/yzx408/blog/item/a050741180944c1cb8127b79.html

http://houh-1984.blog.163.com/

32位RISC芯片ARM 體系結(jié)構(gòu)支持兩種指令集:32位的ARM指令集執(zhí)行效率高,對ARM體系架構(gòu)所有功能的完整支持;16位的Thumb指令集是ARM指令集的子集并以良好的代碼密度著稱。如果拋開預(yù)取指令時間不計,ARM指令相對Thumb指令將有更好的運(yùn)行性能(預(yù)取指令時需要根據(jù)指令地址偏移量來取指, ARM支持更大的地址偏移量而比較耗時)。最近ARM公司推出的的Thumb-2/Thumb2指令集據(jù)稱是上述兩種特性的綜合,是ARM指令集的性能和Thumb指令集的代碼密度的折中。號稱達(dá)到98%的ARM性能而又能降低代碼密度達(dá)30%。在目前的大多數(shù)ARM應(yīng)用中依然采用ARM + Thumb代碼的混雜模式。ARM code對應(yīng)的CPU(ARM處理器)工作狀態(tài)稱為ARM State,Thumb對應(yīng)的稱之為Thumb State,這兩種狀態(tài)的不同主要通過CPSR[bit 5]區(qū)別。CPSR(當(dāng)前程序狀態(tài)寄存器)保存了處理器的當(dāng)前工作狀態(tài),[bit 5]也被稱為T bit。對于所有帶有J標(biāo)志的處理器核,比如ARM926EJ-S和ARM1136J-S,J(Jazelle)代表ARM核中集成了Jazelle技 術(shù)。CPSR[bit24]則被成為J bit,如果這位為1,則代表當(dāng)前CPU工作在Java State下而CPU的取指和解碼都是直接操作Java操作數(shù)棧。當(dāng)然要生成Jazelle支持的字節(jié)碼需要特殊的Java編譯器和JVM,一般由第三方 平臺軟件廠商提供,比如日本的Aplix公司。在ARM處理器的運(yùn)行過程中,匯編指令BX以及BLX可以完成ARM State和Thumb State之間的切換(BXJ和BLXJ完成ARM/Thumb State和Java State之間的切換)。但如果程序有一部分工作在ARM工作狀態(tài)下,一部分工作在Thumb工作狀態(tài)下,而這兩段代碼卻有交互調(diào)用,則在編譯C/C++和匯編源文件時要 加上 -apcs /interwork選項。ARM公司的ADS(ARM Developer Suite,-apcs /interwork)和RealView的RVDS(RealView Developer Suite,--apcs /interwork) 都支持這樣的編譯選項,他們會在鏈接時自動檢測函數(shù)之間的調(diào)用關(guān)系和工作狀態(tài)提供粘合劑(Veneers)以便程序能夠在不同的工作狀態(tài)下切換。arm-linux-gcc編譯器個別版本不支持這個選項,所以在開發(fā)ARM + Linux平臺下使用的程序時應(yīng)該注意到這個問題。最后比較了arm-linux-gcc編譯器下ARM(armv7-a)、Thumb-1、Thumb-2指令集以及armv5te、Cortex-A9與Cortex-A8的tune選項效率性能和代碼密度。



關(guān)鍵詞: ARMThumbThumb-2指令

評論


技術(shù)專區(qū)

關(guān)閉