mirror of
https://github.com/irmen/prog8.git
synced 2025-11-01 22:16:16 +00:00
removed 'continue' statement to be able to generate more optimized loop assembly code. started with for loop optimizations
This commit is contained in:
@@ -305,10 +305,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
|||||||
output(postIncrDecr.operator)
|
output(postIncrDecr.operator)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(contStmt: Continue) {
|
|
||||||
output("continue")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visit(breakStmt: Break) {
|
override fun visit(breakStmt: Break) {
|
||||||
output("break")
|
output("break")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,9 +217,6 @@ private fun prog8Parser.StatementContext.toAst() : Statement {
|
|||||||
val breakstmt = breakstmt()?.toAst()
|
val breakstmt = breakstmt()?.toAst()
|
||||||
if(breakstmt!=null) return breakstmt
|
if(breakstmt!=null) return breakstmt
|
||||||
|
|
||||||
val continuestmt = continuestmt()?.toAst()
|
|
||||||
if(continuestmt!=null) return continuestmt
|
|
||||||
|
|
||||||
val whenstmt = whenstmt()?.toAst()
|
val whenstmt = whenstmt()?.toAst()
|
||||||
if(whenstmt!=null) return whenstmt
|
if(whenstmt!=null) return whenstmt
|
||||||
|
|
||||||
@@ -593,8 +590,6 @@ private fun prog8Parser.ForloopContext.toAst(): ForLoop {
|
|||||||
return ForLoop(loopvar, iterable, scope, toPosition())
|
return ForLoop(loopvar, iterable, scope, toPosition())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun prog8Parser.ContinuestmtContext.toAst() = Continue(toPosition())
|
|
||||||
|
|
||||||
private fun prog8Parser.BreakstmtContext.toAst() = Break(toPosition())
|
private fun prog8Parser.BreakstmtContext.toAst() = Break(toPosition())
|
||||||
|
|
||||||
private fun prog8Parser.WhileloopContext.toAst(): WhileLoop {
|
private fun prog8Parser.WhileloopContext.toAst(): WhileLoop {
|
||||||
|
|||||||
@@ -88,7 +88,6 @@ abstract class AstWalker {
|
|||||||
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(contStmt: Continue, parent: Node): Iterable<IAstModification> = emptyList()
|
|
||||||
open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
@@ -130,7 +129,6 @@ abstract class AstWalker {
|
|||||||
open fun after(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(branchStatement: BranchStatement, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun after(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(breakStmt: Break, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(builtinFunctionStatementPlaceholder: BuiltinFunctionStatementPlaceholder, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun after(contStmt: Continue, parent: Node): Iterable<IAstModification> = emptyList()
|
|
||||||
open fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(decl: VarDecl, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun after(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(directive: Directive, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
open fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
open fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = emptyList()
|
||||||
@@ -309,11 +307,6 @@ abstract class AstWalker {
|
|||||||
track(after(postIncrDecr, parent), postIncrDecr, parent)
|
track(after(postIncrDecr, parent), postIncrDecr, parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(contStmt: Continue, parent: Node) {
|
|
||||||
track(before(contStmt, parent), contStmt, parent)
|
|
||||||
track(after(contStmt, parent), contStmt, parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun visit(breakStmt: Break, parent: Node) {
|
fun visit(breakStmt: Break, parent: Node) {
|
||||||
track(before(breakStmt, parent), breakStmt, parent)
|
track(before(breakStmt, parent), breakStmt, parent)
|
||||||
track(after(breakStmt, parent), breakStmt, parent)
|
track(after(breakStmt, parent), breakStmt, parent)
|
||||||
|
|||||||
@@ -95,9 +95,6 @@ interface IAstVisitor {
|
|||||||
postIncrDecr.target.accept(this)
|
postIncrDecr.target.accept(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visit(contStmt: Continue) {
|
|
||||||
}
|
|
||||||
|
|
||||||
fun visit(breakStmt: Break) {
|
fun visit(breakStmt: Break) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,18 +148,6 @@ class ReturnFromIrq(override val position: Position) : Return(null, position) {
|
|||||||
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
|
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Continue(override val position: Position) : Statement() {
|
|
||||||
override lateinit var parent: Node
|
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
|
||||||
this.parent=parent
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
|
|
||||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
|
||||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Break(override val position: Position) : Statement() {
|
class Break(override val position: Position) : Statement() {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
|
|||||||
@@ -43,13 +43,11 @@ internal class AsmGen(private val program: Program,
|
|||||||
private val assignmentAsmGen = AssignmentAsmGen(program, errors, this)
|
private val assignmentAsmGen = AssignmentAsmGen(program, errors, this)
|
||||||
private val expressionsAsmGen = ExpressionsAsmGen(program, this)
|
private val expressionsAsmGen = ExpressionsAsmGen(program, this)
|
||||||
internal val loopEndLabels = ArrayDeque<String>()
|
internal val loopEndLabels = ArrayDeque<String>()
|
||||||
internal val loopContinueLabels = ArrayDeque<String>()
|
|
||||||
internal val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
|
internal val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
|
||||||
|
|
||||||
override fun compileToAssembly(optimize: Boolean): IAssemblyProgram {
|
override fun compileToAssembly(optimize: Boolean): IAssemblyProgram {
|
||||||
assemblyLines.clear()
|
assemblyLines.clear()
|
||||||
loopEndLabels.clear()
|
loopEndLabels.clear()
|
||||||
loopContinueLabels.clear()
|
|
||||||
|
|
||||||
println("Generating assembly code... ")
|
println("Generating assembly code... ")
|
||||||
|
|
||||||
@@ -638,7 +636,6 @@ internal class AsmGen(private val program: Program,
|
|||||||
is BranchStatement -> translate(stmt)
|
is BranchStatement -> translate(stmt)
|
||||||
is IfStatement -> translate(stmt)
|
is IfStatement -> translate(stmt)
|
||||||
is ForLoop -> forloopsAsmGen.translate(stmt)
|
is ForLoop -> forloopsAsmGen.translate(stmt)
|
||||||
is Continue -> out(" jmp ${loopContinueLabels.peek()}")
|
|
||||||
is Break -> out(" jmp ${loopEndLabels.peek()}")
|
is Break -> out(" jmp ${loopEndLabels.peek()}")
|
||||||
is WhileLoop -> translate(stmt)
|
is WhileLoop -> translate(stmt)
|
||||||
is RepeatLoop -> translate(stmt)
|
is RepeatLoop -> translate(stmt)
|
||||||
@@ -674,11 +671,11 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: RepeatLoop) {
|
private fun translate(stmt: RepeatLoop) {
|
||||||
|
// TODO more optimized code possible now that continue is gone?
|
||||||
val repeatLabel = makeLabel("repeat")
|
val repeatLabel = makeLabel("repeat")
|
||||||
val endLabel = makeLabel("repeatend")
|
val endLabel = makeLabel("repeatend")
|
||||||
val counterLabel = makeLabel("repeatcounter")
|
val counterLabel = makeLabel("repeatcounter")
|
||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
loopContinueLabels.push(repeatLabel)
|
|
||||||
|
|
||||||
when (stmt.iterations) {
|
when (stmt.iterations) {
|
||||||
null -> {
|
null -> {
|
||||||
@@ -737,7 +734,6 @@ internal class AsmGen(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
loopEndLabels.pop()
|
loopEndLabels.pop()
|
||||||
loopContinueLabels.pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun repeatWordCountInAY(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
private fun repeatWordCountInAY(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
|
||||||
@@ -778,10 +774,10 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: WhileLoop) {
|
private fun translate(stmt: WhileLoop) {
|
||||||
|
// TODO more optimized code possible now that continue is gone?
|
||||||
val whileLabel = makeLabel("while")
|
val whileLabel = makeLabel("while")
|
||||||
val endLabel = makeLabel("whileend")
|
val endLabel = makeLabel("whileend")
|
||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
loopContinueLabels.push(whileLabel)
|
|
||||||
out(whileLabel)
|
out(whileLabel)
|
||||||
expressionsAsmGen.translateExpression(stmt.condition)
|
expressionsAsmGen.translateExpression(stmt.condition)
|
||||||
val conditionDt = stmt.condition.inferType(program)
|
val conditionDt = stmt.condition.inferType(program)
|
||||||
@@ -802,14 +798,13 @@ $endLabel""")
|
|||||||
out(" jmp $whileLabel")
|
out(" jmp $whileLabel")
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
loopEndLabels.pop()
|
loopEndLabels.pop()
|
||||||
loopContinueLabels.pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: UntilLoop) {
|
private fun translate(stmt: UntilLoop) {
|
||||||
|
// TODO more optimized code possible now that continue is gone?
|
||||||
val repeatLabel = makeLabel("repeat")
|
val repeatLabel = makeLabel("repeat")
|
||||||
val endLabel = makeLabel("repeatend")
|
val endLabel = makeLabel("repeatend")
|
||||||
loopEndLabels.push(endLabel)
|
loopEndLabels.push(endLabel)
|
||||||
loopContinueLabels.push(repeatLabel)
|
|
||||||
out(repeatLabel)
|
out(repeatLabel)
|
||||||
translate(stmt.body)
|
translate(stmt.body)
|
||||||
expressionsAsmGen.translateExpression(stmt.untilCondition)
|
expressionsAsmGen.translateExpression(stmt.untilCondition)
|
||||||
@@ -829,7 +824,6 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
out(endLabel)
|
out(endLabel)
|
||||||
loopEndLabels.pop()
|
loopEndLabels.pop()
|
||||||
loopContinueLabels.pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(stmt: WhenStatement) {
|
private fun translate(stmt: WhenStatement) {
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX
|
|||||||
import prog8.compiler.toHex
|
import prog8.compiler.toHex
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
// todo optimized loop code for common simple cases 0..N, N..0, >=1..N , N..>=1 where N<=255
|
|
||||||
// todo choose more efficient comparisons to avoid needless lda's
|
// todo choose more efficient comparisons to avoid needless lda's
|
||||||
// todo optimize common case when step == 2 or -2
|
// todo optimized code for step == 2 or -2
|
||||||
// todo allocate loop counter variable dynamically, preferrably on zeropage
|
// todo allocate loop counter variable dynamically, preferrably on zeropage
|
||||||
|
|
||||||
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
internal class ForLoopsAsmGen(private val program: Program, private val asmgen: AsmGen) {
|
||||||
@@ -42,11 +41,11 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForOverNonconstRange(stmt: ForLoop, iterableDt: DataType, range: RangeExpr) {
|
private fun translateForOverNonconstRange(stmt: ForLoop, iterableDt: DataType, range: RangeExpr) {
|
||||||
|
// TODO more optimized code possible now that continue is gone?
|
||||||
|
|
||||||
val loopLabel = asmgen.makeLabel("for_loop")
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
val endLabel = asmgen.makeLabel("for_end")
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
val continueLabel = asmgen.makeLabel("for_continue")
|
|
||||||
asmgen.loopEndLabels.push(endLabel)
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
asmgen.loopContinueLabels.push(continueLabel)
|
|
||||||
val stepsize=range.step.constValue(program)!!.number.toInt()
|
val stepsize=range.step.constValue(program)!!.number.toInt()
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
@@ -66,7 +65,7 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel lda $varname
|
lda $varname
|
||||||
cmp $ESTACK_LO_PLUS1_HEX,x
|
cmp $ESTACK_LO_PLUS1_HEX,x
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
$incdec $varname
|
$incdec $varname
|
||||||
@@ -88,7 +87,7 @@ $endLabel inx""")
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel lda $varname""")
|
lda $varname""")
|
||||||
if(stepsize>0) {
|
if(stepsize>0) {
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
clc
|
clc
|
||||||
@@ -248,15 +247,13 @@ $endLabel inx""")
|
|||||||
}
|
}
|
||||||
|
|
||||||
asmgen.loopEndLabels.pop()
|
asmgen.loopEndLabels.pop()
|
||||||
asmgen.loopContinueLabels.pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForOverIterableVar(stmt: ForLoop, iterableDt: DataType, ident: IdentifierReference) {
|
private fun translateForOverIterableVar(stmt: ForLoop, iterableDt: DataType, ident: IdentifierReference) {
|
||||||
|
// TODO more optimized code possible now that continue is gone?
|
||||||
val loopLabel = asmgen.makeLabel("for_loop")
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
val endLabel = asmgen.makeLabel("for_end")
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
val continueLabel = asmgen.makeLabel("for_continue")
|
|
||||||
asmgen.loopEndLabels.push(endLabel)
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
asmgen.loopContinueLabels.push(continueLabel)
|
|
||||||
val iterableName = asmgen.asmIdentifierName(ident)
|
val iterableName = asmgen.asmIdentifierName(ident)
|
||||||
val decl = ident.targetVarDecl(program.namespace)!!
|
val decl = ident.targetVarDecl(program.namespace)!!
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
@@ -271,7 +268,7 @@ $loopLabel lda ${65535.toHex()} ; modified
|
|||||||
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
|
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel inc $loopLabel+1
|
inc $loopLabel+1
|
||||||
bne $loopLabel
|
bne $loopLabel
|
||||||
inc $loopLabel+2
|
inc $loopLabel+2
|
||||||
bne $loopLabel
|
bne $loopLabel
|
||||||
@@ -293,7 +290,7 @@ $modifiedLabel lda ${65535.toHex()},y ; modified""")
|
|||||||
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
|
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel ldy $counterLabel
|
ldy $counterLabel
|
||||||
iny
|
iny
|
||||||
cpy #${length and 255}
|
cpy #${length and 255}
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
@@ -325,7 +322,7 @@ $modifiedLabel2 lda ${65535.toHex()},y ; modified
|
|||||||
sta $loopvarName+1""")
|
sta $loopvarName+1""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel ldy $counterLabel
|
ldy $counterLabel
|
||||||
iny
|
iny
|
||||||
iny
|
iny
|
||||||
cpy #${length and 255}
|
cpy #${length and 255}
|
||||||
@@ -340,57 +337,34 @@ $endLabel""")
|
|||||||
else -> throw AssemblyError("can't iterate over $iterableDt")
|
else -> throw AssemblyError("can't iterate over $iterableDt")
|
||||||
}
|
}
|
||||||
asmgen.loopEndLabels.pop()
|
asmgen.loopEndLabels.pop()
|
||||||
asmgen.loopContinueLabels.pop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
|
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
|
||||||
// TODO: optimize loop code when the range is < 256 iterations
|
if (range.isEmpty() || range.step==0)
|
||||||
if (range.isEmpty())
|
throw AssemblyError("empty range or step 0")
|
||||||
throw AssemblyError("empty range")
|
if(iterableDt==DataType.ARRAY_B || iterableDt==DataType.ARRAY_UB) {
|
||||||
|
if(range.step==1 && range.first>=0 && range.last <= 255 && range.last>range.first) return translateForSimpleByteRangeAsc(stmt, range)
|
||||||
|
if(range.step==-1 && range.first<=255 && range.first >=0 && range.last<range.first) return translateForSimpleByteRangeDesc(stmt, range)
|
||||||
|
}
|
||||||
|
if(iterableDt==DataType.ARRAY_W || iterableDt==DataType.ARRAY_UW) {
|
||||||
|
if(range.step==1 && range.first>=0 && range.last <= 255 && range.last>range.first) return translateForSimpleWordRange255Asc(stmt, range)
|
||||||
|
if(range.step==-1 && range.first<=255 && range.first >=0 && range.last<range.first) return translateForSimpleWordRange255Desc(stmt, range)
|
||||||
|
if(range.step==1 && range.first>=0 && range.last <= 65535 && range.last>range.first) return translateForSimpleWordRange65535Asc(stmt, range)
|
||||||
|
if(range.step==-1 && range.first<=65535 && range.first >=0 && range.last<range.first) return translateForSimpleWordRange65535Desc(stmt, range)
|
||||||
|
}
|
||||||
|
|
||||||
val loopLabel = asmgen.makeLabel("for_loop")
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
val endLabel = asmgen.makeLabel("for_end")
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
val continueLabel = asmgen.makeLabel("for_continue")
|
|
||||||
asmgen.loopEndLabels.push(endLabel)
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
asmgen.loopContinueLabels.push(continueLabel)
|
// TODO more optimized code possible now that continue is gone?
|
||||||
when(iterableDt) {
|
when(iterableDt) {
|
||||||
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
DataType.ARRAY_B, DataType.ARRAY_UB -> {
|
||||||
|
// loop over byte range via loopvar, step > 1 or < -1
|
||||||
val counterLabel = asmgen.makeLabel("for_counter")
|
val counterLabel = asmgen.makeLabel("for_counter")
|
||||||
// loop over byte range via loopvar
|
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
||||||
when {
|
when {
|
||||||
range.step==1 -> {
|
range.step==1 || range.step==-1 -> {
|
||||||
// step = 1
|
throw AssemblyError("step 1 and -1 should have been handled specifically")
|
||||||
asmgen.out("""
|
|
||||||
lda #${range.first}
|
|
||||||
sta $varname
|
|
||||||
lda #${range.last-range.first+1 and 255}
|
|
||||||
sta $counterLabel
|
|
||||||
$loopLabel""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel dec $counterLabel
|
|
||||||
beq $endLabel
|
|
||||||
inc $varname
|
|
||||||
jmp $loopLabel
|
|
||||||
$counterLabel .byte 0
|
|
||||||
$endLabel""")
|
|
||||||
}
|
|
||||||
range.step==-1 -> {
|
|
||||||
// step = -1
|
|
||||||
asmgen.out("""
|
|
||||||
lda #${range.first}
|
|
||||||
sta $varname
|
|
||||||
lda #${range.first-range.last+1 and 255}
|
|
||||||
sta $counterLabel
|
|
||||||
$loopLabel""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel dec $counterLabel
|
|
||||||
beq $endLabel
|
|
||||||
dec $varname
|
|
||||||
jmp $loopLabel
|
|
||||||
$counterLabel .byte 0
|
|
||||||
$endLabel""")
|
|
||||||
}
|
}
|
||||||
range.step >= 2 -> {
|
range.step >= 2 -> {
|
||||||
// step >= 2
|
// step >= 2
|
||||||
@@ -402,7 +376,7 @@ $endLabel""")
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel dec $counterLabel
|
dec $counterLabel
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
lda $varname
|
lda $varname
|
||||||
clc
|
clc
|
||||||
@@ -422,7 +396,7 @@ $endLabel""")
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel dec $counterLabel
|
dec $counterLabel
|
||||||
beq $endLabel
|
beq $endLabel
|
||||||
lda $varname
|
lda $varname
|
||||||
sec
|
sec
|
||||||
@@ -435,56 +409,59 @@ $endLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
DataType.ARRAY_W, DataType.ARRAY_UW -> {
|
||||||
// loop over word range via loopvar
|
// loop over word range via loopvar, step > 1 or < -1
|
||||||
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
||||||
when {
|
when {
|
||||||
range.step == 1 -> {
|
range.step==1 || range.step==-1 -> {
|
||||||
// word, step = 1
|
throw AssemblyError("step 1 and -1 should have been handled specifically")
|
||||||
val lastValue = range.last+1
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${range.first}
|
|
||||||
ldy #>${range.first}
|
|
||||||
sta $varname
|
|
||||||
sty $varname+1
|
|
||||||
$loopLabel""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel inc $varname
|
|
||||||
bne +
|
|
||||||
inc $varname+1
|
|
||||||
+ lda $varname
|
|
||||||
cmp #<$lastValue
|
|
||||||
bne +
|
|
||||||
lda $varname+1
|
|
||||||
cmp #>$lastValue
|
|
||||||
beq $endLabel
|
|
||||||
+ jmp $loopLabel
|
|
||||||
$endLabel""")
|
|
||||||
}
|
|
||||||
range.step == -1 -> {
|
|
||||||
// word, step = 1
|
|
||||||
val lastValue = range.last-1
|
|
||||||
asmgen.out("""
|
|
||||||
lda #<${range.first}
|
|
||||||
ldy #>${range.first}
|
|
||||||
sta $varname
|
|
||||||
sty $varname+1
|
|
||||||
$loopLabel""")
|
|
||||||
asmgen.translate(stmt.body)
|
|
||||||
asmgen.out("""
|
|
||||||
$continueLabel lda $varname
|
|
||||||
bne +
|
|
||||||
dec $varname+1
|
|
||||||
+ dec $varname
|
|
||||||
lda $varname
|
|
||||||
cmp #<$lastValue
|
|
||||||
bne +
|
|
||||||
lda $varname+1
|
|
||||||
cmp #>$lastValue
|
|
||||||
beq $endLabel
|
|
||||||
+ jmp $loopLabel
|
|
||||||
$endLabel""")
|
|
||||||
}
|
}
|
||||||
|
// range.step == 1 -> {
|
||||||
|
// // word, step = 1
|
||||||
|
// val lastValue = range.last+1
|
||||||
|
// asmgen.out("""
|
||||||
|
// lda #<${range.first}
|
||||||
|
// ldy #>${range.first}
|
||||||
|
// sta $varname
|
||||||
|
// sty $varname+1
|
||||||
|
//$loopLabel""")
|
||||||
|
// asmgen.translate(stmt.body)
|
||||||
|
// asmgen.out("""
|
||||||
|
// inc $varname
|
||||||
|
// bne +
|
||||||
|
// inc $varname+1
|
||||||
|
//+ lda $varname
|
||||||
|
// cmp #<$lastValue
|
||||||
|
// bne +
|
||||||
|
// lda $varname+1
|
||||||
|
// cmp #>$lastValue
|
||||||
|
// beq $endLabel
|
||||||
|
//+ jmp $loopLabel
|
||||||
|
//$endLabel""")
|
||||||
|
// }
|
||||||
|
// range.step == -1 -> {
|
||||||
|
// // word, step = 1
|
||||||
|
// val lastValue = range.last-1
|
||||||
|
// asmgen.out("""
|
||||||
|
// lda #<${range.first}
|
||||||
|
// ldy #>${range.first}
|
||||||
|
// sta $varname
|
||||||
|
// sty $varname+1
|
||||||
|
//$loopLabel""")
|
||||||
|
// asmgen.translate(stmt.body)
|
||||||
|
// asmgen.out("""
|
||||||
|
// lda $varname
|
||||||
|
// bne +
|
||||||
|
// dec $varname+1
|
||||||
|
//+ dec $varname
|
||||||
|
// lda $varname
|
||||||
|
// cmp #<$lastValue
|
||||||
|
// bne +
|
||||||
|
// lda $varname+1
|
||||||
|
// cmp #>$lastValue
|
||||||
|
// beq $endLabel
|
||||||
|
//+ jmp $loopLabel
|
||||||
|
//$endLabel""")
|
||||||
|
// }
|
||||||
range.step >= 2 -> {
|
range.step >= 2 -> {
|
||||||
// word, step >= 2
|
// word, step >= 2
|
||||||
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
|
// note: range.last has already been adjusted by kotlin itself to actually be the last value of the sequence
|
||||||
@@ -497,7 +474,7 @@ $endLabel""")
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel clc
|
clc
|
||||||
lda $varname
|
lda $varname
|
||||||
adc #<${range.step}
|
adc #<${range.step}
|
||||||
sta $varname
|
sta $varname
|
||||||
@@ -525,7 +502,7 @@ $endLabel""")
|
|||||||
$loopLabel""")
|
$loopLabel""")
|
||||||
asmgen.translate(stmt.body)
|
asmgen.translate(stmt.body)
|
||||||
asmgen.out("""
|
asmgen.out("""
|
||||||
$continueLabel sec
|
sec
|
||||||
lda $varname
|
lda $varname
|
||||||
sbc #<${range.step.absoluteValue}
|
sbc #<${range.step.absoluteValue}
|
||||||
sta $varname
|
sta $varname
|
||||||
@@ -546,7 +523,102 @@ $endLabel""")
|
|||||||
else -> throw AssemblyError("range expression can only be byte or word")
|
else -> throw AssemblyError("range expression can only be byte or word")
|
||||||
}
|
}
|
||||||
asmgen.loopEndLabels.pop()
|
asmgen.loopEndLabels.pop()
|
||||||
asmgen.loopContinueLabels.pop()
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleByteRangeAsc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
|
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
||||||
|
if (range.last == 255) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
inc $varname
|
||||||
|
bne $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
} else {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
cmp #${range.last}
|
||||||
|
beq $endLabel
|
||||||
|
inc $varname
|
||||||
|
bne $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
asmgen.loopEndLabels.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleByteRangeDesc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
val loopLabel = asmgen.makeLabel("for_loop")
|
||||||
|
val endLabel = asmgen.makeLabel("for_end")
|
||||||
|
asmgen.loopEndLabels.push(endLabel)
|
||||||
|
val varname = asmgen.asmIdentifierName(stmt.loopVar)
|
||||||
|
when (range.last) {
|
||||||
|
0 -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
beq $endLabel
|
||||||
|
dec $varname
|
||||||
|
jmp $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
dec $varname
|
||||||
|
bne $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
asmgen.out("""
|
||||||
|
lda #${range.first}
|
||||||
|
sta $varname
|
||||||
|
$loopLabel""")
|
||||||
|
asmgen.translate(stmt.body)
|
||||||
|
asmgen.out("""
|
||||||
|
lda $varname
|
||||||
|
cmp #${range.last}
|
||||||
|
beq $endLabel
|
||||||
|
dec $varname
|
||||||
|
bne $loopLabel
|
||||||
|
$endLabel""")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asmgen.loopEndLabels.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleWordRange255Asc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleWordRange255Desc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleWordRange65535Asc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun translateForSimpleWordRange65535Desc(stmt: ForLoop, range: IntProgression) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,6 @@ import prog8.functions.BuiltinFunctions
|
|||||||
import kotlin.math.floor
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO: remove unreachable code after return and exit()
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
internal class StatementOptimizer(private val program: Program,
|
internal class StatementOptimizer(private val program: Program,
|
||||||
private val errors: ErrorReporter) : AstWalker() {
|
private val errors: ErrorReporter) : AstWalker() {
|
||||||
|
|
||||||
@@ -257,9 +252,9 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
val constvalue = untilLoop.untilCondition.constValue(program)
|
val constvalue = untilLoop.untilCondition.constValue(program)
|
||||||
if(constvalue!=null) {
|
if(constvalue!=null) {
|
||||||
if(constvalue.asBooleanValue) {
|
if(constvalue.asBooleanValue) {
|
||||||
// always true -> keep only the statement block (if there are no continue and break statements)
|
// always true -> keep only the statement block (if there are no break statements)
|
||||||
errors.warn("condition is always true", untilLoop.untilCondition.position)
|
errors.warn("condition is always true", untilLoop.untilCondition.position)
|
||||||
if(!hasContinueOrBreak(untilLoop.body))
|
if(!hasBreak(untilLoop.body))
|
||||||
return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent))
|
return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent))
|
||||||
} else {
|
} else {
|
||||||
// always false
|
// always false
|
||||||
@@ -495,7 +490,7 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
return linesToRemove
|
return linesToRemove
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasContinueOrBreak(scope: INameScope): Boolean {
|
private fun hasBreak(scope: INameScope): Boolean {
|
||||||
|
|
||||||
class Searcher: IAstVisitor
|
class Searcher: IAstVisitor
|
||||||
{
|
{
|
||||||
@@ -504,10 +499,6 @@ internal class StatementOptimizer(private val program: Program,
|
|||||||
override fun visit(breakStmt: Break) {
|
override fun visit(breakStmt: Break) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visit(contStmt: Continue) {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val s=Searcher()
|
val s=Searcher()
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import prog8.ast.processing.AstWalker
|
|||||||
import prog8.ast.processing.IAstModification
|
import prog8.ast.processing.IAstModification
|
||||||
import prog8.ast.statements.Block
|
import prog8.ast.statements.Block
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: remove unreachable code after return and exit()
|
||||||
|
*/
|
||||||
|
|
||||||
internal class UnusedCodeRemover: AstWalker() {
|
internal class UnusedCodeRemover: AstWalker() {
|
||||||
|
|
||||||
|
|||||||
@@ -397,6 +397,8 @@ The *repeat* loop is used as a short notation of a for loop where the loop varia
|
|||||||
|
|
||||||
You can also create loops by using the ``goto`` statement, but this should usually be avoided.
|
You can also create loops by using the ``goto`` statement, but this should usually be avoided.
|
||||||
|
|
||||||
|
Breaking out of a loop prematurely is possible with the ``break`` statement.
|
||||||
|
|
||||||
.. attention::
|
.. attention::
|
||||||
The value of the loop variable after executing the loop *is undefined*. Don't use it immediately
|
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!
|
after the loop without first assigning a new value to it!
|
||||||
|
|||||||
@@ -559,7 +559,6 @@ You can use a single statement, or a statement block like in the example below::
|
|||||||
for <loopvar> in <expression> [ step <amount> ] {
|
for <loopvar> in <expression> [ step <amount> ] {
|
||||||
; do something...
|
; do something...
|
||||||
break ; break out of the loop
|
break ; break out of the loop
|
||||||
continue ; immediately enter next iteration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
For example, this is a for loop using a byte variable ``i``, defined before, to loop over a certain range of numbers::
|
For example, this is a for loop using a byte variable ``i``, defined before, to loop over a certain range of numbers::
|
||||||
@@ -592,7 +591,6 @@ You can use a single statement, or a statement block like in the example below::
|
|||||||
while <condition> {
|
while <condition> {
|
||||||
; do something...
|
; do something...
|
||||||
break ; break out of the loop
|
break ; break out of the loop
|
||||||
continue ; immediately enter next iteration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -605,7 +603,6 @@ You can use a single statement, or a statement block like in the example below::
|
|||||||
do {
|
do {
|
||||||
; do something...
|
; do something...
|
||||||
break ; break out of the loop
|
break ; break out of the loop
|
||||||
continue ; immediately enter next iteration
|
|
||||||
} until <condition>
|
} until <condition>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
- finalize (most) of the still missing "new" assignment asm code generation
|
- get rid of all TODO's ;-)
|
||||||
- aliases for imported symbols for example perhaps '%alias print = c64scr.print'
|
- allow declaring arrays on specific memory location and page-aligned
|
||||||
- option to load library files from a directory instead of the embedded ones (easier library development/debugging)
|
- option to load the built-inlibrary files from a directory instead of the embedded ones (for easier library development/debugging)
|
||||||
|
- aliases for imported symbols for example perhaps '%alias print = c64scr.print' ?
|
||||||
- investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs
|
- investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs
|
||||||
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
|
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
|
||||||
|
|
||||||
|
|||||||
74
examples/mfbench/romsum-p8.p8
Normal file
74
examples/mfbench/romsum-p8.p8
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
%import c64utils
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
const uword rom = $e000
|
||||||
|
|
||||||
|
sub sumrom() -> uword {
|
||||||
|
uword p = rom
|
||||||
|
uword s = 0
|
||||||
|
ubyte i
|
||||||
|
repeat $20 {
|
||||||
|
for i in 0 to $ff {
|
||||||
|
s += @(p+i)
|
||||||
|
}
|
||||||
|
p += $100
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
benchcommon.begin()
|
||||||
|
ubyte i
|
||||||
|
for i in 0 to 5 {
|
||||||
|
c64scr.print_uw(sumrom())
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
}
|
||||||
|
benchcommon.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
benchcommon {
|
||||||
|
ubyte last_time0 = 0
|
||||||
|
ubyte last_time1 = 0
|
||||||
|
ubyte last_time2 = 0
|
||||||
|
ubyte time_start0 = 0
|
||||||
|
ubyte time_start1 = 0
|
||||||
|
ubyte time_start2 = 0
|
||||||
|
|
||||||
|
|
||||||
|
asmsub read_time () clobbers(A,X,Y) {
|
||||||
|
%asm {{
|
||||||
|
jsr $FFDE
|
||||||
|
sta last_time0
|
||||||
|
stx last_time1
|
||||||
|
sty last_time2
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub begin() {
|
||||||
|
benchcommon.read_time()
|
||||||
|
benchcommon.time_start0 = benchcommon.last_time0
|
||||||
|
benchcommon.time_start1 = benchcommon.last_time1
|
||||||
|
benchcommon.time_start2 = benchcommon.last_time2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub end() {
|
||||||
|
benchcommon.read_time()
|
||||||
|
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start2, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start1, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start0, false)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time2, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time1, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time0, false)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
void c64scr.input_chars($c000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
88
examples/mfbench/sieve-p8.p8
Normal file
88
examples/mfbench/sieve-p8.p8
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
%import c64utils
|
||||||
|
|
||||||
|
main {
|
||||||
|
|
||||||
|
const uword COUNT = 16384
|
||||||
|
const uword SQRT_COUNT = 128
|
||||||
|
const uword Sieve = $4000
|
||||||
|
|
||||||
|
sub sieve_round() {
|
||||||
|
uword S
|
||||||
|
ubyte I = 2
|
||||||
|
memset(Sieve, COUNT, 0)
|
||||||
|
while I < SQRT_COUNT {
|
||||||
|
if @(Sieve + I) == 0 {
|
||||||
|
S = Sieve + (I << 1)
|
||||||
|
while S < Sieve + COUNT {
|
||||||
|
@(S) = 1
|
||||||
|
S += I
|
||||||
|
}
|
||||||
|
}
|
||||||
|
I ++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub start() {
|
||||||
|
benchcommon.begin()
|
||||||
|
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
sieve_round()
|
||||||
|
|
||||||
|
benchcommon.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
benchcommon {
|
||||||
|
ubyte last_time0 = 0
|
||||||
|
ubyte last_time1 = 0
|
||||||
|
ubyte last_time2 = 0
|
||||||
|
ubyte time_start0 = 0
|
||||||
|
ubyte time_start1 = 0
|
||||||
|
ubyte time_start2 = 0
|
||||||
|
|
||||||
|
|
||||||
|
asmsub read_time () clobbers(A,X,Y) {
|
||||||
|
%asm {{
|
||||||
|
jsr $FFDE
|
||||||
|
sta last_time0
|
||||||
|
stx last_time1
|
||||||
|
sty last_time2
|
||||||
|
rts
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub begin() {
|
||||||
|
benchcommon.read_time()
|
||||||
|
benchcommon.time_start0 = benchcommon.last_time0
|
||||||
|
benchcommon.time_start1 = benchcommon.last_time1
|
||||||
|
benchcommon.time_start2 = benchcommon.last_time2
|
||||||
|
}
|
||||||
|
|
||||||
|
sub end() {
|
||||||
|
benchcommon.read_time()
|
||||||
|
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start2, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start1, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.time_start0, false)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time2, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time1, false)
|
||||||
|
c64scr.print_ubhex(benchcommon.last_time0, false)
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
void c64scr.input_chars($c000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
120
examples/test.p8
120
examples/test.p8
@@ -2,49 +2,97 @@
|
|||||||
%import c64utils
|
%import c64utils
|
||||||
%import c64flt
|
%import c64flt
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option enable_floats
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
|
ubyte counterb
|
||||||
|
uword counterw
|
||||||
|
|
||||||
ubyte wv
|
|
||||||
ubyte wv2
|
|
||||||
|
|
||||||
wv = wv + wv + wv
|
for counterb in 0 to 10 {
|
||||||
|
c64scr.print_ub(counterb)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
; wv *= wv2
|
for counterb in 10 to 30 {
|
||||||
;
|
c64scr.print_ub(counterb)
|
||||||
; wv += 10
|
c64.CHROUT(',')
|
||||||
; wv += 20
|
}
|
||||||
; wv += 30
|
c64.CHROUT('\n')
|
||||||
;
|
|
||||||
; wv += 1 + wv2
|
|
||||||
; wv += 2 + wv2
|
|
||||||
; wv += 3 + wv2
|
|
||||||
;
|
|
||||||
; wv += wv2 + 1
|
|
||||||
; wv += wv2 + 2
|
|
||||||
; wv += wv2 + 3
|
|
||||||
;
|
|
||||||
; wv = wv + 1 + wv2
|
|
||||||
; wv = wv + 2 + wv2
|
|
||||||
; wv = wv + 3 + wv2
|
|
||||||
;
|
|
||||||
; wv = 1 + wv2 + wv
|
|
||||||
; wv = 2 + wv2 + wv
|
|
||||||
; wv = 3 + wv2 + wv
|
|
||||||
;
|
|
||||||
; wv = wv + wv2 + 1
|
|
||||||
; wv = wv + wv2 + 2
|
|
||||||
; wv = wv + wv2 + 3
|
|
||||||
;
|
|
||||||
; wv = wv2 + 1 + wv
|
|
||||||
; wv = wv2 + 2 + wv
|
|
||||||
; wv = wv2 + 3 + wv
|
|
||||||
|
|
||||||
wv = wv2 + wv + 1
|
for counterb in 250 to 255 {
|
||||||
wv = wv2 + wv + 2
|
c64scr.print_ub(counterb)
|
||||||
wv = wv2 + wv + 3
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterb in 10 to 0 step -1 {
|
||||||
|
c64scr.print_ub(counterb)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterb in 10 to 1 step -1 {
|
||||||
|
c64scr.print_ub(counterb)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterb in 30 to 10 step -1 {
|
||||||
|
c64scr.print_ub(counterb)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterb in 255 to 250 step -1 {
|
||||||
|
c64scr.print_ub(counterb)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 0 to 10 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 10 to 30 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 250 to 255 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 10 to 0 step -1 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 10 to 1 step -1 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 30 to 10 step -1 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
|
|
||||||
|
for counterw in 255 to 250 step -1 {
|
||||||
|
c64scr.print_uw(counterw)
|
||||||
|
c64.CHROUT(',')
|
||||||
|
}
|
||||||
|
c64.CHROUT('\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,6 @@ statement :
|
|||||||
| repeatloop
|
| repeatloop
|
||||||
| whenstmt
|
| whenstmt
|
||||||
| breakstmt
|
| breakstmt
|
||||||
| continuestmt
|
|
||||||
| labeldef
|
| labeldef
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -214,8 +213,6 @@ returnstmt : 'return' expression? ;
|
|||||||
|
|
||||||
breakstmt : 'break';
|
breakstmt : 'break';
|
||||||
|
|
||||||
continuestmt: 'continue';
|
|
||||||
|
|
||||||
identifier : NAME ;
|
identifier : NAME ;
|
||||||
|
|
||||||
scoped_identifier : NAME ('.' NAME)* ;
|
scoped_identifier : NAME ('.' NAME)* ;
|
||||||
|
|||||||
Reference in New Issue
Block a user