; bw 26 sept 2000 ; 16bit multiply/divide support. note intel byte order (least sig. byte first/lowest addr) cblock BitCount Product:4 Multiplier:2 Multiplicand:2 Dividend:2 Divisor:2 Quotient:2 Remainder:2 endc ; ********* 16x16 unsigned multply. Written by Bill Welch, 26 sept 2000 *********** ; Derived from "Computer Organization and Design" 2nd Ed, by Patterson & Hennessy, ; figures 4.31 and 4.32, pp 257-258. ; Note the use of the "Intel" byte order-- least significant byte is at lowest address. ; Input is in Multiplier & Multiplicand, Output is in Product (32 bits). umul16: movf Multiplier,w ; copy the multiplier into right-half movwf Product ; of the product register movf Multiplier+1,w movwf Product+1 clrf Product+2 ; zero out the left-half of the clrf Product+3 ; product register clrf BitCount m16A: movlw 16 ; repeat 16 times subwf BitCount,w bnc m16B return m16B: btfss Product,0 ; Is Least Sig. Bit Zero? goto m16C movf Multiplicand,w ; LSB is a One, so add the addwf Product+2,f ; multplicand to the left-half btfsc STATUS,C ; of the product and store the incf Product+3,f ; result in the left-half of movf Multiplicand+1,w ; the product register addwf Product+3,f m16C: rrf Product+3,f ; shift the entire product register rrf Product+2,f ; right rrf Product+1,f rrf Product,f movf BitCount,w incf BitCount, f goto m16A ; ********* 16x16 unsigned divide. Written by Bill Welch, 26 sept 2000 *********** ; Derived from "Computer Organization and Design" 2nd Ed, by Patterson & Hennessy, ; figures 4.40 and 4.41, pp 270-271. ; Note the use of the "Intel" byte order-- least significant byte is at lowest address. ; Input is in Dividend & Divisor, Output is in Remainder and Quotient udiv16: movf Dividend,w ; copy the dividend into the movwf Quotient ; quotient register movf Dividend+1,w movwf Quotient+1 clrf Remainder ; zero out the remainder clrf Remainder+1 bcf STATUS,C rlf Quotient,f ; shift quotient/remainder left 1 bit rlf Quotient+1,f rlf Remainder,f rlf Remainder+1,f clrf BitCount u16A: movlw 16 ; repeat 16 times subwf BitCount,w bnc u16B bcf STATUS,C ; we are done, shift the rrf Remainder+1,f ; remainder right 1 bit rrf Remainder,f return u16B: movf Divisor+1,w ; subtract the divisor register subwf Remainder+1,f ; from the remainder register movf Divisor,w ; and store the result in the subwf Remainder,f ; remainder register btfss STATUS,C decf Remainder+1,f btfss Remainder+1,7 ; is remainder less than zero? goto u16C movf Divisor,w ; remainder is less than zero, so addwf Remainder,f ; restore the original value by btfsc STATUS,C ; adding the divisor register to the incf Remainder+1,f ; remainder. movf Divisor+1,w addwf Remainder+1,f bcf STATUS,C ; prepare to shift in a zero bit goto u16D u16C: bsf STATUS,C ; prepare to shift in a one bit u16D: rlf Quotient,f rlf Quotient+1,f ; shift the quotient/remainder rlf Remainder,f ; left one bit position. rlf Remainder+1,f movf BitCount,w incf BitCount, f goto u16A