1
0
mirror of https://github.com/irmen/prog8.git synced 2025-04-27 12:59:42 +00:00

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
codeGenCpu6502/src/prog8/codegen/cpu6502
examples

@ -1741,12 +1741,13 @@ $repeatLabel""")
return null
}
fun romableWarning(problem: String, pos: Position, assemblerShouldFail: Boolean = true) {
fun romableError(problem: String, pos: Position, assemblerShouldFail: Boolean = true) {
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...
errors.warn("problem for ROMable code: $problem", pos)
if(assemblerShouldFail)
out(" .error \"ROMable code selected but incompatible code was generated: $problem\"")
if(assemblerShouldFail) {
out(" .error \"ROMable code selected but incompatible code was generated: $problem $pos\"")
}
}
}
}

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

@ -652,7 +652,7 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second,
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 {
outputStringvar(
@ -661,22 +661,22 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.second,
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 {
staticVariable2asm(it)
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
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 {
staticVariable2asm(it)
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
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
}
}
}

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