improved ability to use register X in asm subroutine fuction arguments

This commit is contained in:
Irmen de Jong 2020-09-07 00:25:51 +02:00
parent 1377bed988
commit f378a8997b
3 changed files with 22 additions and 9 deletions

View File

@ -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")
}
}

View File

@ -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<Pair<Expression, RegisterOrStatusflag>>()
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("""

View File

@ -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")
}
}