From f3a92708d23d7822e4433f685313970a42047c9b Mon Sep 17 00:00:00 2001 From: Brooke Vibber Date: Sat, 22 Aug 2026 18:48:05 -0700 Subject: [PATCH] unclobber arg in sqr16 this'll make it easier to use direct targets bypassing function args costs 2 cycles on negatives in this version for now but it should save us later --- mandel-core.s | 137 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 82 insertions(+), 55 deletions(-) diff --git a/mandel-core.s b/mandel-core.s index 2777bda..64c5540 100644 --- a/mandel-core.s +++ b/mandel-core.s @@ -533,6 +533,20 @@ input_max: neg 4, arg .endmacro +.macro copy_neg bytes, dest, arg + sec ; 2 cyc + .repeat bytes, byte ; 8 * byte cycles + lda #00 ; 2 cyc + sbc arg + byte ; 3 cyc + sta dest + byte ; 3 cyc + .endrepeat +.endmacro + +; 18 cycles +.macro copy_neg16 dest, arg + copy_neg 2, dest, arg +.endmacro + ; 11-27 + 18 * shift cycles ; 65-81 cycles for shift=3 .macro shift_round_16 arg, shift @@ -790,70 +804,58 @@ inner_loop: ; min ext-mem: 50 * 4 + 22 * 2 + 10 + 6 = 260 cyc ; max ext-mem: 55 * 4 + 27 * 2 + 50 + 6 = 330 cyc .macro imul16_impl xe - .local arg1 - .local arg2 - .local result - .local inter - .local arg1_pos - .local arg2_pos - arg1 = FR0 ; 16-bit arg (clobbered) - arg2 = FR1 ; 16-bit arg (clobbered) - result = FR2 ; 32-bit result - inter = temp2 + .scope + arg1 = FR0 ; 16-bit arg + arg2 = FR1 ; 16-bit arg + result = FR2 ; 32-bit result (output) + inter = temp2 ; 16-bit temporary (clobbered) - ; h1l1 * h2l2 - ; (h1*256 + l1) * (h2*256 + l2) - ; h1*256*(h2*256 + l2) + l1*(h2*256 + l2) - ; h1*h2*256*256 + h1*l2*256 + h2*l1*256 + l1*l2 + ; h1l1 * h2l2 + ; (h1*256 + l1) * (h2*256 + l2) + ; h1*256*(h2*256 + l2) + l1*(h2*256 + l2) + ; h1*h2*256*256 + h1*l2*256 + h2*l1*256 + l1*l2 - ; l1 * l2 - imul8 result, arg1, arg2, xe ; 81-92 or 50-55 + ; l1 * l2 + imul8 result, arg1, arg2, xe ; 81-92 or 50-55 - ; 256 * 256 * h1 * h2 - imul8 result + 2, arg1 + 1, arg2 + 1, xe ; 81-92 or 50-55 + ; 256 * 256 * h1 * h2 + imul8 result + 2, arg1 + 1, arg2 + 1, xe ; 81-92 or 50-55 - ; 256 * h1 * l2 - imul8 inter, arg1 + 1, arg2, xe ; 81-92 or 50-55 - add16 result + 1, result + 1, inter ; 20 cyc - add_carry result + 3 ; 2-7 cyc + ; 256 * h1 * l2 + imul8 inter, arg1 + 1, arg2, xe ; 81-92 or 50-55 + add16 result + 1, result + 1, inter ; 20 cyc + add_carry result + 3 ; 2-7 cyc - ; 256 * l1 * h2 - imul8 inter, arg1, arg2 + 1, xe ; 81-92 or 50-55 - add16 result + 1, result + 1, inter ; 20 cyc - add_carry result + 3 ; 2-7 cyc + ; 256 * l1 * h2 + imul8 inter, arg1, arg2 + 1, xe ; 81-92 or 50-55 + add16 result + 1, result + 1, inter ; 20 cyc + add_carry result + 3 ; 2-7 cyc - ; In case of negative inputs, adjust high word - ; https://stackoverflow.com/a/28827013 - ; 10-50 cycles - lda arg1 + 1 ; 3 cyc - bpl arg1_pos ; 2 cyc - sub16 result + 2, result + 2, arg2 ; 20 cyc -arg1_pos: - lda arg2 + 1 ; 3 cyc - bpl arg2_pos ; 2 cyc - sub16 result + 2, result + 2, arg1 ; 20 cyc -arg2_pos: + ; In case of negative inputs, adjust high word + ; https://stackoverflow.com/a/28827013 + ; 10-50 cycles + lda arg1 + 1 ; 3 cyc + bpl arg1_pos ; 2 cyc + sub16 result + 2, result + 2, arg2 ; 20 cyc + arg1_pos: - rts ; 6 cyc + lda arg2 + 1 ; 3 cyc + bpl arg2_pos ; 2 cyc + sub16 result + 2, result + 2, arg1 ; 20 cyc + arg2_pos: + + rts ; 6 cyc + .endscope .endmacro -; min base ram: 5 + 19 * 2 + 81 + 22 * 2 + 6 = 174 -; max base ram: 23 + 19 * 2 + 92 + 27 * 2 + 6 = 213 -; min ext ram: 5 + 19 * 2 + 50 + 22 * 2 + 6 = 143 -; max ext ram: 23 + 19 * 2 + 55 + 27 * 2 + 6 = 176 -.macro sqr16_impl xe + +; min base: 19 * 2 + 81 + 22 * 2 = 163 +; max base: 19 * 2 + 92 + 27 * 2 = 184 +; min ext: 19 * 2 + 50 + 22 * 2 = 132 +; max ext: 19 * 2 + 55 + 27 * 2 = 147 +.macro sqr16_impl_inner result, arg, xe .scope - arg = FR0 ; 16-bit arg (clobbered) - result = FR2 ; 32-bit result - ;inter = temp2 - inter = FR1 - - ; 5-23 cycles - lda arg + 1 ; 3 cyc - bpl arg_pos ; 2 cyc - neg16 arg ; 18 cyc - arg_pos: - + inter = temp2 ; hl * hl ; (h*256 + l) * (h*256 + l) ; h*256*(h*256 + l) + l*(h*256 + l) @@ -871,8 +873,33 @@ arg2_pos: add_carry result + 3 ; 2-7 cyc add16 result + 1, result + 1, inter ; 20 cyc add_carry result + 3 ; 2-7 cyc + .endscope +.endmacro - rts ; 6 cyc + +; min base ram: 5 + 163 + 6 = 174 +; max base ram: 7 + 184 + 18 + 6 = 215 +; min ext ram: 5 + 132 + 6 = 143 +; max ext ram: 7 + 147 + 18 + 6 = 178 +.macro sqr16_impl xe + .scope + arg = FR0 ; 16-bit arg + negated = FR1 + result = FR2 ; 32-bit result + + ; 5-7 cycles + lda arg + 1 ; 3 cyc + bpl arg_pos ; 2 cyc + jmp arg_neg ; 3 cyc + + arg_pos: + sqr16_impl_inner result, arg, xe ; 163-184 / 132-147 cyc + rts ; 6 cyc + + arg_neg: + copy_neg16 negated, arg ; 18 cyc + sqr16_impl_inner result, negated, xe ; 163-184 / 132-147 cyc + rts ; 6 cyc .endscope .endmacro