page1_st_w:
pop hl
- ld (hl),e
- inc hl
- ld (hl),d
+; ld (hl),e
+; inc hl
+; ld (hl),d
+ call xxxmath_st_w
jr page1_dispatch0
page1_imm_cmprev_sw:
page2_mul_l:
rst 0x30
+ ex de,hl
call math_mul_l
jr mul_l_done
-page1_imm_divrev_sl:
- rst 0x30
- .db 0x3e ; ld a,
-page1_div_sl:
+page2_imm_divrev_sl:
rst 0x38
+ .db 0x3e ; ld a,
+page2_div_sl:
+ rst 0x30
call math_div_sl0
jr div_l_done
-page1_imm_div_sl:
- rst 0x30
- .db 0x3e ; ld a,
-page1_divrev_sl:
+page2_imm_div_sl:
rst 0x38
+ .db 0x3e ; ld a,
+page2_divrev_sl:
+ rst 0x30
ex de,hl
call math_div_sl
jr div_l_done
-page1_imm_divrev_ul:
- rst 0x30
- .db 0x3e ; ld a,
-page1_div_ul:
+page2_imm_divrev_ul:
rst 0x38
+ .db 0x3e ; ld a,
+page2_div_ul:
+ rst 0x30
call math_div_ul0
jr div_l_done
-page1_imm_div_ul:
- rst 0x30
- .db 0x3e ; ld a,
-page1_divrev_ul:
+page2_imm_div_ul:
rst 0x38
+ .db 0x3e ; ld a,
+page2_divrev_ul:
+ rst 0x30
ex de,hl
call math_div_ul
div_l_done:
ld h,a
add hl,sp
; use inline code for math_st_w
+xxxmath_st_w:
+.if 0
+ call print_word
+ ld a,':
+ call print_char
+ ex de,hl
+ call print_word
+ ex de,hl
+ ld a,'
+ call print_char
+.endif
ld (hl),e
inc hl
ld (hl),d
ld h,a
add hl,sp
math_st_l: ; de:hl' to (hl)
+.if 0
+ call print_word
+ ld a,':
+ call print_char
+ ex de,hl
+ call print_word
+ ex de,hl
+ push hl
+ exx
+ push hl
+ exx
+ pop hl
+ call print_word
+ pop hl
+ ld a,'
+ call print_char
+.endif
exx
ld a,l
exx
; debugging
-print_trace: ; print af, bc, de, hl, sp, (sp)
+print_trace: ; print af, bc, de:hl', hl:de', sp, (sp+2):(sp)
push hl
push af
pop hl
ld l,e
ld h,d
call print_word
+ ld a,':
+ call print_char
+ exx
+ push hl
+ exx
+ pop hl
+ call print_word
ld a,'
call print_char
+ pop af
pop hl
push hl
+ push af
+ call print_word
+ ld a,':
+ call print_char
+ exx
+ push de
+ exx
+ pop hl
call print_word
ld a,'
call print_char
call print_word
ld a,'
call print_char
+ ld hl,6
+ add hl,sp
+ ld a,(hl)
+ inc hl
+ ld h,(hl)
+ ld l,a
+ call print_word
+ ld a,':
+ call print_char
+ ld hl,4
+ add hl,sp
ld a,(hl)
inc hl
ld h,(hl)
sm_main:
; create stack frame
.db <page0_stkadj
- .dw -2
+ .dw -4
; push argument
.db <page0_imm_w
- .dw 5
+ .dw 7
; push result pointer
.db <page1_page0
.dw sm_factorial
.dw 4
- ; print 10000s
+ ; let i = 0
+ .db <page0_imm_w
+ .dw 0
+ .db <page1_stkst_w
+ .dw 2+2
+
+digit_loop:
+ ; while i < 5
+ .db <page0_stkld_w
+ .dw 2+2
+ .db <page1_imm_cmp_sw
+ .dw 5
+ .db <page0_jge
+ .dw digit_loope
+
+ ; get current value
.db <page0_stkld_w
.dw 0+2
- .db <page1_imm_div_sw
- .dw 10000
+
+ ; get place value
+ .db <page1_page0
+ .db <page0_stkld_w
+ .dw 4+2
+ .db <page1_imm_sl_w
+ .dw 1
+ .db <page1_imm_add_w
+ .dw place_values
+ .db <page1_ld_w
+
+ ; divide by place value
+ .db <page1_div_sw
+
+ ; replace current value with remainder
.db <page1_stkst_w
.dw 2+2
+
+ ; print quotient plus '0
.db <page0_page1
.db <page1_imm_add_w
.dw '0
.dw sm_print_char
.dw 2
- ; print 1000s
+ ; ++i
.db <page0_stkld_w
- .dw 0+2
- .db <page1_imm_div_sw
- .dw 1000
- .db <page1_stkst_w
.dw 2+2
- .db <page0_page1
.db <page1_imm_add_w
- .dw '0
+ .dw 1
+ .db <page1_stkst_w
+ .dw 2+2
+
+ ; loop
+ .db <page0_imm_jmp
+ .dw digit_loop
+
+digit_loope:
+ ; print cr
+ .db <page0_imm_w
+ .dw 0xd
.db <page1_page0
.db <page0_imm_call
.dw sm_print_char
.dw 2
- ; print 100s
- .db <page0_stkld_w
- .dw 0+2
- .db <page1_imm_div_sw
- .dw 100
- .db <page1_stkst_w
- .dw 2+2
- .db <page0_page1
- .db <page1_imm_add_w
- .dw '0
+ ; print lf
+ .db <page0_imm_w
+ .dw 0xa
.db <page1_page0
.db <page0_imm_call
.dw sm_print_char
.dw 2
- ; print 10s
+ ; enlarge stack frame
+ .db <page0_stkadj
+ .dw -2
+
+ ; push argument
+ .db <page0_imm_l
+ .dw 12,0
+
+ ; push result pointer
+ .db <page2_page0
+ .db <page0_stkptr
+ .dw 4
+
+ ; call sm_factorial(argument)
+ .db <page1_page0
+ .db <page0_imm_call
+ .dw sm_factorial2
+ .dw 6
+
+ ; let i = 0
+ .db <page0_imm_w
+ .dw 0
+ .db <page1_stkst_w
+ .dw 4+2
+
+digit_loop2:
+ ; while i < 10
.db <page0_stkld_w
- .dw 0+2
- .db <page1_imm_div_sw
+ .dw 4+2
+ .db <page1_imm_cmp_sw
.dw 10
- .db <page1_stkst_w
- .dw 2+2
+ .db <page0_jge
+ .dw digit_loope2
+
+ ; get current value
+ .db <page0_stkld_l
+ .dw 0+2
+
+ ; get place value
+ .db <page2_page0
+ .db <page0_stkld_w
+ .dw 8+2
+ .db <page1_imm_sl_w
+ .dw 2
+ .db <page1_imm_add_w
+ .dw place_values2
+ .db <page1_ld_l
+
+ ; divide by place value
+ .db <page2_div_sl
+
+ ; replace current value with remainder
+ .db <page2_stkst_l
+ .dw 4+2
+
+ ; print quotient plus '0
.db <page0_page1
.db <page1_imm_add_w
.dw '0
.db <page1_page0
.db <page0_imm_call
.dw sm_print_char
- .dw 2
+ .dw 4 ; cheating -- kill hi word of long too
- ; print 1s
+ ; ++i
.db <page0_stkld_w
- .dw 0+2
+ .dw 4+2
.db <page1_imm_add_w
- .dw '0
- .db <page1_page0
- .db <page0_imm_call
- .dw sm_print_char
- .dw 2
+ .dw 1
+ .db <page1_stkst_w
+ .dw 4+2
+
+ ; loop
+ .db <page0_imm_jmp
+ .dw digit_loop2
+digit_loope2:
; print cr
.db <page0_imm_w
.dw 0xd
; destroy stack frame
.db <page0_stkadj
- .dw 2
+ .dw 6
; return
.db <page0_ret
+place_values:
+ .dw 10000,1000,100,10,1
+place_values2:
+ .dw 0xca00,0x3b9a ; 1000000000
+ .dw 0xe100,0x5f5 ; 100000000
+ .dw 0x9680,0x98 ; 10000000
+ .dw 0x4240,0xf ; 1000000
+ .dw 0x86a0,1 ; 100000
+ .dw 10000,0
+ .dw 1000,0
+ .dw 100,0
+ .dw 10,0
+ .dw 1,0
+
sm_factorial:
- .db <page0_trace
; get argument
.db <page0_stkld_w
.dw 4+2
.db <page1_st_w
; return
- .db <page0_trace
.db <page0_ret
1$:
.db <page1_st_w
; return
- .db <page0_trace
+ .db <page0_ret
+
+sm_factorial2:
+ ; get argument
+ .db <page0_stkld_l
+ .dw 4+2
+
+ ; is argument < 2?
+ .db <page2_imm_cmp_sl
+ .dw 2
+ .dw 0
+ .db <page0_jlt
+ .dw 1$
+
+ ; no, set up for *result =
+ .db <page0_stkld_w
+ .dw 2+2
+
+ ; get argument
+ .db <page1_page0
+ .db <page0_stkld_l
+ .dw 6+2
+
+ ; subtract 1
+ .db <page2_imm_add_l
+ .dw -1,-1
+
+ ; push result pointer
+ .db <page2_page0
+ .db <page0_stkptr
+ .dw 0
+
+ ; call sm_factorial(argument - 1)
+ .db <page1_page0
+ .db <page0_imm_call
+ .dw sm_factorial2
+ .dw 2
+
+ ; get argument
+ .db <page0_stkld_l
+ .dw 10+2
+
+ ; multiply
+ .db <page2_mul_l
+
+ ; set *result = sm_factorial(argument - 1) * argument
+ .db <page2_st_l
+
+ ; return
+ .db <page0_ret
+
+1$:
+ ; yes, set up for *result =
+ .db <page0_stkld_w
+ .dw 2+2
+
+ ; set *result = 1
+ .db <page1_page0
+ .db <page0_imm_l
+ .dw 1,0
+ .db <page2_st_l
+
+ ; return
.db <page0_ret
sm_print_char: