Add decimal factorial result printing using the division routines
[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         pop     de
11         call    sm
12
13         ; push argument
14         .db     <imm_w
15         .dw     5
16
17         ; push result pointer
18         .db     <add_isp
19         .dw     0
20
21         ; call sm_factorial(argument)
22         .db     <call_i
23         .dw     sm_factorial
24         .db     <adj_isp
25         .dw     2
26
27 ;       ; print it the easy way
28 ;       .db     <esc
29 ;       ex      de,hl
30 ;       call    print_word
31 ;       call    print_crlf
32 ;       ex      de,hl
33 ;       call    sm
34
35         ; print 10000s
36         .db     <div_iuw
37         .dw     10000
38         .db     <add_iw
39         .dw     '0
40         .db     <call_i
41         .dw     sm_print_char
42         .db     <adj_isp
43         .dw     2
44
45         ; print 1000s
46         .db     <div_iuw
47         .dw     1000
48         .db     <add_iw
49         .dw     '0
50         .db     <call_i
51         .dw     sm_print_char
52         .db     <adj_isp
53         .dw     2
54
55         ; print 100s
56         .db     <div_iuw
57         .dw     100
58         .db     <add_iw
59         .dw     '0
60         .db     <call_i
61         .dw     sm_print_char
62         .db     <adj_isp
63         .dw     2
64
65         ; print 10s
66         .db     <div_iuw
67         .dw     10
68         .db     <add_iw
69         .dw     '0
70         .db     <call_i
71         .dw     sm_print_char
72         .db     <adj_isp
73         .dw     2
74
75         ; print 1s
76         .db     <add_iw
77         .dw     '0
78         .db     <call_i
79         .dw     sm_print_char
80         .db     <adj_isp
81         .dw     2
82
83         .db     <imm_w
84         .dw     0xd
85         .db     <call_i
86         .dw     sm_print_char
87         .db     <adj_isp
88         .dw     2
89
90         .db     <imm_w
91         .dw     0xa
92         .db     <call_i
93         .dw     sm_print_char
94         .db     <adj_isp
95         .dw     2
96
97         .db     <esc
98         rst     0 ; can't return into ccp as clobbered by stack growth
99
100 sm_factorial:
101         ; get argument
102         .db     <add_isp
103         .dw     4
104         .db     <ld_w
105
106         ; is argument < 2?
107         .db     <lt_isw
108         .dw     2
109         .db     <jnz_i
110         .dw     1$
111
112         ; no, set up for *result =
113         .db     <add_isp
114         .dw     2
115         .db     <ld_w
116
117         ; get argument
118         .db     <add_isp
119         .dw     6
120         .db     <ld_w
121
122         ; subtract 1
123         .db     <add_iw
124         .dw     -1
125
126         ; push result pointer
127         .db     <add_isp
128         .dw     0
129
130         ; call sm_factorial(argument - 1)
131         .db     <call_i
132         .dw     sm_factorial
133         .db     <adj_isp
134         .dw     2
135
136         ; get argument
137         .db     <add_isp
138         .dw     8
139         .db     <ld_w
140
141         ; multiply
142         .db     <mul_w
143
144         ; set *result = sm_factorial(argument - 1) * argument
145         .db     <st_w
146
147         ; return 
148         .db     <jmp
149
150 1$:     ; yes, set up for *result =
151         .db     <add_isp
152         .dw     2
153         .db     <ld_w
154
155         ; set *result = 1
156         .db     <st_iw
157         .dw     1
158
159         ; return 
160         .db     <jmp
161
162 sm_print_char:
163         .db     <esc
164         ld      hl,0
165         add     hl,sp
166         ld      a,(hl)
167         call    print_char
168         call    sm
169         .db     <jmp
170
171 digits:
172         .ascii  '0123456789abcdef'
173
174 print_word:
175         push    af
176         ld      a,h
177         call    print_byte
178         ld      a,l
179         call    print_byte
180         pop     af
181         ret
182
183 print_byte:
184         push    af
185         push    af
186         rrca
187         rrca
188         rrca
189         rrca
190         call    print_digit
191         pop     af
192         call    print_digit
193         pop     af
194         ret
195
196 print_digit:
197         push    de
198         push    hl
199         and     0xf
200         ld      e,a
201         ld      d,0
202         ld      hl,digits
203         add     hl,de
204         ld      a,(hl)
205         pop     hl
206         pop     de
207         jp      print_char
208
209 print_space:
210         push    af
211         ld      a,0x20
212         call    print_char
213         pop     af
214         ret
215
216 print_trace:
217         push    af
218         push    bc
219         push    de
220         push    hl
221         ld      a,'p
222         call    print_char
223         ld      a,'c
224         call    print_char
225         ld      a,'=
226         call    print_char
227         rst     0x10 ; ex bc,hl
228         call    print_word
229         rst     0x10 ; ex bc,hl
230         call    print_space
231         ld      a,'o
232         call    print_char
233         ld      a,'p
234         call    print_char
235         ld      a,'=
236         call    print_char
237         call    print_word
238         call    print_space
239         ld      a,'s
240         call    print_char
241         ld      a,'p
242         call    print_char
243         ld      a,'=
244         call    print_char
245         ld      hl,10
246         add     hl,sp
247         call    print_word
248         call    print_space
249         ld      a,'t
250         call    print_char
251         ld      a,'o
252         call    print_char
253         ld      a,'s
254         call    print_char
255         ld      a,'=
256         call    print_char
257         ex      de,hl
258         call    print_word
259         ex      de,hl
260         call    print_space
261         ld      a,'s
262         call    print_char
263         ld      a,'t
264         call    print_char
265         ld      a,'k
266         call    print_char
267         ld      b,4
268         ld      a,'=
269 1$:     call    print_char
270         ld      e,(hl)
271         inc     hl
272         ld      d,(hl)
273         inc     hl
274         ex      de,hl
275         call    print_word
276         ex      de,hl
277         ld      a,' 
278         djnz    1$
279         pop     hl
280         pop     de
281         pop     bc
282         pop     af
283 print_crlf:
284         push    af
285         ld      a,0xd
286         call    print_char
287         ld      a,0xa
288         call    print_char
289         pop     af
290         ret
291
292 print_char:
293         push    bc
294         push    de
295         push    hl
296         ld      e,a
297         ld      c,2
298         call    5
299         pop     hl
300         pop     de
301         pop     bc
302         ret
303
304         .org    0x308
305
306 ; ld hl,(bc)+
307         ld      a,(bc)
308         ld      l,a
309         inc     bc
310         ld      a,(bc)
311         ld      h,a
312         inc     bc
313         ret
314
315         .org    0x310
316
317 ; ex bc,hl
318         ld      a,l
319         ld      l,c
320         ld      c,a
321         ld      a,h
322         ld      h,b
323         ld      b,a
324         ret
325
326         .org    0x318
327
328 ; print de
329         ex      de,hl
330         call    print_word
331         ex      de,hl
332         jp      print_space
333
334         .org    0x320
335
336 ; print bc
337         rst     0x10 ; ex bc,hl
338         call    print_word
339         rst     0x10 ; ex bc,hl
340         jp      print_space
341         
342         .org    0x328
343
344 ; print hl
345         call    print_word
346         jp      print_space
347
348         .org    0x330
349
350 ; print stack
351         ret ;jp print_trace
352
353         .org    0x338
354
355 ; print 'A
356         push    af
357         ld      a,'A
358         call    print_char
359         pop     af
360         ret
361
362 ; lower dispatcher, just before 0x100
363
364         .org    0x3eb ;d
365
366 dispatch_l5: ; pc in de
367         ex      de,hl
368         pop     de
369 dispatch_l6: ; tos in de, pc in hl
370         ld      c,l
371         ld      b,h
372         ld      l,(hl)
373         ld      h,>esc
374  rst 0x30 ; print stack
375         inc     bc
376         jp      (hl)
377
378 sm:
379         pop     bc
380         .db     0x21 ; ld hl,
381 dispatch_l1: ; tos in de and hl, pc in bc
382         push    de
383 dispatch_l2: ; tos in hl, pc in bc
384         ex      de,hl
385 dispatch_l3: ; tos in de, pc in bc, h clobbered
386         ld      h,>esc
387 dispatch_l4: ; tos in de, pc in bc, h = >esc
388         ld      a,(bc)
389         ld      l,a
390         inc     bc
391  rst 0x30 ; print stack
392         jp      (hl)
393
394 ; 0x100
395
396 esc:
397         rst     0x10 ; ex bc,hl
398         jp      (hl)
399
400 call_i: ; same as imm_w, call
401         rst     8 ; ld hl,(bc)+
402         push    de
403         ld      e,c
404         ld      d,b
405         jr      dispatch_l6
406
407 _call:
408         rst     0x10 ; ex bc,hl
409         ex      de,hl
410         jr      dispatch_l6
411
412 jmp_i: ; same as imm_w, jmp
413         rst     8 ; ld hl,(bc)+
414         jr      dispatch_l6
415
416 jz_i: ; same as imm_w, jz
417         rst     8 ; ld hl,(bc)+
418         ex      de,hl
419         .db     0x3e ; ld a,
420 jz:
421         pop     hl
422         ld      a,l
423         or      h
424         jr      nz,dispatch_mm1
425         jr      dispatch_l5
426
427 jnz_i: ; same as imm_w, jnz
428         rst     8 ; ld hl,(bc)+
429         ex      de,hl
430         .db     0x3e ; ld a,
431 jnz:
432         pop     hl
433         ld      a,l
434         or      h
435         jr      z,dispatch_mm1
436         jr      dispatch_l5
437
438 xchg_w:
439         pop     hl
440         jr      dispatch_l1
441
442 dup_w:
443         push    de
444         jr      dispatch_l4
445
446 imm_w:
447         rst     8 ; ld hl,(bc)+
448         jr      dispatch_l1
449
450 add_isp: ; same as imm_w, add_sp
451         rst     8 ; ld hl,(bc)+
452         push    de
453         .db     0x3e ; ld a,
454 add_sp:
455         ex      de,hl
456         add     hl,sp
457         jr      dispatch_l2
458
459 ld_iw: ; same as imm_w, ld_w
460         rst     8 ; ld hl,(bc)+
461         push    de
462         .db     0x3e ; ld a,
463 ld_w:
464         ex      de,hl
465         ld      e,(hl)
466         inc     hl
467         ld      d,(hl)
468         jr      dispatch_l3
469
470 ld_isb: ; same as imm_w, ld_sb
471         rst     8 ; ld hl,(bc)+
472         push    de
473         .db     0x3e ; ld a,
474 ld_sb:
475         ex      de,hl
476         ld      e,(hl)
477         ld      a,e
478         rla
479         sbc     a,a
480         ld      d,a
481         jr      dispatch_l3
482
483 ld_iub: ; same as imm_w, ld_ub
484         rst     8 ; ld hl,(bc)+
485         push    de
486         .db     0x3e ; ld a,
487 ld_ub:
488         ex      de,hl
489         ld      e,(hl)
490         ld      d,0
491         jr      dispatch_l3
492
493 neg_w:
494         dec     de
495 not_w:
496         ld      a,e
497         cpl
498         ld      e,a
499         ld      a,d
500         cpl
501         ld      d,a
502         jr      dispatch_l4
503
504 add_iw: ; same as imm_w, add_w
505         rst     8 ; ld hl,(bc)+
506         .db     0x3e ; ld a,
507 add_w:
508         pop     hl
509         add     hl,de
510         jr      dispatch_l2
511
512 ;sub_iw: ; same as imm_w, sub_w
513 ;       rst     8 ; ld hl,(bc)+
514 ;       .db     0x3e ; ld a,
515 sub_xw: ; same as xchg_w, sub_w
516         pop     hl
517         rst     0x10 ; ex bc,hl
518         .db     0x3e ; ld a,
519 sub_w: ; same as neg_w, add_w
520         pop     hl
521         or      a
522         sbc     hl,de
523         jr      dispatch_l2
524
525 eq_iw: ; same as imm_w, eq_w
526         rst     8 ; ld hl,(bc)+
527         .db     0x3e ; ld a,
528 eq_w:
529         pop     hl
530         sub     a
531         sbc     hl,de
532         ld      e,a
533         ld      d,a
534         jr      nz,dispatch_l3
535         inc     e
536         jr      dispatch_l3
537
538 ; middle dispatch routines
539
540 jmp: ; also means ret
541         ld      c,e
542         ld      b,d
543         jr      dispatch_m0
544
545 adj_isp: ; same as imm_w, adj_sp
546         rst     8 ; ld hl,(bc)+
547         push    de
548         .db     0x3e ; ld a,
549 adj_sp: ; same as add_sp, st_sp
550         ex      de,hl
551         add     hl,sp
552         .db     0x3e ; ld a,
553 st_sp:
554         ex      de,hl
555         ld      sp,hl
556         jr      dispatch_mm1
557
558 ;st_ixw: ; same as imm_w, xchg_w, st_w
559 ;       rst     8 ; ld hl,(bc)+
560 ;       ld      (hl),e
561 ;       inc     hl
562 ;       ld      (hl),d
563 ;       jr      dispatch_mm1
564
565 st_iw: ; same as imm_w, st_w
566         rst     8 ; ld hl,(bc)+
567         ex      de,hl
568         .db     0x3e ; ld a,
569 st_w:
570         pop     hl
571         ld      (hl),e
572         inc     hl
573         ld      (hl),d
574         jr      dispatch_mm1
575
576 st_ixb: ; same as imm_w, xchg_w, st_d
577         rst     8 ; ld hl,(bc)+
578         .db     0x3e ; ld a,
579 st_d:
580         pop     hl
581         ld      (hl),e
582         jr      dispatch_mm1
583
584 ; middle dispatcher, near 0x180, smaller in size
585 ; used for store-type routines that empty stack and need it to be popped
586
587 dispatch_mm1: ; pc in bc
588         ld      h,>esc
589 dispatch_m0: ; pc in bc, h = >esc
590         pop     de
591 dispatch_m4:
592         ld      a,(bc)
593         ld      l,a
594  rst 0x30 ; print stack
595         inc     bc
596         jp      (hl)
597
598 lt_iuw: ; same as imm_w, lt_iuw
599         rst     8 ; ld hl,(bc)+
600         .db     0x3e ; ld a,
601 gt_uw: ; same as xchg_w, lt_uw
602         pop     hl
603         ex      de,hl
604         .db     0x3e ; ld a,
605 lt_uw:
606         pop     hl
607         sub     a
608         sbc     hl,de
609         ld      d,a
610         adc     a,a
611         ld      e,a
612         jr      dispatch_u3
613
614 lt_isw: ; same as imm_w, lt_isw
615         rst     8 ; ld hl,(bc)+
616         .db     0x3e ; ld a,
617 gt_sw: ; same as xchg_w, lt_sw
618         pop     hl
619         ex      de,hl
620         .db     0x3e ; ld a,
621 lt_sw:
622         pop     hl
623         sub     a
624         sbc     hl,de
625         ld      d,a
626         jp      pe,lt_sw_overflow
627         add     hl,hl
628         adc     a,a
629         ld      e,a
630         jr      dispatch_u3
631 lt_sw_overflow:
632         add     hl,hl
633         ccf
634         adc     a,a
635         ld      e,a
636         jr      dispatch_u3
637
638 and_iw: ; same as imm_w, and_w
639         rst     8 ; ld hl,(bc)+
640         .db     0x3e ; ld a,
641 and_w:
642         pop     hl
643         ld      a,l
644         or      e
645         ld      e,a
646         ld      a,h
647         or      d
648         ld      d,a
649         jr      dispatch_u3
650
651 or_iw: ; same as imm_w, and_w
652         rst     8 ; ld hl,(bc)+
653         .db     0x3e ; ld a,
654 or_w:
655         pop     hl
656         ld      a,l
657         or      e
658         ld      e,a
659         ld      a,h
660         or      d
661         ld      d,a
662         jr      dispatch_u3
663
664 xor_iw: ; same as imm_w, and_w
665         rst     8 ; ld hl,(bc)+
666         .db     0x3e ; ld a,
667 xor_w:
668         pop     hl
669         ld      a,l
670         xor     e
671         ld      e,a
672         ld      a,h
673         xor     d
674         ld      d,a
675         jr      dispatch_u3
676
677 ;sl_xw:
678 ;       pop     hl
679 ;       ex      de,hl
680 ;       .db     0x3e ; ld a,
681 sl_w:
682         pop     hl
683         call    sl_hl_e
684         jr      dispatch_u2
685
686 ;sr_xuw:
687 ;       pop     hl
688 ;       ex      de,hl
689 ;       .db     0x3e ; ld a,
690 sr_uw:
691         pop     hl
692         call    srl_hl_e
693         jr      dispatch_u2
694
695 ;sr_xsw:
696 ;       pop     hl
697 ;       ex      de,hl
698 ;       .db     0x3e ; ld a,
699 sr_sw:
700         pop     hl
701         call    sra_hl_e
702         jr      dispatch_u2
703
704 mul_iw:
705         rst     8 ; ld hl,(bc)+
706         .db     0x3e ; ld a,
707 mul_w:
708         pop     hl
709         call    mul_hl_de
710         jr      dispatch_u2
711
712 div_iuw:
713         rst     8 ; ld hl,(bc)+
714         .db     0x3e ; ld a,
715 div_xuw:
716         pop     hl
717         ex      de,hl
718         .db     0x3e ; ld a,
719 div_uw:
720         pop     hl
721         call    div_hl_de
722 ;       jr      dispatch_um1
723
724 ; upper dispatcher, after 0x200
725
726 dispatch_um1: ; tos in hl and de, pc in bc
727         push    hl
728         .db     0x3e ; ld a,
729 ;dispatch_u1: ; tos in de and hl, pc in bc
730 ;       push    de
731 dispatch_u2: ; tos in hl, pc in bc
732         ex      de,hl
733 dispatch_u3: ; tos in de, pc in bc, h clobbered
734         ld      h,>esc
735 dispatch_u4: ; tos in de, pc in bc, h = >esc
736         ld      a,(bc)
737         ld      l,a
738  rst 0x30 ; print stack
739         inc     bc
740         jp      (hl)
741
742 ; math package
743
744 sl_hl_e:
745         ld      a,e
746         and     0xf
747         ret     z
748 1$:     add     hl,hl
749         dec     a
750         jr      nz,1$
751         ret
752
753 srl_hl_e:
754         ld      a,e
755         and     0xf
756         ret     z
757         push    bc
758         ld      b,a
759         ld      a,l
760 srl_hl_loop:
761         srl     h
762         rra
763         djnz    srl_hl_loop
764         ld      l,a
765         pop     bc
766         ret
767
768 sra_hl_e:
769         ld      a,e
770         and     0xf
771         ret     z
772         push    bc
773         ld      b,a
774         ld      a,l
775 sra_hl_loop:
776         sra     h
777         rra
778         djnz    sra_hl_loop
779         ld      l,a
780         pop     bc
781         ret
782
783 mul_hl_de:
784         push    bc
785         ld      a,h
786         ld      c,l
787         ld      hl,0
788         ld      b,8
789 1$:     add     hl,hl
790         rla
791         jr      nc,2$
792         add     hl,de
793 2$:     djnz    1$
794         ld      a,c
795         ld      b,8
796 3$:     add     hl,hl
797         rla
798         jr      nc,4$
799         add     hl,de
800 4$:     djnz    3$
801         pop     bc
802         ret
803
804 div_hl_de:
805         push    bc
806         ld      a,h
807         ld      c,l
808         ld      hl,0
809         ld      b,8
810 1$:     rla
811         adc     hl,hl
812         sbc     hl,de
813         jr      nc,2$
814         add     hl,de
815 2$:     djnz    1$
816         rla
817         cpl
818         push    af
819         ld      a,c
820         ld      b,8
821 3$:     rla
822         adc     hl,hl
823         sbc     hl,de
824         jr      nc,4$
825         add     hl,de
826 4$:     djnz    3$
827         rla
828         cpl
829         pop     de
830         ld      e,a
831         pop     bc
832         ret