国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置: > 華清遠(yuǎn)見教育科技集團(tuán) > 嵌入式學(xué)習(xí) > 講師博文 > ARM 浮點(diǎn)運(yùn)算一
ARM 浮點(diǎn)運(yùn)算一
時(shí)間:2016-12-14作者:華清遠(yuǎn)見

很多時(shí)候我們要處理的數(shù)據(jù),不僅僅是整數(shù)和字符串,還有浮點(diǎn)數(shù)即小數(shù)。在多媒體數(shù)據(jù)處理方面表現(xiàn)的更多。是不是所有的CPU都支持,浮點(diǎn)運(yùn)算呢?答案:不是。

我們常常聽到贏浮點(diǎn)和軟浮點(diǎn),這些到底說(shuō)的是什么呢?下面我們就來(lái)一探究竟吧。在這里我們說(shuō)的是ARM核浮點(diǎn)運(yùn)算。

(1)硬浮點(diǎn)(hard-float)

編譯器將代碼直接編譯成硬件浮點(diǎn)協(xié)處理器(浮點(diǎn)運(yùn)算單元FPU)能識(shí)別的指令,這些指令在執(zhí)行的時(shí)候ARM核直接把它轉(zhuǎn)給協(xié)處理器執(zhí)行。FPU 通常有一套額外的寄存器來(lái)完成浮點(diǎn)參數(shù)傳遞和運(yùn)算。使用實(shí)際的硬件浮點(diǎn)運(yùn)算單元(FPU)會(huì)帶來(lái)性能的提升。

(2)軟浮點(diǎn)(soft-float)

編譯器把浮點(diǎn)運(yùn)算轉(zhuǎn)成浮點(diǎn)運(yùn)算的函數(shù)調(diào)用和庫(kù)函數(shù)調(diào)用,沒有FPU的指令調(diào)用,也沒有浮點(diǎn)寄存器的參數(shù)傳遞。浮點(diǎn)參數(shù)的傳遞也是通過(guò)ARM寄存器或者堆棧完成。現(xiàn)在的Linux系統(tǒng)默認(rèn)編譯選擇使用hard-float,如果系統(tǒng)沒有任何浮點(diǎn)處理器單元,這就會(huì)產(chǎn)生非法指令和異常。因而一般的系統(tǒng)鏡像都采用軟浮點(diǎn)以兼容沒有VFP的處理器。

用一句話總結(jié),軟浮點(diǎn)是通過(guò)浮點(diǎn)庫(kù)去實(shí)現(xiàn)浮點(diǎn)運(yùn)算的,效率低;硬浮點(diǎn)是通過(guò)浮點(diǎn)運(yùn)算單元(FPU)來(lái)完成的,效率高。

一、使用浮點(diǎn)庫(kù)實(shí)現(xiàn)浮點(diǎn)運(yùn)算(soft-float)

例如:我想實(shí)現(xiàn)兩個(gè)浮點(diǎn)數(shù)相加,代碼如下:

使用GNU ARM編譯器翻譯成的部分匯編代碼如下:

從圖中我們可以知道,默認(rèn)情況下,編譯器使用的是軟浮點(diǎn),圖中__aeabi_fadd這個(gè)函數(shù)是在浮點(diǎn)庫(kù)中實(shí)現(xiàn)。如果想讓代碼能正常的運(yùn)行,還需要在連接的時(shí)候靜態(tài)連接一下浮點(diǎn)庫(kù)。

在這里我們以一個(gè)完成的案例來(lái)說(shuō)明一下,軟浮點(diǎn)庫(kù)的使用方法。

start.S:
        .global _start
        #define USER_MODE 0x10
        _start:
        @設(shè)置CPU為user模式
        mov r0,#USER_MODE
        msr cpsr_c,r0
        @跳到main函數(shù)
        ldr sp,=0x34000
        bl main
        stop:
        b stop
        main.c:
        int main()
        {
                float f1,f2,f3;
                f1 = 1.24;
                f2 = 1.22;
                f3 = f1 + f2;
                return 0;
        }
        Makefile:
        LD=arm-none-eabi-ld
        OBJDUMP=arm-none-eabi-objdump
        RM=rm -rf
        CFLAG= -g -c
        ASFLAG=-g -c
        OBJ=start.o main.o
        LDFLAGS= -static -L\
        #指定浮點(diǎn)庫(kù)所在的路徑
        "C:\Program Files\yagarto\lib\gcc\arm-none-eabi\4.6.2" -lgcc
        #設(shè)置編譯模式
        %.o:%.S
        $(CC) $(ASFLAG) $< -o $@

        %.o:%.c
        $(CC) $(CFLAG) $< -o $@
        all:$(OBJ)
        $(LD) -Ttext=0x20000 $^ -o arm.elf $(LDFLAGS)
        $(OBJDUMP) -D arm.elf > arm.dis
        clean:
        $(RM) *.o arm.dis arm.elf

使用硬件浮點(diǎn)實(shí)現(xiàn)浮點(diǎn)運(yùn)算(hard-float)

使用硬件浮點(diǎn)的時(shí)候,我們需要給編譯器傳遞一些參數(shù),讓編譯器編譯出硬件浮點(diǎn)單元處理器能識(shí)別的指令。

(1)-mfpu=name

參數(shù)-mfpu就是用來(lái)指定要產(chǎn)生那種硬件浮點(diǎn)運(yùn)算指令,常用的右vfp和neon等。

浮點(diǎn)協(xié)處理器指令:

ARM10 and ARM9:
        -mfpu=vfp(or vfpv1 or vfpv2)
        Cortex-A8:
        -mfpu=neon

(2) -mfloat-abi=value

-mfloat-abi=soft 使用這個(gè)參數(shù)時(shí),其將調(diào)用軟浮點(diǎn)庫(kù)(softfloat lib)來(lái)支持對(duì)浮點(diǎn)的運(yùn)算,GCC編譯器已經(jīng)有這個(gè)庫(kù)了,一般在libgcc里面。這時(shí)根本不會(huì)使用任何浮點(diǎn)指令,而是采用常用的指令來(lái)模擬浮點(diǎn)運(yùn)算。但使用的ARM芯片不支持硬浮點(diǎn)時(shí),可以考慮使用這個(gè)參數(shù)。在使用這個(gè)參數(shù)時(shí),連接時(shí)一般會(huì)出現(xiàn)下面的提示:

undefined reference to `__aeabi_fdiv'

或者類似的提示,主要因?yàn)橐话闱闆r下連接器沒有去主動(dòng)尋找軟浮點(diǎn)庫(kù),這時(shí)使用將libgcc庫(kù)加入即可。

-mfloat-abi=softfp

-mfloat-abi=hard

這兩個(gè)參數(shù)都用來(lái)產(chǎn)生硬浮點(diǎn)指令,至于產(chǎn)生哪里類型的硬浮點(diǎn)指令,需要由

-mfpu=xxx參數(shù)來(lái)指令。這兩個(gè)參數(shù)不同的地方是:

-mfloat-abi=softfp生成的代碼采用兼容軟浮點(diǎn)調(diào)用接口(即使用-mfloat-abi=soft時(shí)的調(diào)用接口),這樣帶來(lái)的好處是:兼容性和靈活性。庫(kù)可以采用-mfloat-abi=soft編譯,而關(guān)鍵的應(yīng)用程序可以采用-mfloat-abi=softfp來(lái)編譯。特別是在庫(kù)由第三方發(fā)布的情況下。

-mfloat-abi=hard生成的代碼采用硬浮點(diǎn)(FPU)調(diào)用接口。這樣要求所有庫(kù)和應(yīng)用程序必須采用這同一個(gè)參數(shù)來(lái)編譯,否則連接時(shí)會(huì)出現(xiàn)接口不兼容錯(cuò)誤。

我們對(duì)main.c文件使用硬件浮點(diǎn)重新編譯:

翻譯成的匯編代碼如下:

start.s:
        .global _start
        #define USER_MODE 0x10
        _start:
        @ 設(shè)置為所有模式都可以訪問協(xié)處理器,cortex-A8手冊(cè) 3.2.27
        mov r0, #0xfffffff
        mcr p15, 0, r0, c1, c0, 2
        @ 使能NEON and VFP協(xié)處理器,NEON and VFP enable bit.
        @ 設(shè)置fpexc的30位為1去使能NEON and VFP,cortex-A8 手冊(cè) 13.4.3
        ldr r0, =1<<30
        fmxr fpexc, r0
        @設(shè)置CPU為user模式
        mov r0,#USER_MODE
        msr cpsr_c,r0
        @跳到main函數(shù)
        ldr sp,=0x34000
        bl main
        stop:
        b stop
        main.c:
        int main()
        {
  nbsp;              float f1,f2,f3;
                f1 = 1.24;
                f2 = 1.22;
                f3 = f1 + f2;
                return 0;
        }
        Makefile:
        CC=arm-none-eabi-gcc
        AS=arm-none-eabi-as
        LD=arm-none-eabi-ld
        OBJDUMP=arm-none-eabi-objdump
        RM=rm -rf
        CFLAG=-g -c -mfpu=neon -mfloat-abi=softfp
        ASFLAG=-g -c -mfpu=neon -mfloat-abi=softfp
        OBJ=start.o main.o
        #設(shè)置編譯模式
        %.o:%.S
        $(CC) $(ASFLAG) $< -o $@
        %.o:%.c
        $(CC) $(CFLAG) $< -o $@
        all:$(OBJ)
        $(LD) -Ttext=0x20000 $^ -o arm.elf
        $(OBJDUMP) -D arm.elf > arm.dis
        clean:
        $(RM) *.o arm.dis arm.elf

發(fā)表評(píng)論
評(píng)論列表(網(wǎng)友評(píng)論僅供網(wǎng)友表達(dá)個(gè)人看法,并不表明本站同意其觀點(diǎn)或證實(shí)其描述)