by Lou Zher
;-[ Div ]--------------------------------------------------------------
; call w/: Number in f_divhi:f_divlo
; Returns: Quotient in f_divlo, remainder in f_divhi. W preserved.
; Carry set if error. Z if divide by zero, NZ if divide overflow.
; Notes: Works by left shifted subtraction.
; Size = 29, Speed(w/ call&ret) = 9 cycles if div by zero
; Speed = 104 minimum, 142 maximum cycles
; Not compatible with the CARRYX option.
Div
or W, #0 ; w |= 0 (to test for div by zero)
setb C ; set carry in case of error
snb Z ; if zero
ret ; return (error C,Z)
call DivSkipHiShift
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
rl f_divlo ; C << lo << C
; If the first subtract didn't underflow, and the carry was shifted
; into the quotient, then it will be shifted back off the end by this
; last RLF. This will automatically raise carry to indicate an error.
; The divide will be accurate to quotients of 9-bits, but past that
; the quotient and remainder will be bogus and carry will be set.
clrb Z ; NZ (in case of overflow error)
ret ; we are done!
DivCode
rl f_divlo ; C << lo << C
rl f_divhi ; C << hi << C
sb C ; if Carry
jmp DivSkipHiShift ;
sub f_divhi, W ; hi-=w
setb C ; ignore carry
ret ; done
; endif
DivSkipHiShift
sub f_divhi, W ; hi-=w
snb C ; if carry set
ret ; done
add f_divhi, W ; hi+=w
clrb C ; clear carry
ret ; done
Comments: