tweak program start initialization and fix cleanup at exit for atari and pet compiler targets

This commit is contained in:
Irmen de Jong 2024-09-27 02:14:54 +02:00
parent 4c843571ea
commit 04cb684fd4
5 changed files with 76 additions and 36 deletions

View File

@ -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
ldy #>prog8_bss_section_start
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldx #<prog8_bss_section_size
ldy #>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(

View File

@ -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
}}
}

View File

@ -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
ldy #>prog8_bss_section_start
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldx #<prog8_bss_section_size
ldy #>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

View File

@ -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),

View File

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