mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
slightly optimized repeat loop asmgen
This commit is contained in:
parent
c03f6604af
commit
e61a2d7083
@ -880,7 +880,16 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
out("; variables")
|
out("; variables")
|
||||||
out("; register saves")
|
for((name, addr) in sub.asmGenInfo.extraVarsZP) {
|
||||||
|
out("$name = $addr")
|
||||||
|
}
|
||||||
|
for((dt, name) in sub.asmGenInfo.extraVars) {
|
||||||
|
when(dt) {
|
||||||
|
DataType.UBYTE -> out("$name .byte 0")
|
||||||
|
DataType.UWORD -> out("$name .word 0")
|
||||||
|
else -> throw AssemblyError("weird dt")
|
||||||
|
}
|
||||||
|
}
|
||||||
if(sub.asmGenInfo.usedRegsaveA)
|
if(sub.asmGenInfo.usedRegsaveA)
|
||||||
out("_prog8_regsaveA .byte 0")
|
out("_prog8_regsaveA .byte 0")
|
||||||
if(sub.asmGenInfo.usedRegsaveX)
|
if(sub.asmGenInfo.usedRegsaveX)
|
||||||
@ -1025,7 +1034,7 @@ internal class AsmGen(private val program: Program,
|
|||||||
return
|
return
|
||||||
// no need to explicitly test for 0 iterations as this is done in the count down logic below
|
// no need to explicitly test for 0 iterations as this is done in the count down logic below
|
||||||
|
|
||||||
val (counterVar: String, declareCounterVarLocally: Boolean) = createRepeatCounterVar(DataType.UWORD, constIterations, stmt)
|
val counterVar: String = createRepeatCounterVar(DataType.UWORD, constIterations, stmt)
|
||||||
out("""
|
out("""
|
||||||
sta $counterVar
|
sta $counterVar
|
||||||
sty $counterVar+1
|
sty $counterVar+1
|
||||||
@ -1040,9 +1049,6 @@ $repeatLabel lda $counterVar
|
|||||||
""")
|
""")
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
jmp(repeatLabel)
|
jmp(repeatLabel)
|
||||||
if(declareCounterVarLocally)
|
|
||||||
out("$counterVar .word 0")
|
|
||||||
|
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,49 +1059,48 @@ $repeatLabel lda $counterVar
|
|||||||
|
|
||||||
if(constIterations==null)
|
if(constIterations==null)
|
||||||
out(" beq $endLabel ; skip loop if zero iters")
|
out(" beq $endLabel ; skip loop if zero iters")
|
||||||
val (counterVar: String, declareCounterVarLocally: Boolean) = createRepeatCounterVar(DataType.UBYTE, constIterations, stmt)
|
val counterVar = createRepeatCounterVar(DataType.UBYTE, constIterations, stmt)
|
||||||
out(" sta $counterVar")
|
out(" sta $counterVar")
|
||||||
out(repeatLabel)
|
out(repeatLabel)
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
out("""
|
out(" dec $counterVar | bne $repeatLabel")
|
||||||
dec $counterVar
|
if(constIterations==null)
|
||||||
bne $repeatLabel
|
|
||||||
beq $endLabel""")
|
|
||||||
if(declareCounterVarLocally)
|
|
||||||
out("$counterVar .byte 0")
|
|
||||||
|
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createRepeatCounterVar(dt: DataType, constIterations: Int?, stmt: RepeatLoop): Pair<String, Boolean> {
|
private fun createRepeatCounterVar(dt: DataType, constIterations: Int?, stmt: RepeatLoop): String {
|
||||||
// TODO share counter variables between subroutines or even between repeat loops as long as they're not nested
|
// TODO share counter variables between subroutines or even between repeat loops as long as they're not nested
|
||||||
|
// var parent = stmt.parent
|
||||||
|
// while(parent !is ParentSentinel) {
|
||||||
|
// if(parent is RepeatLoop)
|
||||||
|
// break
|
||||||
|
// parent = parent.parent
|
||||||
|
// }
|
||||||
|
// val isNested = parent is RepeatLoop
|
||||||
val counterVar = makeLabel("repeatcounter")
|
val counterVar = makeLabel("repeatcounter")
|
||||||
|
val asmInfo = stmt.definingSubroutine()!!.asmGenInfo
|
||||||
// println("REPEATCOUNTERVAR $counterVar SIZE $dt CTX ${stmt.definingSubroutine()}")
|
|
||||||
|
|
||||||
when(dt) {
|
when(dt) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
return if(constIterations!=null && constIterations>=16 && zeropage.hasByteAvailable()) {
|
if(constIterations!=null && constIterations>=16 && zeropage.hasByteAvailable()) {
|
||||||
// allocate count var on ZP
|
// allocate count var on ZP
|
||||||
val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, stmt.position, errors)
|
val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, stmt.position, errors)
|
||||||
out("$counterVar = $zpAddr ; auto zp byte")
|
asmInfo.extraVarsZP.add(Pair(counterVar, zpAddr))
|
||||||
Pair(counterVar, false)
|
|
||||||
} else {
|
} else {
|
||||||
Pair(counterVar, true)
|
asmInfo.extraVars.add(Pair(DataType.UBYTE, counterVar))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD -> {
|
DataType.UWORD -> {
|
||||||
return if(constIterations!=null && constIterations>=16 && zeropage.hasWordAvailable()) {
|
if(constIterations!=null && constIterations>=16 && zeropage.hasWordAvailable()) {
|
||||||
// allocate count var on ZP
|
// allocate count var on ZP
|
||||||
val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, stmt.position, errors)
|
val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, stmt.position, errors)
|
||||||
out("$counterVar = $zpAddr ; auto zp word")
|
asmInfo.extraVarsZP.add(Pair(counterVar, zpAddr))
|
||||||
Pair(counterVar, false)
|
|
||||||
} else {
|
} else {
|
||||||
Pair(counterVar, true)
|
asmInfo.extraVars.add(Pair(DataType.UWORD, counterVar))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("invalidt dt")
|
else -> throw AssemblyError("invalidt dt")
|
||||||
}
|
}
|
||||||
|
return counterVar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: WhileLoop) {
|
private fun translate(stmt: WhileLoop) {
|
||||||
|
@ -588,6 +588,9 @@ class AsmGenInfo {
|
|||||||
var usedRegsaveY = false
|
var usedRegsaveY = false
|
||||||
var usedFloatEvalResultVar1 = false
|
var usedFloatEvalResultVar1 = false
|
||||||
var usedFloatEvalResultVar2 = false
|
var usedFloatEvalResultVar2 = false
|
||||||
|
|
||||||
|
val extraVars = mutableListOf<Pair<DataType, String>>()
|
||||||
|
val extraVarsZP = mutableListOf<Pair<String, Int>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
// the subroutine class covers both the normal user-defined subroutines,
|
// the subroutine class covers both the normal user-defined subroutines,
|
||||||
|
@ -5,6 +5,7 @@ main {
|
|||||||
|
|
||||||
; test program for the optimization of repeat var allocation (asmgen.createRepeatCounterVar)
|
; test program for the optimization of repeat var allocation (asmgen.createRepeatCounterVar)
|
||||||
; output must be: 60 6164 6224 12328
|
; output must be: 60 6164 6224 12328
|
||||||
|
; original program size: $046b
|
||||||
|
|
||||||
uword xx
|
uword xx
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user