;; ;; 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