diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 61323798f..2633e8695 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -87,7 +87,7 @@ class AsmGen(private val program: Program, assemblyLines.addAll(outputFile.readLines()) var optimizationsDone = 1 while (optimizationsDone > 0) { - optimizationsDone = optimizeAssembly(assemblyLines, options.compTarget.machine) + optimizationsDone = optimizeAssembly(assemblyLines, options.compTarget.machine, program) } outputFile.printWriter().use { for (line in assemblyLines) { it.println(line) } diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt index 74c1658f3..b688c92a1 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmOptimizer.kt @@ -1,12 +1,16 @@ package prog8.compiler.target.cpu6502.codegen +import prog8.ast.Program +import prog8.ast.base.VarDeclType +import prog8.ast.expressions.NumericLiteralValue +import prog8.ast.statements.VarDecl import prog8.compilerinterface.IMachineDefinition // note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations -fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition): Int { +fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition, program: Program): Int { var numberOfOptimizations = 0 @@ -33,7 +37,7 @@ fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition): I numberOfOptimizations++ } - mods = optimizeStoreLoadSame(linesByFour, machine) + mods = optimizeStoreLoadSame(linesByFour, machine, program) if(mods.isNotEmpty()) { apply(mods, lines) linesByFour = getLinesBy(lines, 4) @@ -48,7 +52,7 @@ fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition): I } var linesByFourteen = getLinesBy(lines, 14) - mods = optimizeSameAssignments(linesByFourteen, machine) + mods = optimizeSameAssignments(linesByFourteen, machine, program) if(mods.isNotEmpty()) { apply(mods, lines) linesByFourteen = getLinesBy(lines, 14) @@ -113,7 +117,7 @@ private fun optimizeUselessStackByteWrites(linesByFour: List>>, machine: IMachineDefinition): List { +private fun optimizeSameAssignments(linesByFourteen: List>>, machine: IMachineDefinition, program: Program): List { // Optimize sequential assignments of the same value to various targets (bytes, words, floats) // the float one is the one that requires 2*7=14 lines of code to check... @@ -138,8 +142,8 @@ private fun optimizeSameAssignments(linesByFourteen: List remove second lda/ldy pair (fifth and sixth lines) - val address1 = getAddressArg(first) - val address2 = getAddressArg(second) + val address1 = getAddressArg(first, program) + val address2 = getAddressArg(second, program) if(address1==null || address2==null || (!machine.isIOAddress(address1) && !machine.isIOAddress(address2))) { mods.add(Modification(lines[4].index, true, null)) mods.add(Modification(lines[5].index, true, null)) @@ -152,7 +156,7 @@ private fun optimizeSameAssignments(linesByFourteen: List remove second lda (third line) - val address = getAddressArg(first) + val address = getAddressArg(first, program) if(address==null || !machine.isIOAddress(address)) mods.add(Modification(lines[2].index, true, null)) } @@ -235,7 +239,7 @@ private fun optimizeSameAssignments(linesByFourteen: List>>, machine: IMachineDefinition): List { +private fun optimizeStoreLoadSame(linesByFour: List>>, machine: IMachineDefinition, program: Program): List { // sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can OFTEN be eliminated val mods = mutableListOf() for (lines in linesByFour) { @@ -338,7 +342,7 @@ private fun optimizeStoreLoadSame(linesByFour: List>>, } else { // no branch instruction follows, we can remove the load instruction - val address = getAddressArg(lines[2].value) + val address = getAddressArg(lines[2].value, program) address==null || !machine.isIOAddress(address) } @@ -353,13 +357,30 @@ private fun optimizeStoreLoadSame(linesByFour: List>>, return mods } -private fun getAddressArg(line: String): UInt? { +private val identifierRegex = Regex("""^([a-zA-Z_$][a-zA-Z\d_\.$]*)""") + +private fun getAddressArg(line: String, program: Program): UInt? { val loadArg = line.trimStart().substring(3).trim() return when { loadArg.startsWith('$') -> loadArg.substring(1).toUIntOrNull(16) loadArg.startsWith('%') -> loadArg.substring(1).toUIntOrNull(2) loadArg.startsWith('#') -> null loadArg.startsWith('(') -> null + loadArg[0].isLetter() -> { + val identMatch = identifierRegex.find(loadArg) + if(identMatch!=null) { + val identifier = identMatch.value + val decl = program.toplevelModule.lookup(identifier.split(".")) as? VarDecl + if(decl!=null) { + when(decl.type){ + VarDeclType.VAR -> null + VarDeclType.CONST, + VarDeclType.MEMORY -> (decl.value as NumericLiteralValue).number.toUInt() + } + } + else null + } else null + } else -> loadArg.substring(1).toUIntOrNull() } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index a45d41ac4..de2e45cbb 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,9 +3,6 @@ TODO For next compiler release (7.4) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -BUG: amiga example doesn't clear the whole screen when compiled with optimizations (ok without opts) - same sort of problem in bobs example, and highresbitmap, and testgfx2 - ...