mirror of
https://github.com/irmen/prog8.git
synced 2024-11-21 09:32:52 +00:00
make repeat support 65536 iterations
This commit is contained in:
parent
573cecb087
commit
bf98ceca2c
@ -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 asConstValue(): Double? = (this as? PtNumber)?.number ?: (this as? PtBool)?.asInt()?.toDouble()
|
||||
|
||||
fun isSimple(): Boolean {
|
||||
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
|
||||
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
|
||||
|
@ -790,7 +790,7 @@ class AsmGen6502Internal (
|
||||
when {
|
||||
iterations == 0 -> {}
|
||||
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)
|
||||
else -> repeatWordCount(iterations, stmt)
|
||||
}
|
||||
@ -830,10 +830,10 @@ class AsmGen6502Internal (
|
||||
}
|
||||
|
||||
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 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("""
|
||||
ldy #>$loopcount
|
||||
lda #<$loopcount
|
||||
|
@ -359,7 +359,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val variable = targetArray.variable.name
|
||||
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)
|
||||
if(zero) {
|
||||
if(fixedIndex!=null) {
|
||||
|
@ -894,7 +894,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
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")
|
||||
} else {
|
||||
return if(constValue(binExpr.right)==0.0) {
|
||||
return if(binExpr.right.asConstValue()==0.0) {
|
||||
val tr = translateExpression(binExpr.left)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNZ else Opcode.SZ
|
||||
|
@ -1589,7 +1589,7 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
private fun translate(repeat: PtRepeatLoop): IRCodeChunks {
|
||||
when (constIntValue(repeat.count)) {
|
||||
when (repeat.count.asConstInteger()) {
|
||||
0 -> return emptyList()
|
||||
1 -> return translateGroup(repeat.children)
|
||||
256 -> {
|
||||
@ -1600,18 +1600,30 @@ class IRCodeGen(
|
||||
|
||||
val repeatLabel = createLabelName()
|
||||
val skipRepeatLabel = createLabelName()
|
||||
val irDt = irType(repeat.count.type)
|
||||
val constRepeats = repeat.count.asConstInteger()
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val countTr = expressionEval.translateExpression(repeat.count)
|
||||
addToResult(result, countTr, countTr.resultReg, -1)
|
||||
if(constIntValue(repeat.count)==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)
|
||||
if(constRepeats==65536) {
|
||||
// make use of the word wrap around to count to 65536
|
||||
val resultRegister = registers.nextFree()
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=resultRegister, immediate = 0), null)
|
||||
result += labelFirstChunk(translateNode(repeat.statements), repeatLabel)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.DEC, IRDataType.WORD, reg1 = resultRegister) // 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)
|
||||
return result
|
||||
|
@ -547,7 +547,7 @@ internal class AstChecker(private val program: Program,
|
||||
val iterations = repeatLoop.iterations?.constValue(program)
|
||||
if (iterations != null) {
|
||||
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
|
||||
@ -1700,8 +1700,10 @@ internal class AstChecker(private val program: Program,
|
||||
|
||||
private fun checkLongType(expression: Expression) {
|
||||
if(expression.inferType(program).istype(DataType.LONG)) {
|
||||
if(errors.noErrorForLine(expression.position))
|
||||
errors.err("integer overflow", expression.position)
|
||||
if(expression.parent !is RepeatLoop) {
|
||||
if (errors.noErrorForLine(expression.position))
|
||||
errors.err("integer overflow", expression.position)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
make repeat support 65536 iterations
|
||||
|
||||
scripts/cx16_images : add an option to keep the first palette entry black (there's already the option to retain the first 16 entries)
|
||||
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)
|
||||
|
||||
support this usage of defer:
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage basicsafe
|
||||
%address $f200
|
||||
%output raw
|
||||
%launcher none
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
txt.print_uwhex(cbm.MEMTOP(0, true), true)
|
||||
cx16.r0=0
|
||||
repeat 65536 {
|
||||
cx16.r0++
|
||||
}
|
||||
txt.print_uw(cx16.r0)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user