From 04cb684fd42be181cce054d27fd61e86aaf0af4c Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 27 Sep 2024 02:14:54 +0200 Subject: [PATCH] tweak program start initialization and fix cleanup at exit for atari and pet compiler targets --- .../codegen/cpu6502/ProgramAndVarsGen.kt | 36 ++++++++--------- compiler/res/prog8lib/atari/syslib.p8 | 39 ++++++++++++++++--- compiler/res/prog8lib/prog8_lib.asm | 20 ++++++++++ docs/source/todo.rst | 2 +- examples/test.p8 | 15 +++---- 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt index 55a17ffd4..e1c7fca6a 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/ProgramAndVarsGen.kt @@ -103,6 +103,9 @@ internal class ProgramAndVarsGen( asmgen.out(" .null $9e, format(' %d ', prog8_entrypoint), $3a, $8f, ' prog8'") asmgen.out("+\t.word 0") asmgen.out("prog8_entrypoint\t; assembly code starts here") + asmgen.out(" cld") + asmgen.out(" tsx ; save stackpointer for sys.exit()") + asmgen.out(" stx prog8_lib.orig_stackpointer") if(!options.noSysInit) asmgen.out(" jsr sys.init_system") asmgen.out(" jsr sys.init_system_phase2") @@ -110,6 +113,9 @@ internal class ProgramAndVarsGen( CbmPrgLauncherType.NONE -> { asmgen.out("; ---- program without basic sys call ----") asmgen.out("* = ${options.loadAddress.toHex()}") + asmgen.out(" cld") + asmgen.out(" tsx ; save stackpointer for sys.exit()") + asmgen.out(" stx prog8_lib.orig_stackpointer") if(!options.noSysInit) asmgen.out(" jsr sys.init_system") asmgen.out(" jsr sys.init_system_phase2") @@ -119,6 +125,9 @@ internal class ProgramAndVarsGen( OutputType.XEX -> { asmgen.out("; ---- atari xex program ----") asmgen.out("* = ${options.loadAddress.toHex()}") + asmgen.out(" cld") + asmgen.out(" tsx ; save stackpointer for sys.exit()") + asmgen.out(" stx prog8_lib.orig_stackpointer") if(!options.noSysInit) asmgen.out(" jsr sys.init_system") asmgen.out(" jsr sys.init_system_phase2") @@ -149,7 +158,10 @@ internal class ProgramAndVarsGen( asmgen.out(" jsr p8b_main.p8s_start | lda #0 | sta ${"$"}ff00") asmgen.out(" jmp sys.cleanup_at_exit") } - else -> asmgen.jmp("p8b_main.p8s_start") + else -> { + asmgen.out(" jsr p8b_main.p8s_start") + asmgen.out(" jmp sys.cleanup_at_exit") + } } } @@ -451,22 +463,7 @@ internal class ProgramAndVarsGen( } private fun entrypointInitialization() { - asmgen.out("; program startup initialization") - asmgen.out(" cld | tsx | stx prog8_lib.orig_stackpointer ; required for sys.exit()") - // set full BSS area to zero - asmgen.out(""" - .if prog8_bss_section_size>0 - ; reset all variables in BSS section to zero - lda #prog8_bss_section_start - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldx #prog8_bss_section_size - lda #0 - jsr prog8_lib.memset - .endif""") - + // initialize block-level (global) variables at program start blockVariableInitializers.forEach { if (it.value.isNotEmpty()) asmgen.out(" jsr ${it.key.name}.prog8_init_vars") @@ -517,9 +514,8 @@ internal class ProgramAndVarsGen( arrayVariable2asm(varname, it.alloc.dt, it.value, null) } - asmgen.out("""+ - clv - clc""") + // zero out the BSS area + asmgen.out("+ jsr prog8_lib.program_startup_clear_bss") } private class ZpStringWithInitial( diff --git a/compiler/res/prog8lib/atari/syslib.p8 b/compiler/res/prog8lib/atari/syslib.p8 index 2bc89ef60..43ddc145a 100644 --- a/compiler/res/prog8lib/atari/syslib.p8 +++ b/compiler/res/prog8lib/atari/syslib.p8 @@ -44,6 +44,22 @@ sys { }} } + asmsub cleanup_at_exit() { + ; executed when the main subroutine does rts + %asm {{ +_exitcodeCarry = *+1 + lda #0 + lsr a +_exitcode = *+1 + lda #0 ; exit code possibly modified in exit() +_exitcodeX = *+1 + ldx #0 +_exitcodeY = *+1 + ldy #0 + rts + }} + } + asmsub reset_system() { ; Soft-reset the system back to initial power-on Basic prompt. ; TODO @@ -248,27 +264,38 @@ save_SCRATCH_ZPWORD2 .word 0 asmsub exit(ubyte returnvalue @A) { ; -- immediately exit the program with a return code in the A register - ; TODO where to store A as exit code? %asm {{ + sta cleanup_at_exit._exitcode ldx prog8_lib.orig_stackpointer txs - rts ; return to original caller + jmp cleanup_at_exit }} } asmsub exit2(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y) { ; -- immediately exit the program with result values in the A, X and Y registers. - ; TODO where to store A,X,Y as exit code? %asm {{ - jmp exit + sta cleanup_at_exit._exitcode + stx cleanup_at_exit._exitcodeX + sty cleanup_at_exit._exitcodeY + ldx prog8_lib.orig_stackpointer + txs + jmp cleanup_at_exit }} } asmsub exit3(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y, bool carry @Pc) { ; -- immediately exit the program with result values in the A, X and Y registers, and the Carry flag in the status register. - ; TODO where to store A,X,Y,Carry as exit code? %asm {{ - jmp exit + sta cleanup_at_exit._exitcode + lda #0 + rol a + sta cleanup_at_exit._exitcodeCarry + stx cleanup_at_exit._exitcodeX + sty cleanup_at_exit._exitcodeY + ldx prog8_lib.orig_stackpointer + txs + jmp cleanup_at_exit }} } diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index af813ca03..23eea6d12 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -5,6 +5,26 @@ orig_stackpointer .byte 0 ; stores the Stack pointer register at program start +program_startup_clear_bss .proc + ; this is always ran first thing from the start routine to clear out the BSS area + .if prog8_bss_section_size>0 + ; reset all variables in BSS section to zero + lda #prog8_bss_section_start + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldx #prog8_bss_section_size + lda #0 + jsr prog8_lib.memset + .endif + clv + clc + rts + .pend + + + read_byte_from_address_in_AY_into_A .proc sta P8ZP_SCRATCH_W2 sty P8ZP_SCRATCH_W2+1 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index ac5824616..c87475527 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,7 +1,7 @@ TODO ==== -Can we move the asm init code that is injected into the start() subroutine, to init_system_phase2 instead? +Shouldn't RAW output target have some initialization logic too? Does it even clear the variables/bss etc? Doc improvements: some short overview for people coming from other programming languages like C: tell something about prog8 not having function overloading, max 16 bit (u)word integer as native type (and floats sometimes), diff --git a/examples/test.p8 b/examples/test.p8 index 9d37dd7ec..003fd4623 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,16 +1,13 @@ %import textio -%import floats -%zeropage basicsafe +%zeropage dontuse +%option no_sysinit main { + uword @shared variable sub start() { - float fl = 5.23 - fl = floats.ceil(fl) - floats.print(fl) - txt.nl() - fl = 5.23 - fl = floats.floor(fl) - floats.print(fl) + txt.print("hello!\n") + txt.print_uw(variable) txt.nl() + sys.exit3(1,2,3,false) } }