Runtime.def 4.2 KB

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