版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、ARM編程技巧,Agenda,ARM 編譯器優(yōu)化 C/C+和匯編混合模式編程 使用ARM編譯器編碼 局部和全局?jǐn)?shù)據(jù)討論,優(yōu)化級(jí)別,使用的編譯器優(yōu)化級(jí)別是可選擇的 -O0-DEBUG 關(guān)閉大多數(shù)優(yōu)化. 最好的調(diào)試信息,最少的優(yōu)化 -O1-DEBUGREL 多數(shù)優(yōu)化選項(xiàng)許可 給一個(gè)滿意的調(diào)試,好的代碼密度 -O2-RELEASE (default) 完全的優(yōu)化 有限的調(diào)試信息,最好的代碼密度 為代碼大小或運(yùn)行速度的優(yōu)化,可選擇: -Ospace (默認(rèn)的)或 -Otime. 使用-g 選像可包含源碼級(jí)調(diào)試信息,ADS 編譯器在所有級(jí)別中執(zhí)行一些簡(jiǎn)單的優(yōu)化 i.e. -O0, -O1, -O2 下面
2、是一個(gè)例子:即使用-O0,多余的表達(dá)式也被清除了: ATPCS標(biāo)準(zhǔn)中子程序結(jié)果返回規(guī)則 結(jié)果為32位整數(shù),R0返回 結(jié)果為64位整數(shù),R0,R1返回 位數(shù)更多時(shí),用內(nèi)存來(lái)傳遞 ,自動(dòng)優(yōu)化,int f(int *p) return (*p = = *p); ,armcc -c -O0,f MOV r1, r0 MOV r0, #1 MOV pc, lr,注意:在這種情況下,可使用C的關(guān)鍵字volatile 強(qiáng)制使用這些變量,使用 “volatile”,int f(volatile int *p) return (*p = = *p); ,armcc -c,f LDR r1,r0 LDR r0,r
3、0 CMP r1,r0 MOVNE r0,#0 MOVEQ r0,#1 MOV pc,lr,int f(int *p) return (*p = = *p); ,f MOV r0,#1 MOV pc,lr,armcc -c,這個(gè)代碼用的編譯級(jí)別是:-o2,下面是一個(gè)冗余代碼清除的例子,他只用了-o1的優(yōu)化選項(xiàng):,冗余代碼的清除,int dummy() int a=10, b=20; int c; c=a+b; return 0; ,armcc -c -O1,dummy MOV r0, #0 MOV pc, lr,指令編排,指令編排在高級(jí)優(yōu)化選項(xiàng)中是有效的(-O1, -O2). 指令的重新編排是
4、為了使要運(yùn)行的代碼更適合對(duì)應(yīng)的核 為arm9和以后的處理器提高吞吐量(一般可達(dá)到4%),并防止互鎖(interlock) 選擇處理器可決定使用的運(yùn)算法則,在默認(rèn)情況下,使用針對(duì)ARM9的優(yōu)化方案 (對(duì)ARM7的運(yùn)行沒(méi)有影響) 例如: int f(int *p, int x) return *p + x * 3; 沒(méi)用指令編排 (-O0)使用指令編排 (-O1,-O2) ADD r1,r1,r1,LSL #1LDR r0,r0,#0LDR r0,r0,#0ADD r1,r1,r1,LSL #1ADD r0,r0,r1; interlock on ARM9ADD r0,r0,r1MOV pc,lr
5、MOV pc,lr,armcc cpu arm7tdmi,armcc cpu arm9tdmi,Tail-call Optimization,嵌套優(yōu)化可避免在函數(shù)級(jí)里的不必要的返回 在可能的情況下BL 譯碼成B 在高級(jí)優(yōu)化里有效(-O1, -O2).,int main()int x = f();:,int f()int y = g();return y;,int g()return 10;,嵌套優(yōu)化,內(nèi)嵌函數(shù)(inline),內(nèi)嵌可通過(guò)刪除子函數(shù)調(diào)用的開(kāi)銷(xiāo)來(lái)提高性能 這個(gè) inline 關(guān)鍵字顯示哪個(gè)函數(shù)將被內(nèi)嵌 在高級(jí)優(yōu)化選項(xiàng)中,ADS 1.2 編譯器默認(rèn)自動(dòng)內(nèi)嵌 -Oautoinline
6、(default -O2) -Ono_autoline (default for -O0,-O1) 哪個(gè)函數(shù)是否被內(nèi)嵌取決于: 他們是否被 _inline標(biāo)示 優(yōu)化的級(jí)別 -Otime / -Ospace 函數(shù)被調(diào)用的次數(shù) 如果函數(shù)在別的模塊中不被調(diào)用,一個(gè)好的建議是用static標(biāo)識(shí)函數(shù),否則,編譯器將在內(nèi)嵌譯碼里把該函數(shù)編譯乘非內(nèi)嵌的 加代碼的長(zhǎng)度 使調(diào)試信息更復(fù)雜,Example.,Inline example,內(nèi)嵌例子,Agenda,ARM編譯器的優(yōu)化 C/C+和匯編混合模式編程 使用ARM編譯器編碼 局部和全局?jǐn)?shù)據(jù)討論,C和匯編的混合編程,C/C+ 和匯編能很容易的混合: 可實(shí)現(xiàn)在c
7、中無(wú)法實(shí)現(xiàn)的處理器功能 使用新的或不支持的指令 產(chǎn)生更高效的代碼 直接鏈接變量和程序 確定符合程序調(diào)用規(guī)范 輸入/輸出相關(guān)的符號(hào) 編譯器也可包含內(nèi)嵌匯編 大多數(shù)arm指令集都可實(shí)現(xiàn) 寄存器操作數(shù)可支持任意的c/c+的表達(dá)式 內(nèi)嵌匯編代碼可由編譯器的優(yōu)化器來(lái)傳遞,ATPCS(arm/thumb程序調(diào)用規(guī)范),r8,r9/sb,r10/sl,r11,r12,r13/sp,r14/lr,r15/pc,r0,r1,r2,r3,r4,r5,r6,r7,寄存器變量 必須保護(hù),作為函數(shù)傳遞的參數(shù)值,Scratch register (corruptible),Stack PointerLink Regist
8、er Program Counter,編譯器使用一套規(guī)則的來(lái)設(shè)置寄存器的用法 ARM-Thumb Procedure Call Standard or ATPCS (or APCS) CPSR 標(biāo)志位可被函數(shù)調(diào)用所破壞 任何和編譯過(guò)的代碼交互工作的匯編碼在接口層必 須滿足ATPCS的規(guī)范,Register,- 如果 RWPI選項(xiàng)有效,作為棧的基地址,- 如果軟件堆棧檢查有效,作為棧的限制值,- 可作為臨時(shí)的一個(gè)值棧一樣來(lái)使用,- 子程序內(nèi)部調(diào)用的可改寫(xiě)的寄存器,- 程序計(jì)數(shù)器,在C程序中調(diào)用匯編,在匯編程序中用export name來(lái)定義 在C程序中直接調(diào)用,用EXTERN聲明 正常鏈接,ex
9、tern void mystrcopy(char *d, const char *s); int main(void) const char *src = “Source”; char dest10; . mystrcopy(dest, src); . ,AREA StringCopy, CODE, READONLY EXPORT mystrcopy mystrcopy LDRB r2, r1, #1 STRB r2, r0, #1 CMP r2, #0 BNE mystrcopy MOV pc, lr END,這里所有的參數(shù)都是可以用寄存器來(lái)傳遞的,所以不需要在匯編程序中使用PUSH/POP
10、來(lái)保護(hù),CALL,內(nèi)嵌匯編,允許使用一些不能由編譯器自動(dòng)生成的指令: MSR / MRS 新的指令 協(xié)處理器指令 通常在關(guān)聯(lián)的內(nèi)嵌函數(shù)中使用 使用C變量代替寄存器 不是一個(gè)真正的匯編文件 通過(guò)優(yōu)化器實(shí)現(xiàn) ADS FAQ 入口 “Using the Inline Assembler”,#define Q_Flag 0 x08000000 / Bit 27 _inline void Clear_Q_flag (void) int temp; _asm MRS temp, CPSR BIC temp, temp, #Q_Flag MSR CPSR_f, temp _inline int mult16
11、(short a, short b, int c) int temp; _asm SMLABB temp,a,b,c return temp; ,Agenda,ARM編譯器的優(yōu)化 C/C+和匯編混合模式編程 使用ARM編譯器編碼 局部和全局?jǐn)?shù)據(jù)討論,參數(shù)傳遞,開(kāi)始四個(gè)字大小的參數(shù)直接使用寄存器的R0-R3來(lái)傳遞(快速且高效的) 更多的信息可參看ATPCS 如果需要更多的參數(shù),將使用堆棧。(需要額外的指令和慢速的存儲(chǔ)器操作) 所以通常限制參數(shù)的個(gè)數(shù),使它為4或更少。 如果不可避免,把常用的參數(shù)前4個(gè)放在R0-R3中,Example.,Parameter Passing (4 parameters
12、) int func1(int a, int b, int c, int d) return a+b+c+d; int caller1(void) return func1(1,2,3,4); ,func1 0 x000000 : ADD r0,r0,r1 0 x000004 : ADD r0,r0,r2 0 x000008 : ADD r0,r0,r3 0 x00000c : MOV pc,lr caller1 0 x000014 : MOV r3,#4 0 x000018 : MOV r2,#3 0 x00001c : MOV r1,#2 0 x000020 : MOV r0,#1 0 x
13、000024 : B func1,Parameter Passing (4 parameters),Parameter Passing (6 parameters),Parameter Passing (6 parameters),func2 0 x000000 : STR lr, sp,#-4! 0 x000004 : ADD r0,r0,r1 0 x000008 : ADD r0,r0,r2 0 x00000C : ADD r0,r0,r3 0 x000010 : LDMIB sp,r12,r14 0 x000014 : ADD r0,r0,r12 0 x000018 : ADD r0,r
14、0,r14 0 x00001C : LDR pc,sp,#4 caller2 0 x000020 : STMFD sp!,r2,r3,lr 0 x000024 : MOV r3,#6 0 x000028 : MOV r2,#5 0 x00002C : STMIA sp,r2,r3 0 x000030 : MOV r3,#4 0 x000034 : MOV r2,#3 0 x000038 : MOV r1,#2 0 x00003C : MOV r0,#1 0 x000040 : BL func2 0 x000044 : LDMFD sp!,r2,r3,pc,int func2(int a,int
15、 b,intc, int,d,int e,int f) return a+b+c+d+e+f; int caller2(void) return func1(1,2,3,4,5,6); ,This code is compiled with “-O2 -Ono_autoinline”,循環(huán)終止,在for(), while() dowhile()的循環(huán)中,用減到0代替加到某個(gè)值。 比如,用下面的代替 : for (loop = 1; loop = total; loop+) /(ADD,CMP) 代替為: for (loop = total; loop != 0; loop-) /(SUBS)
16、盡量減少循環(huán)的次數(shù) 代碼小,且使用更少的寄存器,Example.,Loop Termination,Count up int fact1(int limit) int i; int fact = 1; for (i = 1; i = limit; i+) fact = fact * i; return fact; ,Count down int fact2(int limit) int i; int fact = 1; for (i = limit; i != 0; i-) fact = fact * i; return fact; ,fact2 0 x000000 : MOVS r1,r0
17、0 x000004 : MOV r0,#1 0 x000008 : MOVEQ pc,lr 0 x00000c : MUL r0,r1,r0 0 x000010 : SUBS r1,r1,#1 0 x000014 : BNE 0 x0c 0 x000018 : MOV pc,lr,fact1 0 x000000 : MOV r2,#1 0 x000004 : MOV r1,#1 0 x000008 : CMP r0,#1 0 x00000c : BLT 0 x20 0 x000010 : MUL r2,r1,r2 0 x000014 : ADD r1,r1,#1 0 x000018 : CMP
18、 r1,r0 0 x00001c : BLE 0 x10 0 x000020 : MOV r0,r2 0 x000024 : MOV pc,lr,This code is compiled with “-O2 -Otime”,除法操作(1),ARM核不含除法硬件 除法通常用一個(gè)運(yùn)行庫(kù)函數(shù)來(lái)實(shí)現(xiàn) 運(yùn)行需要很多的周期,unsigned div(unsigned a, unsigned b) return (b / a); ,div B _rt_udiv,unsigned div2(unsigned b) return (b / 2); ,div2 MOV r0,r0,LSR #1 MOV pc,l
19、r,一些除法操作在編譯時(shí)作為特例來(lái)處理 除2操作,被左移代替,除法操作 (2),在 -O1和-O2 (使用 -Otime), 其他的常量將使用一個(gè)標(biāo)準(zhǔn)的乘法序列來(lái)完成 例如: 實(shí)時(shí)除法程序 使用CLZ指令 只有V5te體系結(jié)構(gòu)才有效。 用下面的辦法來(lái)選擇 C - #pragma import _use_realtime_division Assembler - IMPORT _use_realtime_division,div10 MOV r1,r0 LDR r0,=0 xCCCCCCCD UMULL r2,r1,r0,r1 MOV r0,r1,LSR #3 MOV pc,lr,unsigne
20、d div10(unsigned c) return (c / 10); ,余數(shù) 模算法,余數(shù)的操作符 %, 通常使用模算法 如果這個(gè)值的模不是2的n次冪,它將花費(fèi)大量的時(shí)間和代碼空間 避免這種情況發(fā)生的辦法使用if()作狀態(tài)檢查 比如說(shuō):count的范圍是0到59 count = (count+1) % 60; 用下面的句子代替 if (+count = 60) count = 0;,modulo ADD r1,r0,#1 MOV r0,#0 x3c BL _rt_udiv MOV r0,r1,test_and_reset ADD r0,r0,#1 CMP r0,#0 x3c MOVCS r
21、0,#0,這個(gè)代碼用“-O1 -Ospace”編譯,浮點(diǎn),軟件浮點(diǎn)庫(kù) (fplib) 默認(rèn):-fpu softvfp (or softfpa) 浮點(diǎn)協(xié)處理器 VFP (ARM10 and ARM9) -fpu vfp (or vfpv1 or vfpv2) FPA (eg ARM7 500fe) - now obsolete -fpu fpa 軟件浮點(diǎn)仿真 (FPE) 通過(guò)未定義的異常來(lái)捕獲協(xié)處理器指令 VFP (and FPA) 實(shí)際上是硬件協(xié)處理器和仿真的混合 要求支持代碼去實(shí)現(xiàn)混合運(yùn)算 在AFS 1.3 和以后的版本里有VFP的 支持代碼, 在ADS的FPA里. 在thumb代碼使用fp
22、處, vfp系統(tǒng)用-fpu softvfp+vfp編譯 使用 -auto_float_constants 預(yù)防常量被處理為雙精度類(lèi)型,關(guān)閉警告用 -Wk.,Example.,float foo(float num1, float num2) float temp, temp2; temp = num1 + num2; temp2 = num2 * num2; return temp2-temp; ,Floating point examples,Agenda,ARM 編譯器優(yōu)化 C/C+和匯編混合模式編程 使用ARM編譯器編碼 局部和全局?jǐn)?shù)據(jù),變量類(lèi)型,全局和靜態(tài)變量保留在RAM里 需使用lo
23、ads/stores訪問(wèn)外部存儲(chǔ)器 局部變量通常放在寄存器中,用來(lái)快速且高效的處理 如果編譯器的寄存器分配算法認(rèn)為超過(guò)現(xiàn)有的寄存器數(shù)量,將把變量壓入棧中 對(duì)局部變量,用 word-sized (int) 代替 halfword 和 byte: 為了確保不受其他條件的影響,可特別指定使用32-bit寄存器變量.,int wordsize(int a) wordsize 0 x000000 : MOV r0,r0,LSL #1 return (a*2); 0 x000004 : MOV pc,lr short halfsize(short b) halfsize 0 x000008 : MOV r
24、0,r0,LSL #17 return (b*2); 0 x00000c : MOV r0,r0,ASR #16 0 x000010 : MOV pc,lr char bytesize(char c) bytesize 0 x000014 : MOV r0,r0,LSL #25 return (c*2); 0 x000018 : MOV r0,r0,LSR #24 0 x00001c : MOV pc,lr,變量大小,堆棧的用法,C/C+代碼的堆棧使用,堆棧用來(lái)保留: 子程序的返回地址 溢出的局部變量 局部數(shù)組和結(jié)構(gòu)體 注意: 函數(shù)越小越好: (更少的變量,更少的溢出); 更少數(shù)量的live變
25、量 (比如:函數(shù)里每個(gè)點(diǎn)保存的有用的數(shù)據(jù)) 避免使用大的局部結(jié)構(gòu)體或數(shù)組 (使用malloc/free代替) 避免遞歸,堆棧使用估計(jì),鏈接使用 -callgraph 顯示靜態(tài)堆棧的開(kāi)銷(xiāo)(html文件). 編譯時(shí)使用軟件堆棧檢查 -apcs /swst 在棧結(jié)束點(diǎn)設(shè)置 watchpoint 測(cè)試堆棧 定義大的棧 填充某個(gè)值,看覆蓋了多少,從而判定棧的使用情況 ARMulator映射文件 拒絕訪問(wèn)棧下面的區(qū)域,棧溢出將導(dǎo)致一個(gè)data abort異常 stackuse.c ARMulator模式, 跟蹤堆棧的大小,用ARMulator的統(tǒng)計(jì)來(lái)輸出報(bào)告,當(dāng)要對(duì)堆棧使用情況進(jìn)行估計(jì)時(shí),使用worst
26、case,全局?jǐn)?shù)據(jù)布局,char one; short two; char three; int four;,char,short,char,e.g. 聲明的數(shù)據(jù),Declared alignment 12 bytes (4 bytes of padding),Optimal alignment 8 bytes (Zero bytes of padding),ADS 1.1+ 將自動(dòng) 用此風(fēng)格排序,short,全局?jǐn)?shù)據(jù)保存在存儲(chǔ)器里,不是寄存器 需要load / store指令來(lái)訪問(wèn) 用物理尺寸的邊界對(duì)齊 ADS 1.2 會(huì)優(yōu)化在一個(gè)模塊里的全局?jǐn)?shù)據(jù)的布局 用-Ono_data_reorder
27、 將關(guān)閉排序,不對(duì)齊訪問(wèn),ARM硬件需要在自然尺寸的邊界訪問(wèn)內(nèi)存 Word訪問(wèn)在word尺寸 Halfword訪問(wèn)在halfword尺寸 Byte訪問(wèn)在byte尺寸 不對(duì)齊訪問(wèn) 遺留代碼 特定協(xié)議 需要必須告訴編譯器,讓它產(chǎn)生適當(dāng)?shù)闹噶钚蛄?使用 _packed 屬性 可能導(dǎo)致多字節(jié)訪問(wèn)代替單字節(jié)訪問(wèn) 用LDM指令的結(jié)果有2 字,轉(zhuǎn)變?yōu)樯蓡巫?不對(duì)齊數(shù)據(jù)的訪問(wèn)所產(chǎn)生的意外的結(jié)果取決于指令的使用 將是不可預(yù)知的,指針的對(duì)齊,必須非常小心指針的對(duì)齊 可能導(dǎo)致程序的失敗,#include int *a = (int *)0 x1000;int *b = (int *)0 x2000;char *c
28、 = (char *)0 x3001;_packed int *d;void foo (void) memcpy (b,a,12); memcpy (c,a,12); b = (int *)c; memcpy (b,a,12); d = (_packed int *)c; memcpy (void *)d,a,12);,STMFD r13!,r4,r14 LDR r4,0 x58 LDR r1,r4,#0 LDR r0,r4,#4 LDMIA r1,r2,r3,r12 STMIA r0,r2,r3,r12 LDR r0,r4,#8 LDR r1,r4,#0 MOV r2,#0 xc BL _r
29、t_memcpy LDR r0,r4,#8 STR r0,r4,#4 LDR r1,r4,#0 LDMIA r1,r2,r3,r12 STMIA r0,r2,r3,r12 LDR r0,r4,#8 LDR r1,0 x5c MOV r2,#0 xc STR r0,r1,#0 LDR r1,r4,#0 BL _rt_memcpy LDMFD r13!,r4,pc,結(jié)構(gòu)的打包,在結(jié)構(gòu)里定義打包的元素代替結(jié)構(gòu)的打包 他將幫助減小訪問(wèn)輸出的結(jié)構(gòu)的開(kāi)銷(xiāo) ADS FAQ 入口: Aligned v. unaligned accesses and use of _packed,_packed struct mystruct int aligned_i; short aligned_s; int unaligned_i; ; extern struct mystruct S;,short,int,U_int,
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 酒店裝修改造承包合同
- 二手房私人買(mǎi)賣(mài)合同
- 2025年專(zhuān)利申請(qǐng)代合同樣本(2篇)
- 2025年農(nóng)產(chǎn)品電商平臺(tái)數(shù)據(jù)服務(wù)合同
- 2025年度農(nóng)業(yè)資源調(diào)查承包合同樣本
- 四川省德陽(yáng)市名校2025屆中考生物押題卷含解析
- 2025年個(gè)人業(yè)務(wù)承包合同樣本(2篇)
- 2025屆九電能和電功同步測(cè)試題重點(diǎn)名校中考生物模試卷含解析
- 2025年度配電設(shè)備安裝與調(diào)試服務(wù)合同
- 2025年度農(nóng)業(yè)機(jī)械智能化改造升級(jí)合同
- 2023-餐飲公司章程范本
- 老年肌肉衰減綜合征(肌少癥)-課件
- 九防突發(fā)事件應(yīng)急預(yù)案
- 脫水篩 說(shuō)明書(shū)
- 建筑公司年度工作總結(jié)及計(jì)劃(6篇)
- 2023年昆明貴金屬研究所招聘筆試模擬試題及答案解析
- 硫酸裝置試生產(chǎn)方案
- 國(guó)家重點(diǎn)專(zhuān)科臨床護(hù)理專(zhuān)業(yè)評(píng)選標(biāo)準(zhǔn)
- DB11T 1944-2021 市政基礎(chǔ)設(shè)施工程暗挖施工安全技術(shù)規(guī)程
- 中國(guó)農(nóng)業(yè)核心期刊要目概覽
- 好聽(tīng)簡(jiǎn)單的鋼琴譜
評(píng)論
0/150
提交評(píng)論