




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
C程序在ARM上的優(yōu)化主要內(nèi)容ARM編譯器優(yōu)化C/C++和匯編混合模式編程局部和全局數(shù)據(jù)討論第一節(jié) ARM編譯器優(yōu)化
優(yōu)化級別使用的編譯器優(yōu)化級別是可選擇的
-O0---DEBUG關(guān)閉大多數(shù)優(yōu)化最好的調(diào)試信息,最少的優(yōu)化
-O1---DEBUGREL多數(shù)優(yōu)化選項許可給一個滿意的調(diào)試,好的代碼密度
-O2---RELEASE(default)完全的優(yōu)化有限的調(diào)試信息,最好的代碼密度
為代碼大小或運行速度的優(yōu)化,可選擇:-Ospace(默認的)或-Otime.使用-g
選項可包含源碼級調(diào)試信息ADS編譯器在所有級別中執(zhí)行一些簡單的優(yōu)化i.e.
-O0,-O1,-O2下面是一個例子:即使用-O0,多余的表達式也被清除了ATPCS標準中子程序結(jié)果返回規(guī)則結(jié)果為32位整數(shù),R0返回結(jié)果為64位整數(shù),R0,R1返回位數(shù)更多時,用內(nèi)存來傳遞……自動優(yōu)化intf(int*p){return(*p==*p);}armcc-c–O0fMOVr1,r0MOVr0,#1MOVpc,lr注意:在這種情況下,可使用C的關(guān)鍵字volatile強制使用這些變量使用“volatile”intf(volatileint*p){return(*p==*p);}armcc-cfLDRr1,[r0]LDRr0,[r0]CMPr1,r0MOVNEr0,#0MOVEQr0,#1MOVpc,lrintf(int*p){return(*p==*p);}fMOVr0,#1MOVpc,lrarmcc-c這個代碼用的編譯級別是:-o2下面是一個冗余代碼清除的例子,它只用了-o1的優(yōu)化選項:冗余代碼的清除intdummy(){inta=10,b=20;intc;c=a+b;return0;}armcc-c-O1dummyMOVr0,#0MOVpc,lr指令編排指令編排在高級優(yōu)化選項中是有效的(-O1,-O2)指令的重新編排是為了使要運行的代碼更適合對應(yīng)的核為arm9和以后的處理器提高吞吐量(一般可達到4%),并防止互鎖(interlock)選擇處理器可決定使用的運算法則,在默認情況下,使用針對ARM9的優(yōu)化方案(對ARM7的運行沒有影響)例如:intf(int*p,intx) {return*p+x*3;}
沒用指令編排(-O0) 使用指令編排(-O1,-O2)
ADDr1,r1,r1,LSL#1 LDRr0,[r0,#0]
LDRr0,[r0,#0] ADDr1,r1,r1,LSL#1
ADDr0,r0,r1;interlockonARM9 ADDr0,r0,r1
MOVpc,lr MOVpc,lrarmcc–cpuarm7tdmiarmcc–cpuarm9tdmi
嵌套優(yōu)化可避免在函數(shù)級里的不必要的返回在可能的情況下BL譯碼成B
在高級優(yōu)化里有效(-O1,-O2)intmain()
{
intx=f();
:
}intf()
{
inty=g();
returny;
}intg()
{
return10;
}BgBLf
:MOVr0,#10
MOVpc,lrBLf
:STRlr,[sp,#-4]!
BLg
MOVr1,r0
MOVr0,r1
LDRpc,[sp],#4MOVr0,#10MOVpc,lr嵌套優(yōu)化內(nèi)嵌函數(shù)(inline)內(nèi)嵌可通過刪除子函數(shù)調(diào)用的開銷來提高性能這個inline
關(guān)鍵字顯示哪個函數(shù)將被內(nèi)嵌在高級優(yōu)化選項中,ADS1.2編譯器默認自動內(nèi)嵌-Oautoinline(default-O2)-Ono_autoinline(defaultfor-O0,-O1)哪個函數(shù)是否被內(nèi)嵌取決于:它們是否被__inline標識優(yōu)化的級別-Otime/-Ospace函數(shù)被調(diào)用的次數(shù)intbar(inta){a=a+5;returna;}intfoo(inti){i=bar(i);i=i-2;i=bar(i);i++;returni;}barADDr0,r0,#5MOVpc,lrfooSTRlr,[sp,#-4]!BLbarSUBr0,r0,#2BLbarADDr0,r0,#1LDRpc,[sp],#4__inlineintbar(inta){a=a+5;returna;}intfoo(inti){i=bar(i);i=i-2;i=bar(i);i++;returni;}fooADDr0,r0,#5SUBr0,r0,#2ADDr0,r0,#5ADDr0,r0,#1MOVpc,lr開始四個字大小的參數(shù)直接使用寄存器的R0-R3來傳遞(快速且高效的)更多的信息可參看ATPCS如果需要更多的參數(shù),將使用堆棧。(需要額外的指令和慢速的存儲器操作)
所以通常限制參數(shù)的個數(shù),使它為4或更少。如果不可避免,把常用的參數(shù)前4個放在R0-R3中參數(shù)傳遞參數(shù)傳遞(4參數(shù))intfunc1(inta,intb, intc,intd){returna+b+c+d;}intcaller1(void){returnfunc1(1,2,3,4);}
func10x000000:ADDr0,r0,r10x000004:ADDr0,r0,r20x000008:ADDr0,r0,r30x00000c:MOVpc,lr
caller10x000014:MOVr3,#40x000018:MOVr2,#30x00001c:MOVr1,#20x000020:MOVr0,#10x000024:Bfunc1ParameterPassing(4parameters)參數(shù)傳遞(6參數(shù))func20x000000:STRlr,[sp,#-4]!0x000004:ADDr0,r0,r10x000008:ADDr0,r0,r20x00000C:ADDr0,r0,r30x000010:LDMIAr4,{r12,r14}0x000014:ADDr0,r0,r120x000018:ADDr0,r0,r140x00001C:LDRpc,{sp},#4
caller20x000020:STMFDsp!,{r2,r3,lr}0x000024:MOVr3,#60x000028:MOVr2,#50x00002C:STMIAr4,{r2,r3}0x000030:MOVr3,#40x000034:MOVr2,#30x000038:MOVr1,#20x00003C:MOVr0,#10x000040:BLfunc20x000044:LDMFDsp!,{r2,r3,pc}intfunc2(inta,intb,intc, int,d,inte,intf){returna+b+c+d+e+f;}intcaller2(void){returnfunc2(1,2,3,4,5,6);}Thiscodeiscompiledwith“-O2-Ono_autoinline”在for(),while()do…while()的循環(huán)中,用減到0代替加到某個值比如,用下面的代替:
for(loop=1;loop<=total;loop++)//(ADD,CMP)
代替為:
for(loop=total;loop!=0;loop--)//(SUBS)盡量減少循環(huán)的次數(shù)代碼小,且使用更少的寄存器循環(huán)終止Countupintfact1(intlimit){inti;intfact=1;for(i=1;i<=limit;i++){fact=fact*i;}returnfact;}Countdownintfact2(intlimit){inti;intfact=1;for(i=limit;i!=0;i--){fact=fact*i;}returnfact;}fact20x000000:MOVSr1,r00x000004:MOVr0,#10x000008:MOVEQpc,lr0x00000c:MULr0,r1,r00x000010:SUBSr1,r1,#10x000014:BNE0x0c0x000018:MOVpc,lrfact10x000000:MOVr2,#10x000004:MOVr1,#10x000008:CMPr0,#10x00000c:BLT0x200x000010:MULr2,r1,r20x000014:ADDr1,r1,#10x000018:CMPr1,r00x00001c:BLE0x100x000020:MOVr0,r20x000024:MOVpc,lrThiscodeiscompiledwith“-O2-Otime”循環(huán)終止除法操作(1)ARM核不含除法硬件除法通常用一個運行庫函數(shù)來實現(xiàn),運行需要很多的周期unsigneddiv(unsigneda,unsignedb){return(b/a);}divB__rt_udivunsigneddiv2(unsignedb){return(b/2);}div2MOVr0,r0,LSR#1MOVpc,lr一些除法操作在編譯時作為特例來處理除2操作,被右移代替除法操作(2)在-O1和-O2(使用-Otime),其他的常量將使用一個標準的乘法序列來完成例如:實時除法程序使用CLZ指令只有V5te體系結(jié)構(gòu)才有效。用下面的辦法來選擇C-#pragmaimport__use_realtime_divisionAssembler-IMPORT__use_realtime_divisiondiv10MOVr1,r0
LDRr0,=0xCCCCCCCD
UMULLr2,r1,r0,r1
MOVr0,r1,LSR#3
MOVpc,lrunsigneddiv10(unsignedc){return(c/10);}第二節(jié) C/C++和匯編混合模式編程
C和匯編的混合編程C/C++和匯編能很容易的混合可實現(xiàn)在C中無法實現(xiàn)的處理器功能使用新的或不支持的指令產(chǎn)生更高效的代碼直接鏈接變量和程序確定符合程序調(diào)用規(guī)范輸入/輸出相關(guān)的符號編譯器也可包含內(nèi)嵌匯編大多數(shù)ARM指令集都可實現(xiàn)寄存器操作數(shù)可支持任意的C/C++的表達式內(nèi)嵌匯編代碼可由編譯器的優(yōu)化器來傳遞匯編語言與C/C++的混合編程通常有以下幾種方式:在C/C++代碼中嵌入?yún)R編指令在匯編程序和C/C++的程序之間進行變量的互訪匯編程序、C/C++程序間的相互調(diào)用C和匯編的混合編程r8r9/sbr10/slr11r12r13/spr14/lrr15/pcr0r1r2r3r4r5r6r7寄存器變量必須保護作為函數(shù)傳遞的參數(shù)值Scratchregister(corruptible)StackPointer
LinkRegisterProgramCounterARM-ThumbProcedureCallStandardorATPCS(orAPCS)
編譯器使用一套規(guī)則來設(shè)置寄存器的用法
CPSR標志位可被函數(shù)調(diào)用所破壞任何和編譯過的代碼交互工作的匯編碼在接口層必須滿足ATPCS的規(guī)范Register-如果RWPI選項有效,作為棧的基地址-如果軟件堆棧檢查有效,作為棧的限制值-可作為臨時的一個值棧一樣來使用-子程序內(nèi)部調(diào)用的可改寫的寄存器-程序計數(shù)器在C程序中調(diào)用匯編在匯編程序中用exportname來定義在C程序中直接調(diào)用,用EXTERN聲明正常鏈接externvoidmystrcopy(char*d,constchar*s);intmain(void){constchar*src=“Source”;
chardest[10];...
mystrcopy(dest,src);...}AREAStringCopy,CODE,READONLYEXPORTmystrcopymystrcopyLDRBr2,[r1],#1STRBr2,[r0],#1CMPr2,#0BNEmystrcopyMOVpc,lrEND這里所有的參數(shù)都是可以用寄存器來傳遞的,所以不需要在匯編程序中使用堆棧來保護CALL
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編的語法__asm {指令[;指令]//*注釋*
…… [指令] }
內(nèi)嵌匯編-----------內(nèi)嵌匯編的語法例:使能/禁能IRQ中斷
__inlinevoidenable_IRQ(void){inttmp;
__asm//嵌入?yún)R編代碼
{MRStmp,CPSR//讀取CPSR的值
BICtmp,tmp,#0x80MSRCPSR_c,tmp}}內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編的語法例:使能/禁能IRQ中斷
__inlinevoiddisable_IRQ(void){inttmp;
__asm{MRStmp,CPSRORRtmp,tmp,#0x80MSRCPSR_c,tmp}}內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編的指令用法(1)操作數(shù)內(nèi)嵌的匯編指令中作為操作數(shù)的寄存器和常量可以是C表達式。(2)物理寄存器內(nèi)嵌匯編中使用物理寄存器有以下限制:不能直接向PC寄存器賦值使用物理寄存器的指令中,不要使用過于復雜的C表達式編譯器可能會使用R12或R13存放編譯的中間結(jié)果通常內(nèi)嵌的匯編指令中不要指定物理寄存器內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編的指令用法(3)常量。在內(nèi)嵌匯編指令中,常量前面的“#”可以省略。(4)指令展開。內(nèi)嵌的匯編指令中,如果包含常量操作數(shù),則該指令有可能被內(nèi)嵌匯編器展開成幾條指令。(5)標號。C程序中的標號可以被內(nèi)嵌的匯編指令使用。但是只有指令B可以使用C程序中的標號,而指令BL則不能使用。內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言(6)內(nèi)存單元的分配。所有的內(nèi)存分配均由C編譯器完成,分配的內(nèi)存單元通過變量供內(nèi)嵌匯編器使用。內(nèi)嵌匯編器不支持內(nèi)嵌匯編程序中用于內(nèi)存分配的偽指令。-----------內(nèi)嵌匯編的指令用法(7)SWI和BL指令。在內(nèi)嵌的SWI和BL指令中,除了正常的操作數(shù)域外,還必須增加以下3個可選的寄存器列表:
第1個寄存器列表中的寄存器用于輸入的參數(shù)。第2個寄存器列表中的寄存器用于存儲返回的結(jié)果。第3個寄存器列表中的寄存器的內(nèi)容可能被被調(diào)用的子程序破壞,即這些寄存器是供被調(diào)用的子程序作為工作寄存器。內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編器與armasm匯編器的差異內(nèi)嵌匯編器不支持通過“.”指示符或PC獲取當前指令地址不支持“LDRRn,=expr”偽指令,而使用“MOVRn,expr”指令向寄存器賦值;不支持標號表達式;不支持ADR和ADRL偽指令;不支持BX指令;不能向PC賦值使用0x前綴代替“&”,表示十六進制數(shù)當使用8位移位常數(shù)導致CPSR的ALU標志更新時,N、Z、C和V標志中的C不具有真實意義內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編注意事項(1)必須小心使用物理寄存器如R0~R3、PC、LR和CPSR中的N、Z、C和V標志位,因為計算匯編代碼中的C表達式時,可能會使用這些物理寄存器,并會修改N、Z、C和V標志位。例如:__asm {MOVvar,x ADDy,var,x/y }
計算x/y時R0會被修改。內(nèi)嵌匯編器探測到隱含的寄存器沖突就會報錯。內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編注意事項(2)不要使用寄存器代替變量例如:
intbad_f(intx)//x存放在R0中
{__asm {ADDR0,R0,#1//發(fā)生寄存器沖突,實際上x的值沒有變化
} return(x);
}
盡管根據(jù)編譯器的編譯規(guī)則似乎可以確定R0對應(yīng)x,但這樣的代碼會使內(nèi)嵌匯編器認為發(fā)生了寄存器沖突。內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編注意事項(3)LDM和STM指令的寄存器列表中只允許使用物理寄存器內(nèi)嵌匯編可以修改處理器模式、協(xié)處理器模式以及FP、SL、SB等APCS寄存器。但是編譯器在編譯時并不了解這些變化,因此必須保證在執(zhí)行C代碼前恢復相應(yīng)被修改的處理器模式。內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言-----------內(nèi)嵌匯編注意事項(4)匯編語言中的“,”號作為操作數(shù)分隔符。如果有C表達式作為操作數(shù),若表達式中包含有“,”,則必須使用符號“(”和“)”將其歸約為一個匯編操作數(shù)。例如:__asm{ADDx,y,(f(),z)//“f(),z”為一個帶有“,”的C表達式
}內(nèi)嵌匯編
如何在C語言內(nèi)嵌匯編語言內(nèi)嵌匯編允許使用一些不能由編譯器自動生成的指令:MSR/MRS新的指令協(xié)處理器指令通常在關(guān)聯(lián)的內(nèi)嵌函數(shù)中使用使用C變量代替寄存器不是一個真正的匯編文件通過優(yōu)化器實現(xiàn)ADSFAQ入口“UsingtheInlineAssembler”#defineQ_Flag0x08000000//Bit27__inlinevoidClear_Q_flag(void){inttemp; __asm {
MRStemp,CPSR BICtemp,temp,#Q_Flag MSRCPSR_f,temp }}__inlineintmult16(shorta,
shortb,intc){
inttemp; __asm {
SMLABBtemp,a,b,c } returntemp;}第三節(jié) 局部和全局數(shù)據(jù)討論
變量類型全局和靜態(tài)變量保留在RAM里需使用load/store訪問外部存儲器局部變量通常放在寄存器中,用來快速且高效的處理如果編譯器的寄存器分配算法認為超過現(xiàn)有的寄存器數(shù)量,將把變量壓入棧中對局部變量,用word-sized(int)代替halfword和byte:為了確保不受其他條件的影響,可特別指定使用32-bit寄存器變量intwordsize(inta) wordsize{ 0x000000:MOVr0,r0,LSL#1return(a*2); 0x000004:MOVpc,lr} shorthalfsize(shortb) halfsize{ 0x000008:MOVr0,r0,LSL#17return(b*2); 0x00000c:MOVr0,r0,LSR#16} 0x000010:MOVpc,lr
charbytesize(charc) bytesize{ 0x000014:MOVr0,r0,LSL#25return(c*2); 0x000018:MOVr0,r0,LSR#24} 0x00001c:MOVpc,lr
變量類型堆棧的用法C/C++代碼的堆棧使用,堆棧用來保留:子程序的返回地址‘溢出’的局部變量局部數(shù)組和結(jié)構(gòu)體注意:函數(shù)越小越好(更少的變量,更少的‘溢出’);避免使用大的局部結(jié)構(gòu)體或數(shù)組(使用malloc/free代替)避免遞歸全局數(shù)據(jù)布局charone;shorttwo;charthree;intfour;charshortintchare.g.聲明的數(shù)據(jù)Declaredalignment12bytes(4bytesofpadding)Optimalalignment8bytes(Zerobytesofpadding)ADS將自動用此風格排序shortcharcharint全局數(shù)據(jù)保存在存儲器里,不是寄存器需要load/store指令來訪問用物理尺寸的邊界對齊ADS會優(yōu)化在一個模塊里的全局數(shù)據(jù)的布局用-Ono_data_reorder將關(guān)閉排序不對齊訪問ARM硬件需要在自然尺寸的邊界訪問內(nèi)存Word訪問在word尺寸Halfword訪問在halfword尺寸Byte訪問在byte尺寸不對齊訪問遺留代碼特定協(xié)議 需要必須告訴編譯器,讓它產(chǎn)生適當?shù)闹噶钚蛄惺褂胈_packed
屬性可能導致多字節(jié)訪問代替單字節(jié)訪問用LDM指令的結(jié)果有2字,轉(zhuǎn)變?yōu)樯蓡巫植粚R數(shù)據(jù)的訪問所產(chǎn)生的意外的結(jié)果取決于指令的使用將是不可預知的結(jié)構(gòu)的壓縮在結(jié)構(gòu)里定義壓縮的元素代替結(jié)構(gòu)的壓縮將幫助減小訪問輸出的結(jié)構(gòu)的開銷__packedstructmystruct{intaligned_i;shortaligned_s;intunaligned_i;};externstructmystructS;shortintU_intU_intstructmystruct{intaligned_i;shortaligned_s;__packedintunaligned_i;};externstructmystructS;PREFER... _packed限定的數(shù)據(jù)為1字節(jié)對齊不實現(xiàn)字節(jié)對齊調(diào)整很高的訪問代價,不會節(jié)省存儲空間優(yōu)化的指針基地址externinta;externintb;voidfoo(intx,inty)
{
a=x;
b=y;}baLDRr2,[pc,#12]STRr0,[r2,#0]LDRr3,[pc,#8]STRr1,
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度城市托管班品牌授權(quán)與加盟合同
- 文化產(chǎn)品創(chuàng)意開發(fā)合同
- 工業(yè)管道清洗與維護預案
- 法律咨詢行業(yè)法律服務(wù)結(jié)果保證書
- 三農(nóng)行業(yè)三農(nóng)戶教育培訓計劃
- 農(nóng)業(yè)種植養(yǎng)殖合同
- 智能圖書館管理系統(tǒng)供應(yīng)合同
- 大學語文辯論賽故事征文
- 高考語文復習-文言文專題訓練《史記晉世家》
- 會議紀要與重要決策執(zhí)行情況跟蹤表
- 蛋糕投標書技術(shù)方案
- 機房建設(shè)驗收報告
- 環(huán)境巖土工程學課件-東南大學-潘華良境巖土工程學概論-9大環(huán)境巖土工程問題
- 公路養(yǎng)護的檔案管理-公路養(yǎng)護檔案的內(nèi)容及分類
- 武漢大學《819宏微觀經(jīng)濟學》知識板塊歸納與重點名詞解釋大全
- 脊柱內(nèi)鏡應(yīng)用與進展
- 學校食品安全會議記錄內(nèi)容
- 中國古代文物賞析
- 2022年江蘇省錄用公務(wù)員筆試《公安專業(yè)科目》試題(網(wǎng)友回憶版)
- 光伏電站螺旋地樁承載力計算軟件
- 醫(yī)用耗材配送服務(wù)方案
評論
0/150
提交評論