mirror of
https://github.com/irmen/prog8.git
synced 2025-04-12 03:37:11 +00:00
no more self modifying code for loops over non-const word range
This commit is contained in:
parent
344d79684a
commit
e16452037c
@ -92,18 +92,18 @@ internal class ForLoopsAsmGen(
|
||||
if(asmgen.options.romable) {
|
||||
// cannot use self-modifying code, cannot use cpu stack (because loop can be interrupted halfway)
|
||||
// so we need to store the loop end value in a newly allocated temporary variable
|
||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
||||
// allocate index var on ZP if possible
|
||||
// TODO allocate var in ZP if possible, but maybe we should always allocate it in system memory for this (ZP is precious)?
|
||||
val toValueVar = asmgen.makeLabel("for_tovalue")
|
||||
val result = zeropage.allocate(toValueVar, DataType.UBYTE, null, forloop.position, asmgen.errors)
|
||||
val result = zeropage.allocate(toValueVar, iterableDt.elementType(), null, forloop.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = {
|
||||
(address, _, _)-> asmgen.out("""$toValueVar = $address ; auto zp UBYTE""")
|
||||
},
|
||||
failure = {
|
||||
TODO("no space left in zp for temp loop variable ${forloop.position}, where to put it instead") // maybe we should allocate a non-zeropage variable in system memory?
|
||||
TODO("no space left in zp for temp loop variable ${forloop.position}, where to put it instead?")
|
||||
}
|
||||
)
|
||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.A, false)
|
||||
asmgen.out(" sta $toValueVar")
|
||||
// pre-check for end already reached
|
||||
if(iterableDt.isSignedByteArray) {
|
||||
@ -302,41 +302,87 @@ $modifiedLabel cmp #0 ; modified
|
||||
forOverWordsStepGreaterOneDescending(range, varname, iterableDt, loopLabel, endLabel, stmt)
|
||||
}
|
||||
|
||||
private fun forOverWordsStepOne(range: PtRange, varname: String, iterableDt: DataType, loopLabel: String, endLabel: String, stmt: PtForLoop) {
|
||||
private fun forOverWordsStepOne(range: PtRange, varname: String, iterableDt: DataType, loopLabel: String, endLabel: String, forloop: PtForLoop) {
|
||||
// words, step 1 or -1
|
||||
val stepsize = range.step.asConstInteger()!!
|
||||
val modifiedLabel = asmgen.makeLabel("for_modified")
|
||||
val modifiedLabel2 = asmgen.makeLabel("for_modifiedb")
|
||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||
asmgen.out("""
|
||||
|
||||
if(asmgen.options.romable) {
|
||||
// cannot use self-modifying code, cannot use cpu stack (because loop can be interrupted halfway)
|
||||
// so we need to store the loop end value in a newly allocated temporary variable
|
||||
// TODO allocate var in ZP if possible, but maybe we should always allocate it in system memory for this (ZP is precious)?
|
||||
val toValueVar = asmgen.makeLabel("for_tovalue")
|
||||
val result = zeropage.allocate(toValueVar, iterableDt.elementType(), null, forloop.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = {
|
||||
(address, _, _)-> asmgen.out("""$toValueVar = $address ; auto zp UWORD""")
|
||||
},
|
||||
failure = {
|
||||
TODO("no space left in zp for temp loop variable ${forloop.position}, where to put it instead?")
|
||||
}
|
||||
)
|
||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||
asmgen.out(" sta $toValueVar")
|
||||
asmgen.out(" sty $toValueVar+1")
|
||||
asmgen.out(loopLabel)
|
||||
asmgen.translate(forloop.statements)
|
||||
asmgen.out("""
|
||||
lda $varname+1
|
||||
cmp $toValueVar+1
|
||||
bne +
|
||||
lda $varname
|
||||
cmp $toValueVar
|
||||
beq $endLabel""")
|
||||
if(stepsize==1) {
|
||||
asmgen.out("""
|
||||
+ inc $varname
|
||||
bne $loopLabel
|
||||
inc $varname+1""")
|
||||
asmgen.jmp(loopLabel)
|
||||
} else {
|
||||
asmgen.out("""
|
||||
+ lda $varname
|
||||
bne +
|
||||
dec $varname+1
|
||||
+ dec $varname""")
|
||||
asmgen.jmp(loopLabel)
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
|
||||
} else {
|
||||
|
||||
val modifiedLabel = asmgen.makeLabel("for_modified")
|
||||
val modifiedLabel2 = asmgen.makeLabel("for_modifiedb")
|
||||
asmgen.assignExpressionToRegister(range.to, RegisterOrPair.AY)
|
||||
precheckFromToWord(iterableDt, stepsize, varname, endLabel)
|
||||
asmgen.out("""
|
||||
sty $modifiedLabel+1
|
||||
sta $modifiedLabel2+1
|
||||
$loopLabel""")
|
||||
asmgen.translate(stmt.statements)
|
||||
asmgen.out("""
|
||||
asmgen.translate(forloop.statements)
|
||||
asmgen.out("""
|
||||
lda $varname+1
|
||||
$modifiedLabel cmp #0 ; modified
|
||||
bne +
|
||||
lda $varname
|
||||
$modifiedLabel2 cmp #0 ; modified
|
||||
beq $endLabel""")
|
||||
asmgen.romableError("self-modifying code (forloop over range)", stmt.position) // TODO fix romable
|
||||
if(stepsize==1) {
|
||||
asmgen.out("""
|
||||
+ inc $varname
|
||||
bne $loopLabel
|
||||
inc $varname+1""")
|
||||
asmgen.jmp(loopLabel)
|
||||
} else {
|
||||
asmgen.out("""
|
||||
+ lda $varname
|
||||
bne +
|
||||
dec $varname+1
|
||||
+ dec $varname""")
|
||||
asmgen.jmp(loopLabel)
|
||||
if(stepsize==1) {
|
||||
asmgen.out("""
|
||||
+ inc $varname
|
||||
bne $loopLabel
|
||||
inc $varname+1""")
|
||||
asmgen.jmp(loopLabel)
|
||||
} else {
|
||||
asmgen.out("""
|
||||
+ lda $varname
|
||||
bne +
|
||||
dec $varname+1
|
||||
+ dec $varname""")
|
||||
asmgen.jmp(loopLabel)
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
asmgen.out(endLabel)
|
||||
}
|
||||
|
||||
private fun forOverWordsStepGreaterOne(range: PtRange, varname: String, iterableDt: DataType, loopLabel: String, endLabel: String, stmt: PtForLoop) {
|
||||
@ -486,15 +532,15 @@ $endLabel""")
|
||||
when {
|
||||
iterableDt.isString -> {
|
||||
if(asmgen.options.romable) {
|
||||
// allocate index var on ZP if possible
|
||||
// TODO allocate var in ZP if possible, but maybe we should always allocate it in system memory for this (ZP is precious)?
|
||||
val indexVar = asmgen.makeLabel("for_idx")
|
||||
val result = zeropage.allocate(indexVar, DataType.UBYTE, null, stmt.position, asmgen.errors)
|
||||
result.fold(
|
||||
success = {
|
||||
(address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""")
|
||||
(address, _, _)-> asmgen.out("""$indexVar = $address ; auto zp UBYTE""")
|
||||
},
|
||||
failure = {
|
||||
TODO("no space left in zp for temp loop variable ${stmt.position}, where to put it instead") // maybe we should allocate a non-zeropage variable in system memory?
|
||||
TODO("no space left in zp for temp loop variable ${stmt.position}, where to put it instead")
|
||||
}
|
||||
)
|
||||
asmgen.out("""
|
||||
|
@ -9,6 +9,7 @@ TODO
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- romable: instead of allocating temp var in ZP in for loops, always put it in system memory instead to save precious ZP space. Look for TODO("no space left in zp
|
||||
- romable: write access to strings and arrays should be a compilation error when generating romable code (because strings and arrays are immutable in this case). But only when NOT memory mapped!
|
||||
- Kotlin: can we use inline value classes in certain spots?
|
||||
- add float support to the configurable compiler targets
|
||||
|
Loading…
x
Reference in New Issue
Block a user