make repeat support 65536 iterations

This commit is contained in:
Irmen de Jong 2024-11-11 01:55:25 +01:00
parent 573cecb087
commit bf98ceca2c
8 changed files with 41 additions and 31 deletions

View File

@ -82,6 +82,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
} }
fun asConstInteger(): Int? = (this as? PtNumber)?.number?.toInt() ?: (this as? PtBool)?.asInt() fun asConstInteger(): Int? = (this as? PtNumber)?.number?.toInt() ?: (this as? PtBool)?.asInt()
fun asConstValue(): Double? = (this as? PtNumber)?.number ?: (this as? PtBool)?.asInt()?.toDouble()
fun isSimple(): Boolean { fun isSimple(): Boolean {
return when(this) { return when(this) {
@ -378,7 +379,3 @@ class PtTypeCast(type: DataType, position: Position) : PtExpression(type, positi
// special node that isn't created from compiling user code, but used internally in the Intermediate Code // special node that isn't created from compiling user code, but used internally in the Intermediate Code
class PtIrRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position) class PtIrRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position)
fun constValue(expr: PtExpression): Double? = if(expr is PtNumber) expr.number else if(expr is PtBool) expr.asInt().toDouble() else null
fun constIntValue(expr: PtExpression): Int? = if(expr is PtNumber) expr.number.toInt() else if(expr is PtBool) expr.asInt() else null

View File

@ -790,7 +790,7 @@ class AsmGen6502Internal (
when { when {
iterations == 0 -> {} iterations == 0 -> {}
iterations == 1 -> translate(stmt.statements) iterations == 1 -> translate(stmt.statements)
iterations<0 || iterations>65535 -> throw AssemblyError("invalid number of iterations") iterations<0 || iterations>65536 -> throw AssemblyError("invalid number of iterations")
iterations <= 256 -> repeatByteCount(iterations, stmt) iterations <= 256 -> repeatByteCount(iterations, stmt)
else -> repeatWordCount(iterations, stmt) else -> repeatWordCount(iterations, stmt)
} }
@ -830,10 +830,10 @@ class AsmGen6502Internal (
} }
private fun repeatWordCount(iterations: Int, stmt: PtRepeatLoop) { private fun repeatWordCount(iterations: Int, stmt: PtRepeatLoop) {
require(iterations in 257..65535) { "invalid repeat count ${stmt.position}" } require(iterations in 257..65536) { "invalid repeat count ${stmt.position}" }
val repeatLabel = makeLabel("repeat") val repeatLabel = makeLabel("repeat")
val counterVar = createRepeatCounterVar(DataType.UWORD, isTargetCpu(CpuType.CPU65c02), stmt) val counterVar = createRepeatCounterVar(DataType.UWORD, isTargetCpu(CpuType.CPU65c02), stmt)
val loopcount = if(iterations and 0x00ff == 0) iterations else iterations + 0x0100 // so that the loop can simply use a double-dec val loopcount = if(iterations==65536) 0 else if(iterations and 0x00ff == 0) iterations else iterations + 0x0100 // so that the loop can simply use a double-dec
out(""" out("""
ldy #>$loopcount ldy #>$loopcount
lda #<$loopcount lda #<$loopcount

View File

@ -359,7 +359,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val variable = targetArray.variable.name val variable = targetArray.variable.name
val itemsize = codeGen.program.memsizer.memorySize(targetArray.type) val itemsize = codeGen.program.memsizer.memorySize(targetArray.type)
val fixedIndex = constIntValue(targetArray.index) val fixedIndex = targetArray.index.asConstInteger()
val arrayLength = codeGen.symbolTable.getLength(targetArray.variable.name) val arrayLength = codeGen.symbolTable.getLength(targetArray.variable.name)
if(zero) { if(zero) {
if(fixedIndex!=null) { if(fixedIndex!=null) {

View File

@ -894,7 +894,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
if(binExpr.left.type==DataType.STR || binExpr.right.type==DataType.STR) { if(binExpr.left.type==DataType.STR || binExpr.right.type==DataType.STR) {
throw AssemblyError("str compares should have been replaced with builtin function call to do the compare") throw AssemblyError("str compares should have been replaced with builtin function call to do the compare")
} else { } else {
return if(constValue(binExpr.right)==0.0) { return if(binExpr.right.asConstValue()==0.0) {
val tr = translateExpression(binExpr.left) val tr = translateExpression(binExpr.left)
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ

View File

@ -1589,7 +1589,7 @@ class IRCodeGen(
} }
private fun translate(repeat: PtRepeatLoop): IRCodeChunks { private fun translate(repeat: PtRepeatLoop): IRCodeChunks {
when (constIntValue(repeat.count)) { when (repeat.count.asConstInteger()) {
0 -> return emptyList() 0 -> return emptyList()
1 -> return translateGroup(repeat.children) 1 -> return translateGroup(repeat.children)
256 -> { 256 -> {
@ -1600,18 +1600,30 @@ class IRCodeGen(
val repeatLabel = createLabelName() val repeatLabel = createLabelName()
val skipRepeatLabel = createLabelName() val skipRepeatLabel = createLabelName()
val irDt = irType(repeat.count.type) val constRepeats = repeat.count.asConstInteger()
val result = mutableListOf<IRCodeChunkBase>() val result = mutableListOf<IRCodeChunkBase>()
val countTr = expressionEval.translateExpression(repeat.count) if(constRepeats==65536) {
addToResult(result, countTr, countTr.resultReg, -1) // make use of the word wrap around to count to 65536
if(constIntValue(repeat.count)==null) { val resultRegister = registers.nextFree()
// check if the counter is already zero addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultRegister, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.BSTEQ, labelSymbol = skipRepeatLabel), null) result += labelFirstChunk(translateNode(repeat.statements), repeatLabel)
} result += IRCodeChunk(null, null).also {
result += labelFirstChunk(translateNode(repeat.statements), repeatLabel) it += IRInstruction(Opcode.DEC, IRDataType.WORD, reg1 = resultRegister) // sets status bits
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.BSTNE, labelSymbol = repeatLabel)
it += IRInstruction(Opcode.DEC, irDt, reg1 = countTr.resultReg) // sets status bits }
it += IRInstruction(Opcode.BSTNE, labelSymbol = repeatLabel) } else {
val irDt = irType(repeat.count.type)
val countTr = expressionEval.translateExpression(repeat.count)
addToResult(result, countTr, countTr.resultReg, -1)
if (repeat.count.asConstValue() == null) {
// check if the counter is already zero
addInstr(result, IRInstruction(Opcode.BSTEQ, labelSymbol = skipRepeatLabel), null)
}
result += labelFirstChunk(translateNode(repeat.statements), repeatLabel)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.DEC, irDt, reg1 = countTr.resultReg) // sets status bits
it += IRInstruction(Opcode.BSTNE, labelSymbol = repeatLabel)
}
} }
result += IRCodeChunk(skipRepeatLabel, null) result += IRCodeChunk(skipRepeatLabel, null)
return result return result

View File

@ -547,7 +547,7 @@ internal class AstChecker(private val program: Program,
val iterations = repeatLoop.iterations?.constValue(program) val iterations = repeatLoop.iterations?.constValue(program)
if (iterations != null) { if (iterations != null) {
require(floor(iterations.number)==iterations.number) require(floor(iterations.number)==iterations.number)
if (iterations.number.toInt() > 65535) errors.err("repeat cannot go over 65535 iterations", iterations.position) if (iterations.number.toInt() > 65536) errors.err("repeat cannot exceed 65536 iterations", iterations.position)
} }
val ident = repeatLoop.iterations as? IdentifierReference val ident = repeatLoop.iterations as? IdentifierReference
@ -1700,8 +1700,10 @@ internal class AstChecker(private val program: Program,
private fun checkLongType(expression: Expression) { private fun checkLongType(expression: Expression) {
if(expression.inferType(program).istype(DataType.LONG)) { if(expression.inferType(program).istype(DataType.LONG)) {
if(errors.noErrorForLine(expression.position)) if(expression.parent !is RepeatLoop) {
errors.err("integer overflow", expression.position) if (errors.noErrorForLine(expression.position))
errors.err("integer overflow", expression.position)
}
} }
} }

View File

@ -1,9 +1,7 @@
TODO TODO
==== ====
make repeat support 65536 iterations scripts/cx16_images : add an option to keep the first palette entry black (or any specific color) (there's already the option to retain the first 16 entries)
scripts/cx16_images : add an option to keep the first palette entry black (there's already the option to retain the first 16 entries)
support this usage of defer: support this usage of defer:

View File

@ -1,12 +1,13 @@
%import textio %import textio
%option no_sysinit %option no_sysinit
%zeropage basicsafe %zeropage basicsafe
%address $f200
%output raw
%launcher none
main { main {
sub start() { sub start() {
txt.print_uwhex(cbm.MEMTOP(0, true), true) cx16.r0=0
repeat 65536 {
cx16.r0++
}
txt.print_uw(cx16.r0)
} }
} }