|
|
@@ -692,17 +692,25 @@ initialised past it (`MOV pc,#$2D7C`). Same shape here, and now actually done:
|
|
|
image-absolute. **No relocation pass is needed** — worth having paid for, since
|
|
|
a linker that has to walk fixups is a linker that can get them wrong.
|
|
|
|
|
|
-Current blob: **391 bytes**, 14 entries, 37 branch targets, offsets read back
|
|
|
+Current blob: **436 bytes**, 14 entries, 38 branch targets, offsets read back
|
|
|
out of the assembled bytes by `tests/check_runtime.py` rather than asserted by
|
|
|
hand:
|
|
|
|
|
|
| entry | offset | entry | offset | entry | offset |
|
|
|
|---|---|---|---|---|---|
|
|
|
-| `initmem` | 0 | `wrint` | 36 | `rdint` | 167 |
|
|
|
-| `progend` | 28 | `wrchar` | 97 | `rdchar` | 268 |
|
|
|
-| `stackchk` | 35 | `wrbool` | 109 | `rdbool` | 289 |
|
|
|
-| `halt` | 28 | `wrreal` | 132 | `rdln` | 335 |
|
|
|
-| | | `wrln` | 140 | `wrtinl` | 148 |
|
|
|
+| `initmem` | 0 | `wrint` | 36 | `rdint` | 171 |
|
|
|
+| `progend` | 28 | `wrchar` | 97 | `rdchar` | 279 |
|
|
|
+| `stackchk` | 35 | `wrbool` | 111 | `rdbool` | 302 |
|
|
|
+| `halt` | 28 | `wrreal` | 136 | `rdln` | 350 |
|
|
|
+| | | `wrln` | 144 | `wrtinl` | 152 |
|
|
|
+
|
|
|
+Every number in that table is measured, and that is the point: it was last
|
|
|
+correct when the blob was 391 bytes, and the entries quietly moved as it grew
|
|
|
+to 436 — six of the fourteen offsets in the previous version of this table were
|
|
|
+stale, and the size was stale too. A restated constant that has drifted is
|
|
|
+worse than a derived one, which is why the compiler asks
|
|
|
+`Runtime.RT_Entry` instead (below) and why the checkers locate the runtime by
|
|
|
+its own signature rather than by a literal.
|
|
|
|
|
|
The `TU_*` constants in `Compiler.mod` are **assigned from
|
|
|
`Runtime.RT_Entry` in `Inittur`**, not written down, so a runtime edit that
|
|
|
@@ -753,10 +761,15 @@ Two label-name plus fixup list: `rel8`, `rel16` and runtime-data addresses are
|
|
|
all patched after the blob is placed, so nothing depends on a hand-computed
|
|
|
displacement.
|
|
|
|
|
|
-**It has still never executed.** The encodings are now audited, golden-pinned
|
|
|
-and non-vacuity-proved, which is a much stronger static claim than "it
|
|
|
-assembles" — but a static check cannot tell you the code *works*, only that it
|
|
|
-is what was intended. See the executor section.
|
|
|
+**It executes.** Every entry is called directly under qemu by
|
|
|
+`tests/rt_exec.py` — 36 cases, all passing — with the register contract each
|
|
|
+entry must honour stated rather than assumed, which is how `wrchar` and
|
|
|
+`wrbool` were caught destroying the caller's BP. That milestone
|
|
|
+(`v-TP3-BP-CONTRACT`) is the reason this paragraph no longer says the runtime
|
|
|
+has never run; it did, for two releases. What is *not* covered is what a direct
|
|
|
+call cannot reach: the runtime is still measured entry-by-entry rather than
|
|
|
+against TP3's own binary, so this is a compatibility claim and not a
|
|
|
+byte-for-byte reproduction of the original's.
|
|
|
|
|
|
### The program image — `shell/Linker.mod`
|
|
|
|
|
|
@@ -782,9 +795,10 @@ assertion, rather than asking the compiler where it thinks the header is.
|
|
|
last dot, padded with a zero gap to `max(pc, dc)`; its stack sits at the segment
|
|
|
top (`SS = SP = CS:FFFE`), which is where DOS puts it.
|
|
|
|
|
|
-**Known limit:** the data area starts at a fixed `rtSz + 1000H` (391 + 4096 =
|
|
|
-4481), so a program whose code exceeds 4 KiB runs into its own data. Every
|
|
|
-fixture is at 4491 or 4493 bytes. Documented rather than fixed, because the
|
|
|
+**Known limit:** the data area starts at a fixed `rtSz + 1000H` (436 + 4096 =
|
|
|
+4532), so a program whose code exceeds 4 KiB runs into its own data. Every
|
|
|
+fixture's image is between 4539 and 4547 bytes. Documented rather than fixed,
|
|
|
+because the
|
|
|
original has the same fixed-offset behaviour.
|
|
|
|
|
|
### String literals — `writeln('hi')`
|