refactor repeat loop counter var creation into single routine

This commit is contained in:
Irmen de Jong 2021-05-22 13:01:51 +02:00
parent d7f83f8df2
commit 31ae9e1243
2 changed files with 30 additions and 27 deletions

View File

@ -975,11 +975,11 @@ internal class AsmGen(private val program: Program,
iterations == 0 -> {}
iterations <= 256 -> {
out(" lda #${iterations and 255}")
repeatByteCountInA(iterations, repeatLabel, endLabel, stmt.body)
repeatByteCountInA(iterations, repeatLabel, endLabel, stmt)
}
else -> {
out(" lda #<${iterations} | ldy #>${iterations}")
repeatWordCountInAY(iterations, repeatLabel, endLabel, stmt.body)
repeatWordCountInAY(iterations, repeatLabel, endLabel, stmt)
}
}
}
@ -989,11 +989,11 @@ internal class AsmGen(private val program: Program,
when(vardecl.datatype) {
DataType.UBYTE, DataType.BYTE -> {
assignVariableToRegister(name, RegisterOrPair.A)
repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)
repeatByteCountInA(null, repeatLabel, endLabel, stmt)
}
DataType.UWORD, DataType.WORD -> {
assignVariableToRegister(name, RegisterOrPair.AY)
repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body)
repeatWordCountInAY(null, repeatLabel, endLabel, stmt)
}
else -> throw AssemblyError("invalid loop variable datatype $vardecl")
}
@ -1005,11 +1005,11 @@ internal class AsmGen(private val program: Program,
when (dt.typeOrElse(DataType.UNDEFINED)) {
in ByteDatatypes -> {
assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.A)
repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)
repeatByteCountInA(null, repeatLabel, endLabel, stmt)
}
in WordDatatypes -> {
assignExpressionToRegister(stmt.iterations!!, RegisterOrPair.AY)
repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body)
repeatWordCountInAY(null, repeatLabel, endLabel, stmt)
}
else -> throw AssemblyError("invalid loop expression datatype $dt")
}
@ -1019,13 +1019,13 @@ internal class AsmGen(private val program: Program,
loopEndLabels.pop()
}
private fun repeatWordCountInAY(constIterations: Int?, repeatLabel: String, endLabel: String, body: AnonymousScope) {
private fun repeatWordCountInAY(constIterations: Int?, repeatLabel: String, endLabel: String, stmt: RepeatLoop) {
// note: A/Y must have been loaded with the number of iterations!
if(constIterations==0)
return
// no need to explicitly test for 0 iterations as this is done in the count down logic below
val counterVar = makeLabel("repeatcounter")
val (counterVar: String, declareCounterVarLocally: Boolean) = createRepeatCounterVar(DataType.UWORD, constIterations, stmt)
out("""
sta $counterVar
sty $counterVar+1
@ -1038,46 +1038,49 @@ $repeatLabel lda $counterVar
dec $counterVar+1
+ dec $counterVar
""")
translate(body)
translate(stmt.body)
jmp(repeatLabel)
if(constIterations!=null && constIterations>=16 && zeropage.available() > 1) {
// allocate count var on ZP TODO can be shared with countervars from other subroutines
val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, body.position, errors)
out("$counterVar = $zpAddr ; auto zp UWORD")
} else {
if(declareCounterVarLocally)
out("$counterVar .word 0")
}
out(endLabel)
}
private fun repeatByteCountInA(constIterations: Int?, repeatLabel: String, endLabel: String, body: AnonymousScope) {
private fun repeatByteCountInA(constIterations: Int?, repeatLabel: String, endLabel: String, stmt: RepeatLoop) {
// note: A must have been loaded with the number of iterations!
if(constIterations==0)
return
if(constIterations==null)
out(" beq $endLabel ; skip loop if zero iters")
val counterVar = makeLabel("repeatcounter")
val (counterVar: String, declareCounterVarLocally: Boolean) = createRepeatCounterVar(DataType.UBYTE, constIterations, stmt)
out(" sta $counterVar")
out(repeatLabel)
translate(body)
translate(stmt.body)
out("""
dec $counterVar
bne $repeatLabel
beq $endLabel""")
if(constIterations!=null && constIterations>=16 && zeropage.available() > 0) {
// allocate count var on ZP TODO can be shared with countervars from other subroutines
val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, body.position, errors)
out("$counterVar = $zpAddr ; auto zp UBYTE")
} else {
if(declareCounterVarLocally)
out("$counterVar .byte 0")
}
out(endLabel)
}
private fun createRepeatCounterVar(dt: DataType, constIterations: Int?, stmt: RepeatLoop): Pair<String, Boolean> {
// TODO share counter variables between subroutines or even between repeat loops as long as they're not nested
val counterVar = makeLabel("repeatcounter")
val zpAvail = if(dt==DataType.UWORD) 2 else 1
return if(constIterations!=null && constIterations>=16 && zeropage.available() >= zpAvail) {
// allocate count var on ZP
val zpAddr = zeropage.allocate(counterVar, dt, stmt.position, errors)
out("$counterVar = $zpAddr ; auto zp $dt")
Pair(counterVar, false)
} else {
Pair(counterVar, true)
}
}
private fun translate(stmt: WhileLoop) {
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
val booleanCondition = stmt.condition as BinaryExpression

View File

@ -5,7 +5,7 @@ TODO
- test all examples (including imgviewer, assembler and petaxian) before release of the new version
- simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203
- improve counter vars creation in repeatWordCountInAY() and repeatByteCountInA() (asmgen.kt)
- improve repeat counter vars allocation in asmgen.createRepeatCounterVar()
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- get rid of all other TODO's in the code ;-)