Full Version : Kiryashov' Divide-by-15 Routine (PIC ASM)
avr >>MATH ROUTINES >>Kiryashov' Divide-by-15 Routine (PIC ASM)


Admin3- 04-18-2006
Divide 16 bits by the constant value 15
From: Dmitry Kiryashov

CODE

;high=a.b , low=c.d
movlw   0xF0
andwf   low,F  ;c.0
andwf   high,W ;a.0

; at this point, the low nibble of `low' is zero
; W contains the high nibble of `high'

xorwf   high,W ;a.0^a.b
; now W contains low nibble of high, namely 0x0b
;    W  ^ high
;  0xa0 ^ 0xab => 0x0b

xorwf   high,F ;a.0
;Now the lower nibble of a is cleared.
;    W  ^ high
;  0x0b ^ 0xab => 0xa0  and this is stored back in high

xorwf   high,W ;a.b
;Now W contains the original value of high
;    W  ^ high
;  0x0b ^ 0xa0 => 0xab

swapf   low,F  ;0.c
swapf   high,F ;0.a

addwf   low,F  ;0.c + a.b
skpnc
incf    high,F ;0.a + carry

;11 clocks/words
Scott Dattalo says:

BTW, you should be aware that Nik's generator is more accurate than what Dmitry and I generated. The algorithm is based on this formula:

1/(A+B) ~= B/A - (B/A)^2 + (B/A)^3 + ...

Dmitry and I computed the first two terms, Nik does all three in the generator.

The error is on the order of 1/16/16/16 = 2E-4

For example:

suppose you wanted to divide 65535 by 15. The exact answer is 4369. However, using Dmitry's code you'd get: 4350. Nik's produces: 4365 (I think).

But a slight mod will improve Dmitry's

CODE

;high=a.b , low=c.d

        movlw   0xF0
        andwf   low,F  ;c.0
        andwf   high,W ;a.0

        xorwf   high,W ;a.0^a.b

        xorwf   high,F ;a.0
        xorwf   high,W ;a.b

        swapf   low,F  ;0.c
        swapf   high,F ;0.a

        addwf   low,F  ;0.c + a.b
        skpnc
        incf    high,F ;0.a + carry

[code]
       movf  high,w
       addwf low,f
       skpnc
        incf high,f

This modification will yield the result: 4366



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.