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