Rev 7983 | 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 | |||
8097 | maxcodehac | 4 | Copyright (c) 2018-2020, 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; |
||
8097 | maxcodehac | 59 | _import*: CHL.BYTELIST; |
7597 | akron1 | 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 | |||
8097 | maxcodehac | 87 | program.data := CHL.CreateByteList(); |
88 | program.code := CHL.CreateByteList(); |
||
89 | program._import := CHL.CreateByteList(); |
||
90 | program.export := CHL.CreateByteList() |
||
7597 | akron1 | 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 | |||
8097 | maxcodehac | 123 | PROCEDURE get32le* (_array: CHL.BYTELIST; idx: INTEGER): INTEGER; |
7597 | akron1 | 124 | VAR |
125 | i: INTEGER; |
||
126 | x: INTEGER; |
||
127 | |||
128 | BEGIN |
||
129 | x := 0; |
||
130 | |||
131 | FOR i := 3 TO 0 BY -1 DO |
||
8097 | maxcodehac | 132 | x := LSL(x, 8) + CHL.GetByte(_array, idx + i) |
7597 | akron1 | 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 | |||
8097 | maxcodehac | 146 | PROCEDURE put32le* (_array: CHL.BYTELIST; idx: INTEGER; x: INTEGER); |
7597 | akron1 | 147 | VAR |
148 | i: INTEGER; |
||
149 | |||
150 | BEGIN |
||
151 | FOR i := 0 TO 3 DO |
||
8097 | maxcodehac | 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 |
||
8097 | maxcodehac | 227 | CHL.PushByte(program._import, 0); |
228 | CHL.PushByte(program._import, 0); |
||
7597 | akron1 | 229 | |
8097 | maxcodehac | 230 | IF ODD(CHL.Length(program._import)) THEN |
231 | CHL.PushByte(program._import, 0) |
||
7597 | akron1 | 232 | END; |
233 | |||
234 | NEW(imp); |
||
8097 | maxcodehac | 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 |
||
8097 | maxcodehac | 288 | _import, res: IMPRT; |
7597 | akron1 | 289 | |
290 | BEGIN |
||
8097 | maxcodehac | 291 | _import := program.imp_list.first(IMPRT); |
7597 | akron1 | 292 | |
293 | res := NIL; |
||
8097 | maxcodehac | 294 | WHILE (_import # NIL) & (n >= 0) DO |
295 | IF _import.label # 0 THEN |
||
296 | res := _import; |
||
7597 | akron1 | 297 | DEC(n) |
298 | END; |
||
8097 | maxcodehac | 299 | _import := _import.next(IMPRT) |
7597 | akron1 | 300 | END; |
301 | |||
302 | ASSERT(n = -1) |
||
303 | RETURN res |
||
304 | END GetIProc; |
||
305 | |||
306 | |||
307 | PROCEDURE GetLabel* (program: PROGRAM; label: INTEGER): INTEGER; |
||
308 | RETURN CHL.GetInt(program.labels, label) |
||
309 | END GetLabel; |
||
310 | |||
311 | |||
312 | PROCEDURE NewLabel* (program: PROGRAM); |
||
313 | BEGIN |
||
314 | CHL.PushInt(program.labels, 0) |
||
315 | END NewLabel; |
||
316 | |||
317 | |||
318 | PROCEDURE fixup* (program: PROGRAM); |
||
319 | VAR |
||
320 | rel: RELOC; |
||
321 | imp: IMPRT; |
||
322 | nproc: INTEGER; |
||
323 | L: INTEGER; |
||
324 | |||
325 | BEGIN |
||
326 | |||
327 | nproc := 0; |
||
328 | imp := program.imp_list.first(IMPRT); |
||
329 | WHILE imp # NIL DO |
||
330 | IF imp.label # 0 THEN |
||
331 | CHL.SetInt(program.labels, imp.label, nproc); |
||
332 | INC(nproc) |
||
333 | END; |
||
334 | imp := imp.next(IMPRT) |
||
335 | END; |
||
336 | |||
337 | rel := program.rel_list.first(RELOC); |
||
338 | WHILE rel # NIL DO |
||
339 | |||
340 | IF rel.opcode IN {RIMP, PICIMP} THEN |
||
341 | L := get32le(program.code, rel.offset); |
||
342 | put32le(program.code, rel.offset, GetLabel(program, L)) |
||
343 | END; |
||
344 | |||
345 | rel := rel.next(RELOC) |
||
346 | END |
||
347 | |||
348 | END fixup; |
||
349 | |||
350 | |||
8097 | maxcodehac | 351 | PROCEDURE InitArray* (VAR _array: ARRAY OF BYTE; VAR idx: INTEGER; hex: ARRAY OF CHAR); |
7597 | akron1 | 352 | VAR |
353 | i, k: INTEGER; |
||
354 | |||
355 | |||
356 | PROCEDURE hexdgt (dgt: CHAR): INTEGER; |
||
357 | VAR |
||
358 | res: INTEGER; |
||
359 | |||
360 | BEGIN |
||
361 | IF dgt < "A" THEN |
||
362 | res := ORD(dgt) - ORD("0") |
||
363 | ELSE |
||
364 | res := ORD(dgt) - ORD("A") + 10 |
||
365 | END |
||
366 | |||
367 | RETURN res |
||
368 | END hexdgt; |
||
369 | |||
370 | |||
371 | BEGIN |
||
372 | k := LENGTH(hex); |
||
373 | ASSERT(~ODD(k)); |
||
374 | k := k DIV 2; |
||
375 | |||
376 | FOR i := 0 TO k - 1 DO |
||
8097 | maxcodehac | 377 | _array[i + idx] := hexdgt(hex[2 * i]) * 16 + hexdgt(hex[2 * i + 1]) |
7597 | akron1 | 378 | END; |
379 | |||
7693 | akron1 | 380 | INC(idx, k) |
7597 | akron1 | 381 | END InitArray; |
382 | |||
383 | |||
7983 | leency | 384 | END BIN.>> |