BIN.ob07 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. MODULE BIN;
  2. IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS IN "./utils/UTILS.ob07";
  3. CONST
  4. RCODE* = 0; PICCODE* = RCODE + 1;
  5. RDATA* = 2; PICDATA* = RDATA + 1;
  6. RBSS* = 4; PICBSS* = RBSS + 1;
  7. RIMP* = 6; PICIMP* = RIMP + 1;
  8. IMPTAB* = 8;
  9. TYPE
  10. RELOC* = POINTER TO RECORD (LISTS.ITEM)
  11. opcode*: INTEGER;
  12. offset*: INTEGER
  13. END;
  14. IMPRT* = POINTER TO RECORD (LISTS.ITEM)
  15. nameoffs*: INTEGER;
  16. label*: INTEGER;
  17. OriginalFirstThunk*,
  18. FirstThunk*: INTEGER
  19. END;
  20. EXPRT* = POINTER TO RECORD (LISTS.ITEM)
  21. nameoffs*: INTEGER;
  22. label*: INTEGER
  23. END;
  24. PROGRAM* = POINTER TO RECORD
  25. code*: CHL.BYTELIST;
  26. data*: CHL.BYTELIST;
  27. labels: CHL.INTLIST;
  28. bss*: INTEGER;
  29. stack*: INTEGER;
  30. vmajor*,
  31. vminor*: WCHAR;
  32. modname*: INTEGER;
  33. _import*: CHL.BYTELIST;
  34. export*: CHL.BYTELIST;
  35. rel_list*: LISTS.LIST;
  36. imp_list*: LISTS.LIST;
  37. exp_list*: LISTS.LIST
  38. END;
  39. PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM;
  40. VAR
  41. program: PROGRAM;
  42. i: INTEGER;
  43. BEGIN
  44. NEW(program);
  45. program.bss := 0;
  46. program.labels := CHL.CreateIntList();
  47. FOR i := 0 TO NumberOfLabels - 1 DO
  48. CHL.PushInt(program.labels, 0)
  49. END;
  50. program.rel_list := LISTS.create(NIL);
  51. program.imp_list := LISTS.create(NIL);
  52. program.exp_list := LISTS.create(NIL);
  53. program.data := CHL.CreateByteList();
  54. program.code := CHL.CreateByteList();
  55. program._import := CHL.CreateByteList();
  56. program.export := CHL.CreateByteList()
  57. RETURN program
  58. END create;
  59. PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR);
  60. BEGIN
  61. program.bss := bss;
  62. program.stack := stack;
  63. program.vmajor := vmajor;
  64. program.vminor := vminor
  65. END SetParams;
  66. PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER);
  67. VAR
  68. cmd: RELOC;
  69. BEGIN
  70. NEW(cmd);
  71. cmd.opcode := opcode;
  72. cmd.offset := CHL.Length(program.code);
  73. LISTS.push(program.rel_list, cmd)
  74. END PutReloc;
  75. PROCEDURE PutData* (program: PROGRAM; b: BYTE);
  76. BEGIN
  77. CHL.PushByte(program.data, b)
  78. END PutData;
  79. PROCEDURE get32le* (_array: CHL.BYTELIST; idx: INTEGER): INTEGER;
  80. VAR
  81. i: INTEGER;
  82. x: INTEGER;
  83. BEGIN
  84. x := 0;
  85. FOR i := 3 TO 0 BY -1 DO
  86. x := LSL(x, 8) + CHL.GetByte(_array, idx + i)
  87. END;
  88. IF UTILS.bit_depth = 64 THEN
  89. x := LSL(x, 16);
  90. x := LSL(x, 16);
  91. x := ASR(x, 16);
  92. x := ASR(x, 16)
  93. END
  94. RETURN x
  95. END get32le;
  96. PROCEDURE put32le* (_array: CHL.BYTELIST; idx: INTEGER; x: INTEGER);
  97. VAR
  98. i: INTEGER;
  99. BEGIN
  100. FOR i := 0 TO 3 DO
  101. CHL.SetByte(_array, idx + i, UTILS.Byte(x, i))
  102. END
  103. END put32le;
  104. PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER);
  105. VAR
  106. i: INTEGER;
  107. BEGIN
  108. FOR i := 0 TO 3 DO
  109. CHL.PushByte(program.data, UTILS.Byte(x, i))
  110. END
  111. END PutData32LE;
  112. PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER);
  113. VAR
  114. i: INTEGER;
  115. BEGIN
  116. FOR i := 0 TO 7 DO
  117. CHL.PushByte(program.data, UTILS.Byte(x, i))
  118. END
  119. END PutData64LE;
  120. PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR);
  121. VAR
  122. i: INTEGER;
  123. BEGIN
  124. i := 0;
  125. WHILE s[i] # 0X DO
  126. PutData(program, ORD(s[i]));
  127. INC(i)
  128. END
  129. END PutDataStr;
  130. PROCEDURE PutCode* (program: PROGRAM; b: BYTE);
  131. BEGIN
  132. CHL.PushByte(program.code, b)
  133. END PutCode;
  134. PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER);
  135. VAR
  136. i: INTEGER;
  137. BEGIN
  138. FOR i := 0 TO 3 DO
  139. CHL.PushByte(program.code, UTILS.Byte(x, i))
  140. END
  141. END PutCode32LE;
  142. PROCEDURE PutCode16LE* (program: PROGRAM; x: INTEGER);
  143. BEGIN
  144. CHL.PushByte(program.code, UTILS.Byte(x, 0));
  145. CHL.PushByte(program.code, UTILS.Byte(x, 1))
  146. END PutCode16LE;
  147. PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER);
  148. BEGIN
  149. CHL.SetInt(program.labels, label, offset)
  150. END SetLabel;
  151. PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
  152. VAR
  153. imp: IMPRT;
  154. BEGIN
  155. CHL.PushByte(program._import, 0);
  156. CHL.PushByte(program._import, 0);
  157. IF ODD(CHL.Length(program._import)) THEN
  158. CHL.PushByte(program._import, 0)
  159. END;
  160. NEW(imp);
  161. imp.nameoffs := CHL.PushStr(program._import, name);
  162. imp.label := label;
  163. LISTS.push(program.imp_list, imp)
  164. END Import;
  165. PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN;
  166. VAR
  167. i, j: INTEGER;
  168. BEGIN
  169. i := a.nameoffs;
  170. j := b.nameoffs;
  171. WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) &
  172. (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO
  173. INC(i);
  174. INC(j)
  175. END
  176. RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j)
  177. END less;
  178. PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER);
  179. VAR
  180. exp, cur: EXPRT;
  181. BEGIN
  182. NEW(exp);
  183. exp.label := CHL.GetInt(program.labels, label);
  184. exp.nameoffs := CHL.PushStr(program.export, name);
  185. cur := program.exp_list.first(EXPRT);
  186. WHILE (cur # NIL) & less(program.export, cur, exp) DO
  187. cur := cur.next(EXPRT)
  188. END;
  189. IF cur # NIL THEN
  190. IF cur.prev # NIL THEN
  191. LISTS.insert(program.exp_list, cur.prev, exp)
  192. ELSE
  193. LISTS.insertL(program.exp_list, cur, exp)
  194. END
  195. ELSE
  196. LISTS.push(program.exp_list, exp)
  197. END
  198. END Export;
  199. PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT;
  200. VAR
  201. _import, res: IMPRT;
  202. BEGIN
  203. _import := program.imp_list.first(IMPRT);
  204. res := NIL;
  205. WHILE (_import # NIL) & (n >= 0) DO
  206. IF _import.label # 0 THEN
  207. res := _import;
  208. DEC(n)
  209. END;
  210. _import := _import.next(IMPRT)
  211. END;
  212. ASSERT(n = -1)
  213. RETURN res
  214. END GetIProc;
  215. PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER;
  216. RETURN CHL.GetInt(program.labels, label)
  217. END GetLabel;
  218. PROCEDURE NewLabel* (program: PROGRAM);
  219. BEGIN
  220. CHL.PushInt(program.labels, 0)
  221. END NewLabel;
  222. PROCEDURE fixup* (program: PROGRAM);
  223. VAR
  224. rel: RELOC;
  225. imp: IMPRT;
  226. nproc: INTEGER;
  227. L: INTEGER;
  228. BEGIN
  229. nproc := 0;
  230. imp := program.imp_list.first(IMPRT);
  231. WHILE imp # NIL DO
  232. IF imp.label # 0 THEN
  233. CHL.SetInt(program.labels, imp.label, nproc);
  234. INC(nproc)
  235. END;
  236. imp := imp.next(IMPRT)
  237. END;
  238. rel := program.rel_list.first(RELOC);
  239. WHILE rel # NIL DO
  240. IF rel.opcode IN {RIMP, PICIMP} THEN
  241. L := get32le(program.code, rel.offset);
  242. put32le(program.code, rel.offset, GetLabel(program, L))
  243. END;
  244. rel := rel.next(RELOC)
  245. END
  246. END fixup;
  247. PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR);
  248. VAR
  249. i, k: INTEGER;
  250. PROCEDURE hexdgt (dgt: CHAR): INTEGER;
  251. VAR
  252. res: INTEGER;
  253. BEGIN
  254. IF dgt < "A" THEN
  255. res := ORD(dgt) - ORD("0")
  256. ELSE
  257. res := ORD(dgt) - ORD("A") + 10
  258. END
  259. RETURN res
  260. END hexdgt;
  261. BEGIN
  262. k := LENGTH(hex);
  263. ASSERT(~ODD(k));
  264. k := k DIV 2;
  265. FOR i := 0 TO k - 1 DO
  266. _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1])
  267. END;
  268. INC(idx, k)
  269. END InitArray;
  270. END BIN.