;; ----------------------------------------------------------------------
;; heap.s — Sprinter heap definition.  Replaces SDCC's z80.lib heap.rel
;; with a DYNAMIC heap that auto-sizes to whatever space is left between
;; end-of-BSS and a fixed upper bound near the top of W2.
;;
;; Old design reserved a fixed `.ds 14000` after BSS, which overflowed
;; the stack at 0xBFFE in tiny mode and crashed once allocations crossed
;; that boundary.  Even a static 8 KB would fail once CODE+DATA grew.
;;
;; New design:
;;   ___sdcc_heap     = label at start of _HEAP area (= end of _BSS,
;;                      placed by the linker)
;;   ___sdcc_heap_end = absolute equate at HEAP_TOP (= 0xBB00 default).
;;                      malloc uses `&___sdcc_heap_end` as the upper
;;                      bound of the free list.
;;
;; Heap size = HEAP_TOP - end_of_BSS.  Grows when code shrinks, shrinks
;; when code grows.  Falls to 0 (malloc returns NULL) if BSS grows past
;; HEAP_TOP — safe, no crash.
;;
;; The gap (BSS_end..HEAP_TOP) is real RAM that simply isn't tracked by
;; the linker — it doesn't need to be, since nothing else is placed in
;; that range (the area-ordering in crt0.s ends with _HEAP).
;;
;; Reserve 0xBB00..0xBFFE (= 1278 bytes) for the stack — enough for
;; deep printf and most recursion.  Override with -DHEAP_TOP=0xNNNN.
;; ----------------------------------------------------------------------

    .module sprinter_heap

    .globl  ___sdcc_heap_init

    ;; NOTE: ___sdcc_heap_end is defined in crt0.s (per-program crt0).
    ;; We need it as an absolute equate (since malloc takes &symbol),
    ;; and the value must be configurable per program via -DHEAP_TOP=N
    ;; (or its derivative --stack-size).  Putting it in crt0 means the
    ;; library can stay HEAP_TOP-agnostic.

    ;; gsinit hook — calls into z80.lib's malloc.rel to wire up the
    ;; free-list at startup (after _BSS is zeroed).
    .area _GSINIT
    call  ___sdcc_heap_init

    ;; Heap start label — _HEAP follows _BSS in the area-ordering chain,
    ;; so ___sdcc_heap = first byte after BSS.  No bytes reserved here;
    ;; the heap memory is the gap to HEAP_TOP (defined in crt0).
    .area _HEAP
___sdcc_heap::
