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:
|
// order is:
|
||||||
// 1) cx16 virtual word registers,
|
// 1) cx16 virtual word registers,
|
||||||
// 2) paired CPU registers,
|
// 2) paired CPU registers,
|
||||||
// 3) single CPU registers (X last),
|
// 3) single CPU registers (X last), except A,
|
||||||
// 4) CPU Carry status flag
|
// 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 args = sub.parameters.zip(sub.asmParameterRegisters).withIndex()
|
||||||
val (cx16regs, args2) = args.partition { it.value.second.registerOrPair in Cx16VirtualRegisters }
|
val (cx16regs, args2) = args.partition { it.value.second.registerOrPair in Cx16VirtualRegisters }
|
||||||
val pairedRegisters = arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)
|
val pairedRegisters = arrayOf(RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY)
|
||||||
val (pairedRegs , args3) = args2.partition { it.value.second.registerOrPair in pairedRegisters }
|
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 }
|
cx16regs.forEach { order += it.index }
|
||||||
pairedRegs.forEach { order += it.index }
|
pairedRegs.forEach { order += it.index }
|
||||||
regs.forEach {
|
regsWithoutA.forEach {
|
||||||
if(it.value.second.registerOrPair != RegisterOrPair.X)
|
if(it.value.second.registerOrPair != RegisterOrPair.X)
|
||||||
order += it.index
|
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 }
|
rest.forEach { order += it.index }
|
||||||
|
regA.forEach { order += it.index }
|
||||||
require(order.size==sub.parameters.size)
|
require(order.size==sub.parameters.size)
|
||||||
return order
|
return order
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun funcPop(fcall: IFunctionCall, func: FSignature) {
|
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) {
|
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}"
|
"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) {
|
require(sub.isAsmSubroutine) {
|
||||||
"push/pop arg passing only supported on asmsubs ${(fcall as Node).position}"
|
"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)]
|
val reg = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)]
|
||||||
if(reg.statusflag!=null) {
|
if(reg.statusflag!=null) {
|
||||||
|
if(shouldKeepA)
|
||||||
|
asmgen.out(" sta P8ZP_SCRATCH_REG")
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
sta P8ZP_SCRATCH_REG
|
|
||||||
clc
|
clc
|
||||||
pla
|
pla
|
||||||
beq +
|
beq +
|
||||||
sec
|
sec
|
||||||
+ lda P8ZP_SCRATCH_REG""")
|
+""")
|
||||||
|
if(shouldKeepA)
|
||||||
|
asmgen.out(" lda P8ZP_SCRATCH_REG")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (func.name == "pop") {
|
if (func.name == "pop") {
|
||||||
@ -109,15 +114,25 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
when (reg.registerOrPair) {
|
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.A -> asmgen.out(" pla")
|
||||||
RegisterOrPair.X -> asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG")
|
RegisterOrPair.X -> {
|
||||||
RegisterOrPair.Y -> asmgen.out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG")
|
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()}")
|
in Cx16VirtualRegisters -> asmgen.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 {
|
} else {
|
||||||
|
// word pop
|
||||||
if (asmgen.isTargetCpu(CpuType.CPU65c02))
|
if (asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||||
when (reg.registerOrPair) {
|
when (reg.registerOrPair) {
|
||||||
RegisterOrPair.AX -> asmgen.out(" plx | pla")
|
RegisterOrPair.AX -> asmgen.out(" plx | pla")
|
||||||
|
@ -58,19 +58,17 @@ main {
|
|||||||
txt.nl()
|
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 {{
|
%asm {{
|
||||||
pha
|
sta routine.num
|
||||||
|
sty routine.num+1
|
||||||
lda #0
|
lda #0
|
||||||
adc #0
|
adc #0
|
||||||
sta routine.switch
|
sta routine.switch
|
||||||
pla
|
lda cx16.r0
|
||||||
sta routine.num
|
sta routine.a2
|
||||||
sty routine.num+1
|
|
||||||
lda cx16.r1
|
lda cx16.r1
|
||||||
sta routine.a1
|
sta routine.a1
|
||||||
lda cx16.r2
|
|
||||||
sta routine.a2
|
|
||||||
stx routine.a3
|
stx routine.a3
|
||||||
jmp routine
|
jmp routine
|
||||||
}}
|
}}
|
||||||
|
Loading…
Reference in New Issue
Block a user