mirror of
https://github.com/irmen/prog8.git
synced 2024-09-10 09:54:32 +00:00
fix missing symboltable entries for asmgen
This commit is contained in:
parent
94c9b0d23b
commit
e67464325f
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user