diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 23bee12eb..ce5ea111c 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -684,7 +684,7 @@ internal class AsmGen(private val program: Program, +""") when(register) { CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x") - CpuRegister.X -> throw AssemblyError("can't use X here") + CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax") CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x") } } @@ -722,7 +722,7 @@ internal class AsmGen(private val program: Program, expressionsAsmGen.translateExpression(index) when(register) { CpuRegister.A -> out(" inx | lda P8ESTACK_LO,x") - CpuRegister.X -> throw AssemblyError("can't use X here") + CpuRegister.X -> out(" inx | lda P8ESTACK_LO,x | tax") CpuRegister.Y -> out(" inx | ldy P8ESTACK_LO,x") } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt index 704cf505a..96c1c0247 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt @@ -4,6 +4,7 @@ import prog8.ast.IFunctionCall import prog8.ast.Program import prog8.ast.base.* import prog8.ast.expressions.* +import prog8.ast.statements.RegisterOrStatusflag import prog8.ast.statements.Subroutine import prog8.ast.statements.SubroutineParameter import prog8.compiler.AssemblyError @@ -63,9 +64,21 @@ 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. - for (arg in stmt.args.reversed()) - asmgen.translateExpression(arg) - for (regparam in sub.asmParameterRegisters) { + + // make sure the X register is loaded last so we can "safely" destroy the estack pointer + val argsOrig = stmt.args.zip(sub.asmParameterRegisters) + val args = mutableListOf>() + for(argOrig in argsOrig) { + if(argOrig.second.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY)) + args.add(argOrig) + else + args.add(0, argOrig) + } + + for (arg in args.reversed()) + asmgen.translateExpression(arg.first) + for (arg in args) { + val regparam = arg.second when { regparam.statusflag==Statusflag.Pc -> { asmgen.out(""" diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 77c5d3b3b..5905c0b41 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -260,16 +260,16 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen DataType.UBYTE, DataType.BYTE -> { when(target.register!!) { RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x") - RegisterOrPair.X -> throw AssemblyError("can't use X here") + RegisterOrPair.X -> asmgen.out(" inx | lda P8ESTACK_LO,x | tax") RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x") else -> throw AssemblyError("can't assign byte to register pair word") } } DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> { when(target.register!!) { - RegisterOrPair.AX -> throw AssemblyError("can't use X here") + RegisterOrPair.AX -> asmgen.out(" inx | lda P8ESTACK_LO,x | pha | lda P8ESTACK_HI,x | tax | pla") RegisterOrPair.AY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x") - RegisterOrPair.XY-> throw AssemblyError("can't use X here") + RegisterOrPair.XY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x | tax") else -> throw AssemblyError("can't assign word to single byte register") } } @@ -590,7 +590,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen TargetStorageKind.STACK -> { when(register) { CpuRegister.A -> asmgen.out(" sta P8ESTACK_LO,x | dex") - CpuRegister.X -> throw AssemblyError("can't use X here") + CpuRegister.X -> throw AssemblyError("can't store X itself on eval stack") CpuRegister.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex") } }