From e58df379e72ced940342df9a34b8aeee53480355 Mon Sep 17 00:00:00 2001 From: Brooke Vibber Date: Sun, 23 Aug 2026 15:48:48 -0700 Subject: [PATCH] step 2: break out the multiplication hotspot mandelbrot_hotspot_impl macro calls through to the sqr16_impl and imul16_impl macros with the xe mode this is backed by two realized functions, as mandelbrot_hotspot and mandelbrot_hotspot_xe these are also called via direct jmp instead of jsr/rts because there's only one call site so we can save 6 cycles per iteration by jmp/jmp could save 6 more cycles per iter by specializing all of the mandelbrot proc but there isn't room in ram right now sqr16_func is removed as it is unused and we ran out of code space adding the hotspot's extra implementations imul16_func is kept, as it's called via zoom_factor in a couple of places. this forwards to the xe version at a cost of 3 cycles, as the call sites aren't patched --- mandel-core.s | 85 +++++++++++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 37 deletions(-) diff --git a/mandel-core.s b/mandel-core.s index 2e1c8b2..17ecfc4 100644 --- a/mandel-core.s +++ b/mandel-core.s @@ -558,8 +558,6 @@ input_max: ; input: arg1, arg2 as fixed4.12 ; output: dest as fixed8.24 -; patch point jsr at 16 bytes in -imul16_patch_offset = 16 .macro imul16 dest, arg1, arg2 copy16 FR0, arg1 ; 12 cyc copy16 FR1, arg2 ; 12 cyc @@ -569,13 +567,11 @@ imul16_patch_offset = 16 ; input: arg as fixed4.12 ; output: dest as fixed8.24 -; patch point jsr at 8 bytes in -sqr16_patch_offset = 8 -.macro sqr16 dest, arg - copy16 FR0, arg ; 12 cyc - jsr sqr16_func ; ? cyc - copy32 dest, FR2 ; 24 cyc -.endmacro +;.macro sqr16 dest, arg +; copy16 FR0, arg ; 12 cyc +; jsr sqr16_func ; ? cyc +; copy32 dest, FR2 ; 24 cyc +;.endmacro ; input: arg as u8 ; output: dest as u16 @@ -912,15 +908,15 @@ inner_loop: rts .endproc -.proc sqr16_func - sqr16_impl FR2, FR0, 0 - rts -.endproc +;.proc sqr16_func +; sqr16_impl FR2, FR0, 0 +; rts +;.endproc -.proc sqr16xe_func - sqr16_impl FR2, FR0, 1 - rts -.endproc +;.proc sqr16xe_func +; sqr16_impl FR2, FR0, 1 +; rts +;.endproc ; 11-27 cycles .macro round16 arg @@ -1160,16 +1156,11 @@ keep_going: shift_round_16 zy, 3 ; zx_2 = zx * zx -fixup_sqr16_1: - sqr16 zx_2, zx + 2 - ; zy_2 = zy * zy -fixup_sqr16_2: - sqr16 zy_2, zy + 2 - ; zx_zy = zx * zy -fixup_imul16_1: - imul16 zx_zy, zx + 2, zy + 2 +fixup_mandelbrot_hotspot: + jmp mandelbrot_hotspot +after_mandelbrot_hotspot: ; dist = zx_2 + zy_2 add32 dist, zx_2, zy_2 @@ -1265,6 +1256,27 @@ next: .endproc +.macro mandelbrot_hotspot_impl xe + ; zx_2 = zx * zx + sqr16_impl zx_2, zx + 2, xe + + ; zy_2 = zy * zy + sqr16_impl zy_2, zy + 2, xe + + ; zx_zy = zx * zy + imul16_impl zx_zy, zx + 2, zy + 2, xe + + jmp mandelbrot::after_mandelbrot_hotspot +.endmacro + +.proc mandelbrot_hotspot + mandelbrot_hotspot_impl 0 +.endproc + +.proc mandelbrot_hotspot_xe + mandelbrot_hotspot_impl 1 +.endproc + .macro scale_zoom dest ; clobbers X, flags .local cont @@ -2192,22 +2204,21 @@ init: sta imul16_func lda #.lobyte(imul16xe_func) sta imul16_func + 1 - sta mandelbrot::fixup_imul16_1 + imul16_patch_offset + 1 lda #.hibyte(imul16xe_func) sta imul16_func + 2 - sta mandelbrot::fixup_imul16_1 + imul16_patch_offset + 2 ; ditto for sqr16_func -> sqr16xe_func - lda #$4c ; 'jmp' opcode - sta sqr16_func - lda #.lobyte(sqr16xe_func) - sta sqr16_func + 1 - sta mandelbrot::fixup_sqr16_1 + sqr16_patch_offset + 1 - sta mandelbrot::fixup_sqr16_2 + sqr16_patch_offset + 1 - lda #.hibyte(sqr16xe_func) - sta sqr16_func + 2 - sta mandelbrot::fixup_sqr16_1 + sqr16_patch_offset + 2 - sta mandelbrot::fixup_sqr16_2 + sqr16_patch_offset + 2 + ;lda #$4c ; 'jmp' opcode + ;sta sqr16_func + ;lda #.lobyte(sqr16xe_func) + ;sta sqr16_func + 1 + ;lda #.hibyte(sqr16xe_func) + ;sta sqr16_func + 2 + + lda #.lobyte(mandelbrot_hotspot_xe) + sta mandelbrot::fixup_mandelbrot_hotspot + 1 + lda #.hibyte(mandelbrot_hotspot_xe) + sta mandelbrot::fixup_mandelbrot_hotspot + 2 ; create the lookup table