ON 20081006@3:26:21 PM at page: http://www.piclist.com/techref/microchip/math/div/index.htm# [mark_jeronimus-gmail-] I have agreed to maintain this page. ON 20081006@3:33:45 PM at page: http://www.piclist.com/techref/microchip/math/div/index.htm# [mark_jeronimus-gmail-] change |Replace: '' with: '' ON 20081007@7:56:18 AM at page: http://www.piclist.com/techref/microchip/math/div/16by8lz.htm#39728.3307523148 [mark_jeronimus-gmail-] Code:
The next function divides a 16-bit number in MODREG1:MODREG0 by any N<=16 bit number in TEMP1:TEMP0. The quotient will be stored in DIVREG1:DIVREG:0 and the modulo in MODREG1:MODREG0. (in this notation, MODREG1 is th HI byte, etc.) It is optimized for dividing numbers by a constant. Restraints: - The divisor in TEMP1:TEMP0 should be left-aligned (eg, padded with zeroes on the LSB side). This is easy if you divide by 8-bits. - The high bit of the divisor (TEMP1.7) should be 1. If the high bit of the divisor is not 1 then the result may overflow. This will cause the (17-N)-bit quotient in DIVREG1:DIVREG0 to contain all ones and can be further detected by comparing MODREG1:MODREG0 by the used divisor (which was btw destroyed by this function). Bottomline, it is better to avoid this. - No detection for a divisor of zero (which would mean a divisor of 0 bits long which is nonsense) Worst case timing: 6+(17-N)*23 (where N is the number of bits in the divisor) N=4: T=305 N=8: T=213 N=12: T=121 Here's the universal version: ;;DIVIDE A 16-BIT NUMBER BY AN N-BIT NUMBER ;;IN: ;; MODREG1:MODREG0 = 16-BIT DIVIDEND ;; TEMP1:TEMP0 = N-BIT DIVISOR, LEFT ALIGNED, WITH TEMP1.7 = 1 ;;OUT: ;; DIVREG1:DIVREG0 = (17-N)-BIT WIDE QUOTIENT ;; MODREG1:MODREG0 = N-BIT REMAINDER ;;DESTROYED: ;; COUNT = 0 ;; TEMO1:TEMP0 = ORIGINAL TEMO1:TEMP0 << (17-N) ;; THAT MEANS TEMO1:TEMP0 = 0 IF INPUT IS CORRECT DIV16 MOVLW 17-N MOVWF COUNT CLRF DIVREG0 CLRF DIVREG1 DIV16_LOOP MOVF TEMP0,W ;W=MOD-DIVISOR SUBWF MODREG0,W MOVF TEMP1,W BTFSS STATUS,C ;PROCESS BORROW ADDLW 1 SUBWF MODREG1,W BTFSS STATUS,C ;IF W<0 GOTO DIV16_NOSUB MOVF TEMP0,W ;MOD=MOD-DIVISOR SUBWF MODREG0,F BTFSS STATUS,C DECF MODREG1,F MOVF TEMP1,W SUBWF MODREG1,F BSF STATUS,C DIV16_NOSUB RLF DIVREG0,F ;DIV << 1 + CARRY RLF DIVREG1,F BCF STATUS,C ;DIVISOR>>=1 RRF TEMP1,F RRF TEMP0,F DECFSZ COUNT,F GOTO DIV16_LOOP RETURN In the next example, it has been configured to divide a 16-bit number by a 6-bit number in WREG. It will put it in TEMP1 (and clear TEMP0) and shift it to the left by 2 bits to align it left. The result is 11-bits wide in DIVREG1:DIVREG0 and the remainder is of course 6-bits wide (same width as the divisor) and still occupies MODREG1:MODREG0. ;;DIVIDE A 16-BIT NUMBER BY A 6-BIT WREG. RESULT IS 11-BIT WIDE DIV16_6 ;SHIFT LEFT BY 10 BITS MOVWF TEMP1 CLRF TEMP0 BCF STATUS,C RLF TEMP1,F RLF TEMP1,F MOVLW 11 MOVWF COUNT CLRF DIVREG0 CLRF DIVREG1 DIV16_6_LOOP MOVF TEMP0,W ;W=MOD-DIVISOR SUBWF MODREG0,W MOVF TEMP1,W BTFSS STATUS,C ;PROCESS BORROW ADDLW 1 SUBWF MODREG1,W BTFSS STATUS,C ;IF W<0 GOTO DIV16_6_NOSUB MOVF TEMP0,W ;MOD=MOD-DIVISOR SUBWF MODREG0,F BTFSS STATUS,C DECF MODREG1,F MOVF TEMP1,W SUBWF MODREG1,F BSF STATUS,C DIV16_6_NOSUB RLF DIVREG0,F ;DIV << 1 + CARRY RLF DIVREG1,F BCF STATUS,C ;DIVISOR>>=1 RRF TEMP1,F RRF TEMP0,F DECFSZ COUNT,F GOTO DIV16_6_LOOP RETURNON 20081009@9:27:07 AM at page: http://www.piclist.com/microchip/math/div/div16or32by16to16.htm#39730.3405208333 James Newton[JMN-EFP-786] published post 39730.3405208333 Nikolai, you're a genius! Thanks for the division routine, it'll be used in an ignition mapping system for a motorcycle. |Delete 'P-' before: '' but after: '