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