Search code examples
divisionz80

Is this z80 division algorithm broken?


http://zxm.speccy.cz/data/Z80%20Bits.html#2.2

Input: HL = Dividend, C = Divisor, A = 0 Output: HL = Quotient, A = Remainder

add hl,hl       ; unroll 16 times
rla         ; ...
cp  c       ; ...
jr  c,$+4       ; ...
sub c       ; ...
inc l       ; ...

When I try it out, and set hl=$1200, a=0, c=$91, I get 0 in HL. Shouldn't it be $1f?


Solution

  • It is broken. Here's the fixed version:

    add hl,hl       ; unroll 16 times
    rla             ; ...
    jr  c,$+5       ; important!
    cp  c           ; ...
    jr  c,$+4       ; ...
    sub c           ; ...
    inc l           ; ...
    

    If you shift $1200 through A register you see that it never gets bigger than $91. But once it reaches $90 the next comparison needs to be against $120 not $20. The check for carry I added handles that case.

    Looks like many of the examples on that page have similar problems.

    Incidentally, adc a,a can be used in place of rla with no change in speed or size but with a big increase in clarity. It makes it obvious that AHL is being treated as a 24 bit number.