R3000特訓講座
第2号
更新日付 1998-03-03
R3000のレジスタについて説明します。
英語を身に付けるには話すのが一番です。
単語ばかり覚えていても意味がありませんから、
さっそくプログラミングに挑戦してみましょう。
・R3000のレジスタ
R3000には$0〜$31の32本のレジスタがあります。
これらは基本的に同じ能力を持っていますが、
それでは使いにくいので、レジスタに名前を付けてあります。
レジスタのビット幅は32bitです。
レジスタ |
呼び名 |
用途 |
$0 |
zero |
常に0。あんたそれでもレジスタか? |
$1 |
at |
アセンブラで使用。
命令を最適化する際に使われる。
|
$2〜$3 |
v0〜v1 |
汎用、好きにして〜。 |
$4〜$7 |
a0〜a3 |
汎用、アドレスを入れると○ |
$8〜$15 |
t0〜t7 |
汎用、好きにして〜。 |
$16〜$23 |
s0〜s7 |
汎用、カーネルを呼び出しても保存される。
もちろんプレステでも同じ。
|
$24〜$25 |
t8〜t9 |
汎用、好きにして〜。 |
$26〜$27 |
k0〜k1 |
カーネルで使用。
プレステだとk1は使われていない。
|
$28 |
gp |
グローバルポインタかな。
Cコンパイラがワーク参照のために使用。
|
$29 |
sp |
スタックポインタです。 |
$30 |
s8、fp |
フレームポインタかな。
サブルーチンごとのローカルなワークを参照。
|
$31 |
ra |
サブルーチンからの戻り番地を記憶。 |
・単位
Z80 |
68000 |
65816 |
R3000 |
バイト |
バイト |
バイト |
バイト |
2バイト |
ワード |
ワード |
ハーフワード |
4バイト |
ロングワード |
4バイト |
ワード |
R3000とは関係ありませんが、4ビットのことを1ニブルといいます。
覚えておくとひじょうに便利な単位ですが、
英和辞典にも載っていないようです。
優秀なハッカーの資料を漁っているとたまに出てくる単語です。
・プログラミング
では、そろそろプログラムを組んでみることにしましょう。
まだ一つも命令を覚えていませんが、
できあがったプログラムを見て「覚えて」ください。
問題1.pochi番地からtama番地までをゼロクリアする。
ただし、pochi番地<tama番地とする。
--------------------------------------------------------------------
la a0,pochi #a0にpochiをロード
la a1,tama+1 #a1にtamaをロード
_loop:
sb zero,$0000(a0) #zeroを$0000+a0番地へストア(バイト)
addi a0,a0,1 #a0 = a0 + 1
bne a0,a1,_loop #a0≠a1なら_loopへ分岐
nop #遅延スロットを殺すためのnop
--------------------------------------------------------------------
普通にプログラムすると、このようになります。
laはロード-アドレスという命令です。
別にliと記述してもいいのですが、
アドレスとして使うときはlaと記述した方がいいです。
ゼロクリアするには、$00をストアすればいいので、
常にゼロという、お笑いレジスタzeroをストアします。
sbというのは、ストア-バイトという意味で、
$0000(a0)、つまり$0000+a0番地に$00をストアします。
1バイトのゼロクリアができました。
次に備えて番地を進めます。
addというのは加算命令で、
add-iの「i」はイミディエイト(即値)を意味します。
もし「i」を忘れると1番地の内容を加算することになります。
つまりa0=a0+1ということです。
bneはブランチ-ノット-イコール、
等しくなければ分岐という意味です。
レジスタa0とa1を比較して、等しくなければ分岐します。
分岐命令は勢い余って次の1命令を実行してしまいます。
これを「遅延スロット」というんでしたね。
ここに続く命令によってはプログラムが誤動作するので、
無難なところで、何もしない命令nopを記述しておきます。
さてお立ち会い。
遅延スロットのところにnopを入れました。
ここは、影響を与えない命令なら何を置いてもかまいません。
たとえば、
addi a0,a0,0 #a0=a0+0
でもかまいません。
レジスタa0に0を加えるのですから、悪影響はありません。
これは大ヒントです。
というわけで、さっきのプログラムを高速化してください。
・ちょっとマシなプログラム例
--------------------------------------------------------------------
la a0,pochi #a0にpochiをロード
la a1,tama #a1にtamaをロード
_loop:
sb zero,$0000(a0) #zeroを$0000+a0番地へストア(バイト)
bne a0,a1,_loop #a0≠a1なら_loopへ分岐
addi a0,a0,1 #a0=a0+1(分岐命令と一緒に勢い余って実行される)
--------------------------------------------------------------------
以上のように、アセンブラをうまく使うには、
遅延スロットの使い方が大切になります。
まともなCコンパイラは遅延スロットの使い方がうまいので、
タコなアセンブラ使いよりも速いコードを吐き出します。
アセンブラを使うのは、おそらく処理速度が必要な場面です。
なのにCコンパイラに負けたんじゃ話になりません。
というわけで、目下のライバルはCコンパイラですね。
お仕事ください(笑)...
koh@inetmie.or.jp