Subversion Repositories Kolibri OS

Rev

Rev 7667 | 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
6613 leency 3
 
7597 akron1 4
    Copyright (c) 2018, 2019, Anton Krotov
5
    All rights reserved.
6613 leency 6
*)
7
 
8
MODULE X86;
9
 
7693 akron1 10
IMPORT IL, REG, UTILS, LISTS, BIN, PE32, KOS, MSCOFF, ELF, PROG,
11
       mConst := CONSTANTS, CHL := CHUNKLISTS, PATHS;
6613 leency 12
 
7597 akron1 13
 
6613 leency 14
CONST
15
 
7597 akron1 16
    eax = REG.R0; ecx = REG.R1; edx = REG.R2;
6613 leency 17
 
7597 akron1 18
    al = eax; cl = ecx; dl = edx; ah = 4;
6613 leency 19
 
7597 akron1 20
    ax = eax; cx = ecx; dx = edx;
6613 leency 21
 
7597 akron1 22
    esp = 4;
23
    ebp = 5;
6613 leency 24
 
7597 akron1 25
    sete = 94H; setne = 95H; setl = 9CH; setge = 9DH; setle = 9EH; setg = 9FH; setc = 92H; setnc = 93H;
6613 leency 26
 
7597 akron1 27
    je = 84H; jne = 85H; jl = 8CH; jge = 8DH; jle = 8EH; jg = 8FH; jb = 82H; jnb = 83H;
6613 leency 28
 
29
 
7597 akron1 30
    CODECHUNK = 8;
6613 leency 31
 
32
 
33
TYPE
34
 
7693 akron1 35
    COMMAND = IL.COMMAND;
6613 leency 36
 
37
 
7597 akron1 38
    ANYCODE = POINTER TO RECORD (LISTS.ITEM)
6613 leency 39
 
7597 akron1 40
        offset: INTEGER
6613 leency 41
 
7597 akron1 42
    END;
6613 leency 43
 
7693 akron1 44
    CODE = POINTER TO RECORD (ANYCODE)
6613 leency 45
 
7597 akron1 46
        code:    ARRAY CODECHUNK OF BYTE;
47
        length:  INTEGER
6613 leency 48
 
7597 akron1 49
    END;
6613 leency 50
 
7597 akron1 51
    LABEL = POINTER TO RECORD (ANYCODE)
6613 leency 52
 
7597 akron1 53
        label: INTEGER
6613 leency 54
 
7597 akron1 55
    END;
6613 leency 56
 
7597 akron1 57
    JUMP = POINTER TO RECORD (ANYCODE)
7209 akron1 58
 
7597 akron1 59
        label, diff: INTEGER;
60
        short: BOOLEAN
6613 leency 61
 
7597 akron1 62
    END;
6613 leency 63
 
7597 akron1 64
    JMP = POINTER TO RECORD (JUMP)
6613 leency 65
 
7597 akron1 66
    END;
6613 leency 67
 
7597 akron1 68
    JCC = POINTER TO RECORD (JUMP)
6613 leency 69
 
7597 akron1 70
        jmp: INTEGER
6613 leency 71
 
72
    END;
73
 
7597 akron1 74
    CALL = POINTER TO RECORD (JUMP)
6613 leency 75
 
7597 akron1 76
    END;
6613 leency 77
 
7597 akron1 78
    RELOC = POINTER TO RECORD (ANYCODE)
6613 leency 79
 
7597 akron1 80
        op, value: INTEGER
6613 leency 81
 
7597 akron1 82
    END;
6613 leency 83
 
84
 
7597 akron1 85
VAR
6613 leency 86
 
7597 akron1 87
    R: REG.REGS;
6613 leency 88
 
7597 akron1 89
    program: BIN.PROGRAM;
6613 leency 90
 
7597 akron1 91
    CodeList: LISTS.LIST;
6613 leency 92
 
7693 akron1 93
    tcount: INTEGER;
6613 leency 94
 
7693 akron1 95
 
7597 akron1 96
PROCEDURE Byte (n: INTEGER): BYTE;
7693 akron1 97
    RETURN UTILS.Byte(n, 0)
7597 akron1 98
END Byte;
6613 leency 99
 
100
 
7597 akron1 101
PROCEDURE Word (n: INTEGER): INTEGER;
7693 akron1 102
    RETURN UTILS.Byte(n, 0) + UTILS.Byte(n, 1) * 256
7597 akron1 103
END Word;
6613 leency 104
 
105
 
7597 akron1 106
PROCEDURE OutByte* (n: BYTE);
107
VAR
7693 akron1 108
    c: CODE;
7597 akron1 109
    last: ANYCODE;
6613 leency 110
 
7597 akron1 111
BEGIN
112
    last := CodeList.last(ANYCODE);
6613 leency 113
 
7693 akron1 114
    IF (last IS CODE) & (last(CODE).length < CODECHUNK) THEN
115
        c := last(CODE);
7597 akron1 116
        c.code[c.length] := n;
117
        INC(c.length)
118
    ELSE
119
        NEW(c);
120
        c.code[0] := n;
121
        c.length  := 1;
122
        LISTS.push(CodeList, c)
123
    END
6613 leency 124
 
7597 akron1 125
END OutByte;
6613 leency 126
 
127
 
7597 akron1 128
PROCEDURE OutInt (n: INTEGER);
6613 leency 129
BEGIN
7693 akron1 130
    OutByte(UTILS.Byte(n, 0));
131
    OutByte(UTILS.Byte(n, 1));
132
    OutByte(UTILS.Byte(n, 2));
133
    OutByte(UTILS.Byte(n, 3))
7597 akron1 134
END OutInt;
6613 leency 135
 
136
 
7597 akron1 137
PROCEDURE OutByte2 (a, b: BYTE);
6613 leency 138
BEGIN
7597 akron1 139
    OutByte(a);
140
    OutByte(b)
141
END OutByte2;
6613 leency 142
 
143
 
7597 akron1 144
PROCEDURE OutByte3 (a, b, c: BYTE);
6613 leency 145
BEGIN
7597 akron1 146
    OutByte(a);
147
    OutByte(b);
148
    OutByte(c)
149
END OutByte3;
6613 leency 150
 
151
 
7597 akron1 152
PROCEDURE OutWord (n: INTEGER);
6613 leency 153
BEGIN
7597 akron1 154
    ASSERT((0 <= n) & (n <= 65535));
155
    OutByte2(n MOD 256, n DIV 256)
156
END OutWord;
6613 leency 157
 
158
 
7597 akron1 159
PROCEDURE isByte (n: INTEGER): BOOLEAN;
160
    RETURN (-128 <= n) & (n <= 127)
161
END isByte;
162
 
163
 
164
PROCEDURE short (n: INTEGER): INTEGER;
165
    RETURN 2 * ORD(isByte(n))
166
END short;
167
 
168
 
169
PROCEDURE long (n: INTEGER): INTEGER;
170
    RETURN 40H * ORD(~isByte(n))
171
END long;
172
 
173
 
174
PROCEDURE OutIntByte (n: INTEGER);
6613 leency 175
BEGIN
7597 akron1 176
    IF isByte(n) THEN
177
        OutByte(Byte(n))
178
    ELSE
179
        OutInt(n)
180
    END
181
END OutIntByte;
6613 leency 182
 
7597 akron1 183
 
184
PROCEDURE shift* (op, reg: INTEGER);
6613 leency 185
BEGIN
7597 akron1 186
    CASE op OF
7693 akron1 187
    |IL.opASR, IL.opASR1, IL.opASR2: OutByte(0F8H + reg)
188
    |IL.opROR, IL.opROR1, IL.opROR2: OutByte(0C8H + reg)
189
    |IL.opLSL, IL.opLSL1, IL.opLSL2: OutByte(0E0H + reg)
190
    |IL.opLSR, IL.opLSR1, IL.opLSR2: OutByte(0E8H + reg)
7597 akron1 191
    END
192
END shift;
6613 leency 193
 
7597 akron1 194
 
195
PROCEDURE mov (reg1, reg2: INTEGER);
6613 leency 196
BEGIN
7597 akron1 197
    OutByte2(89H, 0C0H + reg2 * 8 + reg1)  // mov reg1, reg2
198
END mov;
6613 leency 199
 
7597 akron1 200
 
201
PROCEDURE xchg (reg1, reg2: INTEGER);
202
VAR
203
    regs: SET;
204
 
6613 leency 205
BEGIN
7597 akron1 206
    regs := {reg1, reg2};
207
    IF regs = {eax, ecx} THEN
208
        OutByte(91H)                // xchg eax, ecx
209
    ELSIF regs = {eax, edx} THEN
210
        OutByte(92H)                // xchg eax, edx
211
    ELSIF regs = {ecx, edx} THEN
212
        OutByte2(87H, 0D1H)         // xchg ecx, edx
213
    END
214
END xchg;
6613 leency 215
 
7597 akron1 216
 
217
PROCEDURE pop (reg: INTEGER);
6613 leency 218
BEGIN
7597 akron1 219
    OutByte(58H + reg) // pop reg
220
END pop;
6613 leency 221
 
7597 akron1 222
 
223
PROCEDURE push (reg: INTEGER);
6613 leency 224
BEGIN
7597 akron1 225
    OutByte(50H + reg) // push reg
226
END push;
6613 leency 227
 
7597 akron1 228
 
229
PROCEDURE movrc (reg, n: INTEGER);
6613 leency 230
BEGIN
7597 akron1 231
    OutByte(0B8H + reg); // mov reg, n
232
    OutInt(n)
233
END movrc;
6613 leency 234
 
7597 akron1 235
 
236
PROCEDURE pushc (n: INTEGER);
6613 leency 237
BEGIN
7597 akron1 238
    OutByte(68H + short(n)); // push n
239
    OutIntByte(n)
240
END pushc;
6613 leency 241
 
7597 akron1 242
 
243
PROCEDURE test (reg: INTEGER);
6613 leency 244
BEGIN
7597 akron1 245
    OutByte2(85H, 0C0H + reg * 9)  // test reg, reg
246
END test;
6613 leency 247
 
7597 akron1 248
 
249
PROCEDURE neg (reg: INTEGER);
6613 leency 250
BEGIN
7597 akron1 251
    OutByte2(0F7H, 0D8H + reg)  // neg reg
252
END neg;
6613 leency 253
 
7597 akron1 254
 
255
PROCEDURE not (reg: INTEGER);
6613 leency 256
BEGIN
7597 akron1 257
    OutByte2(0F7H, 0D0H + reg)  // not reg
258
END not;
6613 leency 259
 
7597 akron1 260
 
261
PROCEDURE add (reg1, reg2: INTEGER);
6613 leency 262
BEGIN
7597 akron1 263
    OutByte2(01H, 0C0H + reg2 * 8 + reg1)  // add reg1, reg2
264
END add;
6613 leency 265
 
7597 akron1 266
 
267
PROCEDURE andrc (reg, n: INTEGER);
6613 leency 268
BEGIN
7597 akron1 269
    OutByte2(81H + short(n), 0E0H + reg);  // and reg, n
270
    OutIntByte(n)
271
END andrc;
6613 leency 272
 
7597 akron1 273
 
274
PROCEDURE orrc (reg, n: INTEGER);
6613 leency 275
BEGIN
7597 akron1 276
    OutByte2(81H + short(n), 0C8H + reg);  // or reg, n
277
    OutIntByte(n)
278
END orrc;
6613 leency 279
 
7597 akron1 280
 
281
PROCEDURE addrc (reg, n: INTEGER);
6613 leency 282
BEGIN
7597 akron1 283
    OutByte2(81H + short(n), 0C0H + reg);  // add reg, n
284
    OutIntByte(n)
285
END addrc;
6613 leency 286
 
7597 akron1 287
 
288
PROCEDURE subrc (reg, n: INTEGER);
6613 leency 289
BEGIN
7597 akron1 290
    OutByte2(81H + short(n), 0E8H + reg);  // sub reg, n
291
    OutIntByte(n)
292
END subrc;
6613 leency 293
 
7597 akron1 294
 
295
PROCEDURE cmprr (reg1, reg2: INTEGER);
6613 leency 296
BEGIN
7597 akron1 297
    OutByte2(39H, 0C0H + reg2 * 8 + reg1)  // cmp reg1, reg2
298
END cmprr;
6613 leency 299
 
7597 akron1 300
 
301
PROCEDURE cmprc (reg, n: INTEGER);
6613 leency 302
BEGIN
7597 akron1 303
    OutByte2(81H + short(n), 0F8H + reg);  // cmp reg, n
304
    OutIntByte(n)
305
END cmprc;
6613 leency 306
 
7597 akron1 307
 
308
PROCEDURE setcc (cond, reg: INTEGER);
6613 leency 309
BEGIN
7597 akron1 310
    OutByte3(0FH, cond, 0C0H + reg)  // setcc reg
311
END setcc;
6613 leency 312
 
7597 akron1 313
 
7667 akron1 314
PROCEDURE xor (reg1, reg2: INTEGER);
315
BEGIN
316
    OutByte2(31H, 0C0H + reg2 * 8 + reg1) // xor reg1, reg2
317
END xor;
318
 
319
 
7597 akron1 320
PROCEDURE drop;
6613 leency 321
BEGIN
7597 akron1 322
    REG.Drop(R)
323
END drop;
6613 leency 324
 
7597 akron1 325
 
7693 akron1 326
PROCEDURE GetAnyReg (): INTEGER;
327
    RETURN REG.GetAnyReg(R)
328
END GetAnyReg;
7597 akron1 329
 
6613 leency 330
 
7597 akron1 331
PROCEDURE cond* (op: INTEGER): INTEGER;
332
VAR
333
    res: INTEGER;
6613 leency 334
 
335
BEGIN
7597 akron1 336
    CASE op OF
7693 akron1 337
    |IL.opGT, IL.opGTC: res := jg
338
    |IL.opGE, IL.opGEC: res := jge
339
    |IL.opLT, IL.opLTC: res := jl
340
    |IL.opLE, IL.opLEC: res := jle
341
    |IL.opEQ, IL.opEQC: res := je
342
    |IL.opNE, IL.opNEC: res := jne
7597 akron1 343
    END
6613 leency 344
 
7597 akron1 345
    RETURN res
346
END cond;
347
 
348
 
7693 akron1 349
PROCEDURE inv0* (op: INTEGER): INTEGER;
350
    RETURN ORD(BITS(op) / {0})
351
END inv0;
6613 leency 352
 
353
 
7597 akron1 354
PROCEDURE Reloc* (op, value: INTEGER);
355
VAR
356
    reloc: RELOC;
6613 leency 357
 
358
BEGIN
7597 akron1 359
    NEW(reloc);
360
    reloc.op := op;
361
    reloc.value := value;
362
    LISTS.push(CodeList, reloc)
363
END Reloc;
6613 leency 364
 
365
 
7597 akron1 366
PROCEDURE jcc* (cc, label: INTEGER);
367
VAR
368
    j: JCC;
6613 leency 369
 
370
BEGIN
7597 akron1 371
    NEW(j);
372
    j.label := label;
373
    j.jmp   := cc;
374
    j.short := FALSE;
375
    LISTS.push(CodeList, j)
376
END jcc;
6613 leency 377
 
378
 
7597 akron1 379
PROCEDURE jmp* (label: INTEGER);
380
VAR
381
    j: JMP;
6613 leency 382
 
383
BEGIN
7597 akron1 384
    NEW(j);
385
    j.label := label;
386
    j.short := FALSE;
387
    LISTS.push(CodeList, j)
388
END jmp;
6613 leency 389
 
390
 
7597 akron1 391
PROCEDURE call* (label: INTEGER);
392
VAR
393
    c: CALL;
6613 leency 394
 
395
BEGIN
7597 akron1 396
    NEW(c);
397
    c.label := label;
398
    c.short := TRUE;
399
    LISTS.push(CodeList, c)
400
END call;
6613 leency 401
 
402
 
7597 akron1 403
PROCEDURE Pic (reg, opcode, value: INTEGER);
6613 leency 404
BEGIN
7597 akron1 405
    OutByte(0E8H); OutInt(0); // call L
406
                              // L:
407
    pop(reg);
408
    OutByte2(081H, 0C0H + reg);  // add reg, ...
409
    Reloc(opcode, value)
410
END Pic;
6613 leency 411
 
412
 
7597 akron1 413
PROCEDURE CallRTL (pic: BOOLEAN; proc: INTEGER);
414
VAR
415
    label: INTEGER;
416
    reg1:  INTEGER;
6613 leency 417
 
418
BEGIN
7693 akron1 419
    label := IL.codes.rtl[proc];
6613 leency 420
 
7597 akron1 421
    IF label < 0 THEN
422
        label := -label;
423
        IF pic THEN
7693 akron1 424
            reg1 := GetAnyReg();
7597 akron1 425
            Pic(reg1, BIN.PICIMP, label);
426
            OutByte2(0FFH, 010H + reg1);  // call dword[reg1]
427
            drop
428
        ELSE
429
            OutByte2(0FFH, 015H);  // call dword[label]
430
            Reloc(BIN.RIMP, label)
431
        END
432
    ELSE
433
        call(label)
434
    END
435
END CallRTL;
6613 leency 436
 
437
 
7597 akron1 438
PROCEDURE SetLabel* (label: INTEGER);
439
VAR
440
    L: LABEL;
6613 leency 441
 
442
BEGIN
7597 akron1 443
    NEW(L);
444
    L.label := label;
445
    LISTS.push(CodeList, L)
446
END SetLabel;
6613 leency 447
 
448
 
7597 akron1 449
PROCEDURE fixup*;
450
VAR
451
    code:      ANYCODE;
452
    count, i:  INTEGER;
453
    shorted:   BOOLEAN;
454
    jump:      JUMP;
6613 leency 455
 
456
BEGIN
457
 
7597 akron1 458
    REPEAT
6613 leency 459
 
7597 akron1 460
        shorted := FALSE;
461
        count := 0;
6613 leency 462
 
7597 akron1 463
        code := CodeList.first(ANYCODE);
464
        WHILE code # NIL DO
465
            code.offset := count;
6613 leency 466
 
7597 akron1 467
            CASE code OF
7693 akron1 468
            |CODE:   INC(count, code.length)
7597 akron1 469
            |LABEL:  BIN.SetLabel(program, code.label, count)
470
            |JMP:    IF code.short THEN INC(count, 2) ELSE INC(count, 5) END; code.offset := count
471
            |JCC:    IF code.short THEN INC(count, 2) ELSE INC(count, 6) END; code.offset := count
472
            |CALL:   INC(count, 5); code.offset := count
473
            |RELOC:  INC(count, 4)
474
            END;
6613 leency 475
 
7597 akron1 476
            code := code.next(ANYCODE)
477
        END;
6613 leency 478
 
7597 akron1 479
        code := CodeList.first(ANYCODE);
480
        WHILE code # NIL DO
6613 leency 481
 
7597 akron1 482
            IF code IS JUMP THEN
483
                jump := code(JUMP);
484
                jump.diff := BIN.GetLabel(program, jump.label) - code.offset;
485
                IF ~jump.short & isByte(jump.diff) THEN
486
                    jump.short := TRUE;
487
                    shorted := TRUE
488
                END
489
            END;
6613 leency 490
 
7597 akron1 491
            code := code.next(ANYCODE)
492
        END
6613 leency 493
 
7597 akron1 494
    UNTIL ~shorted;
6613 leency 495
 
7597 akron1 496
    code := CodeList.first(ANYCODE);
497
    WHILE code # NIL DO
6613 leency 498
 
7597 akron1 499
        CASE code OF
6613 leency 500
 
7693 akron1 501
        |CODE:
7597 akron1 502
                FOR i := 0 TO code.length - 1 DO
503
                    BIN.PutCode(program, code.code[i])
504
                END
6613 leency 505
 
7597 akron1 506
        |LABEL:
507
                BIN.SetLabel(program, code.label, code.offset)
6613 leency 508
 
7597 akron1 509
        |JMP:
510
                IF code.short THEN
511
                    BIN.PutCode(program, 0EBH);
512
                    BIN.PutCode(program, Byte(code.diff))
513
                ELSE
514
                    BIN.PutCode(program, 0E9H);
515
                    BIN.PutCode32LE(program, code.diff)
516
                END
6613 leency 517
 
7597 akron1 518
        |JCC:
519
                IF code.short THEN
520
                    BIN.PutCode(program, code.jmp - 16);
521
                    BIN.PutCode(program, Byte(code.diff))
522
                ELSE
523
                    BIN.PutCode(program, 0FH);
524
                    BIN.PutCode(program, code.jmp);
525
                    BIN.PutCode32LE(program, code.diff)
526
                END
6613 leency 527
 
7597 akron1 528
        |CALL:
529
                BIN.PutCode(program, 0E8H);
530
                BIN.PutCode32LE(program, code.diff)
6613 leency 531
 
7597 akron1 532
        |RELOC:
533
                BIN.PutReloc(program, code.op);
534
                BIN.PutCode32LE(program, code.value)
6613 leency 535
 
7597 akron1 536
        END;
537
 
538
        code := code.next(ANYCODE)
6613 leency 539
    END
540
 
7597 akron1 541
END fixup;
6613 leency 542
 
543
 
7597 akron1 544
PROCEDURE UnOp (VAR reg: INTEGER);
6613 leency 545
BEGIN
7597 akron1 546
    REG.UnOp(R, reg)
547
END UnOp;
6613 leency 548
 
549
 
7597 akron1 550
PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
6613 leency 551
BEGIN
7597 akron1 552
    REG.BinOp(R, reg1, reg2)
553
END BinOp;
6613 leency 554
 
555
 
7597 akron1 556
PROCEDURE PushAll (NumberOfParameters: INTEGER);
6613 leency 557
BEGIN
7597 akron1 558
    REG.PushAll(R);
7693 akron1 559
    DEC(R.pushed, NumberOfParameters)
7597 akron1 560
END PushAll;
6613 leency 561
 
562
 
7597 akron1 563
PROCEDURE NewLabel (): INTEGER;
6613 leency 564
BEGIN
7597 akron1 565
    BIN.NewLabel(program)
7693 akron1 566
    RETURN IL.NewLabel()
7597 akron1 567
END NewLabel;
6613 leency 568
 
569
 
7597 akron1 570
PROCEDURE GetRegA;
6613 leency 571
BEGIN
7597 akron1 572
    ASSERT(REG.GetReg(R, eax))
573
END GetRegA;
6613 leency 574
 
575
 
7693 akron1 576
PROCEDURE translate (code: IL.CODES; pic: BOOLEAN; stroffs: INTEGER);
7597 akron1 577
VAR
578
    cmd: COMMAND;
6613 leency 579
 
7597 akron1 580
    reg1, reg2: INTEGER;
6613 leency 581
 
7597 akron1 582
    n, a, b, label, cc: INTEGER;
6613 leency 583
 
7693 akron1 584
    opcode, param1, param2: INTEGER;
6613 leency 585
 
7597 akron1 586
    float: REAL;
6613 leency 587
 
588
BEGIN
7597 akron1 589
    cmd := code.commands.first(COMMAND);
6613 leency 590
 
7597 akron1 591
    WHILE cmd # NIL DO
6613 leency 592
 
7597 akron1 593
        param1 := cmd.param1;
594
        param2 := cmd.param2;
6613 leency 595
 
7693 akron1 596
        opcode := cmd.opcode;
6613 leency 597
 
7693 akron1 598
        CASE opcode OF
599
 
600
        |IL.opJMP:
7597 akron1 601
            jmp(param1)
6613 leency 602
 
7693 akron1 603
        |IL.opCALL:
7597 akron1 604
            call(param1)
6613 leency 605
 
7693 akron1 606
        |IL.opCALLI:
7597 akron1 607
            IF pic THEN
7693 akron1 608
                reg1 := GetAnyReg();
7597 akron1 609
                Pic(reg1, BIN.PICIMP, param1);
610
                OutByte2(0FFH, 010H + reg1);  // call dword[reg1]
611
                drop
612
            ELSE
613
                OutByte2(0FFH, 015H);  // call dword[L]
614
                Reloc(BIN.RIMP, param1)
615
            END
6613 leency 616
 
7693 akron1 617
        |IL.opCALLP:
7597 akron1 618
            UnOp(reg1);
619
            OutByte2(0FFH, 0D0H + reg1);    // call reg1
620
            drop;
621
            ASSERT(R.top = -1)
6613 leency 622
 
7693 akron1 623
        |IL.opPRECALL:
7597 akron1 624
            n := param2;
625
            IF (param1 # 0) & (n # 0) THEN
626
                subrc(esp, 8)
627
            END;
628
            WHILE n > 0 DO
629
                subrc(esp, 8);
630
                OutByte3(0DDH, 01CH, 024H); // fstp qword[esp]
631
                DEC(n)
632
            END;
633
            PushAll(0)
6613 leency 634
 
7693 akron1 635
        |IL.opALIGN16:
7597 akron1 636
            ASSERT(eax IN R.regs);
637
            mov(eax, esp);
638
            andrc(esp, -16);
639
            n := (3 - param2 MOD 4) * 4;
640
            IF n > 0 THEN
641
                subrc(esp, n)
642
            END;
643
            push(eax)
644
 
7693 akron1 645
        |IL.opRES:
7597 akron1 646
            ASSERT(R.top = -1);
647
            GetRegA;
648
            n := param2;
649
            WHILE n > 0 DO
650
                OutByte3(0DDH, 004H, 024H); // fld qword[esp]
651
                addrc(esp, 8);
652
                DEC(n)
653
            END
654
 
7693 akron1 655
        |IL.opRESF:
7597 akron1 656
            n := param2;
657
            IF n > 0 THEN
658
                OutByte3(0DDH, 5CH + long(n * 8), 24H);
659
                OutIntByte(n * 8); // fstp qword[esp + n*8]
660
                INC(n)
661
            END;
662
 
663
            WHILE n > 0 DO
664
                OutByte3(0DDH, 004H, 024H); // fld qword[esp]
665
                addrc(esp, 8);
666
                DEC(n)
667
            END
668
 
7693 akron1 669
        |IL.opENTER:
7597 akron1 670
            ASSERT(R.top = -1);
671
 
672
            SetLabel(param1);
673
 
674
            push(ebp);
675
            mov(ebp, esp);
676
 
677
            n := param2;
678
            IF n > 4 THEN
679
                movrc(ecx, n);
680
                pushc(0);             // @@: push 0
681
                OutByte2(0E2H, 0FCH)  // loop @b
682
            ELSE
683
                WHILE n > 0 DO
684
                    pushc(0);
685
                    DEC(n)
686
                END
687
            END
688
 
7693 akron1 689
        |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
690
            IF opcode = IL.opLEAVER THEN
7597 akron1 691
                UnOp(reg1);
692
                IF reg1 # eax THEN
693
                    GetRegA;
694
                    ASSERT(REG.Exchange(R, reg1, eax));
695
                    drop
696
                END;
697
                drop
698
            END;
699
 
700
            ASSERT(R.top = -1);
701
 
7693 akron1 702
            IF param1 > 0 THEN
703
                mov(esp, ebp)
704
            END;
705
 
7597 akron1 706
            pop(ebp);
707
 
708
            n := param2;
709
            IF n > 0 THEN
710
                n := n * 4;
711
                OutByte(0C2H); OutWord(Word(n)) // ret n
712
            ELSE
713
                OutByte(0C3H) // ret
714
            END
715
 
7693 akron1 716
        |IL.opPUSHC:
7597 akron1 717
            pushc(param2)
718
 
7693 akron1 719
        |IL.opPARAM:
7597 akron1 720
            n := param2;
721
            IF n = 1 THEN
722
                UnOp(reg1);
723
                push(reg1);
724
                drop
725
            ELSE
726
                ASSERT(R.top + 1 <= n);
727
                PushAll(n)
728
            END
729
 
7693 akron1 730
        |IL.opCLEANUP:
7597 akron1 731
            n := param2 * 4;
732
            IF n # 0 THEN
733
                addrc(esp, n)
734
            END
735
 
7693 akron1 736
        |IL.opPOPSP:
7597 akron1 737
            pop(esp)
738
 
7693 akron1 739
        |IL.opCONST:
740
            movrc(GetAnyReg(), param2)
7597 akron1 741
 
7693 akron1 742
        |IL.opLABEL:
743
            SetLabel(param1) // L:
7597 akron1 744
 
7693 akron1 745
        |IL.opNOP:
7597 akron1 746
 
7693 akron1 747
        |IL.opGADR:
748
            reg1 := GetAnyReg();
7597 akron1 749
            IF pic THEN
750
                Pic(reg1, BIN.PICBSS, param2)
751
            ELSE
752
                OutByte(0B8H + reg1);  // mov reg1, _bss + param2
753
                Reloc(BIN.RBSS, param2)
754
            END
755
 
7693 akron1 756
        |IL.opLADR:
7597 akron1 757
            n := param2 * 4;
7693 akron1 758
            OutByte2(8DH, 45H + GetAnyReg() * 8 + long(n));  // lea reg1, dword[ebp + n]
7597 akron1 759
            OutIntByte(n)
760
 
7693 akron1 761
        |IL.opVADR:
7597 akron1 762
            n := param2 * 4;
7693 akron1 763
            OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n));  // mov reg1, dword[ebp + n]
7597 akron1 764
            OutIntByte(n)
765
 
7693 akron1 766
        |IL.opSADR:
767
            reg1 := GetAnyReg();
7597 akron1 768
            IF pic THEN
769
                Pic(reg1, BIN.PICDATA, stroffs + param2);
770
            ELSE
771
                OutByte(0B8H + reg1);  // mov reg1, _data + stroffs + param2
772
                Reloc(BIN.RDATA, stroffs + param2)
773
            END
774
 
7693 akron1 775
        |IL.opSAVEC:
7597 akron1 776
            UnOp(reg1);
777
            OutByte2(0C7H, reg1); OutInt(param2);  // mov dword[reg1], param2
778
            drop
779
 
7693 akron1 780
        |IL.opSAVE8C:
7597 akron1 781
            UnOp(reg1);
782
            OutByte3(0C6H, reg1, Byte(param2));  // mov byte[reg1], param2
783
            drop
784
 
7693 akron1 785
        |IL.opSAVE16C:
7597 akron1 786
            UnOp(reg1);
787
            OutByte3(66H, 0C7H, reg1); OutWord(Word(param2));  // mov word[reg1], param2
788
            drop
789
 
7693 akron1 790
        |IL.opVLOAD32:
7597 akron1 791
            n := param2 * 4;
7693 akron1 792
            reg1 := GetAnyReg();
7597 akron1 793
            OutByte2(8BH, 45H + reg1 * 8 + long(n));  // mov reg1, dword[ebp + n]
794
            OutIntByte(n);
795
            OutByte2(8BH, reg1 * 9)  // mov reg1, dword[reg1]
796
 
7693 akron1 797
        |IL.opGLOAD32:
798
            reg1 := GetAnyReg();
7597 akron1 799
            IF pic THEN
800
                Pic(reg1, BIN.PICBSS, param2);
801
                OutByte2(8BH, reg1 * 9)       // mov reg1, dword[reg1]
802
            ELSE
803
                OutByte2(08BH, 05H + reg1 * 8);  // mov reg1, dword[_bss + param2]
804
                Reloc(BIN.RBSS, param2)
805
            END
806
 
7693 akron1 807
        |IL.opLLOAD32:
7597 akron1 808
            n := param2 * 4;
7693 akron1 809
            OutByte2(8BH, 45H + GetAnyReg() * 8 + long(n));  // mov reg1, dword[ebp + n]
7597 akron1 810
            OutIntByte(n)
811
 
7693 akron1 812
        |IL.opLOAD32:
7597 akron1 813
            UnOp(reg1);
814
            OutByte2(8BH, reg1 * 9)  // mov reg1, dword[reg1]
815
 
7693 akron1 816
        |IL.opVLOAD8:
7597 akron1 817
            n := param2 * 4;
7693 akron1 818
            reg1 := GetAnyReg();
7597 akron1 819
            OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n]
820
            OutIntByte(n);
821
            OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1]
822
 
7693 akron1 823
        |IL.opGLOAD8:
824
            reg1 := GetAnyReg();
7597 akron1 825
            IF pic THEN
826
                Pic(reg1, BIN.PICBSS, param2);
827
                OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1]
828
            ELSE
829
                OutByte3(00FH, 0B6H, 05H + reg1 * 8);  // movzx reg1, byte[_bss + param2]
830
                Reloc(BIN.RBSS, param2)
831
            END
832
 
7693 akron1 833
        |IL.opLLOAD8:
7597 akron1 834
            n := param2 * 4;
7693 akron1 835
            OutByte3(0FH, 0B6H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, byte[ebp + n]
7597 akron1 836
            OutIntByte(n)
837
 
7693 akron1 838
        |IL.opLOAD8:
7597 akron1 839
            UnOp(reg1);
840
            OutByte3(0FH, 0B6H, reg1 * 9) // movzx reg1, byte[reg1]
841
 
7693 akron1 842
        |IL.opVLOAD16:
7597 akron1 843
            n := param2 * 4;
7693 akron1 844
            reg1 := GetAnyReg();
7597 akron1 845
            OutByte2(8BH, 45H + reg1 * 8 + long(n)); // mov reg1, dword[ebp + n]
846
            OutIntByte(n);
847
            OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1]
848
 
7693 akron1 849
        |IL.opGLOAD16:
850
            reg1 := GetAnyReg();
7597 akron1 851
            IF pic THEN
852
                Pic(reg1, BIN.PICBSS, param2);
853
                OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1]
854
            ELSE
855
                OutByte3(00FH, 0B7H, 05H + reg1 * 8);  // movzx reg1, word[_bss + param2]
856
                Reloc(BIN.RBSS, param2)
857
            END
858
 
7693 akron1 859
        |IL.opLLOAD16:
7597 akron1 860
            n := param2 * 4;
7693 akron1 861
            OutByte3(0FH, 0B7H, 45H + GetAnyReg() * 8 + long(n)); // movzx reg1, word[ebp + n]
7597 akron1 862
            OutIntByte(n)
863
 
7693 akron1 864
        |IL.opLOAD16:
7597 akron1 865
            UnOp(reg1);
866
            OutByte3(0FH, 0B7H, reg1 * 9) // movzx reg1, word[reg1]
867
 
7693 akron1 868
        |IL.opUMINUS:
7597 akron1 869
            UnOp(reg1);
870
            neg(reg1)
871
 
7693 akron1 872
        |IL.opADD:
7597 akron1 873
            BinOp(reg1, reg2);
874
            add(reg1, reg2);
875
            drop
876
 
7693 akron1 877
        |IL.opADDL, IL.opADDR:
7597 akron1 878
            IF param2 # 0 THEN
879
                UnOp(reg1);
880
                IF param2 = 1 THEN
881
                    OutByte(40H + reg1) // inc reg1
882
                ELSIF param2 = -1 THEN
883
                    OutByte(48H + reg1) // dec reg1
884
                ELSE
885
                    addrc(reg1, param2)
886
                END
887
            END
888
 
7693 akron1 889
        |IL.opSUB:
7597 akron1 890
            BinOp(reg1, reg2);
891
            OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2
892
            drop
893
 
7693 akron1 894
        |IL.opSUBR, IL.opSUBL:
7597 akron1 895
            UnOp(reg1);
896
            n := param2;
897
            IF n = 1 THEN
898
                OutByte(48H + reg1) // dec reg1
899
            ELSIF n = -1 THEN
900
                OutByte(40H + reg1) // inc reg1
901
            ELSIF n # 0 THEN
902
                subrc(reg1, n)
903
            END;
7693 akron1 904
            IF opcode = IL.opSUBL THEN
7597 akron1 905
                neg(reg1)
906
            END
907
 
7693 akron1 908
        |IL.opMULC:
7597 akron1 909
            UnOp(reg1);
910
 
911
            a := param2;
912
            IF a > 1 THEN
7693 akron1 913
                n := UTILS.Log2(a)
7597 akron1 914
            ELSIF a < -1 THEN
7693 akron1 915
                n := UTILS.Log2(-a)
7597 akron1 916
            ELSE
917
                n := -1
918
            END;
919
 
920
            IF a = 1 THEN
921
 
922
            ELSIF a = -1 THEN
923
                neg(reg1)
924
            ELSIF a = 0 THEN
7667 akron1 925
                xor(reg1, reg1)
7597 akron1 926
            ELSE
927
                IF n > 0 THEN
928
                    IF a < 0 THEN
929
                        neg(reg1)
930
                    END;
931
 
932
                    IF n # 1 THEN
933
                        OutByte3(0C1H, 0E0H + reg1, n)   // shl reg1, n
934
                    ELSE
935
                        OutByte2(0D1H, 0E0H + reg1)      // shl reg1, 1
936
                    END
937
                ELSE
938
                    OutByte2(69H + short(a), 0C0H + reg1 * 9); // imul reg1, a
939
                    OutIntByte(a)
940
                END
941
            END
942
 
7693 akron1 943
        |IL.opMUL:
7597 akron1 944
            BinOp(reg1, reg2);
945
            OutByte3(0FH, 0AFH, 0C0H + reg1 * 8 + reg2); // imul reg1, reg2
946
            drop
947
 
7693 akron1 948
        |IL.opSAVE, IL.opSAVE32:
7597 akron1 949
            BinOp(reg2, reg1);
950
            OutByte2(89H, reg2 * 8 + reg1); // mov dword[reg1], reg2
951
            drop;
952
            drop
953
 
7693 akron1 954
        |IL.opSAVE8:
7597 akron1 955
            BinOp(reg2, reg1);
956
            OutByte2(88H, reg2 * 8 + reg1); // mov byte[reg1], reg2
957
            drop;
958
            drop
959
 
7693 akron1 960
        |IL.opSAVE16:
7597 akron1 961
            BinOp(reg2, reg1);
962
            OutByte3(66H, 89H, reg2 * 8 + reg1); // mov word[reg1], reg2
963
            drop;
964
            drop
965
 
7693 akron1 966
        |IL.opSAVEP:
7597 akron1 967
            UnOp(reg1);
968
            IF pic THEN
7693 akron1 969
                reg2 := GetAnyReg();
7597 akron1 970
                Pic(reg2, BIN.PICCODE, param2);
971
                OutByte2(089H, reg2 * 8 + reg1); // mov dword[reg1], reg2
972
                drop
973
            ELSE
974
                OutByte2(0C7H, reg1);  // mov dword[reg1], L
975
                Reloc(BIN.RCODE, param2)
976
            END;
977
            drop
978
 
7693 akron1 979
        |IL.opSAVEIP:
7597 akron1 980
            UnOp(reg1);
981
            IF pic THEN
7693 akron1 982
                reg2 := GetAnyReg();
7597 akron1 983
                Pic(reg2, BIN.PICIMP, param2);
984
                OutByte2(0FFH, 30H + reg2);   // push dword[reg2]
985
                OutByte2(08FH, reg1);         // pop dword[reg1]
986
                drop
987
            ELSE
988
                OutByte2(0FFH, 035H);  // push dword[L]
989
                Reloc(BIN.RIMP, param2);
990
                OutByte2(08FH, reg1)   // pop dword[reg1]
991
            END;
992
            drop
993
 
7693 akron1 994
        |IL.opPUSHP:
995
            reg1 := GetAnyReg();
7597 akron1 996
            IF pic THEN
997
                Pic(reg1, BIN.PICCODE, param2)
998
            ELSE
999
                OutByte(0B8H + reg1);  // mov reg1, L
1000
                Reloc(BIN.RCODE, param2)
1001
            END
1002
 
7693 akron1 1003
        |IL.opPUSHIP:
1004
            reg1 := GetAnyReg();
7597 akron1 1005
            IF pic THEN
1006
                Pic(reg1, BIN.PICIMP, param2);
1007
                OutByte2(08BH, reg1 * 9)         // mov reg1, dword[reg1]
1008
            ELSE
1009
                OutByte2(08BH, 05H + reg1 * 8);  // mov reg1, dword[L]
1010
                Reloc(BIN.RIMP, param2)
1011
            END
1012
 
7693 akron1 1013
        |IL.opNOT:
7597 akron1 1014
            UnOp(reg1);
1015
            test(reg1);
1016
            setcc(sete, reg1);
1017
            andrc(reg1, 1)
1018
 
7693 akron1 1019
        |IL.opORD:
7597 akron1 1020
            UnOp(reg1);
1021
            test(reg1);
1022
            setcc(setne, reg1);
1023
            andrc(reg1, 1)
1024
 
7693 akron1 1025
        |IL.opSBOOL:
7597 akron1 1026
            BinOp(reg2, reg1);
1027
            test(reg2);
7693 akron1 1028
            OutByte3(0FH, 95H, reg1); // setne byte[reg1]
7597 akron1 1029
            drop;
1030
            drop
1031
 
7693 akron1 1032
        |IL.opSBOOLC:
7597 akron1 1033
            UnOp(reg1);
1034
            OutByte3(0C6H, reg1, ORD(param2 # 0)); // mov byte[reg1], 0/1
1035
            drop
1036
 
7693 akron1 1037
        |IL.opODD:
7597 akron1 1038
            UnOp(reg1);
1039
            andrc(reg1, 1)
1040
 
7693 akron1 1041
        |IL.opEQ..IL.opGE,
1042
         IL.opEQC..IL.opGEC:
1043
 
1044
            IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
1045
                BinOp(reg1, reg2);
1046
                cmprr(reg1, reg2);
1047
                drop
7597 akron1 1048
            ELSE
7693 akron1 1049
                UnOp(reg1);
1050
                IF param2 = 0 THEN
1051
                    test(reg1)
1052
                ELSE
1053
                    cmprc(reg1, param2)
1054
                END
7597 akron1 1055
            END;
1056
 
1057
            drop;
7693 akron1 1058
            cc := cond(opcode);
7597 akron1 1059
 
7693 akron1 1060
            IF cmd.next(COMMAND).opcode = IL.opJE THEN
7597 akron1 1061
                label := cmd.next(COMMAND).param1;
1062
                jcc(cc, label);
1063
                cmd := cmd.next(COMMAND)
1064
 
7693 akron1 1065
            ELSIF cmd.next(COMMAND).opcode = IL.opJNE THEN
7597 akron1 1066
                label := cmd.next(COMMAND).param1;
7693 akron1 1067
                jcc(inv0(cc), label);
7597 akron1 1068
                cmd := cmd.next(COMMAND)
1069
 
1070
            ELSE
7693 akron1 1071
                reg1 := GetAnyReg();
7597 akron1 1072
                setcc(cc + 16, reg1);
1073
                andrc(reg1, 1)
1074
            END
1075
 
7693 akron1 1076
        |IL.opEQB, IL.opNEB:
7597 akron1 1077
            BinOp(reg1, reg2);
1078
            drop;
1079
 
1080
            test(reg1);
1081
            OutByte2(74H, 5);  // je @f
1082
            movrc(reg1, 1);    // mov reg1, 1
1083
                               // @@:
1084
            test(reg2);
1085
            OutByte2(74H, 5);  // je @f
1086
            movrc(reg2, 1);    // mov reg2, 1
1087
                               // @@:
1088
 
1089
            cmprr(reg1, reg2);
7693 akron1 1090
            IF opcode = IL.opEQB THEN
7597 akron1 1091
                setcc(sete, reg1)
1092
            ELSE
1093
                setcc(setne, reg1)
1094
            END;
1095
            andrc(reg1, 1)
7693 akron1 1096
 
1097
        |IL.opACC:
7667 akron1 1098
            IF (R.top # 0) OR (R.stk[0] # eax) THEN
1099
                PushAll(0);
1100
                GetRegA;
1101
                pop(eax);
1102
                DEC(R.pushed)
1103
            END
7597 akron1 1104
 
7693 akron1 1105
        |IL.opDROP:
7597 akron1 1106
            UnOp(reg1);
1107
            drop
1108
 
7693 akron1 1109
        |IL.opJNZ:
7597 akron1 1110
            UnOp(reg1);
1111
            test(reg1);
1112
            jcc(jne, param1)
1113
 
7693 akron1 1114
        |IL.opJZ:
7597 akron1 1115
            UnOp(reg1);
1116
            test(reg1);
1117
            jcc(je, param1)
1118
 
7693 akron1 1119
        |IL.opJE:
7597 akron1 1120
            UnOp(reg1);
1121
            test(reg1);
1122
            jcc(jne, param1);
7693 akron1 1123
            drop
7597 akron1 1124
 
7693 akron1 1125
        |IL.opJNE:
7597 akron1 1126
            UnOp(reg1);
1127
            test(reg1);
1128
            jcc(je, param1);
7693 akron1 1129
            drop
7597 akron1 1130
 
7693 akron1 1131
        |IL.opSWITCH:
7597 akron1 1132
            UnOp(reg1);
1133
            IF param2 = 0 THEN
1134
                reg2 := eax
1135
            ELSE
1136
                reg2 := ecx
1137
            END;
1138
            IF reg1 # reg2 THEN
1139
                ASSERT(REG.GetReg(R, reg2));
1140
                ASSERT(REG.Exchange(R, reg1, reg2));
1141
                drop
1142
            END;
1143
            drop
1144
 
7693 akron1 1145
        |IL.opENDSW:
7597 akron1 1146
 
7693 akron1 1147
        |IL.opCASEL:
7597 akron1 1148
            cmprc(eax, param1);
1149
            jcc(jl, param2)
1150
 
7693 akron1 1151
        |IL.opCASER:
7597 akron1 1152
            cmprc(eax, param1);
1153
            jcc(jg, param2)
1154
 
7693 akron1 1155
        |IL.opCASELR:
7597 akron1 1156
            cmprc(eax, param1);
1157
            jcc(jl, param2);
1158
            jcc(jg, cmd.param3)
1159
 
7693 akron1 1160
        |IL.opCODE:
7597 akron1 1161
            OutByte(param2)
1162
 
7693 akron1 1163
        |IL.opGET, IL.opGETC:
1164
            IF opcode = IL.opGET THEN
1165
                BinOp(reg1, reg2)
1166
            ELSIF opcode = IL.opGETC THEN
1167
                UnOp(reg2);
1168
                reg1 := GetAnyReg();
1169
                movrc(reg1, param1)
1170
            END;
7597 akron1 1171
            drop;
1172
            drop;
1173
 
1174
            CASE param2 OF
1175
            |1:
1176
                OutByte2(8AH, reg1 * 9);       // mov reg1, byte[reg1]
1177
                OutByte2(88H, reg1 * 8 + reg2) // mov byte[reg2], reg1
1178
 
1179
            |2:
1180
                OutByte3(66H, 8BH, reg1 * 9);       // mov reg1, word[reg1]
1181
                OutByte3(66H, 89H, reg1 * 8 + reg2) // mov word[reg2], reg1
1182
 
1183
            |4:
1184
                OutByte2(8BH, reg1 * 9);        // mov reg1, dword[reg1]
1185
                OutByte2(89H, reg1 * 8 + reg2)  // mov dword[reg2], reg1
1186
 
1187
            |8:
1188
                PushAll(0);
1189
                push(reg2);
1190
                push(reg1);
1191
                pushc(8);
7693 akron1 1192
                CallRTL(pic, IL._move)
7597 akron1 1193
 
1194
            END
1195
 
7693 akron1 1196
        |IL.opSAVES:
7597 akron1 1197
            UnOp(reg1);
1198
            drop;
1199
            PushAll(0);
1200
            push(reg1);
1201
 
1202
            IF pic THEN
1203
                Pic(reg1, BIN.PICDATA, stroffs + param2);
1204
                push(reg1)
1205
            ELSE
1206
                OutByte(068H);  // push _data + stroffs + param2
1207
                Reloc(BIN.RDATA, stroffs + param2);
1208
            END;
1209
 
1210
            pushc(param1);
7693 akron1 1211
            CallRTL(pic, IL._move)
7597 akron1 1212
 
7693 akron1 1213
        |IL.opCHKBYTE:
7597 akron1 1214
            BinOp(reg1, reg2);
1215
            cmprc(reg1, 256);
1216
            jcc(jb, param1)
1217
 
7693 akron1 1218
        |IL.opCHKIDX:
7597 akron1 1219
            UnOp(reg1);
1220
            cmprc(reg1, param2);
1221
            jcc(jb, param1)
1222
 
7693 akron1 1223
        |IL.opCHKIDX2:
7597 akron1 1224
            BinOp(reg1, reg2);
1225
            IF param2 # -1 THEN
1226
                cmprr(reg2, reg1);
1227
                mov(reg1, reg2);
1228
                drop;
1229
                jcc(jb, param1)
1230
            ELSE
1231
                INCL(R.regs, reg1);
1232
                DEC(R.top);
1233
                R.stk[R.top] := reg2
1234
            END
1235
 
7693 akron1 1236
        |IL.opLEN:
7597 akron1 1237
            n := param2;
1238
            UnOp(reg1);
1239
            drop;
1240
            EXCL(R.regs, reg1);
1241
 
1242
            WHILE n > 0 DO
1243
                UnOp(reg2);
1244
                drop;
1245
                DEC(n)
1246
            END;
1247
 
1248
            INCL(R.regs, reg1);
1249
            ASSERT(REG.GetReg(R, reg1))
1250
 
7693 akron1 1251
        |IL.opINCC:
7597 akron1 1252
            UnOp(reg1);
7693 akron1 1253
            OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2
7597 akron1 1254
            drop
1255
 
7693 akron1 1256
        |IL.opINC, IL.opDEC:
7597 akron1 1257
            BinOp(reg1, reg2);
7693 akron1 1258
            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1
7597 akron1 1259
            drop;
1260
            drop
1261
 
7693 akron1 1262
        |IL.opINCCB, IL.opDECCB:
7597 akron1 1263
            UnOp(reg1);
7693 akron1 1264
            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n
7597 akron1 1265
            drop
1266
 
7693 akron1 1267
        |IL.opINCB, IL.opDECB:
7597 akron1 1268
            BinOp(reg1, reg2);
7693 akron1 1269
            OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1
7597 akron1 1270
            drop;
1271
            drop
1272
 
7693 akron1 1273
        |IL.opMULS:
7597 akron1 1274
            BinOp(reg1, reg2);
1275
            OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2
1276
            drop
1277
 
7693 akron1 1278
        |IL.opMULSC:
7597 akron1 1279
            UnOp(reg1);
1280
            andrc(reg1, param2)
1281
 
7693 akron1 1282
        |IL.opDIVS:
7597 akron1 1283
            BinOp(reg1, reg2);
7667 akron1 1284
            xor(reg1, reg2);
7597 akron1 1285
            drop
1286
 
7693 akron1 1287
        |IL.opDIVSC:
7597 akron1 1288
            UnOp(reg1);
1289
            OutByte2(81H + short(param2), 0F0H + reg1);  // xor reg1, n
1290
            OutIntByte(param2)
1291
 
7693 akron1 1292
        |IL.opADDS:
7597 akron1 1293
            BinOp(reg1, reg2);
1294
            OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2
1295
            drop
1296
 
7693 akron1 1297
        |IL.opSUBS:
7597 akron1 1298
            BinOp(reg1, reg2);
1299
            not(reg2);
1300
            OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2
1301
            drop
1302
 
7693 akron1 1303
        |IL.opADDSL, IL.opADDSR:
7597 akron1 1304
            UnOp(reg1);
1305
            orrc(reg1, param2)
1306
 
7693 akron1 1307
        |IL.opSUBSL:
7597 akron1 1308
            UnOp(reg1);
1309
            not(reg1);
1310
            andrc(reg1, param2)
1311
 
7693 akron1 1312
        |IL.opSUBSR:
7597 akron1 1313
            UnOp(reg1);
7693 akron1 1314
            andrc(reg1, ORD(-BITS(param2)))
7597 akron1 1315
 
7693 akron1 1316
        |IL.opUMINS:
7597 akron1 1317
            UnOp(reg1);
1318
            not(reg1)
1319
 
7693 akron1 1320
        |IL.opLENGTH:
7597 akron1 1321
            PushAll(2);
7693 akron1 1322
            CallRTL(pic, IL._length);
7597 akron1 1323
            GetRegA
1324
 
7693 akron1 1325
        |IL.opLENGTHW:
7597 akron1 1326
            PushAll(2);
7693 akron1 1327
            CallRTL(pic, IL._lengthw);
7597 akron1 1328
            GetRegA
1329
 
7693 akron1 1330
        |IL.opCHR:
7597 akron1 1331
            UnOp(reg1);
1332
            andrc(reg1, 255)
1333
 
7693 akron1 1334
        |IL.opWCHR:
7597 akron1 1335
            UnOp(reg1);
1336
            andrc(reg1, 65535)
1337
 
7693 akron1 1338
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
7597 akron1 1339
            UnOp(reg1);
1340
            IF reg1 # ecx THEN
1341
                ASSERT(REG.GetReg(R, ecx));
1342
                ASSERT(REG.Exchange(R, reg1, ecx));
1343
                drop
1344
            END;
1345
 
1346
            BinOp(reg1, reg2);
1347
            ASSERT(reg2 = ecx);
1348
            OutByte(0D3H);
7693 akron1 1349
            shift(opcode, reg1); // shift reg1, cl
7597 akron1 1350
            drop
1351
 
7693 akron1 1352
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
7597 akron1 1353
            UnOp(reg1);
1354
            IF reg1 # ecx THEN
1355
                ASSERT(REG.GetReg(R, ecx));
1356
                ASSERT(REG.Exchange(R, reg1, ecx));
1357
                drop
1358
            END;
1359
 
7693 akron1 1360
            reg1 := GetAnyReg();
7597 akron1 1361
            movrc(reg1, param2);
1362
            BinOp(reg1, reg2);
1363
            ASSERT(reg1 = ecx);
1364
            OutByte(0D3H);
7693 akron1 1365
            shift(opcode, reg2); // shift reg2, cl
7597 akron1 1366
            drop;
1367
            drop;
1368
            ASSERT(REG.GetReg(R, reg2))
1369
 
7693 akron1 1370
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
7597 akron1 1371
            UnOp(reg1);
7693 akron1 1372
            n := param2 MOD 32;
7597 akron1 1373
            IF n # 1 THEN
1374
                OutByte(0C1H)
1375
            ELSE
1376
                OutByte(0D1H)
1377
            END;
7693 akron1 1378
            shift(opcode, reg1); // shift reg1, n
7597 akron1 1379
            IF n # 1 THEN
1380
                OutByte(n)
1381
            END
1382
 
7693 akron1 1383
        |IL.opMIN:
7597 akron1 1384
            BinOp(reg1, reg2);
1385
            cmprr(reg1, reg2);
1386
            OutByte2(07EH, 002H);  // jle @f
1387
            mov(reg1, reg2);       // mov reg1, reg2
1388
                                   // @@:
1389
            drop
1390
 
7693 akron1 1391
        |IL.opMAX:
7597 akron1 1392
            BinOp(reg1, reg2);
1393
            cmprr(reg1, reg2);
1394
            OutByte2(07DH, 002H);  // jge @f
1395
            mov(reg1, reg2);       // mov reg1, reg2
1396
                                   // @@:
1397
            drop
1398
 
7693 akron1 1399
        |IL.opMINC:
7597 akron1 1400
            UnOp(reg1);
1401
            cmprc(reg1, param2);
1402
            OutByte2(07EH, 005H);    // jle @f
7693 akron1 1403
            movrc(reg1, param2)      // mov reg1, param2
7597 akron1 1404
                                     // @@:
1405
 
7693 akron1 1406
        |IL.opMAXC:
7597 akron1 1407
            UnOp(reg1);
1408
            cmprc(reg1, param2);
1409
            OutByte2(07DH, 005H);    // jge @f
7693 akron1 1410
            movrc(reg1, param2)      // mov reg1, param2
7597 akron1 1411
                                     // @@:
1412
 
7693 akron1 1413
        |IL.opIN:
7597 akron1 1414
            label := NewLabel();
1415
            BinOp(reg1, reg2);
1416
            cmprc(reg1, 32);
1417
            OutByte2(72H, 4); // jb L
7667 akron1 1418
            xor(reg1, reg1);
7597 akron1 1419
            jmp(label);
1420
            //L:
1421
            OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1
1422
            setcc(setc, reg1);
1423
            andrc(reg1, 1);
1424
            SetLabel(label);
1425
            drop
1426
 
7693 akron1 1427
        |IL.opINR:
7597 akron1 1428
            label := NewLabel();
1429
            UnOp(reg1);
7693 akron1 1430
            reg2 := GetAnyReg();
7597 akron1 1431
            cmprc(reg1, 32);
1432
            OutByte2(72H, 4); // jb L
7667 akron1 1433
            xor(reg1, reg1);
7597 akron1 1434
            jmp(label);
1435
            //L:
1436
            movrc(reg2, param2);
1437
            OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1
1438
            setcc(setc, reg1);
1439
            andrc(reg1, 1);
1440
            SetLabel(label);
1441
            drop
1442
 
7693 akron1 1443
        |IL.opINL:
7597 akron1 1444
            UnOp(reg1);
1445
            OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2
1446
            setcc(setc, reg1);
1447
            andrc(reg1, 1)
1448
 
7693 akron1 1449
        |IL.opRSET:
7597 akron1 1450
            PushAll(2);
7693 akron1 1451
            CallRTL(pic, IL._set);
7597 akron1 1452
            GetRegA
1453
 
7693 akron1 1454
        |IL.opRSETR:
7597 akron1 1455
            PushAll(1);
1456
            pushc(param2);
7693 akron1 1457
            CallRTL(pic, IL._set);
7597 akron1 1458
            GetRegA
1459
 
7693 akron1 1460
        |IL.opRSETL:
7597 akron1 1461
            PushAll(1);
1462
            pushc(param2);
7693 akron1 1463
            CallRTL(pic, IL._set2);
7597 akron1 1464
            GetRegA
1465
 
7693 akron1 1466
        |IL.opRSET1:
7597 akron1 1467
            UnOp(reg1);
1468
            PushAll(1);
1469
            push(reg1);
7693 akron1 1470
            CallRTL(pic, IL._set);
7597 akron1 1471
            GetRegA
1472
 
7693 akron1 1473
        |IL.opINCL, IL.opEXCL:
7597 akron1 1474
            BinOp(reg1, reg2);
1475
            cmprc(reg1, 32);
1476
            OutByte2(73H, 03H); // jnb L
1477
            OutByte(0FH);
7693 akron1 1478
            IF opcode = IL.opINCL THEN
7597 akron1 1479
                OutByte(0ABH) // bts dword[reg2], reg1
1480
            ELSE
1481
                OutByte(0B3H) // btr dword[reg2], reg1
1482
            END;
1483
            OutByte(reg2 + 8 * reg1);
1484
            //L:
1485
            drop;
1486
            drop
1487
 
7693 akron1 1488
        |IL.opINCLC:
7597 akron1 1489
            UnOp(reg1);
1490
            OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2
1491
            drop
1492
 
7693 akron1 1493
        |IL.opEXCLC:
7597 akron1 1494
            UnOp(reg1);
1495
            OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2
1496
            drop
1497
 
7693 akron1 1498
        |IL.opDIV:
7597 akron1 1499
            PushAll(2);
7693 akron1 1500
            CallRTL(pic, IL._div);
7597 akron1 1501
            GetRegA
1502
 
7693 akron1 1503
        |IL.opDIVR:
7597 akron1 1504
            a := param2;
1505
            IF a > 1 THEN
7693 akron1 1506
                n := UTILS.Log2(a)
7597 akron1 1507
            ELSIF a < -1 THEN
7693 akron1 1508
                n := UTILS.Log2(-a)
7597 akron1 1509
            ELSE
1510
                n := -1
1511
            END;
1512
 
1513
            IF a = 1 THEN
1514
 
1515
            ELSIF a = -1 THEN
1516
                UnOp(reg1);
1517
                neg(reg1)
1518
            ELSE
1519
                IF n > 0 THEN
1520
                    UnOp(reg1);
1521
 
1522
                    IF a < 0 THEN
7693 akron1 1523
                        reg2 := GetAnyReg();
7597 akron1 1524
                        mov(reg2, reg1);
1525
                        IF n # 1 THEN
1526
                            OutByte3(0C1H, 0F8H + reg1, n)     // sar reg1, n
1527
                        ELSE
1528
                            OutByte2(0D1H, 0F8H + reg1)        // sar reg1, 1
1529
                        END;
1530
                        OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2
1531
                        drop
1532
                    ELSE
1533
                        IF n # 1 THEN
1534
                            OutByte3(0C1H, 0F8H + reg1, n)     // sar reg1, n
1535
                        ELSE
1536
                            OutByte2(0D1H, 0F8H + reg1)        // sar reg1, 1
1537
                        END
1538
                    END
1539
 
1540
                ELSE
1541
                    PushAll(1);
1542
                    pushc(param2);
7693 akron1 1543
                    CallRTL(pic, IL._div);
7597 akron1 1544
                    GetRegA
1545
                END
1546
            END
1547
 
7693 akron1 1548
        |IL.opDIVL:
7597 akron1 1549
            PushAll(1);
1550
            pushc(param2);
7693 akron1 1551
            CallRTL(pic, IL._div2);
7597 akron1 1552
            GetRegA
1553
 
7693 akron1 1554
        |IL.opMOD:
7597 akron1 1555
            PushAll(2);
7693 akron1 1556
            CallRTL(pic, IL._mod);
7597 akron1 1557
            GetRegA
1558
 
7693 akron1 1559
        |IL.opMODR:
7597 akron1 1560
            a := param2;
1561
            IF a > 1 THEN
7693 akron1 1562
                n := UTILS.Log2(a)
7597 akron1 1563
            ELSIF a < -1 THEN
7693 akron1 1564
                n := UTILS.Log2(-a)
7597 akron1 1565
            ELSE
1566
                n := -1
1567
            END;
1568
 
1569
            IF ABS(a) = 1 THEN
1570
                UnOp(reg1);
7667 akron1 1571
                xor(reg1, reg1)
7597 akron1 1572
            ELSE
1573
                IF n > 0 THEN
1574
                    UnOp(reg1);
1575
                    andrc(reg1, ABS(a) - 1);
1576
 
1577
                    IF a < 0 THEN
1578
                        test(reg1);
1579
                        OutByte(74H);      // je @f
1580
                        IF isByte(a) THEN
1581
                            OutByte(3)
1582
                        ELSE
1583
                            OutByte(6)
1584
                        END;
1585
                        addrc(reg1, a)
1586
                                           // @@:
1587
                    END
1588
 
1589
                ELSE
1590
                    PushAll(1);
1591
                    pushc(param2);
7693 akron1 1592
                    CallRTL(pic, IL._mod);
7597 akron1 1593
                    GetRegA
1594
                END
1595
            END
1596
 
7693 akron1 1597
        |IL.opMODL:
7597 akron1 1598
            PushAll(1);
1599
            pushc(param2);
7693 akron1 1600
            CallRTL(pic, IL._mod2);
7597 akron1 1601
            GetRegA
1602
 
7693 akron1 1603
        |IL.opERR:
1604
            CallRTL(pic, IL._error)
7597 akron1 1605
 
7693 akron1 1606
        |IL.opABS:
7597 akron1 1607
            UnOp(reg1);
1608
            test(reg1);
1609
            OutByte2(07DH, 002H); // jge @f
7693 akron1 1610
            neg(reg1)             // neg reg1
7597 akron1 1611
                                  // @@:
1612
 
7693 akron1 1613
        |IL.opCOPY:
7597 akron1 1614
            PushAll(2);
1615
            pushc(param2);
7693 akron1 1616
            CallRTL(pic, IL._move2)
7597 akron1 1617
 
7693 akron1 1618
        |IL.opMOVE:
7597 akron1 1619
            PushAll(3);
7693 akron1 1620
            CallRTL(pic, IL._move2)
7597 akron1 1621
 
7693 akron1 1622
        |IL.opCOPYA:
7597 akron1 1623
            PushAll(4);
1624
            pushc(param2);
7693 akron1 1625
            CallRTL(pic, IL._arrcpy);
7597 akron1 1626
            GetRegA
1627
 
7693 akron1 1628
        |IL.opCOPYS:
7597 akron1 1629
            PushAll(4);
1630
            pushc(param2);
7693 akron1 1631
            CallRTL(pic, IL._strcpy)
7597 akron1 1632
 
7693 akron1 1633
        |IL.opROT:
7597 akron1 1634
            PushAll(0);
1635
            push(esp);
1636
            pushc(param2);
7693 akron1 1637
            CallRTL(pic, IL._rot)
7597 akron1 1638
 
7693 akron1 1639
        |IL.opNEW:
7597 akron1 1640
            PushAll(1);
1641
            n := param2 + 8;
7693 akron1 1642
            ASSERT(UTILS.Align(n, 32));
7597 akron1 1643
            pushc(n);
1644
            pushc(param1);
7693 akron1 1645
            CallRTL(pic, IL._new)
7597 akron1 1646
 
7693 akron1 1647
        |IL.opDISP:
7597 akron1 1648
            PushAll(1);
7693 akron1 1649
            CallRTL(pic, IL._dispose)
7597 akron1 1650
 
7693 akron1 1651
        |IL.opEQS .. IL.opGES:
7597 akron1 1652
            PushAll(4);
7693 akron1 1653
            pushc(opcode - IL.opEQS);
1654
            CallRTL(pic, IL._strcmp);
7597 akron1 1655
            GetRegA
1656
 
7693 akron1 1657
        |IL.opEQSW .. IL.opGESW:
7597 akron1 1658
            PushAll(4);
7693 akron1 1659
            pushc(opcode - IL.opEQSW);
1660
            CallRTL(pic, IL._strcmpw);
7597 akron1 1661
            GetRegA
1662
 
7693 akron1 1663
        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
7597 akron1 1664
            UnOp(reg1);
7693 akron1 1665
            CASE opcode OF
1666
            |IL.opEQP, IL.opNEP:
7597 akron1 1667
                IF pic THEN
7693 akron1 1668
                    reg2 := GetAnyReg();
7597 akron1 1669
                    Pic(reg2, BIN.PICCODE, param1);
1670
                    cmprr(reg1, reg2);
1671
                    drop
1672
                ELSE
1673
                    OutByte2(081H, 0F8H + reg1);  // cmp reg1, L
1674
                    Reloc(BIN.RCODE, param1)
1675
                END
1676
 
7693 akron1 1677
            |IL.opEQIP, IL.opNEIP:
7597 akron1 1678
                IF pic THEN
7693 akron1 1679
                    reg2 := GetAnyReg();
7597 akron1 1680
                    Pic(reg2, BIN.PICIMP, param1);
1681
                    OutByte2(03BH, reg1 * 8 + reg2);  //cmp reg1, dword [reg2]
1682
                    drop
1683
                ELSE
1684
                    OutByte2(3BH, 05H + reg1 * 8);    // cmp reg1, dword[L]
1685
                    Reloc(BIN.RIMP, param1)
1686
                END
1687
 
1688
            END;
1689
            drop;
7693 akron1 1690
            reg1 := GetAnyReg();
7597 akron1 1691
 
7693 akron1 1692
            CASE opcode OF
1693
            |IL.opEQP, IL.opEQIP: setcc(sete,  reg1)
1694
            |IL.opNEP, IL.opNEIP: setcc(setne, reg1)
7597 akron1 1695
            END;
1696
 
1697
            andrc(reg1, 1)
1698
 
7693 akron1 1699
        |IL.opPUSHT:
7597 akron1 1700
            UnOp(reg1);
7693 akron1 1701
            reg2 := GetAnyReg();
7597 akron1 1702
            OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH)  // mov reg2, dword[reg1 - 4]
1703
 
7693 akron1 1704
        |IL.opISREC:
7597 akron1 1705
            PushAll(2);
7693 akron1 1706
            pushc(param2 * tcount);
1707
            CallRTL(pic, IL._isrec);
7597 akron1 1708
            GetRegA
1709
 
7693 akron1 1710
        |IL.opIS:
7597 akron1 1711
            PushAll(1);
7693 akron1 1712
            pushc(param2 * tcount);
1713
            CallRTL(pic, IL._is);
7597 akron1 1714
            GetRegA
1715
 
7693 akron1 1716
        |IL.opTYPEGR:
7597 akron1 1717
            PushAll(1);
7693 akron1 1718
            pushc(param2 * tcount);
1719
            CallRTL(pic, IL._guardrec);
7597 akron1 1720
            GetRegA
1721
 
7693 akron1 1722
        |IL.opTYPEGP:
7597 akron1 1723
            UnOp(reg1);
1724
            PushAll(0);
1725
            push(reg1);
7693 akron1 1726
            pushc(param2 * tcount);
1727
            CallRTL(pic, IL._guard);
7597 akron1 1728
            GetRegA
1729
 
7693 akron1 1730
        |IL.opTYPEGD:
7597 akron1 1731
            UnOp(reg1);
1732
            PushAll(0);
1733
            OutByte3(0FFH, 070H + reg1, 0FCH);  // push dword[reg1 - 4]
7693 akron1 1734
            pushc(param2 * tcount);
1735
            CallRTL(pic, IL._guardrec);
7597 akron1 1736
            GetRegA
1737
 
7693 akron1 1738
        |IL.opCASET:
7597 akron1 1739
            push(ecx);
1740
            push(ecx);
7693 akron1 1741
            pushc(param2 * tcount);
1742
            CallRTL(pic, IL._guardrec);
7597 akron1 1743
            pop(ecx);
1744
            test(eax);
1745
            jcc(jne, param1)
1746
 
7693 akron1 1747
        |IL.opPACK:
7597 akron1 1748
            BinOp(reg1, reg2);
1749
            push(reg2);
1750
            OutByte3(0DBH, 004H, 024H);   // fild dword[esp]
1751
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1752
            OutByte2(0D9H, 0FDH);         // fscale
1753
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1754
            OutByte3(0DBH, 01CH, 024H);   // fistp dword[esp]
1755
            pop(reg2);
1756
            drop;
1757
            drop
1758
 
7693 akron1 1759
        |IL.opPACKC:
7597 akron1 1760
            UnOp(reg1);
1761
            pushc(param2);
1762
            OutByte3(0DBH, 004H, 024H);   // fild dword[esp]
1763
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1764
            OutByte2(0D9H, 0FDH);         // fscale
1765
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1766
            OutByte3(0DBH, 01CH, 024H);   // fistp dword[esp]
1767
            pop(reg1);
1768
            drop
1769
 
7693 akron1 1770
        |IL.opUNPK:
7597 akron1 1771
            BinOp(reg1, reg2);
1772
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1773
            OutByte2(0D9H, 0F4H);         // fxtract
1774
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1775
            OutByte2(0DBH, 018H + reg2);  // fistp dword[reg2]
1776
            drop;
1777
            drop
1778
 
7693 akron1 1779
        |IL.opPUSHF:
7597 akron1 1780
            subrc(esp, 8);
1781
            OutByte3(0DDH, 01CH, 024H)    // fstp qword[esp]
1782
 
7693 akron1 1783
        |IL.opLOADF:
7597 akron1 1784
            UnOp(reg1);
1785
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1786
            drop
1787
 
7693 akron1 1788
        |IL.opCONSTF:
7597 akron1 1789
            float := cmd.float;
1790
            IF float = 0.0 THEN
1791
                OutByte2(0D9H, 0EEH)      // fldz
1792
            ELSIF float = 1.0 THEN
1793
                OutByte2(0D9H, 0E8H)      // fld1
1794
            ELSIF float = -1.0 THEN
1795
                OutByte2(0D9H, 0E8H);     // fld1
1796
                OutByte2(0D9H, 0E0H)      // fchs
1797
            ELSE
1798
                n := UTILS.splitf(float, a, b);
1799
                pushc(b);
1800
                pushc(a);
1801
                OutByte3(0DDH, 004H, 024H); // fld qword[esp]
1802
                addrc(esp, 8)
1803
            END
1804
 
7693 akron1 1805
        |IL.opSAVEF:
7597 akron1 1806
            UnOp(reg1);
1807
            OutByte2(0DDH, 018H + reg1); // fstp qword[reg1]
1808
            drop
1809
 
7693 akron1 1810
        |IL.opADDF, IL.opADDFI:
7597 akron1 1811
            OutByte2(0DEH, 0C1H)  // faddp st1, st
1812
 
7693 akron1 1813
        |IL.opSUBF:
7597 akron1 1814
            OutByte2(0DEH, 0E9H)  // fsubp st1, st
1815
 
7693 akron1 1816
        |IL.opSUBFI:
7597 akron1 1817
            OutByte2(0DEH, 0E1H)  // fsubrp st1, st
1818
 
7693 akron1 1819
        |IL.opMULF:
7597 akron1 1820
            OutByte2(0DEH, 0C9H)  // fmulp st1, st
1821
 
7693 akron1 1822
        |IL.opDIVF:
7597 akron1 1823
            OutByte2(0DEH, 0F9H)  // fdivp st1, st
1824
 
7693 akron1 1825
        |IL.opDIVFI:
7597 akron1 1826
            OutByte2(0DEH, 0F1H)  // fdivrp st1, st
1827
 
7693 akron1 1828
        |IL.opUMINF:
7597 akron1 1829
            OutByte2(0D9H, 0E0H)  // fchs
1830
 
7693 akron1 1831
        |IL.opFABS:
7597 akron1 1832
            OutByte2(0D9H, 0E1H)  // fabs
1833
 
7693 akron1 1834
        |IL.opFLT:
7597 akron1 1835
            UnOp(reg1);
1836
            push(reg1);
1837
            OutByte3(0DBH, 004H, 024H); // fild dword[esp]
1838
            pop(reg1);
1839
            drop
1840
 
7693 akron1 1841
        |IL.opFLOOR:
7597 akron1 1842
            subrc(esp, 8);
1843
            OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H);                   // fstcw word[esp+4]
1844
            OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H);                   // fstcw word[esp+6]
1845
            OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH);  // and word[esp+4], 1111001111111111b
1846
            OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H);  // or  word[esp+4], 0000010000000000b
1847
            OutByte2(0D9H, 06CH); OutByte2(024H, 004H);                         // fldcw word[esp+4]
1848
            OutByte2(0D9H, 0FCH);                                               // frndint
1849
            OutByte3(0DBH, 01CH, 024H);                                         // fistp dword[esp]
7693 akron1 1850
            pop(GetAnyReg());
7597 akron1 1851
            OutByte2(0D9H, 06CH); OutByte2(024H, 002H);                         // fldcw word[esp+2]
1852
            addrc(esp, 4)
1853
 
7693 akron1 1854
        |IL.opEQF:
7597 akron1 1855
            GetRegA;
1856
            OutByte2(0DAH, 0E9H);       // fucompp
1857
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1858
            OutByte(09EH);              // sahf
1859
            movrc(eax, 0);
1860
            OutByte2(07AH, 003H);       // jp L
1861
            setcc(sete, al)
1862
                                        // L:
1863
 
7693 akron1 1864
        |IL.opNEF:
7597 akron1 1865
            GetRegA;
1866
            OutByte2(0DAH, 0E9H);       // fucompp
1867
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1868
            OutByte(09EH);              // sahf
1869
            movrc(eax, 0);
1870
            OutByte2(07AH, 003H);       // jp L
1871
            setcc(setne, al)
1872
                                        // L:
1873
 
7693 akron1 1874
        |IL.opLTF:
7597 akron1 1875
            GetRegA;
1876
            OutByte2(0DAH, 0E9H);       // fucompp
1877
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1878
            OutByte(09EH);              // sahf
1879
            movrc(eax, 0);
1880
            OutByte2(07AH, 00EH);       // jp L
1881
            setcc(setc, al);
1882
            setcc(sete, ah);
1883
            test(eax);
1884
            setcc(sete, al);
1885
            andrc(eax, 1)
1886
                                        // L:
1887
 
7693 akron1 1888
        |IL.opGTF:
7597 akron1 1889
            GetRegA;
1890
            OutByte2(0DAH, 0E9H);       // fucompp
1891
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1892
            OutByte(09EH);              // sahf
1893
            movrc(eax, 0);
1894
            OutByte2(07AH, 00FH);       // jp L
1895
            setcc(setc, al);
1896
            setcc(sete, ah);
1897
            cmprc(eax, 1);
1898
            setcc(sete, al);
1899
            andrc(eax, 1)
1900
                                        // L:
1901
 
7693 akron1 1902
        |IL.opLEF:
7597 akron1 1903
            GetRegA;
1904
            OutByte2(0DAH, 0E9H);       // fucompp
1905
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1906
            OutByte(09EH);              // sahf
1907
            movrc(eax, 0);
1908
            OutByte2(07AH, 003H);       // jp L
1909
            setcc(setnc, al)
1910
                                        // L:
1911
 
7693 akron1 1912
        |IL.opGEF:
7597 akron1 1913
            GetRegA;
1914
            OutByte2(0DAH, 0E9H);       // fucompp
1915
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1916
            OutByte(09EH);              // sahf
1917
            movrc(eax, 0);
1918
            OutByte2(07AH, 010H);       // jp L
1919
            setcc(setc, al);
1920
            setcc(sete, ah);
1921
            OutByte2(000H, 0E0H);       // add al,ah
1922
            OutByte2(03CH, 001H);       // cmp al,1
1923
            setcc(sete, al);
1924
            andrc(eax, 1)
1925
                                        // L:
1926
 
7693 akron1 1927
        |IL.opINF:
7597 akron1 1928
            pushc(7FF00000H);
1929
            pushc(0);
1930
            OutByte3(0DDH, 004H, 024H);  // fld qword[esp]
1931
            addrc(esp, 8)
1932
 
7693 akron1 1933
        |IL.opLADR_UNPK:
7597 akron1 1934
            n := param2 * 4;
7693 akron1 1935
            reg1 := GetAnyReg();
7597 akron1 1936
            OutByte2(8DH, 45H + reg1 * 8 + long(n));  // lea reg1, dword[ebp + n]
1937
            OutIntByte(n);
1938
            BinOp(reg1, reg2);
1939
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1940
            OutByte2(0D9H, 0F4H);         // fxtract
1941
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1942
            OutByte2(0DBH, 018H + reg2);  // fistp dword[reg2]
1943
            drop;
1944
            drop
1945
 
7693 akron1 1946
        |IL.opSADR_PARAM:
7597 akron1 1947
            IF pic THEN
7693 akron1 1948
                reg1 := GetAnyReg();
7597 akron1 1949
                Pic(reg1, BIN.PICDATA, stroffs + param2);
1950
                push(reg1);
1951
                drop
1952
            ELSE
1953
                OutByte(068H);  // push _data + stroffs + param2
1954
                Reloc(BIN.RDATA, stroffs + param2)
1955
            END
1956
 
7693 akron1 1957
        |IL.opVADR_PARAM:
7597 akron1 1958
            n := param2 * 4;
1959
            OutByte2(0FFH, 75H + long(n));  // push dword[ebp + n]
1960
            OutIntByte(n)
1961
 
7693 akron1 1962
        |IL.opCONST_PARAM:
7597 akron1 1963
            pushc(param2)
1964
 
7693 akron1 1965
        |IL.opGLOAD32_PARAM:
7597 akron1 1966
            IF pic THEN
7693 akron1 1967
                reg1 := GetAnyReg();
7597 akron1 1968
                Pic(reg1, BIN.PICBSS, param2);
1969
                OutByte2(0FFH, 30H + reg1);   // push dword[reg1]
1970
                drop
1971
            ELSE
1972
                OutByte2(0FFH, 035H);  // push dword[_bss + param2]
1973
                Reloc(BIN.RBSS, param2)
1974
            END
1975
 
7693 akron1 1976
        |IL.opLLOAD32_PARAM:
7597 akron1 1977
            n := param2 * 4;
1978
            OutByte2(0FFH, 75H + long(n));  // push dword[ebp + n]
1979
            OutIntByte(n)
1980
 
7693 akron1 1981
        |IL.opLOAD32_PARAM:
7597 akron1 1982
            UnOp(reg1);
1983
            OutByte2(0FFH, 30H + reg1);  // push dword[reg1]
1984
            drop
1985
 
7693 akron1 1986
        |IL.opGADR_SAVEC:
7597 akron1 1987
            IF pic THEN
7693 akron1 1988
                reg1 := GetAnyReg();
7597 akron1 1989
                Pic(reg1, BIN.PICBSS, param1);
1990
                OutByte2(0C7H, reg1);  // mov dword[reg1], param2
1991
                OutInt(param2);
1992
                drop
1993
            ELSE
7693 akron1 1994
                OutByte2(0C7H, 05H);  // mov dword[_bss + param1], param2
7597 akron1 1995
                Reloc(BIN.RBSS, param1);
1996
                OutInt(param2)
1997
            END
1998
 
7693 akron1 1999
        |IL.opLADR_SAVEC:
7597 akron1 2000
            n := param1 * 4;
2001
            OutByte2(0C7H, 45H + long(n));  // mov dword[ebp + n], param2
2002
            OutIntByte(n);
2003
            OutInt(param2)
2004
 
7693 akron1 2005
        |IL.opLADR_SAVE:
7597 akron1 2006
            n := param2 * 4;
2007
            UnOp(reg1);
2008
            OutByte2(89H, 45H + reg1 * 8 + long(n));  // mov dword[ebp + n], reg1
2009
            OutIntByte(n);
2010
            drop
2011
 
7693 akron1 2012
        |IL.opLADR_INCC:
7597 akron1 2013
            n := param1 * 4;
7693 akron1 2014
            IF ABS(param2) = 1 THEN
2015
                OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n));  // inc/dec dword[ebp + n]
2016
                OutIntByte(n)
2017
            ELSE
2018
                OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2
2019
                OutIntByte(n);
2020
                OutIntByte(param2)
2021
            END
7597 akron1 2022
 
7693 akron1 2023
        |IL.opLADR_INCCB, IL.opLADR_DECCB:
7597 akron1 2024
            n := param1 * 4;
7693 akron1 2025
            IF param2 = 1 THEN
2026
                OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n));  // inc/dec byte[ebp + n]
2027
                OutIntByte(n)
2028
            ELSE
2029
                OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); // add/sub byte[ebp + n], param2
2030
                OutIntByte(n);
2031
                OutByte(param2 MOD 256)
2032
            END
7597 akron1 2033
 
7693 akron1 2034
        |IL.opLADR_INC, IL.opLADR_DEC:
7597 akron1 2035
            n := param2 * 4;
2036
            UnOp(reg1);
7693 akron1 2037
            OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1
7597 akron1 2038
            OutIntByte(n);
2039
            drop
2040
 
7693 akron1 2041
        |IL.opLADR_INCB, IL.opLADR_DECB:
7597 akron1 2042
            n := param2 * 4;
2043
            UnOp(reg1);
7693 akron1 2044
            OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1
7597 akron1 2045
            OutIntByte(n);
2046
            drop
2047
 
7693 akron1 2048
        |IL.opLADR_INCL, IL.opLADR_EXCL:
7597 akron1 2049
            n := param2 * 4;
2050
            UnOp(reg1);
2051
            cmprc(reg1, 32);
2052
            label := NewLabel();
2053
            jcc(jnb, label);
7693 akron1 2054
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1
7597 akron1 2055
            OutIntByte(n);
2056
            SetLabel(label);
2057
            drop
2058
 
7693 akron1 2059
        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
7597 akron1 2060
            n := param1 * 4;
7693 akron1 2061
            OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2
7597 akron1 2062
            OutIntByte(n);
2063
            OutByte(param2)
2064
 
7693 akron1 2065
        |IL.opLOOP, IL.opENDLOOP:
7597 akron1 2066
 
6613 leency 2067
        END;
7597 akron1 2068
 
2069
        cmd := cmd.next(COMMAND)
6613 leency 2070
    END;
2071
 
7597 akron1 2072
    ASSERT(R.pushed = 0);
2073
    ASSERT(R.top = -1)
6613 leency 2074
 
7597 akron1 2075
END translate;
6613 leency 2076
 
2077
 
7693 akron1 2078
PROCEDURE prolog (code: IL.CODES; pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER);
7597 akron1 2079
VAR
7693 akron1 2080
    reg1, entry, dcount: INTEGER;
6613 leency 2081
 
7597 akron1 2082
BEGIN
6613 leency 2083
 
7597 akron1 2084
    entry := NewLabel();
2085
    SetLabel(entry);
6613 leency 2086
 
7597 akron1 2087
    IF target = mConst.Target_iDLL THEN
2088
        push(ebp);
2089
        mov(ebp, esp);
2090
        OutByte3(0FFH, 75H, 16);  // push dword[ebp+16]
2091
        OutByte3(0FFH, 75H, 12);  // push dword[ebp+12]
2092
        OutByte3(0FFH, 75H, 8);   // push dword[ebp+8]
7693 akron1 2093
        CallRTL(pic, IL._dllentry);
7597 akron1 2094
        test(eax);
2095
        jcc(je, dllret)
2096
    ELSIF target = mConst.Target_iObject THEN
2097
        SetLabel(dllinit)
2098
    END;
6613 leency 2099
 
7597 akron1 2100
    IF target = mConst.Target_iKolibri THEN
7693 akron1 2101
        reg1 := GetAnyReg();
7597 akron1 2102
        Pic(reg1, BIN.IMPTAB, 0);
2103
        push(reg1);    // push IMPORT
2104
        drop
2105
    ELSIF target = mConst.Target_iObject THEN
2106
        OutByte(68H);  // push IMPORT
2107
        Reloc(BIN.IMPTAB, 0)
2108
    ELSIF target = mConst.Target_iELF32 THEN
2109
        push(esp)
2110
    ELSE
2111
        pushc(0)
7667 akron1 2112
    END;
2113
 
7597 akron1 2114
    IF pic THEN
7693 akron1 2115
        reg1 := GetAnyReg();
7597 akron1 2116
        Pic(reg1, BIN.PICCODE, entry);
2117
        push(reg1);     // push CODE
2118
        drop
2119
    ELSE
2120
        OutByte(68H);  // push CODE
2121
        Reloc(BIN.RCODE, entry)
2122
    END;
6613 leency 2123
 
7597 akron1 2124
    IF pic THEN
7693 akron1 2125
        reg1 := GetAnyReg();
7597 akron1 2126
        Pic(reg1, BIN.PICDATA, 0);
2127
        push(reg1);    // push _data
2128
        drop
2129
    ELSE
2130
        OutByte(68H);  // push _data
2131
        Reloc(BIN.RDATA, 0)
2132
    END;
6613 leency 2133
 
7597 akron1 2134
    dcount := CHL.Length(code.data);
6613 leency 2135
 
7597 akron1 2136
    pushc(tcount);
6613 leency 2137
 
7597 akron1 2138
    IF pic THEN
7693 akron1 2139
        reg1 := GetAnyReg();
7597 akron1 2140
        Pic(reg1, BIN.PICDATA, tcount * 4 + dcount);
2141
        push(reg1);    // push _data + tcount * 4 + dcount
2142
        drop
2143
    ELSE
2144
        OutByte(68H);  // push _data
2145
        Reloc(BIN.RDATA, tcount * 4 + dcount)
2146
    END;
6613 leency 2147
 
7693 akron1 2148
    CallRTL(pic, IL._init)
7597 akron1 2149
END prolog;
6613 leency 2150
 
2151
 
7693 akron1 2152
PROCEDURE epilog (code: IL.CODES; pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER);
7597 akron1 2153
VAR
7693 akron1 2154
    exp:  IL.EXPORT_PROC;
7597 akron1 2155
    path, name, ext: PATHS.PATH;
6613 leency 2156
 
7693 akron1 2157
    dcount, i: INTEGER;
6613 leency 2158
 
7597 akron1 2159
 
2160
    PROCEDURE import (imp: LISTS.LIST);
2161
    VAR
7693 akron1 2162
        lib:  IL.IMPORT_LIB;
2163
        proc: IL.IMPORT_PROC;
7597 akron1 2164
 
2165
    BEGIN
2166
 
7693 akron1 2167
        lib := imp.first(IL.IMPORT_LIB);
7597 akron1 2168
        WHILE lib # NIL DO
2169
            BIN.Import(program, lib.name, 0);
7693 akron1 2170
            proc := lib.procs.first(IL.IMPORT_PROC);
7597 akron1 2171
            WHILE proc # NIL DO
2172
                BIN.Import(program, proc.name, proc.label);
7693 akron1 2173
                proc := proc.next(IL.IMPORT_PROC)
7597 akron1 2174
            END;
7693 akron1 2175
            lib := lib.next(IL.IMPORT_LIB)
7597 akron1 2176
        END
2177
 
2178
    END import;
2179
 
2180
 
6613 leency 2181
BEGIN
2182
 
7597 akron1 2183
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN
2184
        pushc(0);
7693 akron1 2185
        CallRTL(pic, IL._exit);
7597 akron1 2186
    ELSIF target = mConst.Target_iDLL THEN
2187
        SetLabel(dllret);
2188
        movrc(eax, 1);
2189
        OutByte(0C9H); // leave
2190
        OutByte3(0C2H, 0CH, 0) // ret 12
2191
    ELSIF target = mConst.Target_iObject THEN
2192
        movrc(eax, 1);
2193
        OutByte(0C3H)  // ret
7693 akron1 2194
    ELSIF target = mConst.Target_iELFSO32 THEN
2195
        OutByte(0C3H);  // ret
2196
        SetLabel(sofinit);
2197
        CallRTL(pic, IL._sofinit);
2198
        OutByte(0C3H)   // ret
7597 akron1 2199
    END;
6613 leency 2200
 
7597 akron1 2201
    fixup;
2202
 
2203
    dcount := CHL.Length(code.data);
2204
 
2205
    FOR i := 0 TO tcount - 1 DO
2206
        BIN.PutData32LE(program, CHL.GetInt(code.types, i))
6613 leency 2207
    END;
2208
 
7597 akron1 2209
    FOR i := 0 TO dcount - 1 DO
2210
        BIN.PutData(program, CHL.GetByte(code.data, i))
6613 leency 2211
    END;
2212
 
7597 akron1 2213
    program.modname := CHL.Length(program.data);
6613 leency 2214
 
7597 akron1 2215
    PATHS.split(modname, path, name, ext);
2216
    BIN.PutDataStr(program, name);
2217
    BIN.PutDataStr(program, ext);
2218
    BIN.PutData(program, 0);
6613 leency 2219
 
7597 akron1 2220
    IF target = mConst.Target_iObject THEN
2221
        BIN.Export(program, "lib_init", dllinit);
2222
    END;
6613 leency 2223
 
7693 akron1 2224
    exp := code.export.first(IL.EXPORT_PROC);
7597 akron1 2225
    WHILE exp # NIL DO
2226
        BIN.Export(program, exp.name, exp.label);
7693 akron1 2227
        exp := exp.next(IL.EXPORT_PROC)
6613 leency 2228
    END;
2229
 
7597 akron1 2230
    import(code.import);
6613 leency 2231
 
7693 akron1 2232
    code.bss := MAX(code.bss, MAX(code.dmin - CHL.Length(code.data), 4));
6613 leency 2233
 
7693 akron1 2234
    BIN.SetParams(program, code.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536));
7597 akron1 2235
 
2236
END epilog;
2237
 
2238
 
7693 akron1 2239
PROCEDURE CodeGen* (code: IL.CODES; outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
7597 akron1 2240
VAR
7693 akron1 2241
    dllret, dllinit, sofinit: INTEGER;
2242
    opt: PROG.OPTIONS;
7597 akron1 2243
 
6613 leency 2244
BEGIN
7693 akron1 2245
    tcount := CHL.Length(code.types);
6613 leency 2246
 
7693 akron1 2247
    opt := options;
7597 akron1 2248
    CodeList := LISTS.create(NIL);
2249
 
2250
    program := BIN.create(code.lcount);
2251
 
2252
    dllinit := NewLabel();
2253
    dllret  := NewLabel();
7693 akron1 2254
    sofinit := NewLabel();
7597 akron1 2255
 
2256
    IF target = mConst.Target_iObject THEN
7693 akron1 2257
        opt.pic := FALSE
6613 leency 2258
    END;
7597 akron1 2259
 
7693 akron1 2260
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
2261
        opt.pic := TRUE
7597 akron1 2262
    END;
2263
 
7693 akron1 2264
    REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {});
7597 akron1 2265
 
7693 akron1 2266
    prolog(code, opt.pic, target, opt.stack, dllinit, dllret);
2267
    translate(code, opt.pic, tcount * 4);
2268
    epilog(code, opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit);
7597 akron1 2269
 
2270
    BIN.fixup(program);
2271
 
2272
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN
7693 akron1 2273
        PE32.write(program, outname, opt.base, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE)
7597 akron1 2274
    ELSIF target = mConst.Target_iKolibri THEN
2275
        KOS.write(program, outname)
2276
    ELSIF target = mConst.Target_iObject THEN
7693 akron1 2277
        MSCOFF.write(program, outname, opt.version)
2278
    ELSIF target IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
2279
        ELF.write(program, outname, sofinit, target = mConst.Target_iELFSO32, FALSE)
6613 leency 2280
    END
2281
 
7597 akron1 2282
END CodeGen;
7209 akron1 2283
 
7597 akron1 2284
 
2285
PROCEDURE SetProgram* (prog: BIN.PROGRAM);
7209 akron1 2286
BEGIN
7597 akron1 2287
    program := prog;
2288
    CodeList := LISTS.create(NIL)
2289
END SetProgram;
2290
 
2291
 
6613 leency 2292
END X86.