--- /dev/null
+ .area SM (abs,ovr)
+
+ .org 0x100
+
+ ld hl,0x308
+ ld de,8
+ ld bc,0x38 ;0x10
+ ldir
+
+ call sm
+
+ ; push argument
+ .db <imm_w
+ .dw 5
+
+ ; push result pointer
+ .db <add_isp
+ .dw 0
+
+ ; call sm_factorial(argument)
+ .db <call_i
+ .dw sm_factorial
+ .db <adj_isp
+ .dw 2
+
+ .db esc
+ rst 0x10 ; ex bc,hl
+ call print_word
+ jp print_crlf
+
+sm_factorial:
+ ; get argument
+ .db <add_isp
+ .dw 4
+ .db <ld_w
+
+ ; is argument < 2?
+ .db <lt_isw
+ .dw 2
+ .db <jnz_i
+ .dw 1$
+
+ ; no, set up for *result =
+ .db <add_isp
+ .dw 2
+ .db <ld_w
+
+ ; get argument
+ .db <add_isp
+ .dw 6
+ .db <ld_w
+
+ ; subtract 1
+ .db <add_iw
+ .dw -1
+
+ ; push result pointer
+ .db <add_isp
+ .dw 0
+
+ ; call sm_factorial(argument - 1)
+ .db <call_i
+ .dw sm_factorial
+ .db <adj_isp
+ .dw 2
+
+ ; get argument
+ .db <add_isp
+ .dw 8
+ .db <ld_w
+
+ ; multiply
+ .db <mul_w
+
+ ; set *result = sm_factorial(argument - 1) * argument
+ .db <st_w
+
+ ; return
+ .db <jmp
+
+1$: ; yes, set up for *result =
+ .db <add_isp
+ .dw 2
+ .db <ld_w
+
+ ; set *result = 1
+ .db <st_iw
+ .dw 1
+
+ ; return
+ .db <jmp
+
+digits:
+ .ascii '0123456789abcdef'
+
+print_word:
+ push af
+ ld a,h
+ call print_byte
+ ld a,l
+ call print_byte
+ pop af
+ ret
+
+print_byte:
+ push af
+ push af
+ rrca
+ rrca
+ rrca
+ rrca
+ call print_digit
+ pop af
+ call print_digit
+ pop af
+ ret
+
+print_digit:
+ push de
+ push hl
+ and 0xf
+ ld e,a
+ ld d,0
+ ld hl,digits
+ add hl,de
+ ld a,(hl)
+ pop hl
+ pop de
+ jr print_char
+
+print_space:
+ push af
+ ld a,0x20
+ call print_char
+ pop af
+ ret
+
+print_stack:
+ push de
+ push hl
+ ld hl,6
+ add hl,sp
+ call print_word
+ call print_space
+ rst 0x10 ; ex bc,hl
+ call print_word
+ rst 0x10 ; ex bc,hl
+ call print_space
+ ld e,(hl)
+ inc hl
+ ld d,(hl)
+ inc hl
+ ex de,hl
+ call print_word
+ ex de,hl
+ call print_space
+ ld e,(hl)
+ inc hl
+ ld d,(hl)
+ inc hl
+ ex de,hl
+ call print_word
+ ex de,hl
+ call print_space
+ ld e,(hl)
+ inc hl
+ ld d,(hl)
+ ;inc hl
+ ex de,hl
+ call print_word
+ ex de,hl
+ pop hl
+ pop de
+print_crlf:
+ push af
+ ld a,0xd
+ call print_char
+ ld a,0xa
+ call print_char
+ pop af
+ ret
+
+print_char:
+ push bc
+ push de
+ push hl
+ ld e,a
+ ld c,2
+ call 5
+ pop hl
+ pop de
+ pop bc
+ ret
+
+ .org 0x308
+
+; ld hl,(de)+
+ ex de,hl
+ ld e,(hl)
+ inc hl
+ ld d,(hl)
+ inc hl
+ ex de,hl
+ ret
+
+ .org 0x310
+
+; ex bc,hl
+ ld a,l
+ ld l,c
+ ld c,a
+ ld a,h
+ ld h,b
+ ld b,a
+ ret
+
+ .org 0x318
+
+; print bc
+ rst 0x10 ; ex bc,hl
+ call print_word
+ rst 0x10 ; ex bc,hl
+ jp print_space
+
+ .org 0x320
+
+; print de
+ ex de,hl
+ call print_word
+ ex de,hl
+ jp print_space
+
+ .org 0x328
+
+; print hl
+ call print_word
+ jp print_space
+
+ .org 0x330
+
+; print stack
+ jp print_stack
+
+ .org 0x338
+
+; print 'A'
+ push af
+ ld a,0x41
+ call print_char
+ pop af
+ ret
+
+; lower dispatcher, just before 0x100
+
+ .org 0x3ed
+
+sm:
+ pop hl
+ .db 0x11 ; ld de,
+
+dispatch_l5m1: ; pc in bc
+ rst 0x10 ; ex bc,hl
+dispatch_l5: ; pc in hl
+ pop bc
+dispatch_l6: ; tos in bc, pc in hl, d clobbered
+ ld d,>esc
+dispatch_l7: ; tos in bc, pc in hl, d = >esc
+ rst 0x28 ; print hl
+ ld e,(hl)
+ inc hl
+ ex de,hl
+ rst 0x28 ; print hl
+ rst 0x30 ; print stack
+ jp (hl)
+
+dispatch_l1: ; tos in bc and hl, pc in de
+ push bc
+dispatch_l2: ; tos in hl, pc in de
+ ld c,l
+ ld b,h
+dispatch_l3: ; tos in bc, pc in de, h clobbered
+ ld h,>esc
+dispatch_l4: ; tos in bc, pc in de, h = >esc
+ rst 0x20 ; print de
+ ld a,(de)
+ ld l,a
+ inc de
+ rst 0x28 ; print hl
+ rst 0x30 ; print stack
+ jp (hl)
+
+; 0x100
+
+esc:
+ ex de,hl
+ jp (hl)
+
+call_i: ; same as imm_w, call
+ rst 8 ; ld hl,(de)+
+ push bc
+ ld c,e
+ ld b,d
+ jr dispatch_l6
+
+_call:
+ ex de,hl
+ rst 0x10 ; ex bc,hl
+ jr dispatch_l6
+
+jmp_i: ; same as imm_w, jmp
+ rst 8 ; ld hl,(de)+
+ jr dispatch_l7
+
+jz_i: ; same as imm_w, jz
+ rst 8 ; ld hl,(de)+
+ rst 0x10 ; ex bc, hl
+ .db 0x3e ; ld a,
+jz:
+ pop hl
+ ld a,l
+ or h
+ jr nz,dispatch_mm1
+ jr dispatch_l5m1
+
+jnz_i: ; same as imm_w, jnz
+ rst 8 ; ld hl,(de)+
+ rst 0x10 ; ex bc, hl
+ .db 0x3e ; ld a,
+jnz:
+ pop hl
+ ld a,l
+ or h
+ jr z,dispatch_mm1
+ jr dispatch_l5m1
+
+;jmp_x: ; same as xchg_w, jmp
+; pop hl
+; jr dispatch_l6
+
+jmp: ; also means ret
+ ld e,c
+ ld d,b
+ jr dispatch_m0
+
+xchg_w:
+ pop hl
+ jr dispatch_l1
+
+dup_w:
+ push bc
+ jr dispatch_l4
+
+imm_w:
+ rst 8 ; ld hl,(de)+
+ jr dispatch_l1
+
+adj_isp: ; same as imm_w, adj_sp
+ rst 8 ; ld hl,(de)+
+ push bc
+ .db 0x3e ; ld a,
+adj_sp: ; same as add_sp, st_sp
+ rst 0x10 ; ex bc,hl
+ add hl,sp
+ .db 0x3e ; ld a,
+st_sp:
+ rst 0x10 ; ex bc,hl
+ ld sp,hl
+ jr dispatch_mm1
+
+add_isp: ; same as imm_w, add_sp
+ rst 8 ; ld hl,(de)+
+ push bc
+ .db 0x3e ; ld a,
+add_sp:
+ rst 0x10 ; ex bc,hl
+ add hl,sp
+ jr dispatch_l2
+
+ld_iw: ; same as imm_w, ld_w
+ rst 8 ; ld hl,(de)+
+ push bc
+ .db 0x3e ; ld a,
+ld_w:
+ rst 0x10 ; ex bc,hl
+ ld c,(hl)
+ inc hl
+ ld b,(hl)
+ jr dispatch_l3
+
+ld_isb: ; same as imm_w, ld_sb
+ rst 8 ; ld hl,(de)+
+ push bc
+ .db 0x3e ; ld a,
+ld_sb:
+ rst 0x10 ; ex bc,hl
+ ld c,(hl)
+ ld a,c
+ rla
+ sbc a,a
+ ld b,a
+ jr dispatch_l3
+
+ld_iub: ; same as imm_w, ld_ub
+ rst 8 ; ld hl,(de)+
+ push bc
+ .db 0x3e ; ld a,
+ld_ub:
+ rst 0x10 ; ex bc,hl
+ ld c,(hl)
+ ld b,0
+ jr dispatch_l3
+
+;st_ixw: ; same as imm_w, xchg_w, st_w
+; rst 8 ; ld hl,(de)+
+; ld (hl),c
+; inc hl
+; ld (hl),b
+; jr dispatch_mm1
+
+st_iw: ; same as imm_w, st_w
+ rst 8 ; ld hl,(de)+
+ rst 0x10 ; ex bc,hl
+ .db 0x3e ; ld a,
+st_w:
+ pop hl
+ ld (hl),c
+ inc hl
+ ld (hl),b
+ jr dispatch_mm1
+
+st_ixb: ; same as imm_w, xchg_w, st_b
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+st_b:
+ pop hl
+ ld (hl),c
+ jr dispatch_mm1
+
+neg_w:
+ dec bc
+not_w:
+ ld a,c
+ cpl
+ ld c,a
+ ld a,b
+ cpl
+ ld b,a
+ jr dispatch_l4
+
+; middle dispatcher, near 0x180, smaller in size
+; used for store-type routines that empty stack and need it to be popped
+
+dispatch_mm1: ; pc in de
+ ld h,>esc
+dispatch_m0: ; pc in de, h = >esc
+ pop bc
+dispatch_m4:
+ rst 0x20 ; print de
+ ld a,(de)
+ ld l,a
+ inc de
+ rst 0x28 ; print hl
+ rst 0x30 ; print stack
+ jp (hl)
+
+add_iw: ; same as imm_w, add_w
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+add_w:
+ pop hl
+ add hl,bc
+ jr dispatch_u2
+
+;sub_iw: ; same as imm_w, sub_w
+; rst 8 ; ld hl,(de)+
+; .db 0x3e ; ld a,
+sub_xw: ; same as xchg_w, sub_w
+ pop hl
+ rst 0x10
+ .db 0x3e ; ld a,
+sub_w: ; same as neg_w, add_w
+ pop hl
+ or a
+ sbc hl,bc
+ jr dispatch_u2
+
+mul_iw:
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+mul_w:
+ pop hl
+ push de
+ call mul_bc_hl
+ pop de
+ jr dispatch_u2
+
+eq_iw: ; same as imm_w, eq_w
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+eq_w:
+ pop hl
+ sub a
+ sbc hl,bc
+ ld c,a
+ ld b,a
+ jr nz,dispatch_u3
+ inc c
+ jr dispatch_u3
+
+lt_iuw: ; same as imm_w, lt_iuw
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+gt_uw: ; same as xchg_w, lt_uw
+ pop hl
+ rst 0x10 ; ex bc,hl
+ .db 0x3e ; ld a,
+lt_uw:
+ pop hl
+ sub a
+ sbc hl,bc
+ ld b,a
+ adc a,a
+ ld c,a
+ jr dispatch_u3
+
+lt_isw: ; same as imm_w, lt_isw
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+gt_sw: ; same as xchg_w, lt_sw
+ pop hl
+ rst 0x10 ; ex bc,hl
+ .db 0x3e ; ld a,
+lt_sw:
+ pop hl
+ sub a
+ sbc hl,bc
+ ld b,a
+ jp pe,lt_sw_overflow
+ add hl,hl
+ adc a,a
+ ld c,a
+ jr dispatch_u3
+lt_sw_overflow:
+ add hl,hl
+ ccf
+ adc a,a
+ ld c,a
+ jr dispatch_u3
+
+and_iw: ; same as imm_w, and_w
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+and_w:
+ pop hl
+ ld a,l
+ or c
+ ld c,a
+ ld a,h
+ or b
+ ld b,a
+ jr dispatch_u3
+
+or_iw: ; same as imm_w, and_w
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+or_w:
+ pop hl
+ ld a,l
+ or c
+ ld c,a
+ ld a,h
+ or b
+ ld b,a
+ jr dispatch_u3
+
+xor_iw: ; same as imm_w, and_w
+ rst 8 ; ld hl,(de)+
+ .db 0x3e ; ld a,
+xor_w:
+ pop hl
+ ld a,l
+ xor c
+ ld c,a
+ ld a,h
+ xor b
+ ld b,a
+ jr dispatch_u3
+
+sl_w:
+ pop hl
+ call sl_hl_c
+ jr dispatch_u2
+
+sr_uw:
+ pop hl
+ call srl_hl_c
+ jr dispatch_u2
+
+sr_sw:
+ pop hl
+ call sra_hl_c
+ jr dispatch_u2
+
+; upper dispatcher, after 0x200
+
+dispatch_u1: ; tos in bc and hl, pc in de
+ push bc
+dispatch_u2: ; tos in hl, pc in de
+ ld c,l
+ ld b,h
+dispatch_u3: ; tos in bc, pc in de, h clobbered
+ ld h,>esc
+dispatch_u4: ; tos in bc, pc in de, h = >esc
+ rst 0x20 ; print de
+ ld a,(de)
+ ld l,a
+ inc de
+ rst 0x28 ; print hl
+ rst 0x30 ; print stack
+ jp (hl)
+
+; math package
+
+sl_hl_c:
+ ld a,c
+sl_hl_a:
+ and 0xf
+ ret z
+ ld b,a
+1$: add hl,hl
+ djnz 1$
+ ret
+
+srl_hl_c:
+ ld a,c
+srl_hl_a:
+ and 0xf
+ ret z
+ ld b,a
+ ld a,l
+srl_hl_loop:
+ srl h
+ rra
+ djnz srl_hl_loop
+ ld l,a
+ ret
+
+sra_hl_c:
+ ld a,c
+sra_hl_a:
+ and 0xf
+ ret z
+ ld b,a
+ ld a,l
+sra_hl_loop:
+ sra h
+ rra
+ djnz sra_hl_loop
+ ld l,a
+ ret
+
+mul_bc_hl:
+ ex de,hl
+mul_bc_de:
+ ld hl,0
+ ld a,b
+ ld b,8
+1$: add hl,hl
+ rla
+ jr nc,2$
+ add hl,de
+2$: djnz 1$
+ ld a,c
+ ld b,8
+3$: add hl,hl
+ rla
+ jr nc,4$
+ add hl,de
+4$: djnz 3$
+ ret