Language

Wednesday, February 22, 2012

gcc for Andes compile 出來的 assembly


為了要做 24-bit signed integer to 32-bit signed integer 的 signed extension 測試,我寫了以下的一小段 code 來測試, 在這裡順便稍微提一下 optimization, 我們先看 c code:




void testSign()
{
unsigned int test=0x00800000;
int test_s;
test_s = ((int)test << 8 ) >> 8;
}





除去 prologue 或 epilogue 的部份,我們來看主體:




00000614 <testSign>:
......
61c: 46 00 08 00 sethi $r0,#2048
620: 14 0e 7f fd swi $r0,[$fp+#-12]
624: 04 0e 7f fd lwi $r0,[$fp+#-12]
628: 40 00 20 08 slli $r0,$r0,#0x8
62c: 90 08 srai45 $r0,#0x8
62e: 14 0e 7f fe swi $r0,[$fp+#-8]




解釋如下:


sethi $r0,#2048

$r0 = 0x00800000

swi $r0,[$fp+#-12]

把 $r0 存回 test 的儲存空間

lwi $r0,[$fp+#-12]

把變數 test 值抓到 $r0

slli $r0,$r0,#0x8

把 $r0 做 logical left shift by 8 bits, $r0 = 0x80000000

srai45 $r0,#0x8

把 $r0 做 arithmetic right shift by 8 bits, $r0 = 0xff800000

swi $r0,[$fp+#-8]

存回 tests 的儲存空間。





而如果我們把這個 c code 改成如下:




int testSign(unsigned int value)
{
return ((int)test << 8) >> 8;
}





產生出來的 assembly 就會變成:




000005f8 <testSign>:
5f8: 40 00 20 08 slli $r0,$r0,#0x8
5fc: 90 08 srai45 $r0,#0x8
5fe: dd 9e ret5 $lp




這個版本完全沒有任何 local variables, 傳入的參數也只有一個, 當傳入參數
只有一個的時候, 會使用 $r0 這個暫存器傳入, 回傳值也是在 $r0 回傳,
所以這樣子最省空間了,也是我們 assembly programmer 會寫出來的樣子。注意
如果沒有做 (int) 的 explicit cast, 編譯器並不會使用 srai45 這個
arithmetic right shift 指令製造 signed extension, 即便是最後的回傳值是
有號數。


--
My Emacs Files At GitHub