Z80 vs 6502
目次
Z80 ループ展開
そこで、「6502 のプログラムは結構長い(28バイト)ので、同程度のサイズまでループ展開させてもらった」というのが次のプログラム。
LD HL,#0 ; 10 (11)
LD BC,#100 ; 10 (11)
LOOP:
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JR Z,EXIT ; 12 / 7 (13 / 8)
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JR Z,EXIT ; 12 / 7 (13 / 8)
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JR Z,EXIT ; 12 / 7 (13 / 8)
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JR Z,EXIT ; 12 / 7 (13 / 8)
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JP NZ,LOOP ; 10 / 10 (11 / 11)
EXIT:
全体としては 27バイトで、6502 のプログラムよりは短いです。
基本形としては先に挙げたものと同じなのですが、見て判る通り、ループ内のプログラムを繰り返しています。
「ループ展開」というテクニックです。
今の CPU では、キャッシュにプログラムが収まっているのが最速なので、プログラムは小さいほうが速いです。
しかし Z80 の時代にはキャッシュなどないため、ループ回数を減らしてオーバーヘッドを無くす、というのが高速化手法として有効でした。
とはいえ、このプログラムでは、どこで終了条件が来るかわからないため、条件分岐を多数入れています。
ループの条件判断より高速化されるようになっていますが、このオーバーヘッドが結構大きい。
前処理が 22 クロック。
ループ内が、基本単位 25 クロックを5回繰り返しているのですが、最後だけ 28 クロックなので 25*4 + 28 = 103 クロック。
これを 25 回繰り返すので、 103 * 25 = 2575 クロック。
合計で、2582 クロック。ファミコンより速くなりました。
Z80 条件省略
…もう一ひねりしてみます。これは投稿されたものではなく、僕の方で作ったもの。
LD BC,#100 ; 10 (11)
LD HL,#0 ; 10 (11)
LD A,C ; 4 (5)
AND #1 ; 7 (8)
JR NZ,MOD1 ; 12 / 7 (13 / 8)
LOOP:
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
MOD1:
ADD HL,BC ; 11 (12)
DEC C ; 4 (5)
JP NZ,LOOP ; 10 / 10 (11 / 11)
前処理が長くなったのでループ展開が1回に減ってしまった…でも、これで 28byte 。
前処理の中で「端数」が出るかどうかを確認し、端数がある場合はループの途中に飛び込んでいます。
なので、ループの最後以外では終了条件の確認が不要になっています。
これも、不定回ループを展開するときの基本テクニックでした。
前処理が 43 クロック。ループ内が 45クロックで、50回繰り返しますから 45*50 = 2250 クロック。
合計で、2293 クロックです。
次の例題は…掛け算