]> git.sur5r.net Git - cc65/commitdiff
Adapted, to the c64 target, the INIT-segment overlay scheme from the apple2 targets.
authorGreg King <gregdk@users.sf.net>
Mon, 5 Oct 2015 09:47:43 +0000 (05:47 -0400)
committerGreg King <gregdk@users.sf.net>
Mon, 5 Oct 2015 09:47:43 +0000 (05:47 -0400)
When a program starts running, INIT is moved from one place to another place.  Then, INIT's code is executed; and, the first place is re-used for variables.  After the INIT code has finished, the second place can be re-used by the heap and the C stack.  That means that initiation code and data won't waste any RAM space after they stop being needed.

asminc/c64.inc
cfg/c64-overlay.cfg
cfg/c64.cfg
libsrc/c64/crt0.s
libsrc/common/moveinit.s [new file with mode: 0644]

index 5815bebf98208534efb8011e20639b62f8ec74fb..ababb1ea0cdc2f933535237aa79aa39747811e57 100644 (file)
@@ -24,6 +24,7 @@ SCREEN_PTR      := $D1          ; Pointer to current char in text screen
 CURS_X          := $D3          ; Cursor column
 CURS_Y          := $D6          ; Cursor row
 CRAM_PTR        := $F3          ; Pointer to current char in color RAM
+FREKZP          := $FB          ; Five unused bytes
 
 BASIC_BUF       := $200         ; Location of command-line
 BASIC_BUF_LEN   = 89            ; Maximum length of command-line
@@ -212,4 +213,3 @@ CASSMOT         = $20           ; Cassette motor on
 TP_FAST         = $80           ; Switch Rossmoeller TurboProcess to fast mode
 
 RAMONLY         = $F8           ; (~(LORAM | HIRAM | IOEN)) & $FF
-
index 2f7693e6ea79c6b5c3bfce8d4e5c90c9e6733f0f..58612e18ed02b511bc2b6b2e4b1b40a4bfeb47a2 100644 (file)
@@ -1,64 +1,70 @@
+FEATURES {
+    STARTADDRESS:    default = $0801;
+}
 SYMBOLS {
     __LOADADDR__:    type = import;
     __EXEHDR__:      type = import;
     __OVERLAYADDR__: type = import;
-    __STACKSIZE__:   type = weak, value = $0800; # 2k stack
-    __OVERLAYSIZE__: type = weak, value = $1000; # 4k overlay
+    __STACKSIZE__:   type = weak,   value = $0800; # 2k stack
+    __OVERLAYSIZE__: type = weak,   value = $1000; # 4k overlay
+    __HIMEM__:       type = weak,   value = $D000;
+    __HIMEM2__:      type = export, value = __HIMEM__ - 2;
 }
 MEMORY {
-    ZP:       file = "", define = yes, start = $0002,                   size = $001A;
-    LOADADDR: file = %O,               start = $07FF,                   size = $0002;
-    HEADER:   file = %O,               start = $0801,                   size = $000C;
-    RAM:      file = %O, define = yes, start = $080D,                   size = $C7F3 - __OVERLAYSIZE__ - __STACKSIZE__;
-    OVL1ADDR: file = "%O.1",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL1:     file = "%O.1",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL2ADDR: file = "%O.2",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL2:     file = "%O.2",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL3ADDR: file = "%O.3",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL3:     file = "%O.3",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL4ADDR: file = "%O.4",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL4:     file = "%O.4",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL5ADDR: file = "%O.5",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL5:     file = "%O.5",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL6ADDR: file = "%O.6",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL6:     file = "%O.6",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL7ADDR: file = "%O.7",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL7:     file = "%O.7",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL8ADDR: file = "%O.8",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL8:     file = "%O.8",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
-    OVL9ADDR: file = "%O.9",           start = $CFFE - __OVERLAYSIZE__, size = $0002;
-    OVL9:     file = "%O.9",           start = $D000 - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    ZP:       file = "", define = yes, start = $0002,                        size = $001A;
+    LOADADDR: file = %O,               start = %S - 2,                       size = $0002;
+    HEADER:   file = %O, define = yes, start = %S,                           size = $000D;
+    RAM:      file = %O,               start = __HEADER_LAST__,              size = __HIMEM__ - __OVERLAYSIZE__ - __STACKSIZE__ - __HEADER_LAST__;
+    MOVE:     file = %O,               start = __ZPSAVE_LOAD__,              size = __HIMEM__ - __INIT_RUN__;
+    OVL1ADDR: file = "%O.1",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL1:     file = "%O.1",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL2ADDR: file = "%O.2",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL2:     file = "%O.2",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL3ADDR: file = "%O.3",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL3:     file = "%O.3",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL4ADDR: file = "%O.4",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL4:     file = "%O.4",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL5ADDR: file = "%O.5",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL5:     file = "%O.5",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL6ADDR: file = "%O.6",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL6:     file = "%O.6",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL7ADDR: file = "%O.7",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL7:     file = "%O.7",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL8ADDR: file = "%O.8",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL8:     file = "%O.8",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
+    OVL9ADDR: file = "%O.9",           start = __HIMEM2__ - __OVERLAYSIZE__, size = $0002;
+    OVL9:     file = "%O.9",           start = __HIMEM__  - __OVERLAYSIZE__, size = __OVERLAYSIZE__;
 }
 SEGMENTS {
-    LOADADDR: load = LOADADDR, type = ro;
-    EXEHDR:   load = HEADER,   type = ro;
-    STARTUP:  load = RAM,      type = ro;
-    LOWCODE:  load = RAM,      type = ro,                optional = yes;
-    INIT:     load = RAM,      type = ro,  define = yes, optional = yes;
-    CODE:     load = RAM,      type = ro;
-    RODATA:   load = RAM,      type = ro;
-    DATA:     load = RAM,      type = rw;
-    ZPSAVE:   load = RAM,      type = bss;
-    BSS:      load = RAM,      type = bss, define = yes;
-    ZEROPAGE: load = ZP,       type = zp;
-    OVL1ADDR: load = OVL1ADDR, type = ro;
-    OVERLAY1: load = OVL1,     type = ro,  define = yes, optional = yes;
-    OVL2ADDR: load = OVL2ADDR, type = ro;
-    OVERLAY2: load = OVL2,     type = ro,  define = yes, optional = yes;
-    OVL3ADDR: load = OVL3ADDR, type = ro;
-    OVERLAY3: load = OVL3,     type = ro,  define = yes, optional = yes;
-    OVL4ADDR: load = OVL4ADDR, type = ro;
-    OVERLAY4: load = OVL4,     type = ro,  define = yes, optional = yes;
-    OVL5ADDR: load = OVL5ADDR, type = ro;
-    OVERLAY5: load = OVL5,     type = ro,  define = yes, optional = yes;
-    OVL6ADDR: load = OVL6ADDR, type = ro;
-    OVERLAY6: load = OVL6,     type = ro,  define = yes, optional = yes;
-    OVL7ADDR: load = OVL7ADDR, type = ro;
-    OVERLAY7: load = OVL7,     type = ro,  define = yes, optional = yes;
-    OVL8ADDR: load = OVL8ADDR, type = ro;
-    OVERLAY8: load = OVL8,     type = ro,  define = yes, optional = yes;
-    OVL9ADDR: load = OVL9ADDR, type = ro;
-    OVERLAY9: load = OVL9,     type = ro,  define = yes, optional = yes;
+    ZEROPAGE: load = ZP,              type = zp;
+    LOADADDR: load = LOADADDR,        type = ro;
+    EXEHDR:   load = HEADER,          type = ro;
+    STARTUP:  load = RAM,             type = ro;
+    LOWCODE:  load = RAM,             type = ro,                optional = yes;
+    CODE:     load = RAM,             type = ro;
+    RODATA:   load = RAM,             type = ro;
+    DATA:     load = RAM,             type = rw;
+    ZPSAVE:   load = RAM,             type = bss, define = yes;
+    BSS:      load = RAM,             type = bss, define = yes;
+    INIT:     load = MOVE, run = RAM, type = ro,  define = yes, optional = yes;
+    OVL1ADDR: load = OVL1ADDR,        type = ro;
+    OVERLAY1: load = OVL1,            type = ro,  define = yes, optional = yes;
+    OVL2ADDR: load = OVL2ADDR,        type = ro;
+    OVERLAY2: load = OVL2,            type = ro,  define = yes, optional = yes;
+    OVL3ADDR: load = OVL3ADDR,        type = ro;
+    OVERLAY3: load = OVL3,            type = ro,  define = yes, optional = yes;
+    OVL4ADDR: load = OVL4ADDR,        type = ro;
+    OVERLAY4: load = OVL4,            type = ro,  define = yes, optional = yes;
+    OVL5ADDR: load = OVL5ADDR,        type = ro;
+    OVERLAY5: load = OVL5,            type = ro,  define = yes, optional = yes;
+    OVL6ADDR: load = OVL6ADDR,        type = ro;
+    OVERLAY6: load = OVL6,            type = ro,  define = yes, optional = yes;
+    OVL7ADDR: load = OVL7ADDR,        type = ro;
+    OVERLAY7: load = OVL7,            type = ro,  define = yes, optional = yes;
+    OVL8ADDR: load = OVL8ADDR,        type = ro;
+    OVERLAY8: load = OVL8,            type = ro,  define = yes, optional = yes;
+    OVL9ADDR: load = OVL9ADDR,        type = ro;
+    OVERLAY9: load = OVL9,            type = ro,  define = yes, optional = yes;
 }
 FEATURES {
     CONDES: type    = constructor,
index 5d8befd020e5052432b0f14a357e74a528b76d5e..861e19faf78cd846fbf82454ebd5faf5ce8133b4 100644 (file)
@@ -1,26 +1,31 @@
+FEATURES {
+    STARTADDRESS:  default = $0801;
+}
 SYMBOLS {
     __LOADADDR__:  type = import;
     __EXEHDR__:    type = import;
     __STACKSIZE__: type = weak, value = $0800; # 2k stack
+    __HIMEM__:     type = weak, value = $D000;
 }
 MEMORY {
-    ZP:       file = "", define = yes, start = $0002, size = $001A;
-    LOADADDR: file = %O,               start = $07FF, size = $0002;
-    HEADER:   file = %O,               start = $0801, size = $000C;
-    RAM:      file = %O, define = yes, start = $080D, size = $C7F3 - __STACKSIZE__;
+    ZP:       file = "", define = yes, start = $0002,           size = $001A;
+    LOADADDR: file = %O,               start = %S - 2,          size = $0002;
+    HEADER:   file = %O, define = yes, start = %S,              size = $000D;
+    RAM:      file = %O,               start = __HEADER_LAST__, size = __HIMEM__ - __STACKSIZE__ - __HEADER_LAST__;
+    MOVE:     file = %O,               start = __ZPSAVE_LOAD__, size = __HIMEM__ - __INIT_RUN__;
 }
 SEGMENTS {
-    LOADADDR: load = LOADADDR, type = ro;
-    EXEHDR:   load = HEADER,   type = ro;
-    STARTUP:  load = RAM,      type = ro;
-    LOWCODE:  load = RAM,      type = ro,                optional = yes;
-    INIT:     load = RAM,      type = ro,  define = yes, optional = yes;
-    CODE:     load = RAM,      type = ro;
-    RODATA:   load = RAM,      type = ro;
-    DATA:     load = RAM,      type = rw;
-    ZPSAVE:   load = RAM,      type = bss;
-    BSS:      load = RAM,      type = bss, define = yes;
-    ZEROPAGE: load = ZP,       type = zp;
+    ZEROPAGE: load = ZP,              type = zp;
+    LOADADDR: load = LOADADDR,        type = ro;
+    EXEHDR:   load = HEADER,          type = ro;
+    STARTUP:  load = RAM,             type = ro;
+    LOWCODE:  load = RAM,             type = ro,                optional = yes;
+    CODE:     load = RAM,             type = ro;
+    RODATA:   load = RAM,             type = ro;
+    DATA:     load = RAM,             type = rw;
+    ZPSAVE:   load = RAM,             type = bss, define = yes;
+    BSS:      load = RAM,             type = bss, define = yes;
+    INIT:     load = MOVE, run = RAM, type = ro,  define = yes, optional = yes;
 }
 FEATURES {
     CONDES: type    = constructor,
index 24fe4376bdafde59d78583f5907ad600a80fef74..5a69f158488f9a3ff12494da4622dcfc8bed9d94 100644 (file)
@@ -3,13 +3,13 @@
 ;
 
         .export         _exit
+        .exportzp       init_load_, init_run_
         .export         __STARTUP__ : absolute = 1      ; Mark as startup
+
         .import         initlib, donelib
-        .import         zerobss
-        .import         callmain
+        .import         move_init, zerobss, callmain
         .import         RESTOR, BSOUT, CLRCH
-        .import         __RAM_START__, __RAM_SIZE__     ; Linker generated
-        .import         __STACKSIZE__                   ; Linker generated
+        .import         __HIMEM__                       ; from configure file
         .importzp       ST
 
         .include        "zeropage.inc"
 ; ------------------------------------------------------------------------
 ; Startup code
 
-.segment        "STARTUP"
+; Two zero-page pointers are needed before any zero-page stuff is saved.
+; Choose locations that are not used by anything.
 
-Start:
+init_load_      :=      FREKZP
+init_run_       :=      FREKZP+2
 
-; Save the zero-page locations that we need.
 
-        ldx     #zpspace-1
-L1:     lda     sp,x
-        sta     zpsave,x
-        dex
-        bpl     L1
+.segment        "STARTUP"
+
+Start:
 
 ; Switch to the second charset.
 
@@ -39,35 +38,30 @@ L1:     lda     sp,x
 ; Switch off the BASIC ROM.
 
         lda     $01
-        pha                     ; Remember the value
+        sta     mmusave         ; Save the memory configuration
         and     #$F8
         ora     #$06            ; Enable Kernal+I/O, disable BASIC
         sta     $01
 
-; Clear the BSS data.
-
-        jsr     zerobss
-
-; Save some system settings; and, set up the stack.
-
-        pla
-        sta     mmusave         ; Save the memory configuration
-
         tsx
         stx     spsave          ; Save the system stack ptr
 
-        lda     #<(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
-        sta     sp
-        lda     #>(__RAM_START__ + __RAM_SIZE__ + __STACKSIZE__)
-        sta     sp+1            ; Set argument stack ptr
+; Allow some re-entrancy by skipping the next task if it already was done.
+; This often can let us rerun the program without reloading it.
 
-; Call the module constructors.
+        ldx     moveinit
+        beq     L0
 
-        jsr     initlib
+; Move the INIT segment from where it was loaded (over ZPSAVE and BSS)
+; into where it must be run (in the heap).
 
-; Push the command-line arguments; and, call main().
+        jsr     move_init
+        dec     moveinit        ; set to false
+
+; Save space by putting the rest of the start-up code in the INIT segment,
+; which can be re-used by the heap.
 
-        jsr     callmain
+L0:     jsr     initstart
 
 ; Back from main() [this is also the exit() entry]. Run the module destructors.
 
@@ -98,14 +92,51 @@ L2:     lda     zpsave,x
 
         rts
 
+
 ; ------------------------------------------------------------------------
-; Data
 
-.segment        "ZPSAVE"
+.segment        "INIT"
 
-zpsave: .res    zpspace
+initstart:
+
+; Save the zero-page locations that we need.
 
-.bss
+        ldx     #zpspace-1
+L1:     lda     sp,x
+        sta     zpsave,x
+        dex
+        bpl     L1
+
+; Clear the BSS data.
+
+        jsr     zerobss
+
+; Set up the stack.
+
+        lda     #<__HIMEM__
+        ldx     #>__HIMEM__
+        sta     sp
+        stx     sp+1            ; Set argument stack ptr
+
+; Call the module constructors.
+
+        jsr     initlib
+
+; Push the command-line arguments; and, call main().
+
+        jmp     callmain
+
+
+; ------------------------------------------------------------------------
+; Data
+
+.data
 
-spsave: .res    1
 mmusave:.res    1
+spsave: .res    1
+moveinit:
+        .byte   1
+
+.segment        "ZPSAVE"
+
+zpsave: .res    zpspace
diff --git a/libsrc/common/moveinit.s b/libsrc/common/moveinit.s
new file mode 100644 (file)
index 0000000..e9cd5fb
--- /dev/null
@@ -0,0 +1,54 @@
+;
+; 2015-10-04, Greg King
+;
+
+        .export         move_init
+
+        .import         __INIT_LOAD__, __INIT_RUN__, __INIT_SIZE__ ; Linker-generated
+        .importzp       init_load_, init_run_
+
+        .macpack        cpu
+        .macpack        generic
+
+
+; Move the INIT segment from where it was loaded (over the bss segments)
+; into where it must be run (in the heap).  The two areas might overlap; and,
+; the segment is moved upwards.  Therefore, this code starts at the highest
+; address, and decrements to the lowest address.  The low bytes of the starting
+; pointers are not sums.  The high bytes are sums; but, they do not include the
+; carry.  Both the low-byte sums and the carries will be done when the pointers
+; are indexed by the .Y register.
+
+move_init:
+        lda     #<__INIT_LOAD__
+        ldx     #>__INIT_LOAD__ + >__INIT_SIZE__
+        sta     init_load_
+        stx     init_load_+1
+        lda     #<__INIT_RUN__
+        ldx     #>__INIT_RUN__ + >__INIT_SIZE__
+        sta     init_run_
+        stx     init_run_+1
+
+; First, move the last, partial page.
+; Then, move all of the full pages.
+
+        ldx     #>__INIT_SIZE__ + 1     ; number of pages, including partial
+        ldy     #<__INIT_SIZE__         ; size of partial page
+.if     .cpu & CPU_ISET_65SC02
+        bra     L3
+.else
+        jmp     L3
+.endif
+
+L1:     dec     init_load_+1
+        dec     init_run_+1
+
+L2:     dey
+        lda     (init_load_),y
+        sta     (init_run_),y
+        tya
+L3:     bnz     L2                      ; page not finished
+
+        dex
+        bnz     L1                      ; move next page
+        rts