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