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
    RETURN
ON 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: '