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
.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