Subversion Repositories Kolibri OS

Rev

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.