R0-R15 register parameter optimization if loaded with byte instead of word

This commit is contained in:
Irmen de Jong 2020-12-25 22:30:40 +01:00
parent 6734ae3c88
commit c2a8dc23d0
3 changed files with 45 additions and 45 deletions

View File

@ -9,6 +9,8 @@ import prog8.ast.statements.RegisterOrStatusflag
import prog8.ast.statements.Subroutine import prog8.ast.statements.Subroutine
import prog8.ast.statements.SubroutineParameter import prog8.ast.statements.SubroutineParameter
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
import prog8.compiler.target.CompilationTarget
import prog8.compiler.target.CpuType
import prog8.compiler.target.c64.codegen.assignment.* import prog8.compiler.target.c64.codegen.assignment.*
@ -96,6 +98,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
asmgen.out(" inx") // align estack pointer asmgen.out(" inx") // align estack pointer
for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) { for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) {
val plusIdxStr = if(argi.index==0) "" else "+${argi.index}"
when { when {
argi.value.second.statusflag == Statusflag.Pc -> { argi.value.second.statusflag == Statusflag.Pc -> {
require(argForCarry == null) require(argForCarry == null)
@ -111,24 +114,40 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
argForAregister = argi argForAregister = argi
} }
argi.value.second.registerOrPair == RegisterOrPair.Y -> { argi.value.second.registerOrPair == RegisterOrPair.Y -> {
asmgen.out(" ldy P8ESTACK_LO+${argi.index},x") asmgen.out(" ldy P8ESTACK_LO$plusIdxStr,x")
} }
argi.value.second.registerOrPair in Cx16VirtualRegisters -> { argi.value.second.registerOrPair in Cx16VirtualRegisters -> {
// immediately output code to load the virtual register, to avoid clobbering the A register later // immediately output code to load the virtual register, to avoid clobbering the A register later
when (sub.parameters[argi.index].type) {
in ByteDatatypes -> {
// only load the lsb of the virtual register
asmgen.out(""" asmgen.out("""
lda P8ESTACK_LO+${argi.index},x lda P8ESTACK_LO$plusIdxStr,x
sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()} sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}
lda P8ESTACK_HI+${argi.index},x """)
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
asmgen.out(" stz cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}+1")
else
asmgen.out(" lda #0 | sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}+1")
}
in WordDatatypes ->
asmgen.out("""
lda P8ESTACK_LO$plusIdxStr,x
sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}
lda P8ESTACK_HI$plusIdxStr,x
sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}+1 sta cx16.${argi.value.second.registerOrPair.toString().toLowerCase()}+1
""") """)
else -> throw AssemblyError("weird dt")
}
} }
else -> throw AssemblyError("weird argument") else -> throw AssemblyError("weird argument")
} }
} }
if(argForCarry!=null) { if(argForCarry!=null) {
val plusIdxStr = if(argForCarry.index==0) "" else "+${argForCarry.index}"
asmgen.out(""" asmgen.out("""
lda P8ESTACK_LO+${argForCarry.index},x lda P8ESTACK_LO$plusIdxStr,x
beq + beq +
sec sec
bcs ++ bcs ++
@ -137,21 +156,23 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
} }
if(argForAregister!=null) { if(argForAregister!=null) {
val plusIdxStr = if(argForAregister.index==0) "" else "+${argForAregister.index}"
when(argForAregister.value.second.registerOrPair) { when(argForAregister.value.second.registerOrPair) {
RegisterOrPair.A -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x") RegisterOrPair.A -> asmgen.out(" lda P8ESTACK_LO$plusIdxStr,x")
RegisterOrPair.AY -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x | ldy P8ESTACK_HI+${argForAregister.index},x") RegisterOrPair.AY -> asmgen.out(" lda P8ESTACK_LO$plusIdxStr,x | ldy P8ESTACK_HI$plusIdxStr,x")
else -> throw AssemblyError("weird arg") else -> throw AssemblyError("weird arg")
} }
} }
if(argForXregister!=null) { if(argForXregister!=null) {
val plusIdxStr = if(argForXregister.index==0) "" else "+${argForXregister.index}"
if(argForAregister!=null) if(argForAregister!=null)
asmgen.out(" pha") asmgen.out(" pha")
when(argForXregister.value.second.registerOrPair) { when(argForXregister.value.second.registerOrPair) {
RegisterOrPair.X -> asmgen.out(" lda P8ESTACK_LO+${argForXregister.index},x | tax") RegisterOrPair.X -> asmgen.out(" lda P8ESTACK_LO$plusIdxStr,x | tax")
RegisterOrPair.AX -> asmgen.out(" ldy P8ESTACK_LO+${argForXregister.index},x | lda P8ESTACK_HI+${argForXregister.index},x | tax | tya") RegisterOrPair.AX -> asmgen.out(" ldy P8ESTACK_LO$plusIdxStr,x | lda P8ESTACK_HI$plusIdxStr,x | tax | tya")
RegisterOrPair.XY -> asmgen.out(" ldy P8ESTACK_HI+${argForXregister.index},x | lda P8ESTACK_LO+${argForXregister.index},x | tax") RegisterOrPair.XY -> asmgen.out(" ldy P8ESTACK_HI$plusIdxStr,x | lda P8ESTACK_LO$plusIdxStr,x | tax")
else -> throw AssemblyError("weird arg") else -> throw AssemblyError("weird arg")
} }
if(argForAregister!=null) if(argForAregister!=null)
@ -242,7 +263,11 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
asmgen.assignVariableToRegister(scratchVar, register) asmgen.assignVariableToRegister(scratchVar, register)
} }
else { else {
val target = AsmAssignTarget.fromRegisters(register, sub, program, asmgen) val target: AsmAssignTarget =
if(parameter.value.type in ByteDatatypes && (register==RegisterOrPair.AX || register == RegisterOrPair.AY || register==RegisterOrPair.XY || register in Cx16VirtualRegisters))
AsmAssignTarget(TargetStorageKind.REGISTER, program, asmgen, parameter.value.type, sub, register = register)
else
AsmAssignTarget.fromRegisters(register, sub, program, asmgen)
val src = if(valueDt in PassByReferenceDatatypes) { val src = if(valueDt in PassByReferenceDatatypes) {
if(value is IdentifierReference) { if(value is IdentifierReference) {
val addr = AddressOf(value, Position.DUMMY) val addr = AddressOf(value, Position.DUMMY)

View File

@ -1559,12 +1559,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
RegisterOrPair.XY -> asmgen.out(" ldx #${byte.toHex()} | ldy #0") RegisterOrPair.XY -> asmgen.out(" ldx #${byte.toHex()} | ldy #0")
RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float") RegisterOrPair.FAC1, RegisterOrPair.FAC2 -> throw AssemblyError("expected typecasted byte to float")
in Cx16VirtualRegisters -> { in Cx16VirtualRegisters -> {
asmgen.out(""" asmgen.out(" lda #${byte.toHex()} | sta cx16.${target.register.toString().toLowerCase()}")
lda #${byte.toHex()} if(CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
sta cx16.${target.register.toString().toLowerCase()} asmgen.out(" stz cx16.${target.register.toString().toLowerCase()}+1\n")
lda #0 else
sta cx16.${target.register.toString().toLowerCase()}+1 asmgen.out(" lda #0 | sta cx16.${target.register.toString().toLowerCase()}+1\n")
""")
} }
else -> throw AssemblyError("weird register") else -> throw AssemblyError("weird register")
} }

View File

@ -1,34 +1,10 @@
%import textio
%import diskio
%import floats
%import graphics
%import test_stack %import test_stack
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
main { main {
; TODO the R0 is loaded as a WORD even though its type is specified as a BYTE...:
asmsub set_8_pixels_from_bits(ubyte bits @R0, ubyte oncolor @A, ubyte offcolor @Y) {
}
asmsub derp(ubyte value @A, uword address @R0) {
%asm {{
rts
}}
}
sub start () { sub start () {
uword bank = 1
uword address = 1000
ubyte value = 123
bank++
derp(value, address)
cx16.vpoke(lsb(bank), address, value)
test_stack.test() test_stack.test()
} }