Subversion Repositories Kolibri OS

Rev

Rev 9177 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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