From a03e36828a396b63688d79992c245a16e75fd756 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 16 Oct 2020 01:12:20 +0200 Subject: [PATCH] fixed lines in assembly source optimizer --- compiler/res/prog8lib/prog8_lib.asm | 32 ++++++++++++++ compiler/res/prog8lib/prog8_lib.p8 | 16 +++++++ .../compiler/target/c64/codegen/AsmGen.kt | 15 ++++--- .../target/c64/codegen/AsmOptimizer.kt | 4 +- compiler/src/prog8/optimizer/CallGraph.kt | 13 +++--- examples/test.p8 | 44 ++----------------- 6 files changed, 72 insertions(+), 52 deletions(-) diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index 9f04644af..52dbb042d 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -1990,6 +1990,38 @@ strcpy .proc .pend +strcmp_mem .proc + ; -- compares strings in s1 (AY) and s2 (PZP_SCRATCH_W2). + ; Returns -1,0,1 in A, depeding on the ordering. Clobbers Y. + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 +_loop ldy #0 + lda (P8ZP_SCRATCH_W1),y + bne + + lda (P8ZP_SCRATCH_W2),y + bne _return_minusone + beq _return ++ lda (P8ZP_SCRATCH_W2),y + sec + sbc (P8ZP_SCRATCH_W1),y + bmi _return_one + bne _return_minusone + inc P8ZP_SCRATCH_W1 + bne + + inc P8ZP_SCRATCH_W1+1 ++ inc P8ZP_SCRATCH_W2 + bne _loop + inc P8ZP_SCRATCH_W2+1 + bne _loop +_return_one + lda #1 +_return rts +_return_minusone + lda #-1 + rts + .pend + + func_leftstr .proc ; leftstr(source, target, length) with params on stack inx diff --git a/compiler/res/prog8lib/prog8_lib.p8 b/compiler/res/prog8lib/prog8_lib.p8 index 4424c1d3e..66b109a03 100644 --- a/compiler/res/prog8lib/prog8_lib.p8 +++ b/compiler/res/prog8lib/prog8_lib.p8 @@ -6,4 +6,20 @@ prog8_lib { %asminclude "library:prog8_lib.asm", "" + + sub strcmp(uword s1, uword s2) -> byte { + ; -- convenience wrapper for plain Prog8 to compare strings TODO turn this into a builtin function + byte result + %asm {{ + lda s2 + sta P8ZP_SCRATCH_W2 + lda s2+1 + sta P8ZP_SCRATCH_W2+1 + lda s1 + ldy s1+1 + jsr prog8_lib.strcmp_mem + sta result + }} + return result + } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index eb59eba48..5348aa93d 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -66,16 +66,21 @@ internal class AsmGen(private val program: Program, block2asm(b) footer() + val outputFile = outputDir.resolve("${program.name}.asm").toFile() + outputFile.printWriter().use { + for (line in assemblyLines) { it.println(line) } + } + if(optimize) { + assemblyLines.clear() + assemblyLines.addAll(outputFile.readLines()) var optimizationsDone = 1 while (optimizationsDone > 0) { optimizationsDone = optimizeAssembly(assemblyLines) } - } - - val outputFile = outputDir.resolve("${program.name}.asm").toFile() - outputFile.printWriter().use { - for (line in assemblyLines) { it.println(line) } + outputFile.printWriter().use { + for (line in assemblyLines) { it.println(line) } + } } return AssemblyProgram(program.name, outputDir) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt index 188bc9f76..8680a7650 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmOptimizer.kt @@ -196,8 +196,8 @@ private fun optimizeStoreLoadSame(linesByFour: List>>) (first.startsWith("sty ") && second.startsWith("ldy ")) || (first.startsWith("stx ") && second.startsWith("ldx ")) ) { - val firstLoc = first.substring(4) - val secondLoc = second.substring(4) + val firstLoc = first.substring(4).trimStart() + val secondLoc = second.substring(4).trimStart() if (firstLoc == secondLoc) { mods.add(Modification(pair[1].index, true, null)) } diff --git a/compiler/src/prog8/optimizer/CallGraph.kt b/compiler/src/prog8/optimizer/CallGraph.kt index 97c3a9468..7b65aad54 100644 --- a/compiler/src/prog8/optimizer/CallGraph.kt +++ b/compiler/src/prog8/optimizer/CallGraph.kt @@ -168,12 +168,12 @@ class CallGraph(private val program: Program) : IAstVisitor { override fun visit(inlineAssembly: InlineAssembly) { // parse inline asm for subroutine calls (jmp, jsr) - val scope = inlineAssembly.definingSubroutine()!! + val scope = inlineAssembly.definingSubroutine() scanAssemblyCode(inlineAssembly.assembly, inlineAssembly, scope) super.visit(inlineAssembly) } - private fun scanAssemblyCode(asm: String, context: Statement, scope: Subroutine) { + private fun scanAssemblyCode(asm: String, context: Statement, scope: Subroutine?) { asm.lines().forEach { line -> val matches = asmJumpRx.matchEntire(line) if (matches != null) { @@ -181,13 +181,15 @@ class CallGraph(private val program: Program) : IAstVisitor { if (jumptarget != null && (jumptarget[0].isLetter() || jumptarget[0] == '_')) { val node = program.namespace.lookup(jumptarget.split('.'), context) if (node is Subroutine) { - calls[scope] = calls.getValue(scope).plus(node) + if(scope!=null) + calls[scope] = calls.getValue(scope).plus(node) calledBy[node] = calledBy.getValue(node).plus(context) } else if (jumptarget.contains('.')) { // maybe only the first part already refers to a subroutine val node2 = program.namespace.lookup(listOf(jumptarget.substringBefore('.')), context) if (node2 is Subroutine) { - calls[scope] = calls.getValue(scope).plus(node2) + if(scope!=null) + calls[scope] = calls.getValue(scope).plus(node2) calledBy[node2] = calledBy.getValue(node2).plus(context) } } @@ -200,7 +202,8 @@ class CallGraph(private val program: Program) : IAstVisitor { if (target.contains('.')) { val node = program.namespace.lookup(listOf(target.substringBefore('.')), context) if (node is Subroutine) { - calls[scope] = calls.getValue(scope).plus(node) + if(scope!=null) + calls[scope] = calls.getValue(scope).plus(node) calledBy[node] = calledBy.getValue(node).plus(context) } } diff --git a/examples/test.p8 b/examples/test.p8 index 7871698d4..5f8157407 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -13,58 +13,22 @@ main { str hex4 = "aap3333" byte result - result = strcmp(hex1, hex1) + result = prog8_lib.strcmp(hex1, hex1) txt.print_b(result) txt.chrout('\n') - result = strcmp(hex1, hex2) + result = prog8_lib.strcmp(hex1, hex2) txt.print_b(result) txt.chrout('\n') - result = strcmp(hex1, hex3) + result = prog8_lib.strcmp(hex1, hex3) txt.print_b(result) txt.chrout('\n') - result = strcmp(hex1, hex4) + result = prog8_lib.strcmp(hex1, hex4) txt.print_b(result) txt.chrout('\n') testX() } - sub strcmp(uword s1, uword s2) -> byte { - byte result = 0 - - %asm {{ -_loop ldy #0 - lda (s1),y - bne + - lda (s2),y - bne _return_minusone - beq _return -+ lda (s2),y - sec - sbc (s1),y - bmi _return_one - bne _return_minusone - inc s1 - bne + - inc s1+1 -+ inc s2 - bne _loop - inc s2+1 - bne _loop - -_return_one - ldy #1 - sty result - bne _return -_return_minusone - ldy #-1 - sty result -_return - }} - - return result - } - asmsub testX() { %asm {{ stx _saveX