From 31c132c2ebfef803ae197489fc7eaf56642501ac Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 14 Sep 2023 23:04:23 +0200 Subject: [PATCH] several optimizations and compiler error fix for @(&var) and @(&var+1) --- .../codegen/cpu6502/BuiltinFunctionsAsmGen.kt | 20 +++++++-------- .../cpu6502/assignment/AssignmentAsmGen.kt | 12 +++++++++ .../optimizer/ConstantFoldingOptimizer.kt | 11 ++++---- .../compiler/astprocessing/CodeDesugarer.kt | 25 +++++++++++++++++++ examples/test.p8 | 24 +++++++++++------- 5 files changed, 68 insertions(+), 24 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt index 6f643f893..1bea01aac 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/BuiltinFunctionsAsmGen.kt @@ -986,17 +986,17 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } else { when(resultRegister) { null, RegisterOrPair.A -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" tya") } RegisterOrPair.X -> { asmgen.out(" pha") - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AX) asmgen.out(" pla") } RegisterOrPair.Y -> { asmgen.out(" pha") - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" pla") } else -> throw AssemblyError("invalid reg") @@ -1032,35 +1032,35 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram, } else { when(resultRegister) { null, RegisterOrPair.A -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) // NOTE: we rely on the fact that the above assignment to AY, assigns the Lsb to A as the last instruction. // this is required because the compiler assumes the status bits are set according to what A is (lsb) // and will not generate another cmp when lsb() is directly used inside a comparison expression. } RegisterOrPair.X -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.XY) // NOTE: we rely on the fact that the above assignment to XY, assigns the Lsb to X as the last instruction. // this is required because the compiler assumes the status bits are set according to what X is (lsb) // and will not generate another cmp when lsb() is directly used inside a comparison expression. } RegisterOrPair.Y -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" tay | cpy #0") } RegisterOrPair.AY -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY) asmgen.out(" ldy #0 | cmp #0") } RegisterOrPair.AX -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.AX) asmgen.out(" ldx #0 | cmp #0") } RegisterOrPair.XY -> { - asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY) + asmgen.assignExpressionToRegister(arg, RegisterOrPair.XY) asmgen.out(" ldy #0 | cpx #0") } in Cx16VirtualRegisters -> { - asmgen.assignExpressionToRegister(fcall.args.single(), resultRegister) + asmgen.assignExpressionToRegister(arg, resultRegister) val zero = PtNumber(DataType.UBYTE, 0.0, Position.DUMMY) zero.parent=fcall assignAsmGen.assignExpressionToVariable(zero, "cx16.${resultRegister.toString().lowercase()}H", DataType.UBYTE) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index ef2df9b37..d73f158c1 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -3592,6 +3592,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, private fun storeRegisterAInMemoryAddress(memoryAddress: PtMemoryByte) { val addressExpr = memoryAddress.address val addressLv = addressExpr as? PtNumber + val addressOf = addressExpr as? PtAddressOf fun storeViaExprEval() { when(addressExpr) { @@ -3613,10 +3614,21 @@ internal class AssignmentAsmGen(private val program: PtProgram, addressLv != null -> { asmgen.out(" sta ${addressLv.number.toHex()}") } + addressOf != null -> { + asmgen.out(" sta ${asmgen.asmSymbolName(addressOf.identifier)}") + } addressExpr is PtIdentifier -> { asmgen.storeAIntoPointerVar(addressExpr) } addressExpr is PtBinaryExpression -> { + if(addressExpr.operator=="+" || addressExpr.operator=="-") { + val addrOf = addressExpr.left as? PtAddressOf + val offset = (addressExpr.right as? PtNumber)?.number?.toInt() + if(addrOf!=null && offset!=null) { + asmgen.out(" sta ${asmgen.asmSymbolName(addrOf.identifier)}${addressExpr.operator}${offset}") + return + } + } if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true)) storeViaExprEval() } diff --git a/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt index 2473a7af3..63b8e31a5 100644 --- a/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt +++ b/codeOptimizers/src/prog8/optimizer/ConstantFoldingOptimizer.kt @@ -19,12 +19,13 @@ import kotlin.math.floor class ConstantFoldingOptimizer(private val program: Program) : AstWalker() { override fun before(memread: DirectMemoryRead, parent: Node): Iterable { - // @( &thing ) --> thing + // @( &thing ) --> thing (but only if thing is a byte type!) val addrOf = memread.addressExpression as? AddressOf - return if(addrOf!=null) - listOf(IAstModification.ReplaceNode(memread, addrOf.identifier, parent)) - else - noModifications + if(addrOf!=null) { + if(addrOf.identifier.inferType(program).isBytes) + return listOf(IAstModification.ReplaceNode(memread, addrOf.identifier, parent)) + } + return noModifications } override fun after(containment: ContainmentCheck, parent: Node): Iterable { diff --git a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt index 859236f24..38fc88200 100644 --- a/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt +++ b/compiler/src/prog8/compiler/astprocessing/CodeDesugarer.kt @@ -24,6 +24,7 @@ internal class CodeDesugarer(val program: Program, private val errors: IErrorRep // - replace peek() and poke() by direct memory accesses. // - repeat-forever loops replaced by label+jump. // - pointer[word] replaced by @(pointer+word) + // - @(&var) and @(&var+1) replaced by lsb(var) and msb(var) if var is a word override fun before(breakStmt: Break, parent: Node): Iterable { @@ -211,4 +212,28 @@ _after: return noModifications } + + override fun after(memread: DirectMemoryRead, parent: Node): Iterable { + // for word variables: + // @(&var) --> lsb(var) + // @(&var+1) --> msb(var) + + val addrOf = memread.addressExpression as? AddressOf + if(addrOf!=null && addrOf.identifier.inferType(program).isWords) { + val lsb = FunctionCallExpression(IdentifierReference(listOf("lsb"), memread.position), mutableListOf(addrOf.identifier), memread.position) + return listOf(IAstModification.ReplaceNode(memread, lsb, parent)) + } + val expr = memread.addressExpression as? BinaryExpression + if(expr!=null && expr.operator=="+") { + val addressOf = expr.left as? AddressOf + val offset = (expr.right as? NumericLiteral)?.number?.toInt() + if(addressOf!=null && offset==1) { + val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), memread.position), mutableListOf(addressOf.identifier), memread.position) + return listOf(IAstModification.ReplaceNode(memread, msb, parent)) + } + } + + return noModifications + } + } diff --git a/examples/test.p8 b/examples/test.p8 index 9d2b43622..9eec7cce7 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,16 +1,22 @@ +%import textio %zeropage basicsafe main { - uword w1 - uword w2 - sub start() { - bool zz = (w1 & w2)==0 + uword zz = 0 - if (w1 & w2) - w1++ - - if not(w1 & w2) - w1++ + @(&zz) = 1 + txt.print_uw(zz) + txt.nl() + @(&zz+1) = 2 + txt.print_uw(zz) + txt.nl() + ubyte bb + bb = @(&zz) + txt.print_ub(bb) + txt.nl() + bb = @(&zz+1) + txt.print_ub(bb) + txt.nl() } }