簡體   English   中英

AVR GCC 上的內聯匯編優化問題 (ATTiny1614)

[英]Inline assembly optimisation problem on AVR GCC (ATTiny1614)

我正在嘗試為 ATtiny1614 開發延遲函數(使用 AtmelStudio 7) 有一個現有平台 _delay_us() 可以做類似的事情,但這與能夠調整自己的代碼一樣是一種學習經驗。

為了延遲分辨率和最小且一致的延遲時間,我決定進行內聯組裝。

我做了以下內容:(片段)

__attribute__((__always_inline__)) static inline void delay_loops(volatile uint32_t numLoops) {
  asm volatile(
    "loop_1%=:          \n\t"
    "   subi %A[numLoops], 1    \n\t"
    "   sbci %B[numLoops], 0    \n\t"
    "   sbci %C[numLoops], 0    \n\t"
    "   sbci %D[numLoops], 0    \n\t"
    "   brcc loop_1%=       \n\t"       
    :                           
    :[numLoops] "d" (numLoops)              
    // d=select upper register (r16-31) only
  );
}

int main(void)
{
   ...

   delay_loops(10);
   delay_loops(12);

   ...
}

到現在為止還挺好。 一切都按預期工作,並生成以下代碼:

 3ec:   8a e0           ldi r24, 0x0A   ; 10
 3ee:   90 e0           ldi r25, 0x00   ; 0
 3f0:   a0 e0           ldi r26, 0x00   ; 0
 3f2:   b0 e0           ldi r27, 0x00   ; 0

000003f4 <loop_1333>:
 3f4:   81 50           subi    r24, 0x01   ; 1
 3f6:   90 40           sbci    r25, 0x00   ; 0
 3f8:   a0 40           sbci    r26, 0x00   ; 0
 3fa:   b0 40           sbci    r27, 0x00   ; 0
 3fc:   d8 f7           brcc    .-10        ; 0x3f4 <loop_1333>

 3fe:   8c e0           ldi r24, 0x0C   ; 12
 400:   90 e0           ldi r25, 0x00   ; 0
 402:   a0 e0           ldi r26, 0x00   ; 0
 404:   b0 e0           ldi r27, 0x00   ; 0

00000406 <loop_1341>:
 406:   81 50           subi    r24, 0x01   ; 1
 408:   90 40           sbci    r25, 0x00   ; 0
 40a:   a0 40           sbci    r26, 0x00   ; 0
 40c:   b0 40           sbci    r27, 0x00   ; 0
 40e:   d8 f7           brcc    .-10        ; 0x406 <loop_1341>

寄存器預先加載了給定的循環值,然后迭代該循環次數。

但是,如果我將主代碼更改為

  int main(void)
  {
    ...

    delay_loops(12);    // changed 10->12
    delay_loops(12);

    ...
  }

然后第二次延遲似乎是無止境的(或至少超出了我的邏輯分析器的范圍)。

編譯后的程序集顯示以下內容:

 3ec:   8c e0           ldi r24, 0x0C   ; 12
 3ee:   90 e0           ldi r25, 0x00   ; 0
 3f0:   a0 e0           ldi r26, 0x00   ; 0
 3f2:   b0 e0           ldi r27, 0x00   ; 0

000003f4 <loop_1332>:
 3f4:   81 50           subi    r24, 0x01   ; 1
 3f6:   90 40           sbci    r25, 0x00   ; 0
 3f8:   a0 40           sbci    r26, 0x00   ; 0
 3fa:   b0 40           sbci    r27, 0x00   ; 0
 3fc:   d8 f7           brcc    .-10        ; 0x3f4 <loop_1332>

000003fe <loop_1339>:
 3fe:   81 50           subi    r24, 0x01   ; 1
 400:   90 40           sbci    r25, 0x00   ; 0
 402:   a0 40           sbci    r26, 0x00   ; 0
 404:   b0 40           sbci    r27, 0x00   ; 0
 406:   d8 f7           brcc    .-10        ; 0x3fe <loop_1339>

輸入值 (12) 的初始化不是在 delay_loops() 的第二個“調用”中完成的。 程序集只是使用它仍然擁有的(改變的)寄存器值繼續第二個循環。 我只能假設編譯器不知道我更改了 r24..27 並假設它們仍然正確初始化為 12,因此優化了正確的初始化。

如何強制正確初始化?

謝謝

內聯匯編程序手冊解釋了如果您有一個操作數用於輸入和輸出時需要做什么。

按照他們的例子,我認為你應該嘗試用這樣的東西替換以冒號開頭的兩行:

:[numLoops] "=d" (numLoops)                          
:"0" (numLoops)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM