Subversion Repositories Kolibri OS

Rev

Rev 7597 | Go to most recent revision | Details | Compare with Previous | 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 CODE;
9
 
10
IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS;
11
 
12
 
13
CONST
14
 
15
    little_endian* = 0;
16
    big_endian* = 1;
17
 
18
    call_stack* = 0;
19
    call_win64* = 1;
20
    call_sysv*  = 2;
21
 
22
    opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5;
23
    opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9;
24
    opDIV* = 10; opMOD* = 11; opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15;
25
    opUMINUS* = 16;
26
    opADD* = 17; opSUB* = 18; opADDL* = 19; opSUBL* = 20; opADDR* = 21; opSUBR* = 22;
27
    opSAVE* = 23; opSAVEC* = 24; opSAVE8* = 25; opSAVE8C* = 26; opCHKBYTE* = 27; opDROP* = 28;
28
    opNOT* = 29;
29
 
30
    opEQ*  = 30; opNE*  = 31; opLT*  = 32; opLE*  = 33; opGT*  = 34; opGE*  = 35;
31
    opEQL* = 36; opNEL* = 37; opLTL* = 38; opLEL* = 39; opGTL* = 40; opGEL* = 41;
32
    opEQR* = 42; opNER* = 43; opLTR* = 44; opLER* = 45; opGTR* = 46; opGER* = 47;
33
 
34
    opVLOAD32* = 48; opGLOAD32* = 49;
35
 
36
    opJNE* = 50; opJE* = 51;
37
 
38
    opEQS* = 52; opNES* = opEQS + 1; opLTS* = opEQS + 2; opLES* = opEQS + 3; opGTS* = opEQS + 4; opGES* = opEQS + 5 (* 58 *);
39
 
40
    opSAVE32* = 58; opLLOAD8* = 59;
41
 
42
    opCONSTF* = 60; opLOADF* = 61; opSAVEF* = 62; opMULF* = 63; opDIVF* = 64; opDIVFI* = 65;
43
    opUMINF* = 66; opADDFI* = 67; opSUBFI* = 68; opADDF* = 69; opSUBF* = 70;
44
 
45
    opINC1B* = 71; opDEC1B* = 72; opINCCB* = 73; opDECCB* = 74; opINCB* = 75; opDECB* = 76;
46
 
47
    opCASEL* = 77; opCASER* = 78; opCASELR* = 79;
48
 
49
    opEQF*  = 80; opNEF*  = opEQF + 1; opLTF*  = opEQF + 2; opLEF*  = opEQF + 3; opGTF*  = opEQF + 4; opGEF*  = opEQF + 5;
50
    opEQFI* = opEQF + 6; opNEFI* = opEQF + 7; opLTFI* = opEQF + 8; opLEFI* = opEQF + 9; opGTFI* = opEQF + 10; opGEFI* = opEQF + 11; (* 91 *)
51
 
52
    opLOAD8* = 92; opLOAD16* = 93; opLOAD32* = 94; opPRECALL* = 95; opRES* = 96; opRESF* = 97;
53
    opERRC* = 98; opSWITCH* = 99;
54
 
55
    opSBOOL* = 100; opSBOOLC* = 101; opNOP* = 102;
56
 
57
    opMULS* = 103; opMULSC* = 104; opDIVS* = 105; opDIVSC* = 106;
58
    opADDS* = 107; opSUBS* = 108; opADDSL* = 109; opSUBSL* = 110; opADDSR* = 111; opSUBSR* = 112;
59
    opUMINS* = 113; opIN* = 114; opINL* = 115; opINR* = 116;
60
    opRSET* = 117; opRSETL* = 118; opRSETR* = 119; opRSET1* = 120; opLENGTH* = 121;
61
 
62
    opINC1* = 122; opDEC1* = 123; opINCC* = 124; opDECC* = 125; opINC* = 126; opDEC* = 127;
63
    opINCL* = 128; opEXCL* = 129; opINCLC* = 130; opEXCLC* = 131; opNEW* = 132; opDISP* = 133;
64
    opPACK* = 134; opPACKC* = 135; opUNPK* = 136; opCOPY* = 137; opENTER* = 138; opLEAVE* = 139;
65
    opCALL* = 140; opSAVEP* = 141; opCALLP* = 142; opEQP* = 143; opNEP* = 144; opLEAVER* = 145;
66
    opGET* = 146; opSAVE16* = 147; opABS* = 148; opFABS* = 149; opFLOOR* = 150; opFLT* = 151;
67
    opODD* = 152; opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156;
68
    opASR1* = 157; opLSL1* = 158; opROR1* = 159; opASR2* = 160; opLSL2* = 161; opROR2* = 162;
69
    opPUSHP* = 163; opLADR* = 164; opTYPEGP* = 165; opIS* = 166; opPUSHF* = 167; opVADR* = 168;
70
    opPUSHT* = 169; opTYPEGR* = 170; opISREC* = 171; opCHKIDX* = 172; opPARAM* = 173;
71
    opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opERR* = 179;
72
 
73
    opCHR* = 180; opENDSW* = 181; opLEAVEF* = 182; opCLEANUP* = 183; opMOVE* = 184;
74
    opLSR* = 185; opLSR1* = 186; opLSR2* = 187;
75
    opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opJNZ* = 192;
76
    opEQB* = 193; opNEB* = 194; opINF* = 195; opJZ* = 196; opVLOAD8* = 197; opGLOAD8* = 198;
77
    opLLOAD16* = 199; opVLOAD16* = 200; opGLOAD16* = 201;
78
    opLOAD64* = 202; opLLOAD64* = 203; opVLOAD64* = 204; opGLOAD64* = 205; opSAVE64* = 206;
79
 
80
    opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212;
81
    opSAVE16C* = 213; opWCHR* = 214; opCOPYS2* = 215; opLENGTHW* = 216;
82
 
83
    opEQS2*  = 217; opNES2* = opEQS2 + 1; opLTS2* = opEQS2 + 2; opLES2* = opEQS2 + 3; opGTS2* = opEQS2 + 4; opGES2* = opEQS2 + 5 (* 222 *);
84
    opEQSW*  = 223; opNESW* = opEQSW + 1; opLTSW* = opEQSW + 2; opLESW* = opEQSW + 3; opGTSW* = opEQSW + 4; opGESW* = opEQSW + 5 (* 228 *);
85
    opEQSW2*  = 229; opNESW2* = opEQSW2 + 1; opLTSW2* = opEQSW2 + 2; opLESW2* = opEQSW2 + 3; opGTSW2* = opEQSW2 + 4; opGESW2* = opEQSW2 + 5 (* 234 *);
86
 
87
    opCODE* = 235;
88
 
89
    opALIGN16* = 236; opPOPSP* = 237;
90
    opWIN64CALL* = 238; opWIN64CALLI* = 239; opWIN64CALLP* = 240; opLOOP* = 241; opENDLOOP* = 242;
91
    opSYSVCALL* = 243; opSYSVCALLI* = 244; opSYSVCALLP* = 245; opSYSVALIGN16* = 246; opWIN64ALIGN16* = 247;
7667 akron1 92
 
93
    opACC* = 248;
7597 akron1 94
 
95
 
96
    opSADR_PARAM* = 1000; opLOAD64_PARAM* = 1001; opLLOAD64_PARAM* = 1002; opGLOAD64_PARAM* = 1003;
97
    opVADR_PARAM* = 1004; opCONST_PARAM* = 1005; opGLOAD32_PARAM* = 1006; opLLOAD32_PARAM* = 1007;
98
    opLOAD32_PARAM* = 1008;
99
 
100
    opLADR_SAVEC* = 1009; opGADR_SAVEC* = 1010; opLADR_SAVE* = 1011;
101
 
102
    opLADR_INC1* = 1012; opLADR_DEC1* = 1013; opLADR_INCC* = 1014; opLADR_DECC* = 1015;
103
    opLADR_INC1B* = 1016; opLADR_DEC1B* = 1017; opLADR_INCCB* = 1018; opLADR_DECCB* = 1019;
104
    opLADR_INC* = 1020; opLADR_DEC* = 1021; opLADR_INCB* = 1022; opLADR_DECB* = 1023;
105
    opLADR_INCL* = 1024; opLADR_EXCL* = 1025; opLADR_INCLC* = 1026; opLADR_EXCLC* = 1027;
106
    opLADR_UNPK* = 1028;
107
 
108
 
109
    _move      *=   0;
110
    _move2     *=   1;
111
    _strcmpw   *=   2;
112
    _strcmpw2  *=   3;
113
    _set       *=   4;
114
    _set2      *=   5;
115
    _lengthw   *=   6;
116
    _strcmp2   *=   7;
117
    _div       *=   8;
118
    _mod       *=   9;
119
    _div2      *=  10;
120
    _mod2      *=  11;
121
    _arrcpy    *=  12;
122
    _rot       *=  13;
123
    _new       *=  14;
124
    _dispose   *=  15;
125
    _strcmp    *=  16;
126
    _error     *=  17;
127
    _is        *=  18;
128
    _isrec     *=  19;
129
    _guard     *=  20;
130
    _guardrec  *=  21;
131
    _length    *=  22;
132
    _init      *=  23;
133
    _dllentry  *=  24;
134
    _strcpy    *=  25;
135
    _exit      *=  26;
136
    _strcpy2   *=  27;
137
 
138
 
139
TYPE
140
 
141
    LOCALVAR* = POINTER TO RECORD (LISTS.ITEM)
142
 
143
        offset*, size*, count*: INTEGER
144
 
145
    END;
146
 
147
    COMMAND* = POINTER TO RECORD (LISTS.ITEM)
148
 
149
        opcode*:    INTEGER;
150
        param1*:    INTEGER;
151
        param2*:    INTEGER;
152
        param3*:    INTEGER;
153
        float*:     REAL;
154
        variables*: LISTS.LIST;
155
        allocReg*:  BOOLEAN
156
 
157
    END;
158
 
159
    CMDSTACK = POINTER TO RECORD
160
 
161
        data: ARRAY 1000 OF COMMAND;
162
        top:  INTEGER
163
 
164
    END;
165
 
166
    EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
167
 
168
        label*: INTEGER;
169
        name*:  SCAN.LEXSTR
170
 
171
    END;
172
 
173
    IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM)
174
 
175
        name*:   SCAN.LEXSTR;
176
        procs*:  LISTS.LIST
177
 
178
    END;
179
 
180
    IMPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
181
 
182
        label*: INTEGER;
183
        lib*:   IMPORT_LIB;
184
        name*:  SCAN.LEXSTR;
185
        count:  INTEGER
186
 
187
    END;
188
 
189
 
190
    CODES* = POINTER TO RECORD
191
 
192
        last:       COMMAND;
193
        begcall:    CMDSTACK;
194
        endcall:    CMDSTACK;
195
        commands*:  LISTS.LIST;
196
        export*:    LISTS.LIST;
197
        import*:    LISTS.LIST;
198
        types*:     CHL.INTLIST;
199
        data*:      CHL.BYTELIST;
200
        dmin*:      INTEGER;
201
        lcount*:    INTEGER;
202
        bss*:       INTEGER;
203
        rtl*:       ARRAY 28 OF INTEGER;
204
 
205
        charoffs:   ARRAY 256 OF INTEGER;
206
        wcharoffs:  ARRAY 65536 OF INTEGER;
207
 
208
        fregs:      INTEGER;
209
        wstr:       ARRAY 4*1024 OF WCHAR;
210
 
211
        errlabel*:  INTEGER
212
 
213
    END;
214
 
215
 
216
VAR
217
 
218
    codes*: CODES;
219
    endianness: INTEGER;
220
    numRegsFloat: INTEGER;
221
 
222
    commands, variables: C.COLLECTION;
223
 
224
 
225
PROCEDURE NewCmd (): COMMAND;
226
VAR
227
    cmd:   COMMAND;
228
    citem: C.ITEM;
229
 
230
BEGIN
231
    citem := C.pop(commands);
232
    IF citem = NIL THEN
233
        NEW(cmd)
234
    ELSE
235
        cmd := citem(COMMAND)
236
    END;
237
 
238
    cmd.allocReg := FALSE
239
 
240
    RETURN cmd
241
END NewCmd;
242
 
243
 
244
PROCEDURE NewVar* (): LOCALVAR;
245
VAR
246
    lvar:  LOCALVAR;
247
    citem: C.ITEM;
248
 
249
BEGIN
250
    citem := C.pop(variables);
251
    IF citem = NIL THEN
252
        NEW(lvar)
253
    ELSE
254
        lvar := citem(LOCALVAR)
255
    END;
256
 
257
    lvar.count := 0
258
 
259
    RETURN lvar
260
END NewVar;
261
 
262
 
263
PROCEDURE setlast* (cmd: COMMAND);
264
BEGIN
265
    codes.last := cmd
266
END setlast;
267
 
268
 
269
PROCEDURE getlast* (): COMMAND;
270
    RETURN codes.last
271
END getlast;
272
 
273
 
274
PROCEDURE PutByte (codes: CODES; b: BYTE);
275
BEGIN
276
    CHL.PushByte(codes.data, b)
277
END PutByte;
278
 
279
 
280
PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER;
281
VAR
282
    i, n, res: INTEGER;
283
BEGIN
284
    res := CHL.Length(codes.data);
285
 
286
    i := 0;
287
    n := LENGTH(s);
288
    WHILE i < n DO
289
        PutByte(codes, ORD(s[i]));
290
        INC(i)
291
    END;
292
 
293
    PutByte(codes, 0)
294
 
295
    RETURN res
296
END putstr;
297
 
298
 
299
PROCEDURE putstr1* (c: INTEGER): INTEGER;
300
VAR
301
    res: INTEGER;
302
 
303
BEGIN
304
    IF codes.charoffs[c] = -1 THEN
305
        res := CHL.Length(codes.data);
306
        PutByte(codes, c);
307
        PutByte(codes, 0);
308
        codes.charoffs[c] := res
309
    ELSE
310
        res := codes.charoffs[c]
311
    END
312
 
313
    RETURN res
314
END putstr1;
315
 
316
 
317
PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER;
318
VAR
319
    i, n, res: INTEGER;
320
 
321
BEGIN
322
    res := CHL.Length(codes.data);
323
 
324
    IF ODD(res) THEN
325
        PutByte(codes, 0);
326
        INC(res)
327
    END;
328
 
329
    n := STRINGS.Utf8To16(s, codes.wstr);
330
 
331
    i := 0;
332
    WHILE i < n DO
333
        IF endianness = little_endian THEN
334
            PutByte(codes, ORD(codes.wstr[i]) MOD 256);
335
            PutByte(codes, ORD(codes.wstr[i]) DIV 256)
336
        ELSIF endianness = big_endian THEN
337
            PutByte(codes, ORD(codes.wstr[i]) DIV 256);
338
            PutByte(codes, ORD(codes.wstr[i]) MOD 256)
339
        END;
340
        INC(i)
341
    END;
342
 
343
    PutByte(codes, 0);
344
    PutByte(codes, 0)
345
 
346
    RETURN res
347
END putstrW;
348
 
349
 
350
PROCEDURE putstrW1* (c: INTEGER): INTEGER;
351
VAR
352
    res: INTEGER;
353
 
354
BEGIN
355
    IF codes.wcharoffs[c] = -1 THEN
356
        res := CHL.Length(codes.data);
357
 
358
        IF ODD(res) THEN
359
            PutByte(codes, 0);
360
            INC(res)
361
        END;
362
 
363
        IF endianness = little_endian THEN
364
            PutByte(codes, c MOD 256);
365
            PutByte(codes, c DIV 256)
366
        ELSIF endianness = big_endian THEN
367
            PutByte(codes, c DIV 256);
368
            PutByte(codes, c MOD 256)
369
        END;
370
 
371
        PutByte(codes, 0);
372
        PutByte(codes, 0);
373
 
374
        codes.wcharoffs[c] := res
375
    ELSE
376
        res := codes.wcharoffs[c]
377
    END
378
 
379
    RETURN res
380
END putstrW1;
381
 
382
 
383
PROCEDURE SetMinDataSize* (size: INTEGER);
384
BEGIN
385
    codes.dmin := CHL.Length(codes.data) + size
386
END SetMinDataSize;
387
 
388
 
389
PROCEDURE push (stk: CMDSTACK; cmd: COMMAND);
390
BEGIN
391
    INC(stk.top);
392
    stk.data[stk.top] := cmd
393
END push;
394
 
395
 
396
PROCEDURE pop (stk: CMDSTACK): COMMAND;
397
VAR
398
    res: COMMAND;
399
BEGIN
400
    res := stk.data[stk.top];
401
    DEC(stk.top)
402
    RETURN res
403
END pop;
404
 
405
 
406
PROCEDURE pushBegEnd* (VAR beg, end: COMMAND);
407
BEGIN
408
    push(codes.begcall, beg);
409
    push(codes.endcall, end);
410
    beg := codes.last;
411
    end := beg.next(COMMAND)
412
END pushBegEnd;
413
 
414
 
415
PROCEDURE popBegEnd* (VAR beg, end: COMMAND);
416
BEGIN
417
    beg := pop(codes.begcall);
418
    end := pop(codes.endcall)
419
END popBegEnd;
420
 
421
 
422
PROCEDURE AddRec* (base: INTEGER);
423
BEGIN
424
    CHL.PushInt(codes.types, base)
425
END AddRec;
426
 
427
 
428
PROCEDURE insert (cur, nov: COMMAND);
429
VAR
430
    old_opcode, param2: INTEGER;
431
 
432
 
433
    PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER);
434
    BEGIN
435
        cur.opcode := opcode;
436
        cur.param1 := cur.param2;
437
        cur.param2 := param2
438
    END set;
439
 
440
 
441
BEGIN
442
    old_opcode := cur.opcode;
443
    param2 := nov.param2;
444
 
445
    IF (nov.opcode = opPARAM) & (param2 = 1) THEN
446
 
447
        CASE old_opcode OF
448
        |opGLOAD64: cur.opcode := opGLOAD64_PARAM
449
        |opLLOAD64: cur.opcode := opLLOAD64_PARAM
450
        |opLOAD64:  cur.opcode := opLOAD64_PARAM
451
        |opGLOAD32: cur.opcode := opGLOAD32_PARAM
452
        |opLLOAD32: cur.opcode := opLLOAD32_PARAM
453
        |opLOAD32:  cur.opcode := opLOAD32_PARAM
454
        |opSADR:    cur.opcode := opSADR_PARAM
455
        |opVADR:    cur.opcode := opVADR_PARAM
456
        |opCONST:   cur.opcode := opCONST_PARAM
457
        ELSE
458
            old_opcode := -1
459
        END
460
 
461
    ELSIF old_opcode = opLADR THEN
462
 
463
        CASE nov.opcode OF
464
        |opSAVEC: set(cur, opLADR_SAVEC, param2)
465
        |opSAVE:  cur.opcode := opLADR_SAVE
466
        |opINC1:  cur.opcode := opLADR_INC1
467
        |opDEC1:  cur.opcode := opLADR_DEC1
468
        |opINC:   cur.opcode := opLADR_INC
469
        |opDEC:   cur.opcode := opLADR_DEC
470
        |opINC1B: cur.opcode := opLADR_INC1B
471
        |opDEC1B: cur.opcode := opLADR_DEC1B
472
        |opINCB:  cur.opcode := opLADR_INCB
473
        |opDECB:  cur.opcode := opLADR_DECB
474
        |opINCL:  cur.opcode := opLADR_INCL
475
        |opEXCL:  cur.opcode := opLADR_EXCL
476
        |opUNPK:  cur.opcode := opLADR_UNPK
477
        |opINCC:  set(cur, opLADR_INCC, param2)
478
        |opDECC:  set(cur, opLADR_DECC, param2)
479
        |opINCCB: set(cur, opLADR_INCCB, param2)
480
        |opDECCB: set(cur, opLADR_DECCB, param2)
481
        |opINCLC: set(cur, opLADR_INCLC, param2)
482
        |opEXCLC: set(cur, opLADR_EXCLC, param2)
483
        ELSE
484
            old_opcode := -1
485
        END
486
 
487
    ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN
488
        set(cur, opGADR_SAVEC, param2)
489
 
490
    ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
491
        cur.param2 := param2 * cur.param2
492
 
493
    ELSE
494
        old_opcode := -1
495
    END;
496
 
497
    IF old_opcode = -1 THEN
498
        LISTS.insert(codes.commands, cur, nov);
499
        codes.last := nov
500
    ELSE
501
        C.push(commands, nov);
502
        codes.last := cur
503
    END
504
END insert;
505
 
506
 
507
PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER);
508
VAR
509
    cmd: COMMAND;
510
BEGIN
511
    cmd := NewCmd();
512
    cmd.opcode := opcode;
513
    cmd.param1 := 0;
514
    cmd.param2 := param;
515
    insert(codes.last, cmd)
516
END AddCmd;
517
 
518
 
519
PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER);
520
VAR
521
    cmd: COMMAND;
522
BEGIN
523
    cmd := NewCmd();
524
    cmd.opcode := opcode;
525
    cmd.param1 := param1;
526
    cmd.param2 := param2;
527
    insert(codes.last, cmd)
528
END AddCmd2;
529
 
530
 
531
PROCEDURE NewLabel* (): INTEGER;
532
BEGIN
533
    INC(codes.lcount)
534
    RETURN codes.lcount - 1
535
END NewLabel;
536
 
537
 
538
PROCEDURE SetLabel* (label: INTEGER);
539
BEGIN
540
    AddCmd(opLABEL, label)
541
END SetLabel;
542
 
543
 
544
PROCEDURE SetErrLabel*;
545
BEGIN
546
    codes.errlabel := NewLabel();
547
    SetLabel(codes.errlabel)
548
END SetErrLabel;
549
 
550
 
551
PROCEDURE AddCmd0* (opcode: INTEGER);
552
BEGIN
553
    AddCmd(opcode, 0)
554
END AddCmd0;
555
 
556
 
557
PROCEDURE deleteVarList (list: LISTS.LIST);
558
VAR
559
    last: LISTS.ITEM;
560
 
561
BEGIN
562
    WHILE list.last # NIL DO
563
        last := LISTS.pop(list);
564
        C.push(variables, last)
565
    END
566
END deleteVarList;
567
 
568
 
569
PROCEDURE delete (cmd: COMMAND);
570
BEGIN
571
    IF cmd.variables # NIL THEN
572
        deleteVarList(cmd.variables)
573
    END;
574
    LISTS.delete(codes.commands, cmd);
575
    C.push(commands, cmd)
576
END delete;
577
 
578
 
579
PROCEDURE delete2* (first, last: LISTS.ITEM);
580
VAR
581
    cur, next: LISTS.ITEM;
582
 
583
BEGIN
584
    cur := first;
585
 
586
    IF first # last THEN
587
        REPEAT
588
            next := cur.next;
589
            LISTS.delete(codes.commands, cur);
590
            C.push(commands, cur);
591
            cur := next
592
        UNTIL cur = last
593
    END;
594
 
595
    LISTS.delete(codes.commands, cur);
596
    C.push(commands, cur)
597
END delete2;
598
 
599
 
600
PROCEDURE AddJmpCmd* (opcode: INTEGER; label: INTEGER);
601
VAR
602
    prev: COMMAND;
603
    not:  BOOLEAN;
604
 
605
BEGIN
606
    prev := codes.last;
607
    not := prev.opcode = opNOT;
608
    IF not THEN
609
        IF opcode = opJE THEN
610
            opcode := opJNE
611
        ELSIF opcode = opJNE THEN
612
            opcode := opJE
613
        ELSE
614
            not := FALSE
615
        END
616
    END;
617
 
618
    AddCmd2(opcode, label, label);
619
 
620
    IF not THEN
621
        delete(prev)
622
    END
623
 
624
END AddJmpCmd;
625
 
626
 
627
PROCEDURE OnError* (line, error: INTEGER);
628
BEGIN
629
    AddCmd(opERRC, LSL(line, 4) + error);
630
    AddJmpCmd(opJMP, codes.errlabel)
631
END OnError;
632
 
633
 
634
PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER);
635
VAR
636
    label: INTEGER;
637
BEGIN
638
    AddCmd(op, t);
639
    label := NewLabel();
640
    AddJmpCmd(opJE, label);
641
    OnError(line, error);
642
    SetLabel(label)
643
END TypeGuard;
644
 
645
 
646
PROCEDURE TypeCheck* (t: INTEGER);
647
BEGIN
648
    AddCmd(opIS, t)
649
END TypeCheck;
650
 
651
 
652
PROCEDURE TypeCheckRec* (t: INTEGER);
653
BEGIN
654
    AddCmd(opISREC, t)
655
END TypeCheckRec;
656
 
657
 
658
PROCEDURE New* (size, typenum: INTEGER);
659
BEGIN
660
    AddCmd2(opNEW, typenum, size)
661
END New;
662
 
663
 
664
PROCEDURE fcmp* (opcode: INTEGER);
665
BEGIN
666
    AddCmd(opcode, 0);
667
    DEC(codes.fregs, 2);
668
    ASSERT(codes.fregs >= 0)
669
END fcmp;
670
 
671
 
672
PROCEDURE not*;
673
VAR
674
    prev: COMMAND;
675
BEGIN
676
    prev := codes.last;
677
    IF prev.opcode = opNOT THEN
678
        codes.last := prev.prev(COMMAND);
679
        delete(prev)
680
    ELSE
681
        AddCmd0(opNOT)
682
    END
683
END not;
684
 
685
 
686
PROCEDURE Enter* (label, params: INTEGER): COMMAND;
687
VAR
688
    cmd: COMMAND;
689
 
690
BEGIN
691
    cmd := NewCmd();
692
    cmd.opcode := opENTER;
693
    cmd.param1 := label;
694
    cmd.param3 := params;
695
    cmd.allocReg := TRUE;
696
    insert(codes.last, cmd)
697
 
698
    RETURN codes.last
699
END Enter;
700
 
701
 
702
PROCEDURE Leave* (result, float: BOOLEAN; paramsize: INTEGER): COMMAND;
703
BEGIN
704
    IF result THEN
705
        IF float THEN
706
            AddCmd(opLEAVEF, paramsize)
707
        ELSE
708
            AddCmd(opLEAVER, paramsize)
709
        END
710
    ELSE
711
        AddCmd(opLEAVE, paramsize)
712
    END
713
 
714
    RETURN codes.last
715
END Leave;
716
 
717
 
718
PROCEDURE Call* (proc, callconv, fparams: INTEGER);
719
BEGIN
720
    CASE callconv OF
721
    |call_stack: AddJmpCmd(opCALL, proc)
722
    |call_win64: AddJmpCmd(opWIN64CALL, proc)
723
    |call_sysv:  AddJmpCmd(opSYSVCALL, proc)
724
    END;
725
    codes.last(COMMAND).param2 := fparams
726
END Call;
727
 
728
 
729
PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER);
730
BEGIN
731
    CASE callconv OF
732
    |call_stack: AddJmpCmd(opCALLI, proc(IMPORT_PROC).label)
733
    |call_win64: AddJmpCmd(opWIN64CALLI, proc(IMPORT_PROC).label)
734
    |call_sysv:  AddJmpCmd(opSYSVCALLI, proc(IMPORT_PROC).label)
735
    END;
736
    codes.last(COMMAND).param2 := fparams
737
END CallImp;
738
 
739
 
740
PROCEDURE CallP* (callconv, fparams: INTEGER);
741
BEGIN
742
    CASE callconv OF
743
    |call_stack: AddCmd0(opCALLP)
744
    |call_win64: AddCmd(opWIN64CALLP, fparams)
745
    |call_sysv:  AddCmd(opSYSVCALLP, fparams)
746
    END
747
END CallP;
748
 
749
 
750
PROCEDURE AssignProc* (proc: INTEGER);
751
BEGIN
752
    AddJmpCmd(opSAVEP, proc)
753
END AssignProc;
754
 
755
 
756
PROCEDURE AssignImpProc* (proc: LISTS.ITEM);
757
BEGIN
758
    AddJmpCmd(opSAVEIP, proc(IMPORT_PROC).label)
759
END AssignImpProc;
760
 
761
 
762
PROCEDURE PushProc* (proc: INTEGER);
763
BEGIN
764
    AddJmpCmd(opPUSHP, proc)
765
END PushProc;
766
 
767
 
768
PROCEDURE PushImpProc* (proc: LISTS.ITEM);
769
BEGIN
770
    AddJmpCmd(opPUSHIP, proc(IMPORT_PROC).label)
771
END PushImpProc;
772
 
773
 
774
PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN);
775
BEGIN
776
    IF eq THEN
777
        AddJmpCmd(opEQP, proc)
778
    ELSE
779
        AddJmpCmd(opNEP, proc)
780
    END
781
END ProcCmp;
782
 
783
 
784
PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN);
785
BEGIN
786
    IF eq THEN
787
        AddJmpCmd(opEQIP, proc(IMPORT_PROC).label)
788
    ELSE
789
        AddJmpCmd(opNEIP, proc(IMPORT_PROC).label)
790
    END
791
END ProcImpCmp;
792
 
793
 
794
PROCEDURE SysGet* (size: INTEGER);
795
BEGIN
796
    AddCmd(opGET, size)
797
END SysGet;
798
 
799
 
800
PROCEDURE load* (size: INTEGER);
801
VAR
802
    last: COMMAND;
803
 
804
BEGIN
805
    last := codes.last;
806
    CASE size OF
807
    |1:
808
        IF last.opcode = opLADR THEN
809
            last.opcode := opLLOAD8
810
        ELSIF last.opcode = opVADR THEN
811
            last.opcode := opVLOAD8
812
        ELSIF last.opcode = opGADR THEN
813
            last.opcode := opGLOAD8
814
        ELSE
815
            AddCmd0(opLOAD8)
816
        END
817
 
818
    |2:
819
        IF last.opcode = opLADR THEN
820
            last.opcode := opLLOAD16
821
        ELSIF last.opcode = opVADR THEN
822
            last.opcode := opVLOAD16
823
        ELSIF last.opcode = opGADR THEN
824
            last.opcode := opGLOAD16
825
        ELSE
826
            AddCmd0(opLOAD16)
827
        END
828
 
829
    |4:
830
        IF last.opcode = opLADR THEN
831
            last.opcode := opLLOAD32
832
        ELSIF last.opcode = opVADR THEN
833
            last.opcode := opVLOAD32
834
        ELSIF last.opcode = opGADR THEN
835
            last.opcode := opGLOAD32
836
        ELSE
837
            AddCmd0(opLOAD32)
838
        END
839
 
840
    |8:
841
        IF last.opcode = opLADR THEN
842
            last.opcode := opLLOAD64
843
        ELSIF last.opcode = opVADR THEN
844
            last.opcode := opVLOAD64
845
        ELSIF last.opcode = opGADR THEN
846
            last.opcode := opGLOAD64
847
        ELSE
848
            AddCmd0(opLOAD64)
849
        END
850
    END
851
END load;
852
 
853
 
854
PROCEDURE SysPut* (size: INTEGER);
855
BEGIN
856
    CASE size OF
857
    |1: AddCmd0(opSAVE8)
858
    |2: AddCmd0(opSAVE16)
859
    |4: AddCmd0(opSAVE32)
860
    |8: AddCmd0(opSAVE64)
861
    END
862
END SysPut;
863
 
864
 
865
PROCEDURE savef*;
866
BEGIN
867
    AddCmd0(opSAVEF);
868
    DEC(codes.fregs);
869
    ASSERT(codes.fregs >= 0)
870
END savef;
871
 
872
 
873
PROCEDURE pushf*;
874
BEGIN
875
    AddCmd0(opPUSHF);
876
    DEC(codes.fregs);
877
    ASSERT(codes.fregs >= 0)
878
END pushf;
879
 
880
 
881
PROCEDURE loadf* (): BOOLEAN;
882
BEGIN
883
    AddCmd0(opLOADF);
884
    INC(codes.fregs)
885
    RETURN codes.fregs < numRegsFloat
886
END loadf;
887
 
888
 
889
PROCEDURE inf* (): BOOLEAN;
890
BEGIN
891
    AddCmd0(opINF);
892
    INC(codes.fregs)
893
    RETURN codes.fregs < numRegsFloat
894
END inf;
895
 
896
 
897
PROCEDURE fbinop* (opcode: INTEGER);
898
BEGIN
899
    AddCmd0(opcode);
900
    DEC(codes.fregs);
901
    ASSERT(codes.fregs > 0)
902
END fbinop;
903
 
904
 
905
PROCEDURE saves* (offset, length: INTEGER);
906
BEGIN
907
    AddCmd2(opSAVES, length, offset)
908
END saves;
909
 
910
 
911
PROCEDURE abs* (real: BOOLEAN);
912
BEGIN
913
    IF real THEN
914
        AddCmd0(opFABS)
915
    ELSE
916
        AddCmd0(opABS)
917
    END
918
END abs;
919
 
920
 
921
PROCEDURE floor*;
922
BEGIN
923
    AddCmd0(opFLOOR);
924
    DEC(codes.fregs);
925
    ASSERT(codes.fregs >= 0)
926
END floor;
927
 
928
 
929
PROCEDURE flt* (): BOOLEAN;
930
BEGIN
931
    AddCmd0(opFLT);
932
    INC(codes.fregs)
933
    RETURN codes.fregs < numRegsFloat
934
END flt;
935
 
936
 
937
PROCEDURE odd*;
938
BEGIN
939
    AddCmd0(opODD)
940
END odd;
941
 
942
 
943
PROCEDURE ord*;
944
BEGIN
945
    AddCmd0(opORD)
946
END ord;
947
 
948
 
949
PROCEDURE shift_minmax* (op: CHAR);
950
BEGIN
951
    CASE op OF
952
    |"A": AddCmd0(opASR)
953
    |"L": AddCmd0(opLSL)
954
    |"O": AddCmd0(opROR)
955
    |"R": AddCmd0(opLSR)
956
    |"m": AddCmd0(opMIN)
957
    |"x": AddCmd0(opMAX)
958
    END
959
END shift_minmax;
960
 
961
 
962
PROCEDURE shift_minmax1* (op: CHAR; x: INTEGER);
963
BEGIN
964
    CASE op OF
965
    |"A": AddCmd(opASR1, x)
966
    |"L": AddCmd(opLSL1, x)
967
    |"O": AddCmd(opROR1, x)
968
    |"R": AddCmd(opLSR1, x)
969
    |"m": AddCmd(opMINC, x)
970
    |"x": AddCmd(opMAXC, x)
971
    END
972
END shift_minmax1;
973
 
974
 
975
PROCEDURE shift_minmax2* (op: CHAR; x: INTEGER);
976
BEGIN
977
    CASE op OF
978
    |"A": AddCmd(opASR2, x)
979
    |"L": AddCmd(opLSL2, x)
980
    |"O": AddCmd(opROR2, x)
981
    |"R": AddCmd(opLSR2, x)
982
    |"m": AddCmd(opMINC, x)
983
    |"x": AddCmd(opMAXC, x)
984
    END
985
END shift_minmax2;
986
 
987
 
988
PROCEDURE len* (dim: INTEGER);
989
BEGIN
990
    AddCmd(opLEN, dim)
991
END len;
992
 
993
 
994
PROCEDURE Float* (r: REAL);
995
VAR
996
    cmd: COMMAND;
997
 
998
BEGIN
999
    cmd := NewCmd();
1000
    cmd.opcode := opCONSTF;
1001
    cmd.float := r;
1002
    insert(codes.last, cmd);
1003
    INC(codes.fregs);
1004
    ASSERT(codes.fregs <= numRegsFloat)
1005
END Float;
1006
 
1007
 
1008
PROCEDURE precall* (flt: BOOLEAN): INTEGER;
1009
VAR
1010
    res: INTEGER;
1011
BEGIN
1012
    res := codes.fregs;
1013
    AddCmd2(opPRECALL, ORD(flt), res);
1014
    codes.fregs := 0
1015
    RETURN res
1016
END precall;
1017
 
1018
 
1019
PROCEDURE resf* (fregs: INTEGER): BOOLEAN;
1020
BEGIN
1021
    AddCmd(opRESF, fregs);
1022
    codes.fregs := fregs + 1
1023
    RETURN codes.fregs < numRegsFloat
1024
END resf;
1025
 
1026
 
1027
PROCEDURE res* (fregs: INTEGER);
1028
BEGIN
1029
    AddCmd(opRES, fregs);
1030
    codes.fregs := fregs
1031
END res;
1032
 
1033
 
1034
PROCEDURE retf*;
1035
BEGIN
1036
    DEC(codes.fregs);
1037
    ASSERT(codes.fregs = 0)
1038
END retf;
1039
 
1040
 
1041
PROCEDURE drop*;
1042
BEGIN
1043
    AddCmd0(opDROP)
1044
END drop;
1045
 
1046
 
1047
PROCEDURE case* (a, b, L, R: INTEGER);
1048
VAR
1049
    cmd: COMMAND;
1050
 
1051
BEGIN
1052
    IF a = b THEN
1053
        cmd := NewCmd();
1054
        cmd.opcode := opCASELR;
1055
        cmd.param1 := a;
1056
        cmd.param2 := L;
1057
        cmd.param3 := R;
1058
        insert(codes.last, cmd)
1059
    ELSE
1060
        AddCmd2(opCASEL, a, L);
1061
        AddCmd2(opCASER, b, R)
1062
    END
1063
END case;
1064
 
1065
 
1066
PROCEDURE caset* (a, label: INTEGER);
1067
BEGIN
1068
    AddCmd2(opCASET, label, a)
1069
END caset;
1070
 
1071
 
1072
PROCEDURE AddExp* (label: INTEGER; name: SCAN.LEXSTR);
1073
VAR
1074
    exp: EXPORT_PROC;
1075
 
1076
BEGIN
1077
    NEW(exp);
1078
    exp.label := label;
1079
    exp.name  := name;
1080
    LISTS.push(codes.export, exp)
1081
END AddExp;
1082
 
1083
 
1084
PROCEDURE AddImp* (dll, proc: SCAN.LEXSTR): IMPORT_PROC;
1085
VAR
1086
    lib: IMPORT_LIB;
1087
    p:   IMPORT_PROC;
1088
 
1089
BEGIN
1090
    lib := codes.import.first(IMPORT_LIB);
1091
    WHILE (lib # NIL) & (lib.name # dll) DO
1092
        lib := lib.next(IMPORT_LIB)
1093
    END;
1094
 
1095
    IF lib = NIL THEN
1096
        NEW(lib);
1097
        lib.name := dll;
1098
        lib.procs := LISTS.create(NIL);
1099
        LISTS.push(codes.import, lib)
1100
    END;
1101
 
1102
    p := lib.procs.first(IMPORT_PROC);
1103
    WHILE (p # NIL) & (p.name # proc) DO
1104
        p := p.next(IMPORT_PROC)
1105
    END;
1106
 
1107
    IF p = NIL THEN
1108
        NEW(p);
1109
        p.name  := proc;
1110
        p.label := NewLabel();
1111
        p.lib   := lib;
1112
        p.count := 1;
1113
        LISTS.push(lib.procs, p)
1114
    ELSE
1115
        INC(p.count)
1116
    END
1117
 
1118
    RETURN p
1119
END AddImp;
1120
 
1121
 
1122
PROCEDURE DelImport* (imp: LISTS.ITEM);
1123
VAR
1124
    lib: IMPORT_LIB;
1125
 
1126
BEGIN
1127
    DEC(imp(IMPORT_PROC).count);
1128
    IF imp(IMPORT_PROC).count = 0 THEN
1129
        lib := imp(IMPORT_PROC).lib;
1130
        LISTS.delete(lib.procs, imp);
1131
        IF lib.procs.first = NIL THEN
1132
            LISTS.delete(codes.import, lib)
1133
        END
1134
    END
1135
END DelImport;
1136
 
1137
 
1138
PROCEDURE init* (pNumRegsFloat, pEndianness: INTEGER);
1139
VAR
1140
    cmd:    COMMAND;
1141
    i:      INTEGER;
1142
 
1143
BEGIN
1144
    commands := C.create();
1145
    variables := C.create();
1146
    numRegsFloat := pNumRegsFloat;
1147
    endianness := pEndianness;
1148
 
1149
    NEW(codes);
1150
    NEW(codes.begcall);
1151
    codes.begcall.top := -1;
1152
    NEW(codes.endcall);
1153
    codes.endcall.top := -1;
1154
    codes.commands := LISTS.create(NIL);
1155
    codes.export   := LISTS.create(NIL);
1156
    codes.import   := LISTS.create(NIL);
1157
    codes.types    := CHL.CreateIntList();
1158
    codes.data     := CHL.CreateByteList();
1159
 
1160
    NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
1161
    codes.last := cmd;
1162
    NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
1163
 
1164
    AddRec(0);
1165
 
1166
    codes.lcount := 0;
1167
 
1168
    codes.fregs := 0;
1169
 
1170
    FOR i := 0 TO LEN(codes.charoffs) - 1 DO
1171
        codes.charoffs[i] := -1
1172
    END;
1173
 
1174
    FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO
1175
        codes.wcharoffs[i] := -1
1176
    END
1177
 
1178
END init;
1179
 
1180
 
1181
END CODE.