/* * bank1.c — code, const tables AND writable static data all live in the * BANK1 page mapped into window 3 while these functions run. * * Compile flags (see Makefile): * --codeseg BANK1 functions go to _BANK1 area * --constseg BANK1 `static const` tables go to _BANK1 * --dataseg BANK1 uninitialized data (BSS) goes to _BANK1 * * mkexe -p 0 zero-pads the bank's image, so any BSS bytes that don't * appear in the IHX file are 0x00 when the bank is loaded — free zero * init for `uint8_t buf[N];`. * * Note: a CRITICAL trampoline fix is required (see memory/sdcc_banking) * — the old bcall used `pop af; out (n), a` which clobbered the uint8_t * return value. Without that fix, banked functions returning a byte * would silently return the saved page number instead. */ #include #include #include uint8_t bank1_buf[16]; static const uint16_t bank1_tab[5] = { 100, 200, 300, 400, 500 }; void bank1_fill(int seed) __banked { uint8_t *p = bank1_buf; for (int i = 0; i < 16; i++) p[i] = (uint8_t)(seed + i); } uint8_t bank1_peek(int idx) __banked { uint8_t *p = bank1_buf; if (idx < 0 || idx >= 16) return 0xFF; return p[idx]; } uint16_t bank1_sumtab(void) __banked { uint16_t s = 0; for (int i = 0; i < 5; i++) s += bank1_tab[i]; return s; } void bank1_map_print(void) __banked { printf( "bank1_buf = %p\n", bank1_buf); printf( "bank1_tab = %p\n", bank1_tab); printf( "bank1_fill = %p\n", bank1_fill); printf( "bank1_peek = %p\n", bank1_peek); printf( "bank1_sumtab = %p\n", bank1_sumtab); } /* * malloc-from-banked test. * * SDCC's heap lives in HOME RAM (W2 = 0x8000-0xBFFF, see runtime/heap.s). * Window 2 is fixed and stays mapped regardless of W3 page swaps. So * malloc() called from a banked function should: * 1. Return a pointer somewhere in 0x80xx..0xBFxx (W2 heap) * 2. The pointer is usable both inside the bank (W2 still mapped) and * after returning to HOME (W2 unchanged across trampoline). * * The function allocates N bytes, fills them with a known pattern, and * returns the pointer to the caller for verification. */ uint8_t *bank1_alloc_and_fill(int n, uint8_t pattern) __banked { uint8_t *p = (uint8_t *)malloc(n); if (p == NULL) return NULL; for (int i = 0; i < n; i++) p[i] = (uint8_t)(pattern + i); printf(" bank1_alloc_and_fill: malloc(%d) -> %p\n", n, p); return p; } void bank1_free(void *p) __banked { free(p); }