Subversion Repositories Kolibri OS

Rev

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