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
3
 
8859 leency 4
    Copyright (c) 2018-2021, 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
 
684
    reg1, reg2, xmm: INTEGER;
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:
7597 akron1 1291
            PushAll(2);
1292
            pushc(param2);
7696 akron1 1293
            CallRTL(IL._move)
7597 akron1 1294
 
7693 akron1 1295
        |IL.opMOVE:
7597 akron1 1296
            PushAll(3);
7696 akron1 1297
            CallRTL(IL._move)
7597 akron1 1298
 
7693 akron1 1299
        |IL.opCOPYA:
7597 akron1 1300
            PushAll(4);
1301
            pushc(param2);
7693 akron1 1302
            CallRTL(IL._arrcpy);
7597 akron1 1303
            GetRegA
1304
 
7693 akron1 1305
        |IL.opCOPYS:
7597 akron1 1306
            PushAll(4);
1307
            pushc(param2);
7693 akron1 1308
            CallRTL(IL._strcpy)
7597 akron1 1309
 
7693 akron1 1310
        |IL.opROT:
7597 akron1 1311
            PushAll(0);
1312
            push(rsp);
1313
            pushc(param2);
7693 akron1 1314
            CallRTL(IL._rot)
7597 akron1 1315
 
7693 akron1 1316
        |IL.opNEW:
7597 akron1 1317
            PushAll(1);
8859 leency 1318
            n := param2 + 8;
1319
            ASSERT(UTILS.Align(n, 8));
7597 akron1 1320
            pushc(n);
1321
            pushc(param1);
7693 akron1 1322
            CallRTL(IL._new)
7597 akron1 1323
 
7693 akron1 1324
        |IL.opDISP:
7597 akron1 1325
            PushAll(1);
7693 akron1 1326
            CallRTL(IL._dispose)
7597 akron1 1327
 
7693 akron1 1328
        |IL.opPUSHT:
7597 akron1 1329
            UnOp(reg1);
8859 leency 1330
            movrm(GetAnyReg(), reg1, -8)
7597 akron1 1331
 
7693 akron1 1332
        |IL.opISREC:
7597 akron1 1333
            PushAll(2);
7693 akron1 1334
            pushc(param2 * tcount);
1335
            CallRTL(IL._isrec);
7597 akron1 1336
            GetRegA
1337
 
7693 akron1 1338
        |IL.opIS:
7597 akron1 1339
            PushAll(1);
7693 akron1 1340
            pushc(param2 * tcount);
1341
            CallRTL(IL._is);
7597 akron1 1342
            GetRegA
1343
 
7693 akron1 1344
        |IL.opTYPEGR:
7597 akron1 1345
            PushAll(1);
7693 akron1 1346
            pushc(param2 * tcount);
1347
            CallRTL(IL._guardrec);
7597 akron1 1348
            GetRegA
1349
 
7693 akron1 1350
        |IL.opTYPEGP:
7597 akron1 1351
            UnOp(reg1);
1352
            PushAll(0);
1353
            push(reg1);
7693 akron1 1354
            pushc(param2 * tcount);
1355
            CallRTL(IL._guard);
7597 akron1 1356
            GetRegA
1357
 
7693 akron1 1358
        |IL.opTYPEGD:
7597 akron1 1359
            UnOp(reg1);
1360
            PushAll(0);
7983 leency 1361
            X86.pushm(reg1, -8);
7693 akron1 1362
            pushc(param2 * tcount);
1363
            CallRTL(IL._guardrec);
7597 akron1 1364
            GetRegA
1365
 
7693 akron1 1366
        |IL.opCASET:
8859 leency 1367
            push(rcx);
1368
            push(rcx);
7693 akron1 1369
            pushc(param2 * tcount);
1370
            CallRTL(IL._guardrec);
8859 leency 1371
            pop(rcx);
7597 akron1 1372
            test(rax);
1373
            jcc(jne, param1)
1374
 
7693 akron1 1375
        |IL.opSAVEP:
7597 akron1 1376
            UnOp(reg1);
7693 akron1 1377
            reg2 := GetAnyReg();
7597 akron1 1378
            lea(reg2, param2, sCODE);
1379
            movmr(reg1, 0, reg2);
1380
            drop;
1381
            drop
1382
 
7693 akron1 1383
        |IL.opPUSHP:
1384
            lea(GetAnyReg(), param2, sCODE)
7597 akron1 1385
 
7693 akron1 1386
        |IL.opINC, IL.opDEC:
7597 akron1 1387
            BinOp(reg1, reg2);
7983 leency 1388
            (* add/sub qword[reg2], reg1 *)
7597 akron1 1389
            Rex(reg2, reg1);
7693 akron1 1390
            OutByte2(01H + 28H * ORD(opcode = IL.opDEC), reg2 MOD 8 + (reg1 MOD 8) * 8);
7597 akron1 1391
            drop;
1392
            drop
1393
 
7693 akron1 1394
        |IL.opINCC:
7597 akron1 1395
            UnOp(reg1);
1396
            IF isLong(param2) THEN
7693 akron1 1397
                reg2 := GetAnyReg();
7597 akron1 1398
                movrc(reg2, param2);
7983 leency 1399
                (* add qword[reg1], reg2 *)
7597 akron1 1400
                Rex(reg1, reg2);
7693 akron1 1401
                OutByte2(01H, reg1 MOD 8 + (reg2 MOD 8) * 8);
7597 akron1 1402
                drop
7693 akron1 1403
            ELSIF ABS(param2) = 1 THEN
1404
                Rex(reg1, 0);
7983 leency 1405
                OutByte2(0FFH, reg1 MOD 8 + 8 * ORD(param2 = -1)) (* inc/dec qword[reg1] *)
7597 akron1 1406
            ELSE
7983 leency 1407
                (* add qword[reg1], param2 *)
7597 akron1 1408
                Rex(reg1, 0);
7693 akron1 1409
                OutByte2(81H + short(param2), reg1 MOD 8);
7597 akron1 1410
                OutIntByte(param2)
1411
            END;
1412
            drop
1413
 
7693 akron1 1414
        |IL.opDROP:
7597 akron1 1415
            UnOp(reg1);
1416
            drop
1417
 
7693 akron1 1418
        |IL.opSAVE, IL.opSAVE64:
7597 akron1 1419
            BinOp(reg2, reg1);
1420
            movmr(reg1, 0, reg2);
1421
            drop;
1422
            drop
1423
 
7693 akron1 1424
        |IL.opSAVE8:
7597 akron1 1425
            BinOp(reg2, reg1);
7983 leency 1426
            X86.movmr8(reg1, 0, reg2);
7597 akron1 1427
            drop;
1428
            drop
1429
 
7693 akron1 1430
        |IL.opSAVE16:
7597 akron1 1431
            BinOp(reg2, reg1);
7983 leency 1432
            X86.movmr16(reg1, 0, reg2);
7597 akron1 1433
            drop;
1434
            drop
1435
 
7693 akron1 1436
        |IL.opSAVE32:
7597 akron1 1437
            BinOp(reg2, reg1);
1438
            movmr32(reg1, 0, reg2);
1439
            drop;
1440
            drop
1441
 
7983 leency 1442
        |IL.opMAX, IL.opMIN:
7597 akron1 1443
            BinOp(reg1, reg2);
1444
            cmprr(reg1, reg2);
7983 leency 1445
            OutByte2(7DH + ORD(opcode = IL.opMIN), 3); (* jge/jle L *)
7597 akron1 1446
            mov(reg1, reg2);
7983 leency 1447
            (* L: *)
7597 akron1 1448
            drop
1449
 
7983 leency 1450
        |IL.opMAXC, IL.opMINC:
7597 akron1 1451
            UnOp(reg1);
1452
            cmprc(reg1, param2);
1453
            label := NewLabel();
7983 leency 1454
            IF opcode = IL.opMINC THEN
1455
                cc := jle
1456
            ELSE
1457
                cc := jge
1458
            END;
1459
            jcc(cc, label);
7597 akron1 1460
            movrc(reg1, param2);
1461
            X86.SetLabel(label)
1462
 
7693 akron1 1463
        |IL.opSBOOL:
7597 akron1 1464
            BinOp(reg2, reg1);
1465
            test(reg2);
7693 akron1 1466
            IF reg1 >= 8 THEN
1467
                OutByte(41H)
1468
            END;
7983 leency 1469
            OutByte3(0FH, 95H, reg1 MOD 8); (* setne byte[reg1] *)
7597 akron1 1470
            drop;
1471
            drop
1472
 
7693 akron1 1473
        |IL.opSBOOLC:
7597 akron1 1474
            UnOp(reg1);
1475
            IF reg1 >= 8 THEN
1476
                OutByte(41H)
1477
            END;
7983 leency 1478
            OutByte3(0C6H, reg1 MOD 8, ORD(param2 # 0)); (* mov byte[reg1], 0/1 *)
7597 akron1 1479
            drop
1480
 
7693 akron1 1481
        |IL.opUMINUS:
7597 akron1 1482
            UnOp(reg1);
1483
            neg(reg1)
1484
 
7693 akron1 1485
        |IL.opADD:
7597 akron1 1486
            BinOp(reg1, reg2);
1487
            add(reg1, reg2);
1488
            drop
1489
 
7693 akron1 1490
        |IL.opSUB:
7597 akron1 1491
            BinOp(reg1, reg2);
1492
            sub(reg1, reg2);
1493
            drop
1494
 
7693 akron1 1495
        |IL.opSUBR, IL.opSUBL:
7597 akron1 1496
            UnOp(reg1);
8097 maxcodehac 1497
            IF param2 = 1 THEN
7597 akron1 1498
                decr(reg1)
8097 maxcodehac 1499
            ELSIF param2 = -1 THEN
7597 akron1 1500
                incr(reg1)
8097 maxcodehac 1501
            ELSIF param2 # 0 THEN
1502
                subrc(reg1, param2)
7597 akron1 1503
            END;
7693 akron1 1504
            IF opcode = IL.opSUBL THEN
7597 akron1 1505
                neg(reg1)
1506
            END
1507
 
8097 maxcodehac 1508
        |IL.opADDC:
7983 leency 1509
            IF (param2 # 0) & ~isLong(param2) THEN
7597 akron1 1510
                UnOp(reg1);
7983 leency 1511
                next := cmd.next(COMMAND);
1512
                CASE next.opcode OF
1513
                |IL.opLOAD64:
1514
                    movrm(reg1, reg1, param2);
1515
                    cmd := next
1516
                |IL.opLOAD32:
1517
                    movrm32(reg1, reg1, param2);
1518
                    shiftrc(shl, reg1, 32);
1519
                    shiftrc(shr, reg1, 32);
1520
                    cmd := next
1521
                |IL.opLOAD16:
1522
                    movzx(reg1, reg1, param2, TRUE);
1523
                    cmd := next
1524
                |IL.opLOAD8:
1525
                    movzx(reg1, reg1, param2, FALSE);
1526
                    cmd := next
1527
                |IL.opLOAD64_PARAM:
1528
                    X86.pushm(reg1, param2);
1529
                    drop;
1530
                    cmd := next
7597 akron1 1531
                ELSE
7983 leency 1532
                    IF param2 = 1 THEN
1533
                        incr(reg1)
1534
                    ELSIF param2 = -1 THEN
1535
                        decr(reg1)
1536
                    ELSE
1537
                        addrc(reg1, param2)
1538
                    END
7597 akron1 1539
                END
7983 leency 1540
            ELSIF isLong(param2) THEN
8859 leency 1541
                UnOp(reg1);
7983 leency 1542
                addrc(reg1, param2)
7597 akron1 1543
            END
1544
 
7693 akron1 1545
        |IL.opDIV:
7597 akron1 1546
            PushAll(2);
7696 akron1 1547
            CallRTL(IL._divmod);
7597 akron1 1548
            GetRegA
1549
 
7693 akron1 1550
        |IL.opDIVR:
7983 leency 1551
            n := UTILS.Log2(param2);
1552
            IF n > 0 THEN
7597 akron1 1553
                UnOp(reg1);
7983 leency 1554
                shiftrc(sar, reg1, n)
1555
            ELSIF n < 0 THEN
1556
                PushAll(1);
1557
                pushc(param2);
1558
                CallRTL(IL._divmod);
1559
                GetRegA
7597 akron1 1560
            END
1561
 
7693 akron1 1562
        |IL.opDIVL:
7696 akron1 1563
            UnOp(reg1);
1564
            REG.PushAll_1(R);
7597 akron1 1565
            pushc(param2);
7696 akron1 1566
            push(reg1);
1567
            drop;
1568
            CallRTL(IL._divmod);
7597 akron1 1569
            GetRegA
1570
 
7693 akron1 1571
        |IL.opMOD:
7597 akron1 1572
            PushAll(2);
7696 akron1 1573
            CallRTL(IL._divmod);
1574
            mov(rax, rdx);
7597 akron1 1575
            GetRegA
1576
 
7693 akron1 1577
        |IL.opMODR:
7983 leency 1578
            n := UTILS.Log2(param2);
1579
            IF n > 0 THEN
1580
                UnOp(reg1);
1581
                andrc(reg1, param2 - 1);
1582
            ELSIF n < 0 THEN
1583
                PushAll(1);
1584
                pushc(param2);
1585
                CallRTL(IL._divmod);
1586
                mov(rax, rdx);
1587
                GetRegA
7597 akron1 1588
            ELSE
1589
                UnOp(reg1);
1590
                xor(reg1, reg1)
1591
            END
1592
 
7693 akron1 1593
        |IL.opMODL:
7696 akron1 1594
            UnOp(reg1);
1595
            REG.PushAll_1(R);
7597 akron1 1596
            pushc(param2);
7696 akron1 1597
            push(reg1);
1598
            drop;
1599
            CallRTL(IL._divmod);
1600
            mov(rax, rdx);
7597 akron1 1601
            GetRegA
1602
 
7693 akron1 1603
        |IL.opMUL:
7597 akron1 1604
            BinOp(reg1, reg2);
7983 leency 1605
            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
7597 akron1 1606
            drop
1607
 
7693 akron1 1608
        |IL.opMULC:
7983 leency 1609
            IF (cmd.next(COMMAND).opcode = IL.opADD) & ((param2 = 2) OR (param2 = 4) OR (param2 = 8)) THEN
1610
                BinOp(reg1, reg2);
1611
                OutByte2(48H + 5 * (reg1 DIV 8) + 2 * (reg2 DIV 8), 8DH); (* lea reg1, [reg1 + reg2 * param2] *)
1612
                reg1 := reg1 MOD 8;
1613
                reg2 := reg2 MOD 8;
1614
                OutByte2(04H + reg1 * 8, reg1 + reg2 * 8 + 40H * UTILS.Log2(param2));
1615
                drop;
1616
                cmd := cmd.next(COMMAND)
7597 akron1 1617
            ELSE
7983 leency 1618
                UnOp(reg1);
7597 akron1 1619
 
7983 leency 1620
                a := param2;
1621
                IF a > 1 THEN
1622
                    n := UTILS.Log2(a)
1623
                ELSIF a < -1 THEN
1624
                    n := UTILS.Log2(-a)
1625
                ELSE
1626
                    n := -1
1627
                END;
7597 akron1 1628
 
7983 leency 1629
                IF a = 1 THEN
1630
 
1631
                ELSIF a = -1 THEN
1632
                    neg(reg1)
1633
                ELSIF a = 0 THEN
1634
                    xor(reg1, reg1)
7597 akron1 1635
                ELSE
7983 leency 1636
                    IF n > 0 THEN
1637
                        IF a < 0 THEN
1638
                            neg(reg1)
1639
                        END;
1640
                        shiftrc(shl, reg1, n)
1641
                    ELSE
1642
                        IF isLong(a) THEN
1643
                            reg2 := GetAnyReg();
1644
                            movabs(reg2, a);
1645
                            ASSERT(reg1 # reg2);
1646
                            oprr2(0FH, 0AFH, reg2, reg1); (* imul reg1, reg2 *)
1647
                            drop
1648
                        ELSE
1649
                            (* imul reg1, a *)
1650
                            Rex(reg1, reg1);
1651
                            OutByte2(69H + short(a), 0C0H + (reg1 MOD 8) * 9);
1652
                            OutIntByte(a)
1653
                        END
1654
                    END
7597 akron1 1655
                END
1656
            END
1657
 
7693 akron1 1658
        |IL.opADDS:
7597 akron1 1659
            BinOp(reg1, reg2);
8097 maxcodehac 1660
            _or(reg1, reg2);
7597 akron1 1661
            drop
1662
 
7693 akron1 1663
        |IL.opSUBS:
7597 akron1 1664
            BinOp(reg1, reg2);
1665
            not(reg2);
1666
            and(reg1, reg2);
1667
            drop
1668
 
8097 maxcodehac 1669
        |IL.opNOP, IL.opAND, IL.opOR:
7597 akron1 1670
 
7693 akron1 1671
        |IL.opSWITCH:
7597 akron1 1672
            UnOp(reg1);
1673
            IF param2 = 0 THEN
1674
                reg2 := rax
1675
            ELSE
8859 leency 1676
                reg2 := rcx
7597 akron1 1677
            END;
1678
            IF reg1 # reg2 THEN
1679
                ASSERT(REG.GetReg(R, reg2));
1680
                ASSERT(REG.Exchange(R, reg1, reg2));
1681
                drop
1682
            END;
1683
            drop
1684
 
7693 akron1 1685
        |IL.opENDSW:
7597 akron1 1686
 
7693 akron1 1687
        |IL.opCASEL:
7983 leency 1688
            GetRegA;
7597 akron1 1689
            cmprc(rax, param1);
7983 leency 1690
            jcc(jl, param2);
1691
            drop
7597 akron1 1692
 
7693 akron1 1693
        |IL.opCASER:
7983 leency 1694
            GetRegA;
7597 akron1 1695
            cmprc(rax, param1);
7983 leency 1696
            jcc(jg, param2);
1697
            drop
7597 akron1 1698
 
7693 akron1 1699
        |IL.opCASELR:
7983 leency 1700
            GetRegA;
7597 akron1 1701
            cmprc(rax, param1);
8859 leency 1702
            IF param2 = cmd.param3 THEN
1703
                jcc(jne, param2)
1704
            ELSE
1705
                jcc(jl, param2);
1706
                jcc(jg, cmd.param3)
1707
            END;
7983 leency 1708
            drop
7597 akron1 1709
 
7693 akron1 1710
        |IL.opASR, IL.opROR, IL.opLSL, IL.opLSR:
8859 leency 1711
            UnOp(reg1);
1712
            IF reg1 # rcx THEN
1713
                ASSERT(REG.GetReg(R, rcx));
1714
                ASSERT(REG.Exchange(R, reg1, rcx));
1715
                drop
1716
            END;
1717
 
7597 akron1 1718
            BinOp(reg1, reg2);
8859 leency 1719
            ASSERT(reg2 = rcx);
7597 akron1 1720
            Rex(reg1, 0);
1721
            OutByte(0D3H);
7983 leency 1722
            X86.shift(opcode, reg1 MOD 8); (* shift reg1, cl *)
7597 akron1 1723
            drop
1724
 
7693 akron1 1725
        |IL.opASR1, IL.opROR1, IL.opLSL1, IL.opLSR1:
8859 leency 1726
            UnOp(reg1);
1727
            IF reg1 # rcx THEN
1728
                ASSERT(REG.GetReg(R, rcx));
1729
                ASSERT(REG.Exchange(R, reg1, rcx));
1730
                drop
1731
            END;
1732
 
7693 akron1 1733
            reg1 := GetAnyReg();
7597 akron1 1734
            movrc(reg1, param2);
1735
            BinOp(reg1, reg2);
8859 leency 1736
            ASSERT(reg1 = rcx);
7597 akron1 1737
            Rex(reg2, 0);
1738
            OutByte(0D3H);
7983 leency 1739
            X86.shift(opcode, reg2 MOD 8); (* shift reg2, cl *)
7597 akron1 1740
            drop;
1741
            drop;
1742
            ASSERT(REG.GetReg(R, reg2))
1743
 
7693 akron1 1744
        |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
7597 akron1 1745
            UnOp(reg1);
7693 akron1 1746
            shiftrc(opcode, reg1, param2 MOD 64)
7597 akron1 1747
 
7693 akron1 1748
        |IL.opGET, IL.opGETC:
1749
            IF opcode = IL.opGET THEN
1750
                BinOp(reg1, reg2)
1751
            ELSIF opcode = IL.opGETC THEN
1752
                UnOp(reg2);
1753
                reg1 := GetAnyReg();
1754
                movrc(reg1, param1)
1755
            END;
7597 akron1 1756
            drop;
1757
            drop;
7983 leency 1758
            X86._movrm(reg1, reg1, 0, param2 * 8, FALSE);
1759
            X86._movrm(reg1, reg2, 0, param2 * 8, TRUE)
7597 akron1 1760
 
7693 akron1 1761
        |IL.opCHKBYTE:
7597 akron1 1762
            BinOp(reg1, reg2);
1763
            cmprc(reg1, 256);
1764
            jcc(jb, param1)
1765
 
7693 akron1 1766
        |IL.opCHKIDX:
7597 akron1 1767
            UnOp(reg1);
1768
            cmprc(reg1, param2);
1769
            jcc(jb, param1)
1770
 
7693 akron1 1771
        |IL.opCHKIDX2:
7597 akron1 1772
            BinOp(reg1, reg2);
1773
            IF param2 # -1 THEN
1774
                cmprr(reg2, reg1);
7983 leency 1775
                jcc(jb, param1);
1776
            END;
1777
            INCL(R.regs, reg1);
1778
            DEC(R.top);
1779
            R.stk[R.top] := reg2
7597 akron1 1780
 
7693 akron1 1781
        |IL.opLENGTH:
7597 akron1 1782
            PushAll(2);
7693 akron1 1783
            CallRTL(IL._length);
7597 akron1 1784
            GetRegA
1785
 
7693 akron1 1786
        |IL.opLENGTHW:
7597 akron1 1787
            PushAll(2);
7693 akron1 1788
            CallRTL(IL._lengthw);
7597 akron1 1789
            GetRegA
1790
 
7693 akron1 1791
        |IL.opLEN:
7597 akron1 1792
            n := param2;
1793
            UnOp(reg1);
1794
            drop;
1795
            EXCL(R.regs, reg1);
1796
 
1797
            WHILE n > 0 DO
1798
                UnOp(reg2);
1799
                drop;
1800
                DEC(n)
1801
            END;
1802
 
1803
            INCL(R.regs, reg1);
1804
            ASSERT(REG.GetReg(R, reg1))
1805
 
7693 akron1 1806
        |IL.opCHR:
7597 akron1 1807
            UnOp(reg1);
1808
            andrc(reg1, 255)
1809
 
7693 akron1 1810
        |IL.opWCHR:
7597 akron1 1811
            UnOp(reg1);
1812
            andrc(reg1, 65535)
1813
 
7693 akron1 1814
        |IL.opEQP, IL.opNEP, IL.opEQIP, IL.opNEIP:
7597 akron1 1815
            UnOp(reg1);
7693 akron1 1816
            reg2 := GetAnyReg();
7597 akron1 1817
 
7693 akron1 1818
            CASE opcode OF
1819
            |IL.opEQP, IL.opNEP:
7597 akron1 1820
                lea(reg2, param1, sCODE)
1821
 
7693 akron1 1822
            |IL.opEQIP, IL.opNEIP:
7597 akron1 1823
                lea(reg2, param1, sIMP);
1824
                movrm(reg2, reg2, 0)
1825
            END;
1826
 
1827
            cmprr(reg1, reg2);
1828
            drop;
1829
            drop;
7693 akron1 1830
            reg1 := GetAnyReg();
7597 akron1 1831
 
7693 akron1 1832
            CASE opcode OF
8097 maxcodehac 1833
            |IL.opEQP, IL.opEQIP: X86.setcc(sete,  reg1)
1834
            |IL.opNEP, IL.opNEIP: X86.setcc(setne, reg1)
7597 akron1 1835
            END;
1836
 
1837
            andrc(reg1, 1)
1838
 
7693 akron1 1839
        |IL.opINCCB, IL.opDECCB:
7597 akron1 1840
            UnOp(reg1);
1841
            IF reg1 >= 8 THEN
1842
                OutByte(41H)
1843
            END;
7983 leency 1844
            OutByte3(80H, 28H * ORD(opcode = IL.opDECCB) + reg1 MOD 8, param2 MOD 256); (* add/sub byte[reg1], param2 MOD 256 *)
7597 akron1 1845
            drop
1846
 
7693 akron1 1847
        |IL.opINCB, IL.opDECB:
7597 akron1 1848
            BinOp(reg1, reg2);
1849
            IF (reg1 >= 8) OR (reg2 >= 8) THEN
1850
                OutByte(40H + reg2 DIV 8 + 4 * (reg1 DIV 8))
1851
            END;
7983 leency 1852
            OutByte2(28H * ORD(opcode = IL.opDECB), reg2 MOD 8 + 8 * (reg1 MOD 8)); (* add/sub byte[reg2], reg1_8 *)
7597 akron1 1853
            drop;
1854
            drop
1855
 
7693 akron1 1856
        |IL.opSAVEIP:
7597 akron1 1857
            UnOp(reg1);
7693 akron1 1858
            reg2 := GetAnyReg();
7597 akron1 1859
            lea(reg2, param2, sIMP);
1860
            movrm(reg2, reg2, 0);
1861
            push(reg2);
1862
            drop;
1863
            IF reg1 >= 8 THEN
1864
                OutByte(41H)
1865
            END;
7983 leency 1866
            OutByte2(8FH, reg1 MOD 8); (* pop qword[reg1] *)
7597 akron1 1867
            drop
1868
 
7693 akron1 1869
        |IL.opCLEANUP:
8097 maxcodehac 1870
            IF param2 # 0 THEN
1871
                addrc(rsp, param2 * 8)
7597 akron1 1872
            END
1873
 
7693 akron1 1874
        |IL.opPOPSP:
7597 akron1 1875
            pop(rsp)
1876
 
7693 akron1 1877
        |IL.opLOADF:
7597 akron1 1878
            UnOp(reg1);
1879
            INC(xmm);
8097 maxcodehac 1880
            IF xmm > MAX_XMM THEN
1881
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1882
            END;
7597 akron1 1883
            movsdrm(xmm, reg1, 0);
1884
            drop
1885
 
7693 akron1 1886
        |IL.opPUSHF:
8097 maxcodehac 1887
            ASSERT(xmm >= 0);
7597 akron1 1888
            subrc(rsp, 8);
1889
            movsdmr(rsp, 0, xmm);
1890
            DEC(xmm)
1891
 
7693 akron1 1892
        |IL.opCONSTF:
7597 akron1 1893
            float := cmd.float;
1894
            INC(xmm);
8097 maxcodehac 1895
            IF xmm > MAX_XMM THEN
1896
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1897
            END;
1898
            (* movsd xmm, qword ptr [rip + Numbers_Offs + Numbers_Count * 8 + DATA] *)
1899
            OutByte(0F2H);
1900
            IF xmm >= 8 THEN
1901
                OutByte(44H)
1902
            END;
1903
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
1904
            X86.Reloc(sDATA, Numbers_Offs + Numbers_Count * 8);
7597 akron1 1905
            NewNumber(UTILS.splitf(float, a, b))
1906
 
7983 leency 1907
        |IL.opSAVEF, IL.opSAVEFI:
8097 maxcodehac 1908
            ASSERT(xmm >= 0);
7597 akron1 1909
            UnOp(reg1);
1910
            movsdmr(reg1, 0, xmm);
1911
            DEC(xmm);
1912
            drop
1913
 
8097 maxcodehac 1914
        |IL.opADDF:
1915
            ASSERT(xmm >= 1);
7597 akron1 1916
            opxx(58H, xmm - 1, xmm);
1917
            DEC(xmm)
1918
 
7693 akron1 1919
        |IL.opSUBF:
8097 maxcodehac 1920
            ASSERT(xmm >= 1);
7597 akron1 1921
            opxx(5CH, xmm - 1, xmm);
1922
            DEC(xmm)
1923
 
7693 akron1 1924
        |IL.opSUBFI:
8097 maxcodehac 1925
            ASSERT(xmm >= 1);
7597 akron1 1926
            opxx(5CH, xmm, xmm - 1);
1927
            opxx(10H, xmm - 1, xmm);
1928
            DEC(xmm)
1929
 
7693 akron1 1930
        |IL.opMULF:
8097 maxcodehac 1931
            ASSERT(xmm >= 1);
7597 akron1 1932
            opxx(59H, xmm - 1, xmm);
1933
            DEC(xmm)
1934
 
7693 akron1 1935
        |IL.opDIVF:
8097 maxcodehac 1936
            ASSERT(xmm >= 1);
7597 akron1 1937
            opxx(5EH, xmm - 1, xmm);
1938
            DEC(xmm)
1939
 
7693 akron1 1940
        |IL.opDIVFI:
8097 maxcodehac 1941
            ASSERT(xmm >= 1);
7597 akron1 1942
            opxx(5EH, xmm, xmm - 1);
1943
            opxx(10H, xmm - 1, xmm);
1944
            DEC(xmm)
1945
 
8097 maxcodehac 1946
        |IL.opFABS, IL.opUMINF: (* andpd/xorpd xmm, xmmword[rip + Numbers_Offs + (16) + DATA] *)
1947
            ASSERT(xmm >= 0);
1948
            OutByte(66H);
1949
            IF xmm >= 8 THEN
1950
                OutByte(44H)
1951
            END;
1952
            OutByte3(0FH, 54H + 3 * ORD(opcode = IL.opUMINF), 05H + (xmm MOD 8) * 8);
1953
            X86.Reloc(sDATA, Numbers_Offs + 16 * ORD(opcode = IL.opFABS))
7597 akron1 1954
 
7693 akron1 1955
        |IL.opFLT:
7597 akron1 1956
            UnOp(reg1);
1957
            INC(xmm);
8097 maxcodehac 1958
            IF xmm > MAX_XMM THEN
1959
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1960
            END;
7983 leency 1961
            OutByte(0F2H); Rex(reg1, xmm); OutByte(0FH); (* cvtsi2sd xmm, reg1 *)
7597 akron1 1962
            OutByte2(2AH, 0C0H + (xmm MOD 8) * 8 + reg1 MOD 8);
1963
            drop
1964
 
7693 akron1 1965
        |IL.opFLOOR:
8097 maxcodehac 1966
            ASSERT(xmm >= 0);
7693 akron1 1967
            reg1 := GetAnyReg();
7597 akron1 1968
            subrc(rsp, 8);
7983 leency 1969
            OutByte3(00FH, 0AEH, 05CH); OutByte2(024H, 004H);                       (* stmxcsr dword[rsp+4];                              *)
1970
            OutByte2(00FH, 0AEH); OutByte2(01CH, 024H);                             (* stmxcsr dword[rsp];                                *)
1971
            OutByte3(081H, 024H, 024H); OutByte2(0FFH, 09FH); OutByte2(0FFH, 0FFH); (* and dword[rsp],11111111111111111001111111111111b;  *)
1972
            OutByte3(081H, 00CH, 024H); OutByte2(000H, 020H); OutByte2(000H, 000H); (* or dword[rsp],00000000000000000010000000000000b;   *)
1973
            OutByte2(00FH, 0AEH); OutByte2(014H, 024H);                             (* ldmxcsr dword[rsp];                                *)
1974
            OutByte(0F2H); Rex(xmm, reg1); OutByte(0FH);                            (* cvtsd2si reg1, xmm                                 *)
7597 akron1 1975
            OutByte2(2DH, 0C0H + xmm MOD 8 + (reg1 MOD 8) * 8);
7983 leency 1976
            OutByte3(00FH, 0AEH, 054H); OutByte2(024H, 004H);                       (* ldmxcsr dword[rsp+4];                              *)
7597 akron1 1977
            addrc(rsp, 8);
1978
            DEC(xmm)
1979
 
7693 akron1 1980
        |IL.opEQF .. IL.opGEF:
8097 maxcodehac 1981
            ASSERT(xmm >= 1);
7693 akron1 1982
            fcmp(opcode, xmm);
7597 akron1 1983
            DEC(xmm, 2)
1984
 
7693 akron1 1985
        |IL.opINF:
7597 akron1 1986
            INC(xmm);
8097 maxcodehac 1987
            IF xmm > MAX_XMM THEN
1988
                ERRORS.ErrorMsg(fname, param1, param2, FPR_ERR)
1989
            END;
1990
            (* movsd xmm, qword ptr [rip + Numbers_Offs + 32 + DATA] *)
1991
            OutByte(0F2H);
1992
            IF xmm >= 8 THEN
1993
                OutByte(44H)
1994
            END;
1995
            OutByte3(0FH, 10H, 05H + 8 * (xmm MOD 8));
1996
            X86.Reloc(sDATA, Numbers_Offs + 32)
7597 akron1 1997
 
7693 akron1 1998
        |IL.opPACK, IL.opPACKC:
1999
            IF opcode = IL.opPACK THEN
7597 akron1 2000
                BinOp(reg1, reg2)
2001
            ELSE
2002
                UnOp(reg1);
7693 akron1 2003
                reg2 := GetAnyReg();
7597 akron1 2004
                movrc(reg2, param2)
2005
            END;
2006
            push(reg1);
2007
            movrm(reg1, reg1, 0);
2008
            shiftrc(shl, reg1, 1);
2009
            shiftrc(shr, reg1, 53);
2010
            add(reg1, reg2);
2011
            andrc(reg1, ORD({0..10}));
2012
            shiftrc(shl, reg1, 52);
2013
            movrm(reg2, rsp, 0);
2014
            movrm(reg2, reg2, 0);
2015
 
2016
            push(reg1);
7983 leency 2017
            lea(reg1, Numbers_Offs + 40, sDATA); (* {0..51, 63} *)
7597 akron1 2018
            movrm(reg1, reg1, 0);
2019
            and(reg2, reg1);
2020
            pop(reg1);
2021
 
8097 maxcodehac 2022
            _or(reg2, reg1);
7597 akron1 2023
            pop(reg1);
2024
            movmr(reg1, 0, reg2);
2025
            drop;
2026
            drop
2027
 
7693 akron1 2028
        |IL.opUNPK, IL.opLADR_UNPK:
7597 akron1 2029
 
7693 akron1 2030
            IF opcode = IL.opLADR_UNPK THEN
7597 akron1 2031
                n := param2 * 8;
2032
                UnOp(reg1);
8859 leency 2033
                reg2 := GetAnyReg();
2034
                Rex(0, reg2);
2035
                OutByte2(8DH, 45H + long(n) + (reg2 MOD 8) * 8); (* lea reg2, qword[rbp+n] *)
2036
                OutIntByte(n)
7597 akron1 2037
            ELSE
8859 leency 2038
                BinOp(reg1, reg2)
7597 akron1 2039
            END;
2040
 
2041
            push(reg1);
2042
            movrm(reg1, reg1, 0);
2043
            shiftrc(shl, reg1, 1);
2044
            shiftrc(shr, reg1, 53);
2045
            subrc(reg1, 1023);
2046
 
8859 leency 2047
            movmr(reg2, 0, reg1);
7597 akron1 2048
 
2049
            pop(reg2);
2050
            movrm(reg1, reg2, 0);
2051
 
2052
            push(reg2);
7983 leency 2053
            lea(reg2, Numbers_Offs + 48, sDATA); (* {52..61} *)
7597 akron1 2054
            movrm(reg2, reg2, 0);
8097 maxcodehac 2055
            _or(reg1, reg2);
7597 akron1 2056
            pop(reg2);
2057
 
2058
            Rex(reg1, 0);
2059
            OutByte2(0FH, 0BAH);
7983 leency 2060
            OutByte2(0F0H + reg1 MOD 8, 3EH); (* btr reg1, 62 *)
7597 akron1 2061
            movmr(reg2, 0, reg1);
2062
            drop;
2063
            drop
2064
 
7693 akron1 2065
        |IL.opSADR_PARAM:
7597 akron1 2066
            pushDA(stroffs + param2)
2067
 
7693 akron1 2068
        |IL.opVADR_PARAM:
7983 leency 2069
            X86.pushm(rbp, param2 * 8)
7597 akron1 2070
 
7693 akron1 2071
        |IL.opLOAD64_PARAM:
7597 akron1 2072
            UnOp(reg1);
7983 leency 2073
            X86.pushm(reg1, 0);
7597 akron1 2074
            drop
2075
 
7693 akron1 2076
        |IL.opLLOAD64_PARAM:
8859 leency 2077
            X86.pushm(rbp, param2 * 8)
7597 akron1 2078
 
7693 akron1 2079
        |IL.opGLOAD64_PARAM:
8097 maxcodehac 2080
            OutByte2(0FFH, 35H); (* push qword[rip + param2 + BSS] *)
2081
            X86.Reloc(sBSS, param2)
7597 akron1 2082
 
7693 akron1 2083
        |IL.opCONST_PARAM:
7597 akron1 2084
            pushc(param2)
2085
 
8097 maxcodehac 2086
        |IL.opGLOAD32_PARAM, IL.opLOAD32_PARAM:
2087
            IF opcode = IL.opGLOAD32_PARAM THEN
2088
                reg1 := GetAnyReg();
2089
                lea(reg1, param2, sBSS)
2090
            ELSE
2091
                UnOp(reg1)
2092
            END;
7597 akron1 2093
            movrm32(reg1, reg1, 0);
2094
            shiftrc(shl, reg1, 32);
2095
            shiftrc(shr, reg1, 32);
2096
            push(reg1);
2097
            drop
2098
 
7693 akron1 2099
        |IL.opLLOAD32_PARAM:
2100
            reg1 := GetAnyReg();
8859 leency 2101
            movrm32(reg1, rbp, param2 * 8);
8097 maxcodehac 2102
            shiftrc(shl, reg1, 32);
2103
            shiftrc(shr, reg1, 32);
7597 akron1 2104
            push(reg1);
2105
            drop
2106
 
7693 akron1 2107
        |IL.opLADR_SAVEC:
7597 akron1 2108
            n := param1 * 8;
8859 leency 2109
            IF isLong(param2) THEN
2110
                reg2 := GetAnyReg();
2111
                movrc(reg2, param2);
2112
                movmr(rbp, n, reg2);
2113
                drop
7597 akron1 2114
            ELSE
8859 leency 2115
                OutByte3(48H, 0C7H, 45H + long(n)); (* mov qword[rbp+n], param2 *)
2116
                OutIntByte(n);
2117
                OutInt(param2)
7597 akron1 2118
            END
2119
 
7693 akron1 2120
        |IL.opGADR_SAVEC:
7597 akron1 2121
            IF isLong(param2) THEN
7693 akron1 2122
                reg1 := GetAnyReg();
7597 akron1 2123
                movrc(reg1, param2);
7693 akron1 2124
                reg2 := GetAnyReg();
7597 akron1 2125
                lea(reg2, param1, sBSS);
2126
                movmr(reg2, 0, reg1);
2127
                drop;
2128
                drop
2129
            ELSE
8097 maxcodehac 2130
                (* mov qword[rip + param1 - 4 + BSS], param2 *)
2131
                OutByte3(48H, 0C7H, 05H);
2132
                X86.Reloc(sBSS, param1 - 4);
2133
                OutInt(param2)
7597 akron1 2134
            END
2135
 
7693 akron1 2136
        |IL.opLADR_SAVE:
7597 akron1 2137
            UnOp(reg1);
8859 leency 2138
            movmr(rbp, param2 * 8, reg1);
7597 akron1 2139
            drop
2140
 
7693 akron1 2141
        |IL.opLADR_INCC:
7597 akron1 2142
            IF isLong(param2) THEN
7693 akron1 2143
                reg2 := GetAnyReg();
7597 akron1 2144
                movrc(reg2, param2);
8859 leency 2145
                n := param1 * 8;
2146
                Rex(0, reg2);
2147
                OutByte2(01H, 45H + long(n) + (reg2 MOD 8) * 8);
2148
                OutIntByte(n); (* add qword[rbp+n], reg2 *)
7597 akron1 2149
                drop
7693 akron1 2150
            ELSIF ABS(param2) = 1 THEN
8859 leency 2151
                n := param1 * 8;
2152
                OutByte3(48H, 0FFH, 45H + 8 * ORD(param2 = -1) + long(n)); (* inc/dec qword[rbp+n] *)
2153
                OutIntByte(n)
7693 akron1 2154
            ELSE
8859 leency 2155
                n := param1 * 8;
2156
                OutByte3(48H, 81H + short(param2), 45H + long(n));
2157
                OutIntByte(n);
2158
                OutIntByte(param2) (* add qword[rbp+n], param2 *)
7597 akron1 2159
            END
2160
 
7693 akron1 2161
        |IL.opLADR_INCCB, IL.opLADR_DECCB:
7597 akron1 2162
            param2 := param2 MOD 256;
8859 leency 2163
            n := param1 * 8;
2164
            OutByte2(80H, 45H + long(n) + 28H * ORD(opcode = IL.opLADR_DECCB));
2165
            OutIntByte(n);
2166
            OutByte(param2) (* add/sub byte[rbp+n], param2 *)
7597 akron1 2167
 
7693 akron1 2168
        |IL.opLADR_INC, IL.opLADR_DEC:
7597 akron1 2169
            UnOp(reg1);
8859 leency 2170
            n := param2 * 8;
2171
            Rex(0, reg1);
2172
            OutByte2(01H + 28H * ORD(opcode = IL.opLADR_DEC), 45H + long(n) + (reg1 MOD 8) * 8);
2173
            OutIntByte(n); (* add/sub qword[rbp+n], reg1 *)
7597 akron1 2174
            drop
2175
 
7693 akron1 2176
        |IL.opLADR_INCB, IL.opLADR_DECB:
7597 akron1 2177
            UnOp(reg1);
8859 leency 2178
            n := param2 * 8;
2179
            IF reg1 >= 8 THEN
2180
                OutByte(44H)
7597 akron1 2181
            END;
8859 leency 2182
            OutByte2(28H * ORD(opcode = IL.opLADR_DECB), 45H + long(n) + 8 * (reg1 MOD 8));
2183
            OutIntByte(n); (* add/sub byte[rbp+n], reg1_8 *)
7597 akron1 2184
            drop
2185
 
7693 akron1 2186
        |IL.opLADR_INCL, IL.opLADR_EXCL:
7597 akron1 2187
            UnOp(reg1);
2188
            cmprc(reg1, 64);
8859 leency 2189
            n := param2 * 8;
2190
            OutByte2(73H, 5 + 3 * ORD(~X86.isByte(n))); (* jnb L *)
2191
            Rex(0, reg1);
2192
            OutByte3(0FH, 0ABH + 8 * ORD(opcode = IL.opLADR_EXCL), 45H + long(n) + 8 * (reg1 MOD 8));
2193
            OutIntByte(n); (* bts/btr qword[rbp+n], reg1 *)
7983 leency 2194
            (* L: *)
7597 akron1 2195
            drop
2196
 
7693 akron1 2197
        |IL.opLADR_INCLC, IL.opLADR_EXCLC:
8859 leency 2198
            n := param1 * 8;
2199
            OutByte3(48H, 0FH, 0BAH); (* bts/btr qword[rbp+n], param2 *)
2200
            OutByte(6DH + long(n) + 8 * ORD(opcode = IL.opLADR_EXCLC));
2201
            OutIntByte(n);
2202
            OutByte(param2)
7597 akron1 2203
 
8097 maxcodehac 2204
        |IL.opFNAME:
2205
            fname := cmd(IL.FNAMECMD).fname
2206
 
7597 akron1 2207
        END;
2208
 
2209
        cmd := cmd.next(COMMAND)
2210
    END;
2211
 
2212
    ASSERT(R.pushed = 0);
2213
    ASSERT(R.top = -1);
2214
    ASSERT(xmm = -1)
2215
END translate;
2216
 
2217
 
7696 akron1 2218
PROCEDURE prolog (modname: ARRAY OF CHAR; target, stack_size: INTEGER);
7597 akron1 2219
VAR
7693 akron1 2220
    ModName_Offs, entry, L: INTEGER;
7597 akron1 2221
 
2222
BEGIN
7696 akron1 2223
    ModName_Offs := tcount * 8 + CHL.Length(IL.codes.data);
7597 akron1 2224
    Numbers_Offs := ModName_Offs + LENGTH(modname) + 1;
7693 akron1 2225
    ASSERT(UTILS.Align(Numbers_Offs, 16));
7597 akron1 2226
 
2227
    entry := NewLabel();
2228
    X86.SetLabel(entry);
2229
 
7983 leency 2230
    IF target = TARGETS.Win64DLL THEN
7597 akron1 2231
        dllret := NewLabel();
2232
        push(r8);
2233
        push(rdx);
2234
        push(rcx);
7693 akron1 2235
        CallRTL(IL._dllentry);
7597 akron1 2236
        test(rax);
8097 maxcodehac 2237
        jcc(je, dllret);
2238
        pushc(0)
2239
    ELSIF target = TARGETS.Linux64 THEN
7693 akron1 2240
        push(rsp)
2241
    ELSE
2242
        pushc(0)
2243
    END;
2244
 
7597 akron1 2245
    lea(rax, entry, sCODE);
2246
    push(rax);
7983 leency 2247
    pushDA(0); (* TYPES *)
7693 akron1 2248
    pushc(tcount);
7983 leency 2249
    pushDA(ModName_Offs); (* MODNAME *)
7693 akron1 2250
    CallRTL(IL._init);
2251
 
7983 leency 2252
    IF target IN {TARGETS.Win64C, TARGETS.Win64GUI, TARGETS.Linux64} THEN
7693 akron1 2253
        L := NewLabel();
2254
        pushc(0);
2255
        push(rsp);
2256
        pushc(1024 * 1024 * stack_size);
2257
        pushc(0);
2258
        CallRTL(IL._new);
2259
        pop(rax);
2260
        test(rax);
2261
        jcc(je, L);
7983 leency 2262
        GetRegA;
7693 akron1 2263
        addrc(rax, 1024 * 1024 * stack_size - 8);
7983 leency 2264
        drop;
7693 akron1 2265
        mov(rsp, rax);
2266
        X86.SetLabel(L)
2267
    END
7597 akron1 2268
END prolog;
2269
 
2270
 
7696 akron1 2271
PROCEDURE epilog (modname: ARRAY OF CHAR; target: INTEGER);
7597 akron1 2272
VAR
2273
    i, n: INTEGER;
2274
    number: Number;
7693 akron1 2275
    exp: IL.EXPORT_PROC;
7597 akron1 2276
 
2277
 
8097 maxcodehac 2278
    PROCEDURE _import (imp: LISTS.LIST);
7597 akron1 2279
    VAR
7693 akron1 2280
        lib:  IL.IMPORT_LIB;
2281
        proc: IL.IMPORT_PROC;
7597 akron1 2282
 
2283
    BEGIN
2284
 
7693 akron1 2285
        lib := imp.first(IL.IMPORT_LIB);
7597 akron1 2286
        WHILE lib # NIL DO
2287
            BIN.Import(prog, lib.name, 0);
7693 akron1 2288
            proc := lib.procs.first(IL.IMPORT_PROC);
7597 akron1 2289
            WHILE proc # NIL DO
2290
                BIN.Import(prog, proc.name, proc.label);
7693 akron1 2291
                proc := proc.next(IL.IMPORT_PROC)
7597 akron1 2292
            END;
7693 akron1 2293
            lib := lib.next(IL.IMPORT_LIB)
7597 akron1 2294
        END
2295
 
8097 maxcodehac 2296
    END _import;
7597 akron1 2297
 
2298
 
2299
BEGIN
7983 leency 2300
    IF target = TARGETS.Win64DLL THEN
7597 akron1 2301
        X86.SetLabel(dllret);
7983 leency 2302
        X86.ret
2303
    ELSIF target = TARGETS.Linux64SO THEN
7693 akron1 2304
        sofinit := NewLabel();
7983 leency 2305
        X86.ret;
7693 akron1 2306
        X86.SetLabel(sofinit);
2307
        CallRTL(IL._sofinit);
7983 leency 2308
        X86.ret
7597 akron1 2309
    ELSE
2310
        pushc(0);
7693 akron1 2311
        CallRTL(IL._exit)
7597 akron1 2312
    END;
2313
 
2314
    X86.fixup;
2315
 
2316
    i := 0;
7693 akron1 2317
    WHILE i < tcount DO
7696 akron1 2318
        BIN.PutData64LE(prog, CHL.GetInt(IL.codes.types, i));
7597 akron1 2319
        INC(i)
2320
    END;
2321
 
2322
    i := 0;
7696 akron1 2323
    WHILE i < CHL.Length(IL.codes.data) DO
2324
        BIN.PutData(prog, CHL.GetByte(IL.codes.data, i));
7597 akron1 2325
        INC(i)
2326
    END;
2327
 
2328
    BIN.PutDataStr(prog, modname);
2329
    BIN.PutData(prog, 0);
2330
    n := CHL.Length(prog.data);
7693 akron1 2331
    ASSERT(UTILS.Align(n, 16));
7597 akron1 2332
    i := n - CHL.Length(prog.data);
2333
    WHILE i > 0 DO
2334
        BIN.PutData(prog, 0);
2335
        DEC(i)
2336
    END;
2337
    number := Numbers.first(Number);
2338
    FOR i := 0 TO Numbers_Count - 1 DO
2339
        BIN.PutData64LE(prog, number.value);
2340
        number := number.next(Number)
2341
    END;
2342
 
7696 akron1 2343
    exp := IL.codes.export.first(IL.EXPORT_PROC);
7597 akron1 2344
    WHILE exp # NIL DO
2345
        BIN.Export(prog, exp.name, exp.label);
7693 akron1 2346
        exp := exp.next(IL.EXPORT_PROC)
7597 akron1 2347
    END;
2348
 
8097 maxcodehac 2349
    _import(IL.codes._import)
7597 akron1 2350
END epilog;
2351
 
2352
 
7696 akron1 2353
PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
7597 akron1 2354
VAR
2355
    path, modname, ext: PATHS.PATH;
2356
 
2357
BEGIN
8097 maxcodehac 2358
    Xmm[0] := 0;
7696 akron1 2359
    tcount := CHL.Length(IL.codes.types);
7693 akron1 2360
 
7597 akron1 2361
    Win64RegPar[0] := rcx;
2362
    Win64RegPar[1] := rdx;
2363
    Win64RegPar[2] := r8;
2364
    Win64RegPar[3] := r9;
2365
 
2366
    SystemVRegPar[0] := rdi;
2367
    SystemVRegPar[1] := rsi;
2368
    SystemVRegPar[2] := rdx;
2369
    SystemVRegPar[3] := rcx;
2370
    SystemVRegPar[4] := r8;
2371
    SystemVRegPar[5] := r9;
2372
 
2373
    PATHS.split(outname, path, modname, ext);
2374
    S.append(modname, ext);
2375
 
8859 leency 2376
    REG.Init(R, push, pop, mov, xchg, {rax, rcx, rdx, r8, r9, r10, r11});
7597 akron1 2377
 
7696 akron1 2378
    IL.set_bss(MAX(IL.codes.bss, MAX(IL.codes.dmin - CHL.Length(IL.codes.data), 8)));
7597 akron1 2379
 
2380
    Numbers := LISTS.create(NIL);
2381
    Numbers_Count := 0;
2382
    NewNumber(ROR(1, 1));      (* 8000000000000000H *)
2383
    NewNumber(0);
2384
    NewNumber(ROR(-2, 1));     (* 7FFFFFFFFFFFFFFFH *)
2385
    NewNumber(-1);
2386
    NewNumber(ROR(7FFH, 12));  (* +Infinity *)
2387
    NewNumber(ORD(-BITS(LSR(ASR(ROR(1, 1), 10), 1))));  (* {0..51, 63} *)
2388
    NewNumber(LSR(ASR(ROR(1, 1), 9), 2));  (* {52..61} *)
2389
 
7696 akron1 2390
    prog := BIN.create(IL.codes.lcount);
2391
    BIN.SetParams(prog, IL.codes.bss, 1, WCHR(1), WCHR(0));
7597 akron1 2392
 
2393
    X86.SetProgram(prog);
2394
 
7696 akron1 2395
    prolog(modname, target, options.stack);
2396
    translate(IL.codes.commands, tcount * 8);
2397
    epilog(modname, target);
7597 akron1 2398
 
2399
    BIN.fixup(prog);
7983 leency 2400
    IF TARGETS.OS = TARGETS.osWIN64 THEN
2401
        PE32.write(prog, outname, target = TARGETS.Win64C, target = TARGETS.Win64DLL, TRUE)
2402
    ELSIF TARGETS.OS = TARGETS.osLINUX64 THEN
2403
        ELF.write(prog, outname, sofinit, target = TARGETS.Linux64SO, TRUE)
7597 akron1 2404
    END
2405
END CodeGen;
2406
 
2407
 
7983 leency 2408
END AMD64.