refactor for loop over byte ranges

This commit is contained in:
Irmen de Jong 2025-03-22 15:57:53 +01:00
parent 25ab57580c
commit 573a1d9b7b
4 changed files with 121 additions and 118 deletions

View File

@ -1741,12 +1741,13 @@ $repeatLabel""")
return null return null
} }
fun romableWarning(problem: String, pos: Position, assemblerShouldFail: Boolean = true) { fun romableError(problem: String, pos: Position, assemblerShouldFail: Boolean = true) {
if(options.romable) { if(options.romable) {
// until the code generation can provide an alternative, we have to report about code generated that is incompatible with ROMable code mode... // until the code generation can provide an alternative, we have to report about code generated that is incompatible with ROMable code mode...
errors.warn("problem for ROMable code: $problem", pos) errors.warn("problem for ROMable code: $problem", pos)
if(assemblerShouldFail) if(assemblerShouldFail) {
out(" .error \"ROMable code selected but incompatible code was generated: $problem\"") out(" .error \"ROMable code selected but incompatible code was generated: $problem $pos\"")
}
} }
} }
} }

View File

@ -52,9 +52,9 @@ internal class ForLoopsAsmGen(
val stepsize = range.step.asConstInteger()!! val stepsize = range.step.asConstInteger()!!
val loopLabel = asmgen.makeLabel("for_loop") val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end") val endLabel = asmgen.makeLabel("for_end")
val modifiedLabel = asmgen.makeLabel("for_modified")
asmgen.loopEndLabels.add(endLabel) asmgen.loopEndLabels.add(endLabel)
val varname = asmgen.asmVariableName(stmt.variable) val varname = asmgen.asmVariableName(stmt.variable)
asmgen.assignExpressionToVariable(range.from, varname, iterableDt.elementType()) asmgen.assignExpressionToVariable(range.from, varname, iterableDt.elementType())
if (stepsize==-1 && range.to.asConstInteger()==0) { if (stepsize==-1 && range.to.asConstInteger()==0) {
// simple loop downto 0 step -1 // simple loop downto 0 step -1
@ -74,113 +74,122 @@ internal class ForLoopsAsmGen(
dec $varname dec $varname
bne $loopLabel""") bne $loopLabel""")
} }
else if (stepsize==1 || stepsize==-1) { else if (stepsize==1 || stepsize==-1)
// bytes array, step 1 or -1 forOverBytesStepOne(range, varname, iterableDt, loopLabel, endLabel, stmt)
else
forOverBytesStepGreaterOne(range, varname, iterableDt, loopLabel, endLabel, stmt)
}
val incdec = if(stepsize==1) "inc" else "dec" private fun forOverBytesStepOne(range: PtRange, varname: String, iterableDt: DataType, loopLabel: String, endLabel: String, forloop: PtForLoop) {
// loop over byte range via loopvar // bytes array, step 1 or -1
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
// pre-check for end already reached val stepsize = range.step.asConstInteger()!!
if(iterableDt.isSignedByteArray) { val incdec = if(stepsize==1) "inc" else "dec"
asmgen.out(" sta $modifiedLabel+1")
if(stepsize<0) { val modifiedLabel = asmgen.makeLabel("for_modified")
asmgen.out(""" asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
clc // pre-check for end already reached
sbc $varname if(iterableDt.isSignedByteArray) {
bvc + asmgen.out(" sta $modifiedLabel+1")
eor #${'$'}80 if(stepsize<0) {
+ bpl $endLabel""") asmgen.out("""
} clc
else sbc $varname
asmgen.out(""" bvc +
sec eor #$80
sbc $varname + bpl $endLabel""")
bvc +
eor #${'$'}80
+ bmi $endLabel""")
} else {
if(stepsize<0) {
asmgen.out("""
cmp $varname
beq +
bcs $endLabel
+""")
}
else {
asmgen.out(" cmp $varname | bcc $endLabel")
}
asmgen.out(" sta $modifiedLabel+1")
} }
asmgen.out(loopLabel) else
asmgen.translate(stmt.statements) asmgen.out("""
asmgen.out(""" sec
sbc $varname
bvc +
eor #$80
+ bmi $endLabel""")
} else {
if(stepsize<0) {
asmgen.out("""
cmp $varname
beq +
bcs $endLabel
+""")
}
else {
asmgen.out(" cmp $varname | bcc $endLabel")
}
asmgen.out(" sta $modifiedLabel+1")
}
asmgen.out(loopLabel)
asmgen.translate(forloop.statements)
asmgen.out("""
lda $varname lda $varname
$modifiedLabel cmp #0 ; modified $modifiedLabel cmp #0 ; modified
beq $endLabel beq $endLabel
$incdec $varname""") $incdec $varname""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO asmgen.romableError("self-modifying code (forloop over range)", forloop.position) // TODO
asmgen.jmp(loopLabel) asmgen.jmp(loopLabel)
asmgen.out(endLabel) asmgen.out(endLabel)
}
} else { private fun forOverBytesStepGreaterOne(range: PtRange, varname: String, iterableDt: DataType, loopLabel: String, endLabel: String, forloop: PtForLoop) {
// bytes, step >= 2 or <= -2
// bytes, step >= 2 or <= -2 val stepsize = range.step.asConstInteger()!!
// loop over byte range via loopvar val modifiedLabel = asmgen.makeLabel("for_modified")
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false) asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
// pre-check for end already reached // pre-check for end already reached
if(iterableDt.isSignedByteArray) { if(iterableDt.isSignedByteArray) {
asmgen.out(" sta $modifiedLabel+1") asmgen.out(" sta $modifiedLabel+1")
if(stepsize<0) if(stepsize<0)
asmgen.out("""
clc
sbc $varname
bvc +
eor #${'$'}80
+ bpl $endLabel""")
else
asmgen.out("""
sec
sbc $varname
bvc +
eor #${'$'}80
+ bmi $endLabel""")
} else {
if(stepsize<0)
asmgen.out("""
cmp $varname
beq +
bcs $endLabel
+""")
else {
asmgen.out(" cmp $varname | bcc $endLabel")
}
asmgen.out(" sta $modifiedLabel+1")
}
asmgen.out(loopLabel)
asmgen.translate(stmt.statements)
if(stepsize>0) {
asmgen.out(""" asmgen.out("""
lda $varname
clc clc
adc #$stepsize sbc $varname
sta $varname bvc +
$modifiedLabel cmp #0 ; modified eor #$80
bmi $loopLabel + bpl $endLabel""")
beq $loopLabel""") else
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO
} else {
asmgen.out(""" asmgen.out("""
lda $varname
sec sec
sbc #${stepsize.absoluteValue} sbc $varname
sta $varname bvc +
$modifiedLabel cmp #0 ; modified eor #$80
bpl $loopLabel""") + bmi $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO } else {
if(stepsize<0)
asmgen.out("""
cmp $varname
beq +
bcs $endLabel
+""")
else {
asmgen.out(" cmp $varname | bcc $endLabel")
} }
asmgen.out(endLabel) asmgen.out(" sta $modifiedLabel+1")
} }
asmgen.out(loopLabel)
asmgen.translate(forloop.statements)
if(stepsize>0) {
asmgen.out("""
lda $varname
clc
adc #$stepsize
sta $varname
$modifiedLabel cmp #0 ; modified
bmi $loopLabel
beq $loopLabel""")
asmgen.romableError("self-modifying code (forloop over range)", forloop.position) // TODO
} else {
asmgen.out("""
lda $varname
sec
sbc #${stepsize.absoluteValue}
sta $varname
$modifiedLabel cmp #0 ; modified
bpl $loopLabel""")
asmgen.romableError("self-modifying code (forloop over range)", forloop.position) // TODO
}
asmgen.out(endLabel)
} }
private fun forOverNonconstWordRange(stmt: PtForLoop, iterableDt: DataType, range: PtRange) { private fun forOverNonconstWordRange(stmt: PtForLoop, iterableDt: DataType, range: PtRange) {
@ -241,7 +250,7 @@ $modifiedLabel cmp #0 ; modified
lda $varname lda $varname
$modifiedLabel2 cmp #0 ; modified $modifiedLabel2 cmp #0 ; modified
beq $endLabel""") beq $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO asmgen.romableError("self-modifying code (forloop over range)", stmt.position) // TODO
if(stepsize==1) { if(stepsize==1) {
asmgen.out(""" asmgen.out("""
+ inc $varname + inc $varname
@ -285,7 +294,7 @@ $modifiedLabel2 lda #0 ; modified
bcc $endLabel bcc $endLabel
bcs $loopLabel bcs $loopLabel
$endLabel""") $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO asmgen.romableError("self-modifying code (forloop over range)", stmt.position) // TODO
} else { } else {
asmgen.out(""" asmgen.out("""
lda $varname lda $varname
@ -303,7 +312,7 @@ $modifiedLabel lda #0 ; modified
eor #$80 eor #$80
+ bpl $loopLabel + bpl $loopLabel
$endLabel""") $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO asmgen.romableError("self-modifying code (forloop over range)", stmt.position) // TODO
} }
} }
else { else {
@ -334,7 +343,7 @@ $modifiedLabel sbc #0 ; modified
eor #$80 eor #$80
+ bpl $loopLabel + bpl $loopLabel
$endLabel""") $endLabel""")
asmgen.romableWarning("self-modifying code (forloop over range)", stmt.position) // TODO asmgen.romableError("self-modifying code (forloop over range)", stmt.position) // TODO
} }
} }

View File

@ -652,7 +652,7 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second, it.initializationStringValue!!.second,
it.initializationStringValue!!.first it.initializationStringValue!!.first
) )
asmgen.romableWarning("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
} }
alignedStrings.sortedBy { it.align }.forEach { alignedStrings.sortedBy { it.align }.forEach {
outputStringvar( outputStringvar(
@ -661,22 +661,22 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second, it.initializationStringValue!!.second,
it.initializationStringValue!!.first it.initializationStringValue!!.first
) )
asmgen.romableWarning("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var asmgen.romableError("string (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
} }
notAlignedOther.sortedBy { it.type }.forEach { notAlignedOther.sortedBy { it.type }.forEach {
staticVariable2asm(it) staticVariable2asm(it)
if(it.dt.isArray) if(it.dt.isArray)
asmgen.romableWarning("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
else else
asmgen.romableWarning("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var asmgen.romableError("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var
} }
alignedOther.sortedBy { it.align }.sortedBy { it.type }.forEach { alignedOther.sortedBy { it.align }.sortedBy { it.type }.forEach {
staticVariable2asm(it) staticVariable2asm(it)
if(it.dt.isArray) if(it.dt.isArray)
asmgen.romableWarning("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var asmgen.romableError("array (${it.dt} ${it.name}) can only be used as read-only in ROMable code", Position.DUMMY, false) // TODO print warning with position of the var
else else
asmgen.romableWarning("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var asmgen.romableError("inlined variable (${it.dt} ${it.name})", Position.DUMMY) // TODO print warning with position of the var
} }
} }
} }

View File

@ -6,21 +6,14 @@
main { main {
sub start() { sub start() {
&ubyte[100] @shared array = $a000 cx16.r8L = 3
str name = "irmen1234567890" * 16 + "abcdefghijklmno" cx16.r9L = 20
txt.print_ub(len(name)) for cx16.r2L in cx16.r8L to cx16.r9L step 1 {
txt.nl() txt.print_ub(cx16.r2L)
txt.spc()
test_stack.test()
for cx16.r0L in name {
txt.chrout(cx16.r0L)
} }
test_stack.test()
cx16.r0++
; cx16.r0L = @(ptr) ; cx16.r0L = @(ptr)
; ;
; @(ptr)++ ; @(ptr)++