From: Dmitry Kiryashov
;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
> > ;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 movf high,w addwf low,f skpnc incf high,fThis modification will yield the result: 4366
Code:
Here is a 9 instruction version of Dmitry's code:
swapf low,w ; W = d.c
andlw 15 ; W = 0.c
addwf high,w ; W = 0.c + a.b
movwf low ; W -> low byte
swapf high,w ; W = b.a
andlw 15 ; W = 0.a
movwf high ; W -> high byte
btfsc status,c ; check carry from add
incf high,f ; 0.a + carry