removed 'continue' statement to be able to generate more optimized loop assembly code. started with for loop optimizations

This commit is contained in:
Irmen de Jong 2020-08-17 18:42:02 +02:00
parent f14dda4eca
commit c0887b5f08
16 changed files with 437 additions and 201 deletions

View File

@ -305,10 +305,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
output(postIncrDecr.operator)
}
override fun visit(contStmt: Continue) {
output("continue")
}
override fun visit(breakStmt: Break) {
output("break")
}

View File

@ -217,9 +217,6 @@ private fun prog8Parser.StatementContext.toAst() : Statement {
val breakstmt = breakstmt()?.toAst()
if(breakstmt!=null) return breakstmt
val continuestmt = continuestmt()?.toAst()
if(continuestmt!=null) return continuestmt
val whenstmt = whenstmt()?.toAst()
if(whenstmt!=null) return whenstmt
@ -593,8 +590,6 @@ private fun prog8Parser.ForloopContext.toAst(): ForLoop {
return ForLoop(loopvar, iterable, scope, toPosition())
}
private fun prog8Parser.ContinuestmtContext.toAst() = Continue(toPosition())
private fun prog8Parser.BreakstmtContext.toAst() = Break(toPosition())
private fun prog8Parser.WhileloopContext.toAst(): WhileLoop {

View File

@ -88,7 +88,6 @@ abstract class AstWalker {
open fun before(branchStatement: BranchStatement, 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(contStmt: Continue, 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(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(breakStmt: Break, 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(directive: Directive, 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)
}
fun visit(contStmt: Continue, parent: Node) {
track(before(contStmt, parent), contStmt, parent)
track(after(contStmt, parent), contStmt, parent)
}
fun visit(breakStmt: Break, parent: Node) {
track(before(breakStmt, parent), breakStmt, parent)
track(after(breakStmt, parent), breakStmt, parent)

View File

@ -95,9 +95,6 @@ interface IAstVisitor {
postIncrDecr.target.accept(this)
}
fun visit(contStmt: Continue) {
}
fun visit(breakStmt: Break) {
}

View File

@ -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")
}
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() {
override lateinit var parent: Node

View File

@ -43,13 +43,11 @@ internal class AsmGen(private val program: Program,
private val assignmentAsmGen = AssignmentAsmGen(program, errors, this)
private val expressionsAsmGen = ExpressionsAsmGen(program, this)
internal val loopEndLabels = ArrayDeque<String>()
internal val loopContinueLabels = ArrayDeque<String>()
internal val blockLevelVarInits = mutableMapOf<Block, MutableSet<VarDecl>>()
override fun compileToAssembly(optimize: Boolean): IAssemblyProgram {
assemblyLines.clear()
loopEndLabels.clear()
loopContinueLabels.clear()
println("Generating assembly code... ")
@ -638,7 +636,6 @@ internal class AsmGen(private val program: Program,
is BranchStatement -> translate(stmt)
is IfStatement -> translate(stmt)
is ForLoop -> forloopsAsmGen.translate(stmt)
is Continue -> out(" jmp ${loopContinueLabels.peek()}")
is Break -> out(" jmp ${loopEndLabels.peek()}")
is WhileLoop -> translate(stmt)
is RepeatLoop -> translate(stmt)
@ -674,11 +671,11 @@ internal class AsmGen(private val program: Program,
}
private fun translate(stmt: RepeatLoop) {
// TODO more optimized code possible now that continue is gone?
val repeatLabel = makeLabel("repeat")
val endLabel = makeLabel("repeatend")
val counterLabel = makeLabel("repeatcounter")
loopEndLabels.push(endLabel)
loopContinueLabels.push(repeatLabel)
when (stmt.iterations) {
null -> {
@ -737,7 +734,6 @@ internal class AsmGen(private val program: Program,
}
loopEndLabels.pop()
loopContinueLabels.pop()
}
private fun repeatWordCountInAY(counterVar: String, repeatLabel: String, endLabel: String, body: AnonymousScope) {
@ -778,10 +774,10 @@ $endLabel""")
}
private fun translate(stmt: WhileLoop) {
// TODO more optimized code possible now that continue is gone?
val whileLabel = makeLabel("while")
val endLabel = makeLabel("whileend")
loopEndLabels.push(endLabel)
loopContinueLabels.push(whileLabel)
out(whileLabel)
expressionsAsmGen.translateExpression(stmt.condition)
val conditionDt = stmt.condition.inferType(program)
@ -802,14 +798,13 @@ $endLabel""")
out(" jmp $whileLabel")
out(endLabel)
loopEndLabels.pop()
loopContinueLabels.pop()
}
private fun translate(stmt: UntilLoop) {
// TODO more optimized code possible now that continue is gone?
val repeatLabel = makeLabel("repeat")
val endLabel = makeLabel("repeatend")
loopEndLabels.push(endLabel)
loopContinueLabels.push(repeatLabel)
out(repeatLabel)
translate(stmt.body)
expressionsAsmGen.translateExpression(stmt.untilCondition)
@ -829,7 +824,6 @@ $endLabel""")
}
out(endLabel)
loopEndLabels.pop()
loopContinueLabels.pop()
}
private fun translate(stmt: WhenStatement) {

View File

@ -14,9 +14,8 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX
import prog8.compiler.toHex
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 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
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) {
// TODO more optimized code possible now that continue is gone?
val loopLabel = asmgen.makeLabel("for_loop")
val endLabel = asmgen.makeLabel("for_end")
val continueLabel = asmgen.makeLabel("for_continue")
asmgen.loopEndLabels.push(endLabel)
asmgen.loopContinueLabels.push(continueLabel)
val stepsize=range.step.constValue(program)!!.number.toInt()
when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> {
@ -66,7 +65,7 @@ internal class ForLoopsAsmGen(private val program: Program, private val asmgen:
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $varname
lda $varname
cmp $ESTACK_LO_PLUS1_HEX,x
beq $endLabel
$incdec $varname
@ -88,7 +87,7 @@ $endLabel inx""")
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel lda $varname""")
lda $varname""")
if(stepsize>0) {
asmgen.out("""
clc
@ -248,15 +247,13 @@ $endLabel inx""")
}
asmgen.loopEndLabels.pop()
asmgen.loopContinueLabels.pop()
}
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 endLabel = asmgen.makeLabel("for_end")
val continueLabel = asmgen.makeLabel("for_continue")
asmgen.loopEndLabels.push(endLabel)
asmgen.loopContinueLabels.push(continueLabel)
val iterableName = asmgen.asmIdentifierName(ident)
val decl = ident.targetVarDecl(program.namespace)!!
when(iterableDt) {
@ -271,7 +268,7 @@ $loopLabel lda ${65535.toHex()} ; modified
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel inc $loopLabel+1
inc $loopLabel+1
bne $loopLabel
inc $loopLabel+2
bne $loopLabel
@ -293,7 +290,7 @@ $modifiedLabel lda ${65535.toHex()},y ; modified""")
asmgen.out(" sta ${asmgen.asmIdentifierName(stmt.loopVar)}")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel ldy $counterLabel
ldy $counterLabel
iny
cpy #${length and 255}
beq $endLabel
@ -325,7 +322,7 @@ $modifiedLabel2 lda ${65535.toHex()},y ; modified
sta $loopvarName+1""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel ldy $counterLabel
ldy $counterLabel
iny
iny
cpy #${length and 255}
@ -340,57 +337,34 @@ $endLabel""")
else -> throw AssemblyError("can't iterate over $iterableDt")
}
asmgen.loopEndLabels.pop()
asmgen.loopContinueLabels.pop()
}
private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) {
// TODO: optimize loop code when the range is < 256 iterations
if (range.isEmpty())
throw AssemblyError("empty range")
if (range.isEmpty() || range.step==0)
throw AssemblyError("empty range or step 0")
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 endLabel = asmgen.makeLabel("for_end")
val continueLabel = asmgen.makeLabel("for_continue")
asmgen.loopEndLabels.push(endLabel)
asmgen.loopContinueLabels.push(continueLabel)
// TODO more optimized code possible now that continue is gone?
when(iterableDt) {
DataType.ARRAY_B, DataType.ARRAY_UB -> {
// loop over byte range via loopvar, step > 1 or < -1
val counterLabel = asmgen.makeLabel("for_counter")
// loop over byte range via loopvar
val varname = asmgen.asmIdentifierName(stmt.loopVar)
when {
range.step==1 -> {
// step = 1
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==1 || range.step==-1 -> {
throw AssemblyError("step 1 and -1 should have been handled specifically")
}
range.step >= 2 -> {
// step >= 2
@ -402,7 +376,7 @@ $endLabel""")
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
dec $counterLabel
beq $endLabel
lda $varname
clc
@ -422,7 +396,7 @@ $endLabel""")
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel dec $counterLabel
dec $counterLabel
beq $endLabel
lda $varname
sec
@ -435,56 +409,59 @@ $endLabel""")
}
}
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)
when {
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 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 || range.step==-1 -> {
throw AssemblyError("step 1 and -1 should have been handled specifically")
}
// 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 -> {
// word, step >= 2
// 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""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel clc
clc
lda $varname
adc #<${range.step}
sta $varname
@ -525,7 +502,7 @@ $endLabel""")
$loopLabel""")
asmgen.translate(stmt.body)
asmgen.out("""
$continueLabel sec
sec
lda $varname
sbc #<${range.step.absoluteValue}
sta $varname
@ -546,7 +523,102 @@ $endLabel""")
else -> throw AssemblyError("range expression can only be byte or word")
}
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")
}
}

View File

@ -14,11 +14,6 @@ import prog8.functions.BuiltinFunctions
import kotlin.math.floor
/*
TODO: remove unreachable code after return and exit()
*/
internal class StatementOptimizer(private val program: Program,
private val errors: ErrorReporter) : AstWalker() {
@ -257,9 +252,9 @@ internal class StatementOptimizer(private val program: Program,
val constvalue = untilLoop.untilCondition.constValue(program)
if(constvalue!=null) {
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)
if(!hasContinueOrBreak(untilLoop.body))
if(!hasBreak(untilLoop.body))
return listOf(IAstModification.ReplaceNode(untilLoop, untilLoop.body, parent))
} else {
// always false
@ -495,7 +490,7 @@ internal class StatementOptimizer(private val program: Program,
return linesToRemove
}
private fun hasContinueOrBreak(scope: INameScope): Boolean {
private fun hasBreak(scope: INameScope): Boolean {
class Searcher: IAstVisitor
{
@ -504,10 +499,6 @@ internal class StatementOptimizer(private val program: Program,
override fun visit(breakStmt: Break) {
count++
}
override fun visit(contStmt: Continue) {
count++
}
}
val s=Searcher()

View File

@ -6,6 +6,9 @@ import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification
import prog8.ast.statements.Block
/*
TODO: remove unreachable code after return and exit()
*/
internal class UnusedCodeRemover: AstWalker() {

View File

@ -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.
Breaking out of a loop prematurely is possible with the ``break`` statement.
.. 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!

View File

@ -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> ] {
; do something...
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::
@ -592,7 +591,6 @@ You can use a single statement, or a statement block like in the example below::
while <condition> {
; do something...
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 something...
break ; break out of the loop
continue ; immediately enter next iteration
} until <condition>

View File

@ -2,9 +2,10 @@
TODO
====
- finalize (most) of the still missing "new" assignment asm code generation
- aliases for imported symbols for example perhaps '%alias print = c64scr.print'
- option to load library files from a directory instead of the embedded ones (easier library development/debugging)
- get rid of all TODO's ;-)
- allow declaring arrays on specific memory location and page-aligned
- 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
- see if we can group some errors together for instance the (now single) errors about unidentified symbols

View 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)
}
}

View 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)
}
}

View File

@ -2,49 +2,97 @@
%import c64utils
%import c64flt
%zeropage basicsafe
%option enable_floats
main {
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
;
; wv += 10
; wv += 20
; wv += 30
;
; 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
for counterb in 10 to 30 {
c64scr.print_ub(counterb)
c64.CHROUT(',')
}
c64.CHROUT('\n')
wv = wv2 + wv + 1
wv = wv2 + wv + 2
wv = wv2 + wv + 3
for counterb in 250 to 255 {
c64scr.print_ub(counterb)
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')
}
}

View File

@ -98,7 +98,6 @@ statement :
| repeatloop
| whenstmt
| breakstmt
| continuestmt
| labeldef
;
@ -214,8 +213,6 @@ returnstmt : 'return' expression? ;
breakstmt : 'break';
continuestmt: 'continue';
identifier : NAME ;
scoped_identifier : NAME ('.' NAME)* ;