don't clobber A when trying to save X at functioncall

This commit is contained in:
Irmen de Jong 2020-09-12 18:53:44 +02:00
parent 35aebbc209
commit 97b9c8f320
4 changed files with 31 additions and 28 deletions

View File

@ -552,55 +552,60 @@ internal class AsmGen(private val program: Program,
internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names internal fun fixNameSymbols(name: String) = name.replace("<", "prog8_").replace(">", "") // take care of the autogenerated invalid (anon) label names
internal fun saveRegister(register: CpuRegister, forFuncCall: Boolean = false, dontClobberA: Boolean = false) {
private val saveRegisterLabels = Stack<String>();
internal fun saveRegister(register: CpuRegister, forFuncCall: Boolean = false) {
when(register) { when(register) {
CpuRegister.A -> out(" pha") CpuRegister.A -> out(" pha")
CpuRegister.X -> { CpuRegister.X -> {
// TODO get rid of REG_X altogheter! replace with sta _save | txa | pha | lda _save // TODO get rid of REG_X altogether!
when { when {
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" phx") CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" phx")
forFuncCall -> { forFuncCall -> {
if(dontClobberA) val save = makeLabel("saveX")
out(" sta P8ZP_SCRATCH_REG | txa | pha | lda P8ZP_SCRATCH_REG") saveRegisterLabels.push(save)
else out("""
out(" txa | pha") stx $save
jmp +
$save .byte 0
+""")
} }
else -> out(" stx P8ZP_SCRATCH_REG_X") else -> out(" stx P8ZP_SCRATCH_REG_X")
} }
} }
CpuRegister.Y -> { CpuRegister.Y -> {
when { if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" phy") else {
dontClobberA -> out(" sta P8ZP_SCRATCH_REG | tya | pha | lda P8ZP_SCRATCH_REG") val save = makeLabel("saveY")
else -> out(" tya | pha") out("""
sty $save
jmp +
$save .byte 0
+""")
} }
} }
} }
} }
internal fun restoreRegister(register: CpuRegister, forFuncCall: Boolean = false, dontClobberA: Boolean=false) { internal fun restoreRegister(register: CpuRegister, forFuncCall: Boolean = false) {
when(register) { when(register) {
CpuRegister.A -> { CpuRegister.A -> out(" pla")
require(!dontClobberA)
out(" pla")
}
CpuRegister.X -> { CpuRegister.X -> {
when { when {
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" plx") CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" plx")
forFuncCall -> { forFuncCall -> {
if(dontClobberA) val save = saveRegisterLabels.pop()
out(" sta P8ZP_SCRATCH_REG | pla | tax | lda P8ZP_SCRATCH_REG") out(" ldx $save")
else
out(" pla | tax")
} }
else -> out(" ldx P8ZP_SCRATCH_REG_X") else -> out(" ldx P8ZP_SCRATCH_REG_X")
} }
} }
CpuRegister.Y -> { CpuRegister.Y -> {
when { if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" ply")
CompilationTarget.instance.machine.cpu == CpuType.CPU65c02 -> out(" ply") else {
dontClobberA -> out(" sta P8ZP_SCRATCH_REG | pla | tay | lda P8ZP_SCRATCH_REG") val save = saveRegisterLabels.pop()
else -> out(" pla | tay") out(" ldy $save")
} }
} }
} }

View File

@ -19,7 +19,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}") val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam() val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
if(saveX) if(saveX)
asmgen.saveRegister(CpuRegister.X, forFuncCall = true, dontClobberA = false) // we only save X for now (required! is the eval stack pointer), screw A and Y... asmgen.saveRegister(CpuRegister.X, forFuncCall = true)
val subName = asmgen.asmSymbolName(stmt.target) val subName = asmgen.asmSymbolName(stmt.target)
if(stmt.args.isNotEmpty()) { if(stmt.args.isNotEmpty()) {
@ -58,7 +58,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
asmgen.out(" jsr $subName") asmgen.out(" jsr $subName")
if(saveX) if(saveX)
asmgen.restoreRegister(CpuRegister.X, forFuncCall = true, dontClobberA = false) asmgen.restoreRegister(CpuRegister.X, forFuncCall = true)
} }
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) { private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {

View File

@ -248,7 +248,6 @@ waitkey:
c64.CHROUT('K') c64.CHROUT('K')
while c64.GETIN()!=133 { while c64.GETIN()!=133 {
; TODO FIX THIS, DOESN'T TRIGGER ANYMORE ON F1
; endless loop until user presses F1 to restart the game ; endless loop until user presses F1 to restart the game
} }
} }

View File

@ -1,5 +1,4 @@
%target cx16 %import c64textio
%import cx16textio
;%import c64flt ;%import c64flt
;%option enable_floats ;%option enable_floats
; %zeropage kernalsafe ; %zeropage kernalsafe