mirror of
https://github.com/irmen/prog8.git
synced 2024-08-18 23:29:32 +00:00
moved A to the end of the param list to avoid having to store its value
This commit is contained in:
parent
f3a4048ebf
commit
3d23b39f4c
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
}}
|
||||
|
Loading…
Reference in New Issue
Block a user