Minor optimization due to unrolled loop not using b anymore
[stack_machine.git] / sm.asm
1         .area   SM (abs,ovr)
2
3         .org    0x100
4
5         ld      hl,0x308
6         ld      de,8
7         ld      bc,0x30 ;0x38 ;0x10
8         ldir
9
10         ld      hl,0x1234
11         ld      de,0x56
12         call    div_hl_de
13         call    print_div
14
15         ld      hl,0x6543
16         ld      de,0x21
17         call    div_hl_de
18         call    print_div
19
20         ld      hl,0xb975
21         ld      de,0x31
22         call    div_hl_de
23         call    print_div
24
25         ld      hl,0xdb97
26         ld      de,0x531
27         call    div_hl_de
28         call    print_div
29
30         ld      hl,0x1234
31         ld      de,0x56
32         call    div_hl_de_signed
33         call    print_div
34
35         ld      hl,0x6543
36         ld      de,0x21
37         call    div_hl_de_signed
38         call    print_div
39
40         ld      hl,0xb975
41         ld      de,0x31
42         call    div_hl_de_signed
43         call    print_div
44
45         ld      hl,0xdb97
46         ld      de,0x531
47         call    div_hl_de_signed
48         call    print_div
49
50         ld      hl,-0x1234
51         ld      de,0x56
52         call    div_hl_de_signed
53         call    print_div
54
55         ld      hl,-0x6543
56         ld      de,0x21
57         call    div_hl_de_signed
58         call    print_div
59
60         ld      hl,-0xb975
61         ld      de,0x31
62         call    div_hl_de_signed
63         call    print_div
64
65         ld      hl,-0xdb97
66         ld      de,0x531
67         call    div_hl_de_signed
68         call    print_div
69
70         ld      hl,0x1234
71         ld      de,-0x56
72         call    div_hl_de_signed
73         call    print_div
74
75         ld      hl,0x6543
76         ld      de,-0x21
77         call    div_hl_de_signed
78         call    print_div
79
80         ld      hl,0xb975
81         ld      de,-0x31
82         call    div_hl_de_signed
83         call    print_div
84
85         ld      hl,0xdb97
86         ld      de,-0x531
87         call    div_hl_de_signed
88         call    print_div
89
90         ld      hl,-0x1234
91         ld      de,-0x56
92         call    div_hl_de_signed
93         call    print_div
94
95         ld      hl,-0x6543
96         ld      de,-0x21
97         call    div_hl_de_signed
98         call    print_div
99
100         ld      hl,-0xb975
101         ld      de,-0x31
102         call    div_hl_de_signed
103         call    print_div
104
105         ld      hl,-0xdb97
106         ld      de,-0x531
107         call    div_hl_de_signed
108         call    print_div
109
110         rst     0
111
112 print_div:
113         ex      de,hl
114         call    print_word
115         ex      de,hl
116         call    print_space
117         call    print_word
118         jp      print_crlf
119
120 ;       pop     de
121 ;       call    sm
122 ;
123 ;       ; push argument
124 ;       .db     <imm_w
125 ;       .dw     5
126 ;
127 ;       ; push result pointer
128 ;       .db     <add_isp
129 ;       .dw     0
130 ;
131 ;       ; call sm_factorial(argument)
132 ;       .db     <call_i
133 ;       .dw     sm_factorial
134 ;       .db     <adj_isp
135 ;       .dw     2
136 ;
137 ;;      ; print it the easy way
138 ;;      .db     <esc
139 ;;      ex      de,hl
140 ;;      call    print_word
141 ;;      call    print_crlf
142 ;;      ex      de,hl
143 ;;      call    sm
144 ;
145 ;       ; print 10000s
146 ;       .db     <div_iuw
147 ;       .dw     10000
148 ;       .db     <add_iw
149 ;       .dw     '0
150 ;       .db     <call_i
151 ;       .dw     sm_print_char
152 ;       .db     <adj_isp
153 ;       .dw     2
154 ;
155 ;       ; print 1000s
156 ;       .db     <div_iuw
157 ;       .dw     1000
158 ;       .db     <add_iw
159 ;       .dw     '0
160 ;       .db     <call_i
161 ;       .dw     sm_print_char
162 ;       .db     <adj_isp
163 ;       .dw     2
164 ;
165 ;       ; print 100s
166 ;       .db     <div_iuw
167 ;       .dw     100
168 ;       .db     <add_iw
169 ;       .dw     '0
170 ;       .db     <call_i
171 ;       .dw     sm_print_char
172 ;       .db     <adj_isp
173 ;       .dw     2
174 ;
175 ;       ; print 10s
176 ;       .db     <div_iuw
177 ;       .dw     10
178 ;       .db     <add_iw
179 ;       .dw     '0
180 ;       .db     <call_i
181 ;       .dw     sm_print_char
182 ;       .db     <adj_isp
183 ;       .dw     2
184 ;
185 ;       ; print 1s
186 ;       .db     <add_iw
187 ;       .dw     '0
188 ;       .db     <call_i
189 ;       .dw     sm_print_char
190 ;       .db     <adj_isp
191 ;       .dw     2
192 ;
193 ;       .db     <imm_w
194 ;       .dw     0xd
195 ;       .db     <call_i
196 ;       .dw     sm_print_char
197 ;       .db     <adj_isp
198 ;       .dw     2
199 ;
200 ;       .db     <imm_w
201 ;       .dw     0xa
202 ;       .db     <call_i
203 ;       .dw     sm_print_char
204 ;       .db     <adj_isp
205 ;       .dw     2
206 ;
207 ;       .db     <esc
208 ;       rst     0 ; can't return into ccp as clobbered by stack growth
209 ;
210 ;sm_factorial:
211 ;       ; get argument
212 ;       .db     <add_isp
213 ;       .dw     4
214 ;       .db     <ld_w
215 ;
216 ;       ; is argument < 2?
217 ;       .db     <lt_isw
218 ;       .dw     2
219 ;       .db     <jnz_i
220 ;       .dw     1$
221 ;
222 ;       ; no, set up for *result =
223 ;       .db     <add_isp
224 ;       .dw     2
225 ;       .db     <ld_w
226 ;
227 ;       ; get argument
228 ;       .db     <add_isp
229 ;       .dw     6
230 ;       .db     <ld_w
231 ;
232 ;       ; subtract 1
233 ;       .db     <add_iw
234 ;       .dw     -1
235 ;
236 ;       ; push result pointer
237 ;       .db     <add_isp
238 ;       .dw     0
239 ;
240 ;       ; call sm_factorial(argument - 1)
241 ;       .db     <call_i
242 ;       .dw     sm_factorial
243 ;       .db     <adj_isp
244 ;       .dw     2
245 ;
246 ;       ; get argument
247 ;       .db     <add_isp
248 ;       .dw     8
249 ;       .db     <ld_w
250 ;
251 ;       ; multiply
252 ;       .db     <mul_w
253 ;
254 ;       ; set *result = sm_factorial(argument - 1) * argument
255 ;       .db     <st_w
256 ;
257 ;       ; return 
258 ;       .db     <jmp
259 ;
260 ;1$:    ; yes, set up for *result =
261 ;       .db     <add_isp
262 ;       .dw     2
263 ;       .db     <ld_w
264 ;
265 ;       ; set *result = 1
266 ;       .db     <st_iw
267 ;       .dw     1
268 ;
269 ;       ; return 
270 ;       .db     <jmp
271 ;
272 ;sm_print_char:
273 ;       .db     <esc
274 ;       ld      hl,0
275 ;       add     hl,sp
276 ;       ld      a,(hl)
277 ;       call    print_char
278 ;       call    sm
279 ;       .db     <jmp
280
281 digits:
282         .ascii  '0123456789abcdef'
283
284 print_word:
285         push    af
286         ld      a,h
287         call    print_byte
288         ld      a,l
289         call    print_byte
290         pop     af
291         ret
292
293 print_byte:
294         push    af
295         push    af
296         rrca
297         rrca
298         rrca
299         rrca
300         call    print_digit
301         pop     af
302         call    print_digit
303         pop     af
304         ret
305
306 print_digit:
307         push    de
308         push    hl
309         and     0xf
310         ld      e,a
311         ld      d,0
312         ld      hl,digits
313         add     hl,de
314         ld      a,(hl)
315         pop     hl
316         pop     de
317         jp      print_char
318
319 print_space:
320         push    af
321         ld      a,0x20
322         call    print_char
323         pop     af
324         ret
325
326 print_trace:
327         push    af
328         push    bc
329         push    de
330         push    hl
331         ld      a,'p
332         call    print_char
333         ld      a,'c
334         call    print_char
335         ld      a,'=
336         call    print_char
337         rst     0x10 ; ex bc,hl
338         call    print_word
339         rst     0x10 ; ex bc,hl
340         call    print_space
341         ld      a,'o
342         call    print_char
343         ld      a,'p
344         call    print_char
345         ld      a,'=
346         call    print_char
347         call    print_word
348         call    print_space
349         ld      a,'s
350         call    print_char
351         ld      a,'p
352         call    print_char
353         ld      a,'=
354         call    print_char
355         ld      hl,10
356         add     hl,sp
357         call    print_word
358         call    print_space
359         ld      a,'t
360         call    print_char
361         ld      a,'o
362         call    print_char
363         ld      a,'s
364         call    print_char
365         ld      a,'=
366         call    print_char
367         ex      de,hl
368         call    print_word
369         ex      de,hl
370         call    print_space
371         ld      a,'s
372         call    print_char
373         ld      a,'t
374         call    print_char
375         ld      a,'k
376         call    print_char
377         ld      b,4
378         ld      a,'=
379 1$:     call    print_char
380         ld      e,(hl)
381         inc     hl
382         ld      d,(hl)
383         inc     hl
384         ex      de,hl
385         call    print_word
386         ex      de,hl
387         ld      a,' 
388         djnz    1$
389         pop     hl
390         pop     de
391         pop     bc
392         pop     af
393 print_crlf:
394         push    af
395         ld      a,0xd
396         call    print_char
397         ld      a,0xa
398         call    print_char
399         pop     af
400         ret
401
402 print_char:
403         push    bc
404         push    de
405         push    hl
406         ld      e,a
407         ld      c,2
408         call    5
409         pop     hl
410         pop     de
411         pop     bc
412         ret
413
414         .org    0x308
415
416 ; ld hl,(bc)+
417         ld      a,(bc)
418         ld      l,a
419         inc     bc
420         ld      a,(bc)
421         ld      h,a
422         inc     bc
423         ret
424
425         .org    0x310
426
427 ; ex bc,hl
428         ld      a,l
429         ld      l,c
430         ld      c,a
431         ld      a,h
432         ld      h,b
433         ld      b,a
434         ret
435
436         .org    0x318
437
438 ; print de
439         ex      de,hl
440         call    print_word
441         ex      de,hl
442         jp      print_space
443
444         .org    0x320
445
446 ; print bc
447         rst     0x10 ; ex bc,hl
448         call    print_word
449         rst     0x10 ; ex bc,hl
450         jp      print_space
451         
452         .org    0x328
453
454 ; print hl
455         call    print_word
456         jp      print_space
457
458         .org    0x330
459
460 ; print stack
461         ret ;jp print_trace
462
463         .org    0x338
464
465 ; print 'A
466         push    af
467         ld      a,'A
468         call    print_char
469         pop     af
470         ret
471
472 ; lower dispatcher, just before 0x100
473
474         .org    0x3eb ;d
475
476 dispatch_l5: ; pc in de
477         ex      de,hl
478         pop     de
479 dispatch_l6: ; tos in de, pc in hl
480         ld      c,l
481         ld      b,h
482         ld      l,(hl)
483         ld      h,>esc
484  rst 0x30 ; print stack
485         inc     bc
486         jp      (hl)
487
488 sm:
489         pop     bc
490         .db     0x21 ; ld hl,
491 dispatch_l1: ; tos in de and hl, pc in bc
492         push    de
493 dispatch_l2: ; tos in hl, pc in bc
494         ex      de,hl
495 dispatch_l3: ; tos in de, pc in bc, h clobbered
496         ld      h,>esc
497 dispatch_l4: ; tos in de, pc in bc, h = >esc
498         ld      a,(bc)
499         ld      l,a
500         inc     bc
501  rst 0x30 ; print stack
502         jp      (hl)
503
504 ; 0x100
505
506 esc:
507         rst     0x10 ; ex bc,hl
508         jp      (hl)
509
510 call_i: ; same as imm_w, call
511         rst     8 ; ld hl,(bc)+
512         push    de
513         ld      e,c
514         ld      d,b
515         jr      dispatch_l6
516
517 _call:
518         rst     0x10 ; ex bc,hl
519         ex      de,hl
520         jr      dispatch_l6
521
522 jmp_i: ; same as imm_w, jmp
523         rst     8 ; ld hl,(bc)+
524         jr      dispatch_l6
525
526 jz_i: ; same as imm_w, jz
527         rst     8 ; ld hl,(bc)+
528         ex      de,hl
529         .db     0x3e ; ld a,
530 jz:
531         pop     hl
532         ld      a,l
533         or      h
534         jr      nz,dispatch_mm1
535         jr      dispatch_l5
536
537 jnz_i: ; same as imm_w, jnz
538         rst     8 ; ld hl,(bc)+
539         ex      de,hl
540         .db     0x3e ; ld a,
541 jnz:
542         pop     hl
543         ld      a,l
544         or      h
545         jr      z,dispatch_mm1
546         jr      dispatch_l5
547
548 xchg_w:
549         pop     hl
550         jr      dispatch_l1
551
552 dup_w:
553         push    de
554         jr      dispatch_l4
555
556 imm_w:
557         rst     8 ; ld hl,(bc)+
558         jr      dispatch_l1
559
560 add_isp: ; same as imm_w, add_sp
561         rst     8 ; ld hl,(bc)+
562         push    de
563         .db     0x3e ; ld a,
564 add_sp:
565         ex      de,hl
566         add     hl,sp
567         jr      dispatch_l2
568
569 ld_iw: ; same as imm_w, ld_w
570         rst     8 ; ld hl,(bc)+
571         push    de
572         .db     0x3e ; ld a,
573 ld_w:
574         ex      de,hl
575         ld      e,(hl)
576         inc     hl
577         ld      d,(hl)
578         jr      dispatch_l3
579
580 ld_isb: ; same as imm_w, ld_sb
581         rst     8 ; ld hl,(bc)+
582         push    de
583         .db     0x3e ; ld a,
584 ld_sb:
585         ex      de,hl
586         ld      e,(hl)
587         ld      a,e
588         rla
589         sbc     a,a
590         ld      d,a
591         jr      dispatch_l3
592
593 ld_iub: ; same as imm_w, ld_ub
594         rst     8 ; ld hl,(bc)+
595         push    de
596         .db     0x3e ; ld a,
597 ld_ub:
598         ex      de,hl
599         ld      e,(hl)
600         ld      d,0
601         jr      dispatch_l3
602
603 neg_w:
604         dec     de
605 not_w:
606         ld      a,e
607         cpl
608         ld      e,a
609         ld      a,d
610         cpl
611         ld      d,a
612         jr      dispatch_l4
613
614 add_iw: ; same as imm_w, add_w
615         rst     8 ; ld hl,(bc)+
616         .db     0x3e ; ld a,
617 add_w:
618         pop     hl
619         add     hl,de
620         jr      dispatch_l2
621
622 ;sub_iw: ; same as imm_w, sub_w
623 ;       rst     8 ; ld hl,(bc)+
624 ;       .db     0x3e ; ld a,
625 sub_xw: ; same as xchg_w, sub_w
626         pop     hl
627         rst     0x10 ; ex bc,hl
628         .db     0x3e ; ld a,
629 sub_w: ; same as neg_w, add_w
630         pop     hl
631         or      a
632         sbc     hl,de
633         jr      dispatch_l2
634
635 eq_iw: ; same as imm_w, eq_w
636         rst     8 ; ld hl,(bc)+
637         .db     0x3e ; ld a,
638 eq_w:
639         pop     hl
640         sub     a
641         sbc     hl,de
642         ld      e,a
643         ld      d,a
644         jr      nz,dispatch_l3
645         inc     e
646         jr      dispatch_l3
647
648 ; middle dispatch routines
649
650 jmp: ; also means ret
651         ld      c,e
652         ld      b,d
653         jr      dispatch_m0
654
655 adj_isp: ; same as imm_w, adj_sp
656         rst     8 ; ld hl,(bc)+
657         push    de
658         .db     0x3e ; ld a,
659 adj_sp: ; same as add_sp, st_sp
660         ex      de,hl
661         add     hl,sp
662         .db     0x3e ; ld a,
663 st_sp:
664         ex      de,hl
665         ld      sp,hl
666         jr      dispatch_mm1
667
668 ;st_ixw: ; same as imm_w, xchg_w, st_w
669 ;       rst     8 ; ld hl,(bc)+
670 ;       ld      (hl),e
671 ;       inc     hl
672 ;       ld      (hl),d
673 ;       jr      dispatch_mm1
674
675 st_iw: ; same as imm_w, st_w
676         rst     8 ; ld hl,(bc)+
677         ex      de,hl
678         .db     0x3e ; ld a,
679 st_w:
680         pop     hl
681         ld      (hl),e
682         inc     hl
683         ld      (hl),d
684         jr      dispatch_mm1
685
686 st_ixb: ; same as imm_w, xchg_w, st_d
687         rst     8 ; ld hl,(bc)+
688         .db     0x3e ; ld a,
689 st_d:
690         pop     hl
691         ld      (hl),e
692         jr      dispatch_mm1
693
694 ; middle dispatcher, near 0x180, smaller in size
695 ; used for store-type routines that empty stack and need it to be popped
696
697 dispatch_mm1: ; pc in bc
698         ld      h,>esc
699 dispatch_m0: ; pc in bc, h = >esc
700         pop     de
701 dispatch_m4:
702         ld      a,(bc)
703         ld      l,a
704  rst 0x30 ; print stack
705         inc     bc
706         jp      (hl)
707
708 lt_iuw: ; same as imm_w, lt_iuw
709         rst     8 ; ld hl,(bc)+
710         .db     0x3e ; ld a,
711 gt_uw: ; same as xchg_w, lt_uw
712         pop     hl
713         ex      de,hl
714         .db     0x3e ; ld a,
715 lt_uw:
716         pop     hl
717         sub     a
718         sbc     hl,de
719         ld      d,a
720         adc     a,a
721         ld      e,a
722         jr      dispatch_u3
723
724 lt_isw: ; same as imm_w, lt_isw
725         rst     8 ; ld hl,(bc)+
726         .db     0x3e ; ld a,
727 gt_sw: ; same as xchg_w, lt_sw
728         pop     hl
729         ex      de,hl
730         .db     0x3e ; ld a,
731 lt_sw:
732         pop     hl
733         sub     a
734         sbc     hl,de
735         ld      d,a
736         jp      pe,lt_sw_overflow
737         add     hl,hl
738         adc     a,a
739         ld      e,a
740         jr      dispatch_u3
741 lt_sw_overflow:
742         add     hl,hl
743         ccf
744         adc     a,a
745         ld      e,a
746         jr      dispatch_u3
747
748 and_iw: ; same as imm_w, and_w
749         rst     8 ; ld hl,(bc)+
750         .db     0x3e ; ld a,
751 and_w:
752         pop     hl
753         ld      a,l
754         or      e
755         ld      e,a
756         ld      a,h
757         or      d
758         ld      d,a
759         jr      dispatch_u3
760
761 or_iw: ; same as imm_w, and_w
762         rst     8 ; ld hl,(bc)+
763         .db     0x3e ; ld a,
764 or_w:
765         pop     hl
766         ld      a,l
767         or      e
768         ld      e,a
769         ld      a,h
770         or      d
771         ld      d,a
772         jr      dispatch_u3
773
774 xor_iw: ; same as imm_w, and_w
775         rst     8 ; ld hl,(bc)+
776         .db     0x3e ; ld a,
777 xor_w:
778         pop     hl
779         ld      a,l
780         xor     e
781         ld      e,a
782         ld      a,h
783         xor     d
784         ld      d,a
785         jr      dispatch_u3
786
787 ;sl_xw:
788 ;       pop     hl
789 ;       ex      de,hl
790 ;       .db     0x3e ; ld a,
791 sl_w:
792         pop     hl
793         call    sl_hl_e
794         jr      dispatch_u2
795
796 ;sr_xuw:
797 ;       pop     hl
798 ;       ex      de,hl
799 ;       .db     0x3e ; ld a,
800 sr_uw:
801         pop     hl
802         call    srl_hl_e
803         jr      dispatch_u2
804
805 ;sr_xsw:
806 ;       pop     hl
807 ;       ex      de,hl
808 ;       .db     0x3e ; ld a,
809 sr_sw:
810         pop     hl
811         call    sra_hl_e
812         jr      dispatch_u2
813
814 mul_iw:
815         rst     8 ; ld hl,(bc)+
816         .db     0x3e ; ld a,
817 mul_w:
818         pop     hl
819         call    mul_hl_de
820         jr      dispatch_u2
821
822 div_iuw:
823         rst     8 ; ld hl,(bc)+
824         .db     0x3e ; ld a,
825 div_xuw:
826         pop     hl
827         ex      de,hl
828         .db     0x3e ; ld a,
829 div_uw:
830         pop     hl
831         call    div_hl_de
832 ;       jr      dispatch_um1
833
834 ; upper dispatcher, after 0x200
835
836 dispatch_um1: ; tos in hl and de, pc in bc
837         push    hl
838         .db     0x3e ; ld a,
839 ;dispatch_u1: ; tos in de and hl, pc in bc
840 ;       push    de
841 dispatch_u2: ; tos in hl, pc in bc
842         ex      de,hl
843 dispatch_u3: ; tos in de, pc in bc, h clobbered
844         ld      h,>esc
845 dispatch_u4: ; tos in de, pc in bc, h = >esc
846         ld      a,(bc)
847         ld      l,a
848  rst 0x30 ; print stack
849         inc     bc
850         jp      (hl)
851
852 ; math package
853
854 sl_hl_e:
855         ld      a,e
856         and     0xf
857         ret     z
858 1$:     add     hl,hl
859         dec     a
860         jr      nz,1$
861         ret
862
863 srl_hl_e:
864         ld      a,e
865         and     0xf
866         ret     z
867         push    bc
868         ld      b,a
869         ld      a,l
870 srl_hl_loop:
871         srl     h
872         rra
873         djnz    srl_hl_loop
874         ld      l,a
875         pop     bc
876         ret
877
878 sra_hl_e:
879         ld      a,e
880         and     0xf
881         ret     z
882         push    bc
883         ld      b,a
884         ld      a,l
885 sra_hl_loop:
886         sra     h
887         rra
888         djnz    sra_hl_loop
889         ld      l,a
890         pop     bc
891         ret
892
893 mul_hl_de:
894         push    bc
895         ld      a,h
896         ld      c,l
897         ld      hl,0
898         ld      b,8
899 1$:     add     hl,hl
900         rla
901         jr      nc,2$
902         add     hl,de
903 2$:     djnz    1$
904         ld      a,c
905         ld      b,8
906 3$:     add     hl,hl
907         rla
908         jr      nc,4$
909         add     hl,de
910 4$:     djnz    3$
911         pop     bc
912         ret
913
914 div_hl_de_signed:
915         push    bc
916         ld      a,h
917         or      a
918         ld      a,d
919         rla
920         jp      p,4$                    ; positive dividend
921
922         ; negative dividend
923         dec     hl                      ; reduces remainder by 1 (we inc later)
924         ld      a,h
925         ld      c,l
926         ld      hl,-1
927         jr      c,2$                    ; negative dividend, negative divisor
928
929         ; negative dividend, positive divisor
930         call    div1
931         ld      b,a
932         ld      a,c
933         call    div
934         inc     a
935         jr      c,1$
936         sbc     hl,de
937 1$:     inc     hl                      ; get into range -divisor+1..0
938         ld      d,b
939         ld      e,a
940         pop     bc
941         ret
942
943 2$:     ; negative dividend, negative divisor
944         call    divn0
945         ld      b,a
946         ld      a,c
947         call    divn
948         jr      nc,3$
949         add     hl,de
950 3$:     inc     hl                      ; get into range divisor+1..0
951         ld      d,b
952         ld      e,a
953         pop     bc
954         ret
955
956 4$:     ; positive dividend
957         ld      a,h
958         ld      c,l
959         ld      hl,0
960         jr      nc,divu                 ; positive dividend, positive divisor
961
962         ; positive dividend, negative divisor
963         call    divn1
964         ld      b,a
965         ld      a,c
966         call    divn
967         inc     a
968         jr      c,5$
969         sbc     hl,de
970 5$:     ld      d,b
971         ld      e,a
972         pop     bc
973         ret
974
975 div_hl_de:
976         push    bc
977         ld      a,h
978         ld      c,l
979         ld      hl,0
980
981 divu:   ; positive dividend, positive divisor
982         call    div0
983         ld      b,a
984         ld      a,c
985         call    div
986         jr      nc,1$
987         add     hl,de
988 1$:     ld      d,b
989         ld      e,a
990         pop     bc
991         ret
992
993 ; non-restoring division routine
994
995 ; de = divisor, hl:a = dividend with hl = previous remainder, a = next byte
996 ; enter at div0 with positive remainder in hl, such that hl < de
997 ; enter at div1 with negative remainder in hl, such that hl >= -de
998
999 ; div0/1 return a = 8-bit quotient as an odd number interpreted as -ff..ff,
1000 ; by summing positive/negative place values, e.g. -80 +40 +20 -10 +8 -4 -2 +1
1001
1002 ; if entered at div0, there is a -80 and so quotient is in range -ff..-1
1003 ; if entered at div1, there is a +80 and so quotient is in range 1..ff
1004 ; falls out of loop after div01 with positive remainder, div11 with negative,
1005 ; depending on this we should re-enter at div0 or div1, signalled by cf return
1006
1007 ; the successive quotient bytes can be concatenated into a full quotient,
1008 ; but negative bytes require the next higher quotient byte to be decremented,
1009 ; we know in advance if this will happen because the implied sign of the
1010 ; quotient byte depends only on whether we entered at div0 or div1, hence,
1011 ; before the div11 return we'll decrement to compensate for next negative byte
1012
1013 ; the decrement can also be seen as compensating for the extra add hl,de that
1014 ; may be needed to make negative remainder positive before return to caller,
1015 ; thus leaving quotient in a consistent state regardless of which exit taken,
1016 ; remainder needs the add hl,de if cf=1 returned (equiv. return byte is even)
1017
1018 ; in the following code each sbc hl,de gets an inc a and each add hl,de gets
1019 ; a dec a, guaranteeing the integrity of the division, the initial scf/rla is
1020 ; needed to make the result 100 + -ff..ff or 1..1ff, so that the decrements
1021 ; cannot borrow into the upcoming dividend bits also held in a, and there must
1022 ; be another shift between the scf/rla and increment/decrement so that the scf
1023 ; is implicitly in the 100s place, making the code awkward though it's correct 
1024
1025 ; now optimized to only inc/dec a when doing zero-crossing, fix above analysis
1026
1027 div:    jr      c,div1
1028 div0:   ; bit 0, above
1029         scf
1030         rla
1031         adc     hl,hl
1032         sbc     hl,de
1033         jr      nc,div01
1034         dec     a
1035 div11:  ; bit 1, below
1036         add     a,a
1037         adc     hl,hl
1038         add     hl,de
1039         jr      nc,div12
1040         inc     a
1041 div02:  ; bit 2, above
1042         add     a,a
1043         adc     hl,hl
1044         sbc     hl,de
1045         jr      nc,div03
1046         dec     a
1047 div13:  ; bit 3, below
1048         add     a,a
1049         adc     hl,hl
1050         add     hl,de
1051         jr      nc,div14
1052         inc     a
1053 div04:  ; bit 4, above
1054         add     a,a
1055         adc     hl,hl
1056         sbc     hl,de
1057         jr      nc,div05
1058         dec     a
1059 div15:  ; bit 5, below
1060         add     a,a
1061         adc     hl,hl
1062         add     hl,de
1063         jr      nc,div16
1064         inc     a
1065 div06:  ; bit 6, above
1066         add     a,a
1067         adc     hl,hl
1068         sbc     hl,de
1069         jr      nc,div07
1070         dec     a
1071 div17:  ; bit 7, below
1072         add     a,a
1073         adc     hl,hl
1074         add     hl,de
1075         jr      nc,div18
1076         inc     a
1077 div08:  ; done, above
1078         add     a,a
1079         dec     a
1080         or      a
1081         ret
1082
1083 div1:   ; bit 0, below
1084         add     a,a
1085         adc     hl,hl
1086         add     hl,de
1087         jr      nc,div11
1088         inc     a
1089 div01:  ; bit 1, above
1090         add     a,a
1091         adc     hl,hl
1092         sbc     hl,de
1093         jr      nc,div02
1094         dec     a
1095 div12:  ; bit 2, below
1096         add     a,a
1097         adc     hl,hl
1098         add     hl,de
1099         jr      nc,div13
1100         inc     a
1101 div03:  ; bit 3, above
1102         add     a,a
1103         adc     hl,hl
1104         sbc     hl,de
1105         jr      nc,div04
1106         dec     a
1107 div14:  ; bit 4, below
1108         add     a,a
1109         adc     hl,hl
1110         add     hl,de
1111         jr      nc,div15
1112         inc     a
1113 div05:  ; bit 5, above
1114         add     a,a
1115         adc     hl,hl
1116         sbc     hl,de
1117         jr      nc,div06
1118         dec     a
1119 div16:  ; bit 6, below
1120         add     a,a
1121         adc     hl,hl
1122         add     hl,de
1123         jr      nc,div17
1124         inc     a
1125 div07:  ; bit 7, above
1126         add     a,a
1127         adc     hl,hl
1128         sbc     hl,de
1129         jr      nc,div08
1130         dec     a
1131 div18:  ; done, below
1132         add     a,a
1133         ;inc    a
1134         ;dec    a                       ; compensation
1135         scf
1136         ret
1137
1138 ; divn0/1 are the same as div0/1 but carry reversed after add/subtract divisor
1139 ; this is for negative divisors where we expect carry (means no zero crossing)
1140
1141 ; when divisor negated, remainder also negated, so we expect to do subtraction
1142 ; when remainder negative and vice versa, need to clear carry after add hl,hl
1143
1144 divn:   jr      c,divn1
1145 divn0:  ; bit 0, above
1146         scf
1147         rla
1148         adc     hl,hl
1149         or      a
1150         sbc     hl,de
1151         jr      c,divn01
1152         dec     a
1153 divn11: ; bit 1, below
1154         add     a,a
1155         adc     hl,hl
1156         add     hl,de
1157         jr      c,divn12
1158         inc     a
1159 divn02: ; bit 2, above
1160         add     a,a
1161         adc     hl,hl
1162         or      a
1163         sbc     hl,de
1164         jr      c,divn03
1165         dec     a
1166 divn13: ; bit 3, below
1167         add     a,a
1168         adc     hl,hl
1169         add     hl,de
1170         jr      c,divn14
1171         inc     a
1172 divn04: ; bit 4, above
1173         add     a,a
1174         adc     hl,hl
1175         or      a
1176         sbc     hl,de
1177         jr      c,divn05
1178         dec     a
1179 divn15: ; bit 5, below
1180         add     a,a
1181         adc     hl,hl
1182         add     hl,de
1183         jr      c,divn16
1184         inc     a
1185 divn06: ; bit 6, above
1186         add     a,a
1187         adc     hl,hl
1188         or      a
1189         sbc     hl,de
1190         jr      c,divn07
1191         dec     a
1192 divn17: ; bit 7, below
1193         add     a,a
1194         adc     hl,hl
1195         add     hl,de
1196         jr      c,divn18
1197         inc     a
1198 divn08: ; done, above
1199         add     a,a
1200         dec     a
1201         or      a
1202         ret
1203
1204 divn1:  ; bit 0, below
1205         add     a,a
1206         adc     hl,hl
1207         add     hl,de
1208         jr      c,divn11
1209         inc     a
1210 divn01: ; bit 1, above
1211         add     a,a
1212         adc     hl,hl
1213         or      a
1214         sbc     hl,de
1215         jr      c,divn02
1216         dec     a
1217 divn12: ; bit 2, below
1218         add     a,a
1219         adc     hl,hl
1220         add     hl,de
1221         jr      c,divn13
1222         inc     a
1223 divn03: ; bit 3, above
1224         add     a,a
1225         adc     hl,hl
1226         or      a
1227         sbc     hl,de
1228         jr      c,divn04
1229         dec     a
1230 divn14: ; bit 4, below
1231         add     a,a
1232         adc     hl,hl
1233         add     hl,de
1234         jr      c,divn15
1235         inc     a
1236 divn05: ; bit 5, above
1237         add     a,a
1238         adc     hl,hl
1239         or      a
1240         sbc     hl,de
1241         jr      c,divn06
1242         dec     a
1243 divn16: ; bit 6, below
1244         add     a,a
1245         adc     hl,hl
1246         add     hl,de
1247         jr      c,divn17
1248         inc     a
1249 divn07: ; bit 7, above
1250         add     a,a
1251         adc     hl,hl
1252         or      a
1253         sbc     hl,de
1254         jr      c,divn08
1255         dec     a
1256 divn18: ; done, below
1257         add     a,a
1258         ;inc    a
1259         ;dec    a                       ; compensation
1260         scf
1261         ret