Divide 48 bit int by 23 bit int to 48 bit int
by Nikolai Golovchenko
Dividend DS 6
Divisor DS 3
Temp DS 3
BitCount DS 1
;**********************************************************************
;
;48 BY 23 BIT UNSIGNED DIVISION (Non-restoring method)
;
;**********************************************************************
;
; Input: Dividend, 6 bytes (Dividend+0 MSB, ... , Dividend+5 LSB)
; Divisor, 3 bytes (Divisor+0 MSB, ... , Divisor+2 LSB)
;
; Output: Dividend, 6 bytes (Dividend = Dividend / Divisor)
; Z - division by zero
; NZ - okay
;
; Temporary: Temp, 3 bytes - remainder
; BitCount, 1 byte - counter
;
; Size: 52 instructions
;
;Max timing: 3+5+6+28*48-2+7+3=1366 cycles
;
;**********************************************************************
DIVIDE_48by23
; Test for zero division
mov W, Divisor
or W, Divisor+1
or W, Divisor+2
snz
ret ; divisor = zero, not possible to calculate -
; return with set zero flag (Z)
; clear remainder
clr Temp
clr Temp+1
clr Temp+2
mov W, #48 ; initialize bit counter
mov BitCount, W
stc ; set carry to perform subtraction
; first in the following loop
DIVIDE_LOOP_48by23
; shift in next result bit and
; shift out next bit of dividend
rl Dividend+5
rl Dividend+4
rl Dividend+3
rl Dividend+2
rl Dividend+1
rl Dividend
; shift in highest bit from dividend through carry in temp
rl Temp+2
rl Temp+1
rl Temp
mov W, Divisor+2 ; load w with LSB of divisor
; to use it in subtraction or
; addition afterwards
; If previous result bit was set (subtraction was performed
; without borrow or addition made the remainder positive),
; subtract divisor from remainder,
; else add divisor to remainder
sb Dividend+5.0
jmp Div48by23_add
; subtract 23 bit divisor from 24 bit temp,
; divisor LSB is in w
sub Temp+2, W ; subtract LSB
mov W, Divisor+1 ; get middle byte
sc ; if overflow ( from prev. subtraction )
movsz W, ++Divisor+1 ; incresase source
sub Temp+1, W ; and subtract from dest.
mov W, Divisor ; get top byte
sc ; if overflow ( from prev. subtraction )
movsz W, ++Divisor ; increase source
sub Temp, W ; and subtract from dest.
jmp DIVIDE_NEXT_48by23 ; jump to loop end
Div48by23_add
; add 23 bit divisor to 24 bit temp
; divisor LSB is in w
add Temp+2, W ; add LSB
mov W, Divisor+1 ; middle byte
snc ; check carry for overflow from previous addition
movsz W, ++Divisor+1 ; if carry set we add 1 to the source
add Temp+1, W ; and add it if not zero
mov W, Divisor ; MSB byte
snc ; check carry for overflow from previous addition
movsz W, ++Divisor
add Temp, W ; add
DIVIDE_NEXT_48by23
; carry contains next result bit
decsz BitCount ; decrement loop counter (carry not influenced)
jmp DIVIDE_LOOP_48by23 ; another run
; finally shift in the last carry
rl Dividend+5
rl Dividend+4
rl Dividend+3
rl Dividend+2
rl Dividend+1
rl Dividend
clz ; done, clear zero flag (NZ) and
ret ; return
;**********************************************************************