Subversion Repositories Kolibri OS

Rev

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.