Decent speedup in XE mode

Noticed that the separate addition for the low 1 bit case was
doing some dupe memory loads. Ended up making separate code
paths for even and odd values so the even saves two cycles
(from 52 down to 50 cycles) and the odd saves 14 cycles (from
69 down to 55 cycles). nice!

This gets the XE runtime on default view down from 3m38s to 3m33s,
a 5 second runtime improvement
This commit is contained in:
Brooke Vibber 2026-08-22 16:45:09 -07:00
commit 65563b0e79

View file

@ -593,7 +593,9 @@ bank_switch_table:
.macro imul8 dest, arg1, arg2, xe .macro imul8 dest, arg1, arg2, xe
.if xe .if xe
; using 64KB lookup table ; using 64KB lookup table
; 52-69 cycles ; 50-55 cycles
; min: 11 + 9 + 9 + 21 = 50
; max: 11 + 9 + 9 + 26 = 55
; clobbers x, y, dest, ptr ; clobbers x, y, dest, ptr
.scope .scope
output = dest output = dest
@ -612,15 +614,36 @@ bank_switch_table:
ora #$40 ; 2 cyc ora #$40 ; 2 cyc
sta ptr + 1 ; 3 cyc sta ptr + 1 ; 3 cyc
; copy the entry into output ; mask off the low bit for the index, as the table contains
; entries for every other arg1 value...
lda arg1 ; 3 cyc lda arg1 ; 3 cyc
and #$fe ; 2 cyc
tay ; 2 cyc tay ; 2 cyc
and #1 ; 2 cyc
bne odd ; 2 cyc
even:
; copy the entry into output
lda (ptr),y ; 5 cyc lda (ptr),y ; 5 cyc
sta output ; 3 cyc sta output ; 3 cyc
iny ; 2 cyc iny ; 2 cyc
lda (ptr),y ; 5 cyc lda (ptr),y ; 5 cyc
sta output + 1 ; 3 cyc sta output + 1 ; 3 cyc
jmp done ; 3 cyc
odd:
; skip the LSB for the index
dey ; 2 cyc
; add arg2 one last time for the skipped bit
txa ; 2 cyc
clc ; 2 cyc
adc (ptr), y ; 5 cyc
sta output ; 3 cyc
lda #0 ; 2 cyc
iny ; 2 cyc
adc (ptr),y ; 5 cyc
sta output + 1 ; 3 cyc
; note: we are not restoring memory to save 6 cycles! ; note: we are not restoring memory to save 6 cycles!
; this means those 16kb have to be switched back to base RAM ; this means those 16kb have to be switched back to base RAM
@ -629,18 +652,6 @@ bank_switch_table:
;;lda #$81 ; 2 cyc - disabled ;;lda #$81 ; 2 cyc - disabled
;;sta PORTB ; 4 cyc - disabled ;;sta PORTB ; 4 cyc - disabled
; check that 1 bit we skipped to fit into space
lda arg1 ; 3 cyc
and #1 ; 2 cyc
beq done ; 2 cyc
; add arg2 one last time for the skipped bit
clc ; 2 cyc
txa ; 2 cyc
adc output ; 3 cyc
sta output ; 3 cyc
add_carry output + 1 ; 2-7 cyc
done: done:
.endscope .endscope
.else .else
@ -776,8 +787,8 @@ inner_loop:
; min base mem: 81 * 4 + 22 * 2 + 10 + 6 = 384 cyc ; min base mem: 81 * 4 + 22 * 2 + 10 + 6 = 384 cyc
; max base mem: 92 * 4 + 27 * 2 + 50 + 6 = 478 cyc ; max base mem: 92 * 4 + 27 * 2 + 50 + 6 = 478 cyc
; min ext-mem: 52 * 4 + 22 * 2 + 10 + 6 = 268 cyc ; min ext-mem: 50 * 4 + 22 * 2 + 10 + 6 = 260 cyc
; max ext-mem: 69 * 4 + 27 * 2 + 50 + 6 = 386 cyc ; max ext-mem: 55 * 4 + 27 * 2 + 50 + 6 = 330 cyc
.macro imul16_impl xe .macro imul16_impl xe
.local arg1 .local arg1
.local arg2 .local arg2
@ -796,18 +807,18 @@ inner_loop:
; h1*h2*256*256 + h1*l2*256 + h2*l1*256 + l1*l2 ; h1*h2*256*256 + h1*l2*256 + h2*l1*256 + l1*l2
; l1 * l2 ; l1 * l2
imul8 result, arg1, arg2, xe ; 81-92 or 52-69 imul8 result, arg1, arg2, xe ; 81-92 or 50-55
; 256 * 256 * h1 * h2 ; 256 * 256 * h1 * h2
imul8 result + 2, arg1 + 1, arg2 + 1, xe ; 81-92 or 52-69 imul8 result + 2, arg1 + 1, arg2 + 1, xe ; 81-92 or 50-55
; 256 * h1 * l1 ; 256 * h1 * l1
imul8 inter, arg1 + 1, arg2, xe ; 81-92 or 52-69 imul8 inter, arg1 + 1, arg2, xe ; 81-92 or 50-55
add16 result + 1, result + 1, inter ; 20 cyc add16 result + 1, result + 1, inter ; 20 cyc
add_carry result + 3 ; 2-7 cyc add_carry result + 3 ; 2-7 cyc
; 256 * l1 * h2 ; 256 * l1 * h2
imul8 inter, arg1, arg2 + 1, xe ; 81-92 or 52-69 imul8 inter, arg1, arg2 + 1, xe ; 81-92 or 50-55
add16 result + 1, result + 1, inter ; 20 cyc add16 result + 1, result + 1, inter ; 20 cyc
add_carry result + 3 ; 2-7 cyc add_carry result + 3 ; 2-7 cyc
@ -828,8 +839,8 @@ arg2_pos:
; min base ram: 5 + 19 * 2 + 81 + 22 * 2 + 6 = 174 ; min base ram: 5 + 19 * 2 + 81 + 22 * 2 + 6 = 174
; max base ram: 23 + 19 * 2 + 92 + 27 * 2 + 6 = 213 ; max base ram: 23 + 19 * 2 + 92 + 27 * 2 + 6 = 213
; min ext ram: 5 + 19 * 2 + 52 + 22 * 2 + 6 = 145 ; min ext ram: 5 + 19 * 2 + 50 + 22 * 2 + 6 = 143
; max ext ram: 23 + 19 * 2 + 69 + 27 * 2 + 6 = 190 ; max ext ram: 23 + 19 * 2 + 55 + 27 * 2 + 6 = 176
.macro sqr16_impl xe .macro sqr16_impl xe
.scope .scope
arg = FR0 ; 16-bit arg (clobbered) arg = FR0 ; 16-bit arg (clobbered)
@ -855,7 +866,7 @@ arg2_pos:
sqr8 result + 2, arg + 1 ; 19 cyc sqr8 result + 2, arg + 1 ; 19 cyc
; 2 * h * l * 256 ; 2 * h * l * 256
imul8 inter, arg + 1, arg, xe ; 81-92 / 52-69 cyc imul8 inter, arg + 1, arg, xe ; 81-92 / 50-55 cyc
add16 result + 1, result + 1, inter ; 20 cyc add16 result + 1, result + 1, inter ; 20 cyc
add_carry result + 3 ; 2-7 cyc add_carry result + 3 ; 2-7 cyc
add16 result + 1, result + 1, inter ; 20 cyc add16 result + 1, result + 1, inter ; 20 cyc