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