mirror of
https://github.com/imjasonh/nescript
synced 2026-07-13 02:59:36 +00:00
codegen: support banked → banked cross-bank function calls
Programs that put functions in switchable banks can now call across
bank boundaries — `bank A { fun step() { helper() } }` where
`helper` lives in `bank B` used to panic in the IR codegen. Three
small pieces unblock it:
1. **Generic trampoline.** `runtime/gen_bank_trampoline` no longer
takes a `fixed_bank_index` argument. Instead it reads the
caller's current bank from `ZP_BANK_CURRENT`, pushes it on the
hardware stack, switches to the target, JSRs the entry, then
pulls and restores the saved bank. The same per-callee stub
works for fixed→banked and banked→banked direction; nested
trampolines compose because each PHA/PLA pair sits inside its
own JSR/RTS frame. `gen_mapper_init` seeds `ZP_BANK_CURRENT`
with the fixed bank index for any banked mapper so the very
first cross-bank call from the fixed bank still restores to
the fixed bank (matching pre-banked-banked semantics).
2. **Codegen drops the panic.** The `Some(from), Some(to)` arm in
the call-resolution switch now emits `JSR __tramp_<name>` like
the fixed→banked case instead of panicking. Banked→fixed calls
still go direct (the fixed bank is always mapped at $C000).
3. **Bank-namespaced local labels.** Two banks emitting the same
`__ir_cmp_e_8` would trip the linker's discovery-pass duplicate-
label check the moment any banked code generated a comparison.
The new `local_label_suffix` helper prefixes the suffix with the
current bank name when banked code is being emitted, leaving
fixed-bank label generation untouched (so existing examples are
byte-identical apart from the trampoline / init bytes
themselves).
The new `examples/uxrom_banked_to_banked.ne` demonstrates the path
end-to-end: `bank Logic { fun step() { ... clamp() } }` calls
`bank Helpers { fun clamp() { ... } }` once per frame. The harness
golden is committed alongside it. The five existing banked example
ROMs change byte-for-byte because of the new trampoline shape and
the seed-ZP_BANK_CURRENT init, but their emulator goldens still
match exactly — observable behaviour is unchanged.
https://claude.ai/code/session_01KEczoNUX3WmcFLfq6iAQxB
This commit is contained in:
parent
7294ae3efa
commit
db3a4adc57
15 changed files with 403 additions and 66 deletions
|
|
@ -341,7 +341,6 @@ impl Linker {
|
|||
// maps to $C000-$FFFF and one of the switchable banks maps
|
||||
// to $8000-$BFFF.
|
||||
let total_banks = switchable_banks.len() + 1;
|
||||
let fixed_bank_index = total_banks - 1;
|
||||
|
||||
// Discovery pass: assemble each switchable bank that has
|
||||
// its own instruction stream so we know what labels live
|
||||
|
|
@ -447,8 +446,6 @@ impl Linker {
|
|||
// which switchable bank is currently mapped at $8000.
|
||||
if self.mapper != Mapper::NROM {
|
||||
all_instructions.extend(runtime::gen_bank_select(self.mapper));
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let fixed_bank_num = fixed_bank_index as u8;
|
||||
for (i, bank) in switchable_banks.iter().enumerate() {
|
||||
if bank.trampolines.is_empty() {
|
||||
continue;
|
||||
|
|
@ -460,7 +457,6 @@ impl Linker {
|
|||
&tramp.tramp_label,
|
||||
&tramp.entry_label,
|
||||
bank_num,
|
||||
fixed_bank_num,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue