fix popCpuStack to load values into asmsub register params

This commit is contained in:
Irmen de Jong 2023-02-01 22:00:37 +01:00
parent 988a3e4446
commit a5ca08f33d
3 changed files with 86 additions and 85 deletions

View File

@ -2875,99 +2875,102 @@ $repeatLabel lda $counterVar
}
}
internal fun popCpuStack(dt: DataType, target: IPtVariable, scope: IPtSubroutine?) {
// note: because A is pushed first so popped last, saving A is often not required here.
val parameter = (target as PtNode).definingSub()?.parameters?.singleOrNull { it.name===target.name }
if(parameter!=null) {
val sub = parameter.definingAsmSub() ?: throw AssemblyError("push/pop arg passing only supported on asmsubs ${target.position}")
val shouldKeepA = sub.parameters.any { it.second.registerOrPair==RegisterOrPair.AX || it.second.registerOrPair==RegisterOrPair.AY}
val reg = sub.parameters.single { it.first === parameter }.second
if(reg.statusflag!=null) {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG")
out("""
internal fun popCpuStack(asmsub: PtAsmSub, parameter: PtSubroutineParameter, reg: RegisterOrStatusflag) {
val shouldKeepA = asmsub.parameters.any { it.second.registerOrPair==RegisterOrPair.AX || it.second.registerOrPair==RegisterOrPair.AY}
if(reg.statusflag!=null) {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG")
out("""
clc
pla
beq +
sec
+""")
if(shouldKeepA)
out(" lda P8ZP_SCRATCH_REG")
}
else {
if (dt in ByteDatatypes) {
if (isTargetCpu(CpuType.CPU65c02)) {
when (reg.registerOrPair) {
RegisterOrPair.A -> out(" pla")
RegisterOrPair.X -> out(" plx")
RegisterOrPair.Y -> out(" ply")
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
} else {
when (reg.registerOrPair) {
RegisterOrPair.A -> out(" pla")
RegisterOrPair.X -> {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
else
out(" pla | tax")
}
RegisterOrPair.Y -> {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
else
out(" pla | tay")
}
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
if(shouldKeepA)
out(" lda P8ZP_SCRATCH_REG")
}
else {
if (parameter.type in ByteDatatypes) {
if (isTargetCpu(CpuType.CPU65c02)) {
when (reg.registerOrPair) {
RegisterOrPair.A -> out(" pla")
RegisterOrPair.X -> out(" plx")
RegisterOrPair.Y -> out(" ply")
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
} else {
// word pop
if (isTargetCpu(CpuType.CPU65c02))
when (reg.registerOrPair) {
RegisterOrPair.AX -> out(" plx | pla")
RegisterOrPair.AY -> out(" ply | pla")
RegisterOrPair.XY -> out(" ply | plx")
in Cx16VirtualRegisters -> {
val regname = reg.registerOrPair!!.name.lowercase()
out(" pla | sta cx16.$regname+1 | pla | sta cx16.$regname")
}
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
when (reg.registerOrPair) {
RegisterOrPair.A -> out(" pla")
RegisterOrPair.X -> {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
else
out(" pla | tax")
}
else {
when (reg.registerOrPair) {
RegisterOrPair.AX -> out(" pla | tax | pla")
RegisterOrPair.AY -> out(" pla | tay | pla")
RegisterOrPair.XY -> out(" pla | tay | pla | tax")
in Cx16VirtualRegisters -> {
val regname = reg.registerOrPair!!.name.lowercase()
out(" pla | sta cx16.$regname+1 | pla | sta cx16.$regname")
}
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
RegisterOrPair.Y -> {
if(shouldKeepA)
out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
else
out(" pla | tay")
}
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
}
} else {
// word pop
if (isTargetCpu(CpuType.CPU65c02))
when (reg.registerOrPair) {
RegisterOrPair.AX -> out(" plx | pla")
RegisterOrPair.AY -> out(" ply | pla")
RegisterOrPair.XY -> out(" ply | plx")
in Cx16VirtualRegisters -> {
val regname = reg.registerOrPair!!.name.lowercase()
out(" pla | sta cx16.$regname+1 | pla | sta cx16.$regname")
}
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
else {
when (reg.registerOrPair) {
RegisterOrPair.AX -> out(" pla | tax | pla")
RegisterOrPair.AY -> out(" pla | tay | pla")
RegisterOrPair.XY -> out(" pla | tay | pla | tax")
in Cx16VirtualRegisters -> {
val regname = reg.registerOrPair!!.name.lowercase()
out(" pla | sta cx16.$regname+1 | pla | sta cx16.$regname")
}
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
}
}
}
}
internal fun popCpuStack(dt: DataType, target: IPtVariable, scope: IPtSubroutine?) {
// note: because A is pushed first so popped last, saving A is often not required here.
val targetAsmSub = (target as PtNode).definingAsmSub()
if(targetAsmSub != null) {
val parameter = targetAsmSub.parameters.first { it.first.name==target.name }
popCpuStack(targetAsmSub, parameter.first, parameter.second)
return
}
val scopedName = when(target) {
is PtConstant -> target.scopedName
is PtMemMapped -> target.scopedName
is PtVariable -> target.scopedName
else -> throw AssemblyError("weird target var")
}
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, this, target.type, scope, variableAsmName = asmVariableName(scopedName))
if (dt in ByteDatatypes) {
out(" pla")
assignRegister(RegisterOrPair.A, tgt)
} else {
val scopedName = when(target) {
is PtConstant -> target.scopedName
is PtMemMapped -> target.scopedName
is PtVariable -> target.scopedName
else -> throw AssemblyError("weird target var")
}
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, this, target.type, scope, variableAsmName = asmVariableName(scopedName))
if (dt in ByteDatatypes) {
out(" pla")
assignRegister(RegisterOrPair.A, tgt)
} else {
if (isTargetCpu(CpuType.CPU65c02))
out(" ply | pla")
else
out(" pla | tay | pla")
assignRegister(RegisterOrPair.AY, tgt)
}
if (isTargetCpu(CpuType.CPU65c02))
out(" ply | pla")
else
out(" pla | tay | pla")
assignRegister(RegisterOrPair.AY, tgt)
}
}

View File

@ -36,12 +36,12 @@ fun asmsub6502ArgsEvalOrder(sub: PtAsmSub): List<Int> {
fun asmsub6502ArgsHaveRegisterClobberRisk(
args: List<PtExpression>,
paramRegisters: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>
params: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>
): Boolean {
fun isClobberRisk(expr: PtExpression): Boolean {
when (expr) {
is PtArrayIndexer -> {
return paramRegisters.any {
return params.any {
it.second.registerOrPair in listOf(RegisterOrPair.Y, RegisterOrPair.AY, RegisterOrPair.XY)
}
}

View File

@ -131,9 +131,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
}
argOrder.forEach {
val param = callee.parameters[it]
TODO("pop cpu stack into asmsub param ${param.first.name} ${param.second}")
// val targetVar = callee.searchParameter(param.name)!!
// asmgen.popCpuStack(param.first.type, targetVar, call.definingISub())
asmgen.popCpuStack(callee, param.first, param.second)
}
}