Subversion Repositories Kolibri OS

Rev

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