MC6800のプログラミングテクニック(11) シフト操作の高速化
複数回の左右シフト操作を効率化したい。例えば、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/RORA | TBA++ |
---|---|---|---|---|
1 | 4, 2 | |||
2 | 8, 4 | |||
3 | 12, 6 | |||
4 | 16, 8 | |||
5 | 20, 10 | |||
6 | 24, 12 | 22, 10 | ||
7 | 28, 14 | 10, 6 | ||
8 | 4, 2 | |||
9 | 8, 4 | |||
10 | 12, 6 | |||
11 | 16, 8 | |||
12 | 20, 10 | 20, 11 | ||
13 | 24, 12 | 16, 9 | ||
14 | 28, 14 | 12, 7 | ||
15 | 32, 16 | 8, 5 |
5,6,12回は20cycle以上かかって遅い。うまい方法はないだろうか?
ディスカッション
コメント一覧
まだ、コメントがありません