Divide 16 bit int by 8 bit int to 8 bit int and remainder
#define bf_carry 3, 0
#define bf_zero 3, 2
#define same 1
#define wreg 0
#define stc bsf bf_carry
#define clc bcf bf_carry
;-[ 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) = 7 cycles if div by zero
; Speed = 94 minimum, 129 maximum cycles
Div;
;*** WARNING: ADDLW was expanded in three instructions! Check if previous instruction is a skip instruction.
; addlw 0 ; w+=0 (to test for div by zero)
mov Hack, W
mov W, #0 ; w+=0 (to test for div by zero)
add W, Hack
stc ; set carry in case of error
snb bf_zero ; if zero
ret ; return (error C,Z)
call DivSkipHiShift
iDivRepeat = 8
while iDivRepeat
call DivCode
iDivRepeat--
endw
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 bf_zero ; NZ (in case of overflow error)
ret ; we are done!
DivCode
rl f_divlo ; C << lo << C
rl f_divhi ; C << hi << C
sb bf_carry ; if Carry
jmp DivSkipHiShift ;
sub f_divhi, W ; hi-=w
stc ; ignore carry
ret ; done
; endif
DivSkipHiShift
sub f_divhi, W ; hi-=w
snb bf_carry ; if carry set
ret ; done
add f_divhi, W ; hi+=w
clc ; clear carry
ret ; done