2007年10月30日 星期二

ARM GCC inline assembler

緣起:
有關在ARM的平台上開發embedded system,在trace UBoot或是Linux Kernel,在C的程式碼中總是會嵌入一些assembly code,舉例如下


廣布UBoot source中,也不知道這是幹嗎的


隨便再去找個例子,不過這段code就很好猜,基本上就是delay幾個machine cycle


include/asm-arm/spinlock.h
這是Linux Kernel 中 spinlock的程式碼

原本想偷懶,就大概看看猜猜意思就好,但是發現了還真怪,跟標準ARM的assembly language有一些差距,舉例如下%0, %1, %2到底是啥register,ARM不就是R1~R15 PC這些嗎?還有第一個例子,還真的很不懂他的意義

後來根據上課的講義中的參考網站
ARM GCC Inline Assembler Cookbook
這真是好網站啊....
以下為那篇的簡單心得

心得:
1. 為什麼要在GNU C compiler提供內嵌式assembly code?
ANS:因為可以自行最佳化critical部份的code,有些想做的事很難用C語言來寫,用assembly language卻事半功倍(例如delay幾個machine cycle)

2. GCC ASM statement
分成4部分
1. The assembler instruction
2. output operands
3. input operands
4. Clobbered(打倒毀壞..) register ....(P.S. 描述哪些register或是記憶體被assembly code破壞掉了 請compiler要特別處理後面的code)

拿幾個例子


四個部份用冒號(:)來區分
"mov %0, %1, ror #1"是assembly instruction部份
"=r" (result) 是output operands
"r" (value)是input operands
此範例沒有clobber list所以就直接省略掉

這範例的意思
將value 向右rotate 1 bit然後存到 result

GNU C compiler處理後可能會編成


3. 甚麼是%0, %1, %2 ....?有甚麼好處?
ANS:從output operands 到 input operands一路編號從%0, %1 .... %n
剛剛的範例GNU C compiler可以自由的拿r3來使用,他會根據compile到這行取用compiler覺得最好的register,因為我們並不在意到底是r1還是r2 or r3,就讓compiler做吧

4. volatile關鍵字?

告訴compiler別optimize這段程式,不然可能會跟據最佳化法則直接不編譯

這樣一來這些例子就都看得懂囉

tiny delay


只有第四部份 clobber part說明memory可能被更動了,之後compiler要視為memory有更動,任何需要載入register處理都要真的做ldr的動作,不能直接拿暫存的register來用(如果之前已經在register中了)
這很適合用到memory mapping I/O才會真正把一些Hardware狀態取出

5. Input/Output Operands的修飾子
r是代表general register
"r", "=r", "=&r" 在r前面不加東西或是加= or &
不加代表此register是read-only
=為write-only
&代表Register shoud be used for output only

所以很簡單的在output operads 都會有"=" 如果只有output only就可以在多加"&"
input operand的都不用加

至於既是input又是output則有特別作法
舉個範例
asm volatile("mov %0, %0, ror #1" : "=r" (value) : "0" (value));
就用"0"來代表

6. Clobber list
剛剛已經看過一個範例了(有關在控制Hardware memory mapping IO)
另外
asm ("":::"cc", "r3");
則是說明我們在asembly language已經破壞r3,請compiler在進來前跟出去後要自己保證r3的正確性

7.__asm__, __volatile__?
為什麼會用__asm__取代asm,用__volatile__取代volatile
這些有底線的都是因為我們通常會define成macro,但如果直接用asm or volatile會在strict ANSI compile下會出現warning所以使用加底線的版本,但其實是一樣的
(這部份其實我並不是很了解啊)WHY

沒有留言: