Files
Sprinter-SDCC/runtime/bank.s
T
snark13 c71e249a4e Add full compiler toolchain, libc, examples and reference docs
First substantive commit: the entire Sprinter C compiler tree on top of
the bare README+gitignore initial commit.

What's in here:
  bin/sprinter-cc        — driver script invoking SDCC + linker + mkexe
  libc/                  — Sprinter-specific libc layer over ESTEX/BIOS
                           (conio, gfx, io, mem, stdio + headers)
  runtime/               — crt0 variants (default/small/banked/minimal)
                           + heap + bank trampolines
  toolchain/             — mkexe (SprintEXE packer, C + tests)
  examples/              — 30 demo programs (gfx, file I/O, env, time, …)
  lib/Makefile           — builds the libc archive (sprinter.lib)
  docs/                  — converted Sprinter manuals + asm reference samples
  third_party/           — solid-c reference compiler dump + sdcc setup script
  release_docs/          — packaging / release notes

gitignore overhaul:
  • Drop dangerous blanket patterns: *.asm (would hide docs/samples/*.asm)
    and *.exe (case-insensitive match was hiding third_party/solid-c/*.EXE
    on macOS APFS).  Replaced with examples/*/*.{asm,exe,…} and lib/*.lib.
  • Restore tracking of toolchain/mkexe/tests/{one,big}.bin — those are
    INPUT fixtures, not build outputs.
  • Collapse the duplicated SDCC/C/Sdcc sections into one section per
    concern (build outputs / vendored / OS-junk).
  • Add .sprinter-cc-*/, build/ (catches lib/build/ too), .claude/.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 16:13:21 +03:00

71 lines
2.9 KiB
ArmAsm

;; ----------------------------------------------------------------------
;; bank.s — Sprinter banked-call trampolines for SDCC __banked functions.
;;
;; ABI (verified empirically with SDCC 4.5, see memory/sdcc_banking.md):
;; On entry to ___sdcc_bcall_ehl:
;; E = bank id (1..15), HL = target address (low 16 bits).
;; Args already on stack, pushed by the caller right-to-left.
;; Stack picture once the trampoline finishes set-up and jp(hl) fires:
;; SP+0..1 = bjump return (callee's "ret address")
;; SP+2 = saved physical page (1 byte)
;; SP+3..4 = bcall caller return
;; SP+5.. = args ← __banked callees read from here
;;
;; The 3-byte spacer between callee ret and args is the contract SDCC bakes
;; into its codegen — touching it breaks all __banked calls.
;; ----------------------------------------------------------------------
.module bank
.globl _bank_pages
.globl ___sdcc_bcall_ehl
.globl ___sdcc_bjump_ehl
;; Choose between W3 (HUGE mode, default) and W1 (BIG mode, sprinter-cc
;; prepends `BANK_W1 = 1`). Keep in sync with crt0_banked.s.
.ifdef BANK_W1
BANK_PORT = 0xA2
.else
BANK_PORT = 0xE2
.endif
;; HOME area — always mapped, so the trampoline is reachable from any bank.
.area _CODE
___sdcc_bcall_ehl::
;; The 3-byte spacer between bcall-ret and args (1-byte saved page
;; + 2-byte bjump return address) is baked into SDCC's __banked
;; codegen — callees access their args at fixed offsets from SP.
;; We MUST keep that contract intact.
;;
;; The old `pop af; out (n), a` restore sequence clobbered A,
;; dropping uint8_t return values. We use the `OUT (C), r` form
;; (port via C, byte via B) so A is preserved. BC is scratch in
;; SDCC __sdcccall(1), so clobbering it here is harmless.
in a, (#BANK_PORT) ; A = current bank-window page
push af ; push A:F (2 bytes)
inc sp ; keep only the A byte (1-byte spacer)
call ___sdcc_bjump_ehl
;; Callee returned. A may hold a uint8_t return value.
dec sp ; widen back to 2 bytes
pop bc ; B = saved page (C = whatever F was)
ld c, #BANK_PORT ; C = bank-window select port
out (c), b ; OUT (port), B — A and F untouched
ret ; back to bcall caller
___sdcc_bjump_ehl::
push hl ; preserve target address
ld d, #0 ; D:E = 0:bank_id
ld hl, #_bank_pages
add hl, de ; HL = &_bank_pages[bank_id]
ld a, (hl) ; A = physical page for this bank
pop hl ; restore target address
out (#BANK_PORT), a ; map bank into banking window
jp (hl) ; tail-jump to callee
;; Per-bank physical page table. Index = bank id (1-based; [0] is unused).
;; Filled at startup by crt0_banked.s.
.area _DATA
_bank_pages::
.ds 16