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