mirror of
https://github.com/irmen/prog8.git
synced 2024-07-24 22:29:15 +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?) {
|
internal fun popCpuStack(asmsub: PtAsmSub, parameter: PtSubroutineParameter, reg: RegisterOrStatusflag) {
|
||||||
// note: because A is pushed first so popped last, saving A is often not required here.
|
val shouldKeepA = asmsub.parameters.any { it.second.registerOrPair==RegisterOrPair.AX || it.second.registerOrPair==RegisterOrPair.AY}
|
||||||
val parameter = (target as PtNode).definingSub()?.parameters?.singleOrNull { it.name===target.name }
|
if(reg.statusflag!=null) {
|
||||||
if(parameter!=null) {
|
if(shouldKeepA)
|
||||||
val sub = parameter.definingAsmSub() ?: throw AssemblyError("push/pop arg passing only supported on asmsubs ${target.position}")
|
out(" sta P8ZP_SCRATCH_REG")
|
||||||
val shouldKeepA = sub.parameters.any { it.second.registerOrPair==RegisterOrPair.AX || it.second.registerOrPair==RegisterOrPair.AY}
|
out("""
|
||||||
val reg = sub.parameters.single { it.first === parameter }.second
|
|
||||||
if(reg.statusflag!=null) {
|
|
||||||
if(shouldKeepA)
|
|
||||||
out(" sta P8ZP_SCRATCH_REG")
|
|
||||||
out("""
|
|
||||||
clc
|
clc
|
||||||
pla
|
pla
|
||||||
beq +
|
beq +
|
||||||
sec
|
sec
|
||||||
+""")
|
+""")
|
||||||
if(shouldKeepA)
|
if(shouldKeepA)
|
||||||
out(" lda P8ZP_SCRATCH_REG")
|
out(" lda P8ZP_SCRATCH_REG")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (dt in ByteDatatypes) {
|
if (parameter.type in ByteDatatypes) {
|
||||||
if (isTargetCpu(CpuType.CPU65c02)) {
|
if (isTargetCpu(CpuType.CPU65c02)) {
|
||||||
when (reg.registerOrPair) {
|
when (reg.registerOrPair) {
|
||||||
RegisterOrPair.A -> out(" pla")
|
RegisterOrPair.A -> out(" pla")
|
||||||
RegisterOrPair.X -> out(" plx")
|
RegisterOrPair.X -> out(" plx")
|
||||||
RegisterOrPair.Y -> out(" ply")
|
RegisterOrPair.Y -> out(" ply")
|
||||||
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
|
in Cx16VirtualRegisters -> out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
|
||||||
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
|
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}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// word pop
|
when (reg.registerOrPair) {
|
||||||
if (isTargetCpu(CpuType.CPU65c02))
|
RegisterOrPair.A -> out(" pla")
|
||||||
when (reg.registerOrPair) {
|
RegisterOrPair.X -> {
|
||||||
RegisterOrPair.AX -> out(" plx | pla")
|
if(shouldKeepA)
|
||||||
RegisterOrPair.AY -> out(" ply | pla")
|
out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
|
||||||
RegisterOrPair.XY -> out(" ply | plx")
|
else
|
||||||
in Cx16VirtualRegisters -> {
|
out(" pla | tax")
|
||||||
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 {
|
RegisterOrPair.Y -> {
|
||||||
when (reg.registerOrPair) {
|
if(shouldKeepA)
|
||||||
RegisterOrPair.AX -> out(" pla | tax | pla")
|
out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
|
||||||
RegisterOrPair.AY -> out(" pla | tay | pla")
|
else
|
||||||
RegisterOrPair.XY -> out(" pla | tay | pla | tax")
|
out(" pla | tay")
|
||||||
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}")
|
|
||||||
}
|
}
|
||||||
|
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 {
|
} else {
|
||||||
val scopedName = when(target) {
|
if (isTargetCpu(CpuType.CPU65c02))
|
||||||
is PtConstant -> target.scopedName
|
out(" ply | pla")
|
||||||
is PtMemMapped -> target.scopedName
|
else
|
||||||
is PtVariable -> target.scopedName
|
out(" pla | tay | pla")
|
||||||
else -> throw AssemblyError("weird target var")
|
assignRegister(RegisterOrPair.AY, tgt)
|
||||||
}
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,12 +36,12 @@ fun asmsub6502ArgsEvalOrder(sub: PtAsmSub): List<Int> {
|
|||||||
|
|
||||||
fun asmsub6502ArgsHaveRegisterClobberRisk(
|
fun asmsub6502ArgsHaveRegisterClobberRisk(
|
||||||
args: List<PtExpression>,
|
args: List<PtExpression>,
|
||||||
paramRegisters: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>
|
params: List<Pair<PtSubroutineParameter, RegisterOrStatusflag>>
|
||||||
): Boolean {
|
): Boolean {
|
||||||
fun isClobberRisk(expr: PtExpression): Boolean {
|
fun isClobberRisk(expr: PtExpression): Boolean {
|
||||||
when (expr) {
|
when (expr) {
|
||||||
is PtArrayIndexer -> {
|
is PtArrayIndexer -> {
|
||||||
return paramRegisters.any {
|
return params.any {
|
||||||
it.second.registerOrPair in listOf(RegisterOrPair.Y, RegisterOrPair.AY, RegisterOrPair.XY)
|
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 {
|
argOrder.forEach {
|
||||||
val param = callee.parameters[it]
|
val param = callee.parameters[it]
|
||||||
TODO("pop cpu stack into asmsub param ${param.first.name} ${param.second}")
|
asmgen.popCpuStack(callee, param.first, param.second)
|
||||||
// val targetVar = callee.searchParameter(param.name)!!
|
|
||||||
// asmgen.popCpuStack(param.first.type, targetVar, call.definingISub())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user