Subversion Repositories Kolibri OS

Rev

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