Armv8上不棄不離的NEON FPU

2021-09-10 07:31:32 字數 2333 閱讀 3232

熟悉arm processor的朋友應該知道arm的cortex-a是帶有fpu和neon的,fpu用來做浮點數運算的,而neon是simd指令做並行運算的。在現有cortex-a的設計裡,neon和fpu是不可分的,也就是不能單獨只有neon或是fpu。在比較高效能的cortex-a cpu(比如cortex-a15/a57/a72/a73/a75)中,neon和fpu是不能在rtl配置裡去掉的,在高能效的cortex-a的cpu(比如cortex-a7/a53/a55)中neon和fpu是可以在rtl配置裡面配置有或是沒有。

neon和fpu畢竟是佔面積的,也許你會認為你的應用可能用不到neon或是fpu,所以你可以配置rtl沒有neon/fpu,以減少面積die size或功耗。

這在armv7裡可能不是問題,但是在armv8 64位里需要非常小心,也許因為這個配置導致你的晶元稱為無用的廢片,有些客戶因此遭受損失,雖然我們已經盡可能地告知客戶們。

問題描述

在 armv8 aarch64中,arm規定了過程呼叫規範procedure call standard for the arm 64-bit architecture』–aapcs64,這個規範時規定在函式呼叫過程中怎麼傳輸入和輸出引數,哪些暫存器需要呼叫者保護,哪些暫存器需要被呼叫者保護。之所以要定義這個規範就是要使不同的compiler (arm compiler, gcc, llvm)生成的庫能相容地被使用,能被鏈結器鏈結起來生成乙個可執行檔案或是庫。這保證了arm生態的軟體相容,非常重要。

和我們這次要討論的話題相關的是怎麼來傳浮點數的函式輸入輸出引數。

在armv7的aapcs32規範裡,我們實際上定義了兩種傳浮點數的方式:

softfp

hardfp

這兩個的區別在於,softfp 是用整形的通用暫存器(r0-r3)來傳浮點數引數的,比如

float fadd(float a, float b)

a和b實際上是通過r0,r1傳入到被調函式的,結果也是通過r0傳出的。

但如果使用hardfp,那麼用浮點數暫存器來傳引數,以上同樣的例子,a和b是通過s0, s1暫存器來傳的,結果是通過s0傳出的。

在gcc compiler裡提供了一下選項來選擇你編譯的**是使用哪個方式

-mfloat-abi=softfp/hard

因為使用不同的引數傳遞方式,所以你不能將乙個使用softfp另外乙個使用hardfp的庫或目標檔案鏈結起來。

正式因為如此,在armv7的時候有些編譯好的庫(比如glibc使用softfp)沒法在使用另一種(使用hardfp)的應用編譯中。

有的工具鏈直接只支援一種方式比如arm-linux-gnueabi,和arm-linux-gnueabihf。

但是維護這種不同的abi帶來了相容性維護的問題,比如同樣一套庫可能要提供兩個版本。因此很多os廠商開始只支援一種方式,比如ubuntu從12.04開始只支援hardfp.

正是因為以上原因,armv8 aarch64的aapcs只支援hardfp,這就需要用到neon/fpu暫存器。如果你的cpu配置了沒有neon/fpu,可能軟體上會帶來比較大的問題,導致一些通用的os分發版本(ubuntu,redhat)沒法正常跑。

對軟體和compiler的影響

compiler和一般的os分發版本都會假設armv8

aarch64的cpu是帶neon/fpu的,除非你能非常肯定地知道你的軟體和庫不會使用任何的浮點數運算,這樣的話我們之後會提供一些編譯選項,以便compiler不生成使用浮點數的指令。這樣的話你或許可以在rtl裡去掉neon/fpu.

對linux kernel的影響

為了可以是之前的32位且使用softfp應用可以跑在arm64kernel上,linux kernel提供下面的patch,

這個patch允許arm64 linux kernel本身可以在沒有neon/fpu的cpu上跑。

但是我們不建議去除neon/fpu,因為你可能需要跑通用的linux kernel.即使linux kernel本身可以在沒有neon/fpu的cpu上執行,但是還需要考慮user space的應用和庫是使用aapcs64abi編譯的,他們還是需要neon/fpu.

compiler的支援

gcc提供了-mgeneral-regs-onlyoption選項,這個選項禁止生成的**使用浮點數暫存器,但他不限制彙編使用浮點數暫存器。

arm compiler 6也提供了-mcpu=name+nofp+nosimd這個選項達到以上目標,但是一旦使用這個選項,你的**就不能有浮點數的型別和運算。

如果你肯定你的程式和庫都只需要整形運算,你可以試以上選項,這樣的話就不需要neon/fpu的硬體支援。

ARMv7與ARMv8的區別

參考連線 區別 1.指令集 armv8使用64位及32位的指令集,armv7使用32位及16位的指令集。2.通用暫存器 v8包含32個暫存器其中前32個位64位暫存器,後32個位32位暫存器,v7只包含16個32位暫存器。3.simd暫存器 v8包含32個128位暫存器,v7是32個64位暫存器。目...

ARMv8 中斷處理介面

不考慮el2和el3,irq處理分兩種情況 使用者態發生的中斷和核心態發生的中斷,相應的中斷處理介面分別為 el1 irq el0 irq 以核心態el1發生的irq為例 358 align 6 359 el1 irq 360 kernel entry 1 壓棧,儲存上下文 361 enable d...

armV8 下除錯232 485小結,

通過文件,因為我單獨安裝過dxx的驅動,不確定是kernal整合 還是我之前安裝的可行,上述步驟可以不用一步步做,我直接 1,dmesg grep ftdi 發現,最後那句,ttyusb0 已經attached,故 沒有按照上面編寫那個檔案 99 usbftdi.rules 而我後面 發現只有sud...