Subversion Repositories Kolibri OS

Rev

Rev 7693 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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