Subversion Repositories Kolibri OS

Rev

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

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