From a983a896f2519f7263aff9474cfe4d4e4db1c5af Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 15 Aug 2019 23:52:52 +0200 Subject: [PATCH] some asm and some for loop asm fixed, renamed asmgen2 back to just asmgen --- compiler/src/prog8/ast/base/Extensions.kt | 2 +- compiler/src/prog8/compiler/Main.kt | 4 +- .../AnonymousScopeVarsCleanup.kt | 2 +- .../AsmGen2.kt => codegen/AsmGen.kt} | 240 ++++++++++++------ .../c64/{codegen2 => codegen}/AsmOptimizer.kt | 2 +- .../BuiltinFunctionsAsmGen.kt | 4 +- .../src/prog8/optimizer/ConstantFolding.kt | 2 +- .../src/prog8/optimizer/StatementOptimizer.kt | 2 +- examples/test.p8 | 72 ++++-- 9 files changed, 222 insertions(+), 108 deletions(-) rename compiler/src/prog8/compiler/target/c64/{codegen2 => codegen}/AnonymousScopeVarsCleanup.kt (97%) rename compiler/src/prog8/compiler/target/c64/{codegen2/AsmGen2.kt => codegen/AsmGen.kt} (95%) rename compiler/src/prog8/compiler/target/c64/{codegen2 => codegen}/AsmOptimizer.kt (99%) rename compiler/src/prog8/compiler/target/c64/{codegen2 => codegen}/BuiltinFunctionsAsmGen.kt (99%) diff --git a/compiler/src/prog8/ast/base/Extensions.kt b/compiler/src/prog8/ast/base/Extensions.kt index 96bcf6695..2e8d6dc09 100644 --- a/compiler/src/prog8/ast/base/Extensions.kt +++ b/compiler/src/prog8/ast/base/Extensions.kt @@ -4,7 +4,7 @@ import prog8.ast.Module import prog8.ast.Program import prog8.ast.processing.* import prog8.compiler.CompilationOptions -import prog8.compiler.target.c64.codegen2.AnonymousScopeVarsCleanup +import prog8.compiler.target.c64.codegen.AnonymousScopeVarsCleanup import prog8.optimizer.FlattenAnonymousScopesAndRemoveNops diff --git a/compiler/src/prog8/compiler/Main.kt b/compiler/src/prog8/compiler/Main.kt index d0daeaff4..304e34c7c 100644 --- a/compiler/src/prog8/compiler/Main.kt +++ b/compiler/src/prog8/compiler/Main.kt @@ -5,7 +5,7 @@ import prog8.ast.Program import prog8.ast.base.* import prog8.ast.statements.Directive import prog8.compiler.target.c64.MachineDefinition -import prog8.compiler.target.c64.codegen2.AsmGen2 +import prog8.compiler.target.c64.codegen.AsmGen import prog8.optimizer.constantFold import prog8.optimizer.optimizeStatements import prog8.optimizer.simplifyExpressions @@ -102,7 +102,7 @@ fun compileProgram(filepath: Path, // asm generation directly from the Ast, no need for intermediate code val zeropage = MachineDefinition.C64Zeropage(compilerOptions) programAst.anonscopeVarsCleanup() - val assembly = AsmGen2(programAst, compilerOptions, zeropage).compileToAssembly(optimize) + val assembly = AsmGen(programAst, compilerOptions, zeropage).compileToAssembly(optimize) assembly.assemble(compilerOptions) programName = assembly.name } diff --git a/compiler/src/prog8/compiler/target/c64/codegen2/AnonymousScopeVarsCleanup.kt b/compiler/src/prog8/compiler/target/c64/codegen/AnonymousScopeVarsCleanup.kt similarity index 97% rename from compiler/src/prog8/compiler/target/c64/codegen2/AnonymousScopeVarsCleanup.kt rename to compiler/src/prog8/compiler/target/c64/codegen/AnonymousScopeVarsCleanup.kt index efa721c78..0907e426e 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen2/AnonymousScopeVarsCleanup.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AnonymousScopeVarsCleanup.kt @@ -1,4 +1,4 @@ -package prog8.compiler.target.c64.codegen2 +package prog8.compiler.target.c64.codegen import prog8.ast.Program import prog8.ast.base.AstException diff --git a/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt similarity index 95% rename from compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt rename to compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index 0b549dd42..a29164a36 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen2/AsmGen2.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -1,4 +1,4 @@ -package prog8.compiler.target.c64.codegen2 +package prog8.compiler.target.c64.codegen import prog8.ast.IFunctionCall import prog8.ast.Node @@ -27,9 +27,9 @@ import kotlin.math.absoluteValue internal class AssemblyError(msg: String) : RuntimeException(msg) -internal class AsmGen2(val program: Program, - val options: CompilationOptions, - val zeropage: Zeropage) { +internal class AsmGen(val program: Program, + val options: CompilationOptions, + val zeropage: Zeropage) { private val assemblyLines = mutableListOf() private val globalFloatConsts = mutableMapOf() // all float values in the entire program (value -> varname) @@ -1065,7 +1065,8 @@ internal class AsmGen2(val program: Program, val counterLabel = makeLabel("for_counter") loopEndLabels.push(endLabel) loopContinueLabels.push(continueLabel) - when (range.step.constValue(program)?.number) { + val stepsize=range.step.constValue(program)?.number + when (stepsize) { 1 -> { when(iterableDt) { DataType.ARRAY_B, DataType.ARRAY_UB -> { @@ -1121,17 +1122,118 @@ $endLabel""") } } DataType.ARRAY_UW, DataType.ARRAY_W -> { - TODO("loop over word range") + translateExpression(range.to) + out(" inc $ESTACK_LO_HEX+1,x | bne + | inc $ESTACK_HI_HEX+1,x |+ ") + val varname = asmIdentifierName(stmt.loopVar!!) + val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position), + null, range.from, range.position) + assignLoopvar.linkParents(stmt) + translate(assignLoopvar) + out(loopLabel) + translate(stmt.body) + out(""" + inc $varname + bne + + inc $varname+1 ++ lda $ESTACK_HI_HEX+1,x + cmp $varname+1 + bne + + lda $ESTACK_LO_HEX+1,x + cmp $varname + beq $endLabel ++ jmp $loopLabel +$endLabel inx""") } else -> throw AssemblyError("range expression can only be byte or word") } } -1 -> { - TODO("non-const forloop with step -1") + when(iterableDt){ + DataType.ARRAY_B, DataType.ARRAY_UB -> { + if (stmt.loopRegister != null) { + // loop register over range + if(stmt.loopRegister!=Register.A) + throw AssemblyError("can only use A") + translateExpression(range.from) + translateExpression(range.to) + out(""" + inx + lda $ESTACK_LO_HEX+1,x + sta $loopLabel+1 + sec + sbc $ESTACK_LO_HEX,x + adc #0 + sta $counterLabel + inx +$loopLabel lda #0 ; modified""") + translate(stmt.body) + out(""" +$continueLabel dec $counterLabel + beq $endLabel + dec $loopLabel+1 + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } else { + // loop over byte range via loopvar + val varname = asmIdentifierName(stmt.loopVar!!) + translateExpression(range.from) + translateExpression(range.to) + out(""" + inx + lda $ESTACK_LO_HEX+1,x + sta $varname + sec + sbc $ESTACK_LO_HEX,x + adc #0 + sta $counterLabel + inx +$loopLabel""") + translate(stmt.body) + out(""" +$continueLabel dec $counterLabel + beq $endLabel + dec $varname + jmp $loopLabel +$counterLabel .byte 0 +$endLabel""") + } + } + DataType.ARRAY_UW, DataType.ARRAY_W -> { + translateExpression(range.to) + out(""" + lda $ESTACK_LO_HEX+1,x + bne + + dec $ESTACK_HI_HEX+1,x ++ dec $ESTACK_LO_HEX+1,x + """) + val varname = asmIdentifierName(stmt.loopVar!!) + val assignLoopvar = Assignment(AssignTarget(null, stmt.loopVar, null, null, stmt.loopVar!!.position), + null, range.from, range.position) + assignLoopvar.linkParents(stmt) + translate(assignLoopvar) + out(loopLabel) + translate(stmt.body) + out(""" + lda $varname + bne + + dec $varname+1 ++ dec $varname + lda $ESTACK_HI_HEX+1,x + cmp $varname+1 + bne + + lda $ESTACK_LO_HEX+1,x + cmp $varname + beq $endLabel ++ jmp $loopLabel +$endLabel inx""") + } + else -> throw AssemblyError("range expression can only be byte or word") + } } else -> when (iterableDt) { - DataType.ARRAY_UB, DataType.ARRAY_B -> TODO("non-const forloop bytes") - DataType.ARRAY_UW, DataType.ARRAY_W -> TODO("non-const forloop words") + DataType.ARRAY_UB, DataType.ARRAY_B -> TODO("non-const forloop bytes, step >1: $stepsize") + DataType.ARRAY_UW, DataType.ARRAY_W -> TODO("non-const forloop words, step >1: $stepsize") else -> throw AssemblyError("range expression can only be byte or word") } } @@ -1238,14 +1340,15 @@ $endLabel""") } private fun translateForOverConstRange(stmt: ForLoop, iterableDt: DataType, range: IntProgression) { + // TODO: optimize loop code when the range is < 256 iterations, don't need a separate counter in such cases val loopLabel = makeLabel("for_loop") val endLabel = makeLabel("for_end") val continueLabel = makeLabel("for_continue") - val counterLabel = makeLabel("for_counter") loopEndLabels.push(endLabel) loopContinueLabels.push(continueLabel) when(iterableDt) { DataType.ARRAY_B, DataType.ARRAY_UB -> { + val counterLabel = makeLabel("for_counter") if(stmt.loopRegister!=null) { // loop register over range @@ -1412,97 +1515,59 @@ $endLabel""") val varname = asmIdentifierName(stmt.loopVar!!) when { range.step == 1 -> { - // step = 1 + // word, step = 1 + val lastValue = range.last+1 out(""" lda #<${range.first} ldy #>${range.first} sta $varname sty $varname+1 - lda #${range.last - range.first + 1 and 255} - sta $counterLabel $loopLabel""") translate(stmt.body) out(""" -$continueLabel dec $counterLabel - beq $endLabel - inc $varname - bne $loopLabel +$continueLabel inc $varname + bne + inc $varname+1 - jmp $loopLabel -$counterLabel .byte 0 ++ lda $varname + cmp #<$lastValue + bne + + lda $varname+1 + cmp #>$lastValue + beq $endLabel ++ jmp $loopLabel $endLabel""") } range.step == -1 -> { - // step = 1 + // word, step = 1 + val lastValue = range.last-1 out(""" lda #<${range.first} ldy #>${range.first} sta $varname sty $varname+1 - lda #${range.first - range.last + 1 and 255} - sta $counterLabel $loopLabel""") translate(stmt.body) out(""" -$continueLabel dec $counterLabel - beq $endLabel - lda $varname +$continueLabel lda $varname bne + dec $varname+1 -+ dec $varname - jmp $loopLabel -$counterLabel .byte 0 ++ dec $varname + lda $varname + cmp #<$lastValue + bne + + lda $varname+1 + cmp #>$lastValue + beq $endLabel ++ jmp $loopLabel $endLabel""") } range.step >= 2 -> { - // step >= 2 - out(""" - lda #<${range.first} - ldy #>${range.first} - sta $varname - sty $varname+1 - lda #${(range.last-range.first) / range.step + 1} - sta $counterLabel -$loopLabel""") - translate(stmt.body) - out(""" -$continueLabel dec $counterLabel - beq $endLabel - clc - lda $varname - adc #<${range.step} - sta $varname - lda $varname+1 - adc #>${range.step} - sta $varname+1 - jmp $loopLabel -$counterLabel .byte 0 -$endLabel""") + // word, step >= 2 + TODO("for, word, step>=2") } else -> { // step <= -2 - out(""" - lda #<${range.first} - ldy #>${range.first} - sta $varname - sty $varname+1 - lda #${(range.first-range.last) / range.step.absoluteValue + 1} - sta $counterLabel -$loopLabel""") - translate(stmt.body) - out(""" -$continueLabel dec $counterLabel - beq $endLabel - sec - lda $varname - sbc #<${range.step.absoluteValue} - sta $varname - lda $varname+1 - sbc #>${range.step.absoluteValue} - sta $varname+1 - jmp $loopLabel -$counterLabel .byte 0 -$endLabel""") + TODO("for, word, step<=-2") } } } @@ -2518,7 +2583,34 @@ $endLabel""") addressLv != null -> out(" st$registerName ${addressLv.number.toHex()}") addressExpr is IdentifierReference -> { val targetName = asmIdentifierName(addressExpr) - out(" st$registerName $targetName") + when(register) { + Register.A -> out(""" + ldy $targetName + sty ${C64Zeropage.SCRATCH_W1} + ldy $targetName+1 + sty ${C64Zeropage.SCRATCH_W1+1} + ldy #0 + sta (${C64Zeropage.SCRATCH_W1}),y + """) + Register.X -> out(""" + txa + ldy $targetName + sty ${C64Zeropage.SCRATCH_W1} + ldy $targetName+1 + sty ${C64Zeropage.SCRATCH_W1+1} + ldy #0 + sta (${C64Zeropage.SCRATCH_W1}),y + """) + Register.Y -> out(""" + tya + ldy $targetName + sty ${C64Zeropage.SCRATCH_W1} + ldy $targetName+1 + sty ${C64Zeropage.SCRATCH_W1+1} + ldy #0 + sta (${C64Zeropage.SCRATCH_W1}),y + """) + } } else -> { saveRegister(register) diff --git a/compiler/src/prog8/compiler/target/c64/codegen2/AsmOptimizer.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt similarity index 99% rename from compiler/src/prog8/compiler/target/c64/codegen2/AsmOptimizer.kt rename to compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt index a0eb3be0a..61295a3e7 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen2/AsmOptimizer.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt @@ -1,4 +1,4 @@ -package prog8.compiler.target.c64.codegen2 +package prog8.compiler.target.c64.codegen import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_HEX import prog8.compiler.target.c64.MachineDefinition.ESTACK_LO_PLUS1_HEX diff --git a/compiler/src/prog8/compiler/target/c64/codegen2/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt similarity index 99% rename from compiler/src/prog8/compiler/target/c64/codegen2/BuiltinFunctionsAsmGen.kt rename to compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 176376a4d..5ba9da502 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen2/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -1,4 +1,4 @@ -package prog8.compiler.target.c64.codegen2 +package prog8.compiler.target.c64.codegen import prog8.ast.IFunctionCall import prog8.ast.Program @@ -21,7 +21,7 @@ import prog8.functions.FunctionSignature internal class BuiltinFunctionsAsmGen(private val program: Program, private val options: CompilationOptions, private val zeropage: Zeropage, - private val asmgen: AsmGen2) { + private val asmgen: AsmGen) { internal fun translateFunctioncallExpression(fcall: FunctionCall, func: FunctionSignature) { translateFunctioncall(fcall, func, false) diff --git a/compiler/src/prog8/optimizer/ConstantFolding.kt b/compiler/src/prog8/optimizer/ConstantFolding.kt index 0b73f571f..dcdafb233 100644 --- a/compiler/src/prog8/optimizer/ConstantFolding.kt +++ b/compiler/src/prog8/optimizer/ConstantFolding.kt @@ -9,7 +9,7 @@ import prog8.ast.processing.fixupArrayDatatype import prog8.ast.statements.* import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_NEGATIVE import prog8.compiler.target.c64.MachineDefinition.FLOAT_MAX_POSITIVE -import prog8.compiler.target.c64.codegen2.AssemblyError +import prog8.compiler.target.c64.codegen.AssemblyError import prog8.functions.BuiltinFunctions import kotlin.math.floor diff --git a/compiler/src/prog8/optimizer/StatementOptimizer.kt b/compiler/src/prog8/optimizer/StatementOptimizer.kt index 5842228c8..16b7628ea 100644 --- a/compiler/src/prog8/optimizer/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizer/StatementOptimizer.kt @@ -10,7 +10,7 @@ import prog8.ast.processing.IAstModifyingVisitor import prog8.ast.processing.IAstVisitor import prog8.ast.statements.* import prog8.compiler.target.c64.Petscii -import prog8.compiler.target.c64.codegen2.AssemblyError +import prog8.compiler.target.c64.codegen.AssemblyError import prog8.functions.BuiltinFunctions import kotlin.math.floor diff --git a/examples/test.p8 b/examples/test.p8 index e7c22c18e..d52107157 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,32 +7,54 @@ main { sub start() { - uword uw - ubyte ub + uword start=1027 + uword stop=2020 + uword i + ubyte ib -; uw = uw>>0 -; uw = uw>>7 - ub = uw>>8 as ubyte - A++ - uw = uw>>8 - A++ - uw = msb(uw) + c64scr.print("\n\n\n\n\n\n\n\n") + memset($0400, 40*25, 30) + + ubyte ibstart = 1 + for ib in ibstart to 255-ibstart { + @(ib+1024) = 44 + } + + for ib in 253 to 2 step -1 { + @(ib+1024) = 3 + } + + ibstart = 3 + for ib in 255-ibstart to ibstart step -1 { + @(ib+1024) = 45 + } + + + for i in 1025 to 2022 { + @(i) = 1 + } + + for i in 2021 to 1026 step -1 { + @(i) = 92 + } + + for i in start to stop { + @(i) = 0 + } + + for i in stop-1 to start+1 step -1 { + @(i) = 91 + } + + + ubyte xx=X + c64scr.print_ub(xx) + + +; for i in stop to start { +; c64scr.print_uw(i) +; c64.CHROUT(',') +; } -; uw <<= 1 -; uw >>= 1 -; -; ub <<= 1 -; ub >>= 1 -; -; uw *= 2 -; ub *= 2 } - - - asmsub aa(byte arg @ Y) clobbers() { - %asm {{ - rts - }} - } - }