moved A to the end of the param list to avoid having to store its value

This commit is contained in:
Irmen de Jong 2021-11-28 03:55:13 +01:00
parent f3a4048ebf
commit 3d23b39f4c
3 changed files with 32 additions and 16 deletions

View File

@ -11,22 +11,25 @@ internal fun asmsub6502ArgsEvalOrder(sub: Subroutine): List<Int> {
// order is:
// 1) cx16 virtual word registers,
// 2) paired CPU registers,
// 3) single CPU registers (X last),
// 3) single CPU registers (X last), except A,
// 4) CPU Carry status flag
// 5) the A register itself last (so everything before it can use the accumulator without having to save its value)
val args = sub.parameters.zip(sub.asmParameterRegisters).withIndex()
val (cx16regs, args2) = args.partition { it.value.second.registerOrPair in Cx16VirtualRegisters }
val pairedRegisters = arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)
val (pairedRegs , args3) = args2.partition { it.value.second.registerOrPair in pairedRegisters }
val (regs, rest) = args3.partition { it.value.second.registerOrPair != null }
val (regsWithoutA, args4) = args3.partition { it.value.second.registerOrPair != RegisterOrPair.A }
val (regA, rest) = args4.partition { it.value.second.registerOrPair != null }
cx16regs.forEach { order += it.index }
pairedRegs.forEach { order += it.index }
regs.forEach {
regsWithoutA.forEach {
if(it.value.second.registerOrPair != RegisterOrPair.X)
order += it.index
}
regs.firstOrNull { it.value.second.registerOrPair==RegisterOrPair.X } ?.let { order += it.index}
regsWithoutA.firstOrNull { it.value.second.registerOrPair==RegisterOrPair.X } ?.let { order += it.index}
rest.forEach { order += it.index }
regA.forEach { order += it.index }
require(order.size==sub.parameters.size)
return order
}

View File

@ -77,6 +77,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
private fun funcPop(fcall: IFunctionCall, func: FSignature) {
// note: because A is pushed first so popped last, saving A is often not required here.
require(fcall.args[0] is IdentifierReference) {
"attempt to pop a value into a differently typed variable, or in something else that isn't supported ${(fcall as Node).position}"
}
@ -87,15 +88,19 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
require(sub.isAsmSubroutine) {
"push/pop arg passing only supported on asmsubs ${(fcall as Node).position}"
}
val shouldKeepA = sub.asmParameterRegisters.any { it.registerOrPair==RegisterOrPair.AX || it.registerOrPair==RegisterOrPair.AY }
val reg = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)]
if(reg.statusflag!=null) {
if(shouldKeepA)
asmgen.out(" sta P8ZP_SCRATCH_REG")
asmgen.out("""
sta P8ZP_SCRATCH_REG
clc
pla
beq +
sec
+ lda P8ZP_SCRATCH_REG""")
+""")
if(shouldKeepA)
asmgen.out(" lda P8ZP_SCRATCH_REG")
}
else {
if (func.name == "pop") {
@ -109,15 +114,25 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
} else {
when (reg.registerOrPair) {
// TODO make sure that A is pushed first so popped last, so that those store/load to save A are no longer needed (c64)
RegisterOrPair.A -> asmgen.out(" pla")
RegisterOrPair.X -> asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
RegisterOrPair.Y -> asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
RegisterOrPair.X -> {
if(shouldKeepA)
asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
else
asmgen.out(" pla | tax")
}
RegisterOrPair.Y -> {
if(shouldKeepA)
asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
else
asmgen.out(" pla | tay")
}
in Cx16VirtualRegisters -> asmgen.out(" pla | sta cx16.${reg.registerOrPair!!.name.lowercase()}")
else -> throw AssemblyError("invalid target register ${reg.registerOrPair}")
}
}
} else {
// word pop
if (asmgen.isTargetCpu(CpuType.CPU65c02))
when (reg.registerOrPair) {
RegisterOrPair.AX -> asmgen.out(" plx | pla")

View File

@ -58,19 +58,17 @@ main {
txt.nl()
}
asmsub routine2(uword num @AY, ubyte a1 @R1, ubyte a2 @R2, ubyte switch @Pc, ubyte a3 @X) {
asmsub routine2(uword num @AY, ubyte a1 @R1, ubyte a2 @R0, ubyte switch @Pc, ubyte a3 @X) {
%asm {{
pha
sta routine.num
sty routine.num+1
lda #0
adc #0
sta routine.switch
pla
sta routine.num
sty routine.num+1
lda cx16.r0
sta routine.a2
lda cx16.r1
sta routine.a1
lda cx16.r2
sta routine.a2
stx routine.a3
jmp routine
}}