Re: [cc65] linker cfg files

Date view Thread view Subject view

From: Greg King (gngking_at_erols.com)
Date: 2003-05-20 22:11:22


From: Ullrich von Bassewitz
Date: Friday, April 25, 2003, 06:10 AM
>
> But, Shawn and Groepaz are right with one thing:  This won't work with
> the current library code, because the heap is initialized to start
> at the end of the BSS segment, and extends to the bottom of the stack,
> which, in turn, is placed at the end of the RAM memory section.
> And, there is no way to use a HEAP segment as a general solution,
> because the linker can only handle fixed-size segments, while the heap
> size should vary, depending on the size of the program.

I recognize a challenge when I see one.  I believe that I have discovered
a way to do it:

Only the linker-script defines the heap and the stack.  ld65 determines
most of their addresses when a program is built.  BSS, the heap,
and the stack don't need to be next to each other.  The heap can be
stationary (pre-set location and size) or mobile (as in the C64).
They can be changed without changing the library.

Two segments, in different memory-areas,
are used as fences around the heap.

The crt0.s files set the stack-pointer to
"(__STK_START__ + __STK_SIZE__)".
stkchk.s uses "__STK_SIZE__" instead of "__STACKSIZE__".

This file defines the heap's pointers:
=====================================================================
; _heap.s
;
; Names that describe the heap:
; static size_t        _heaporg;      /* Bottom of heap */
; struct freeblock*    _heapfirst;    /* First free-block in list */
; struct freeblock*    _heaplast;     /* Last free-block in list */
; size_t*              _heapptr;      /* Current top */
; size_t               _heapend;      /* Upper limit */
        .constructor   initheap
        .include       "_heap.inc"
; Initiation -- is run during start-up.
;
initheap:
        lda  #<__heaporg
        ldx  #>__heaporg
        sta  __heapptr
        stx  __heapptr+1
        rts
        .bss
__heapfirst:
        .res 2         ; zerobss puts NULL here
__heaplast:
        .res 2
__heapptr:
        .res 2
        .segment "HEAP"
__heaporg:
        .segment "HEAPEND"
__heapend:
=====================================================================

malloc.s, _heapmaxavail.s, _heapmemavail.s, _heap.h, heaptest.c,
and strdup-test.c use "__heaporg" and "__heapend" as immediate-addresses,
instead of, as variables.

Here are the relevant parts of the C64 target's configuration-script:

MEMORY {
    ZP: ...
    RAM: start = $07FF, size = $c801;
    STK: start = $c800, size = $0800, define = yes, file = "";
}
SEGMENTS {
    ZEROPAGE: load = ZP, type = zp;
    STARTUP: load = RAM, type = wp;
    ...
    ...
    ...
    BSS:     load = RAM, type = bss, define = yes;
    HEAP:    load = RAM, type = bss;
    HEAPEND: load = STK, type = bss;
}
...
    ...
    ...
#SYMBOLS {
#    __STACKSIZE__ = $800; # (delete this section)
#}

And, here are the relevant parts of the NES target's configuration-script:

MEMORY {
    ZP:  ...
    # ...
    HEADER: ... , type = ro, ...
    # ...
    # - data (load)
    # Hardware Vectors at end of 2nd 16k ROM
    ROM0: start = $8000, size = $8000, type = ro, fill = yes;
    # ...
    ROM2: ... , type = ro, ...
    # ...
    # $0500-$0800 3 pages for cc65's parameter stack
    STK:  start = $0500, size = $0300, define = yes, file = "";
    # ...
    # - data (run)
    # - bss
    # - heap
    RAM0: start = $6000, size = $2000;
    RAM1: start = $8000, size = 1;
}

SEGMENTS {
    ZEROPAGE: load = ZP,     type = zp;
    HEADER:   load = HEADER, type = wp;
    STARTUP:  load = ROM0,   type = wp;
    CODE:     load = ROM0,   type = ro;
    RODATA:   load = ROM0,   type = ro;
    DATA:     load = ROM0,   type = rw,  define = yes, run = RAM0;
    VECTORS:  load = ROM0,   type = ro,                start = $fff4;
    CHARS:    load = ROM2,   type = ro;
    BSS:      load = RAM0,   type = bss, define = yes;
    HEAP:     load = RAM0,   type = bss;
    HEAPEND:  load = RAM1,   type = bss;
}

...
    ...
    ...

#SYMBOLS {
#    __STACKSIZE__ = $0300;  # (delete this section)
#}

The NES's heap and stack have a different relationship.
But, the library code is the same as it is for the C64's configuration
(and, for other configurations).

P.S.,
(I removed "define=yes" from ROM0, STARTUP, CODE, and RODATA.
They aren't needed, because the __DATA_SIZE__ number of bytes
should be copied from __DATA_LOAD__ to __DATA_RUN__.)

----------------------------------------------------------------------
To unsubscribe from the list send mail to majordomo_at_musoftware.de with
the string "unsubscribe cc65" in the body(!) of the mail.


Date view Thread view Subject view

This archive was generated by hypermail 2.1.3 : 2003-05-20 22:17:16 CEST