;;
;; Somewhat optimised math routines:
;; 16x16 -> 32 signed multiply
;; 16/16 -> 16,16 signed divide (with remainder)
;;
;; For PIC16 chips, without a hardware multiplier. I thought that Microchip
;; would surely provide an app note for this, but if they do then I can't
;; find it and I think these are good enough.
;;
;; I found the Atmel application note `AVR200: Multiply and Divide Routines'
;; very helpful in writing these routines.
;;
;; THESE ROUTINES ARE DISTRIBUTED WITHOUT WARRANTY, TO THE EXTENT PERMITTED
;; BY APPLICABLE LAW. The author assumes no liability for the correctness
;; of these routines. These routines are in the public domain. You may
;; use them for any purpose, commercial or non-commercial, with or without
;; attribution to the author.
;;
;; by Jonathan Westhues, Jul 2005
;;
;;;
;; 16x16 -> 32 signed multiply.
;;
;; IN: multiplier in result1:0, multiplicand in multiplicand1:0
;; OUT: product in result3:0
;;
;; Requires a single scratch variable counter, assumes that all variables
;; are in the currently selected bank.
;;
multiply_16_16s
clrf result3
clrf result2
bcf STATUS, C
rrf result1, F
rrf result0, F
movlw 16
movwf counter
top
btfss STATUS, C
goto dontAdd
movf multiplicand0, W
addwf result2, F
btfsc STATUS, C
incf result3, F
movf multiplicand1, W
addwf result3, F
dontAdd
bcf STATUS, C
rrf result3, F
rrf result2, F
rrf result1, F
rrf result0, F
decfsz counter, F
goto top
return
;;;
;; 16/16 -> 16, 16 signed divide with remainder
;;
;; IN: divisor in divisor1:0, dividend in dividend1:0
;; OUT: remainder in remainder1:0, quotient in dividend1:0
;;
;; Requires two scratch variables, sign and counter, assumes that all
;; variables are in the currently selected bank. Note that (-32768)/(-1)
;; won't fit in the 16-bit quotient.
;;
divide_16_16s
movf dividend1, W
xorwf divisor1, W
movwf sign
btfss divisor1, 7
goto dontNegateDivisor
comf divisor0, F
comf divisor1, F
incf divisor0, F
btfsc STATUS, Z
incf divisor1, F
dontNegateDivisor
btfss dividend1, 7
goto dontNegateDividend
comf dividend0, F
comf dividend1, F
incf dividend0, F
btfsc STATUS, Z
incf dividend1, F
dontNegateDividend
clrf remainder1
clrf remainder0
bcf STATUS, C
movlw 17
movwf counter
loop
rlf dividend0, F
rlf dividend1, F
decf counter, F
btfsc STATUS, Z
goto done
rlf remainder0, F
rlf remainder1, F
movf divisor0, W
subwf remainder0, F
btfss STATUS, C
decf remainder1, F
movf divisor1, W
subwf remainder1, F
btfss remainder1, 7
goto notNegative
movf divisor0, W
addwf remainder0, F
btfsc STATUS, C
incf remainder1, F
movf divisor1, W
addwf remainder1, F
bcf STATUS, C
goto loop
notNegative
bsf STATUS, C
goto loop
done
btfss sign, 7
return
comf dividend0, F
comf dividend1, F
incf dividend0, F
btfsc STATUS, Z
incf dividend1, F
return