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
This commit is contained in:
Brooke Vibber 2026-08-22 18:48:05 -07:00
commit f3a92708d2

View file

@ -533,6 +533,20 @@ input_max:
neg 4, arg neg 4, arg
.endmacro .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 ; 11-27 + 18 * shift cycles
; 65-81 cycles for shift=3 ; 65-81 cycles for shift=3
.macro shift_round_16 arg, shift .macro shift_round_16 arg, shift
@ -790,16 +804,11 @@ inner_loop:
; min ext-mem: 50 * 4 + 22 * 2 + 10 + 6 = 260 cyc ; min ext-mem: 50 * 4 + 22 * 2 + 10 + 6 = 260 cyc
; max ext-mem: 55 * 4 + 27 * 2 + 50 + 6 = 330 cyc ; max ext-mem: 55 * 4 + 27 * 2 + 50 + 6 = 330 cyc
.macro imul16_impl xe .macro imul16_impl xe
.local arg1 .scope
.local arg2 arg1 = FR0 ; 16-bit arg
.local result arg2 = FR1 ; 16-bit arg
.local inter result = FR2 ; 32-bit result (output)
.local arg1_pos inter = temp2 ; 16-bit temporary (clobbered)
.local arg2_pos
arg1 = FR0 ; 16-bit arg (clobbered)
arg2 = FR1 ; 16-bit arg (clobbered)
result = FR2 ; 32-bit result
inter = temp2
; h1l1 * h2l2 ; h1l1 * h2l2
; (h1*256 + l1) * (h2*256 + l2) ; (h1*256 + l1) * (h2*256 + l2)
@ -828,32 +837,25 @@ inner_loop:
lda arg1 + 1 ; 3 cyc lda arg1 + 1 ; 3 cyc
bpl arg1_pos ; 2 cyc bpl arg1_pos ; 2 cyc
sub16 result + 2, result + 2, arg2 ; 20 cyc sub16 result + 2, result + 2, arg2 ; 20 cyc
arg1_pos: arg1_pos:
lda arg2 + 1 ; 3 cyc lda arg2 + 1 ; 3 cyc
bpl arg2_pos ; 2 cyc bpl arg2_pos ; 2 cyc
sub16 result + 2, result + 2, arg1 ; 20 cyc sub16 result + 2, result + 2, arg1 ; 20 cyc
arg2_pos: arg2_pos:
rts ; 6 cyc rts ; 6 cyc
.endscope
.endmacro .endmacro
; min base ram: 5 + 19 * 2 + 81 + 22 * 2 + 6 = 174
; max base ram: 23 + 19 * 2 + 92 + 27 * 2 + 6 = 213 ; min base: 19 * 2 + 81 + 22 * 2 = 163
; min ext ram: 5 + 19 * 2 + 50 + 22 * 2 + 6 = 143 ; max base: 19 * 2 + 92 + 27 * 2 = 184
; max ext ram: 23 + 19 * 2 + 55 + 27 * 2 + 6 = 176 ; min ext: 19 * 2 + 50 + 22 * 2 = 132
.macro sqr16_impl xe ; max ext: 19 * 2 + 55 + 27 * 2 = 147
.macro sqr16_impl_inner result, arg, xe
.scope .scope
arg = FR0 ; 16-bit arg (clobbered) inter = temp2
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:
; hl * hl ; hl * hl
; (h*256 + l) * (h*256 + l) ; (h*256 + l) * (h*256 + l)
; h*256*(h*256 + l) + l*(h*256 + l) ; h*256*(h*256 + l) + l*(h*256 + l)
@ -871,7 +873,32 @@ arg2_pos:
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
add_carry result + 3 ; 2-7 cyc add_carry result + 3 ; 2-7 cyc
.endscope
.endmacro
; 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 rts ; 6 cyc
.endscope .endscope
.endmacro .endmacro