diff --git a/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt b/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt index e3c3c438c..4968d4cea 100644 --- a/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt +++ b/codeGeneration/src/prog8/codegen/target/cbm/AssemblyProgram.kt @@ -3,10 +3,10 @@ package prog8.codegen.target.cbm import com.github.michaelbull.result.Ok import com.github.michaelbull.result.Result import com.github.michaelbull.result.mapError +import prog8.codegen.target.cpu6502.codegen.generatedLabelPrefix import prog8.compilerinterface.CompilationOptions import prog8.compilerinterface.IAssemblyProgram import prog8.compilerinterface.OutputType -import prog8.compilerinterface.generatedLabelPrefix import prog8.parser.SourceCode import java.io.File import java.nio.file.Path diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt index 97331ec33..27d575214 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt @@ -29,6 +29,11 @@ import kotlin.io.path.writeLines import kotlin.math.absoluteValue +const val generatedLabelPrefix = "prog8_label_" +const val subroutineFloatEvalResultVar1 = "prog8_float_eval_result1" +const val subroutineFloatEvalResultVar2 = "prog8_float_eval_result2" + + class AsmGen(private val program: Program, val errors: IErrorReporter, val zeropage: Zeropage, @@ -196,9 +201,9 @@ class AsmGen(private val program: Program, out("* = ${program.actualLoadAddress.toHex()}") val year = LocalDate.now().year out(" .word (+), $year") - out(" .null $9e, format(' %d ', _prog8_entrypoint), $3a, $8f, ' prog8'") + out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'") out("+\t.word 0") - out("_prog8_entrypoint\t; assembly code starts here\n") + out("prog8_entrypoint\t; assembly code starts here\n") if(!options.noSysInit) out(" jsr ${compTarget.name}.init_system") out(" jsr ${compTarget.name}.init_system_phase2") @@ -620,34 +625,16 @@ class AsmGen(private val program: Program, return identifier.nameInSource.joinToString(".") val tgt2 = identifier.targetStatement(program) - if (tgt2 == null && (identifier.nameInSource[0].startsWith("_prog8") || identifier.nameInSource[0].startsWith( - "prog8" - )) - ) + if (tgt2 == null && (identifier.nameInSource[0].startsWith("prog8"))) return identifier.nameInSource.joinToString(".") val target = identifier.targetStatement(program)!! val targetScope = target.definingSubroutine val identScope = identifier.definingSubroutine - return if (targetScope !== identScope) { - val scopedName = (target as INamedStatement).scopedName - if (target is Label) { - // make labels locally scoped in the asm. Is slightly problematic, see GitHub issue #62 - val newName = scopedName.dropLast(1) + ("_${scopedName.last()}") - fixNameSymbols(newName.joinToString(".")) - } - else { - fixNameSymbols(scopedName.joinToString(".")) - } - } else { - if (target is Label) { - // make labels locally scoped in the asm. Is slightly problematic, see GitHub issue #62 - val scopedName = identifier.nameInSource.toMutableList() - val last = scopedName.removeLast() - scopedName.add("_$last") - fixNameSymbols(scopedName.joinToString(".")) - } else fixNameSymbols(identifier.nameInSource.joinToString(".")) - } + return if (targetScope !== identScope) + fixNameSymbols((target as INamedStatement).scopedName.joinToString(".")) + else + fixNameSymbols(identifier.nameInSource.joinToString(".")) } return fixNameSymbols(internalName()) @@ -789,11 +776,11 @@ class AsmGen(private val program: Program, out(" pha") } CpuRegister.X -> { - out(" stx _prog8_regsaveX") + out(" stx prog8_regsaveX") scope.asmGenInfo.usedRegsaveX = true } CpuRegister.Y -> { - out(" sty _prog8_regsaveY") + out(" sty prog8_regsaveY") scope.asmGenInfo.usedRegsaveY = true } } @@ -836,8 +823,8 @@ class AsmGen(private val program: Program, } else { when (register) { CpuRegister.A -> out(" pla") // this just used the stack but only for A - CpuRegister.X -> out(" ldx _prog8_regsaveX") - CpuRegister.Y -> out(" ldy _prog8_regsaveY") + CpuRegister.X -> out(" ldx prog8_regsaveX") + CpuRegister.Y -> out(" ldy prog8_regsaveY") } } } @@ -1163,12 +1150,12 @@ class AsmGen(private val program: Program, else -> throw AssemblyError("weird dt") } } - if(sub.asmGenInfo.usedRegsaveA) - out("_prog8_regsaveA .byte 0") + if(sub.asmGenInfo.usedRegsaveA) // will probably never occur + out("prog8_regsaveA .byte 0") if(sub.asmGenInfo.usedRegsaveX) - out("_prog8_regsaveX .byte 0") + out("prog8_regsaveX .byte 0") if(sub.asmGenInfo.usedRegsaveY) - out("_prog8_regsaveY .byte 0") + out("prog8_regsaveY .byte 0") if(sub.asmGenInfo.usedFloatEvalResultVar1) out("$subroutineFloatEvalResultVar1 .byte 0,0,0,0,0") if(sub.asmGenInfo.usedFloatEvalResultVar2) @@ -1561,8 +1548,7 @@ $repeatLabel lda $counterVar } private fun translate(stmt: Label) { - // underscore prefix to make sure it's a local label. Is slightly problematic, see GitHub issue #62 - out("_${stmt.name}") + out(stmt.name) } private fun translate(scope: AnonymousScope) { @@ -1636,6 +1622,9 @@ $repeatLabel lda $counterVar "%breakpoint" -> { val label = "_prog8_breakpoint_${breakpointLabels.size+1}" breakpointLabels.add(label) + + // TODO still need 2 nops to make 64tass generate correc breakpoint list for vice??? + out(""" nop $label nop""") diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt index 11c0e6ca0..dd3b1d63c 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/BuiltinFunctionsAsmGen.kt @@ -16,7 +16,7 @@ import prog8.codegen.target.cpu6502.codegen.assignment.* import prog8.compilerinterface.BuiltinFunctions import prog8.compilerinterface.CpuType import prog8.compilerinterface.FSignature -import prog8.compilerinterface.subroutineFloatEvalResultVar2 + internal class BuiltinFunctionsAsmGen(private val program: Program, private val asmgen: AsmGen, private val assignAsmGen: AssignmentAsmGen) { diff --git a/compiler/res/prog8lib/c64/graphics.p8 b/compiler/res/prog8lib/c64/graphics.p8 index 4065d1b0f..ca9b6bf98 100644 --- a/compiler/res/prog8lib/c64/graphics.p8 +++ b/compiler/res/prog8lib/c64/graphics.p8 @@ -163,7 +163,7 @@ graphics { lda addr+1 sta P8ZP_SCRATCH_W1+1 ldy separate_pixels - lda _filled_right,y + lda hline_filled_right,y eor #255 ldy #0 ora (P8ZP_SCRATCH_W1),y @@ -207,18 +207,18 @@ _modified stx $ffff ; modified _zero ldx P8ZP_SCRATCH_REG ldy separate_pixels - beq _zero2 + beq hline_zero2 lda _modified+1 sta P8ZP_SCRATCH_W1 lda _modified+2 sta P8ZP_SCRATCH_W1+1 - lda _filled_right,y + lda hline_filled_right,y ldy #0 ora (P8ZP_SCRATCH_W1),y sta (P8ZP_SCRATCH_W1),y - jmp _zero2 -_filled_right .byte 0, %10000000, %11000000, %11100000, %11110000, %11111000, %11111100, %11111110 -_zero2 + jmp hline_zero2 +hline_filled_right .byte 0, %10000000, %11000000, %11100000, %11110000, %11111000, %11111100, %11111110 +hline_zero2 }} } } diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index ece443fdd..92433b7b6 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -242,18 +242,18 @@ close_end: void c64.CHKIN(11) ; use #11 as input channel again %asm {{ lda bufferpointer - sta _in_buffer+1 + sta m_in_buffer+1 lda bufferpointer+1 - sta _in_buffer+2 + sta m_in_buffer+2 }} repeat num_bytes { %asm {{ jsr c64.CHRIN sta cx16.r5 -_in_buffer sta $ffff - inc _in_buffer+1 +m_in_buffer sta $ffff + inc m_in_buffer+1 bne + - inc _in_buffer+2 + inc m_in_buffer+2 + inc list_blocks bne + inc list_blocks+1 diff --git a/compiler/test/codegeneration/TestAsmGenSymbols.kt b/compiler/test/codegeneration/TestAsmGenSymbols.kt index 49d8e9ecf..3dd2adf61 100644 --- a/compiler/test/codegeneration/TestAsmGenSymbols.kt +++ b/compiler/test/codegeneration/TestAsmGenSymbols.kt @@ -1,6 +1,5 @@ package prog8tests.codegeneration -import io.kotest.assertions.withClue import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import prog8.ast.Module @@ -121,27 +120,19 @@ class TestAsmGenSymbols: StringSpec({ // local label val localLabelIdent = (sub.statements.asSequence().filterIsInstance().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("locallabel") }.value as AddressOf).identifier - asmgen.asmSymbolName(localLabelIdent) shouldBe "_locallabel" - withClue("as a variable it uses different naming rules (no underscore prefix)") { - asmgen.asmVariableName(localLabelIdent) shouldBe "locallabel" - } + asmgen.asmSymbolName(localLabelIdent) shouldBe "locallabel" + asmgen.asmVariableName(localLabelIdent) shouldBe "locallabel" val localLabelIdentScoped = (sub.statements.asSequence().filterIsInstance().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","start","locallabel") }.value as AddressOf).identifier - asmgen.asmSymbolName(localLabelIdentScoped) shouldBe "main.start._locallabel" - withClue("as a variable it uses different naming rules (no underscore prefix)") { - asmgen.asmVariableName(localLabelIdentScoped) shouldBe "main.start.locallabel" - } + asmgen.asmSymbolName(localLabelIdentScoped) shouldBe "main.start.locallabel" + asmgen.asmVariableName(localLabelIdentScoped) shouldBe "main.start.locallabel" // label from outer scope needs sope prefixes because it is outputted as a locally scoped symbol for the assembler val scopedLabelIdent = (sub.statements.asSequence().filterIsInstance().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("label_outside") }.value as AddressOf).identifier - asmgen.asmSymbolName(scopedLabelIdent) shouldBe "main._label_outside" - withClue("as a variable it uses different naming rules (no underscore prefix)") { - asmgen.asmVariableName(scopedLabelIdent) shouldBe "label_outside" - } + asmgen.asmSymbolName(scopedLabelIdent) shouldBe "main.label_outside" + asmgen.asmVariableName(scopedLabelIdent) shouldBe "label_outside" val scopedLabelIdentScoped = (sub.statements.asSequence().filterIsInstance().first { (it.value as? AddressOf)?.identifier?.nameInSource==listOf("main","label_outside") }.value as AddressOf).identifier - asmgen.asmSymbolName(scopedLabelIdentScoped) shouldBe "main._label_outside" - withClue("as a variable it uses different naming rules (no underscore prefix)") { - asmgen.asmVariableName(scopedLabelIdentScoped) shouldBe "main.label_outside" - } + asmgen.asmSymbolName(scopedLabelIdentScoped) shouldBe "main.label_outside" + asmgen.asmVariableName(scopedLabelIdentScoped) shouldBe "main.label_outside" } "asm names for hooks to zp temp vars" { diff --git a/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt index 934485fec..8d1b58394 100644 --- a/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt +++ b/compilerInterfaces/src/prog8/compilerinterface/IAssemblyGenerator.kt @@ -4,10 +4,6 @@ interface IAssemblyGenerator { fun compileToAssembly(): IAssemblyProgram } -const val generatedLabelPrefix = "_prog8_label_" -const val subroutineFloatEvalResultVar1 = "_prog8_float_eval_result1" -const val subroutineFloatEvalResultVar2 = "_prog8_float_eval_result2" - interface IAssemblyProgram { val valid: Boolean val name: String diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4dd9ef82d..c08285556 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,8 @@ TODO For next compiler release (7.7) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... +check AsmGen translate(stmt: Directive) breakpoint nop issue + Need help with ^^^^^^^^^^^^^^ @@ -25,7 +26,6 @@ Future Things and Ideas - for the pipe operator: recognise a placeholder (``?`` or ``%`` or ``_``) in a non-unary function call to allow things as ``4 |> mkword(?, $44) |> print_uw`` - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_`` then we can get rid of the instruction lists in the machinedefinitions as well? -- fix the asm-labels problem (github issue #62) - make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment) but this requires all identifiers in the inlined expression to be changed to fully scoped names - simplifyConditionalExpression() should not split expression if it still results in stack-based evaluation diff --git a/examples/test.p8 b/examples/test.p8 index 31da64778..00602c722 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,51 +1,16 @@ %import textio -%import test_stack main { - %option force_output + str myBar = "main.bar" - sub start() { - test_stack.test() - uword ww = 10 - repeat 10 { - ww++ - txt.print_uw(ww) - txt.nl() - } - test_stack.test() +foo_bar: + %asm {{ + nop + }} - repeat { - } - } + sub start() { + txt.print(myBar) + txt.print(&foo_bar) + return + } } - - -;main { -; sub start() { -; %asm {{ -; lda #float5_111 -; jsr floats.MOVFM -; lda #float5_122 -; jsr floats.FADD -; jsr floats.FOUT -; sta $7e -; sty $7f -; ldy #64 -;_loop -; lda ($7e),y -; beq _done -; jsr c64.CHROUT -; iny -; bne _loop -;_done -; rts -; -;float5_111 .byte $81, $64e, $14, $7a, $e1 ; float 1.11 -;float5_122 .byte $81, $1c, $28, $f5, $c2 ; float 1.22 -; -; }} -; } -; -;}