8 ! 4-byte divide routine for z80
12 ! stack: quotient (out)
13 ! bc de: remainder (out) (high part in bc)
17 ! a n-byte divide may be implemented
18 ! using 2 (virtual) registers:
19 ! - a n-byte register containing
21 ! - a 2n-byte shiftregister (VSR)
23 ! Initially, the VSR contains the dividend
24 ! in its low (right) n bytes and zeroes in its
25 ! high n bytes. The dividend is shifted
26 ! left into a "window" bit by bit. After
27 ! each shift, the contents of the window
28 ! is compared with the divisor. If it is
29 ! higher or equal, the divisor is subtracted from
30 ! it and a "1" bit is inserted in the
31 ! VSR from the right side; else a "0" bit
32 ! is inserted. These bits are shifted left
33 ! too during subsequent iterations.
34 ! At the end, the rightmost part of VSR
35 ! contains the quotient.
36 ! For n=4, we need 2*4+4 = 12 bytes of
37 ! registers. Unfortunately we only have
38 ! 5 2-byte registers on the z80
39 ! (bc,de,hl,ix and iy). Therefore we use
40 ! an overlay technique for the rightmost
41 ! 4 bytes of the VSR. The 32 iterations
42 ! are split up into two groups: during
43 ! the first 16 iterations we use the high
44 ! order 16 bits of the dividend; during
45 ! the last 16 iterations we use the
47 ! register allocation:
52 pop hl ! save return address
54 pop bc ! low part (2 bytes)
56 xor a ! clear carry, a := 0
59 ld (.flag),a ! first pass main loop
60 pop de ! high part divisor
61 sbc hl,de ! inverse of high part
62 ex de,hl ! of divisor in de
63 pop hl ! save low part of
65 ld (.low),hl ! used during second
66 ! iteration over main loop
67 pop ix ! high part of dividend
71 ld iy,0 ! now the VSR is initialized
73 ! main loop, done twice
76 ! sub-loop, done 16 times
78 add iy,iy ! shift VSR left
84 or a ! subtract divisor from
88 jr nc,4f ! decrement iy if there
92 add iy,de ! there is no "sbc iy,ss"
93 ! on the z80, so de was
94 ! inverted during init.
96 ! see if the result is non-negative,
97 ! otherwise undo the subtract.
98 ! note that this uncooperating machine
99 ! does not set its S -or Z flag after
101 ex (sp),iy ! does anyone see a better
102 ex (sp),hl ! solution ???
114 ld a,(.flag) ! see if this was first or
115 ! second iteration of main loop
116 or a ! 0=first, 1=second
119 ld (.flag),a ! flag := 1
120 ld (.result),ix ! save high part of result
121 ld ix,(.low) ! initialize second
122 ! iteration, ix := low
127 push iy ! transfer remainder
128 pop bc ! from iy-hl to bc-de
131 ld hl,(.result) ! high part of result
133 push ix ! low part of result