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は読み書きできない。
- 無理に読み書きすると、計算終了まで待たされる。
- 他の命令は実行できる。
というわけで、乗除算には遅延があります。
遅延時間をうまく利用すれば、より高速なプログラムが組めそうです。
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種類あります。
- mfhi...Move From HI
- mflo...Move From LO
- mthi...Move To HI
- mtlo...Move To LO
HIやLOにレジスタの値を転送したところで、
どういう利点があるのかは不明です。
・食品添加物
三重県四日市市には永餅という和菓子があります。
細い餅の中に甘さ控えめの餡を入れ、それを焼いたものです。
昔の永餅は日がたつとすぐに固くなり、
私はそれを焼き直して食べるのが大好きでした。
しかし、今は食品添加物として酵素が入っており、
いつまでたってもふにゃふにゃで固くなりません。
やはり食品添加物はよくありません。
永餅を作っている和菓子屋は二つあります。
どちらの店も互いに「本家」を名乗っています。
お仕事ください(笑)...
koh@inetmie.or.jp