Subversion Repositories Kolibri OS

Rev

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

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