mirror of
https://github.com/irmen/prog8.git
synced 2025-02-06 01:30:23 +00:00
fix popCpuStack to load values into asmsub register params
This commit is contained in:
parent
988a3e4446
commit
a5ca08f33d
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user