Runtime.def 4.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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. E_RdStr = 16 ; (* readln(s)/read(s) of a string variable: address
  30. on the stack, limit in CX; TPSRC4 xrdstr *)
  31. E_StrStore = 17 ; (* s := t for string variables: destination and
  32. source addresses on the stack, limit in CX;
  33. TPSRC2 strstore *)
  34. (* Where a .COM's first byte ends up. DOS loads a .COM at CS:0100 (the
  35. 100 bytes below are the PSP), and CS = DS, so an image offset K is at
  36. DS:(K + 0100h). EVERY address baked into the image as an absolute
  37. literal must therefore carry this. It is here, in Runtime, because
  38. FixUp needs it and Compiler needs it, and one constant in one place is
  39. the only way a six-site bias can stay consistent - see the long note in
  40. Runtime.mod, which also records how the failure looks: the program
  41. runs, prints its first field, and then walks a $ that is 100h too low
  42. through the runtime's own code. *)
  43. LoadBias = 100H ;
  44. PROCEDURE RT_Build (base : CARDINAL) ;
  45. (* assemble the runtime; idempotent, called once at Compile time.
  46. `base' is the IMAGE OFFSET the runtime blob will be copied to. It is a
  47. parameter rather than an assumption because the image begins with a
  48. three-byte entry JMP, so the runtime does not sit at image offset 0 - and
  49. every address the runtime bakes into its own code (its data block, and the
  50. entry offsets RT_Entry hands back) has to be biased by it. The emitted
  51. BYTES are the same for any base, because both are computed after assembly,
  52. so the standalone probes and tests/runtime.golden pass 0 and are unaffected.
  53. NOTE, because it has already cost time: this .def file is HAND-MAINTAINED.
  54. gm2 reads X.def to resolve `FROM X IMPORT ...' and checks the
  55. implementation against it, but it does NOT rewrite it - a successful
  56. compile leaves X.def byte-identical, and deleting it makes gm2 fail with
  57. "the file containing the definition module « X » cannot be found" rather
  58. than regenerate it. So an interface change means editing Runtime.def by
  59. hand in the same commit, exactly as Editor.def was edited to add
  60. Editor.GotoOffset. Keep such changes ADDITIVE where possible: an
  61. unchanged procedure's declaration does not need re-typing, so only the
  62. lines that actually moved have to be right. *)
  63. PROCEDURE RT_Size () : CARDINAL ;
  64. (* size of the runtime in bytes - the offset at which the generated program
  65. starts inside the image *)
  66. PROCEDURE RT_Byte (i : CARDINAL) : BYTE ;
  67. (* i-th runtime byte, 0 past the end, for hex dumps *)
  68. PROCEDURE RT_Entry (i : CARDINAL) : CARDINAL ;
  69. (* offset of entry i (an E_* selector) inside the runtime; 0 if unknown *)
  70. PROCEDURE RT_CodeEnd () : CARDINAL ;
  71. (* offset where the code stops and the runtime's data block starts. Bytes
  72. from here on are strings and scratch, so disassembling them is
  73. meaningless; tests use this to sweep the code region only. *)
  74. END Runtime.