Working factorial program with the new stack machine
authorNick Downing <nick@ndcode.org>
Sun, 16 Jun 2019 10:55:31 +0000 (20:55 +1000)
committerNick Downing <nick@ndcode.org>
Sun, 16 Jun 2019 11:05:57 +0000 (21:05 +1000)
o.sh [new file with mode: 0755]
sm2.asm

diff --git a/o.sh b/o.sh
new file mode 100755 (executable)
index 0000000..d0956a0
--- /dev/null
+++ b/o.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+#pip3 install --user intelhex
+bin/asz80 -l -o sm2.asm
+bin/aslink -i sm2.ihx sm2.rel
+python3 ~/.local/bin/hex2bin.py sm2.ihx sm2.com
+../z80pack/cpmsim/srctools/cpmw.sh a sm2.com
diff --git a/sm2.asm b/sm2.asm
index 0b52b17..7fed975 100644 (file)
--- a/sm2.asm
+++ b/sm2.asm
@@ -8,7 +8,40 @@ page1  =       2
 
        .org    page0 * 0x100
 
-p0_page1:
+       jp      start
+
+page0_trace:
+       ld      l,c
+       ld      h,b
+       call    print_word
+       ld      a,' 
+       call    print_char
+       ld      hl,0
+       push    af
+       add     hl,sp
+       pop     af
+       call    print_word
+       ld      a,' 
+       call    print_char
+       pop     hl
+       push    hl
+       call    print_word
+       ld      a,0xd
+       call    print_char
+       ld      a,0xa
+       call    print_char
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       ld      h,page0
+       jp      (hl)
+
+page0_esc:
+       ld      l,c
+       ld      h,b
+       jp      (hl)
+
+page0_page1:
        pop     de
        ld      a,(bc)
        inc     bc
@@ -16,7 +49,7 @@ p0_page1:
        inc     h ; page 1
        jp      (hl)
 
-p0_imm_call:
+page0_imm_call:
        ld      a,(bc)  
        inc     bc
        ld      l,a
@@ -30,7 +63,7 @@ p0_imm_call:
        ld      l,a
        jp      (hl)
 
-p0_call:
+page0_call:
        pop     hl
        push    bc
        ld      c,l
@@ -40,8 +73,8 @@ p0_call:
        ld      h,page0
        jp      (hl)
 
-p0_imm_jfalse:
-       jr      nc,p0_imm_jmp
+page0_imm_jfalse:
+       jr      nc,page0_imm_jmp
 imm_not_taken:
        inc     bc
        inc     bc
@@ -50,9 +83,9 @@ imm_not_taken:
        ld      l,a
        jp      (hl)
 
-p0_imm_jtrue:
+page0_imm_jtrue:
        jr      nc,imm_not_taken
-p0_imm_jmp:
+page0_imm_jmp:
        ld      a,(bc)  
        inc     bc
        ld      l,a
@@ -64,8 +97,8 @@ p0_imm_jmp:
        ld      l,a
        jp      (hl)
 
-p0_jfalse:
-       jr      nc,p0_jmp
+page0_jfalse:
+       jr      nc,page0_jmp
 not_taken:
        inc     sp
        inc     sp
@@ -74,18 +107,18 @@ not_taken:
        ld      l,a
        jp      (hl)
 
-p0_jtrue:
+page0_jtrue:
        jr      nc,not_taken
-p0_jmp:
+page0_jmp:
        pop     bc
        ld      a,(bc)
        inc     bc
        ld      l,a
        jp      (hl)
 
-       .org    page0 * 0x100 + 0x8f
+       .org    page0 * 0x100 + 0x83
 
-p0_imm_stkadj:
+page0_imm_stkadj:
 imm_stkadj:
        ld      a,(bc)  
        inc     bc
@@ -94,7 +127,7 @@ imm_stkadj:
        inc     bc
        ld      h,a
        .db     0x3e ; ld a,
-p0_stkadj:
+page0_stkadj:
        pop     hl
 stkadj:
        add     hl,sp
@@ -105,7 +138,7 @@ stkadj:
        ld      h,page0
        jp      (hl)
 
-p0_imm_stkptr:
+page0_imm_stkptr:
 imm_stkptr:
        ld      a,(bc)  
        inc     bc
@@ -114,7 +147,7 @@ imm_stkptr:
        inc     bc
        ld      h,a
        .db     0x3e ; ld a,
-p0_stkptr:
+page0_stkptr:
        pop     hl
 stkptr:
        add     hl,sp
@@ -125,7 +158,7 @@ stkptr:
        ld      h,page1
        jp      (hl)
 
-p0_imm_stkld_w:
+page0_imm_stkld_w:
 imm_stkld_w:
        ld      a,(bc)  
        inc     bc
@@ -134,7 +167,7 @@ imm_stkld_w:
        inc     bc
        ld      h,a
        .db     0x3e ; ld a,
-p0_stkld_w:
+page0_stkld_w:
        pop     hl
 stkld_w:
        add     hl,sp
@@ -147,16 +180,29 @@ stkld_w:
        ld      h,page1
        jp      (hl)
 
-p0_imm_stkst_w:
+page0_imm_stkstrev_w:
        pop     de
-imm_stkst_w:
+imm_stkstrev_w:
        ld      a,(bc)  
        inc     bc
        ld      l,a
        ld      a,(bc)
        inc     bc
        ld      h,a
+       add     hl,sp
+       ld      (hl),e
+       inc     hl
+       ld      (hl),d
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       ld      h,page0
+       jp      (hl)
+
+page0_stkst_w:
+       pop     de
 stkst_w:
+       pop     hl
        add     hl,sp
        ld      (hl),e
        inc     hl
@@ -167,7 +213,7 @@ stkst_w:
        ld      h,page0
        jp      (hl)
 
-p0_imm_w:
+page0_imm_w:
        inc     h ; page1
 imm_w:
        ld      a,(bc)
@@ -181,7 +227,7 @@ imm_w:
        ld      l,a
        jp      (hl)
 
-p0_ld_w:
+page0_ld_w:
        pop     de
        inc     h ; page1
 ld_w:
@@ -196,7 +242,7 @@ ld_w:
        ld      l,a
        jp      (hl)
 
-p0_imm_st_w:
+page0_imm_st_w:
        pop     de
 imm_st_w:
        ld      a,(bc)
@@ -211,7 +257,7 @@ imm_st_w:
        ld      l,a
        jp      (hl)
 
-p0_st_w:
+page0_st_w:
        pop     de
 st_w:
        pop     hl
@@ -230,48 +276,48 @@ st_w:
 
        .org    page1 * 0x100
 
-p1_page0:
-       push    de
-       ld      a,(bc)
-       inc     bc
-       ld      l,a
-       dec     h ; page 0
-       jp      (hl)
-
-p1_imm_stkadj:
+page1_imm_stkadj:
        push    de
        jr      imm_stkadj
-p1_stkadj:
+page1_stkadj:
        ex      de,hl
        jr      stkadj
-p1_imm_stkptr:
+page1_imm_stkptr:
        push    de
        jr      imm_stkptr
-p1_stkptr:
+page1_stkptr:
        ex      de,hl
        jr      stkptr
-p1_imm_stkld_w:
+page1_imm_stkld_w:
        push    de
        jr      imm_stkld_w
-p1_stkld_w:
+page1_stkld_w:
        ex      de,hl
        jr      stkld_w
-p1_imm_stkst_w:
-       jr      imm_stkst_w
-p1_stkst_w:
-       push    de
+page1_imm_stkstrev_w:
+       jr      imm_stkstrev_w
+page1_stkst_w:
        jr      stkst_w
-p1_imm_w:
+page1_imm_w:
+       push    de
        jr      imm_w
-p1_ld_w:
+page1_ld_w:
        jr      ld_w
-p1_imm_st_w:
+page1_imm_st_w:
        dec     h ; page0
        jr      imm_st_w
-p1_st_w:
+page1_st_w:
        jr      st_w
 
-p1_imm_and_w:
+page1_page0:
+       push    de
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       dec     h ; page 0
+       jp      (hl)
+
+page1_imm_and_w:
        ld      a,(bc)
        inc     bc
        and     e
@@ -285,7 +331,7 @@ p1_imm_and_w:
        ld      l,a
        jp      (hl)
 
-p1_and_w:
+page1_and_w:
        pop     hl
        ld      a,e
        and     l
@@ -299,7 +345,7 @@ p1_and_w:
        ld      h,page1
        jp      (hl)
 
-p1_imm_or_w:
+page1_imm_or_w:
        ld      a,(bc)
        inc     bc
        or      e
@@ -313,7 +359,7 @@ p1_imm_or_w:
        ld      l,a
        jp      (hl)
 
-p1_or_w:
+page1_or_w:
        pop     hl
        ld      a,e
        or      l
@@ -327,7 +373,7 @@ p1_or_w:
        ld      h,page1
        jp      (hl)
 
-;p1_imm_xor_w:
+;page1_imm_xor_w:
 ;      ld      a,(bc)
 ;      inc     bc
 ;      xor     e
@@ -341,7 +387,7 @@ p1_or_w:
 ;      ld      l,a
 ;      jp      (hl)
 
-p1_imm_xor_w: ; xor is less common than and/or, so save space for immediate
+page1_imm_xor_w: ; xor is less common than and/or, so save space for immediate
        ld      a,(bc)
        ld      l,a
        inc     bc
@@ -349,7 +395,7 @@ p1_imm_xor_w: ; xor is less common than and/or, so save space for immediate
        ld      h,a
        inc     bc
        .db     0x3e ; ld a,
-p1_xor_w:
+page1_xor_w:
        pop     hl
        ld      a,e
        xor     l
@@ -363,7 +409,7 @@ p1_xor_w:
        ld      h,page1
        jp      (hl)
 
-p1_imm_add_w: ; use also for p1_imm_sub_w with negated argument
+page1_imm_add_w: ; use also for page1_imm_sub_w with negated argument
        ld      a,(bc)
        ld      l,a
        inc     bc
@@ -371,7 +417,7 @@ p1_imm_add_w: ; use also for p1_imm_sub_w with negated argument
        ld      h,a
        inc     bc
        .db     0x3e ; ld a,
-p1_add_w:
+page1_add_w:
        pop     hl
        add     hl,de
        ex      de,hl
@@ -381,7 +427,7 @@ p1_add_w:
        ld      h,page1
        jp      (hl)
 
-p1_imm_subr_w: ; reversed, use with argument 0 for neg, -1 for cpl
+page1_imm_subrev_w: ; reversed, use with argument 0 for neg, -1 for cpl
        ld      a,(bc)
        ld      l,a
        inc     bc
@@ -389,7 +435,7 @@ p1_imm_subr_w: ; reversed, use with argument 0 for neg, -1 for cpl
        ld      h,a
        inc     bc
        .db     0x3e ; ld a,
-p1_sub_w:
+page1_sub_w:
        pop     hl
        or      a
        sbc     hl,de
@@ -401,7 +447,7 @@ mul_done:
        ld      h,page1
        jp      (hl)
 
-p1_imm_eq_w:
+page1_imm_eq_w:
        ld      a,(bc)
        ld      l,a
        inc     bc
@@ -409,7 +455,7 @@ p1_imm_eq_w:
        ld      h,a
        inc     bc
        .db     0x3e ; ld a,
-p1_eq_w:
+page1_eq_w:
        pop     hl
        or      a
        sbc     hl,de
@@ -422,7 +468,7 @@ p1_eq_w:
        ld      h,page0
        jp      (hl)
 
-p1_imm_gt_uw:
+page1_imm_gt_uw:
        ld      a,(bc)
        ld      l,a
        inc     bc
@@ -430,7 +476,7 @@ p1_imm_gt_uw:
        ld      h,a
        inc     bc
        .db     0x3e ; ld a,
-p1_lt_uw:
+page1_lt_uw:
        pop     hl
        or      a
        sbc     hl,de
@@ -440,88 +486,94 @@ p1_lt_uw:
        ld      h,page0
        jp      (hl)
 
-p1_imm_gt_sw:
-       ld      a,(bc)
-       ld      l,a
-       inc     bc
-       ld      a,(bc)
-       ld      h,a
-       inc     bc
-       .db     0x3e ; ld a,
-p1_lt_sw:
-       pop     hl
-       ld      a,l
-       sub     e
-       ld      a,h
-       sbc     a,d
-       rla
-       jp      po,1$
-       ccf
-1$:    ld      a,(bc)
-       inc     bc
-       ld      l,a
-       ld      h,page0
-       jp      (hl)
-
-p1_imm_sl_w: ; nonzero unsigned byte argument
+page1_imm_sl_w: ; nonzero unsigned byte argument
        jr      imm_sl_w
 
-p1_sl_w:
+page1_sl_w:
        pop     hl
        inc     e
        jr      sl_loope
 
-p1_imm_sr_uw: ; nonzero unsigned byte argument
+page1_imm_sr_uw: ; nonzero unsigned byte argument
        jr      imm_sr_uw
 
-p1_sr_uw:
+page1_sr_uw:
        ld      l,e
        pop     de
        ld      a,e
        inc     l
        jr      srl_loope
 
-p1_imm_sr_sw: ; nonzero unsigned byte argument
+page1_imm_sr_sw: ; nonzero unsigned byte argument
        jr      imm_sr_sw
 
-p1_sr_sw:
+page1_sr_sw:
        ld      l,e
        pop     de
        ld      a,e
        inc     l
        jr      sra_loope
 
-p1_imm_mul_w: ; big endian argument
+page1_div_sw:
+       pop     hl
+       call    div_sw
+div_done:
+       push    de
+       ex      de,hl
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       ld      h,page1
+       jp      (hl)
+
+page1_div_uw:
+       ld      l,<div_done
+       ex      (sp),hl
+       jr      div_uw
+
+page1_imm_div_sw:
+       jr      imm_div_sw
+
+page1_imm_div_uw:
+       jr      imm_div_uw
+
+page1_imm_mul_w: ; big endian argument
        ld      l,mul_done
        push    hl
        ld      a,(bc)
        inc     bc
        ld      hl,0
-       call    mul
+       call    mul0
        ld      a,(bc)
        inc     bc
-       jr      mul
+       jp      mul ; a shame it can't be jr
 
-p1_mul_w:
+page1_mul_w:
        ld      l,<mul_done
        ex      (sp),hl
        jr      mul_w
 
-p1_div_uw:
-       ld      l,<div_done
-       ex      (sp),hl
-       jr      div_uw
-
-p1_div_sw:
-       pop     hl
-       call    div_sw
-div_done:
-       push    de
-       ex      de,hl
+page1_imm_gt_sw:
+       ld      a,(bc)
+       ld      l,a
+       inc     bc
        ld      a,(bc)
+       ld      h,a
+       inc     bc
+       .db     0x3e ; ld a,
+page1_lt_sw: ; put this at the end because it's the longest one
+       pop     hl
+       ld      a,l
+       sub     e
+       ld      a,h
+       sbc     a,d
+       rla
+       jp      po,1$
+       ccf
+1$:    ld      a,(bc)
        inc     bc
        ld      l,a
-       ld      h,page1
+       ld      h,page0
        jp      (hl)
 
 ; math package
@@ -577,16 +629,69 @@ sra_loope:
        ld      l,a
        jp      (hl)
 
-mul_w:
+imm_div_uw:
+       ld      l,div_done
+       push    hl
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       ld      a,(bc)
+       inc     bc
+       ld      h,a
+       ex      de,hl
+div_uw:
+       push    bc
+       ld      a,h
+       ld      c,l
+       ld      hl,0
+divpp: ; positive dividend, positive divisor
+       call    div0
+       ld      b,a
+       ld      a,c
+       call    div
+       jr      nc,1$
+       add     hl,de
+1$:    ld      d,b
+       ld      e,a
+       pop     bc
+       ret
+
+imm_div_sw:
+       ld      l,div_done
+       push    hl
+       ld      a,(bc)
+       inc     bc
+       ld      l,a
+       ld      a,(bc)
+       inc     bc
+       ld      h,a
+       ex      de,hl
+div_sw:
+       push    bc
+       ld      a,h
+       or      a
+       ld      a,d
+       rla
+       jp      p,divp                  ; positive dividend
+
+       ; negative dividend
+       dec     hl                      ; reduces remainder by 1 (we inc later)
+       ld      a,h
+       ld      c,l
+       ld      hl,-1
+       jr      nc,divnp ; a shame it can't be a fallthru
+       jr      divnn                   ; negative dividend, negative divisor
+
+mul_w: ; mul placed as soon as possible after all div entry points
        ld      a,l
        push    af
        ld      a,h
        ld      hl,0
-       call    mul
+       call    mul0
        pop     af
 mul:   ; bit 0
        add     hl,hl
-       rla
+mul0:  rla
        jr      nc,1$
        add     hl,de
 1$:    ; bit 1
@@ -626,40 +731,26 @@ mul:      ; bit 0
        add     hl,de
        ret
 
-div_uw:
-       push    bc
+divp:  ; positive dividend
        ld      a,h
        ld      c,l
        ld      hl,0
+       jr      nc,divpp                ; positive dividend, positive divisor
 
-divu:  ; positive dividend, positive divisor
-       call    div0
+       ; positive dividend, negative divisor
+       call    divn1
        ld      b,a
        ld      a,c
-       call    div
-       jr      nc,1$
-       add     hl,de
+       call    divn
+       inc     a
+       jr      c,1$
+       sbc     hl,de
 1$:    ld      d,b
        ld      e,a
        pop     bc
        ret
 
-div_sw:
-       push    bc
-       ld      a,h
-       or      a
-       ld      a,d
-       rla
-       jp      p,4$                    ; positive dividend
-
-       ; negative dividend
-       dec     hl                      ; reduces remainder by 1 (we inc later)
-       ld      a,h
-       ld      c,l
-       ld      hl,-1
-       jr      c,2$                    ; negative dividend, negative divisor
-
-       ; negative dividend, positive divisor
+divnp: ; negative dividend, positive divisor
        call    div1
        ld      b,a
        ld      a,c
@@ -673,38 +764,19 @@ div_sw:
        pop     bc
        ret
 
-2$:    ; negative dividend, negative divisor
+divnn: ; negative dividend, negative divisor
        call    divn0
        ld      b,a
        ld      a,c
        call    divn
-       jr      nc,3$
+       jr      nc,1$
        add     hl,de
-3$:    inc     hl                      ; get into range divisor+1..0
+1$:    inc     hl                      ; get into range divisor+1..0
        ld      d,b
        ld      e,a
        pop     bc
        ret
 
-4$:    ; positive dividend
-       ld      a,h
-       ld      c,l
-       ld      hl,0
-       jr      nc,divu                 ; positive dividend, positive divisor
-
-       ; positive dividend, negative divisor
-       call    divn1
-       ld      b,a
-       ld      a,c
-       call    divn
-       inc     a
-       jr      c,5$
-       sbc     hl,de
-5$:    ld      d,b
-       ld      e,a
-       pop     bc
-       ret
-
 ; non-restoring division routine
 
 ; de = divisor, hl:a = dividend with hl = previous remainder, a = next byte
@@ -1024,3 +1096,205 @@ print_char:
        pop     de
        pop     bc
        ret
+
+; sm code
+
+start:
+       ld      h,page0
+       call    page0_jmp
+       .db     <page0_imm_call
+       .dw     sm_main
+       .db     <page0_esc
+       jp      0
+
+sm_main:
+       ; create stack frame
+       .db     <page0_imm_stkadj
+       .dw     -2
+
+       ; push argument
+       .db     <page0_imm_w
+       .dw     5
+
+       ; push result pointer
+       .db     <page1_imm_stkptr
+       .dw     2
+
+       ; call sm_factorial(argument)
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_factorial
+       .db     <page0_imm_stkadj
+       .dw     4
+
+       ; print 10000s
+       .db     <page0_imm_stkld_w
+       .dw     0
+       .db     <page1_imm_div_sw
+       .dw     10000
+       .db     <page1_imm_stkstrev_w
+       .dw     2
+       .db     <page0_page1
+       .db     page1_imm_add_w
+       .dw     '0
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print 1000s
+       .db     <page0_imm_stkld_w
+       .dw     0
+       .db     <page1_imm_div_sw
+       .dw     1000
+       .db     <page1_imm_stkstrev_w
+       .dw     2
+       .db     <page0_page1
+       .db     page1_imm_add_w
+       .dw     '0
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print 100s
+       .db     <page0_imm_stkld_w
+       .dw     0
+       .db     <page1_imm_div_sw
+       .dw     100
+       .db     <page1_imm_stkstrev_w
+       .dw     2
+       .db     <page0_page1
+       .db     page1_imm_add_w
+       .dw     '0
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print 10s
+       .db     <page0_imm_stkld_w
+       .dw     0
+       .db     <page1_imm_div_sw
+       .dw     10
+       .db     <page1_imm_stkstrev_w
+       .dw     2
+       .db     <page0_page1
+       .db     page1_imm_add_w
+       .dw     '0
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print 1s
+       .db     <page0_imm_stkld_w
+       .dw     0
+       .db     page1_imm_add_w
+       .dw     '0
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print cr
+       .db     <page0_imm_w
+       .dw     0xd
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; print lf
+       .db     <page0_imm_w
+       .dw     0xa
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_print_char
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; destroy stack frame
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; return
+       .db     <page0_jmp
+
+sm_factorial:
+ .db <page0_trace
+       ; get argument
+       .db     <page0_imm_stkld_w
+       .dw     4
+
+       ; is argument < 2?
+       .db     <page1_imm_gt_sw
+       .dw     1
+       .db     <page0_imm_jfalse
+       .dw     1$
+       
+       ; no, set up for *result =
+       .db     <page0_imm_stkld_w
+       .dw     2
+
+       ; get argument
+       .db     <page1_imm_stkld_w
+       .dw     6
+
+       ; subtract 1
+       .db     <page1_imm_add_w
+       .dw     -1
+
+       ; push result pointer
+       .db     <page1_imm_stkptr
+       .dw     0
+
+       ; call sm_factorial(argument - 1)
+       .db     <page1_page0
+       .db     <page0_imm_call
+       .dw     sm_factorial
+       .db     <page0_imm_stkadj
+       .dw     2
+
+       ; get argument
+       .db     <page0_imm_stkld_w
+       .dw     8
+
+       ; multiply
+       .db     <page1_mul_w
+
+       ; set *result = sm_factorial(argument - 1) * argument
+       .db     <page1_st_w
+
+       ; return 
+ .db <page0_trace
+       .db     <page0_jmp
+
+1$:
+       ; yes, set up for *result =
+       .db     <page0_imm_stkld_w
+       .dw     2
+
+       ; set *result = 1
+       .db     page1_imm_w
+       .dw     1
+       .db     <page1_st_w
+
+       ; return
+ .db <page0_trace
+       .db     <page0_jmp
+
+sm_print_char:
+       .db     <page0_esc
+       ld      hl,2
+       add     hl,sp
+       ld      a,(hl)
+       call    print_char
+       ld      h,page0
+       jp      page0_jmp