ARM 浮點運算一
時間:2016-12-14作者:華(hua)清遠見
很多時候我們要處理(li)的(de)數(shu)據,不僅僅是(shi)整數(shu)和字符(fu)串,還有浮點(dian)數(shu)即小數(shu)。在(zai)多媒(mei)體數(shu)據處理(li)方面(mian)表現的(de)更多。是(shi)不是(shi)所(suo)有的(de)CPU都(dou)支(zhi)持(chi),浮點(dian)運算呢?答案:不是(shi)。 我(wo)們(men)常常聽(ting)到贏浮(fu)點和(he)軟浮(fu)點,這(zhe)(zhe)些(xie)到底說的是什么呢?下面我(wo)們(men)就(jiu)來(lai)一探(tan)究竟吧。在這(zhe)(zhe)里我(wo)們(men)說的是ARM核浮(fu)點運算。 (1)硬浮點(hard-float) 編譯器(qi)將(jiang)代碼直(zhi)接編譯成硬件浮(fu)點協(xie)處(chu)理器(qi)(浮(fu)點運(yun)(yun)算單(dan)元FPU)能識(shi)別的(de)指令,這些指令在執行(xing)的(de)時候ARM核直(zhi)接把它轉(zhuan)給協(xie)處(chu)理器(qi)執行(xing)。FPU 通常(chang)有一套額外的(de)寄存(cun)器(qi)來完(wan)成浮(fu)點參(can)數傳(chuan)遞(di)和運(yun)(yun)算。使用實際的(de)硬件浮(fu)點運(yun)(yun)算單(dan)元(FPU)會帶來性能的(de)提升。 (2)軟浮(fu)點(dian)(soft-float) 編譯器(qi)把(ba)浮(fu)(fu)(fu)點(dian)運算轉(zhuan)成浮(fu)(fu)(fu)點(dian)運算的(de)函(han)數調(diao)(diao)用(yong)和庫函(han)數調(diao)(diao)用(yong),沒(mei)有(you)(you)FPU的(de)指(zhi)令調(diao)(diao)用(yong),也(ye)沒(mei)有(you)(you)浮(fu)(fu)(fu)點(dian)寄存(cun)器(qi)的(de)參(can)數傳(chuan)遞。浮(fu)(fu)(fu)點(dian)參(can)數的(de)傳(chuan)遞也(ye)是(shi)通過ARM寄存(cun)器(qi)或者堆棧完(wan)成。現在的(de)Linux系統默認編譯選擇使(shi)用(yong)hard-float,如果系統沒(mei)有(you)(you)任(ren)何浮(fu)(fu)(fu)點(dian)處理器(qi)單元,這就會產生非法指(zhi)令和異(yi)常。因(yin)而一般的(de)系統鏡像(xiang)都采(cai)用(yong)軟浮(fu)(fu)(fu)點(dian)以兼(jian)容沒(mei)有(you)(you)VFP的(de)處理器(qi)。 用(yong)一句話總結,軟浮(fu)點(dian)(dian)是通過浮(fu)點(dian)(dian)庫去(qu)實現浮(fu)點(dian)(dian)運(yun)算的,效率低;硬浮(fu)點(dian)(dian)是通過浮(fu)點(dian)(dian)運(yun)算單(dan)元(FPU)來完成的,效率高。 一、使(shi)用浮點(dian)(dian)庫實現浮點(dian)(dian)運算(soft-float) 例如:我想實現兩個(ge)浮點數相加(jia),代(dai)碼如下:
使(shi)用GNU ARM編譯(yi)器翻譯(yi)成的部分匯編代碼如下:
從圖中(zhong)我們可以(yi)知道,默認情況(kuang)下,編譯器使用的是軟浮點(dian),圖中(zhong)__aeabi_fadd這個函數是在浮點(dian)庫中(zhong)實(shi)現。如果想讓代(dai)碼能(neng)正(zheng)常(chang)的運行,還(huan)需要在連(lian)接(jie)的時候靜態連(lian)接(jie)一下浮點(dian)庫。 在這里我們以一(yi)個完成的(de)案(an)例來說(shuo)明一(yi)下,軟浮點庫(ku)的(de)使用方法。 start.S: 使(shi)用硬(ying)件浮點實現(xian)浮點運算(suan)(hard-float) 使用硬件(jian)(jian)浮(fu)點(dian)的(de)時候,我(wo)們需(xu)要給編譯器(qi)傳(chuan)遞一(yi)些參數,讓編譯器(qi)編譯出硬件(jian)(jian)浮(fu)點(dian)單(dan)元(yuan)處理器(qi)能識別(bie)的(de)指令。 (1)-mfpu=name 參數-mfpu就是用來指(zhi)定(ding)要產生那種硬(ying)件浮點(dian)運算指(zhi)令,常(chang)用的右vfp和(he)neon等。 浮點協處理器指令: ARM10 and ARM9: (2) -mfloat-abi=value -mfloat-abi=soft 使(shi)用(yong)(yong)(yong)(yong)這(zhe)個參(can)數(shu)時(shi),其將調用(yong)(yong)(yong)(yong)軟浮(fu)點(dian)庫(softfloat lib)來支持(chi)對浮(fu)點(dian)的運算,GCC編譯器已經(jing)有這(zhe)個庫了,一(yi)(yi)般(ban)(ban)在libgcc里面(mian)。這(zhe)時(shi)根本(ben)不會(hui)使(shi)用(yong)(yong)(yong)(yong)任何浮(fu)點(dian)指(zhi)令,而是采用(yong)(yong)(yong)(yong)常用(yong)(yong)(yong)(yong)的指(zhi)令來模擬浮(fu)點(dian)運算。但使(shi)用(yong)(yong)(yong)(yong)的ARM芯片不支持(chi)硬浮(fu)點(dian)時(shi),可以考慮使(shi)用(yong)(yong)(yong)(yong)這(zhe)個參(can)數(shu)。在使(shi)用(yong)(yong)(yong)(yong)這(zhe)個參(can)數(shu)時(shi),連(lian)接時(shi)一(yi)(yi)般(ban)(ban)會(hui)出現下面(mian)的提(ti)示: undefined reference to `__aeabi_fdiv' 或者類似(si)的提示,主(zhu)要(yao)因為一(yi)般情況下連接器沒有去主(zhu)動尋找軟浮(fu)點(dian)庫,這(zhe)時(shi)使用(yong)將libgcc庫加入即可。 -mfloat-abi=softfp -mfloat-abi=hard 這兩個參數都(dou)用來產生硬浮點(dian)指令(ling)(ling),至于產生哪里類型的(de)硬浮點(dian)指令(ling)(ling),需要(yao)由 -mfpu=xxx參數來指令。這兩個參數不(bu)同(tong)的地(di)方是: -mfloat-abi=softfp生成的(de)代碼(ma)采用(yong)(yong)兼容(rong)軟浮點調用(yong)(yong)接口(即使(shi)用(yong)(yong)-mfloat-abi=soft時的(de)調用(yong)(yong)接口),這樣帶來的(de)好處是:兼容(rong)性和(he)靈活(huo)性。庫可以(yi)(yi)采用(yong)(yong)-mfloat-abi=soft編(bian)譯(yi),而關鍵的(de)應(ying)用(yong)(yong)程(cheng)序可以(yi)(yi)采用(yong)(yong)-mfloat-abi=softfp來編(bian)譯(yi)。特別是在(zai)庫由第三方發布的(de)情況下。 -mfloat-abi=hard生成(cheng)的(de)代碼采用硬(ying)浮點(FPU)調用接口(kou)。這樣要(yao)求所有庫和應(ying)用程序必須采用這同一個參數來編譯,否則連接時會出現接口(kou)不兼容錯誤。 我(wo)們對main.c文件使用硬(ying)件浮點(dian)重(zhong)新編譯:
翻譯成的匯(hui)編代碼如下:
start.s:
發表評論
|