BAKの日記: OpenBlockS266 めも
gcc におけるレジスタの使われかた
一般に RISC 系の石では
- 汎用レジスタ操作について,対称性がある
- 明示的なスタックポインタレジスタを持たない
という特徴がある.
で,gcc(や,おそらく他の C コンパイラも)の場合,対称性があるからと言って,空いているレジスタを片っ端から使うということはない.たいてい「このレジスタはこの役割」と,役割分担が決まっているものである.まぁ,サブルーチンコールとかがあるので,呼び出し元と呼び出し先でレジスタインターフェースが決まっていないといけないわけだから,ある意味当然とも言える.
MIPS の場合も,汎用レジスタは(r0 と r31 を除いてはほぼ)対称性がある.が,「このレジスタにはこういうニックネームを付けてこういう風に使うといいですよ」というガイドラインが MIPS 社より出ている.人間,ホントに自由だとかえって戸惑うもので,ある程度束縛されていた方か活動しやすい,というところはあるわけで.
この MIPS の「ニックネームと使い分けの表」は,Linux のカーネルソースにヘッダファイルとして添付されている.linux-2.4.20/include/asm-mips/regdef.h である.
で,問題の PowerPC であるが,Linux カーネルのヘッダファイルを漁ってみても残念ながらこのような一覧表は見当たらないようである.アセンブリ言語のソースを読んでみてもレジスタの名前が直書きされていて,ニックネームが使われている雰囲気はない.
というわけで,簡単なプログラムを書いてみた.
int function ( int arg0, int arg1, int arg2, int arg3, int arg4, int arg5 )
{
arg0 += 1234;
arg1 += 5678;
arg2 += 9012;
arg3 += 3456;
arg4 += 7890;
arg5 += 1111;return arg0 + arg1 + arg2 + arg3 +arg4 + arg5;
}
これを hoge.c という名前で保存し,コンパイルする.
powerpc-redhat-linux-gcc -O0 hoge.c -c
あ,これは x86 上のクロスコンパイル環境でやっているので,セルフ環境でやる時は,powerpc-redhat-linux- のプレフィクスは不要.あと,-O0 (おー・ぜろ)は,「最適化をしないでね」という,gcc へのお願いである.
そして,ディスアセンブル.
powerpc-redhat-linux-objdump -d hoge.o
結果はこちら.
hoge.o: file format elf32-powerpc
Disassembly of section .text:
00000000 <function>:
0: 94 21 ff d0 stwu r1,-48(r1)
4: 93 e1 00 2c stw r31,44(r1)
8: 7c 3f 0b 78 mr r31,r1
c: 90 7f 00 08 stw r3,8(r31)
10: 90 9f 00 0c stw r4,12(r31)
14: 90 bf 00 10 stw r5,16(r31)
18: 90 df 00 14 stw r6,20(r31)
1c: 90 ff 00 18 stw r7,24(r31)
20: 91 1f 00 1c stw r8,28(r31)
24: 81 3f 00 08 lwz r9,8(r31)
28: 38 09 04 d2 addi r0,r9,1234
2c: 90 1f 00 08 stw r0,8(r31)
30: 81 3f 00 0c lwz r9,12(r31)
34: 38 09 16 2e addi r0,r9,5678
38: 90 1f 00 0c stw r0,12(r31)
3c: 81 3f 00 10 lwz r9,16(r31)
40: 38 09 23 34 addi r0,r9,9012
44: 90 1f 00 10 stw r0,16(r31)
48: 81 3f 00 14 lwz r9,20(r31)
4c: 38 09 0d 80 addi r0,r9,3456
50: 90 1f 00 14 stw r0,20(r31)
54: 81 3f 00 18 lwz r9,24(r31)
58: 38 09 1e d2 addi r0,r9,7890
5c: 90 1f 00 18 stw r0,24(r31)
60: 81 3f 00 1c lwz r9,28(r31)
64: 38 09 04 57 addi r0,r9,1111
68: 90 1f 00 1c stw r0,28(r31)
6c: 81 3f 00 08 lwz r9,8(r31)
70: 80 1f 00 0c lwz r0,12(r31)
74: 7c 09 02 14 add r0,r9,r0
78: 81 3f 00 10 lwz r9,16(r31)
7c: 7c 00 4a 14 add r0,r0,r9
80: 81 3f 00 14 lwz r9,20(r31)
84: 7c 00 4a 14 add r0,r0,r9
88: 81 3f 00 18 lwz r9,24(r31)
8c: 7c 00 4a 14 add r0,r0,r9
90: 81 3f 00 1c lwz r9,28(r31)
94: 7c 00 4a 14 add r0,r0,r9
98: 7c 03 03 78 mr r3,r0
9c: 81 61 00 00 lwz r11,0(r1)
a0: 83 eb ff fc lwz r31,-4(r11)
a4: 7d 61 5b 78 mr r1,r11
a8: 4e 80 00 20 blr
ここから何となく読めるレジスタの役割分担は
- r0,r9: 作業用・破壊可能
- r1: スタックポインタ・破壊不可
- r3~r8: 関数の引数・破壊可能
r3 は関数の戻り値 - r11: 作業用(?)・破壊可能(?)
- r31: スタック上のワーク領域へのポインタ・破壊不可(?)
といった感じか.
OpenBlockS266 めも More ログイン