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 MSP430;
  9.  
  10. IMPORT IL, LISTS, REG, CHL := CHUNKLISTS, ERRORS, WR := WRITER, HEX,
  11.        UTILS, C := CONSOLE, PROG, RTL := MSP430RTL;
  12.  
  13.  
  14. CONST
  15.  
  16.     chkSTK* = 6;
  17.  
  18.     minRAM* = 128;  maxRAM* = 2048;
  19.     minROM* = 2048; maxROM* = 24576;
  20.  
  21.     StkReserve = RTL.StkReserve;
  22.  
  23.     IntVectorSize* = RTL.IntVectorSize;
  24.  
  25.     PC = 0; SP = 1; SR = 2; CG = 3;
  26.  
  27.     R4 = 4; R5 = 5; R6 = 6; R7 = 7;
  28.  
  29.     HP = RTL.HP;
  30.  
  31.     ACC = R4;
  32.  
  33.     opRRC  = 1000H;  opSWPB = 1080H;  opRRA  = 1100H;  opSXT = 1180H;
  34.     opPUSH = 1200H;  opCALL = 1280H;  opRETI = 1300H;
  35.  
  36.     opMOV = 04000H;  opADD = 05000H;  opADDC = 06000H;  opSUBC = 07000H;
  37.     opSUB = 08000H;  opCMP = 09000H;  opDADD = 0A000H;  opBIT  = 0B000H;
  38.     opBIC = 0C000H;  opBIS = 0D000H;  opXOR  = 0E000H;  opAND  = 0F000H;
  39.  
  40.     opJNE = 2000H;  opJEQ = 2400H;  opJNC = 2800H;  opJC  = 2C00H;
  41.     opJN  = 3000H;  opJGE = 3400H;  opJL  = 3800H;  opJMP = 3C00H;
  42.  
  43.     sREG = 0; sIDX = 16; sINDIR = 32; sINCR = 48; BW = 64; dIDX = 128;
  44.  
  45.     NOWORD = 10000H;
  46.  
  47.     RCODE = 0; RDATA = 1; RBSS = 2;
  48.  
  49.     je  = 0;  jne = je  + 1;
  50.     jge = 2;  jl  = jge + 1;
  51.     jle = 4;  jg  = jle + 1;
  52.     jb  = 6;
  53.  
  54.  
  55. TYPE
  56.  
  57.     ANYCODE = POINTER TO RECORD (LISTS.ITEM)
  58.  
  59.         offset: INTEGER
  60.  
  61.     END;
  62.  
  63.     WORD = POINTER TO RECORD (ANYCODE)
  64.  
  65.         val: INTEGER
  66.  
  67.     END;
  68.  
  69.     LABEL = POINTER TO RECORD (ANYCODE)
  70.  
  71.         num: INTEGER
  72.  
  73.     END;
  74.  
  75.     JMP = POINTER TO RECORD (ANYCODE)
  76.  
  77.         cc, label: INTEGER;
  78.         short: BOOLEAN
  79.  
  80.     END;
  81.  
  82.     CALL = POINTER TO RECORD (ANYCODE)
  83.  
  84.         label: INTEGER
  85.  
  86.     END;
  87.  
  88.     COMMAND = IL.COMMAND;
  89.  
  90.     RELOC = POINTER TO RECORD (LISTS.ITEM)
  91.  
  92.         section: INTEGER;
  93.         WordPtr: WORD
  94.  
  95.     END;
  96.  
  97.  
  98. VAR
  99.  
  100.     R: REG.REGS;
  101.  
  102.     CodeList: LISTS.LIST;
  103.     RelList:  LISTS.LIST;
  104.  
  105.     mem: ARRAY 65536 OF BYTE;
  106.  
  107.     Labels: CHL.INTLIST;
  108.  
  109.     IV: ARRAY RTL.LenIV OF INTEGER;
  110.  
  111.     IdxWords: RECORD src, dst: INTEGER END;
  112.  
  113.     StkCnt, MaxStkCnt: INTEGER;
  114.  
  115.  
  116. PROCEDURE CheckProcDataSize* (VarSize, RamSize: INTEGER): BOOLEAN;
  117.     RETURN (VarSize + 1) * 2 + StkReserve + RTL.VarSize < RamSize
  118. END CheckProcDataSize;
  119.  
  120.  
  121. PROCEDURE EmitLabel (L: INTEGER);
  122. VAR
  123.     label: LABEL;
  124.  
  125. BEGIN
  126.     NEW(label);
  127.     label.num := L;
  128.     LISTS.push(CodeList, label)
  129. END EmitLabel;
  130.  
  131.  
  132. PROCEDURE EmitWord (val: INTEGER);
  133. VAR
  134.     word: WORD;
  135.  
  136. BEGIN
  137.     IF val < 0 THEN
  138.         ASSERT(val >= -32768);
  139.         val := val MOD 65536
  140.     ELSE
  141.         ASSERT(val <= 65535)
  142.     END;
  143.     NEW(word);
  144.     word.val := val;
  145.     LISTS.push(CodeList, word)
  146. END EmitWord;
  147.  
  148.  
  149. PROCEDURE EmitJmp (cc, label: INTEGER);
  150. VAR
  151.     jmp: JMP;
  152.  
  153. BEGIN
  154.     NEW(jmp);
  155.     jmp.cc := cc;
  156.     jmp.label := label;
  157.     jmp.short := FALSE;
  158.     LISTS.push(CodeList, jmp)
  159. END EmitJmp;
  160.  
  161.  
  162. PROCEDURE EmitCall (label: INTEGER);
  163. VAR
  164.     call: CALL;
  165.  
  166. BEGIN
  167.     NEW(call);
  168.     call.label := label;
  169.     LISTS.push(CodeList, call)
  170. END EmitCall;
  171.  
  172.  
  173. PROCEDURE IncStk;
  174. BEGIN
  175.     INC(StkCnt);
  176.     MaxStkCnt := MAX(StkCnt, MaxStkCnt)
  177. END IncStk;
  178.  
  179.  
  180. PROCEDURE bw (b: BOOLEAN): INTEGER;
  181.     RETURN BW * ORD(b)
  182. END bw;
  183.  
  184.  
  185. PROCEDURE src_x (x, Rn: INTEGER): INTEGER;
  186. VAR
  187.     res: INTEGER;
  188.  
  189. BEGIN
  190.     IF (x = 0) & ~(Rn IN {PC, SR, CG}) THEN
  191.         res := Rn * 256 + sINDIR
  192.     ELSE
  193.         IdxWords.src := x;
  194.         res := Rn * 256 + sIDX
  195.     END
  196.  
  197.     RETURN res
  198. END src_x;
  199.  
  200.  
  201. PROCEDURE dst_x (x, Rn: INTEGER): INTEGER;
  202. BEGIN
  203.     IdxWords.dst := x
  204.     RETURN Rn + dIDX
  205. END dst_x;
  206.  
  207.  
  208. PROCEDURE indir (Rn: INTEGER): INTEGER;
  209.     RETURN Rn * 256 + sINDIR
  210. END indir;
  211.  
  212.  
  213. PROCEDURE incr (Rn: INTEGER): INTEGER;
  214.     RETURN Rn * 256 + sINCR
  215. END incr;
  216.  
  217.  
  218. PROCEDURE imm (x: INTEGER): INTEGER;
  219. VAR
  220.     res: INTEGER;
  221.  
  222. BEGIN
  223.     CASE x OF
  224.     | 0: res := CG * 256
  225.     | 1: res := CG * 256 + sIDX
  226.     | 2: res := indir(CG)
  227.     | 4: res := indir(SR)
  228.     | 8: res := incr(SR)
  229.     |-1: res := incr(CG)
  230.     ELSE
  231.         res := incr(PC);
  232.         IdxWords.src := x
  233.     END
  234.  
  235.     RETURN res
  236. END imm;
  237.  
  238.  
  239. PROCEDURE Op2 (op, src, dst: INTEGER);
  240. BEGIN
  241.     ASSERT(BITS(op) - {6, 12..15} = {});
  242.     ASSERT(BITS(src) - {4, 5, 8..11} = {});
  243.     ASSERT(BITS(dst) - {0..3, 7} = {});
  244.  
  245.     EmitWord(op + src + dst);
  246.  
  247.     IF IdxWords.src # NOWORD THEN
  248.         EmitWord(IdxWords.src);
  249.         IdxWords.src := NOWORD
  250.     END;
  251.  
  252.     IF IdxWords.dst # NOWORD THEN
  253.         EmitWord(IdxWords.dst);
  254.         IdxWords.dst := NOWORD
  255.     END
  256. END Op2;
  257.  
  258.  
  259. PROCEDURE Op1 (op, reg, As: INTEGER);
  260. BEGIN
  261.     EmitWord(op + reg + As)
  262. END Op1;
  263.  
  264.  
  265. PROCEDURE MovRR (src, dst: INTEGER);
  266. BEGIN
  267.     Op2(opMOV, src * 256, dst)
  268. END MovRR;
  269.  
  270.  
  271. PROCEDURE PushImm (imm: INTEGER);
  272. BEGIN
  273.     imm := UTILS.Long(imm);
  274.     CASE imm OF
  275.     | 0: Op1(opPUSH, CG, sREG)
  276.     | 1: Op1(opPUSH, CG, sIDX)
  277.     | 2: Op1(opPUSH, CG, sINDIR)
  278.     |-1: Op1(opPUSH, CG, sINCR)
  279.     ELSE
  280.         Op1(opPUSH, PC, sINCR);
  281.         EmitWord(imm)
  282.     END;
  283.     IncStk
  284. END PushImm;
  285.  
  286.  
  287. PROCEDURE PutWord (word: INTEGER; VAR adr: INTEGER);
  288. BEGIN
  289.     ASSERT(~ODD(adr));
  290.     ASSERT((0 <= word) & (word <= 65535));
  291.     mem[adr] := word MOD 256;
  292.     mem[adr + 1] := word DIV 256;
  293.     INC(adr, 2)
  294. END PutWord;
  295.  
  296.  
  297. PROCEDURE NewLabel (): INTEGER;
  298. BEGIN
  299.     CHL.PushInt(Labels, 0)
  300.     RETURN IL.NewLabel()
  301. END NewLabel;
  302.  
  303.  
  304. PROCEDURE LabelOffs (n: INTEGER): INTEGER;
  305.     RETURN CHL.GetInt(Labels, n)
  306. END LabelOffs;
  307.  
  308.  
  309. PROCEDURE Fixup (CodeAdr, IntVectorSize: INTEGER): INTEGER;
  310. VAR
  311.     cmd:      ANYCODE;
  312.     adr:      INTEGER;
  313.     offset:   INTEGER;
  314.     diff:     INTEGER;
  315.     cc:       INTEGER;
  316.     shorted:  BOOLEAN;
  317.  
  318. BEGIN
  319.     REPEAT
  320.         shorted := FALSE;
  321.         offset := CodeAdr DIV 2;
  322.  
  323.         cmd := CodeList.first(ANYCODE);
  324.         WHILE cmd # NIL DO
  325.             cmd.offset := offset;
  326.             CASE cmd OF
  327.             |LABEL: CHL.SetInt(Labels, cmd.num, offset)
  328.             |JMP:   INC(offset);
  329.                     IF ~cmd.short THEN
  330.                         INC(offset);
  331.                         IF cmd.cc # opJMP THEN
  332.                             INC(offset)
  333.                         END
  334.                     END
  335.  
  336.             |CALL:  INC(offset, 2)
  337.             |WORD:  INC(offset)
  338.             END;
  339.             cmd := cmd.next(ANYCODE)
  340.         END;
  341.  
  342.         cmd := CodeList.first(ANYCODE);
  343.         WHILE cmd # NIL DO
  344.             IF (cmd IS JMP) & ~cmd(JMP).short THEN
  345.                 diff := LabelOffs(cmd(JMP).label) - cmd.offset - 1;
  346.                 IF ABS(diff) <= 512 THEN
  347.                     cmd(JMP).short := TRUE;
  348.                     shorted := TRUE
  349.                 END
  350.             END;
  351.             cmd := cmd.next(ANYCODE)
  352.         END
  353.  
  354.     UNTIL ~shorted;
  355.  
  356.     IF offset * 2 > 10000H - IntVectorSize THEN
  357.         ERRORS.Error(203)
  358.     END;
  359.  
  360.     adr := CodeAdr;
  361.     cmd := CodeList.first(ANYCODE);
  362.     WHILE cmd # NIL DO
  363.         CASE cmd OF
  364.         |LABEL:
  365.  
  366.         |JMP:   IF ~cmd.short THEN
  367.                     CASE cmd.cc OF
  368.                     |opJNE: cc := opJEQ
  369.                     |opJEQ: cc := opJNE
  370.                     |opJNC: cc := opJC
  371.                     |opJC:  cc := opJNC
  372.                     |opJGE: cc := opJL
  373.                     |opJL:  cc := opJGE
  374.                     |opJMP: cc := opJMP
  375.                     END;
  376.  
  377.                     IF cc # opJMP THEN
  378.                         PutWord(cc + 2, adr)  (* jcc L *)
  379.                     END;
  380.  
  381.                     PutWord(4030H, adr); (* MOV @PC+, PC *)
  382.                     PutWord(LabelOffs(cmd.label) * 2, adr)
  383.                     (* L: *)
  384.                 ELSE
  385.                     diff := LabelOffs(cmd.label) - cmd.offset - 1;
  386.                     ASSERT((-512 <= diff) & (diff <= 511));
  387.                     PutWord(cmd.cc + diff MOD 1024, adr)
  388.                 END
  389.  
  390.         |CALL:  PutWord(12B0H, adr); (* CALL @PC+ *)
  391.                 PutWord(LabelOffs(cmd.label) * 2, adr)
  392.  
  393.         |WORD:  PutWord(cmd.val, adr)
  394.  
  395.         END;
  396.         cmd := cmd.next(ANYCODE)
  397.     END
  398.  
  399.     RETURN adr - CodeAdr
  400. END Fixup;
  401.  
  402.  
  403. PROCEDURE Push (reg: INTEGER);
  404. BEGIN
  405.     Op1(opPUSH, reg, sREG);
  406.     IncStk
  407. END Push;
  408.  
  409.  
  410. PROCEDURE Pop (reg: INTEGER);
  411. BEGIN
  412.     Op2(opMOV, incr(SP), reg);
  413.     DEC(StkCnt)
  414. END Pop;
  415.  
  416.  
  417. PROCEDURE Test (reg: INTEGER);
  418. BEGIN
  419.     Op2(opCMP, imm(0), reg)
  420. END Test;
  421.  
  422.  
  423. PROCEDURE Clear (reg: INTEGER);
  424. BEGIN
  425.     Op2(opMOV, imm(0), reg)
  426. END Clear;
  427.  
  428.  
  429. PROCEDURE mov (dst, src: INTEGER);
  430. BEGIN
  431.     MovRR(src, dst)
  432. END mov;
  433.  
  434.  
  435. PROCEDURE xchg (reg1, reg2: INTEGER);
  436. BEGIN
  437.     Push(reg1);
  438.     mov(reg1, reg2);
  439.     Pop(reg2)
  440. END xchg;
  441.  
  442.  
  443. PROCEDURE Reloc (section: INTEGER);
  444. VAR
  445.     reloc: RELOC;
  446.  
  447. BEGIN
  448.     NEW(reloc);
  449.     reloc.section := section;
  450.     reloc.WordPtr := CodeList.last(WORD);
  451.     LISTS.push(RelList, reloc)
  452. END Reloc;
  453.  
  454.  
  455. PROCEDURE CallRTL (proc, params: INTEGER);
  456. BEGIN
  457.     IncStk;
  458.     DEC(StkCnt);
  459.     EmitCall(RTL.rtl[proc].label);
  460.     RTL.Used(proc);
  461.     IF params > 0 THEN
  462.         Op2(opADD, imm(params * 2), SP);
  463.         DEC(StkCnt, params)
  464.     END
  465. END CallRTL;
  466.  
  467.  
  468. PROCEDURE UnOp (VAR reg: INTEGER);
  469. BEGIN
  470.     REG.UnOp(R, reg)
  471. END UnOp;
  472.  
  473.  
  474. PROCEDURE BinOp (VAR reg1, reg2: INTEGER);
  475. BEGIN
  476.     REG.BinOp(R, reg1, reg2)
  477. END BinOp;
  478.  
  479.  
  480. PROCEDURE GetRegA;
  481. BEGIN
  482.     ASSERT(REG.GetReg(R, ACC))
  483. END GetRegA;
  484.  
  485.  
  486. PROCEDURE drop;
  487. BEGIN
  488.     REG.Drop(R)
  489. END drop;
  490.  
  491.  
  492. PROCEDURE GetAnyReg (): INTEGER;
  493.     RETURN REG.GetAnyReg(R)
  494. END GetAnyReg;
  495.  
  496.  
  497. PROCEDURE PushAll (NumberOfParameters: INTEGER);
  498. BEGIN
  499.     REG.PushAll(R);
  500.     DEC(R.pushed, NumberOfParameters)
  501. END PushAll;
  502.  
  503.  
  504. PROCEDURE PushAll_1;
  505. BEGIN
  506.     REG.PushAll_1(R)
  507. END PushAll_1;
  508.  
  509.  
  510. PROCEDURE cond (op: INTEGER): INTEGER;
  511. VAR
  512.     res: INTEGER;
  513.  
  514. BEGIN
  515.     CASE op OF
  516.     |IL.opGT, IL.opGTC: res := jg
  517.     |IL.opGE, IL.opGEC: res := jge
  518.     |IL.opLT, IL.opLTC: res := jl
  519.     |IL.opLE, IL.opLEC: res := jle
  520.     |IL.opEQ, IL.opEQC: res := je
  521.     |IL.opNE, IL.opNEC: res := jne
  522.     END
  523.  
  524.     RETURN res
  525. END cond;
  526.  
  527.  
  528. PROCEDURE jcc (cc, label: INTEGER);
  529. VAR
  530.     L: INTEGER;
  531.  
  532. BEGIN
  533.     CASE cc OF
  534.     |jne:
  535.         EmitJmp(opJNE, label)
  536.     |je:
  537.         EmitJmp(opJEQ, label)
  538.     |jge:
  539.         EmitJmp(opJGE, label)
  540.     |jl:
  541.         EmitJmp(opJL, label)
  542.     |jle:
  543.         EmitJmp(opJL, label);
  544.         EmitJmp(opJEQ, label)
  545.     |jg:
  546.         L := NewLabel();
  547.         EmitJmp(opJEQ, L);
  548.         EmitJmp(opJGE, label);
  549.         EmitLabel(L)
  550.     |jb:
  551.         EmitJmp(opJNC, label)
  552.     END
  553. END jcc;
  554.  
  555.  
  556. PROCEDURE setcc (cc, reg: INTEGER);
  557. VAR
  558.     L: INTEGER;
  559.  
  560. BEGIN
  561.     L := NewLabel();
  562.     Op2(opMOV, imm(1), reg);
  563.     jcc(cc, L);
  564.     Clear(reg);
  565.     EmitLabel(L)
  566. END setcc;
  567.  
  568.  
  569. PROCEDURE Shift2 (op, reg, n: INTEGER);
  570. VAR
  571.     reg2: INTEGER;
  572.  
  573. BEGIN
  574.     IF n >= 8 THEN
  575.         CASE op OF
  576.         |IL.opASR2: Op1(opSWPB, reg, sREG); Op1(opSXT, reg, sREG)
  577.         |IL.opROR2: Op1(opSWPB, reg, sREG)
  578.         |IL.opLSL2: Op1(opSWPB, reg, sREG); Op2(opBIC, imm(255), reg)
  579.         |IL.opLSR2: Op2(opBIC, imm(255), reg); Op1(opSWPB, reg, sREG)
  580.         END;
  581.         DEC(n, 8)
  582.     END;
  583.  
  584.     IF (op = IL.opROR2) & (n > 0) THEN
  585.         reg2 := GetAnyReg();
  586.         MovRR(reg, reg2)
  587.     ELSE
  588.         reg2 := -1
  589.     END;
  590.  
  591.     WHILE n > 0 DO
  592.         CASE op OF
  593.         |IL.opASR2: Op1(opRRA, reg, sREG)
  594.         |IL.opROR2: Op1(opRRC, reg2, sREG); Op1(opRRC, reg, sREG)
  595.         |IL.opLSL2: Op2(opADD, reg * 256, reg)
  596.         |IL.opLSR2: Op2(opBIC, imm(1), SR); Op1(opRRC, reg, sREG)
  597.         END;
  598.         DEC(n)
  599.     END;
  600.  
  601.     IF reg2 # -1 THEN
  602.         drop
  603.     END
  604.  
  605. END Shift2;
  606.  
  607.  
  608. PROCEDURE Neg (reg: INTEGER);
  609. BEGIN
  610.     Op2(opXOR, imm(-1), reg);
  611.     Op2(opADD, imm(1), reg)
  612. END Neg;
  613.  
  614.  
  615. PROCEDURE LocalOffset (offset: INTEGER): INTEGER;
  616.     RETURN (offset + StkCnt - ORD(offset > 0)) * 2
  617. END LocalOffset;
  618.  
  619.  
  620. PROCEDURE LocalDst (offset: INTEGER): INTEGER;
  621.     RETURN dst_x(LocalOffset(offset), SP)
  622. END LocalDst;
  623.  
  624.  
  625. PROCEDURE LocalSrc (offset: INTEGER): INTEGER;
  626.     RETURN src_x(LocalOffset(offset), SP)
  627. END LocalSrc;
  628.  
  629.  
  630. PROCEDURE translate (chk_stk: BOOLEAN);
  631. VAR
  632.     cmd, next: COMMAND;
  633.  
  634.     opcode, param1, param2, L, a, n, c1, c2: INTEGER;
  635.  
  636.     reg1, reg2: INTEGER;
  637.  
  638.     cc: INTEGER;
  639.  
  640.     word: WORD;
  641.  
  642. BEGIN
  643.     cmd := IL.codes.commands.first(COMMAND);
  644.  
  645.     WHILE cmd # NIL DO
  646.  
  647.         param1 := cmd.param1;
  648.         param2 := cmd.param2;
  649.  
  650.         opcode := cmd.opcode;
  651.  
  652.         CASE opcode OF
  653.         |IL.opJMP:
  654.             EmitJmp(opJMP, param1)
  655.  
  656.         |IL.opCALL:
  657.             IncStk;
  658.             DEC(StkCnt);
  659.             EmitCall(param1)
  660.  
  661.         |IL.opCALLP:
  662.             IncStk;
  663.             DEC(StkCnt);
  664.             UnOp(reg1);
  665.             Op1(opCALL, reg1, sREG);
  666.             drop;
  667.             ASSERT(R.top = -1)
  668.  
  669.         |IL.opPRECALL:
  670.             PushAll(0)
  671.  
  672.         |IL.opLABEL:
  673.             EmitLabel(param1)
  674.  
  675.         |IL.opSADR_PARAM:
  676.             Op1(opPUSH, PC, sINCR);
  677.             IncStk;
  678.             EmitWord(param2);
  679.             Reloc(RDATA)
  680.  
  681.         |IL.opERR:
  682.             CallRTL(RTL._error, 2)
  683.  
  684.         |IL.opPUSHC:
  685.             PushImm(param2)
  686.  
  687.         |IL.opONERR:
  688.             DEC(StkCnt);
  689.             EmitWord(0C232H); (*  BIC   #8, SR; DINT  *)
  690.             EmitWord(4303H);  (*  MOV   R3, R3; NOP   *)
  691.             PushImm(param2);
  692.             EmitJmp(opJMP, param1)
  693.  
  694.         |IL.opLEAVEC:
  695.             Pop(PC)
  696.  
  697.         |IL.opENTER:
  698.             ASSERT(R.top = -1);
  699.             EmitLabel(param1);
  700.             n := param2 MOD 65536;
  701.             param2 := param2 DIV 65536;
  702.             StkCnt := 0;
  703.             IF chk_stk THEN
  704.                 L := NewLabel();
  705.                 Op2(opMOV, SP * 256, R4);
  706.                 Op2(opSUB, HP * 256, R4);
  707.                 Op2(opCMP, imm(StkReserve), R4);
  708.                 word := CodeList.last(WORD);
  709.                 jcc(jge, L);
  710.                 DEC(StkCnt);
  711.                 EmitWord(0C232H); (*  BIC   #8, SR; DINT  *)
  712.                 EmitWord(4303H);  (*  MOV   R3, R3; NOP   *)
  713.                 PushImm(n);
  714.                 EmitJmp(opJMP, cmd.param3);
  715.                 EmitLabel(L)
  716.             END;
  717.  
  718.             IF param2 > 8 THEN
  719.                 Op2(opMOV, imm(param2), R4);
  720.                 L := NewLabel();
  721.                 EmitLabel(L);
  722.                 Push(CG);
  723.                 Op2(opSUB, imm(1), R4);
  724.                 jcc(jne, L)
  725.             ELSE
  726.                 FOR n := 1 TO param2 DO
  727.                     Push(CG)
  728.                 END
  729.             END;
  730.             StkCnt := param2;
  731.             MaxStkCnt := StkCnt
  732.  
  733.         |IL.opLEAVE, IL.opLEAVER:
  734.             ASSERT(param2 = 0);
  735.             IF opcode = IL.opLEAVER THEN
  736.                 UnOp(reg1);
  737.                 IF reg1 # ACC THEN
  738.                     mov(ACC, reg1)
  739.                 END;
  740.                 drop
  741.             END;
  742.             ASSERT(R.top = -1);
  743.             ASSERT(StkCnt = param1);
  744.             IF chk_stk THEN
  745.                 INC(word.val, MaxStkCnt * 2)
  746.             END;
  747.             IF param1 > 0 THEN
  748.                 Op2(opADD, imm(param1 * 2), SP)
  749.             END;
  750.             Pop(PC)
  751.  
  752.         |IL.opRES:
  753.             ASSERT(R.top = -1);
  754.             GetRegA
  755.  
  756.         |IL.opCLEANUP:
  757.             IF param2 # 0 THEN
  758.                 Op2(opADD, imm(param2 * 2), SP);
  759.                 DEC(StkCnt, param2)
  760.             END
  761.  
  762.         |IL.opCONST:
  763.             next := cmd.next(COMMAND);
  764.             IF next.opcode = IL.opCONST THEN
  765.                 c1 := param2;
  766.                 c2 := next.param2;
  767.                 next := next.next(COMMAND);
  768.                 IF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
  769.                     Op2(opMOV + bw(next.opcode = IL.opSAVE8), imm(c1), dst_x(c2, SR));
  770.                     cmd := next
  771.                 ELSE
  772.                     Op2(opMOV, imm(param2), GetAnyReg())
  773.                 END
  774.             ELSIF (next.opcode = IL.opSAVE) OR (next.opcode = IL.opSAVE16) OR (next.opcode = IL.opSAVE8) THEN
  775.                 UnOp(reg1);
  776.                 Op2(opMOV + bw(next.opcode = IL.opSAVE8), reg1 * 256, dst_x(param2, SR));
  777.                 drop;
  778.                 cmd := next
  779.             ELSE
  780.                 Op2(opMOV, imm(param2), GetAnyReg())
  781.             END
  782.  
  783.         |IL.opSADR:
  784.             Op2(opMOV, incr(PC), GetAnyReg());
  785.             EmitWord(param2);
  786.             Reloc(RDATA)
  787.  
  788.         |IL.opGADR:
  789.             Op2(opMOV, incr(PC), GetAnyReg());
  790.             EmitWord(param2);
  791.             Reloc(RBSS)
  792.  
  793.         |IL.opLADR:
  794.             reg1 := GetAnyReg();
  795.             n := LocalOffset(param2);
  796.             Op2(opMOV, SP * 256, reg1);
  797.             IF n # 0 THEN
  798.                 Op2(opADD, imm(n), reg1)
  799.             END
  800.  
  801.         |IL.opLLOAD8:
  802.             Op2(opMOV + BW, LocalSrc(param2), GetAnyReg())
  803.  
  804.         |IL.opLLOAD16, IL.opVADR:
  805.             Op2(opMOV, LocalSrc(param2), GetAnyReg())
  806.  
  807.         |IL.opGLOAD8:
  808.             Op2(opMOV + BW, src_x(param2, SR), GetAnyReg());
  809.             Reloc(RBSS)
  810.  
  811.         |IL.opGLOAD16:
  812.             Op2(opMOV, src_x(param2, SR), GetAnyReg());
  813.             Reloc(RBSS)
  814.  
  815.         |IL.opLOAD8:
  816.             UnOp(reg1);
  817.             Op2(opMOV + BW, indir(reg1), reg1)
  818.  
  819.         |IL.opLOAD16:
  820.             UnOp(reg1);
  821.             Op2(opMOV, indir(reg1), reg1)
  822.  
  823.         |IL.opVLOAD8:
  824.             reg1 := GetAnyReg();
  825.             Op2(opMOV, LocalSrc(param2), reg1);
  826.             Op2(opMOV + BW, indir(reg1), reg1)
  827.  
  828.         |IL.opVLOAD16:
  829.             reg1 := GetAnyReg();
  830.             Op2(opMOV, LocalSrc(param2), reg1);
  831.             Op2(opMOV, indir(reg1), reg1)
  832.  
  833.         |IL.opSAVE, IL.opSAVE16:
  834.             BinOp(reg2, reg1);
  835.             Op2(opMOV, reg2 * 256, dst_x(0, reg1));
  836.             drop;
  837.             drop
  838.  
  839.         |IL.opSAVE8:
  840.             BinOp(reg2, reg1);
  841.             Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
  842.             drop;
  843.             drop
  844.  
  845.         |IL.opSAVE8C:
  846.             UnOp(reg1);
  847.             Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
  848.             drop
  849.  
  850.         |IL.opSAVE16C, IL.opSAVEC:
  851.             UnOp(reg1);
  852.             Op2(opMOV, imm(param2), dst_x(0, reg1));
  853.             drop
  854.  
  855.         |IL.opUMINUS:
  856.             UnOp(reg1);
  857.             Neg(reg1)
  858.  
  859.         |IL.opADD:
  860.             BinOp(reg1, reg2);
  861.             Op2(opADD, reg2 * 256, reg1);
  862.             drop
  863.  
  864.         |IL.opADDC:
  865.             IF param2 # 0 THEN
  866.                 UnOp(reg1);
  867.                 Op2(opADD, imm(param2), reg1)
  868.             END
  869.  
  870.         |IL.opSUB:
  871.             BinOp(reg1, reg2);
  872.             Op2(opSUB, reg2 * 256, reg1);
  873.             drop
  874.  
  875.         |IL.opSUBR, IL.opSUBL:
  876.             UnOp(reg1);
  877.             IF param2 # 0 THEN
  878.                 Op2(opSUB, imm(param2), reg1)
  879.             END;
  880.             IF opcode = IL.opSUBL THEN
  881.                 Neg(reg1)
  882.             END
  883.  
  884.         |IL.opLADR_SAVEC:
  885.             Op2(opMOV, imm(param2), LocalDst(param1))
  886.  
  887.         |IL.opLADR_SAVE:
  888.             UnOp(reg1);
  889.             Op2(opMOV, reg1 * 256, LocalDst(param2));
  890.             drop
  891.  
  892.         |IL.opGADR_SAVEC:
  893.             Op2(opMOV, imm(param2), dst_x(param1, SR));
  894.             Reloc(RBSS)
  895.  
  896.         |IL.opCONST_PARAM:
  897.             PushImm(param2)
  898.  
  899.         |IL.opPARAM:
  900.             IF param2 = 1 THEN
  901.                 UnOp(reg1);
  902.                 Push(reg1);
  903.                 drop
  904.             ELSE
  905.                 ASSERT(R.top + 1 <= param2);
  906.                 PushAll(param2)
  907.             END
  908.  
  909.         |IL.opEQ..IL.opGE,
  910.          IL.opEQC..IL.opGEC:
  911.  
  912.             IF (IL.opEQ <= opcode) & (opcode <= IL.opGE) THEN
  913.                 BinOp(reg1, reg2);
  914.                 Op2(opCMP, reg2 * 256, reg1);
  915.                 drop
  916.             ELSE
  917.                 UnOp(reg1);
  918.                 Op2(opCMP, imm(param2), reg1)
  919.             END;
  920.  
  921.             drop;
  922.             cc := cond(opcode);
  923.             next := cmd.next(COMMAND);
  924.  
  925.             IF next.opcode = IL.opJNZ THEN
  926.                 jcc(cc, next.param1);
  927.                 cmd := next
  928.             ELSIF next.opcode = IL.opJZ THEN
  929.                 jcc(ORD(BITS(cc) / {0}), next.param1);
  930.                 cmd := next
  931.             ELSE
  932.                 setcc(cc, GetAnyReg())
  933.             END
  934.  
  935.         |IL.opNOP, IL.opAND, IL.opOR:
  936.  
  937.         |IL.opCODE:
  938.             EmitWord(param2)
  939.  
  940.         |IL.opDROP:
  941.             UnOp(reg1);
  942.             drop
  943.  
  944.         |IL.opJNZ1:
  945.             UnOp(reg1);
  946.             Test(reg1);
  947.             jcc(jne, param1)
  948.  
  949.         |IL.opJG:
  950.             UnOp(reg1);
  951.             Test(reg1);
  952.             jcc(jg, param1)
  953.  
  954.         |IL.opJNZ:
  955.             UnOp(reg1);
  956.             Test(reg1);
  957.             jcc(jne, param1);
  958.             drop
  959.  
  960.         |IL.opJZ:
  961.             UnOp(reg1);
  962.             Test(reg1);
  963.             jcc(je, param1);
  964.             drop
  965.  
  966.         |IL.opNOT:
  967.             UnOp(reg1);
  968.             Test(reg1);
  969.             setcc(je, reg1)
  970.  
  971.         |IL.opORD:
  972.             UnOp(reg1);
  973.             Test(reg1);
  974.             setcc(jne, reg1)
  975.  
  976.         |IL.opGET:
  977.             BinOp(reg1, reg2);
  978.             drop;
  979.             drop;
  980.             Op2(opMOV + bw(param2 = 1), indir(reg1), dst_x(0, reg2))
  981.  
  982.         |IL.opGETC:
  983.             UnOp(reg2);
  984.             drop;
  985.             Op2(opMOV + bw(param2 = 1), src_x(param1, SR), dst_x(0, reg2))
  986.  
  987.         |IL.opCHKBYTE:
  988.             BinOp(reg1, reg2);
  989.             Op2(opCMP, imm(256), reg1);
  990.             jcc(jb, param1)
  991.  
  992.         |IL.opCHKIDX:
  993.             UnOp(reg1);
  994.             Op2(opCMP, imm(param2), reg1);
  995.             jcc(jb, param1)
  996.  
  997.         |IL.opCHKIDX2:
  998.             BinOp(reg1, reg2);
  999.             IF param2 # -1 THEN
  1000.                 Op2(opCMP, reg1 * 256, reg2);
  1001.                 jcc(jb, param1)
  1002.             END;
  1003.             INCL(R.regs, reg1);
  1004.             DEC(R.top);
  1005.             R.stk[R.top] := reg2
  1006.  
  1007.         |IL.opINCC, IL.opINCCB:
  1008.             UnOp(reg1);
  1009.             Op2(opADD + bw(opcode = IL.opINCCB), imm(param2), dst_x(0, reg1));
  1010.             drop
  1011.  
  1012.         |IL.opDECCB:
  1013.             UnOp(reg1);
  1014.             Op2(opSUB + BW, imm(param2), dst_x(0, reg1));
  1015.             drop
  1016.  
  1017.         |IL.opINC, IL.opINCB:
  1018.             BinOp(reg1, reg2);
  1019.             Op2(opADD + bw(opcode = IL.opINCB), reg1 * 256, dst_x(0, reg2));
  1020.             drop;
  1021.             drop
  1022.  
  1023.         |IL.opDEC, IL.opDECB:
  1024.             BinOp(reg1, reg2);
  1025.             Op2(opSUB + bw(opcode = IL.opDECB), reg1 * 256, dst_x(0, reg2));
  1026.             drop;
  1027.             drop
  1028.  
  1029.         |IL.opLADR_INCC, IL.opLADR_INCCB:
  1030.             Op2(opADD + bw(opcode = IL.opLADR_INCCB), imm(param2), LocalDst(param1))
  1031.  
  1032.         |IL.opLADR_DECCB:
  1033.             Op2(opSUB + BW, imm(param2), LocalDst(param1))
  1034.  
  1035.         |IL.opLADR_INC, IL.opLADR_INCB:
  1036.             UnOp(reg1);
  1037.             Op2(opADD + bw(opcode = IL.opLADR_INCB), reg1 * 256, LocalDst(param2));
  1038.             drop
  1039.  
  1040.         |IL.opLADR_DEC, IL.opLADR_DECB:
  1041.             UnOp(reg1);
  1042.             Op2(opSUB + bw(opcode = IL.opLADR_DECB), reg1 * 256, LocalDst(param2));
  1043.             drop
  1044.  
  1045.         |IL.opPUSHT:
  1046.             UnOp(reg1);
  1047.             Op2(opMOV, src_x(-2, reg1), GetAnyReg())
  1048.  
  1049.         |IL.opISREC:
  1050.             PushAll(2);
  1051.             PushImm(param2);
  1052.             CallRTL(RTL._guardrec, 3);
  1053.             GetRegA
  1054.  
  1055.         |IL.opIS:
  1056.             PushAll(1);
  1057.             PushImm(param2);
  1058.             CallRTL(RTL._is, 2);
  1059.             GetRegA
  1060.  
  1061.         |IL.opTYPEGR:
  1062.             PushAll(1);
  1063.             PushImm(param2);
  1064.             CallRTL(RTL._guardrec, 2);
  1065.             GetRegA
  1066.  
  1067.         |IL.opTYPEGP:
  1068.             UnOp(reg1);
  1069.             PushAll(0);
  1070.             Push(reg1);
  1071.             PushImm(param2);
  1072.             CallRTL(RTL._guard, 2);
  1073.             GetRegA
  1074.  
  1075.         |IL.opTYPEGD:
  1076.             UnOp(reg1);
  1077.             PushAll(0);
  1078.             Op1(opPUSH, reg1, sIDX);
  1079.             IncStk;
  1080.             EmitWord(-2);
  1081.             PushImm(param2);
  1082.             CallRTL(RTL._guardrec, 2);
  1083.             GetRegA
  1084.  
  1085.         |IL.opMULS:
  1086.             BinOp(reg1, reg2);
  1087.             Op2(opAND, reg2 * 256, reg1);
  1088.             drop
  1089.  
  1090.         |IL.opMULSC:
  1091.             UnOp(reg1);
  1092.             Op2(opAND, imm(param2), reg1)
  1093.  
  1094.         |IL.opDIVS:
  1095.             BinOp(reg1, reg2);
  1096.             Op2(opXOR, reg2 * 256, reg1);
  1097.             drop
  1098.  
  1099.         |IL.opDIVSC:
  1100.             UnOp(reg1);
  1101.             Op2(opXOR, imm(param2), reg1)
  1102.  
  1103.         |IL.opADDS:
  1104.             BinOp(reg1, reg2);
  1105.             Op2(opBIS, reg2 * 256, reg1);
  1106.             drop
  1107.  
  1108.         |IL.opSUBS:
  1109.             BinOp(reg1, reg2);
  1110.             Op2(opBIC, reg2 * 256, reg1);
  1111.             drop
  1112.  
  1113.         |IL.opADDSC:
  1114.             UnOp(reg1);
  1115.             Op2(opBIS, imm(param2), reg1)
  1116.  
  1117.         |IL.opSUBSL:
  1118.             UnOp(reg1);
  1119.             Op2(opXOR, imm(-1), reg1);
  1120.             Op2(opAND, imm(param2), reg1)
  1121.  
  1122.         |IL.opSUBSR:
  1123.             UnOp(reg1);
  1124.             Op2(opBIC, imm(param2), reg1)
  1125.  
  1126.         |IL.opUMINS:
  1127.             UnOp(reg1);
  1128.             Op2(opXOR, imm(-1), reg1)
  1129.  
  1130.         |IL.opLENGTH:
  1131.             PushAll(2);
  1132.             CallRTL(RTL._length, 2);
  1133.             GetRegA
  1134.  
  1135.         |IL.opMAX,IL.opMIN:
  1136.             BinOp(reg1, reg2);
  1137.             Op2(opCMP, reg2 * 256, reg1);
  1138.             IF opcode = IL.opMIN THEN
  1139.                 cc := opJL + 1
  1140.             ELSE
  1141.                 cc := opJGE + 1
  1142.             END;
  1143.             EmitWord(cc);        (* jge/jl L *)
  1144.             MovRR(reg2, reg1);
  1145.                                  (* L: *)
  1146.             drop
  1147.  
  1148.         |IL.opMAXC, IL.opMINC:
  1149.             UnOp(reg1);
  1150.             Op2(opCMP, imm(param2), reg1);
  1151.             L := NewLabel();
  1152.             IF opcode = IL.opMINC THEN
  1153.                 cc := jl
  1154.             ELSE
  1155.                 cc := jge
  1156.             END;
  1157.             jcc(cc, L);
  1158.             Op2(opMOV, imm(param2), reg1);
  1159.             EmitLabel(L)
  1160.  
  1161.         |IL.opSWITCH:
  1162.             UnOp(reg1);
  1163.             IF param2 = 0 THEN
  1164.                 reg2 := ACC
  1165.             ELSE
  1166.                 reg2 := R5
  1167.             END;
  1168.             IF reg1 # reg2 THEN
  1169.                 ASSERT(REG.GetReg(R, reg2));
  1170.                 ASSERT(REG.Exchange(R, reg1, reg2));
  1171.                 drop
  1172.             END;
  1173.             drop
  1174.  
  1175.         |IL.opENDSW:
  1176.  
  1177.         |IL.opCASEL:
  1178.             Op2(opCMP, imm(param1), ACC);
  1179.             jcc(jl, param2)
  1180.  
  1181.         |IL.opCASER:
  1182.             Op2(opCMP, imm(param1), ACC);
  1183.             jcc(jg, param2)
  1184.  
  1185.         |IL.opCASELR:
  1186.             Op2(opCMP, imm(param1), ACC);
  1187.             IF param2 = cmd.param3 THEN
  1188.                 jcc(jne, param2)
  1189.             ELSE
  1190.                 jcc(jl, param2);
  1191.                 jcc(jg, cmd.param3)
  1192.             END
  1193.  
  1194.         |IL.opSBOOL:
  1195.             BinOp(reg2, reg1);
  1196.             Test(reg2);
  1197.             setcc(jne, reg2);
  1198.             Op2(opMOV + BW, reg2 * 256, dst_x(0, reg1));
  1199.             drop;
  1200.             drop
  1201.  
  1202.         |IL.opSBOOLC:
  1203.             UnOp(reg1);
  1204.             Op2(opMOV + BW, imm(param2), dst_x(0, reg1));
  1205.             drop
  1206.  
  1207.         |IL.opEQS .. IL.opGES:
  1208.             PushAll(4);
  1209.             PushImm((opcode - IL.opEQS) * 12);
  1210.             CallRTL(RTL._strcmp, 5);
  1211.             GetRegA
  1212.  
  1213.         |IL.opLEN:
  1214.             UnOp(reg1);
  1215.             drop;
  1216.             EXCL(R.regs, reg1);
  1217.  
  1218.             WHILE param2 > 0 DO
  1219.                 UnOp(reg2);
  1220.                 drop;
  1221.                 DEC(param2)
  1222.             END;
  1223.  
  1224.             INCL(R.regs, reg1);
  1225.             ASSERT(REG.GetReg(R, reg1))
  1226.  
  1227.         |IL.opLSL, IL.opASR, IL.opROR, IL.opLSR:
  1228.             PushAll(2);
  1229.             CASE opcode OF
  1230.             |IL.opLSL: CallRTL(RTL._lsl, 2)
  1231.             |IL.opASR: CallRTL(RTL._asr, 2)
  1232.             |IL.opROR: CallRTL(RTL._ror, 2)
  1233.             |IL.opLSR: CallRTL(RTL._lsr, 2)
  1234.             END;
  1235.             GetRegA
  1236.  
  1237.         |IL.opLSL1, IL.opASR1, IL.opROR1, IL.opLSR1:
  1238.             UnOp(reg1);
  1239.             PushAll_1;
  1240.             PushImm(param2);
  1241.             Push(reg1);
  1242.             drop;
  1243.             CASE opcode OF
  1244.             |IL.opLSL1: CallRTL(RTL._lsl, 2)
  1245.             |IL.opASR1: CallRTL(RTL._asr, 2)
  1246.             |IL.opROR1: CallRTL(RTL._ror, 2)
  1247.             |IL.opLSR1: CallRTL(RTL._lsr, 2)
  1248.             END;
  1249.             GetRegA
  1250.  
  1251.         |IL.opASR2, IL.opROR2, IL.opLSL2, IL.opLSR2:
  1252.             param2 := param2 MOD 16;
  1253.             IF param2 # 0 THEN
  1254.                 UnOp(reg1);
  1255.                 Shift2(opcode, reg1, param2)
  1256.             END
  1257.  
  1258.         |IL.opMUL:
  1259.             PushAll(2);
  1260.             CallRTL(RTL._mul, 2);
  1261.             GetRegA
  1262.  
  1263.         |IL.opMULC:
  1264.             UnOp(reg1);
  1265.  
  1266.             a := param2;
  1267.             IF a > 1 THEN
  1268.                 n := UTILS.Log2(a)
  1269.             ELSIF a < -1 THEN
  1270.                 n := UTILS.Log2(-a)
  1271.             ELSE
  1272.                 n := -1
  1273.             END;
  1274.  
  1275.             IF a = 1 THEN
  1276.  
  1277.             ELSIF a = -1 THEN
  1278.                 Neg(reg1)
  1279.             ELSIF a = 0 THEN
  1280.                 Clear(reg1)
  1281.             ELSE
  1282.                 IF n > 0 THEN
  1283.                     IF a < 0 THEN
  1284.                         Neg(reg1)
  1285.                     END;
  1286.                     Shift2(IL.opLSL2, reg1, n)
  1287.                 ELSE
  1288.                     PushAll(1);
  1289.                     PushImm(a);
  1290.                     CallRTL(RTL._mul, 2);
  1291.                     GetRegA
  1292.                 END
  1293.             END
  1294.  
  1295.         |IL.opDIV:
  1296.             PushAll(2);
  1297.             CallRTL(RTL._divmod, 2);
  1298.             GetRegA
  1299.  
  1300.         |IL.opDIVR:
  1301.             ASSERT(param2 > 0);
  1302.  
  1303.             IF param2 > 1 THEN
  1304.                 n := UTILS.Log2(param2);
  1305.                 IF n > 0 THEN
  1306.                     UnOp(reg1);
  1307.                     Shift2(IL.opASR2, reg1, n)
  1308.                 ELSE
  1309.                     PushAll(1);
  1310.                     PushImm(param2);
  1311.                     CallRTL(RTL._divmod, 2);
  1312.                     GetRegA
  1313.                 END
  1314.             END
  1315.  
  1316.         |IL.opDIVL:
  1317.             UnOp(reg1);
  1318.             PushAll_1;
  1319.             PushImm(param2);
  1320.             Push(reg1);
  1321.             drop;
  1322.             CallRTL(RTL._divmod, 2);
  1323.             GetRegA
  1324.  
  1325.         |IL.opMOD:
  1326.             PushAll(2);
  1327.             CallRTL(RTL._divmod, 2);
  1328.             ASSERT(REG.GetReg(R, R5))
  1329.  
  1330.         |IL.opMODR:
  1331.             ASSERT(param2 > 0);
  1332.  
  1333.             IF param2 = 1 THEN
  1334.                 UnOp(reg1);
  1335.                 Clear(reg1)
  1336.             ELSE
  1337.                 IF UTILS.Log2(param2) > 0 THEN
  1338.                     UnOp(reg1);
  1339.                     Op2(opAND, imm(param2 - 1), reg1)
  1340.                 ELSE
  1341.                     PushAll(1);
  1342.                     PushImm(param2);
  1343.                     CallRTL(RTL._divmod, 2);
  1344.                     ASSERT(REG.GetReg(R, R5))
  1345.                 END
  1346.             END
  1347.  
  1348.         |IL.opMODL:
  1349.             UnOp(reg1);
  1350.             PushAll_1;
  1351.             PushImm(param2);
  1352.             Push(reg1);
  1353.             drop;
  1354.             CallRTL(RTL._divmod, 2);
  1355.             ASSERT(REG.GetReg(R, R5))
  1356.  
  1357.         |IL.opCOPYS:
  1358.             ASSERT(R.top = 3);
  1359.             Push(R.stk[2]);
  1360.             Push(R.stk[0]);
  1361.             Op2(opCMP, R.stk[1] * 256, R.stk[3]);
  1362.             EmitWord(3801H); (* JL L1 *)
  1363.             MovRR(R.stk[1], R.stk[3]);
  1364.                              (* L1:   *)
  1365.             Push(R.stk[3]);
  1366.             drop;
  1367.             drop;
  1368.             drop;
  1369.             drop;
  1370.             CallRTL(RTL._move, 3)
  1371.  
  1372.         |IL.opCOPY:
  1373.             PushAll(2);
  1374.             PushImm(param2);
  1375.             CallRTL(RTL._move, 3)
  1376.  
  1377.         |IL.opMOVE:
  1378.             PushAll(3);
  1379.             CallRTL(RTL._move, 3)
  1380.  
  1381.         |IL.opCOPYA:
  1382.             PushAll(4);
  1383.             PushImm(param2);
  1384.             CallRTL(RTL._arrcpy, 5);
  1385.             GetRegA
  1386.  
  1387.         |IL.opROT:
  1388.             PushAll(0);
  1389.             MovRR(SP, ACC);
  1390.             Push(ACC);
  1391.             PushImm(param2);
  1392.             CallRTL(RTL._rot, 2)
  1393.  
  1394.         |IL.opSAVES:
  1395.             UnOp(reg1);
  1396.             PushAll_1;
  1397.             Op1(opPUSH, PC, sINCR);
  1398.             IncStk;
  1399.             EmitWord(param2);
  1400.             Reloc(RDATA);
  1401.             Push(reg1);
  1402.             drop;
  1403.             PushImm(param1);
  1404.             CallRTL(RTL._move, 3)
  1405.  
  1406.         |IL.opCASET:
  1407.             Push(R5);
  1408.             Push(R5);
  1409.             PushImm(param2);
  1410.             CallRTL(RTL._guardrec, 2);
  1411.             Pop(R5);
  1412.             Test(ACC);
  1413.             jcc(jne, param1)
  1414.  
  1415.         |IL.opCHR:
  1416.             UnOp(reg1);
  1417.             Op2(opAND, imm(255), reg1)
  1418.  
  1419.         |IL.opABS:
  1420.             UnOp(reg1);
  1421.             Test(reg1);
  1422.             L := NewLabel();
  1423.             jcc(jge, L);
  1424.             Neg(reg1);
  1425.             EmitLabel(L)
  1426.  
  1427.         |IL.opEQB, IL.opNEB:
  1428.             BinOp(reg1, reg2);
  1429.             drop;
  1430.  
  1431.             Test(reg1);
  1432.             L := NewLabel();
  1433.             jcc(je, L);
  1434.             Op2(opMOV, imm(1), reg1);
  1435.             EmitLabel(L);
  1436.  
  1437.             Test(reg2);
  1438.             L := NewLabel();
  1439.             jcc(je, L);
  1440.             Op2(opMOV, imm(1), reg2);
  1441.             EmitLabel(L);
  1442.  
  1443.             Op2(opCMP, reg2 * 256, reg1);
  1444.             IF opcode = IL.opEQB THEN
  1445.                 setcc(je, reg1)
  1446.             ELSE
  1447.                 setcc(jne, reg1)
  1448.             END
  1449.  
  1450.         |IL.opSAVEP:
  1451.             UnOp(reg1);
  1452.             Op2(opMOV, incr(PC), reg1 + dIDX);
  1453.             EmitWord(param2);
  1454.             Reloc(RCODE);
  1455.             EmitWord(0);
  1456.             drop
  1457.  
  1458.         |IL.opPUSHP:
  1459.             Op2(opMOV, incr(PC), GetAnyReg());
  1460.             EmitWord(param2);
  1461.             Reloc(RCODE)
  1462.  
  1463.         |IL.opEQP, IL.opNEP:
  1464.             UnOp(reg1);
  1465.             Op2(opCMP, incr(PC), reg1);
  1466.             EmitWord(param1);
  1467.             Reloc(RCODE);
  1468.             drop;
  1469.             reg1 := GetAnyReg();
  1470.  
  1471.             IF opcode = IL.opEQP THEN
  1472.                 setcc(je, reg1)
  1473.             ELSIF opcode = IL.opNEP THEN
  1474.                 setcc(jne, reg1)
  1475.             END
  1476.  
  1477.         |IL.opVADR_PARAM:
  1478.             reg1 := GetAnyReg();
  1479.             Op2(opMOV, LocalSrc(param2), reg1);
  1480.             Push(reg1);
  1481.             drop
  1482.  
  1483.         |IL.opNEW:
  1484.             PushAll(1);
  1485.             n := param2 + 2;
  1486.             ASSERT(UTILS.Align(n, 2));
  1487.             PushImm(n);
  1488.             PushImm(param1);
  1489.             CallRTL(RTL._new, 3)
  1490.  
  1491.         |IL.opRSET:
  1492.             PushAll(2);
  1493.             CallRTL(RTL._set, 2);
  1494.             GetRegA
  1495.  
  1496.         |IL.opRSETR:
  1497.             PushAll(1);
  1498.             PushImm(param2);
  1499.             CallRTL(RTL._set, 2);
  1500.             GetRegA
  1501.  
  1502.         |IL.opRSETL:
  1503.             UnOp(reg1);
  1504.             PushAll_1;
  1505.             PushImm(param2);
  1506.             Push(reg1);
  1507.             drop;
  1508.             CallRTL(RTL._set, 2);
  1509.             GetRegA
  1510.  
  1511.         |IL.opRSET1:
  1512.             PushAll(1);
  1513.             CallRTL(RTL._set1, 1);
  1514.             GetRegA
  1515.  
  1516.         |IL.opINCLC:
  1517.             UnOp(reg1);
  1518.             Op2(opBIS, imm(ORD({param2})), dst_x(0, reg1));
  1519.             drop
  1520.  
  1521.         |IL.opEXCLC:
  1522.             UnOp(reg1);
  1523.             Op2(opBIC, imm(ORD({param2})), dst_x(0, reg1));
  1524.             drop
  1525.  
  1526.         |IL.opIN:
  1527.             PushAll(2);
  1528.             CallRTL(RTL._in, 2);
  1529.             GetRegA
  1530.  
  1531.         |IL.opINR:
  1532.             PushAll(1);
  1533.             PushImm(param2);
  1534.             CallRTL(RTL._in, 2);
  1535.             GetRegA
  1536.  
  1537.         |IL.opINL:
  1538.             PushAll(1);
  1539.             PushImm(param2);
  1540.             CallRTL(RTL._in2, 2);
  1541.             GetRegA
  1542.  
  1543.         |IL.opINCL:
  1544.             PushAll(2);
  1545.             CallRTL(RTL._incl, 2)
  1546.  
  1547.         |IL.opEXCL:
  1548.             PushAll(2);
  1549.             CallRTL(RTL._excl, 2)
  1550.  
  1551.         |IL.opLADR_INCL, IL.opLADR_EXCL:
  1552.             PushAll(1);
  1553.             MovRR(SP, ACC);
  1554.             n := LocalOffset(param2);
  1555.             IF n # 0 THEN
  1556.                 Op2(opADD, imm(n), ACC)
  1557.             END;
  1558.             Push(ACC);
  1559.             IF opcode = IL.opLADR_INCL THEN
  1560.                 CallRTL(RTL._incl, 2)
  1561.             ELSIF opcode = IL.opLADR_EXCL THEN
  1562.                 CallRTL(RTL._excl, 2)
  1563.             END
  1564.  
  1565.         |IL.opLADR_INCLC:
  1566.             Op2(opBIS, imm(ORD({param2})), LocalDst(param1))
  1567.  
  1568.         |IL.opLADR_EXCLC:
  1569.             Op2(opBIC, imm(ORD({param2})), LocalDst(param1))
  1570.  
  1571.         END;
  1572.  
  1573.         cmd := cmd.next(COMMAND)
  1574.     END;
  1575.  
  1576.     ASSERT(R.pushed = 0);
  1577.     ASSERT(R.top = -1)
  1578. END translate;
  1579.  
  1580.  
  1581. PROCEDURE prolog;
  1582. VAR
  1583.     i: INTEGER;
  1584.  
  1585. BEGIN
  1586.     RTL.Init(EmitLabel, EmitWord, EmitCall);
  1587.     FOR i := 0 TO LEN(RTL.rtl) - 1 DO
  1588.         RTL.Set(i, NewLabel())
  1589.     END;
  1590.  
  1591.     IV[LEN(IV) - 1] := NewLabel();
  1592.     EmitLabel(IV[LEN(IV) - 1]);
  1593.     Op2(opMOV, incr(PC), SP);
  1594.     EmitWord(0);
  1595.     Op2(opMOV, incr(PC), HP);
  1596.     EmitWord(0);
  1597.     Op2(opMOV, imm(5A80H), dst_x(0120H, SR)); (* stop WDT *)
  1598.     Op2(opMOV, imm(RTL.empty_proc), dst_x(0, SP));
  1599.     Op2(opMOV, imm(RTL.empty_proc), dst_x(2, SP));
  1600. END prolog;
  1601.  
  1602.  
  1603. PROCEDURE epilog;
  1604. VAR
  1605.     L1, i, n: INTEGER;
  1606.  
  1607. BEGIN
  1608.     Op2(opBIS, imm(10H), SR); (* CPUOFF *)
  1609.  
  1610.     L1 := NewLabel();
  1611.     FOR i := 0 TO LEN(IV) - 2 DO
  1612.         IV[i] := NewLabel();
  1613.         EmitLabel(IV[i]);
  1614.         PushImm(i);
  1615.         IF i # LEN(IV) - 2 THEN
  1616.             EmitJmp(opJMP, L1)
  1617.         END
  1618.     END;
  1619.  
  1620.     EmitLabel(L1);
  1621.  
  1622.     n := 0;
  1623.     FOR i := 0 TO 15 DO
  1624.         IF i IN R.regs THEN
  1625.             Push(i);
  1626.             INC(n)
  1627.         END
  1628.     END;
  1629.  
  1630.     MovRR(SP, R4);
  1631.     Op2(opADD, imm(n * 2), R4);
  1632.  
  1633.     Push(R4);
  1634.     Op1(opPUSH, R4, sINDIR);
  1635.     Op1(opCALL, SR, sIDX); EmitWord(-RTL.VarSize); Reloc(RBSS); (* call int *)
  1636.     Op2(opADD, imm(4), SP);
  1637.  
  1638.     FOR i := 15 TO 0 BY -1 DO
  1639.         IF i IN R.regs THEN
  1640.             Pop(i)
  1641.         END
  1642.     END;
  1643.  
  1644.     Op2(opADD, imm(2), SP);
  1645.     Op1(opRETI, 0, 0);
  1646.  
  1647.     RTL.Gen
  1648. END epilog;
  1649.  
  1650.  
  1651. PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
  1652. VAR
  1653.     i, adr, heap, stack, TextSize, TypesSize, bits, n, val: INTEGER;
  1654.  
  1655.     Code, Data, Bss: RECORD address, size: INTEGER END;
  1656.  
  1657.     ram, rom: INTEGER;
  1658.  
  1659.     reloc: RELOC;
  1660.  
  1661. BEGIN
  1662.     IdxWords.src := NOWORD;
  1663.     IdxWords.dst := NOWORD;
  1664.  
  1665.     ram := options.ram;
  1666.     rom := options.rom;
  1667.  
  1668.     IF ODD(ram) THEN DEC(ram) END;
  1669.     IF ODD(rom) THEN DEC(rom) END;
  1670.  
  1671.     ram := MIN(MAX(ram, minRAM), maxRAM);
  1672.     rom := MIN(MAX(rom, minROM), maxROM);
  1673.  
  1674.     IF IL.codes.bss > ram - StkReserve - RTL.VarSize THEN
  1675.         ERRORS.Error(204)
  1676.     END;
  1677.  
  1678.     Labels := CHL.CreateIntList();
  1679.     FOR i := 1 TO IL.codes.lcount DO
  1680.         CHL.PushInt(Labels, 0)
  1681.     END;
  1682.  
  1683.     CodeList := LISTS.create(NIL);
  1684.     RelList  := LISTS.create(NIL);
  1685.     REG.Init(R, Push, Pop, mov, xchg, {R4, R5, R6, R7});
  1686.  
  1687.     prolog;
  1688.     translate(chkSTK IN options.checking);
  1689.     epilog;
  1690.  
  1691.     TypesSize := CHL.Length(IL.codes.types) * 2;
  1692.     Data.size := CHL.Length(IL.codes.data);
  1693.     IF ODD(Data.size) THEN
  1694.         CHL.PushByte(IL.codes.data, 0);
  1695.         INC(Data.size)
  1696.     END;
  1697.     Code.size := Fixup(0, IntVectorSize + TypesSize + Data.size);
  1698.     Code.address := 10000H - (IntVectorSize + TypesSize + Data.size + Code.size);
  1699.     IF Code.address < 10000H - rom THEN
  1700.         ERRORS.Error(203)
  1701.     END;
  1702.     Code.size := Fixup(Code.address, IntVectorSize + TypesSize + Data.size);
  1703.     Data.address := Code.address + Code.size;
  1704.     TextSize := Code.size + Data.size;
  1705.  
  1706.     IF Code.address + TextSize + MAX(IL.codes.dmin - Data.size, IntVectorSize + TypesSize) > 10000H THEN
  1707.         ERRORS.Error(203)
  1708.     END;
  1709.  
  1710.     stack := RTL.ram + ram;
  1711.     Bss.size := IL.codes.bss + IL.codes.bss MOD 2;
  1712.     DEC(stack, Bss.size);
  1713.     Bss.address := stack;
  1714.     DEC(stack, RTL.VarSize);
  1715.     heap := RTL.ram;
  1716.     ASSERT(stack - heap >= StkReserve);
  1717.     adr := Code.address + 2;
  1718.     PutWord(stack, adr);
  1719.     adr := Code.address + 6;
  1720.     PutWord(heap, adr);
  1721.  
  1722.     reloc := RelList.first(RELOC);
  1723.     WHILE reloc # NIL DO
  1724.         adr := reloc.WordPtr.offset * 2;
  1725.         val := reloc.WordPtr.val;
  1726.         CASE reloc.section OF
  1727.         |RCODE: PutWord(LabelOffs(val) * 2, adr)
  1728.         |RDATA: PutWord(val + Data.address, adr)
  1729.         |RBSS:  PutWord((val + Bss.address) MOD 65536, adr)
  1730.         END;
  1731.         reloc := reloc.next(RELOC)
  1732.     END;
  1733.  
  1734.     adr := Data.address;
  1735.  
  1736.     FOR i := 0 TO Data.size - 1 DO
  1737.         mem[adr] := CHL.GetByte(IL.codes.data, i);
  1738.         INC(adr)
  1739.     END;
  1740.  
  1741.     FOR i := TypesSize DIV 2 - 1 TO 0 BY -1 DO
  1742.         PutWord(CHL.GetInt(IL.codes.types, i), adr)
  1743.     END;
  1744.  
  1745.     FOR i := 0 TO 15 DO
  1746.         PutWord((33 - i) * i, adr);
  1747.     END;
  1748.  
  1749.     FOR n := 0 TO 15 DO
  1750.         bits := ORD({0 .. n});
  1751.         FOR i := 0 TO 15 - n DO
  1752.             PutWord(bits, adr);
  1753.             bits := LSL(bits, 1)
  1754.         END
  1755.     END;
  1756.  
  1757.     PutWord(4130H, adr); (* RET *)
  1758.     PutWord(stack, adr);
  1759.     PutWord(0001H, adr); (* bsl signature (adr 0FFBEH) *)
  1760.  
  1761.     FOR i := 0 TO LEN(IV) - 1 DO
  1762.         PutWord(LabelOffs(IV[i]) * 2, adr)
  1763.     END;
  1764.  
  1765.     INC(TextSize, IntVectorSize + TypesSize + Code.address MOD 16);
  1766.     INC(Bss.size, StkReserve + RTL.VarSize);
  1767.  
  1768.     WR.Create(outname);
  1769.     HEX.Data(mem, Code.address - Code.address MOD 16, TextSize);
  1770.     HEX.End;
  1771.     WR.Close;
  1772.  
  1773.     C.Dashes;
  1774.     C.String("  rom:  "); C.Int(TextSize); C.String(" of "); C.Int(rom); C.String("  ("); C.Int(TextSize * 100 DIV rom); C.StringLn("%)");
  1775.     C.Ln;
  1776.     C.String("  ram:  "); C.Int(Bss.size); C.String(" of "); C.Int(ram); C.String("  ("); C.Int(Bss.size * 100 DIV ram); C.StringLn("%)")
  1777. END CodeGen;
  1778.  
  1779.  
  1780. END MSP430.