割り算
目次
6502基本
作るのが面倒なので、6502 は「基本」として引き放し法を示します (^^;
変数などは次のようになっています。
>0 >1 被除数
>2 >3 除数
>4 >5 商
X ループカウンタ
LDA #>12345 ; 2
STA >0 ; 3
LDA #<12345 ; 2
STA >1 ; 3
LDA #0 ; 2
STA >2 ; 3
STA >4 ; 3
LDX #7 ; 2
LDA #10 ; 2
PRE:
INX ; 2
ASL A ; 2
BPL PRE ; 3 / 2
STA >3 ; 3
CLC ; 2
PLUS:
LDA >0 ; 3
SBC >2 ; 3
STA >0 ; 3
LDA >1 ; 3
SBC >3 ; 3
STA >1 ; 3
BMI MINUS_AFTER ; 3 / 2
PLUS_AFTER:
ASL >4 ; 5
ROL >5 ; 5
INC >4 ; 5
LSR >3 ; 5
ROR >2 ; 5
DEX ; 2
BNE PLUS ; 3 / 2
LDA >0 ; 3
BCC END ; 3 / 2
MINUS:
LDA >0 ; 3
ADC >2 ; 3
STA >0 ; 3
LDA >1 ; 3
ADC >3 ; 3
STA >1 ; 3
BPL PLUS_AFTER ; 3 / 2
MINUS_AFTER:
ASL >4 ; 5
ROL >5 ; 5
LSR >3 ; 5
ROR >2 ; 5
DEX ; 2
BNE MINUS ; 3 / 2
LDA >0 ; 3
ADC >2 ; 3
END:
; >4 >5 に商、A に剰余
前処理の「左詰め」では、最上位ビットを見られるために、Z80 で生じる「無駄な」処理が無くなっています。
(Z80 では、追い出されてキャリーに入るまで分からないため、行き過ぎて戻る、2回の無駄なローテート動作が生じてしまう)
そのほかはほぼ同じ。ただし、16bit の扱いが苦手な 6502 では、8bit の演算を繰り返して 16bit にしています。
前処理 22クロック
左詰め処理は、1bit 左詰めにつき、7 クロック。
その後、次への準備などで 4 クロック。
Z80 と異なり、無駄なローテートは生じず、4bit 詰めて終わります。
7*4 +4 = 32 クロック。
1桁分の計算は、結果がプラスの時、 50 クロック(最後だけ +5)、マイナスの時、 45 クロック(最後だけ +5)。
ただし、結果が同じ符号で連続しなかった時は、処理の切り替えに +1 クロック。
Z80 と同じように計算すると、次のようになります。
22 + 32 + 50*8 + 45*5 +5 +8 = 692
総計 692クロック
速度判定
6502 は 692 クロック。周波数を考慮して倍にすると、MSX での 1384クロック相当の実時間になります。
Z80 は 1296クロックなので、差は88クロック。MSXが 6%ほど速いです。
6% なら、ほぼ同等の速度。ちょっとした高速化アイディアでひっくり返るかもしれません。
除算の場合、もっと優れたアルゴリズムも考案されているのですが、16bit/8bit 程度に使うには大げさすぎてかえって遅いかも?