MC6800のプログラミングテクニック(11) シフト操作の高速化

2024/12/30BASICMASTER, 昔のパソコン

複数回の左右シフト操作を効率化したい。例えば、AccABを左に8bitシフトする場合は、TBAが使える。

LSLB/ROLA が4クロック必要なので、普通に書くと32cyc,16bytes必要。下記の方法なら 4cyc, 2bytesである

厳密にはフラグの立ち方が異なるが、コンパイラで使うならこれで十分。


	tba
	clrb


右シフト 8回の場合

unsigned 16bitは簡単である。


	tab
	clra

signed の場合は最上位ビットが0か1かを見る必要がある。普通に書くとこうなる。分岐あり(正数)で10cyc, 無し(負数)は12cyc, 6bytes.

TABの時にNフラグが変化しているのに、それを捨てているのが勿体無いが、CLRAでもLDAA #0でもNが消えるので仕方がない。


	tab
	clra
	tstb
	bpl pos
	coma
pos:

符号拡張するいつもの方法。10cyc,6bytes。少しだけ速い。


	tab
	clra
	asrb
	rolb
	suba #0

追記(2025/01/03): TABの時に変化したNフラグを使う方法を思いついた。8 or 10cycle, 5bytes。短くて速い。

tab すると AccA == AccB なので、sba すれば 0 になる。負数のときに deca しておけば、AccAが$FFになる。


	tab
	bpl	plus
	deca
plus:	sba


左シフトのバリエーション

1,2,3,4,5 回までは単純に aslb/rola を繰り返せば良い。実行時間はシフト数*4, バイト数はシフト数*2。

8回以上は、TBAしてシフトする。


	tba
	clrb
	lsra
	rolb
	lsra
	rolb
	lsra
	rolb

14-15回シフトはLSBをMSBに持ってくれば良い。15回の場合 8cyc, 5bytes。14回だとlsrb/roraが増えて12cyc,7bytes。13回はTBA+左シフトが勝る。


	lsrb
	rora
	anda #$80
	clrb

7回シフトはTBAと組み合わせる。10cyc, 6bytes。1bitはC経由で移動できるのがミソ。


	lsra
	tba
	rora
	rorb
	andb #$80

6回の場合。psha/tba/pulbで、AccABを入れ替える。この状態で2bit分右rotateすることで、元のAccAの下位2bitをMSB 2bitに移動する。22cyc, 10bytes


	psha
	tba
	pulb
	lsrb
	rora
	rorb
	rora
	rorb
	andb #$c0
回数単純法TBA+LSRB/RORATBA++
14, 2
28, 4
312, 6
416, 8
520, 10
624, 1222, 10
728, 1410, 6
84, 2
98, 4
1012, 6
1116, 8
1220, 1020, 11
1324, 1216, 9
1428, 1412, 7
1532, 168, 5

5,6,12回は20cycle以上かかって遅い。うまい方法はないだろうか?