R3000特訓講座
第4号


更新日付 1998-03-03

68000でおなじみの符号拡張について説明します。
ネイティブ命令でコーディングするのであれば、
符号拡張を利用することで命令数を減らすことができます。
結果的にプログラムの高速化が図れます。

[戻る]


・符号拡張

addiは16bitの即値を32bitに符号拡張し、レジスタに加算する命令です。
この符号拡張というのはいったい何でしょう。

-1という値を8bitで表わすと$ffになります。
しかし16bitで表わすと$ffffです。決して$00ffではありません。
このように、8bitの-1を16bitのレジスタに入れるなら、
値の補正をしなければなりません。
この処理を「符号拡張」といいます。

問題0.ハーフワードの値を符号拡張してワード値とせよ。
 値の最上位ビットは符号ビットです。
 そのビットを拡張する部分にコピーすればできあがりです。
   (1)$1234 = $00001234
   (2)$6809 = $00006809
   (3)$e000 = $ffffe000
   (4)$8931 = $ffff8931
ようするに、16進数の最上位が8以上ならfで埋める。
そうでなければ0で埋めるということです。
addiではなく、addiuだと符号拡張がありません。
ゼロ拡張といって、上位は必ず0で埋められます。


・プログラミング

それでは、プログラミングに入ります。
符号拡張とはあまり関係ないのですが、気にしないでください。

問題1.scoreに入っているワード値を+100する。
 ワードの値をロードするにはlwを使います。
 前回はlbを使いましたが、アドレスの指定方法もlbと同じです。
--------------------------------------------------------------------
	la	a0,score	#アドレス
	lw	t0,$0000(a0)	#score番地のワード値をロード
	nop			#ロード完了までの時間待ち
★	addi	t0,t0,100	#t0 = t0 + 100
	sw	t0,$0000(a0)	#score番地にワード値をストア
--------------------------------------------------------------------

以下の問題は、★印がついている行だけを変更すれば完成します。


問題2.scoreに入っているワード値を-100する。
--------------------------------------------------------------------
	addi	t0,t0,-100	#t0 = t0 + 100
--------------------------------------------------------------------
R3000にはsubiという命令はありません。
100を引き算するには、-100を加算することになります。


問題3.scoreに入っているワード値を+$168000する。
--------------------------------------------------------------------
	li	t1,$00168000	#t1 = $00168000
	add	t0,t0,t1	#t0 = t0 + t1
--------------------------------------------------------------------
$168000は16bitで表すことができません。
そこで値を別のレジスタにロード(li)し、
レジスタ同士の足し算としてプログラムします。
即値ではなくレジスタ同士の足し算なので、
addiの代わりにaddという命令を使います。


問題4.scoreに入っているワード値を+$168000する。
 ただしマクロ命令の使用を禁止する。
 liはマクロ命令ですから、別の命令に置換すればいいですね。
--------------------------------------------------------------------
	lui	t1,$0016	#t1 = $00160000
	ori	t1,t1,$8000	#t1 = $00168000
	add	t0,t0,t1	#t0 = t0 + t1
--------------------------------------------------------------------
luiという命令はロード・アッパー・イミディエイトと読みます。
ハーフワードの即値をレジスタの上位にロードする命令です。
次は下位ハーフワードに残りの値をロードすると思いきや、
R3000には下位ハーフワードへのロード命令がありません。
そこで、代わりにoriを使います。
oriはハーフワードの即値と論理和をとる命令で、
luiによってできた下位$0000という部分に、値を入れてくれます。

oriの代わりに「add t1,t1,$8000」でもよさそうです。
しかしワードの即値$8000は、符号拡張により、
$ffff80000に変換されてしまうので失敗します。
そこで符号拡張しないadduを使って、
「addu t1,t1,$8000」とやれば、正しく動きます。

[戻る]


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