diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 9e19378ac..7cc6ef77a 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -11,6 +11,7 @@ import prog8.compiler.target.C64Target import prog8.compiler.target.Cx16Target import prog8.compiler.target.cbm.AssemblyProgram import prog8.compiler.target.cbm.loadAsmIncludeFile +import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen import prog8.compilerinterface.* @@ -856,6 +857,21 @@ class AsmGen(private val program: Program, internal fun assignVariableToRegister(asmVarName: String, register: RegisterOrPair) = assignmentAsmGen.assignVariableToRegister(asmVarName, register) + internal fun assignRegister(reg: RegisterOrPair, target: AsmAssignTarget) { + when(reg) { + RegisterOrPair.A, + RegisterOrPair.X, + RegisterOrPair.Y -> assignmentAsmGen.assignRegisterByte(target, reg.asCpuRegister()) + RegisterOrPair.AX, + RegisterOrPair.AY, + RegisterOrPair.XY, + in Cx16VirtualRegisters -> assignmentAsmGen.assignRegisterpairWord(target, reg) + RegisterOrPair.FAC1 -> assignmentAsmGen.assignFAC1float(target) + RegisterOrPair.FAC2 -> throw AssemblyError("no support yet to assign FAC2 directly to something") + else -> throw AssemblyError("invalid register") + } + } + private fun translateSubroutine(sub: Subroutine) { var onlyVariables = false diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index db286a136..7ba03fba8 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -13,6 +13,7 @@ import prog8.compiler.target.AssemblyError import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignSource import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment +import prog8.compiler.target.cpu6502.codegen.assignment.SourceStorageKind import prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind import prog8.compilerinterface.CpuType @@ -104,7 +105,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg } else -> { // Risk of clobbering due to complex expression args. Evaluate first, then assign registers. - // TODO find another way to prepare the arguments, without using the eval stack registerArgsViaStackEvaluation(stmt, sub) } } @@ -136,13 +136,43 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) { // this is called when one or more of the arguments are 'complex' and // cannot be assigned to a register easily or risk clobbering other registers. + // TODO find another way to prepare the arguments, without using the eval stack if(sub.parameters.isEmpty()) return + // 1. load all arguments reversed onto the stack: first arg goes last (is on top). - for (arg in stmt.args.reversed()) - asmgen.translateExpression(arg) + + for (arg in stmt.args.reversed()) { + if(arg.isSimple) { // TODO FOR ALL ARG TYPES? + // note this stuff below is needed to (eventually) avoid calling asmgen.translateExpression() + // TODO but This STILL requires the translateNormalAssignment() to be fixed to avoid stack eval for expressions... + when (val dt = arg.inferType(program).getOr(DataType.UNDEFINED)) { + in ByteDatatypes -> { + asmgen.assignExpressionToRegister(arg, RegisterOrPair.A) + asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub)) + } + in WordDatatypes, in PassByReferenceDatatypes -> { + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) + asmgen.translateNormalAssignment( + AsmAssignment( + AsmAssignSource(SourceStorageKind.REGISTER, program, asmgen, dt, register=RegisterOrPair.AY), + AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub), + false, program.memsizer, arg.position + ) + ) + } + DataType.FLOAT -> { + asmgen.assignExpressionToRegister(arg, RegisterOrPair.FAC1) + asmgen.assignRegister(RegisterOrPair.FAC1, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub)) + } + else -> throw AssemblyError("weird dt $dt") + } + } else { + asmgen.translateExpression(arg) // TODO GET RID OF THIS, if the above actually produces compact code + } + } var argForCarry: IndexedValue>? = null var argForXregister: IndexedValue>? = null diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index a9bba57dd..41ca9c6c5 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -263,9 +263,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } SourceStorageKind.REGISTER -> { when(assign.source.datatype) { - DataType.UBYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister()) - DataType.UWORD -> assignRegisterpairWord(assign.target, assign.source.register!!) - else -> throw AssemblyError("invalid register dt") + DataType.UBYTE, DataType.BYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister()) + DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> assignRegisterpairWord(assign.target, assign.source.register!!) + else -> throw AssemblyError("invalid register dt ${assign.source.datatype}") } } SourceStorageKind.STACK -> { @@ -1455,7 +1455,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) { - require(target.datatype in NumericDatatypes) + require(target.datatype in NumericDatatypes || target.datatype in PassByReferenceDatatypes) if(target.datatype==DataType.FLOAT) throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer") diff --git a/examples/test.p8 b/examples/test.p8 index e009e22cb..334ca8f09 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -2,5 +2,9 @@ main { sub start() { + uword xx=$2000 + ubyte yy=30 + ubyte zz=9 + sys.memset(xx+200, yy*2, zz+yy) } }