| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- DEFINITION MODULE Runtime ;
- (* 8086 runtime library for TP3-compiled programs.
- The original embeds its runtime in the compiler's own code segment and
- copies it to the front of the generated code buffer (TPSRC7 "copyrt":
- "MOV CX,#start / REPZ MOVS.B" with SI=DI=0, then "MOV pc,#$2D7C" so the
- generated program starts past it; the .COM writer emits the runtime as a
- block ahead of the program). Same shape here: RT_Build assembles the
- library into rt[0..RT_Size-1], the compiler copies it to the front of its
- code buffer (behind the entry JMP) and starts pc/dc past it, so the
- runtime's own data lives at low, link-time-constant addresses and needs no
- relocation. The "front" is now at RT_Build's `base' rather than at 0.
- Entry offsets are *derived* from where the code actually lands, not
- hardcoded - see RT_Entry. Everything the compiler calls is reached by a
- relative CALL, and both sides shift by the same runtime size, so the
- displacement arithmetic in EmCall is unaffected by the runtime being
- prepended. *)
- FROM SYSTEM IMPORT BYTE ;
- CONST
- (* entry selectors for RT_Entry *)
- E_InitMem = 0 ; E_ProgEnd = 1 ; E_StackChk = 2 ;
- E_WrInt = 3 ; E_WrChar = 4 ; E_WrBool = 5 ;
- E_WrReal = 6 ; E_WrLn = 7 ;
- E_RdInt = 8 ; E_RdChar = 9 ; E_RdBool = 10 ;
- E_RdLn = 11 ; E_Halt = 12 ; E_WrInl = 13 ;
- (* Where a .COM's first byte ends up. DOS loads a .COM at CS:0100 (the
- 100 bytes below are the PSP), and CS = DS, so an image offset K is at
- DS:(K + 0100h). EVERY address baked into the image as an absolute
- literal must therefore carry this. It is here, in Runtime, because
- FixUp needs it and Compiler needs it, and one constant in one place is
- the only way a six-site bias can stay consistent - see the long note in
- Runtime.mod, which also records how the failure looks: the program
- runs, prints its first field, and then walks a $ that is 100h too low
- through the runtime's own code. *)
- LoadBias = 100H ;
- PROCEDURE RT_Build (base : CARDINAL) ;
- (* assemble the runtime; idempotent, called once at Compile time.
- `base' is the IMAGE OFFSET the runtime blob will be copied to. It is a
- parameter rather than an assumption because the image begins with a
- three-byte entry JMP, so the runtime does not sit at image offset 0 - and
- every address the runtime bakes into its own code (its data block, and the
- entry offsets RT_Entry hands back) has to be biased by it. The emitted
- BYTES are the same for any base, because both are computed after assembly,
- so the standalone probes and tests/runtime.golden pass 0 and are unaffected.
- NOTE, because it has already cost time: this .def file is HAND-MAINTAINED.
- gm2 reads X.def to resolve `FROM X IMPORT ...' and checks the
- implementation against it, but it does NOT rewrite it - a successful
- compile leaves X.def byte-identical, and deleting it makes gm2 fail with
- "the file containing the definition module « X » cannot be found" rather
- than regenerate it. So an interface change means editing Runtime.def by
- hand in the same commit, exactly as Editor.def was edited to add
- Editor.GotoOffset. Keep such changes ADDITIVE where possible: an
- unchanged procedure's declaration does not need re-typing, so only the
- lines that actually moved have to be right. *)
- PROCEDURE RT_Size () : CARDINAL ;
- (* size of the runtime in bytes - the offset at which the generated program
- starts inside the image *)
- PROCEDURE RT_Byte (i : CARDINAL) : BYTE ;
- (* i-th runtime byte, 0 past the end, for hex dumps *)
- PROCEDURE RT_Entry (i : CARDINAL) : CARDINAL ;
- (* offset of entry i (an E_* selector) inside the runtime; 0 if unknown *)
- PROCEDURE RT_CodeEnd () : CARDINAL ;
- (* offset where the code stops and the runtime's data block starts. Bytes
- from here on are strings and scratch, so disassembling them is
- meaningless; tests use this to sweep the code region only. *)
- END Runtime.
|