Story: E01-S05
Status: frozen for the compiler (D117); verified in VICE x128 3.10
Authoritative source: cfg/compiler.cfg. This document explains it.
The generated-program memory map is not frozen here. It belongs to E04-S01 and E04-S02, which must reuse the test mailbox below.
| State | CR | RCR (low bits) | P0 | P1 | IRQs |
|---|---|---|---|---|---|
| System | as BASIC left it ($00) |
as BASIC left it | $0000 |
$0001 |
caller's |
| Compiler bank 0 | $0E |
%0110 8K bottom common |
bank 0 page $1A |
$0001 |
masked |
| Compiler bank 1 | $4E |
%0110 8K bottom common |
bank 0 page $1A |
$0001 |
masked |
RCR bits 6–7 (VIC bank) are always carried over from the system value.
src/compiler/mmu.s is the only module that writes MMU registers.
| Range | Size | Name | Contents |
|---|---|---|---|
$0000-$12FF |
system | BASIC 7, KERNAL, editor, screen. Off limits except NMINV ($0318), which the compiler saves and restores |
|
$1300-$18FF |
1536 | COMMON | Copied from the PRG by mmu_init: MMU switches, KERNAL wrapper, NMI guard, and any code that runs while bank 1 is mapped |
$1900-$19FF |
256 | DISKBUF | Disk transfer buffer, visible from both banks |
$1A00-$1AFF |
256 | private ZP | Physical page behind logical zero page in compiler states. Not a linker area: nothing else may live here |
$1B00-$1BEF |
240 | SCRATCH | Shared state needed from both banks |
$1BF0-$1BFF |
16 | MAILBOX | Fixed test mailbox (below) |
$1C01-$1C0C |
12 | header | BASIC 7 stub 10 SYS 7181 |
$1C0D-$B7FF |
39923 | MAIN | STARTUP (always first, entry at $1C0D), CODE, RODATA, DATA, COMMON load image, BSS |
$B800-$BFFF |
2048 | SWSTACK | Compiler software stack |
$C000-$FFFF |
system ROM | KERNAL/editor in both compiler states |
$1300-$1BFF is the C128's free application area: after boot x128 shows only
the power-on fill pattern there. All of $0000-$1FFF is bottom common RAM, so
COMMON, DISKBUF, private ZP, SCRATCH, and MAILBOX are visible from bank 1.
| Range | Size | Name | Contents |
|---|---|---|---|
$0000-$1FFF |
hidden | Covered by bottom common RAM in compiler states | |
$2000-$BFFF |
40960 | BANK1 / TABLES |
Names, symbols, class/interface/type records, pass workspaces |
$C000-$FFFF |
unmapped | System ROM is visible here instead; BASIC string space at the top of bank 1 is untouched |
Bank-1 data is reached only through mmu.s helpers (mmu_peek1/mmu_poke1
with the zero-page pointer mmu_ptr, and later block-copy routines), or by
code in COMMON. MAIN code never runs while bank 1 is mapped, because MAIN above
$1FFF is not visible then.
BASIC 7 keeps variables in bank 1 from $0400. The compiler is started with
RUN, which clears variables, so overwriting $2000-$BFFF loses no BASIC
state.
In compiler states P0 points at bank 0 page $1A, so the compiler owns the
whole logical zero page $02-$FF (linker area ZP, 254 bytes). $00/$01 are
the 8502 port and are never allocated. Modules allocate zero page only through
the ZEROPAGE segment. Current users: mmu_ptr (2 bytes).
System zero page stays intact. KERNAL calls switch P0 back to $0000 for the
call. While P0 is relocated, the system zero page is still readable at
$1A00-$1AFF (the MMU swaps the two pages), e.g. ST at $1A90.
$FF17) jumps via
$0314 into BASIC's handler, which uses system zero page and would corrupt
the private page. kcall enables IRQs only for the duration of a KERNAL call,
in system state.$FF05 uses no zero page: it pushes
A/X/Y/CR, sets CR=0, and jumps via $0318. mmu_init points $0318 at
mmu_nmi_guard (in COMMON), which reads the CIA #2 ICR, counts the event,
and exits through $FF33 (pull CR/Y/X/A, RTI). RESTORE is therefore ignored
while the compiler runs. mmu_shutdown restores $0318.Defined in src/common/mailbox.inc. Used by platform tests, the compiler, and
generated programs, and read by the harness after the program returns.
| Address | Field | Meaning |
|---|---|---|
$1BF0 |
magic 0 | $4E (N) once initialized |
$1BF1 |
magic 1 | $38 (8) |
$1BF2 |
producer | $01 platform test, $02 compiler, $03 generated program |
$1BF3 |
status | $01 running, $A5 pass, $FA fail |
$1BF4-$1BF5 |
code | Little-endian diagnostic, fault, or failed-check code; 0 on pass |
$1BF6-$1BF7 |
address | Little-endian fault or completion address |
$1BF8-$1BFF |
data | Eight producer-defined bytes |
Protocol:
$01 before doing any work.$A5 or $FA. A
status still $01 at the timeout means the producer hung or crashed. A
missing magic means it never started.scripts/verify-map-skeleton.ps1 links src/compiler/mmu.s with
tests/platform/map-skeleton.s using cfg/compiler.cfg, then:
skel_entry at $1C0D, MAILBOX at
$1BF0, COMMON within $1300-$18FF, TABLES within $2000-$BFFF.4E 38 01 A5 00 00 … 01 4E 1A C5. All six checks pass:| Check | What it proves |
|---|---|
| ZP | A store to logical ZP lands at $1Axx; system ZP is unchanged |
| KCALL | CHROUT via kcall_inline from both states; private ZP and CR/P0 intact afterwards |
| BANK1 | First and last TABLES bytes hold bank-1 values; bank 0 at the same addresses unchanged |
| COMMON | DISKBUF/SCRATCH written in bank 0 read back in bank 1; mailbox written from bank 1 |
| NMI | A CIA #2 timer NMI taken in the bank-1 state returns with CR $4E, P0 $1A, sentinel $C5, and the same SP |
| RESTORE | After mmu_shutdown: CR/RCR/P0/P1/$0318 and SP equal their entry values |
Negative control: forcing P0L to $00 in mmu_bank0/1 makes the skeleton
report FAIL with code $000F (ZP, KCALL, BANK1, NMI).
Powered by TurnKey Linux.