亚洲春色中文字幕久久久-三上亚,一吻二脱三床四吻胸,国产真实伦对白视频全集,在线毛片观看,精品成品入口黄网,国产毛aⅴ片久久久,亚洲AV色香蕉一区二区三区老师,萧皇后A级艳片,色情日本视频更新,99久久亚洲精品日本无码

標題: STM32H7/cotex M內核 匯編,內嵌匯編小技巧 [打印本頁]

作者: UH502    時間: 2025-11-6 02:39
標題: STM32H7/cotex M內核 匯編,內嵌匯編小技巧
以下作為我個使用cotex  M7內核統計的一些特性:

一  內核行為分析
實例代碼1:
FPU_Test: //double FPU_Test (double a_mul,double b_mul,double c_add);
        
        
        PUSH{R4-R7}
        MOV R0, #1024        //減少循環次數,避免緩存影響
    // 初始化完全獨立的寄存器組

    LDR R1,=8234
        MOV R6,R0
        MOV R7,R1
        PLI [LR]
        
FPU_Test_Loop_Opt:
    // 8組完全獨立的 VFMA 操作
    VFMA.F32 S2, S1, S0      // 組1
        SMLAL  R3,R2,R1,R0
    VFMA.F32 S3, S1, S0      // 組2 - 完全獨立
        SUBS R4,R4, #1
        SHADD16 R5,R5,R0
        SMLAL  R3,R2,R1,R0
    VFMA.F32 S4, S1, S0      // 組3 - 完全獨立
        SHADD16 R4,R4,R1
        SUBS R5,R5, #1
        SMLAL  R3,R2,R1,R0
    VFMA.F32 S5, S1, S0    // 組4 - 完全獨立
        SHADD16 R5,R5,R0
        SUBS R4,R4, #1
        SMLAL  R3,R2,R1,R0
    VFMA.F32 S6, S1, S0   // 組5 - 完全獨立
    SUBS R0,R0, #1
    BNE FPU_Test_Loop_Opt

        
        

        POP{R4-R7}
    BX LR


以上為keilv5  MDK V5.23 編譯器語法
1:使用VFMA(浮點區域指令)與使用SMLAL(整數區域指令)能夠讓處理器進行雙發射(在cotex  M7權威手冊里亦有記載)
但是,注意需注意順序即:
    VFMA.F32 S2, S1, S0      // 組1
    SMLAL  R3,R2,R1,R0


      VFMA.F32 S4, S1, S0      // 組3 - 完全獨立
      SHADD16 R4,R4,R1
是能夠正常雙發射
    VFMA.F32 S2, S1, S0      // 組1
    SMLAL  R3,R2,R1,R0


      SHADD16 R4,R4,R1
      VFMA.F32 S4, S1, S0      // 組3 - 完全獨立
以上只能單發射,而不能雙發射

      SHADD16 R4,R4,R1
      SUBS R5,R5, #1
      SMLAL  R3,R2,R1,R0
      VFMA.F32 S5, S1, S0    // 組4 - 完全獨立
   以上可以雙發射
總結為:在使用浮點+整數指令時,下一條指令如果需要使用整數并且需要使用寄存器,那么MCU則不支持雙發射,如果為浮點,即可成功雙發射.
若持續為整數指令,那么在數據無依賴的情況下,即可雙發射,否者只能單發射,或者阻塞 (均不包含除法指令)
1     針對于除法指令,在mcu上能不用就不用,無符號/有符號整數除法平均會消耗10個周期左右,除非你的結果較小,例如小于256.那么可以在較短的時間里得出結果,對于雙精度浮點除法,通常需要14-16個時鐘周期,單精度需要8-12個周期.除法指令是阻塞運行的,不支持單周期的吞吐量.除法比較特殊,即使數據無依賴也不行
2    在cotex-m7內核上,大部分都會有支持雙精度浮點,但是,雙精度浮點一般比單精度慢2-8倍,不同指令有著不同的效率,如VADD.F64就最快,2周期的吞吐量,基本與VADD.F32 的單周期差不了太多,對于像VFMA.F32(實例代碼中的指令)為單周期吞吐量.  VFMA.F64不支持單周期吞吐量,執行一條需要7個周期,并且不支持與其他指令雙發射,包括大部分的.F64的運算指令(像VMOV.F64這種執行時間為2周期,與雙精度與單精度無關,執行周期按位寬/32bit)都不支持與其他指令雙發射


二    性能優化:
對于需要性能優化的場景來說,手動添加(C#) __ASM    volatile{  "PLI  [這里填C里的一個變量]");用于提前預加載(提示內核等會兒要使用)需要執行的指令,可以在跳轉后更快的執行,通常用于執行動態代碼,例如:
__ASM volatile (
                        "push{r0,r1}\n"
                        "MOV R0,0X01 \n"
                        "ISB SY\n"
                        "PLI [R0]\n"
                        "ISB SY\n"
                        "pop {r0,r1}\n"
                );



__ASM  volatile (
                        "push {r0-r3,r12,lr} \n"
                        "MOV R0,0X01 \n"
                       "BLX R0 \n"
                        "pop {r0-r3,r12,lr} \n"
    );
中,將動態代碼存放于ITCM內存中,代碼就是實例代碼1,存放地址0x00
對于需要跳轉動態代碼時,保存寄存器是一個必不可少的的操作,通常使用堆棧保存,通常建議堆棧始終為8字節對齊(在cotex  M系列內核權威手冊里亦有記載) 所以在使用push的時候,建議一次性壓入兩個寄存器(64位)保持一直為8字節對齊.對于未對其的情況下,我也測試過了,首先效率會下降,對齊的情況,入棧8個字節僅需一個周期,無阻塞的發射,即可執行接下來的指令,未對其情況下,與使用STM  SP!{ }是等效的,需要1個周期解析指令+2個周期存入數據.

      其次未8字節對齊容易導致未定義行為,進入HardFault_Handler,這個問題隱藏的很隱蔽,使用Jlink單步調試是無法復現問題.(我沒記錯的話,權威手冊里應該有記載,不過容易忽略,這里就提個醒)
      對于地址跳轉,一定要保證,需要跳轉的地址的最低位一定要為1, 例如你需要跳轉到0x0800346,那么你實際要寫入PC指針的地址一定是0x0800347,而不是0x0800346,否則也會導致未定義行為,進入HardFault_Handler,同樣使用jlink無法復現,單步無法發現問題.


先記錄到這里,如有新的勘誤點會在更新,附件為cotex  M4系列內核匯編編程手冊,全冊中文,對于初學者來說很有用處

STM32F3與F4系列Cortex M4內核編程手冊_中文版.pdf

6.71 MB, 下載次數: 0, 下載積分: 黑幣 -5






歡迎光臨 (http://www.denmoz.com/bbs/) Powered by Discuz! X3.1