Rev 7696 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7983 | leency | 1 | (* |
7597 | akron1 | 2 | BSD 2-Clause License |
3 | |||
7696 | akron1 | 4 | Copyright (c) 2018-2019, Anton Krotov |
7597 | akron1 | 5 | All rights reserved. |
6 | *) |
||
7 | |||
8 | MODULE BIN; |
||
9 | |||
7693 | akron1 | 10 | IMPORT LISTS, CHL := CHUNKLISTS, ARITH, UTILS; |
7597 | akron1 | 11 | |
12 | |||
13 | CONST |
||
14 | |||
7983 | leency | 15 | RCODE* = 0; PICCODE* = RCODE + 1; |
16 | RDATA* = 2; PICDATA* = RDATA + 1; |
||
17 | RBSS* = 4; PICBSS* = RBSS + 1; |
||
18 | RIMP* = 6; PICIMP* = RIMP + 1; |
||
7597 | akron1 | 19 | |
7983 | leency | 20 | IMPTAB* = 8; |
7597 | akron1 | 21 | |
22 | |||
23 | TYPE |
||
24 | |||
25 | RELOC* = POINTER TO RECORD (LISTS.ITEM) |
||
26 | |||
27 | opcode*: INTEGER; |
||
28 | offset*: INTEGER |
||
29 | |||
30 | END; |
||
31 | |||
32 | IMPRT* = POINTER TO RECORD (LISTS.ITEM) |
||
33 | |||
34 | nameoffs*: INTEGER; |
||
35 | label*: INTEGER; |
||
36 | |||
37 | OriginalFirstThunk*, |
||
38 | FirstThunk*: INTEGER |
||
39 | |||
40 | END; |
||
41 | |||
42 | EXPRT* = POINTER TO RECORD (LISTS.ITEM) |
||
43 | |||
44 | nameoffs*: INTEGER; |
||
45 | label*: INTEGER |
||
46 | |||
47 | END; |
||
48 | |||
49 | PROGRAM* = POINTER TO RECORD |
||
50 | |||
51 | code*: CHL.BYTELIST; |
||
52 | data*: CHL.BYTELIST; |
||
53 | labels: CHL.INTLIST; |
||
54 | bss*: INTEGER; |
||
55 | stack*: INTEGER; |
||
56 | vmajor*, |
||
57 | vminor*: WCHAR; |
||
58 | modname*: INTEGER; |
||
59 | import*: CHL.BYTELIST; |
||
60 | export*: CHL.BYTELIST; |
||
61 | rel_list*: LISTS.LIST; |
||
62 | imp_list*: LISTS.LIST; |
||
63 | exp_list*: LISTS.LIST |
||
64 | |||
65 | END; |
||
66 | |||
67 | |||
68 | PROCEDURE create* (NumberOfLabels: INTEGER): PROGRAM; |
||
69 | VAR |
||
70 | program: PROGRAM; |
||
71 | i: INTEGER; |
||
72 | |||
73 | BEGIN |
||
74 | NEW(program); |
||
75 | |||
76 | program.bss := 0; |
||
77 | |||
78 | program.labels := CHL.CreateIntList(); |
||
79 | FOR i := 0 TO NumberOfLabels - 1 DO |
||
80 | CHL.PushInt(program.labels, 0) |
||
81 | END; |
||
82 | |||
83 | program.rel_list := LISTS.create(NIL); |
||
84 | program.imp_list := LISTS.create(NIL); |
||
85 | program.exp_list := LISTS.create(NIL); |
||
86 | |||
87 | program.data := CHL.CreateByteList(); |
||
88 | program.code := CHL.CreateByteList(); |
||
89 | program.import := CHL.CreateByteList(); |
||
90 | program.export := CHL.CreateByteList() |
||
91 | |||
92 | RETURN program |
||
93 | END create; |
||
94 | |||
95 | |||
96 | PROCEDURE SetParams* (program: PROGRAM; bss, stack: INTEGER; vmajor, vminor: WCHAR); |
||
97 | BEGIN |
||
98 | program.bss := bss; |
||
99 | program.stack := stack; |
||
100 | program.vmajor := vmajor; |
||
101 | program.vminor := vminor |
||
102 | END SetParams; |
||
103 | |||
104 | |||
105 | PROCEDURE PutReloc* (program: PROGRAM; opcode: INTEGER); |
||
106 | VAR |
||
107 | cmd: RELOC; |
||
108 | |||
109 | BEGIN |
||
110 | NEW(cmd); |
||
111 | cmd.opcode := opcode; |
||
112 | cmd.offset := CHL.Length(program.code); |
||
113 | LISTS.push(program.rel_list, cmd) |
||
114 | END PutReloc; |
||
115 | |||
116 | |||
117 | PROCEDURE PutData* (program: PROGRAM; b: BYTE); |
||
118 | BEGIN |
||
119 | CHL.PushByte(program.data, b) |
||
120 | END PutData; |
||
121 | |||
122 | |||
123 | PROCEDURE get32le* (array: CHL.BYTELIST; idx: INTEGER): INTEGER; |
||
124 | VAR |
||
125 | i: INTEGER; |
||
126 | x: INTEGER; |
||
127 | |||
128 | BEGIN |
||
129 | x := 0; |
||
130 | |||
131 | FOR i := 3 TO 0 BY -1 DO |
||
132 | x := LSL(x, 8) + CHL.GetByte(array, idx + i) |
||
133 | END; |
||
134 | |||
135 | IF UTILS.bit_depth = 64 THEN |
||
7693 | akron1 | 136 | x := LSL(x, 16); |
137 | x := LSL(x, 16); |
||
138 | x := ASR(x, 16); |
||
139 | x := ASR(x, 16) |
||
7597 | akron1 | 140 | END |
141 | |||
142 | RETURN x |
||
143 | END get32le; |
||
144 | |||
145 | |||
146 | PROCEDURE put32le* (array: CHL.BYTELIST; idx: INTEGER; x: INTEGER); |
||
147 | VAR |
||
148 | i: INTEGER; |
||
149 | |||
150 | BEGIN |
||
151 | FOR i := 0 TO 3 DO |
||
7693 | akron1 | 152 | CHL.SetByte(array, idx + i, UTILS.Byte(x, i)) |
7597 | akron1 | 153 | END |
154 | END put32le; |
||
155 | |||
156 | |||
157 | PROCEDURE PutData32LE* (program: PROGRAM; x: INTEGER); |
||
158 | VAR |
||
159 | i: INTEGER; |
||
160 | |||
161 | BEGIN |
||
162 | FOR i := 0 TO 3 DO |
||
7693 | akron1 | 163 | CHL.PushByte(program.data, UTILS.Byte(x, i)) |
7597 | akron1 | 164 | END |
165 | END PutData32LE; |
||
166 | |||
167 | |||
168 | PROCEDURE PutData64LE* (program: PROGRAM; x: INTEGER); |
||
169 | VAR |
||
170 | i: INTEGER; |
||
171 | |||
172 | BEGIN |
||
173 | FOR i := 0 TO 7 DO |
||
7693 | akron1 | 174 | CHL.PushByte(program.data, UTILS.Byte(x, i)) |
7597 | akron1 | 175 | END |
176 | END PutData64LE; |
||
177 | |||
178 | |||
179 | PROCEDURE PutDataStr* (program: PROGRAM; s: ARRAY OF CHAR); |
||
180 | VAR |
||
181 | i: INTEGER; |
||
182 | |||
183 | BEGIN |
||
184 | i := 0; |
||
185 | WHILE s[i] # 0X DO |
||
186 | PutData(program, ORD(s[i])); |
||
187 | INC(i) |
||
188 | END |
||
189 | END PutDataStr; |
||
190 | |||
191 | |||
192 | PROCEDURE PutCode* (program: PROGRAM; b: BYTE); |
||
193 | BEGIN |
||
194 | CHL.PushByte(program.code, b) |
||
195 | END PutCode; |
||
196 | |||
197 | |||
198 | PROCEDURE PutCode32LE* (program: PROGRAM; x: INTEGER); |
||
199 | VAR |
||
200 | i: INTEGER; |
||
201 | |||
202 | BEGIN |
||
203 | FOR i := 0 TO 3 DO |
||
7693 | akron1 | 204 | CHL.PushByte(program.code, UTILS.Byte(x, i)) |
7597 | akron1 | 205 | END |
206 | END PutCode32LE; |
||
207 | |||
208 | |||
7983 | leency | 209 | PROCEDURE PutCode16LE* (program: PROGRAM; x: INTEGER); |
210 | BEGIN |
||
211 | CHL.PushByte(program.code, UTILS.Byte(x, 0)); |
||
212 | CHL.PushByte(program.code, UTILS.Byte(x, 1)) |
||
213 | END PutCode16LE; |
||
214 | |||
215 | |||
7597 | akron1 | 216 | PROCEDURE SetLabel* (program: PROGRAM; label, offset: INTEGER); |
217 | BEGIN |
||
218 | CHL.SetInt(program.labels, label, offset) |
||
219 | END SetLabel; |
||
220 | |||
221 | |||
222 | PROCEDURE Import* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); |
||
223 | VAR |
||
224 | imp: IMPRT; |
||
225 | |||
226 | BEGIN |
||
227 | CHL.PushByte(program.import, 0); |
||
228 | CHL.PushByte(program.import, 0); |
||
229 | |||
230 | IF ODD(CHL.Length(program.import)) THEN |
||
231 | CHL.PushByte(program.import, 0) |
||
232 | END; |
||
233 | |||
234 | NEW(imp); |
||
7693 | akron1 | 235 | imp.nameoffs := CHL.PushStr(program.import, name); |
7597 | akron1 | 236 | imp.label := label; |
7693 | akron1 | 237 | LISTS.push(program.imp_list, imp) |
7597 | akron1 | 238 | END Import; |
239 | |||
240 | |||
241 | PROCEDURE less (bytes: CHL.BYTELIST; a, b: EXPRT): BOOLEAN; |
||
242 | VAR |
||
243 | i, j: INTEGER; |
||
244 | |||
245 | BEGIN |
||
246 | i := a.nameoffs; |
||
247 | j := b.nameoffs; |
||
248 | |||
249 | WHILE (CHL.GetByte(bytes, i) # 0) & (CHL.GetByte(bytes, j) # 0) & |
||
250 | (CHL.GetByte(bytes, i) = CHL.GetByte(bytes, j)) DO |
||
251 | INC(i); |
||
252 | INC(j) |
||
253 | END |
||
254 | |||
255 | RETURN CHL.GetByte(bytes, i) < CHL.GetByte(bytes, j) |
||
256 | END less; |
||
257 | |||
258 | |||
259 | PROCEDURE Export* (program: PROGRAM; name: ARRAY OF CHAR; label: INTEGER); |
||
260 | VAR |
||
261 | exp, cur: EXPRT; |
||
262 | |||
263 | BEGIN |
||
264 | NEW(exp); |
||
265 | exp.label := CHL.GetInt(program.labels, label); |
||
7693 | akron1 | 266 | exp.nameoffs := CHL.PushStr(program.export, name); |
7597 | akron1 | 267 | |
268 | cur := program.exp_list.first(EXPRT); |
||
269 | WHILE (cur # NIL) & less(program.export, cur, exp) DO |
||
270 | cur := cur.next(EXPRT) |
||
271 | END; |
||
272 | |||
273 | IF cur # NIL THEN |
||
274 | IF cur.prev # NIL THEN |
||
275 | LISTS.insert(program.exp_list, cur.prev, exp) |
||
276 | ELSE |
||
277 | LISTS.insertL(program.exp_list, cur, exp) |
||
278 | END |
||
279 | ELSE |
||
280 | LISTS.push(program.exp_list, exp) |
||
281 | END |
||
282 | |||
283 | END Export; |
||
284 | |||
285 | |||
286 | PROCEDURE GetIProc* (program: PROGRAM; n: INTEGER): IMPRT; |
||
287 | VAR |
||
288 | import: IMPRT; |
||
289 | res: IMPRT; |
||
290 | |||
291 | BEGIN |
||
292 | import := program.imp_list.first(IMPRT); |
||
293 | |||
294 | res := NIL; |
||
295 | WHILE (import # NIL) & (n >= 0) DO |
||
296 | IF import.label # 0 THEN |
||
297 | res := import; |
||
298 | DEC(n) |
||
299 | END; |
||
300 | import := import.next(IMPRT) |
||
301 | END; |
||
302 | |||
303 | ASSERT(n = -1) |
||
304 | RETURN res |
||
305 | END GetIProc; |
||
306 | |||
307 | |||
308 | PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER; |
||
309 | RETURN CHL.GetInt(program.labels, label) |
||
310 | END GetLabel; |
||
311 | |||
312 | |||
313 | PROCEDURE NewLabel* (program: PROGRAM); |
||
314 | BEGIN |
||
315 | CHL.PushInt(program.labels, 0) |
||
316 | END NewLabel; |
||
317 | |||
318 | |||
319 | PROCEDURE fixup* (program: PROGRAM); |
||
320 | VAR |
||
321 | rel: RELOC; |
||
322 | imp: IMPRT; |
||
323 | nproc: INTEGER; |
||
324 | L: INTEGER; |
||
325 | |||
326 | BEGIN |
||
327 | |||
328 | nproc := 0; |
||
329 | imp := program.imp_list.first(IMPRT); |
||
330 | WHILE imp # NIL DO |
||
331 | IF imp.label # 0 THEN |
||
332 | CHL.SetInt(program.labels, imp.label, nproc); |
||
333 | INC(nproc) |
||
334 | END; |
||
335 | imp := imp.next(IMPRT) |
||
336 | END; |
||
337 | |||
338 | rel := program.rel_list.first(RELOC); |
||
339 | WHILE rel # NIL DO |
||
340 | |||
341 | IF rel.opcode IN {RIMP, PICIMP} THEN |
||
342 | L := get32le(program.code, rel.offset); |
||
343 | put32le(program.code, rel.offset, GetLabel(program, L)) |
||
344 | END; |
||
345 | |||
346 | rel := rel.next(RELOC) |
||
347 | END |
||
348 | |||
349 | END fixup; |
||
350 | |||
351 | |||
352 | PROCEDURE InitArray* (VAR array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); |
||
353 | VAR |
||
354 | i, k: INTEGER; |
||
355 | |||
356 | |||
357 | PROCEDURE hexdgt (dgt: CHAR): INTEGER; |
||
358 | VAR |
||
359 | res: INTEGER; |
||
360 | |||
361 | BEGIN |
||
362 | IF dgt < "A" THEN |
||
363 | res := ORD(dgt) - ORD("0") |
||
364 | ELSE |
||
365 | res := ORD(dgt) - ORD("A") + 10 |
||
366 | END |
||
367 | |||
368 | RETURN res |
||
369 | END hexdgt; |
||
370 | |||
371 | |||
372 | BEGIN |
||
373 | k := LENGTH(hex); |
||
374 | ASSERT(~ODD(k)); |
||
375 | k := k DIV 2; |
||
376 | |||
377 | FOR i := 0 TO k - 1 DO |
||
378 | array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) |
||
379 | END; |
||
380 | |||
7693 | akron1 | 381 | INC(idx, k) |
7597 | akron1 | 382 | END InitArray; |
383 | |||
384 | |||
7983 | leency | 385 | END BIN.>> |