Code: Select all
LDX #$09I think that 27 bytes for a 32x32->64 multiply is pretty good, so it will be interesting to see if you or one of the usual suspects around here can improve it further!
Code: Select all
LDX #$09Code: Select all
LDX #$09Code: Select all
;imul: FACA = FACA × FACB (64 bit integer multiplication)
;
; —————————————————————————————————————————————————
; Preparatory Ops : FACA: 32 bit multiplicand
; FACB: 32 bit multplier
;
; Computed Returns: FACA: 64 bit product
; FACB: entry value
;
; Register Usage : .A: used
; .B: used
; .X: used
; .Y: truncated to 8 bits
;
; MPU Flags: NVmxDIZC
; ||||||||
; |||||||+———> 0
; ||||||+————> undefined
; |||||+—————> entry value
; ||+++——————> 0
; ++—————————> undefined
;
; Notes: 1) Product is undefined if either operand
; is greater than $FFFFFFFF.
; 2) A call to CLRFACA must be made before
; FACA is loaded with the multiplicand.
; —————————————————————————————————————————————————
;
imul longa ;16 bit accumulator
shortx ;8 bit index
cld ;ensure binary mode
ldx #s_bdword+1 ;bits to process +1
clc
;
.0000010 ror faca+s_long+s_word;rotate...
ror faca+s_long ;out...
ror faca+s_word ;a...
ror faca ;bit
bcc .0000020 ;0, skip ahead
;
clc
lda faca+s_long ;partial product
adc facb ;multiplier
sta faca+s_long ;new partial product
lda faca+s_long+s_word;ditto
adc facb+s_word ;ditto
sta faca+s_long+s_word;ditto
;
.0000020 dex
bne .0000010 ;next bit
;
longx ;16 bit index
rtsCode: Select all
;idiv: FACA = FACA ÷ FACB (64 bit integer division)
;
; —————————————————————————————————————————————————
; Preparatory Ops : FACA: 64 bit dividend
; FACB: 64 bit divisor
;
; Computed Returns: FACA: 64 bit quotient
; FACB: entry value
; FACC: used
;
; Register Returns: .A: used
; .B: used
; .X: remainder LSW
; .Y: remainder MSW
;
; MPU Flags: NVmxDIZC
; ||||||||
; |||||||+———> 0: quotient valid
; ||||||| 1: division by zero
; ||||||+————> 0: remainder != zero
; |||||| 1: remainder == zero
; |||||+—————> entry value
; ||+++——————> 0
; ++—————————> undefined
;
; NOTES: 1) All values are in little-endian format.
; 2) The remainder will also be in _OVRFLO_.
; —————————————————————————————————————————————————
;
idiv longa ;16 bit accumulator
shortx ;8 bit index
cld ;ensure binary mode
jsr clrfacc ;clear tertiary accumulator
jsr clrovrfl ;clear overflow
ldx #s_dlong-s_word
;
;
; perform divide-by-zero check...
;
.0000010 lda facb,x
bne idiv01
;
.rept s_word ;decrement .X twice
dex
.endr
bpl .0000010
;
tax
tay
longx
sec ;division by zero error
rts
;
idiv01 ldy #s_blword
clc
;
.0000010 phy
ldx #0
ldy #_loopct_
;
.0000020 rol faca,x
.rept s_word
inx
.endr
dey
bne .0000020
;
ldx #0
ldy #_loopct_
;
.0000030 rol _ovrflo_,x
.rept s_word
inx
.endr
dey
bpl .0000030
;
ldx #0
ldy #_loopct_
sec
;
.0000040 lda _ovrflo_,x
sbc facb,x
sta facc,x
.rept s_word
inx
.endr
dey
bne .0000040
;
bcc .0000060
;
ldx #_loopct_
;
.0000050 lda facc,x
sta _ovrflo_,x
.rept s_word
dex
.endr
bpl .0000050
;
.0000060 ply
dey
bne .0000010
;
tyx
ldy #_loopct_
;
.0000070 rol faca,x
.rept s_word
inx
.endr
dey
bne .0000070
;
longx
ldx _ovrflo_
ldy _ovrflo_+s_word
txa
ora _ovrflo_+s_word
clc
rts