mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
better asm code for repeat loops
This commit is contained in:
parent
cf6ea63fa6
commit
53e9ad5088
@ -671,10 +671,8 @@ internal class AsmGen(private val program: Program,
|
||||
}
|
||||
|
||||
private fun translate(stmt: RepeatLoop) {
|
||||
// TODO more optimized code possible now that continue is gone?
|
||||
val repeatLabel = makeLabel("repeat")
|
||||
val endLabel = makeLabel("repeatend")
|
||||
val counterLabel = makeLabel("repeatcounter")
|
||||
loopEndLabels.push(endLabel)
|
||||
|
||||
when (stmt.iterations) {
|
||||
@ -691,13 +689,13 @@ internal class AsmGen(private val program: Program,
|
||||
throw AssemblyError("invalid number of iterations")
|
||||
when {
|
||||
iterations == 0 -> {}
|
||||
iterations <= 255 -> {
|
||||
out(" lda #${iterations}")
|
||||
repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
iterations <= 256 -> {
|
||||
out(" lda #${iterations and 255}")
|
||||
repeatByteCountInA(iterations, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
else -> {
|
||||
out(" lda #<${iterations} | ldy #>${iterations}")
|
||||
repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
repeatWordCountInAY(iterations, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -707,11 +705,11 @@ internal class AsmGen(private val program: Program,
|
||||
when(vardecl.datatype) {
|
||||
DataType.UBYTE, DataType.BYTE -> {
|
||||
out(" lda $name")
|
||||
repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
DataType.UWORD, DataType.WORD -> {
|
||||
out(" lda $name | ldy $name+1")
|
||||
repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
else -> throw AssemblyError("invalid loop variable datatype $vardecl")
|
||||
}
|
||||
@ -722,11 +720,11 @@ internal class AsmGen(private val program: Program,
|
||||
when (dt) {
|
||||
in ByteDatatypes -> {
|
||||
out(" inx | lda ${ESTACK_LO_HEX},x")
|
||||
repeatByteCountInA(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
repeatByteCountInA(null, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
in WordDatatypes -> {
|
||||
out(" inx | lda ${ESTACK_LO_HEX},x | ldy ${ESTACK_HI_HEX},x")
|
||||
repeatWordCountInAY(counterLabel, repeatLabel, endLabel, stmt.body)
|
||||
repeatWordCountInAY(null, repeatLabel, endLabel, stmt.body)
|
||||
}
|
||||
else -> throw AssemblyError("invalid loop expression datatype $dt")
|
||||
}
|
||||
@ -736,9 +734,9 @@ internal class AsmGen(private val program: Program,
|
||||
loopEndLabels.pop()
|
||||
}
|
||||
|
||||
private fun repeatWordCountInAY(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
||||
private fun repeatWordCountInAY(constIterations: Int?, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
||||
// note: A/Y must have been loaded with the number of iterations already!
|
||||
// TODO allocate word counterVar on zeropage preferrably
|
||||
val counterVar = makeLabel("repeatcounter")
|
||||
out("""
|
||||
sta $counterVar
|
||||
sty $counterVar+1
|
||||
@ -752,29 +750,42 @@ $repeatLabel lda $counterVar
|
||||
+ dec $counterVar
|
||||
""")
|
||||
translate(body)
|
||||
out("""
|
||||
jmp $repeatLabel
|
||||
$counterVar .word 0
|
||||
$endLabel""")
|
||||
out(" jmp $repeatLabel")
|
||||
if(constIterations!=null && constIterations>=16 && zeropage.available() > 1) {
|
||||
// allocate count var on ZP
|
||||
val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, body.position, errors)
|
||||
out("""$counterVar = $zpAddr ; auto zp UWORD""")
|
||||
} else {
|
||||
out("""
|
||||
$counterVar .word 0""")
|
||||
}
|
||||
out(endLabel)
|
||||
|
||||
}
|
||||
|
||||
private fun repeatByteCountInA(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
||||
private fun repeatByteCountInA(constIterations: Int?, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
||||
// note: A must have been loaded with the number of iterations already!
|
||||
// TODO allocate word counterVar on zeropage preferrably
|
||||
val counterVar = makeLabel("repeatcounter")
|
||||
out("""
|
||||
sta $counterVar
|
||||
$repeatLabel lda $counterVar
|
||||
beq $endLabel
|
||||
dec $counterVar""")
|
||||
sta $counterVar
|
||||
$repeatLabel""")
|
||||
translate(body)
|
||||
out("""
|
||||
jmp $repeatLabel
|
||||
$counterVar .byte 0
|
||||
$endLabel""")
|
||||
dec $counterVar
|
||||
bne $repeatLabel
|
||||
beq $endLabel""")
|
||||
if(constIterations!=null && constIterations>=16 && zeropage.available() > 0) {
|
||||
// allocate count var on ZP
|
||||
val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, body.position, errors)
|
||||
out("""$counterVar = $zpAddr ; auto zp UBYTE""")
|
||||
} else {
|
||||
out("""
|
||||
$counterVar .byte 0""")
|
||||
}
|
||||
out(endLabel)
|
||||
}
|
||||
|
||||
private fun translate(stmt: WhileLoop) {
|
||||
// TODO more optimized code possible now that continue is gone?
|
||||
val whileLabel = makeLabel("while")
|
||||
val endLabel = makeLabel("whileend")
|
||||
loopEndLabels.push(endLabel)
|
||||
@ -801,7 +812,6 @@ $endLabel""")
|
||||
}
|
||||
|
||||
private fun translate(stmt: UntilLoop) {
|
||||
// TODO more optimized code possible now that continue is gone?
|
||||
val repeatLabel = makeLabel("repeat")
|
||||
val endLabel = makeLabel("repeatend")
|
||||
loopEndLabels.push(endLabel)
|
||||
|
@ -314,7 +314,7 @@ $loopLabel sty $indexVar
|
||||
beq $endLabel""")
|
||||
}
|
||||
if(length>=16 && asmgen.zeropage.available() > 0) {
|
||||
// allocate index var on ZP if possible
|
||||
// allocate index var on ZP
|
||||
val zpAddr = asmgen.zeropage.allocate(indexVar, DataType.UBYTE, stmt.position, asmgen.errors)
|
||||
asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""")
|
||||
} else {
|
||||
@ -353,7 +353,7 @@ $loopLabel sty $indexVar
|
||||
beq $endLabel""")
|
||||
}
|
||||
if(length>=16 && asmgen.zeropage.available() > 0) {
|
||||
// allocate index var on ZP if possible
|
||||
// allocate index var on ZP
|
||||
val zpAddr = asmgen.zeropage.allocate(indexVar, DataType.UBYTE, stmt.position, asmgen.errors)
|
||||
asmgen.out("""$indexVar = $zpAddr ; auto zp UBYTE""")
|
||||
} else {
|
||||
|
@ -293,8 +293,10 @@ internal class StatementOptimizer(private val program: Program,
|
||||
errors.warn("iterations is always 0, removed loop", iter.position)
|
||||
return listOf(IAstModification.Remove(repeatLoop, parent))
|
||||
}
|
||||
if (iterations == 1)
|
||||
if (iterations == 1) {
|
||||
errors.warn("iterations is always 1", iter.position)
|
||||
return listOf(IAstModification.ReplaceNode(repeatLoop, repeatLoop.body, parent))
|
||||
}
|
||||
}
|
||||
return noModifications
|
||||
}
|
||||
|
@ -6,50 +6,36 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
byte[] data = [11,22,33,44,55,66]
|
||||
ubyte[256] data256 = 1
|
||||
word[] dataw = [1111,2222,3333,4444,5555,6666]
|
||||
uword[128] dataw128 = 1
|
||||
uword count=0
|
||||
|
||||
ubyte u
|
||||
byte d
|
||||
word w
|
||||
uword uw
|
||||
|
||||
for u in "hello" {
|
||||
c64scr.print_ub(u)
|
||||
c64.CHROUT(',')
|
||||
count=0
|
||||
repeat 10 {
|
||||
count++
|
||||
}
|
||||
c64scr.print_uw(count)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for d in data {
|
||||
c64scr.print_b(d)
|
||||
c64.CHROUT(',')
|
||||
count=0
|
||||
repeat 255 {
|
||||
count++
|
||||
}
|
||||
c64scr.print_uw(count)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
data256[0]=0
|
||||
data256[254]=254
|
||||
data256[255]=255
|
||||
for u in data256 {
|
||||
c64scr.print_ub(u)
|
||||
c64.CHROUT(',')
|
||||
count=0
|
||||
repeat 256 {
|
||||
count++
|
||||
}
|
||||
c64scr.print_uw(count)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
for w in dataw {
|
||||
c64scr.print_w(w)
|
||||
c64.CHROUT(',')
|
||||
count=0
|
||||
repeat 40000 {
|
||||
count++
|
||||
}
|
||||
c64scr.print_uw(count)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
dataw128[0] = 0
|
||||
dataw128[126] =126
|
||||
dataw128[127] =127
|
||||
for uw in dataw128 {
|
||||
c64scr.print_uw(uw)
|
||||
c64.CHROUT(',')
|
||||
}
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user