mirror of
https://github.com/irmen/prog8.git
synced 2024-11-16 22:09:56 +00:00
R0-R15 register parameter optimization if loaded with byte instead of word
This commit is contained in:
parent
6734ae3c88
commit
c2a8dc23d0
@ -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)
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user