乗除算

65C816には乗除算機能が無いため、乗除算をする場合はI/Oポートを通してコプロセッサに値を渡して処理します。BGモード7の拡縮回転用マトリクスを使って計算しています。

「2の累乗を掛ける」、「2の累乗で割る」はそれぞれ左シフトと右シフトを繰り返せば可能なのでコプロセッサに値渡しをする必要性はあまりありませんが、24bit演算をする場合はコプロセッサに値渡しをする必要があります。

符号付8bit x 8bit

$4202に被乗数をセットします。
$4203に乗数をセットします。(このレジスタに値を入れると計算が始まります。最後に書き込んでください)
8CPUサイクル後に$4216-$4217に乗算結果(16bit)が入ります。

コード例
 
LDA  #$16
STA  $4202
LDA  #$24
STA  $4203
REP  #$20
NOP
LDA  $4216
0x16 x 0x24を計算してその結果(0x318)をAレジスタに取得します。このコードは以下のように書き換えることが出来ます。NOPは、計算が終わるまでの時間稼ぎに使っています。
 
LDA  #$2416
STA  $4202
NOP
NOP
LDA  $4216

符号付16bit x 8bit

$211Bに被乗数の下位バイトをセットします。
$211Bに被乗数の上位バイトをセットします。(このポートは2度書きレジスタとなっています)
$211Cに乗数をセットします。(このレジスタに値を入れると計算が始まります。最後に書き込んでください)
16CPUサイクル後に$2134-$2136に乗算結果(24bit)が入ります。

コード例
 
SEP  #$20
LDA  #$34
STA  $211B
LDA  #$12
STA  $211B
LDA  #$56
STA  $211C
REP  #$20
NOP
NOP
NOP
NOP
NOP
NOP
NOP
LDA  [$2134]
このコードは0x1234 x 0x56を計算し、その結果得られる24bit値(0x61D78)をアドレスとしたRAMの内容を16bit幅でロードします。最後の行で$61D78からの2バイトをAレジスタに読み込んでいます。

符号付16bit / 8bit

$4204-$4205に被除数をセットします。
$4206に除数をセットします。(このレジスタに値を入れると計算が始まります。最後に書き込んでください)
16CPUサイクル後に$4214-$4215に商、$4216に余りが入ります。
ゼロ除算を行った場合は、商は#$FFFF、余りは被除数となります。

コード例
 
LDA  #$6759
STA  $4204
SEP  #$20
LDA  #$35
STA  $4206
REP  #$20
NOP
NOP
NOP
NOP
NOP
NOP
NOP
LDA  $4214
LDX  $4216
このコードは0x6759 / 0x35を計算し、その商(0x1F3)をAレジスタに、余り(0xA)をXレジスタに読み込みます。

上に挙げた以外の乗除算を行う場合は、自分で演算ルーチンを組む必要があります。以下、拾い物のコード

符号なし16bit x 8bit

$00-$01に被除数をセットします
$02に除数をセットします
96CPUサイクル後に$00-$02に計算結果(24bit)が返ります。

コード例
 
LDY $02
LDA $00
JSR Multi_8
STY $02
PHA
LDY $01
JSR Multi_8_0
STA $00
TYA
CLC
ADC $02
STA $01
PLA
ADC #$00
STA $02
RTS

Multi_8:
STA $4202

Multi_8_0:
STY $4203
NOP
NOP
NOP
NOP
LDA $4216
LDY $4217
RTS

符号なし16bit x 16bit

$00-$01に被除数をセットします
$02-$03に除数をセットします
$00-$03に計算結果(32bit)が返ります。

コード例
 
LDA $03
LDY $01
JSR Multi_0
PHA
PHY
LDA $03
LDY $00
JSR Multi_0
STA $03
PHY
LDA $02
LDY $01
JSR Multi_0
STA $01
LDA $02
STY $02
LDY $00
JSR Multi_0
STA $00
TYA
CLC
ADC $01
STA $01
PLA
ADC $02
PLY
BCC Multi_1
INY

Multi_1:
STA $02
LDA $01
CLC
ADC $03
STA $01
PLA
ADC $02
BCC Multi_2
INY

Multi_2:
STA $02
STY $03
RTS

Multi_0:
STA $4202

Multi_3:
STY $4203
NOP
NOP
NOP
NOP
LDA $4216
LDY $4217
RTS

符号なし16bit / 16bit

$00-$01に被除数をセットします
$02-$03に除数をセットします
$06-$07に商(16bit)が、$00-$01に余り(16bit)が返ります。ゼロ除算を行った場合は商と余りに0xFFFFを返します。

コード例
 
REP #$20
LDA $00     ; 被除数
ASL A
STA $06     ; 結果
LDY #$0F
TDC

.Loop
ROL A
CMP $02
BCC .Skip
SBC $02

.Skip
ROL $06
DEY
BPL .Loop
STA $00
SEP #$20
RTS

偏角を求める

原点から目標点への偏角を求めます。コードとは別にarctanのテーブルを準備する必要があります。
$00-$01に原点とするX座標をセットします
$02-$03に原点とするY座標をセットします
$04-$05に目標点のX座標をセットします
$06-$07に目標点のY座標をセットします
$00-$01に偏角(0x0000-0x01FF)が返ります。
原点と目標点の座標の差が±0x1FF以上(以下)の場合は計算できません。

コード例
 
PHX
REP #$20
LDA $02
SEC
SBC $06
PHP
BPL IfPlus1
EOR.w #$FFFF
INC A

IfPlus1:
STA $02
LDA $00
SEC
SBC $04
PHP
BPL IfPlus0
EOR.w #$FFFF
INC A

IfPlus0:
STA $00
BEQ X_Zero
LSR A
TAY
LDA $02
BEQ Y_Zero
CMP.w #$0100
XBA
ROR A
AND.w #$FF80
STA $4204
STY $4206
STZ $00
LDA.w #$0040
STA $02
LDA $4214
STA $06

Loop00:
LDA $00
INY
ORA $02
ASL A
TAX
LDA $06
CMP.l GetTan,x
BCC Label00
LDA $02
TSB $00

Label00:
LSR $02
BCC Loop00
SEP #$20
PLA
EOR $01,s
db $43,$01
BPL Label02
LDA $00
EOR #$FF
INC A
STA $00
BNE Label02
INC $01

Label02:
PLP
BMI Label03
INC $01

Label03:
PLX
RTS

X_Zero:
LDA.w #$0080
STA $00
PLP
PLP
BMI IfPlus4
INC $01

IfPlus4:
PLX
RTS

Y_Zero:
STZ $00
PLP
BMI IfPlus5
INC $01

IfPlus5:
PLP
PLX
RTS

GetTan:
dw $0000,$0003,$0006,$0009,$000C,$000F,$0012,$0016
dw $0019,$001C,$001F,$0022,$0025,$0029,$002C,$002F
dw $0032,$0036,$0039,$003C,$0040,$0043,$0046,$004A
dw $004D,$0051,$0054,$0058,$005B,$005F,$0062,$0066
dw $006A,$006D,$0071,$0075,$0079,$007C,$0080,$0084
dw $0088,$008C,$0091,$0095,$0099,$009D,$00A2,$00A6
dw $00AB,$00AF,$00B4,$00B9,$00BD,$00C2,$00C7,$00CC
dw $00D2,$00D7,$00DC,$00E2,$00E8,$00ED,$00F3,$00F9
dw $0100,$0106,$010C,$0113,$011A,$0121,$0128,$0130
dw $0137,$013F,$0148,$0150,$0159,$0162,$016B,$0175
dw $017F,$0189,$0194,$019F,$01AB,$01B7,$01C3,$01D1
dw $01DE,$01ED,$01FC,$020C,$021D,$022E,$0241,$0255
dw $026A,$0280,$0297,$02B0,$02CB,$02E8,$0306,$0328
dw $034B,$0372,$039D,$03CB,$03FE,$0435,$0474,$04B9
dw $0506,$055E,$05C3,$0637,$06BD,$075C,$081B,$0904
dw $0A27,$0B9C,$0D8E,$1046,$145A,$1B26,$28BC,$517B