for loops...

This commit is contained in:
Irmen de Jong 2023-05-02 22:25:55 +02:00
parent 87d3109ffb
commit d81fdf6d6b
4 changed files with 121 additions and 11 deletions

View File

@ -51,7 +51,22 @@ internal class ForLoopsAsmGen(private val program: PtProgram,
// loop over byte range via loopvar
val varname = asmgen.asmVariableName(stmt.variable)
asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt))
asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayToElementTypes.getValue(iterableDt))
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
// pre-check for end already reached
if(iterableDt==DataType.ARRAY_B) {
if(stepsize<0) {
println("signed byte check to<=from") // TODO
} else {
println("signed byte check from<=to") // TODO
}
} else {
if(stepsize<0) {
println("unsigned byte check to<=from") // TODO
} else {
println("unsigned byte check from<=to") // TODO
}
}
asmgen.out(" sta $modifiedLabel+1")
asmgen.out(loopLabel)
asmgen.translate(stmt.statements)
asmgen.out("""
@ -70,6 +85,20 @@ $modifiedLabel cmp #0 ; modified
val varname = asmgen.asmVariableName(stmt.variable)
asmgen.assignExpressionToVariable(range.from, varname, ArrayToElementTypes.getValue(iterableDt))
asmgen.assignExpressionToVariable(range.to, "$modifiedLabel+1", ArrayToElementTypes.getValue(iterableDt))
// pre-check for end already reached
if(iterableDt==DataType.ARRAY_B) {
if(stepsize<0) {
println("signed byte check to<=from") // TODO
} else {
println("signed byte check from<=to") // TODO
}
} else {
if(stepsize<0) {
println("unsigned byte check to<=from") // TODO
} else {
println("unsigned byte check from<=to") // TODO
}
}
asmgen.out(loopLabel)
asmgen.translate(stmt.statements)
if(stepsize>0) {
@ -102,6 +131,20 @@ $modifiedLabel cmp #0 ; modified
val varname = asmgen.asmVariableName(stmt.variable)
assignLoopvar(stmt, range)
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
// pre-check for end already reached
if(iterableDt==DataType.ARRAY_W) {
if(stepsize<0) {
println("signed word check to<=from") // TODO
} else {
println("signed word check from<=to") // TODO
}
} else {
if(stepsize<0) {
println("unsigned word check to<=from") // TODO
} else {
println("unsigned word check from<=to") // TODO
}
}
asmgen.out("""
sty $modifiedLabel+1
sta $modifiedLabel2+1
@ -136,6 +179,12 @@ $modifiedLabel2 cmp #0 ; modified
val varname = asmgen.asmVariableName(stmt.variable)
assignLoopvar(stmt, range)
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
// pre-check for end already reached
if(iterableDt==DataType.ARRAY_W) {
println("signed word check from<=to") // TODO
} else {
println("unsigned word check from<=to") // TODO
}
asmgen.out("""
sty $modifiedLabel+1
sta $modifiedLabel2+1
@ -184,6 +233,12 @@ $endLabel""")
val varname = asmgen.asmVariableName(stmt.variable)
assignLoopvar(stmt, range)
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
// pre-check for end already reached
if(iterableDt==DataType.ARRAY_W) {
println("signed word check to<=from") // TODO
} else {
println("unsigned word check to<=from") // TODO
}
asmgen.out("""
sty $modifiedLabel+1
sta $modifiedLabel2+1

View File

@ -488,8 +488,8 @@ the given number of times. It's meant to "unroll loops" - trade memory for speed
Only simple statements are allowed to be inside an unroll loop (assignments, function calls etc.).
.. attention::
The value of the loop variable after executing the loop *is undefined*. Don't use it immediately
after the loop without first assigning a new value to it!
The value of the loop variable after executing the loop *is undefined* - you cannot rely
on it to be the last value in the range for instance! The value of the variable should only be used inside the for loop body.
(this is an optimization issue to avoid having to deal with mostly useless post-loop logic to adjust the loop variable's value)
.. warning::

View File

@ -11,10 +11,11 @@ For 9.0 major changes
- DONE: cx16diskio module merged into diskio (which got specialized for commander x16 target). load() and load_raw() with extra ram bank parameter are gone.
- DONE: drivenumber parameter removed from all routines in diskio module. The drive to work on is now simply stored as a diskio.drivenumber variable, which defaults to 8.
- VM codegen: fix for loop pre-check for negative stepsizes.
- 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition.
It is documented behavior to now loop 'around' $00 but it's too easy to forget about!
Lot of work because of so many special cases in ForLoopsAsmgen.....
(vm codegen already behaves like this!)
Lot of work because of many special cases in ForLoopsAsmgen.translateForOverNonconstRange()
(vm codegen already behaves like this partly! Except for negative step sizes right now)
- once 9.0 is stable, upgrade other programs (assem, shell, etc) to it. + add migration guide to the manual.
- [much work:] add special (u)word array type (or modifier such as @fast? ) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256 and faster indexing
this is an enormous amout of work, if this type is to be treated equally as existing (u)word , because all expression / lookup / assignment routines need to know about the distinction....

View File

@ -6,12 +6,66 @@
main {
sub start() {
ubyte bb = 199
txt.print_ub(sqrt(bb))
txt.nl()
float fl = 199.99
floats.print_f(floats.sqrtf(fl))
txt.nl()
ubyte target = 10
ubyte from = 250
ubyte xx
for xx in from to target {
txt.print_ub(xx)
txt.spc()
}
txt.print("done\n")
for xx in target downto from {
txt.print_ub(xx)
txt.spc()
}
txt.print("done\n")
byte starget = -120
byte sfrom = 120
byte sxx
for sxx in sfrom to starget {
txt.print_b(sxx)
txt.spc()
}
txt.print("done\n")
for sxx in starget downto sfrom {
txt.print_b(sxx)
txt.spc()
}
txt.print("done\n")
uword wtarget = 10
uword wfrom = 65530
uword ww
for ww in wfrom to wtarget {
txt.print_uw(ww)
txt.spc()
}
txt.print("done\n")
for ww in wtarget downto wfrom {
txt.print_uw(ww)
txt.spc()
}
txt.print("done\n")
word swtarget = -32760
word swfrom = 32760
word sww
for sww in swfrom to swtarget {
txt.print_w(sww)
txt.spc()
}
txt.print("done\n")
for sww in swtarget downto swfrom {
txt.print_w(sww)
txt.spc()
}
txt.print("done\n")
; TODO all of the above with stepsize 2 / -2
}
}