From e67464325f8d144273b67068767457d7f5af02b9 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 28 Jan 2023 00:00:23 +0100 Subject: [PATCH] fix missing symboltable entries for asmgen --- .../src/prog8/codegen/cpu6502/AsmGen.kt | 2 +- .../src/prog8/codegen/cpu6502/AsmOptimizer.kt | 52 ++++++++++++------- .../astprocessing/SymbolTableMaker.kt | 9 ++++ 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt index efcb9d514..154ac15fe 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmGen.kt @@ -48,7 +48,7 @@ class AsmGen( if(options.optimize) { val separateLines = assemblyLines.flatMapTo(mutableListOf()) { it.split('\n') } assemblyLines.clear() - while(optimizeAssembly(separateLines, options.compTarget.machine, program)>0) { + while(optimizeAssembly(separateLines, options.compTarget.machine, symbolTable)>0) { // optimize the assembly source code } output.writeLines(separateLines) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt index e50c17c6f..ba312db61 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AsmOptimizer.kt @@ -1,13 +1,16 @@ package prog8.codegen.cpu6502 -import prog8.code.ast.PtProgram +import prog8.code.StConstant +import prog8.code.StMemVar +import prog8.code.SymbolTable +import prog8.code.core.AssemblyError import prog8.code.core.IMachineDefinition // note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations -internal fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition, program: PtProgram): Int { +internal fun optimizeAssembly(lines: MutableList, machine: IMachineDefinition, symbolTable: SymbolTable): Int { var numberOfOptimizations = 0 @@ -34,7 +37,7 @@ internal fun optimizeAssembly(lines: MutableList, machine: IMachineDefin numberOfOptimizations++ } - mods = optimizeStoreLoadSame(linesByFour, machine, program) + mods = optimizeStoreLoadSame(linesByFour, machine, symbolTable) if(mods.isNotEmpty()) { apply(mods, lines) linesByFour = getLinesBy(lines, 4) @@ -49,14 +52,14 @@ internal fun optimizeAssembly(lines: MutableList, machine: IMachineDefin } var linesByFourteen = getLinesBy(lines, 14) - mods = optimizeSameAssignments(linesByFourteen, machine, program) + mods = optimizeSameAssignments(linesByFourteen, machine, symbolTable) if(mods.isNotEmpty()) { apply(mods, lines) linesByFourteen = getLinesBy(lines, 14) numberOfOptimizations++ } - mods = optimizeSamePointerIndexing(linesByFourteen, machine, program) + mods = optimizeSamePointerIndexing(linesByFourteen) if(mods.isNotEmpty()) { apply(mods, lines) linesByFourteen = getLinesBy(lines, 14) @@ -126,7 +129,11 @@ private fun optimizeUselessStackByteWrites(linesByFour: List>>, machine: IMachineDefinition, program: PtProgram): List { +private fun optimizeSameAssignments( + linesByFourteen: List>>, + machine: IMachineDefinition, + symbolTable: SymbolTable +): 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... @@ -151,8 +158,8 @@ private fun optimizeSameAssignments(linesByFourteen: List remove second lda/ldy pair (fifth and sixth lines) - val address1 = getAddressArg(first, program) - val address2 = getAddressArg(second, program) + val address1 = getAddressArg(first, symbolTable) + val address2 = getAddressArg(second, symbolTable) 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)) @@ -165,7 +172,7 @@ private fun optimizeSameAssignments(linesByFourteen: List remove second lda (third line) - val address = getAddressArg(first, program) + val address = getAddressArg(first, symbolTable) if(address==null || !machine.isIOAddress(address)) mods.add(Modification(lines[2].index, true, null)) } @@ -248,7 +255,7 @@ private fun optimizeSameAssignments(linesByFourteen: List>>, machine: IMachineDefinition, program: PtProgram): List { +private fun optimizeSamePointerIndexing(linesByFourteen: List>>): List { // Optimize same pointer indexing where for instance we load and store to the same ptr index in Y // if Y isn't modified in between we can omit the second LDY: @@ -366,7 +373,11 @@ private fun optimizeSamePointerIndexing(linesByFourteen: List>>, machine: IMachineDefinition, program: PtProgram): List { +private fun optimizeStoreLoadSame( + linesByFour: List>>, + machine: IMachineDefinition, + symbolTable: SymbolTable +): 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) { @@ -394,7 +405,7 @@ private fun optimizeStoreLoadSame(linesByFour: List>>, } else { // no branch instruction follows, we can remove the load instruction - val address = getAddressArg(lines[2].value, program) + val address = getAddressArg(lines[2].value, symbolTable) address==null || !machine.isIOAddress(address) } @@ -436,7 +447,7 @@ private fun optimizeStoreLoadSame(linesByFour: List>>, private val identifierRegex = Regex("""^([a-zA-Z_$][a-zA-Z\d_\.$]*)""") -private fun getAddressArg(line: String, program: PtProgram): UInt? { +private fun getAddressArg(line: String, symbolTable: SymbolTable): UInt? { val loadArg = line.trimStart().substring(3).trim() return when { loadArg.startsWith('$') -> loadArg.substring(1).toUIntOrNull(16) @@ -447,7 +458,12 @@ private fun getAddressArg(line: String, program: PtProgram): UInt? { val identMatch = identifierRegex.find(loadArg) if(identMatch!=null) { val identifier = identMatch.value - TODO("lookup symbol's value $identifier") + when (val symbol = symbolTable.flat[identifier]) { + is StConstant -> symbol.value.toUInt() + is StMemVar -> symbol.address + null -> null + else -> throw AssemblyError("expected constant or memvar for address $line") + } } else null } else -> loadArg.substring(1).toUIntOrNull() diff --git a/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt b/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt index c78ec197a..9e412db3e 100644 --- a/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt +++ b/compiler/src/prog8/compiler/astprocessing/SymbolTableMaker.kt @@ -28,6 +28,15 @@ internal class SymbolTableMaker(private val program: Program, private val option st.add(node) } require(scopestack.isEmpty()) + + // add the hardcoded temporary zeropage variables + st.add(StMemVar("P8ZP_SCRATCH_B1", DataType.UBYTE, options.compTarget.machine.zeropage.SCRATCH_B1, null, Position.DUMMY)) + st.add(StMemVar("P8ZP_SCRATCH_REG", DataType.UBYTE, options.compTarget.machine.zeropage.SCRATCH_REG, null, Position.DUMMY)) + st.add(StMemVar("P8ZP_SCRATCH_W1", DataType.UWORD, options.compTarget.machine.zeropage.SCRATCH_W1, null, Position.DUMMY)) + st.add(StMemVar("P8ZP_SCRATCH_W2", DataType.UWORD, options.compTarget.machine.zeropage.SCRATCH_W2, null, Position.DUMMY)) + st.add(StMemVar("P8ESTACK_LO", DataType.UBYTE, options.compTarget.machine.ESTACK_LO, null, Position.DUMMY)) + st.add(StMemVar("P8ESTACK_HI", DataType.UBYTE, options.compTarget.machine.ESTACK_HI, null, Position.DUMMY)) + return st }