fix missing symboltable entries for asmgen

This commit is contained in:
Irmen de Jong 2023-01-28 00:00:23 +01:00
parent 94c9b0d23b
commit e67464325f
3 changed files with 44 additions and 19 deletions

View File

@ -48,7 +48,7 @@ class AsmGen(
if(options.optimize) { if(options.optimize) {
val separateLines = assemblyLines.flatMapTo(mutableListOf()) { it.split('\n') } val separateLines = assemblyLines.flatMapTo(mutableListOf()) { it.split('\n') }
assemblyLines.clear() assemblyLines.clear()
while(optimizeAssembly(separateLines, options.compTarget.machine, program)>0) { while(optimizeAssembly(separateLines, options.compTarget.machine, symbolTable)>0) {
// optimize the assembly source code // optimize the assembly source code
} }
output.writeLines(separateLines) output.writeLines(separateLines)

View File

@ -1,13 +1,16 @@
package prog8.codegen.cpu6502 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 import prog8.code.core.IMachineDefinition
// note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations // note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations
internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefinition, program: PtProgram): Int { internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefinition, symbolTable: SymbolTable): Int {
var numberOfOptimizations = 0 var numberOfOptimizations = 0
@ -34,7 +37,7 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
numberOfOptimizations++ numberOfOptimizations++
} }
mods = optimizeStoreLoadSame(linesByFour, machine, program) mods = optimizeStoreLoadSame(linesByFour, machine, symbolTable)
if(mods.isNotEmpty()) { if(mods.isNotEmpty()) {
apply(mods, lines) apply(mods, lines)
linesByFour = getLinesBy(lines, 4) linesByFour = getLinesBy(lines, 4)
@ -49,14 +52,14 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
} }
var linesByFourteen = getLinesBy(lines, 14) var linesByFourteen = getLinesBy(lines, 14)
mods = optimizeSameAssignments(linesByFourteen, machine, program) mods = optimizeSameAssignments(linesByFourteen, machine, symbolTable)
if(mods.isNotEmpty()) { if(mods.isNotEmpty()) {
apply(mods, lines) apply(mods, lines)
linesByFourteen = getLinesBy(lines, 14) linesByFourteen = getLinesBy(lines, 14)
numberOfOptimizations++ numberOfOptimizations++
} }
mods = optimizeSamePointerIndexing(linesByFourteen, machine, program) mods = optimizeSamePointerIndexing(linesByFourteen)
if(mods.isNotEmpty()) { if(mods.isNotEmpty()) {
apply(mods, lines) apply(mods, lines)
linesByFourteen = getLinesBy(lines, 14) linesByFourteen = getLinesBy(lines, 14)
@ -126,7 +129,11 @@ private fun optimizeUselessStackByteWrites(linesByFour: List<List<IndexedValue<S
return mods return mods
} }
private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<String>>>, machine: IMachineDefinition, program: PtProgram): List<Modification> { private fun optimizeSameAssignments(
linesByFourteen: List<List<IndexedValue<String>>>,
machine: IMachineDefinition,
symbolTable: SymbolTable
): List<Modification> {
// Optimize sequential assignments of the same value to various targets (bytes, words, floats) // 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... // 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<List<IndexedValue<Stri
val fourthvalue = sixth.substring(4) val fourthvalue = sixth.substring(4)
if(firstvalue==thirdvalue && secondvalue==fourthvalue) { if(firstvalue==thirdvalue && secondvalue==fourthvalue) {
// lda/ldy sta/sty twice the same word --> remove second lda/ldy pair (fifth and sixth lines) // lda/ldy sta/sty twice the same word --> remove second lda/ldy pair (fifth and sixth lines)
val address1 = getAddressArg(first, program) val address1 = getAddressArg(first, symbolTable)
val address2 = getAddressArg(second, program) val address2 = getAddressArg(second, symbolTable)
if(address1==null || address2==null || (!machine.isIOAddress(address1) && !machine.isIOAddress(address2))) { if(address1==null || address2==null || (!machine.isIOAddress(address1) && !machine.isIOAddress(address2))) {
mods.add(Modification(lines[4].index, true, null)) mods.add(Modification(lines[4].index, true, null))
mods.add(Modification(lines[5].index, true, null)) mods.add(Modification(lines[5].index, true, null))
@ -165,7 +172,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
val secondvalue = third.substring(4) val secondvalue = third.substring(4)
if(firstvalue==secondvalue) { if(firstvalue==secondvalue) {
// lda value / sta ? / lda same-value / sta ? -> remove second lda (third line) // lda value / sta ? / lda same-value / sta ? -> remove second lda (third line)
val address = getAddressArg(first, program) val address = getAddressArg(first, symbolTable)
if(address==null || !machine.isIOAddress(address)) if(address==null || !machine.isIOAddress(address))
mods.add(Modification(lines[2].index, true, null)) mods.add(Modification(lines[2].index, true, null))
} }
@ -248,7 +255,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
val thirdvalue = third.substring(4) val thirdvalue = third.substring(4)
val fourthvalue = fourth.substring(4) val fourthvalue = fourth.substring(4)
if(firstvalue==thirdvalue && secondvalue == fourthvalue) { if(firstvalue==thirdvalue && secondvalue == fourthvalue) {
val address = getAddressArg(first, program) val address = getAddressArg(first, symbolTable)
if(address==null || !machine.isIOAddress(address)) { if(address==null || !machine.isIOAddress(address)) {
overlappingMods = true overlappingMods = true
mods.add(Modification(lines[2].index, true, null)) mods.add(Modification(lines[2].index, true, null))
@ -272,7 +279,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
val firstvalue = first.substring(4) val firstvalue = first.substring(4)
val thirdvalue = third.substring(4) val thirdvalue = third.substring(4)
if(firstvalue==thirdvalue) { if(firstvalue==thirdvalue) {
val address = getAddressArg(first, program) val address = getAddressArg(first, symbolTable)
if(address==null || !machine.isIOAddress(address)) { if(address==null || !machine.isIOAddress(address)) {
overlappingMods = true overlappingMods = true
mods.add(Modification(lines[2].index, true, null)) mods.add(Modification(lines[2].index, true, null))
@ -292,7 +299,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
val secondvalue = second.substring(4) val secondvalue = second.substring(4)
val thirdvalue = third.substring(4) val thirdvalue = third.substring(4)
if(firstvalue==secondvalue && firstvalue==thirdvalue) { if(firstvalue==secondvalue && firstvalue==thirdvalue) {
val address = getAddressArg(first, program) val address = getAddressArg(first, symbolTable)
if(address==null || !machine.isIOAddress(address)) { if(address==null || !machine.isIOAddress(address)) {
overlappingMods = true overlappingMods = true
val reg2 = second[2] val reg2 = second[2]
@ -311,7 +318,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
val firstvalue = first.substring(4) val firstvalue = first.substring(4)
val secondvalue = second.substring(4) val secondvalue = second.substring(4)
if(firstvalue==secondvalue) { if(firstvalue==secondvalue) {
val address = getAddressArg(first, program) val address = getAddressArg(first, symbolTable)
if(address==null || !machine.isIOAddress(address)) { if(address==null || !machine.isIOAddress(address)) {
overlappingMods = true overlappingMods = true
mods.add(Modification(lines[0].index, true, null)) mods.add(Modification(lines[0].index, true, null))
@ -324,7 +331,7 @@ private fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<Stri
return mods return mods
} }
private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<String>>>, machine: IMachineDefinition, program: PtProgram): List<Modification> { private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<String>>>): List<Modification> {
// Optimize same pointer indexing where for instance we load and store to the same ptr index in Y // 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: // if Y isn't modified in between we can omit the second LDY:
@ -366,7 +373,11 @@ private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<
return mods return mods
} }
private fun optimizeStoreLoadSame(linesByFour: List<List<IndexedValue<String>>>, machine: IMachineDefinition, program: PtProgram): List<Modification> { private fun optimizeStoreLoadSame(
linesByFour: List<List<IndexedValue<String>>>,
machine: IMachineDefinition,
symbolTable: SymbolTable
): List<Modification> {
// sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can OFTEN be eliminated // sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can OFTEN be eliminated
val mods = mutableListOf<Modification>() val mods = mutableListOf<Modification>()
for (lines in linesByFour) { for (lines in linesByFour) {
@ -394,7 +405,7 @@ private fun optimizeStoreLoadSame(linesByFour: List<List<IndexedValue<String>>>,
} }
else { else {
// no branch instruction follows, we can remove the load instruction // 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) address==null || !machine.isIOAddress(address)
} }
@ -436,7 +447,7 @@ private fun optimizeStoreLoadSame(linesByFour: List<List<IndexedValue<String>>>,
private val identifierRegex = Regex("""^([a-zA-Z_$][a-zA-Z\d_\.$]*)""") 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() val loadArg = line.trimStart().substring(3).trim()
return when { return when {
loadArg.startsWith('$') -> loadArg.substring(1).toUIntOrNull(16) loadArg.startsWith('$') -> loadArg.substring(1).toUIntOrNull(16)
@ -447,7 +458,12 @@ private fun getAddressArg(line: String, program: PtProgram): UInt? {
val identMatch = identifierRegex.find(loadArg) val identMatch = identifierRegex.find(loadArg)
if(identMatch!=null) { if(identMatch!=null) {
val identifier = identMatch.value 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 null
} }
else -> loadArg.substring(1).toUIntOrNull() else -> loadArg.substring(1).toUIntOrNull()

View File

@ -28,6 +28,15 @@ internal class SymbolTableMaker(private val program: Program, private val option
st.add(node) st.add(node)
} }
require(scopestack.isEmpty()) 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 return st
} }