R3000特訓講座
第6号(校正中)

更新日付 1998-03-05

今回は掛け算、割り算、それからテーブル参照をやります。
三角関数も登場しますが、心配はいりません。
中卒の私でも理解できるレベルです。
最終回で作るプログラムへの布石です。

[戻る]


・掛け算と割り算

R3000には、掛け算と割り算の命令があります。
しかし掛け算と割り算は難しいので、
RISC-CPUといえど1クロックでは計算が終わりません。
そこで、乗除算は専用の回路に押し付けて、
CPUは自分の仕事を黙々とこなします。
こうすることで、パイプラインを止めることなく、
命令を実行することができるのです。

掛け算...mult, multu
割り算...div, divu
	mult	t0,t1		#HI:LO = t0 * t1
	div	t0,t1		#HI=t0 / t1、LO=余り
ここでHIとLOという謎のレジスタが登場しました。
HIとLOは共に32bitのレジスタで、乗除算の結果が入ります。
というわけで、乗除算には遅延があります。
遅延時間をうまく利用すれば、より高速なプログラムが組めそうです。

HI:LOの転送...mfhi, mflo
	mflo	t0		#t0 = LO
覚え辛い命令ですが、「Move From LO」と考えれば、
そのまんまやんけ〜と、突っ込みたくなるでしょう。
それでは、プログラムに入ります。

問題61.t0に半径を入れて呼び出すと、円の面積を返すサブルーチン。
 面倒なので面積は32bit以内、面積の計算式は半径×半径×3とする。
-------------------------------------------------------------------
circle:
	addi	sp,sp,-4	#スタック確保
	sw	ra,$0000(sp)	#ra保存

	mult	t0,t0		#HI:LO = 半径×半径
	li	at,3		#掛け算の待ちを利用してロード
	mflo	t0		#t0 = LO(半径×半径)
	mult	t0,at		#半径×半径×π
	mflo	t0		#t0 = 答え

	lw	ra,$0000(sp)	#ra復帰
	addi	sp,sp,4		#スタック開放
	jr	ra		#戻る
	nop			#遅延スロットを殺す
-------------------------------------------------------------------
それでは、次回のために予習をしておきます。

[戻る]


・テーブル参照

問題62.t0に角度を入れて呼び出すと、
 t0に「tan t0」を返すサブルーチン。

tan xをまじめに計算する必要はありません。
答えは0°〜89°まで、すべてテーブルとして用意しておき、
t0番目の値を取り出すだことにします。
一つの値が1ワード(4バイト)とすれば、
テーブル先頭+t0×4番地から、値をロードすればいいのです。
-------------------------------------------------------------------
tantan:
	addi	sp,sp,-4	#スタック確保
	sw	ra,$0000(sp)	#ra保存

	la	at,_tan		#テーブルの先頭アドレスをロード
	sll	t0,t0,2		#オフセットの計算、左シフト2回=4倍
	add	at,at,t0	#先頭アドレス+オフセット
	lw	t0,$0000(at)	#答えをロード

	lw	ra,$0000(sp)	#ra復帰
	addi	sp,sp,4		#スタック開放
	jr	ra		#戻る
	nop			#遅延スロットを殺す

_tan:
	dw	$00000000,$xxxxxxxx,$xxxxxxxx,...
-------------------------------------------------------------------
tanの一つの値は、1ワード(4バイト)あります。
よってt0の値を4倍しなければなりません。
これは掛け算ではなく、左シフトでやります。

今度はテーブル参照を応用して、
ジャンプテーブルに挑戦します。

問題63.t0が1=pochi、2=tama、3=jiro、4=tanu...というように、
 ジャンプテーブルを使って分岐するプログラム。
-------------------------------------------------------------------
	la	at,_jump	#ジャンプテーブル先頭
	sll	t0,t0,2		#t0×4(オフセットを計算)
	add	at,at,t0	#テーブル先頭+オフセット
	lw	at,$0000(at)	#ジャンプアドレスをロード
	nop			#ロード完了を待つ
	jr	at		#at番地へジャンプ
	nop			#遅延スロットを殺す
_jump:
	dw	pochi, tama, jiro, tanu...
-------------------------------------------------------------------
ロード完了を待つところに、ちゃんとnopを入れられましたか?
ちなみにこの部分を「srl t0,t0,2」なんてやると、
t0を元に戻すことになり、破壊レジスタを減らせます。

[戻る]


・おまけ

書き切れなかったことを補足しておきます。
この欄に書かれている内容は無理に覚える必要はありません。

・HIとLOの転送命令

上ではHIとLOからの転送しかやっていないのですが、
その逆も用意されているので、全部で4種類あります。
HIやLOにレジスタの値を転送したところで、
どういう利点があるのかは不明です。

・食品添加物

三重県四日市市には永餅という和菓子があります。
細い餅の中に甘さ控えめの餡を入れ、それを焼いたものです。
昔の永餅は日がたつとすぐに固くなり、
私はそれを焼き直して食べるのが大好きでした。
しかし、今は食品添加物として酵素が入っており、
いつまでたってもふにゃふにゃで固くなりません。
やはり食品添加物はよくありません。

永餅を作っている和菓子屋は二つあります。
どちらの店も互いに「本家」を名乗っています。

[戻る]


お仕事ください(笑)... koh@inetmie.or.jp