;-[ Div ]--------------------------------------------------------------
; Call w/: Number in f_divhi:f_divlo, divisor in W.
; 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) = 7 cycles if div by zero
; Speed = 94 minimum, 129 maximum cycles
Div
iorlw 0 ; w |= 0 (to test for div by zero)
setc ; set carry in case of error
skpnz ; if zero
return ; return (error C,Z)
call DivSkipHiShift
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
call DivCode
rlf f_divlo, f ; 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.
clrz ; NZ (in case of overflow error)
return ; we are done!
DivCode
rlf f_divlo, f ; C << lo << C
rlf f_divhi, f ; C << hi << C
skpc ; if Carry
goto DivSkipHiShift ;
subwf f_divhi, f ; hi-=w
setc ; ignore carry
return ; done
; endif
DivSkipHiShift
subwf f_divhi, f ; hi-=w
skpnc ; if carry set
return ; done
addwf f_divhi, f ; hi+=w
clrc ; clear carry
return ; done
Questions: