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
This commit is contained in:
Brooke Vibber 2026-08-23 15:48:48 -07:00
commit e58df379e7

View file

@ -558,8 +558,6 @@ input_max:
; input: arg1, arg2 as fixed4.12 ; input: arg1, arg2 as fixed4.12
; output: dest as fixed8.24 ; output: dest as fixed8.24
; patch point jsr at 16 bytes in
imul16_patch_offset = 16
.macro imul16 dest, arg1, arg2 .macro imul16 dest, arg1, arg2
copy16 FR0, arg1 ; 12 cyc copy16 FR0, arg1 ; 12 cyc
copy16 FR1, arg2 ; 12 cyc copy16 FR1, arg2 ; 12 cyc
@ -569,13 +567,11 @@ imul16_patch_offset = 16
; input: arg as fixed4.12 ; input: arg as fixed4.12
; output: dest as fixed8.24 ; output: dest as fixed8.24
; patch point jsr at 8 bytes in ;.macro sqr16 dest, arg
sqr16_patch_offset = 8 ; copy16 FR0, arg ; 12 cyc
.macro sqr16 dest, arg ; jsr sqr16_func ; ? cyc
copy16 FR0, arg ; 12 cyc ; copy32 dest, FR2 ; 24 cyc
jsr sqr16_func ; ? cyc ;.endmacro
copy32 dest, FR2 ; 24 cyc
.endmacro
; input: arg as u8 ; input: arg as u8
; output: dest as u16 ; output: dest as u16
@ -912,15 +908,15 @@ inner_loop:
rts rts
.endproc .endproc
.proc sqr16_func ;.proc sqr16_func
sqr16_impl FR2, FR0, 0 ; sqr16_impl FR2, FR0, 0
rts ; rts
.endproc ;.endproc
.proc sqr16xe_func ;.proc sqr16xe_func
sqr16_impl FR2, FR0, 1 ; sqr16_impl FR2, FR0, 1
rts ; rts
.endproc ;.endproc
; 11-27 cycles ; 11-27 cycles
.macro round16 arg .macro round16 arg
@ -1160,16 +1156,11 @@ keep_going:
shift_round_16 zy, 3 shift_round_16 zy, 3
; zx_2 = zx * zx ; zx_2 = zx * zx
fixup_sqr16_1:
sqr16 zx_2, zx + 2
; zy_2 = zy * zy ; zy_2 = zy * zy
fixup_sqr16_2:
sqr16 zy_2, zy + 2
; zx_zy = zx * zy ; zx_zy = zx * zy
fixup_imul16_1: fixup_mandelbrot_hotspot:
imul16 zx_zy, zx + 2, zy + 2 jmp mandelbrot_hotspot
after_mandelbrot_hotspot:
; dist = zx_2 + zy_2 ; dist = zx_2 + zy_2
add32 dist, zx_2, zy_2 add32 dist, zx_2, zy_2
@ -1265,6 +1256,27 @@ next:
.endproc .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 .macro scale_zoom dest
; clobbers X, flags ; clobbers X, flags
.local cont .local cont
@ -2192,22 +2204,21 @@ init:
sta imul16_func sta imul16_func
lda #.lobyte(imul16xe_func) lda #.lobyte(imul16xe_func)
sta imul16_func + 1 sta imul16_func + 1
sta mandelbrot::fixup_imul16_1 + imul16_patch_offset + 1
lda #.hibyte(imul16xe_func) lda #.hibyte(imul16xe_func)
sta imul16_func + 2 sta imul16_func + 2
sta mandelbrot::fixup_imul16_1 + imul16_patch_offset + 2
; ditto for sqr16_func -> sqr16xe_func ; ditto for sqr16_func -> sqr16xe_func
lda #$4c ; 'jmp' opcode ;lda #$4c ; 'jmp' opcode
sta sqr16_func ;sta sqr16_func
lda #.lobyte(sqr16xe_func) ;lda #.lobyte(sqr16xe_func)
sta sqr16_func + 1 ;sta sqr16_func + 1
sta mandelbrot::fixup_sqr16_1 + sqr16_patch_offset + 1 ;lda #.hibyte(sqr16xe_func)
sta mandelbrot::fixup_sqr16_2 + sqr16_patch_offset + 1 ;sta sqr16_func + 2
lda #.hibyte(sqr16xe_func)
sta sqr16_func + 2 lda #.lobyte(mandelbrot_hotspot_xe)
sta mandelbrot::fixup_sqr16_1 + sqr16_patch_offset + 2 sta mandelbrot::fixup_mandelbrot_hotspot + 1
sta mandelbrot::fixup_sqr16_2 + sqr16_patch_offset + 2 lda #.hibyte(mandelbrot_hotspot_xe)
sta mandelbrot::fixup_mandelbrot_hotspot + 2
; create the lookup table ; create the lookup table