From ddf1be2a13f190576f0dab1b901d5a873455617d Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 8 Dec 2020 22:10:12 +0100 Subject: [PATCH] status condition couldn't properly be tested because restoring the X register clobbers the status flag --- compiler/res/prog8lib/diskio.p8 | 8 ++--- .../src/prog8/ast/statements/AstStatements.kt | 2 ++ .../target/c64/codegen/ExpressionsAsmGen.kt | 2 +- .../target/c64/codegen/FunctionCallAsmGen.kt | 4 +-- .../codegen/assignment/AssignmentAsmGen.kt | 2 +- examples/test.p8 | 34 +++---------------- 6 files changed, 14 insertions(+), 38 deletions(-) diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index 017fb37d2..423c0e510 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -134,11 +134,9 @@ io_error: @(nameptr) = 0 - ; read the rest of the entry until the end - do { - ubyte char2 = c64.CHRIN() - char2++ ; TODO fix condition test problem with ldx - } until char2==1 + while c64.CHRIN() { + ; read the rest of the entry until the end + } void c64.CHRIN() ; skip 2 bytes void c64.CHRIN() diff --git a/compiler/src/prog8/ast/statements/AstStatements.kt b/compiler/src/prog8/ast/statements/AstStatements.kt index 97b52423b..b1e922fb7 100644 --- a/compiler/src/prog8/ast/statements/AstStatements.kt +++ b/compiler/src/prog8/ast/statements/AstStatements.kt @@ -757,6 +757,8 @@ class Subroutine(override val name: String, fun regXasResult() = asmReturnvaluesRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) } fun regXasParam() = asmParameterRegisters.any { it.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) } + fun shouldPreserveStatusRegisterAfterCall() = asmReturnvaluesRegisters.any { it.statusflag != null } || shouldSaveX() + fun shouldSaveX() = CpuRegister.X in asmClobbers || regXasResult() || regXasParam() fun amountOfRtsInAsm(): Int = statements .asSequence() diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index e15408c14..a7e2cb8c3 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1329,7 +1329,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge asmgen.translateBuiltinFunctionCallExpression(expression, builtinFunc, true) } else { sub as Subroutine - val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any {it.statusflag!=null} + val preserveStatusRegisterAfterCall = sub.shouldPreserveStatusRegisterAfterCall() asmgen.translateFunctionCall(expression, preserveStatusRegisterAfterCall) val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters) for ((_, reg) in returns) { diff --git a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt index 46bca62d2..07f399073 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/FunctionCallAsmGen.kt @@ -16,7 +16,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg internal fun translateFunctionCallStatement(stmt: IFunctionCall) { val sub = stmt.target.targetSubroutine(program.namespace)!! - val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any {it.statusflag!=null} + val preserveStatusRegisterAfterCall = sub.shouldPreserveStatusRegisterAfterCall() translateFunctionCall(stmt, preserveStatusRegisterAfterCall) // functioncalls no longer return results on the stack, so simply ignore the results in the registers if(preserveStatusRegisterAfterCall) @@ -28,7 +28,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg // output the code to setup the parameters and perform the actual call // does NOT output the code to deal with the result values! 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 = sub.shouldSaveX() if(saveX) asmgen.saveRegister(CpuRegister.X, preserveStatusRegisterAfterCall, (stmt as Node).definingSubroutine()!!) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt index 03e9bc4aa..dd9da521c 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AssignmentAsmGen.kt @@ -142,7 +142,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen is FunctionCall -> { when (val sub = value.target.targetStatement(program.namespace)) { is Subroutine -> { - val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any { it.statusflag != null } + val preserveStatusRegisterAfterCall = sub.shouldPreserveStatusRegisterAfterCall() asmgen.translateFunctionCall(value, preserveStatusRegisterAfterCall) val returnValue = sub.returntypes.zip(sub.asmReturnvaluesRegisters).single { it.second.registerOrPair!=null } when (returnValue.first) { diff --git a/examples/test.p8 b/examples/test.p8 index 0b7e8340c..ad1a9262f 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -8,36 +8,12 @@ errors { sub tofix() { - repeat { - ubyte char3 = c64.CHRIN() - if_cc - break - if_z - char3 ++ - else - break - - char3-- - } -labeltje: - - - while c64.CHRIN() { - ; TODO: the loop condition isn't properly tested because a ldx is in the way before the beq - } - - repeat { - ubyte char2 = c64.CHRIN() - if char2==0 ; TODO condition not properly tested after optimizing because there's only a sta char2 before it (works without optimizing) - break - } - - ; TODO fix undefined symbol: - repeat { - ubyte char = c64.CHRIN() - ; ... - } +; ; TODO fix undefined symbol: +; repeat { +; ubyte char = c64.CHRIN() +; ; ... +; } ; do { ; char = c64.CHRIN() ; TODO fix undefined symbol error, should refer to 'char' above in the subroutine's scope ; } until char==0