Subversion Repositories Kolibri OS

Rev

Rev 8859 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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