Subversion Repositories Kolibri OS

Rev

Rev 7693 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
7696 akron1 1
(*
7597 akron1 2
    BSD 2-Clause License
6613 leency 3
 
7696 akron1 4
    Copyright (c) 2018-2019, Anton Krotov
7597 akron1 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
 
7696 akron1 576
PROCEDURE translate (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
7696 akron1 589
    cmd := IL.codes.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);
7696 akron1 1189
                push(reg1);
7597 akron1 1190
                push(reg2);
1191
                pushc(8);
7693 akron1 1192
                CallRTL(pic, IL._move)
7597 akron1 1193
 
1194
            END
1195
 
7693 akron1 1196
        |IL.opSAVES:
7696 akron1 1197
            UnOp(reg2);
1198
            REG.PushAll_1(R);
7597 akron1 1199
 
1200
            IF pic THEN
7696 akron1 1201
                reg1 := GetAnyReg();
7597 akron1 1202
                Pic(reg1, BIN.PICDATA, stroffs + param2);
7696 akron1 1203
                push(reg1);
1204
                drop
7597 akron1 1205
            ELSE
1206
                OutByte(068H);  // push _data + stroffs + param2
1207
                Reloc(BIN.RDATA, stroffs + param2);
1208
            END;
1209
 
7696 akron1 1210
            push(reg2);
1211
            drop;
7597 akron1 1212
            pushc(param1);
7693 akron1 1213
            CallRTL(pic, IL._move)
7597 akron1 1214
 
7693 akron1 1215
        |IL.opCHKBYTE:
7597 akron1 1216
            BinOp(reg1, reg2);
1217
            cmprc(reg1, 256);
1218
            jcc(jb, param1)
1219
 
7693 akron1 1220
        |IL.opCHKIDX:
7597 akron1 1221
            UnOp(reg1);
1222
            cmprc(reg1, param2);
1223
            jcc(jb, param1)
1224
 
7693 akron1 1225
        |IL.opCHKIDX2:
7597 akron1 1226
            BinOp(reg1, reg2);
1227
            IF param2 # -1 THEN
1228
                cmprr(reg2, reg1);
1229
                mov(reg1, reg2);
1230
                drop;
1231
                jcc(jb, param1)
1232
            ELSE
1233
                INCL(R.regs, reg1);
1234
                DEC(R.top);
1235
                R.stk[R.top] := reg2
1236
            END
1237
 
7693 akron1 1238
        |IL.opLEN:
7597 akron1 1239
            n := param2;
1240
            UnOp(reg1);
1241
            drop;
1242
            EXCL(R.regs, reg1);
1243
 
1244
            WHILE n > 0 DO
1245
                UnOp(reg2);
1246
                drop;
1247
                DEC(n)
1248
            END;
1249
 
1250
            INCL(R.regs, reg1);
1251
            ASSERT(REG.GetReg(R, reg1))
1252
 
7693 akron1 1253
        |IL.opINCC:
7597 akron1 1254
            UnOp(reg1);
7693 akron1 1255
            OutByte2(81H + short(param2), reg1); OutIntByte(param2); // add dword[reg1], param2
7597 akron1 1256
            drop
1257
 
7693 akron1 1258
        |IL.opINC, IL.opDEC:
7597 akron1 1259
            BinOp(reg1, reg2);
7693 akron1 1260
            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg1 * 8 + reg2); // add/sub dword[reg2], reg1
7597 akron1 1261
            drop;
1262
            drop
1263
 
7693 akron1 1264
        |IL.opINCCB, IL.opDECCB:
7597 akron1 1265
            UnOp(reg1);
7693 akron1 1266
            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1, Byte(param2)); // add/sub byte[reg1], n
7597 akron1 1267
            drop
1268
 
7693 akron1 1269
        |IL.opINCB, IL.opDECB:
7597 akron1 1270
            BinOp(reg1, reg2);
7693 akron1 1271
            OutByte2(28H * ORD(opcode = IL.opDECB), reg1 * 8 + reg2); // add/sub byte[reg2], reg1
7597 akron1 1272
            drop;
1273
            drop
1274
 
7693 akron1 1275
        |IL.opMULS:
7597 akron1 1276
            BinOp(reg1, reg2);
1277
            OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2
1278
            drop
1279
 
7693 akron1 1280
        |IL.opMULSC:
7597 akron1 1281
            UnOp(reg1);
1282
            andrc(reg1, param2)
1283
 
7693 akron1 1284
        |IL.opDIVS:
7597 akron1 1285
            BinOp(reg1, reg2);
7667 akron1 1286
            xor(reg1, reg2);
7597 akron1 1287
            drop
1288
 
7693 akron1 1289
        |IL.opDIVSC:
7597 akron1 1290
            UnOp(reg1);
1291
            OutByte2(81H + short(param2), 0F0H + reg1);  // xor reg1, n
1292
            OutIntByte(param2)
1293
 
7693 akron1 1294
        |IL.opADDS:
7597 akron1 1295
            BinOp(reg1, reg2);
1296
            OutByte2(9H, 0C0H + reg2 * 8 + reg1); // or reg1, reg2
1297
            drop
1298
 
7693 akron1 1299
        |IL.opSUBS:
7597 akron1 1300
            BinOp(reg1, reg2);
1301
            not(reg2);
1302
            OutByte2(21H, 0C0H + reg2 * 8 + reg1); // and reg1, reg2
1303
            drop
1304
 
7693 akron1 1305
        |IL.opADDSL, IL.opADDSR:
7597 akron1 1306
            UnOp(reg1);
1307
            orrc(reg1, param2)
1308
 
7693 akron1 1309
        |IL.opSUBSL:
7597 akron1 1310
            UnOp(reg1);
1311
            not(reg1);
1312
            andrc(reg1, param2)
1313
 
7693 akron1 1314
        |IL.opSUBSR:
7597 akron1 1315
            UnOp(reg1);
7693 akron1 1316
            andrc(reg1, ORD(-BITS(param2)))
7597 akron1 1317
 
7693 akron1 1318
        |IL.opUMINS:
7597 akron1 1319
            UnOp(reg1);
1320
            not(reg1)
1321
 
7693 akron1 1322
        |IL.opLENGTH:
7597 akron1 1323
            PushAll(2);
7693 akron1 1324
            CallRTL(pic, IL._length);
7597 akron1 1325
            GetRegA
1326
 
7693 akron1 1327
        |IL.opLENGTHW:
7597 akron1 1328
            PushAll(2);
7693 akron1 1329
            CallRTL(pic, IL._lengthw);
7597 akron1 1330
            GetRegA
1331
 
7693 akron1 1332
        |IL.opCHR:
7597 akron1 1333
            UnOp(reg1);
1334
            andrc(reg1, 255)
1335
 
7693 akron1 1336
        |IL.opWCHR:
7597 akron1 1337
            UnOp(reg1);
1338
            andrc(reg1, 65535)
1339
 
7693 akron1 1340
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
7597 akron1 1341
            UnOp(reg1);
1342
            IF reg1 # ecx THEN
1343
                ASSERT(REG.GetReg(R, ecx));
1344
                ASSERT(REG.Exchange(R, reg1, ecx));
1345
                drop
1346
            END;
1347
 
1348
            BinOp(reg1, reg2);
1349
            ASSERT(reg2 = ecx);
1350
            OutByte(0D3H);
7693 akron1 1351
            shift(opcode, reg1); // shift reg1, cl
7597 akron1 1352
            drop
1353
 
7693 akron1 1354
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
7597 akron1 1355
            UnOp(reg1);
1356
            IF reg1 # ecx THEN
1357
                ASSERT(REG.GetReg(R, ecx));
1358
                ASSERT(REG.Exchange(R, reg1, ecx));
1359
                drop
1360
            END;
1361
 
7693 akron1 1362
            reg1 := GetAnyReg();
7597 akron1 1363
            movrc(reg1, param2);
1364
            BinOp(reg1, reg2);
1365
            ASSERT(reg1 = ecx);
1366
            OutByte(0D3H);
7693 akron1 1367
            shift(opcode, reg2); // shift reg2, cl
7597 akron1 1368
            drop;
1369
            drop;
1370
            ASSERT(REG.GetReg(R, reg2))
1371
 
7693 akron1 1372
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
7597 akron1 1373
            UnOp(reg1);
7693 akron1 1374
            n := param2 MOD 32;
7597 akron1 1375
            IF n # 1 THEN
1376
                OutByte(0C1H)
1377
            ELSE
1378
                OutByte(0D1H)
1379
            END;
7693 akron1 1380
            shift(opcode, reg1); // shift reg1, n
7597 akron1 1381
            IF n # 1 THEN
1382
                OutByte(n)
1383
            END
1384
 
7693 akron1 1385
        |IL.opMIN:
7597 akron1 1386
            BinOp(reg1, reg2);
1387
            cmprr(reg1, reg2);
1388
            OutByte2(07EH, 002H);  // jle @f
1389
            mov(reg1, reg2);       // mov reg1, reg2
1390
                                   // @@:
1391
            drop
1392
 
7693 akron1 1393
        |IL.opMAX:
7597 akron1 1394
            BinOp(reg1, reg2);
1395
            cmprr(reg1, reg2);
1396
            OutByte2(07DH, 002H);  // jge @f
1397
            mov(reg1, reg2);       // mov reg1, reg2
1398
                                   // @@:
1399
            drop
1400
 
7693 akron1 1401
        |IL.opMINC:
7597 akron1 1402
            UnOp(reg1);
1403
            cmprc(reg1, param2);
1404
            OutByte2(07EH, 005H);    // jle @f
7693 akron1 1405
            movrc(reg1, param2)      // mov reg1, param2
7597 akron1 1406
                                     // @@:
1407
 
7693 akron1 1408
        |IL.opMAXC:
7597 akron1 1409
            UnOp(reg1);
1410
            cmprc(reg1, param2);
1411
            OutByte2(07DH, 005H);    // jge @f
7693 akron1 1412
            movrc(reg1, param2)      // mov reg1, param2
7597 akron1 1413
                                     // @@:
1414
 
7693 akron1 1415
        |IL.opIN:
7597 akron1 1416
            label := NewLabel();
1417
            BinOp(reg1, reg2);
1418
            cmprc(reg1, 32);
1419
            OutByte2(72H, 4); // jb L
7667 akron1 1420
            xor(reg1, reg1);
7597 akron1 1421
            jmp(label);
1422
            //L:
1423
            OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1
1424
            setcc(setc, reg1);
1425
            andrc(reg1, 1);
1426
            SetLabel(label);
1427
            drop
1428
 
7693 akron1 1429
        |IL.opINR:
7597 akron1 1430
            label := NewLabel();
1431
            UnOp(reg1);
7693 akron1 1432
            reg2 := GetAnyReg();
7597 akron1 1433
            cmprc(reg1, 32);
1434
            OutByte2(72H, 4); // jb L
7667 akron1 1435
            xor(reg1, reg1);
7597 akron1 1436
            jmp(label);
1437
            //L:
1438
            movrc(reg2, param2);
1439
            OutByte3(0FH, 0A3H, 0C0H + reg2 + 8 * reg1); // bt reg2, reg1
1440
            setcc(setc, reg1);
1441
            andrc(reg1, 1);
1442
            SetLabel(label);
1443
            drop
1444
 
7693 akron1 1445
        |IL.opINL:
7597 akron1 1446
            UnOp(reg1);
1447
            OutByte3(0FH, 0BAH, 0E0H + reg1); OutByte(param2); // bt reg1, param2
1448
            setcc(setc, reg1);
1449
            andrc(reg1, 1)
1450
 
7693 akron1 1451
        |IL.opRSET:
7597 akron1 1452
            PushAll(2);
7693 akron1 1453
            CallRTL(pic, IL._set);
7597 akron1 1454
            GetRegA
1455
 
7693 akron1 1456
        |IL.opRSETR:
7597 akron1 1457
            PushAll(1);
1458
            pushc(param2);
7693 akron1 1459
            CallRTL(pic, IL._set);
7597 akron1 1460
            GetRegA
1461
 
7693 akron1 1462
        |IL.opRSETL:
7696 akron1 1463
            UnOp(reg1);
1464
            REG.PushAll_1(R);
7597 akron1 1465
            pushc(param2);
7696 akron1 1466
            push(reg1);
1467
            drop;
1468
            CallRTL(pic, IL._set);
7597 akron1 1469
            GetRegA
1470
 
7693 akron1 1471
        |IL.opRSET1:
7597 akron1 1472
            PushAll(1);
7696 akron1 1473
            CallRTL(pic, IL._set1);
7597 akron1 1474
            GetRegA
1475
 
7693 akron1 1476
        |IL.opINCL, IL.opEXCL:
7597 akron1 1477
            BinOp(reg1, reg2);
1478
            cmprc(reg1, 32);
1479
            OutByte2(73H, 03H); // jnb L
1480
            OutByte(0FH);
7693 akron1 1481
            IF opcode = IL.opINCL THEN
7597 akron1 1482
                OutByte(0ABH) // bts dword[reg2], reg1
1483
            ELSE
1484
                OutByte(0B3H) // btr dword[reg2], reg1
1485
            END;
1486
            OutByte(reg2 + 8 * reg1);
1487
            //L:
1488
            drop;
1489
            drop
1490
 
7693 akron1 1491
        |IL.opINCLC:
7597 akron1 1492
            UnOp(reg1);
1493
            OutByte3(0FH, 0BAH, 28H + reg1); OutByte(param2); //bts dword[reg1],param2
1494
            drop
1495
 
7693 akron1 1496
        |IL.opEXCLC:
7597 akron1 1497
            UnOp(reg1);
1498
            OutByte3(0FH, 0BAH, 30H + reg1); OutByte(param2); //btr dword[reg1],param2
1499
            drop
1500
 
7693 akron1 1501
        |IL.opDIV:
7597 akron1 1502
            PushAll(2);
7696 akron1 1503
            CallRTL(pic, IL._divmod);
7597 akron1 1504
            GetRegA
1505
 
7693 akron1 1506
        |IL.opDIVR:
7597 akron1 1507
            a := param2;
1508
            IF a > 1 THEN
7693 akron1 1509
                n := UTILS.Log2(a)
7597 akron1 1510
            ELSIF a < -1 THEN
7693 akron1 1511
                n := UTILS.Log2(-a)
7597 akron1 1512
            ELSE
1513
                n := -1
1514
            END;
1515
 
1516
            IF a = 1 THEN
1517
 
1518
            ELSIF a = -1 THEN
1519
                UnOp(reg1);
1520
                neg(reg1)
1521
            ELSE
1522
                IF n > 0 THEN
1523
                    UnOp(reg1);
1524
 
1525
                    IF a < 0 THEN
7693 akron1 1526
                        reg2 := GetAnyReg();
7597 akron1 1527
                        mov(reg2, reg1);
1528
                        IF n # 1 THEN
1529
                            OutByte3(0C1H, 0F8H + reg1, n)     // sar reg1, n
1530
                        ELSE
1531
                            OutByte2(0D1H, 0F8H + reg1)        // sar reg1, 1
1532
                        END;
1533
                        OutByte2(29H, 0C0H + reg2 * 8 + reg1); // sub reg1, reg2
1534
                        drop
1535
                    ELSE
1536
                        IF n # 1 THEN
1537
                            OutByte3(0C1H, 0F8H + reg1, n)     // sar reg1, n
1538
                        ELSE
1539
                            OutByte2(0D1H, 0F8H + reg1)        // sar reg1, 1
1540
                        END
1541
                    END
1542
 
1543
                ELSE
1544
                    PushAll(1);
1545
                    pushc(param2);
7696 akron1 1546
                    CallRTL(pic, IL._divmod);
7597 akron1 1547
                    GetRegA
1548
                END
1549
            END
1550
 
7693 akron1 1551
        |IL.opDIVL:
7696 akron1 1552
            UnOp(reg1);
1553
            REG.PushAll_1(R);
7597 akron1 1554
            pushc(param2);
7696 akron1 1555
            push(reg1);
1556
            drop;
1557
            CallRTL(pic, IL._divmod);
7597 akron1 1558
            GetRegA
1559
 
7693 akron1 1560
        |IL.opMOD:
7597 akron1 1561
            PushAll(2);
7696 akron1 1562
            CallRTL(pic, IL._divmod);
1563
            mov(eax, edx);
7597 akron1 1564
            GetRegA
1565
 
7693 akron1 1566
        |IL.opMODR:
7597 akron1 1567
            a := param2;
1568
            IF a > 1 THEN
7693 akron1 1569
                n := UTILS.Log2(a)
7597 akron1 1570
            ELSIF a < -1 THEN
7693 akron1 1571
                n := UTILS.Log2(-a)
7597 akron1 1572
            ELSE
1573
                n := -1
1574
            END;
1575
 
1576
            IF ABS(a) = 1 THEN
1577
                UnOp(reg1);
7667 akron1 1578
                xor(reg1, reg1)
7597 akron1 1579
            ELSE
1580
                IF n > 0 THEN
1581
                    UnOp(reg1);
1582
                    andrc(reg1, ABS(a) - 1);
1583
 
1584
                    IF a < 0 THEN
1585
                        test(reg1);
1586
                        OutByte(74H);      // je @f
1587
                        IF isByte(a) THEN
1588
                            OutByte(3)
1589
                        ELSE
1590
                            OutByte(6)
1591
                        END;
1592
                        addrc(reg1, a)
1593
                                           // @@:
1594
                    END
1595
 
1596
                ELSE
1597
                    PushAll(1);
1598
                    pushc(param2);
7696 akron1 1599
                    CallRTL(pic, IL._divmod);
1600
                    mov(eax, edx);
7597 akron1 1601
                    GetRegA
1602
                END
1603
            END
1604
 
7693 akron1 1605
        |IL.opMODL:
7696 akron1 1606
            UnOp(reg1);
1607
            REG.PushAll_1(R);
7597 akron1 1608
            pushc(param2);
7696 akron1 1609
            push(reg1);
1610
            drop;
1611
            CallRTL(pic, IL._divmod);
1612
            mov(eax, edx);
7597 akron1 1613
            GetRegA
1614
 
7693 akron1 1615
        |IL.opERR:
1616
            CallRTL(pic, IL._error)
7597 akron1 1617
 
7693 akron1 1618
        |IL.opABS:
7597 akron1 1619
            UnOp(reg1);
1620
            test(reg1);
1621
            OutByte2(07DH, 002H); // jge @f
7693 akron1 1622
            neg(reg1)             // neg reg1
7597 akron1 1623
                                  // @@:
1624
 
7693 akron1 1625
        |IL.opCOPY:
7597 akron1 1626
            PushAll(2);
1627
            pushc(param2);
7696 akron1 1628
            CallRTL(pic, IL._move)
7597 akron1 1629
 
7693 akron1 1630
        |IL.opMOVE:
7597 akron1 1631
            PushAll(3);
7696 akron1 1632
            CallRTL(pic, IL._move)
7597 akron1 1633
 
7693 akron1 1634
        |IL.opCOPYA:
7597 akron1 1635
            PushAll(4);
1636
            pushc(param2);
7693 akron1 1637
            CallRTL(pic, IL._arrcpy);
7597 akron1 1638
            GetRegA
1639
 
7693 akron1 1640
        |IL.opCOPYS:
7597 akron1 1641
            PushAll(4);
1642
            pushc(param2);
7693 akron1 1643
            CallRTL(pic, IL._strcpy)
7597 akron1 1644
 
7693 akron1 1645
        |IL.opROT:
7597 akron1 1646
            PushAll(0);
1647
            push(esp);
1648
            pushc(param2);
7693 akron1 1649
            CallRTL(pic, IL._rot)
7597 akron1 1650
 
7693 akron1 1651
        |IL.opNEW:
7597 akron1 1652
            PushAll(1);
1653
            n := param2 + 8;
7693 akron1 1654
            ASSERT(UTILS.Align(n, 32));
7597 akron1 1655
            pushc(n);
1656
            pushc(param1);
7693 akron1 1657
            CallRTL(pic, IL._new)
7597 akron1 1658
 
7693 akron1 1659
        |IL.opDISP:
7597 akron1 1660
            PushAll(1);
7693 akron1 1661
            CallRTL(pic, IL._dispose)
7597 akron1 1662
 
7693 akron1 1663
        |IL.opEQS .. IL.opGES:
7597 akron1 1664
            PushAll(4);
7693 akron1 1665
            pushc(opcode - IL.opEQS);
1666
            CallRTL(pic, IL._strcmp);
7597 akron1 1667
            GetRegA
1668
 
7693 akron1 1669
        |IL.opEQSW .. IL.opGESW:
7597 akron1 1670
            PushAll(4);
7693 akron1 1671
            pushc(opcode - IL.opEQSW);
1672
            CallRTL(pic, IL._strcmpw);
7597 akron1 1673
            GetRegA
1674
 
7693 akron1 1675
        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
7597 akron1 1676
            UnOp(reg1);
7693 akron1 1677
            CASE opcode OF
1678
            |IL.opEQP, IL.opNEP:
7597 akron1 1679
                IF pic THEN
7693 akron1 1680
                    reg2 := GetAnyReg();
7597 akron1 1681
                    Pic(reg2, BIN.PICCODE, param1);
1682
                    cmprr(reg1, reg2);
1683
                    drop
1684
                ELSE
1685
                    OutByte2(081H, 0F8H + reg1);  // cmp reg1, L
1686
                    Reloc(BIN.RCODE, param1)
1687
                END
1688
 
7693 akron1 1689
            |IL.opEQIP, IL.opNEIP:
7597 akron1 1690
                IF pic THEN
7693 akron1 1691
                    reg2 := GetAnyReg();
7597 akron1 1692
                    Pic(reg2, BIN.PICIMP, param1);
1693
                    OutByte2(03BH, reg1 * 8 + reg2);  //cmp reg1, dword [reg2]
1694
                    drop
1695
                ELSE
1696
                    OutByte2(3BH, 05H + reg1 * 8);    // cmp reg1, dword[L]
1697
                    Reloc(BIN.RIMP, param1)
1698
                END
1699
 
1700
            END;
1701
            drop;
7693 akron1 1702
            reg1 := GetAnyReg();
7597 akron1 1703
 
7693 akron1 1704
            CASE opcode OF
1705
            |IL.opEQP, IL.opEQIP: setcc(sete,  reg1)
1706
            |IL.opNEP, IL.opNEIP: setcc(setne, reg1)
7597 akron1 1707
            END;
1708
 
1709
            andrc(reg1, 1)
1710
 
7693 akron1 1711
        |IL.opPUSHT:
7597 akron1 1712
            UnOp(reg1);
7693 akron1 1713
            reg2 := GetAnyReg();
7597 akron1 1714
            OutByte3(8BH, 40H + reg2 * 8 + reg1, 0FCH)  // mov reg2, dword[reg1 - 4]
1715
 
7693 akron1 1716
        |IL.opISREC:
7597 akron1 1717
            PushAll(2);
7693 akron1 1718
            pushc(param2 * tcount);
1719
            CallRTL(pic, IL._isrec);
7597 akron1 1720
            GetRegA
1721
 
7693 akron1 1722
        |IL.opIS:
7597 akron1 1723
            PushAll(1);
7693 akron1 1724
            pushc(param2 * tcount);
1725
            CallRTL(pic, IL._is);
7597 akron1 1726
            GetRegA
1727
 
7693 akron1 1728
        |IL.opTYPEGR:
7597 akron1 1729
            PushAll(1);
7693 akron1 1730
            pushc(param2 * tcount);
1731
            CallRTL(pic, IL._guardrec);
7597 akron1 1732
            GetRegA
1733
 
7693 akron1 1734
        |IL.opTYPEGP:
7597 akron1 1735
            UnOp(reg1);
1736
            PushAll(0);
1737
            push(reg1);
7693 akron1 1738
            pushc(param2 * tcount);
1739
            CallRTL(pic, IL._guard);
7597 akron1 1740
            GetRegA
1741
 
7693 akron1 1742
        |IL.opTYPEGD:
7597 akron1 1743
            UnOp(reg1);
1744
            PushAll(0);
1745
            OutByte3(0FFH, 070H + reg1, 0FCH);  // push dword[reg1 - 4]
7693 akron1 1746
            pushc(param2 * tcount);
1747
            CallRTL(pic, IL._guardrec);
7597 akron1 1748
            GetRegA
1749
 
7693 akron1 1750
        |IL.opCASET:
7597 akron1 1751
            push(ecx);
1752
            push(ecx);
7693 akron1 1753
            pushc(param2 * tcount);
1754
            CallRTL(pic, IL._guardrec);
7597 akron1 1755
            pop(ecx);
1756
            test(eax);
1757
            jcc(jne, param1)
1758
 
7693 akron1 1759
        |IL.opPACK:
7597 akron1 1760
            BinOp(reg1, reg2);
1761
            push(reg2);
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(reg2);
1768
            drop;
1769
            drop
1770
 
7693 akron1 1771
        |IL.opPACKC:
7597 akron1 1772
            UnOp(reg1);
1773
            pushc(param2);
1774
            OutByte3(0DBH, 004H, 024H);   // fild dword[esp]
1775
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1776
            OutByte2(0D9H, 0FDH);         // fscale
1777
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1778
            OutByte3(0DBH, 01CH, 024H);   // fistp dword[esp]
1779
            pop(reg1);
1780
            drop
1781
 
7693 akron1 1782
        |IL.opUNPK:
7597 akron1 1783
            BinOp(reg1, reg2);
1784
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1785
            OutByte2(0D9H, 0F4H);         // fxtract
1786
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1787
            OutByte2(0DBH, 018H + reg2);  // fistp dword[reg2]
1788
            drop;
1789
            drop
1790
 
7693 akron1 1791
        |IL.opPUSHF:
7597 akron1 1792
            subrc(esp, 8);
1793
            OutByte3(0DDH, 01CH, 024H)    // fstp qword[esp]
1794
 
7693 akron1 1795
        |IL.opLOADF:
7597 akron1 1796
            UnOp(reg1);
1797
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1798
            drop
1799
 
7693 akron1 1800
        |IL.opCONSTF:
7597 akron1 1801
            float := cmd.float;
1802
            IF float = 0.0 THEN
1803
                OutByte2(0D9H, 0EEH)      // fldz
1804
            ELSIF float = 1.0 THEN
1805
                OutByte2(0D9H, 0E8H)      // fld1
1806
            ELSIF float = -1.0 THEN
1807
                OutByte2(0D9H, 0E8H);     // fld1
1808
                OutByte2(0D9H, 0E0H)      // fchs
1809
            ELSE
1810
                n := UTILS.splitf(float, a, b);
1811
                pushc(b);
1812
                pushc(a);
1813
                OutByte3(0DDH, 004H, 024H); // fld qword[esp]
1814
                addrc(esp, 8)
1815
            END
1816
 
7693 akron1 1817
        |IL.opSAVEF:
7597 akron1 1818
            UnOp(reg1);
1819
            OutByte2(0DDH, 018H + reg1); // fstp qword[reg1]
1820
            drop
1821
 
7693 akron1 1822
        |IL.opADDF, IL.opADDFI:
7597 akron1 1823
            OutByte2(0DEH, 0C1H)  // faddp st1, st
1824
 
7693 akron1 1825
        |IL.opSUBF:
7597 akron1 1826
            OutByte2(0DEH, 0E9H)  // fsubp st1, st
1827
 
7693 akron1 1828
        |IL.opSUBFI:
7597 akron1 1829
            OutByte2(0DEH, 0E1H)  // fsubrp st1, st
1830
 
7693 akron1 1831
        |IL.opMULF:
7597 akron1 1832
            OutByte2(0DEH, 0C9H)  // fmulp st1, st
1833
 
7693 akron1 1834
        |IL.opDIVF:
7597 akron1 1835
            OutByte2(0DEH, 0F9H)  // fdivp st1, st
1836
 
7693 akron1 1837
        |IL.opDIVFI:
7597 akron1 1838
            OutByte2(0DEH, 0F1H)  // fdivrp st1, st
1839
 
7693 akron1 1840
        |IL.opUMINF:
7597 akron1 1841
            OutByte2(0D9H, 0E0H)  // fchs
1842
 
7693 akron1 1843
        |IL.opFABS:
7597 akron1 1844
            OutByte2(0D9H, 0E1H)  // fabs
1845
 
7693 akron1 1846
        |IL.opFLT:
7597 akron1 1847
            UnOp(reg1);
1848
            push(reg1);
1849
            OutByte3(0DBH, 004H, 024H); // fild dword[esp]
1850
            pop(reg1);
1851
            drop
1852
 
7693 akron1 1853
        |IL.opFLOOR:
7597 akron1 1854
            subrc(esp, 8);
1855
            OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 004H);                   // fstcw word[esp+4]
1856
            OutByte2(09BH, 0D9H); OutByte3(07CH, 024H, 006H);                   // fstcw word[esp+6]
1857
            OutByte2(066H, 081H); OutByte3(064H, 024H, 004H); OutWord(0F3FFH);  // and word[esp+4], 1111001111111111b
1858
            OutByte2(066H, 081H); OutByte3(04CH, 024H, 004H); OutWord(00400H);  // or  word[esp+4], 0000010000000000b
1859
            OutByte2(0D9H, 06CH); OutByte2(024H, 004H);                         // fldcw word[esp+4]
1860
            OutByte2(0D9H, 0FCH);                                               // frndint
1861
            OutByte3(0DBH, 01CH, 024H);                                         // fistp dword[esp]
7693 akron1 1862
            pop(GetAnyReg());
7597 akron1 1863
            OutByte2(0D9H, 06CH); OutByte2(024H, 002H);                         // fldcw word[esp+2]
1864
            addrc(esp, 4)
1865
 
7693 akron1 1866
        |IL.opEQF:
7597 akron1 1867
            GetRegA;
1868
            OutByte2(0DAH, 0E9H);       // fucompp
1869
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1870
            OutByte(09EH);              // sahf
1871
            movrc(eax, 0);
1872
            OutByte2(07AH, 003H);       // jp L
1873
            setcc(sete, al)
1874
                                        // L:
1875
 
7693 akron1 1876
        |IL.opNEF:
7597 akron1 1877
            GetRegA;
1878
            OutByte2(0DAH, 0E9H);       // fucompp
1879
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1880
            OutByte(09EH);              // sahf
1881
            movrc(eax, 0);
1882
            OutByte2(07AH, 003H);       // jp L
1883
            setcc(setne, al)
1884
                                        // L:
1885
 
7693 akron1 1886
        |IL.opLTF:
7597 akron1 1887
            GetRegA;
1888
            OutByte2(0DAH, 0E9H);       // fucompp
1889
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1890
            OutByte(09EH);              // sahf
1891
            movrc(eax, 0);
1892
            OutByte2(07AH, 00EH);       // jp L
1893
            setcc(setc, al);
1894
            setcc(sete, ah);
1895
            test(eax);
1896
            setcc(sete, al);
1897
            andrc(eax, 1)
1898
                                        // L:
1899
 
7693 akron1 1900
        |IL.opGTF:
7597 akron1 1901
            GetRegA;
1902
            OutByte2(0DAH, 0E9H);       // fucompp
1903
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1904
            OutByte(09EH);              // sahf
1905
            movrc(eax, 0);
1906
            OutByte2(07AH, 00FH);       // jp L
1907
            setcc(setc, al);
1908
            setcc(sete, ah);
1909
            cmprc(eax, 1);
1910
            setcc(sete, al);
1911
            andrc(eax, 1)
1912
                                        // L:
1913
 
7693 akron1 1914
        |IL.opLEF:
7597 akron1 1915
            GetRegA;
1916
            OutByte2(0DAH, 0E9H);       // fucompp
1917
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1918
            OutByte(09EH);              // sahf
1919
            movrc(eax, 0);
1920
            OutByte2(07AH, 003H);       // jp L
1921
            setcc(setnc, al)
1922
                                        // L:
1923
 
7693 akron1 1924
        |IL.opGEF:
7597 akron1 1925
            GetRegA;
1926
            OutByte2(0DAH, 0E9H);       // fucompp
1927
            OutByte3(09BH, 0DFH, 0E0H); // fstsw ax
1928
            OutByte(09EH);              // sahf
1929
            movrc(eax, 0);
1930
            OutByte2(07AH, 010H);       // jp L
1931
            setcc(setc, al);
1932
            setcc(sete, ah);
1933
            OutByte2(000H, 0E0H);       // add al,ah
1934
            OutByte2(03CH, 001H);       // cmp al,1
1935
            setcc(sete, al);
1936
            andrc(eax, 1)
1937
                                        // L:
1938
 
7693 akron1 1939
        |IL.opINF:
7597 akron1 1940
            pushc(7FF00000H);
1941
            pushc(0);
1942
            OutByte3(0DDH, 004H, 024H);  // fld qword[esp]
1943
            addrc(esp, 8)
1944
 
7693 akron1 1945
        |IL.opLADR_UNPK:
7597 akron1 1946
            n := param2 * 4;
7693 akron1 1947
            reg1 := GetAnyReg();
7597 akron1 1948
            OutByte2(8DH, 45H + reg1 * 8 + long(n));  // lea reg1, dword[ebp + n]
1949
            OutIntByte(n);
1950
            BinOp(reg1, reg2);
1951
            OutByte2(0DDH, reg1);         // fld qword[reg1]
1952
            OutByte2(0D9H, 0F4H);         // fxtract
1953
            OutByte2(0DDH, 018H + reg1);  // fstp qword[reg1]
1954
            OutByte2(0DBH, 018H + reg2);  // fistp dword[reg2]
1955
            drop;
1956
            drop
1957
 
7693 akron1 1958
        |IL.opSADR_PARAM:
7597 akron1 1959
            IF pic THEN
7693 akron1 1960
                reg1 := GetAnyReg();
7597 akron1 1961
                Pic(reg1, BIN.PICDATA, stroffs + param2);
1962
                push(reg1);
1963
                drop
1964
            ELSE
1965
                OutByte(068H);  // push _data + stroffs + param2
1966
                Reloc(BIN.RDATA, stroffs + param2)
1967
            END
1968
 
7693 akron1 1969
        |IL.opVADR_PARAM:
7597 akron1 1970
            n := param2 * 4;
1971
            OutByte2(0FFH, 75H + long(n));  // push dword[ebp + n]
1972
            OutIntByte(n)
1973
 
7693 akron1 1974
        |IL.opCONST_PARAM:
7597 akron1 1975
            pushc(param2)
1976
 
7693 akron1 1977
        |IL.opGLOAD32_PARAM:
7597 akron1 1978
            IF pic THEN
7693 akron1 1979
                reg1 := GetAnyReg();
7597 akron1 1980
                Pic(reg1, BIN.PICBSS, param2);
1981
                OutByte2(0FFH, 30H + reg1);   // push dword[reg1]
1982
                drop
1983
            ELSE
1984
                OutByte2(0FFH, 035H);  // push dword[_bss + param2]
1985
                Reloc(BIN.RBSS, param2)
1986
            END
1987
 
7693 akron1 1988
        |IL.opLLOAD32_PARAM:
7597 akron1 1989
            n := param2 * 4;
1990
            OutByte2(0FFH, 75H + long(n));  // push dword[ebp + n]
1991
            OutIntByte(n)
1992
 
7693 akron1 1993
        |IL.opLOAD32_PARAM:
7597 akron1 1994
            UnOp(reg1);
1995
            OutByte2(0FFH, 30H + reg1);  // push dword[reg1]
1996
            drop
1997
 
7693 akron1 1998
        |IL.opGADR_SAVEC:
7597 akron1 1999
            IF pic THEN
7693 akron1 2000
                reg1 := GetAnyReg();
7597 akron1 2001
                Pic(reg1, BIN.PICBSS, param1);
2002
                OutByte2(0C7H, reg1);  // mov dword[reg1], param2
2003
                OutInt(param2);
2004
                drop
2005
            ELSE
7693 akron1 2006
                OutByte2(0C7H, 05H);  // mov dword[_bss + param1], param2
7597 akron1 2007
                Reloc(BIN.RBSS, param1);
2008
                OutInt(param2)
2009
            END
2010
 
7693 akron1 2011
        |IL.opLADR_SAVEC:
7597 akron1 2012
            n := param1 * 4;
2013
            OutByte2(0C7H, 45H + long(n));  // mov dword[ebp + n], param2
2014
            OutIntByte(n);
2015
            OutInt(param2)
2016
 
7693 akron1 2017
        |IL.opLADR_SAVE:
7597 akron1 2018
            n := param2 * 4;
2019
            UnOp(reg1);
2020
            OutByte2(89H, 45H + reg1 * 8 + long(n));  // mov dword[ebp + n], reg1
2021
            OutIntByte(n);
2022
            drop
2023
 
7693 akron1 2024
        |IL.opLADR_INCC:
7597 akron1 2025
            n := param1 * 4;
7693 akron1 2026
            IF ABS(param2) = 1 THEN
2027
                OutByte2(0FFH, 45H + 8 * ORD(param2 = -1) + long(n));  // inc/dec dword[ebp + n]
2028
                OutIntByte(n)
2029
            ELSE
2030
                OutByte2(81H + short(param2), 45H + long(n)); // add dword[ebp + n], param2
2031
                OutIntByte(n);
2032
                OutIntByte(param2)
2033
            END
7597 akron1 2034
 
7693 akron1 2035
        |IL.opLADR_INCCB, IL.opLADR_DECCB:
7597 akron1 2036
            n := param1 * 4;
7693 akron1 2037
            IF param2 = 1 THEN
2038
                OutByte2(0FEH, 45H + 8 * ORD(opcode = IL.opLADR_DECCB) + long(n));  // inc/dec byte[ebp + n]
2039
                OutIntByte(n)
2040
            ELSE
2041
                OutByte2(80H, 45H + 28H * ORD(opcode = IL.opLADR_DECCB) + long(n)); // add/sub byte[ebp + n], param2
2042
                OutIntByte(n);
2043
                OutByte(param2 MOD 256)
2044
            END
7597 akron1 2045
 
7693 akron1 2046
        |IL.opLADR_INC, IL.opLADR_DEC:
7597 akron1 2047
            n := param2 * 4;
2048
            UnOp(reg1);
7693 akron1 2049
            OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + reg1 * 8); // add/sub dword[ebp + n], reg1
7597 akron1 2050
            OutIntByte(n);
2051
            drop
2052
 
7693 akron1 2053
        |IL.opLADR_INCB, IL.opLADR_DECB:
7597 akron1 2054
            n := param2 * 4;
2055
            UnOp(reg1);
7693 akron1 2056
            OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + reg1 * 8); // add/sub byte[ebp + n], reg1
7597 akron1 2057
            OutIntByte(n);
2058
            drop
2059
 
7693 akron1 2060
        |IL.opLADR_INCL, IL.opLADR_EXCL:
7597 akron1 2061
            n := param2 * 4;
2062
            UnOp(reg1);
2063
            cmprc(reg1, 32);
2064
            label := NewLabel();
2065
            jcc(jnb, label);
7693 akron1 2066
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + reg1 * 8); // bts(r) dword[ebp + n], reg1
7597 akron1 2067
            OutIntByte(n);
2068
            SetLabel(label);
2069
            drop
2070
 
7693 akron1 2071
        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
7597 akron1 2072
            n := param1 * 4;
7693 akron1 2073
            OutByte3(0FH, 0BAH, 6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC)); // bts(r) dword[ebp + n], param2
7597 akron1 2074
            OutIntByte(n);
2075
            OutByte(param2)
2076
 
7693 akron1 2077
        |IL.opLOOP, IL.opENDLOOP:
7597 akron1 2078
 
6613 leency 2079
        END;
7597 akron1 2080
 
2081
        cmd := cmd.next(COMMAND)
6613 leency 2082
    END;
2083
 
7597 akron1 2084
    ASSERT(R.pushed = 0);
2085
    ASSERT(R.top = -1)
6613 leency 2086
 
7597 akron1 2087
END translate;
6613 leency 2088
 
2089
 
7696 akron1 2090
PROCEDURE prolog (pic: BOOLEAN; target, stack, dllinit, dllret: INTEGER);
7597 akron1 2091
VAR
7696 akron1 2092
    reg1, entry, L, dcount: INTEGER;
6613 leency 2093
 
7597 akron1 2094
BEGIN
6613 leency 2095
 
7597 akron1 2096
    entry := NewLabel();
2097
    SetLabel(entry);
6613 leency 2098
 
7597 akron1 2099
    IF target = mConst.Target_iDLL THEN
2100
        push(ebp);
2101
        mov(ebp, esp);
2102
        OutByte3(0FFH, 75H, 16);  // push dword[ebp+16]
2103
        OutByte3(0FFH, 75H, 12);  // push dword[ebp+12]
2104
        OutByte3(0FFH, 75H, 8);   // push dword[ebp+8]
7693 akron1 2105
        CallRTL(pic, IL._dllentry);
7597 akron1 2106
        test(eax);
2107
        jcc(je, dllret)
2108
    ELSIF target = mConst.Target_iObject THEN
2109
        SetLabel(dllinit)
2110
    END;
6613 leency 2111
 
7597 akron1 2112
    IF target = mConst.Target_iKolibri THEN
7693 akron1 2113
        reg1 := GetAnyReg();
7597 akron1 2114
        Pic(reg1, BIN.IMPTAB, 0);
2115
        push(reg1);    // push IMPORT
2116
        drop
2117
    ELSIF target = mConst.Target_iObject THEN
2118
        OutByte(68H);  // push IMPORT
2119
        Reloc(BIN.IMPTAB, 0)
2120
    ELSIF target = mConst.Target_iELF32 THEN
2121
        push(esp)
2122
    ELSE
2123
        pushc(0)
7667 akron1 2124
    END;
2125
 
7597 akron1 2126
    IF pic THEN
7693 akron1 2127
        reg1 := GetAnyReg();
7597 akron1 2128
        Pic(reg1, BIN.PICCODE, entry);
2129
        push(reg1);     // push CODE
2130
        drop
2131
    ELSE
2132
        OutByte(68H);  // push CODE
2133
        Reloc(BIN.RCODE, entry)
2134
    END;
6613 leency 2135
 
7597 akron1 2136
    IF pic THEN
7693 akron1 2137
        reg1 := GetAnyReg();
7597 akron1 2138
        Pic(reg1, BIN.PICDATA, 0);
2139
        push(reg1);    // push _data
2140
        drop
2141
    ELSE
2142
        OutByte(68H);  // push _data
2143
        Reloc(BIN.RDATA, 0)
2144
    END;
6613 leency 2145
 
7696 akron1 2146
    dcount := CHL.Length(IL.codes.data);
6613 leency 2147
 
7597 akron1 2148
    pushc(tcount);
6613 leency 2149
 
7597 akron1 2150
    IF pic THEN
7693 akron1 2151
        reg1 := GetAnyReg();
7597 akron1 2152
        Pic(reg1, BIN.PICDATA, tcount * 4 + dcount);
2153
        push(reg1);    // push _data + tcount * 4 + dcount
2154
        drop
2155
    ELSE
2156
        OutByte(68H);  // push _data
2157
        Reloc(BIN.RDATA, tcount * 4 + dcount)
2158
    END;
6613 leency 2159
 
7696 akron1 2160
    CallRTL(pic, IL._init);
2161
 
2162
    IF target = mConst.Target_iELF32 THEN
2163
        L := NewLabel();
2164
        pushc(0);
2165
        push(esp);
2166
        pushc(1024 * 1024 * stack);
2167
        pushc(0);
2168
        CallRTL(pic, IL._new);
2169
        pop(eax);
2170
        test(eax);
2171
        jcc(je, L);
2172
        addrc(eax, 1024 * 1024 * stack - 4);
2173
        mov(esp, eax);
2174
        SetLabel(L)
2175
    END
7597 akron1 2176
END prolog;
6613 leency 2177
 
2178
 
7696 akron1 2179
PROCEDURE epilog (pic: BOOLEAN; modname: ARRAY OF CHAR; target, stack, ver, dllinit, dllret, sofinit: INTEGER);
7597 akron1 2180
VAR
7693 akron1 2181
    exp:  IL.EXPORT_PROC;
7597 akron1 2182
    path, name, ext: PATHS.PATH;
6613 leency 2183
 
7693 akron1 2184
    dcount, i: INTEGER;
6613 leency 2185
 
7597 akron1 2186
 
2187
    PROCEDURE import (imp: LISTS.LIST);
2188
    VAR
7693 akron1 2189
        lib:  IL.IMPORT_LIB;
2190
        proc: IL.IMPORT_PROC;
7597 akron1 2191
 
2192
    BEGIN
2193
 
7693 akron1 2194
        lib := imp.first(IL.IMPORT_LIB);
7597 akron1 2195
        WHILE lib # NIL DO
2196
            BIN.Import(program, lib.name, 0);
7693 akron1 2197
            proc := lib.procs.first(IL.IMPORT_PROC);
7597 akron1 2198
            WHILE proc # NIL DO
2199
                BIN.Import(program, proc.name, proc.label);
7693 akron1 2200
                proc := proc.next(IL.IMPORT_PROC)
7597 akron1 2201
            END;
7693 akron1 2202
            lib := lib.next(IL.IMPORT_LIB)
7597 akron1 2203
        END
2204
 
2205
    END import;
2206
 
2207
 
6613 leency 2208
BEGIN
2209
 
7597 akron1 2210
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iKolibri, mConst.Target_iELF32} THEN
2211
        pushc(0);
7693 akron1 2212
        CallRTL(pic, IL._exit);
7597 akron1 2213
    ELSIF target = mConst.Target_iDLL THEN
2214
        SetLabel(dllret);
2215
        movrc(eax, 1);
2216
        OutByte(0C9H); // leave
2217
        OutByte3(0C2H, 0CH, 0) // ret 12
2218
    ELSIF target = mConst.Target_iObject THEN
2219
        movrc(eax, 1);
2220
        OutByte(0C3H)  // ret
7693 akron1 2221
    ELSIF target = mConst.Target_iELFSO32 THEN
2222
        OutByte(0C3H);  // ret
2223
        SetLabel(sofinit);
2224
        CallRTL(pic, IL._sofinit);
2225
        OutByte(0C3H)   // ret
7597 akron1 2226
    END;
6613 leency 2227
 
7597 akron1 2228
    fixup;
2229
 
7696 akron1 2230
    dcount := CHL.Length(IL.codes.data);
7597 akron1 2231
 
2232
    FOR i := 0 TO tcount - 1 DO
7696 akron1 2233
        BIN.PutData32LE(program, CHL.GetInt(IL.codes.types, i))
6613 leency 2234
    END;
2235
 
7597 akron1 2236
    FOR i := 0 TO dcount - 1 DO
7696 akron1 2237
        BIN.PutData(program, CHL.GetByte(IL.codes.data, i))
6613 leency 2238
    END;
2239
 
7597 akron1 2240
    program.modname := CHL.Length(program.data);
6613 leency 2241
 
7597 akron1 2242
    PATHS.split(modname, path, name, ext);
2243
    BIN.PutDataStr(program, name);
2244
    BIN.PutDataStr(program, ext);
2245
    BIN.PutData(program, 0);
6613 leency 2246
 
7597 akron1 2247
    IF target = mConst.Target_iObject THEN
2248
        BIN.Export(program, "lib_init", dllinit);
2249
    END;
6613 leency 2250
 
7696 akron1 2251
    exp := IL.codes.export.first(IL.EXPORT_PROC);
7597 akron1 2252
    WHILE exp # NIL DO
2253
        BIN.Export(program, exp.name, exp.label);
7693 akron1 2254
        exp := exp.next(IL.EXPORT_PROC)
6613 leency 2255
    END;
2256
 
7696 akron1 2257
    import(IL.codes.import);
6613 leency 2258
 
7696 akron1 2259
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 4)));
6613 leency 2260
 
7696 akron1 2261
    BIN.SetParams(program, IL.codes.bss, stack * (1024 * 1024), WCHR(ver DIV 65536), WCHR(ver MOD 65536));
7597 akron1 2262
 
2263
END epilog;
2264
 
2265
 
7696 akron1 2266
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
7597 akron1 2267
VAR
7693 akron1 2268
    dllret, dllinit, sofinit: INTEGER;
2269
    opt: PROG.OPTIONS;
7597 akron1 2270
 
6613 leency 2271
BEGIN
7696 akron1 2272
    tcount := CHL.Length(IL.codes.types);
6613 leency 2273
 
7693 akron1 2274
    opt := options;
7597 akron1 2275
    CodeList := LISTS.create(NIL);
2276
 
7696 akron1 2277
    program := BIN.create(IL.codes.lcount);
7597 akron1 2278
 
2279
    dllinit := NewLabel();
2280
    dllret  := NewLabel();
7693 akron1 2281
    sofinit := NewLabel();
7597 akron1 2282
 
2283
    IF target = mConst.Target_iObject THEN
7693 akron1 2284
        opt.pic := FALSE
6613 leency 2285
    END;
7597 akron1 2286
 
7693 akron1 2287
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL, mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
2288
        opt.pic := TRUE
7597 akron1 2289
    END;
2290
 
7693 akron1 2291
    REG.Init(R, push, pop, mov, xchg, NIL, NIL, {eax, ecx, edx}, {});
7597 akron1 2292
 
7696 akron1 2293
    prolog(opt.pic, target, opt.stack, dllinit, dllret);
2294
    translate(opt.pic, tcount * 4);
2295
    epilog(opt.pic, outname, target, opt.stack, opt.version, dllinit, dllret, sofinit);
7597 akron1 2296
 
2297
    BIN.fixup(program);
2298
 
2299
    IF target IN {mConst.Target_iConsole, mConst.Target_iGUI, mConst.Target_iDLL} THEN
7696 akron1 2300
        PE32.write(program, outname, target = mConst.Target_iConsole, target = mConst.Target_iDLL, FALSE)
7597 akron1 2301
    ELSIF target = mConst.Target_iKolibri THEN
2302
        KOS.write(program, outname)
2303
    ELSIF target = mConst.Target_iObject THEN
7693 akron1 2304
        MSCOFF.write(program, outname, opt.version)
2305
    ELSIF target IN {mConst.Target_iELF32, mConst.Target_iELFSO32} THEN
2306
        ELF.write(program, outname, sofinit, target = mConst.Target_iELFSO32, FALSE)
6613 leency 2307
    END
2308
 
7597 akron1 2309
END CodeGen;
7209 akron1 2310
 
7597 akron1 2311
 
2312
PROCEDURE SetProgram* (prog: BIN.PROGRAM);
7209 akron1 2313
BEGIN
7597 akron1 2314
    program := prog;
2315
    CodeList := LISTS.create(NIL)
2316
END SetProgram;
2317
 
2318
 
7696 akron1 2319
END X86.