Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2020, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE RVM32I;
  9.  
  10. IMPORT
  11.  
  12.     PROG, WR := WRITER, IL, CHL := CHUNKLISTS, REG, UTILS, STRINGS, ERRORS;
  13.  
  14.  
  15. CONST
  16.  
  17.     LTypes   = 0;
  18.     LStrings = 1;
  19.     LGlobal  = 2;
  20.     LHeap    = 3;
  21.     LStack   = 4;
  22.  
  23.     numGPRs = 3;
  24.  
  25.     R0 = 0; R1 = 1;
  26.     BP = 3; SP = 4;
  27.  
  28.     ACC = R0;
  29.  
  30.     GPRs = {0 .. 2} + {5 .. numGPRs + 1};
  31.  
  32.     opSTOP = 0; opRET = 1; opENTER = 2; opNEG = 3; opNOT = 4; opABS = 5;
  33.     opXCHG = 6; opLDR8 = 7; opLDR16 = 8; opLDR32 = 9; opPUSH = 10; opPUSHC = 11;
  34.     opPOP = 12; opJGZ = 13; opJZ = 14; opJNZ = 15; opLLA = 16; opJGA = 17;
  35.     opJLA = 18; opJMP = 19; opCALL = 20; opCALLI = 21;
  36.  
  37.     opMOV = 22; opMUL = 24; opADD = 26; opSUB = 28; opDIV = 30; opMOD = 32;
  38.     opSTR8 = 34; opSTR16 = 36; opSTR32 = 38; opINCL = 40; opEXCL = 42;
  39.     opIN = 44; opAND = 46; opOR = 48; opXOR = 50; opASR = 52; opLSR = 54;
  40.     opLSL = 56; opROR = 58; opMIN = 60; opMAX = 62; opEQ = 64; opNE = 66;
  41.     opLT = 68; opLE = 70; opGT = 72; opGE = 74; opBT = 76;
  42.  
  43.     opMOVC = 23; opMULC = 25; opADDC = 27; opSUBC = 29; opDIVC = 31; opMODC = 33;
  44.     opSTR8C = 35; opSTR16C = 37; opSTR32C = 39; opINCLC = 41; opEXCLC = 43;
  45.     opINC = 45; opANDC = 47; opORC = 49; opXORC = 51; opASRC = 53; opLSRC = 55;
  46.     opLSLC = 57; opRORC = 59; opMINC = 61; opMAXC = 63; opEQC = 65; opNEC = 67;
  47.     opLTC = 69; opLEC = 71; opGTC = 73; opGEC = 75; opBTC = 77;
  48.  
  49.     opLEA = 78; opLABEL = 79;
  50.  
  51.     inf = 7F800000H;
  52.  
  53.  
  54. VAR
  55.  
  56.     R: REG.REGS; count: INTEGER;
  57.  
  58.  
  59. PROCEDURE OutByte (n: BYTE);
  60. BEGIN
  61.     WR.WriteByte(n);
  62.     INC(count)
  63. END OutByte;
  64.  
  65.  
  66. PROCEDURE OutInt (n: INTEGER);
  67. BEGIN
  68.     WR.Write32LE(n);
  69.     INC(count, 4)
  70. END OutInt;
  71.  
  72.  
  73. PROCEDURE Emit (op, par1, par2: INTEGER);
  74. BEGIN
  75.     OutInt(op);
  76.     OutInt(par1);
  77.     OutInt(par2)
  78. END Emit;
  79.  
  80.  
  81. PROCEDURE drop;
  82. BEGIN
  83.     REG.Drop(R)
  84. END drop;
  85.  
  86.  
  87. PROCEDURE GetAnyReg (): INTEGER;
  88.     RETURN REG.GetAnyReg(R)
  89. END GetAnyReg;
  90.  
  91.  
  92. PROCEDURE GetAcc;
  93. BEGIN
  94.     ASSERT(REG.GetReg(R, ACC))
  95. END GetAcc;
  96.  
  97.  
  98. PROCEDURE UnOp (VAR r: INTEGER);
  99. BEGIN
  100.     REG.UnOp(R, r)
  101. END UnOp;
  102.  
  103.  
  104. PROCEDURE BinOp (VAR r1, r2: INTEGER);
  105. BEGIN
  106.     REG.BinOp(R, r1, r2)
  107. END BinOp;
  108.  
  109.  
  110. PROCEDURE PushAll (NumberOfParameters: INTEGER);
  111. BEGIN
  112.     REG.PushAll(R);
  113.     DEC(R.pushed, NumberOfParameters)
  114. END PushAll;
  115.  
  116.  
  117. PROCEDURE push (r: INTEGER);
  118. BEGIN
  119.     Emit(opPUSH, r, 0)
  120. END push;
  121.  
  122.  
  123. PROCEDURE pop (r: INTEGER);
  124. BEGIN
  125.     Emit(opPOP, r, 0)
  126. END pop;
  127.  
  128.  
  129. PROCEDURE mov (r1, r2: INTEGER);
  130. BEGIN
  131.     Emit(opMOV, r1, r2)
  132. END mov;
  133.  
  134.  
  135. PROCEDURE xchg (r1, r2: INTEGER);
  136. BEGIN
  137.     Emit(opXCHG, r1, r2)
  138. END xchg;
  139.  
  140.  
  141. PROCEDURE addrc (r, c: INTEGER);
  142. BEGIN
  143.     Emit(opADDC, r, c)
  144. END addrc;
  145.  
  146.  
  147. PROCEDURE subrc (r, c: INTEGER);
  148. BEGIN
  149.     Emit(opSUBC, r, c)
  150. END subrc;
  151.  
  152.  
  153. PROCEDURE movrc (r, c: INTEGER);
  154. BEGIN
  155.     Emit(opMOVC, r, c)
  156. END movrc;
  157.  
  158.  
  159. PROCEDURE pushc (c: INTEGER);
  160. BEGIN
  161.     Emit(opPUSHC, c, 0)
  162. END pushc;
  163.  
  164.  
  165. PROCEDURE add (r1, r2: INTEGER);
  166. BEGIN
  167.     Emit(opADD, r1, r2)
  168. END add;
  169.  
  170.  
  171. PROCEDURE sub (r1, r2: INTEGER);
  172. BEGIN
  173.     Emit(opSUB, r1, r2)
  174. END sub;
  175.  
  176.  
  177. PROCEDURE ldr32 (r1, r2: INTEGER);
  178. BEGIN
  179.     Emit(opLDR32, r1, r2)
  180. END ldr32;
  181.  
  182.  
  183. PROCEDURE ldr16 (r1, r2: INTEGER);
  184. BEGIN
  185.     Emit(opLDR16, r1, r2)
  186. END ldr16;
  187.  
  188.  
  189. PROCEDURE ldr8 (r1, r2: INTEGER);
  190. BEGIN
  191.     Emit(opLDR8, r1, r2)
  192. END ldr8;
  193.  
  194.  
  195. PROCEDURE str32 (r1, r2: INTEGER);
  196. BEGIN
  197.     Emit(opSTR32, r1, r2)
  198. END str32;
  199.  
  200.  
  201. PROCEDURE str16 (r1, r2: INTEGER);
  202. BEGIN
  203.     Emit(opSTR16, r1, r2)
  204. END str16;
  205.  
  206.  
  207. PROCEDURE str8 (r1, r2: INTEGER);
  208. BEGIN
  209.     Emit(opSTR8, r1, r2)
  210. END str8;
  211.  
  212.  
  213. PROCEDURE GlobalAdr (r, offset: INTEGER);
  214. BEGIN
  215.     Emit(opLEA, r + 256 * LGlobal, offset)
  216. END GlobalAdr;
  217.  
  218.  
  219. PROCEDURE StrAdr (r, offset: INTEGER);
  220. BEGIN
  221.     Emit(opLEA, r + 256 * LStrings, offset)
  222. END StrAdr;
  223.  
  224.  
  225. PROCEDURE ProcAdr (r, label: INTEGER);
  226. BEGIN
  227.     Emit(opLLA, r, label)
  228. END ProcAdr;
  229.  
  230.  
  231. PROCEDURE jnz (r, label: INTEGER);
  232. BEGIN
  233.     Emit(opJNZ, r, label)
  234. END jnz;
  235.  
  236.  
  237. PROCEDURE CallRTL (proc, par: INTEGER);
  238. BEGIN
  239.     Emit(opCALL, IL.codes.rtl[proc], 0);
  240.     addrc(SP, par * 4)
  241. END CallRTL;
  242.  
  243.  
  244. PROCEDURE translate;
  245. VAR
  246.     cmd: IL.COMMAND;
  247.     opcode, param1, param2: INTEGER;
  248.     r1, r2, r3: INTEGER;
  249.  
  250. BEGIN
  251.     cmd := IL.codes.commands.first(IL.COMMAND);
  252.  
  253.     WHILE cmd # NIL DO
  254.  
  255.         param1 := cmd.param1;
  256.         param2 := cmd.param2;
  257.         opcode := cmd.opcode;
  258.  
  259.         CASE opcode OF
  260.  
  261.         |IL.opJMP:
  262.             Emit(opJMP, param1, 0)
  263.  
  264.         |IL.opLABEL:
  265.             Emit(opLABEL, param1, 0)
  266.  
  267.         |IL.opCALL:
  268.             Emit(opCALL, param1, 0)
  269.  
  270.         |IL.opCALLP:
  271.             UnOp(r1);
  272.             Emit(opCALLI, r1, 0);
  273.             drop;
  274.             ASSERT(R.top = -1)
  275.  
  276.         |IL.opPUSHC:
  277.             pushc(param2)
  278.  
  279.         |IL.opCLEANUP:
  280.             IF param2 # 0 THEN
  281.                 addrc(SP, param2 * 4)
  282.             END
  283.  
  284.         |IL.opNOP, IL.opAND, IL.opOR:
  285.  
  286.         |IL.opSADR:
  287.             StrAdr(GetAnyReg(), param2)
  288.  
  289.         |IL.opGADR:
  290.             GlobalAdr(GetAnyReg(), param2)
  291.  
  292.         |IL.opLADR:
  293.             r1 := GetAnyReg();
  294.             mov(r1, BP);
  295.             addrc(r1, param2 * 4)
  296.  
  297.         |IL.opPARAM:
  298.             IF param2 = 1 THEN
  299.                 UnOp(r1);
  300.                 push(r1);
  301.                 drop
  302.             ELSE
  303.                 ASSERT(R.top + 1 <= param2);
  304.                 PushAll(param2)
  305.             END
  306.  
  307.         |IL.opONERR:
  308.             pushc(param2);
  309.             Emit(opJMP, param1, 0)
  310.  
  311.         |IL.opPRECALL:
  312.             PushAll(0)
  313.  
  314.         |IL.opRES, IL.opRESF:
  315.             ASSERT(R.top = -1);
  316.             GetAcc
  317.  
  318.         |IL.opENTER:
  319.             ASSERT(R.top = -1);
  320.             Emit(opLABEL, param1, 0);
  321.             Emit(opENTER, param2, 0)
  322.  
  323.         |IL.opLEAVE, IL.opLEAVER, IL.opLEAVEF:
  324.             IF opcode # IL.opLEAVE THEN
  325.                 UnOp(r1);
  326.                 IF r1 # ACC THEN
  327.                     GetAcc;
  328.                     ASSERT(REG.Exchange(R, r1, ACC));
  329.                     drop
  330.                 END;
  331.                 drop
  332.             END;
  333.  
  334.             ASSERT(R.top = -1);
  335.  
  336.             IF param1 > 0 THEN
  337.                 mov(SP, BP)
  338.             END;
  339.  
  340.             pop(BP);
  341.  
  342.             Emit(opRET, 0, 0)
  343.  
  344.         |IL.opLEAVEC:
  345.             Emit(opRET, 0, 0)
  346.  
  347.         |IL.opCONST:
  348.             movrc(GetAnyReg(), param2)
  349.  
  350.         |IL.opDROP:
  351.             UnOp(r1);
  352.             drop
  353.  
  354.         |IL.opSAVEC:
  355.             UnOp(r1);
  356.             Emit(opSTR32C, r1, param2);
  357.             drop
  358.  
  359.         |IL.opSAVE8C:
  360.             UnOp(r1);
  361.             Emit(opSTR8C, r1, param2 MOD 256);
  362.             drop
  363.  
  364.         |IL.opSAVE16C:
  365.             UnOp(r1);
  366.             Emit(opSTR16C, r1, param2 MOD 65536);
  367.             drop
  368.  
  369.         |IL.opSAVE, IL.opSAVE32, IL.opSAVEF:
  370.             BinOp(r2, r1);
  371.             str32(r1, r2);
  372.             drop;
  373.             drop
  374.  
  375.         |IL.opSAVEFI:
  376.             BinOp(r2, r1);
  377.             str32(r2, r1);
  378.             drop;
  379.             drop
  380.  
  381.         |IL.opSAVE8:
  382.             BinOp(r2, r1);
  383.             str8(r1, r2);
  384.             drop;
  385.             drop
  386.  
  387.         |IL.opSAVE16:
  388.             BinOp(r2, r1);
  389.             str16(r1, r2);
  390.             drop;
  391.             drop
  392.  
  393.         |IL.opGLOAD32:
  394.             r1 := GetAnyReg();
  395.             GlobalAdr(r1, param2);
  396.             ldr32(r1, r1)
  397.  
  398.         |IL.opVADR, IL.opLLOAD32:
  399.             r1 := GetAnyReg();
  400.             mov(r1, BP);
  401.             addrc(r1, param2 * 4);
  402.             ldr32(r1, r1)
  403.  
  404.         |IL.opVLOAD32:
  405.             r1 := GetAnyReg();
  406.             mov(r1, BP);
  407.             addrc(r1, param2 * 4);
  408.             ldr32(r1, r1);
  409.             ldr32(r1, r1)
  410.  
  411.         |IL.opGLOAD16:
  412.             r1 := GetAnyReg();
  413.             GlobalAdr(r1, param2);
  414.             ldr16(r1, r1)
  415.  
  416.         |IL.opLLOAD16:
  417.             r1 := GetAnyReg();
  418.             mov(r1, BP);
  419.             addrc(r1, param2 * 4);
  420.             ldr16(r1, r1)
  421.  
  422.         |IL.opVLOAD16:
  423.             r1 := GetAnyReg();
  424.             mov(r1, BP);
  425.             addrc(r1, param2 * 4);
  426.             ldr32(r1, r1);
  427.             ldr16(r1, r1)
  428.  
  429.         |IL.opGLOAD8:
  430.             r1 := GetAnyReg();
  431.             GlobalAdr(r1, param2);
  432.             ldr8(r1, r1)
  433.  
  434.         |IL.opLLOAD8:
  435.             r1 := GetAnyReg();
  436.             mov(r1, BP);
  437.             addrc(r1, param2 * 4);
  438.             ldr8(r1, r1)
  439.  
  440.         |IL.opVLOAD8:
  441.             r1 := GetAnyReg();
  442.             mov(r1, BP);
  443.             addrc(r1, param2 * 4);
  444.             ldr32(r1, r1);
  445.             ldr8(r1, r1)
  446.  
  447.         |IL.opLOAD8:
  448.             UnOp(r1);
  449.             ldr8(r1, r1)
  450.  
  451.         |IL.opLOAD16:
  452.             UnOp(r1);
  453.             ldr16(r1, r1)
  454.  
  455.         |IL.opLOAD32, IL.opLOADF:
  456.             UnOp(r1);
  457.             ldr32(r1, r1)
  458.  
  459.         |IL.opLOOP, IL.opENDLOOP:
  460.  
  461.         |IL.opUMINUS:
  462.             UnOp(r1);
  463.             Emit(opNEG, r1, 0)
  464.  
  465.         |IL.opADD:
  466.             BinOp(r1, r2);
  467.             add(r1, r2);
  468.             drop
  469.  
  470.         |IL.opSUB:
  471.             BinOp(r1, r2);
  472.             sub(r1, r2);
  473.             drop
  474.  
  475.         |IL.opADDC:
  476.             UnOp(r1);
  477.             addrc(r1, param2)
  478.  
  479.         |IL.opSUBR:
  480.             UnOp(r1);
  481.             subrc(r1, param2)
  482.  
  483.         |IL.opSUBL:
  484.             UnOp(r1);
  485.             subrc(r1, param2);
  486.             Emit(opNEG, r1, 0)
  487.  
  488.         |IL.opMULC:
  489.             UnOp(r1);
  490.             Emit(opMULC, r1, param2)
  491.  
  492.         |IL.opMUL:
  493.             BinOp(r1, r2);
  494.             Emit(opMUL, r1, r2);
  495.             drop
  496.  
  497.         |IL.opDIV:
  498.             BinOp(r1, r2);
  499.             Emit(opDIV, r1, r2);
  500.             drop
  501.  
  502.         |IL.opMOD:
  503.             BinOp(r1, r2);
  504.             Emit(opMOD, r1, r2);
  505.             drop
  506.  
  507.         |IL.opDIVR:
  508.             UnOp(r1);
  509.             Emit(opDIVC, r1, param2)
  510.  
  511.         |IL.opMODR:
  512.             UnOp(r1);
  513.             Emit(opMODC, r1, param2)
  514.  
  515.         |IL.opDIVL:
  516.             UnOp(r1);
  517.             r2 := GetAnyReg();
  518.             movrc(r2, param2);
  519.             Emit(opDIV, r2, r1);
  520.             mov(r1, r2);
  521.             drop
  522.  
  523.         |IL.opMODL:
  524.             UnOp(r1);
  525.             r2 := GetAnyReg();
  526.             movrc(r2, param2);
  527.             Emit(opMOD, r2, r1);
  528.             mov(r1, r2);
  529.             drop
  530.  
  531.         |IL.opEQ:
  532.             BinOp(r1, r2);
  533.             Emit(opEQ, r1, r2);
  534.             drop
  535.  
  536.         |IL.opNE:
  537.             BinOp(r1, r2);
  538.             Emit(opNE, r1, r2);
  539.             drop
  540.  
  541.         |IL.opLT:
  542.             BinOp(r1, r2);
  543.             Emit(opLT, r1, r2);
  544.             drop
  545.  
  546.         |IL.opLE:
  547.             BinOp(r1, r2);
  548.             Emit(opLE, r1, r2);
  549.             drop
  550.  
  551.         |IL.opGT:
  552.             BinOp(r1, r2);
  553.             Emit(opGT, r1, r2);
  554.             drop
  555.  
  556.         |IL.opGE:
  557.             BinOp(r1, r2);
  558.             Emit(opGE, r1, r2);
  559.             drop
  560.  
  561.         |IL.opEQC:
  562.             UnOp(r1);
  563.             Emit(opEQC, r1, param2)
  564.  
  565.         |IL.opNEC:
  566.             UnOp(r1);
  567.             Emit(opNEC, r1, param2)
  568.  
  569.         |IL.opLTC:
  570.             UnOp(r1);
  571.             Emit(opLTC, r1, param2)
  572.  
  573.         |IL.opLEC:
  574.             UnOp(r1);
  575.             Emit(opLEC, r1, param2)
  576.  
  577.         |IL.opGTC:
  578.             UnOp(r1);
  579.             Emit(opGTC, r1, param2)
  580.  
  581.         |IL.opGEC:
  582.             UnOp(r1);
  583.             Emit(opGEC, r1, param2)
  584.  
  585.         |IL.opJNZ1:
  586.             UnOp(r1);
  587.             jnz(r1, param1)
  588.  
  589.         |IL.opJG:
  590.             UnOp(r1);
  591.             Emit(opJGZ, r1, param1)
  592.  
  593.         |IL.opJNZ:
  594.             UnOp(r1);
  595.             jnz(r1, param1);
  596.             drop
  597.  
  598.         |IL.opJZ:
  599.             UnOp(r1);
  600.             Emit(opJZ, r1, param1);
  601.             drop
  602.  
  603.         |IL.opMULS:
  604.             BinOp(r1, r2);
  605.             Emit(opAND, r1, r2);
  606.             drop
  607.  
  608.         |IL.opMULSC:
  609.             UnOp(r1);
  610.             Emit(opANDC, r1, param2)
  611.  
  612.         |IL.opDIVS:
  613.             BinOp(r1, r2);
  614.             Emit(opXOR, r1, r2);
  615.             drop
  616.  
  617.         |IL.opDIVSC:
  618.             UnOp(r1);
  619.             Emit(opXORC, r1, param2)
  620.  
  621.         |IL.opADDS:
  622.             BinOp(r1, r2);
  623.             Emit(opOR, r1, r2);
  624.             drop
  625.  
  626.         |IL.opSUBS:
  627.             BinOp(r1, r2);
  628.             Emit(opNOT, r2, 0);
  629.             Emit(opAND, r1, r2);
  630.             drop
  631.  
  632.         |IL.opADDSC:
  633.             UnOp(r1);
  634.             Emit(opORC, r1, param2)
  635.  
  636.         |IL.opSUBSL:
  637.             UnOp(r1);
  638.             Emit(opNOT, r1, 0);
  639.             Emit(opANDC, r1, param2)
  640.  
  641.         |IL.opSUBSR:
  642.             UnOp(r1);
  643.             Emit(opANDC, r1, ORD(-BITS(param2)))
  644.  
  645.         |IL.opUMINS:
  646.             UnOp(r1);
  647.             Emit(opNOT, r1, 0)
  648.  
  649.         |IL.opASR:
  650.             BinOp(r1, r2);
  651.             Emit(opASR, r1, r2);
  652.             drop
  653.  
  654.         |IL.opLSL:
  655.             BinOp(r1, r2);
  656.             Emit(opLSL, r1, r2);
  657.             drop
  658.  
  659.         |IL.opROR:
  660.             BinOp(r1, r2);
  661.             Emit(opROR, r1, r2);
  662.             drop
  663.  
  664.         |IL.opLSR:
  665.             BinOp(r1, r2);
  666.             Emit(opLSR, r1, r2);
  667.             drop
  668.  
  669.         |IL.opASR1:
  670.             r2 := GetAnyReg();
  671.             Emit(opMOVC, r2, param2);
  672.             BinOp(r1, r2);
  673.             Emit(opASR, r2, r1);
  674.             mov(r1, r2);
  675.             drop
  676.  
  677.         |IL.opLSL1:
  678.             r2 := GetAnyReg();
  679.             Emit(opMOVC, r2, param2);
  680.             BinOp(r1, r2);
  681.             Emit(opLSL, r2, r1);
  682.             mov(r1, r2);
  683.             drop
  684.  
  685.         |IL.opROR1:
  686.             r2 := GetAnyReg();
  687.             Emit(opMOVC, r2, param2);
  688.             BinOp(r1, r2);
  689.             Emit(opROR, r2, r1);
  690.             mov(r1, r2);
  691.             drop
  692.  
  693.         |IL.opLSR1:
  694.             r2 := GetAnyReg();
  695.             Emit(opMOVC, r2, param2);
  696.             BinOp(r1, r2);
  697.             Emit(opLSR, r2, r1);
  698.             mov(r1, r2);
  699.             drop
  700.  
  701.         |IL.opASR2:
  702.             UnOp(r1);
  703.             Emit(opASRC, r1, param2 MOD 32)
  704.  
  705.         |IL.opLSL2:
  706.             UnOp(r1);
  707.             Emit(opLSLC, r1, param2 MOD 32)
  708.  
  709.         |IL.opROR2:
  710.             UnOp(r1);
  711.             Emit(opRORC, r1, param2 MOD 32)
  712.  
  713.         |IL.opLSR2:
  714.             UnOp(r1);
  715.             Emit(opLSRC, r1, param2 MOD 32)
  716.  
  717.         |IL.opCHR:
  718.             UnOp(r1);
  719.             Emit(opANDC, r1, 255)
  720.  
  721.         |IL.opWCHR:
  722.             UnOp(r1);
  723.             Emit(opANDC, r1, 65535)
  724.  
  725.         |IL.opABS:
  726.             UnOp(r1);
  727.             Emit(opABS, r1, 0)
  728.  
  729.         |IL.opLEN:
  730.             UnOp(r1);
  731.             drop;
  732.             EXCL(R.regs, r1);
  733.  
  734.             WHILE param2 > 0 DO
  735.                 UnOp(r2);
  736.                 drop;
  737.                 DEC(param2)
  738.             END;
  739.  
  740.             INCL(R.regs, r1);
  741.             ASSERT(REG.GetReg(R, r1))
  742.  
  743.         |IL.opSWITCH:
  744.             UnOp(r1);
  745.             IF param2 = 0 THEN
  746.                 r2 := ACC
  747.             ELSE
  748.                 r2 := R1
  749.             END;
  750.             IF r1 # r2 THEN
  751.                 ASSERT(REG.GetReg(R, r2));
  752.                 ASSERT(REG.Exchange(R, r1, r2));
  753.                 drop
  754.             END;
  755.             drop
  756.  
  757.         |IL.opENDSW:
  758.  
  759.         |IL.opCASEL:
  760.             GetAcc;
  761.             Emit(opJLA, param1, param2);
  762.             drop
  763.  
  764.         |IL.opCASER:
  765.             GetAcc;
  766.             Emit(opJGA, param1, param2);
  767.             drop
  768.  
  769.         |IL.opCASELR:
  770.             GetAcc;
  771.             Emit(opJLA, param1, param2);
  772.             Emit(opJGA, param1, cmd.param3);
  773.             drop
  774.  
  775.         |IL.opSBOOL:
  776.             BinOp(r2, r1);
  777.             Emit(opNEC, r2, 0);
  778.             str8(r1, r2);
  779.             drop;
  780.             drop
  781.  
  782.         |IL.opSBOOLC:
  783.             UnOp(r1);
  784.             Emit(opSTR8C, r1, ORD(param2 # 0));
  785.             drop
  786.  
  787.         |IL.opINCC:
  788.             UnOp(r1);
  789.             r2 := GetAnyReg();
  790.             ldr32(r2, r1);
  791.             addrc(r2, param2);
  792.             str32(r1, r2);
  793.             drop;
  794.             drop
  795.  
  796.         |IL.opINCCB, IL.opDECCB:
  797.             IF opcode = IL.opDECCB THEN
  798.                 param2 := -param2
  799.             END;
  800.             UnOp(r1);
  801.             r2 := GetAnyReg();
  802.             ldr8(r2, r1);
  803.             addrc(r2, param2);
  804.             str8(r1, r2);
  805.             drop;
  806.             drop
  807.  
  808.         |IL.opINCB, IL.opDECB:
  809.             BinOp(r2, r1);
  810.             r3 := GetAnyReg();
  811.             ldr8(r3, r1);
  812.             IF opcode = IL.opINCB THEN
  813.                 add(r3, r2)
  814.             ELSE
  815.                 sub(r3, r2)
  816.             END;
  817.             str8(r1, r3);
  818.             drop;
  819.             drop;
  820.             drop
  821.  
  822.         |IL.opINC, IL.opDEC:
  823.             BinOp(r2, r1);
  824.             r3 := GetAnyReg();
  825.             ldr32(r3, r1);
  826.             IF opcode = IL.opINC THEN
  827.                 add(r3, r2)
  828.             ELSE
  829.                 sub(r3, r2)
  830.             END;
  831.             str32(r1, r3);
  832.             drop;
  833.             drop;
  834.             drop
  835.  
  836.         |IL.opINCL, IL.opEXCL:
  837.             BinOp(r2, r1);
  838.             IF opcode = IL.opINCL THEN
  839.                 Emit(opINCL, r1, r2)
  840.             ELSE
  841.                 Emit(opEXCL, r1, r2)
  842.             END;
  843.             drop;
  844.             drop
  845.  
  846.         |IL.opINCLC, IL.opEXCLC:
  847.             UnOp(r1);
  848.             r2 := GetAnyReg();
  849.             ldr32(r2, r1);
  850.             IF opcode = IL.opINCLC THEN
  851.                 Emit(opINCLC, r2, param2)
  852.             ELSE
  853.                 Emit(opEXCLC, r2, param2)
  854.             END;
  855.             str32(r1, r2);
  856.             drop;
  857.             drop
  858.  
  859.         |IL.opEQB, IL.opNEB:
  860.             BinOp(r1, r2);
  861.             Emit(opNEC, r1, 0);
  862.             Emit(opNEC, r2, 0);
  863.             IF opcode = IL.opEQB THEN
  864.                 Emit(opEQ, r1, r2)
  865.             ELSE
  866.                 Emit(opNE, r1, r2)
  867.             END;
  868.             drop
  869.  
  870.         |IL.opCHKBYTE:
  871.             BinOp(r1, r2);
  872.             r3 := GetAnyReg();
  873.             mov(r3, r1);
  874.             Emit(opBTC, r3, 256);
  875.             jnz(r3, param1);
  876.             drop
  877.  
  878.         |IL.opCHKIDX:
  879.             UnOp(r1);
  880.             r2 := GetAnyReg();
  881.             mov(r2, r1);
  882.             Emit(opBTC, r2, param2);
  883.             jnz(r2, param1);
  884.             drop
  885.  
  886.         |IL.opCHKIDX2:
  887.             BinOp(r1, r2);
  888.             IF param2 # -1 THEN
  889.                 r3 := GetAnyReg();
  890.                 mov(r3, r2);
  891.                 Emit(opBT, r3, r1);
  892.                 jnz(r3, param1);
  893.                 drop
  894.             END;
  895.             INCL(R.regs, r1);
  896.             DEC(R.top);
  897.             R.stk[R.top] := r2
  898.  
  899.         |IL.opEQP, IL.opNEP:
  900.             ProcAdr(GetAnyReg(), param1);
  901.             BinOp(r1, r2);
  902.             IF opcode = IL.opEQP THEN
  903.                 Emit(opEQ, r1, r2)
  904.             ELSE
  905.                 Emit(opNE, r1, r2)
  906.             END;
  907.             drop
  908.  
  909.         |IL.opSAVEP:
  910.             UnOp(r1);
  911.             r2 := GetAnyReg();
  912.             ProcAdr(r2, param2);
  913.             str32(r1, r2);
  914.             drop;
  915.             drop
  916.  
  917.         |IL.opPUSHP:
  918.             ProcAdr(GetAnyReg(), param2)
  919.  
  920.         |IL.opPUSHT:
  921.             UnOp(r1);
  922.             r2 := GetAnyReg();
  923.             mov(r2, r1);
  924.             subrc(r2, 4);
  925.             ldr32(r2, r2)
  926.  
  927.         |IL.opGET, IL.opGETC:
  928.             IF opcode = IL.opGET THEN
  929.                 BinOp(r1, r2)
  930.             ELSIF opcode = IL.opGETC THEN
  931.                 UnOp(r2);
  932.                 r1 := GetAnyReg();
  933.                 movrc(r1, param1)
  934.             END;
  935.             drop;
  936.             drop;
  937.  
  938.             CASE param2 OF
  939.             |1: ldr8(r1, r1);  str8(r2, r1)
  940.             |2: ldr16(r1, r1); str16(r2, r1)
  941.             |4: ldr32(r1, r1); str32(r2, r1)
  942.             END
  943.  
  944.         |IL.opNOT:
  945.             UnOp(r1);
  946.             Emit(opEQC, r1, 0)
  947.  
  948.         |IL.opORD:
  949.             UnOp(r1);
  950.             Emit(opNEC, r1, 0)
  951.  
  952.         |IL.opMIN:
  953.             BinOp(r1, r2);
  954.             Emit(opMIN, r1, r2);
  955.             drop
  956.  
  957.         |IL.opMAX:
  958.             BinOp(r1, r2);
  959.             Emit(opMAX, r1, r2);
  960.             drop
  961.  
  962.         |IL.opMINC:
  963.             UnOp(r1);
  964.             Emit(opMINC, r1, param2)
  965.  
  966.         |IL.opMAXC:
  967.             UnOp(r1);
  968.             Emit(opMAXC, r1, param2)
  969.  
  970.         |IL.opIN:
  971.             BinOp(r1, r2);
  972.             Emit(opIN, r1, r2);
  973.             drop
  974.  
  975.         |IL.opINL:
  976.             r1 := GetAnyReg();
  977.             movrc(r1, param2);
  978.             BinOp(r2, r1);
  979.             Emit(opIN, r1, r2);
  980.             mov(r2, r1);
  981.             drop
  982.  
  983.         |IL.opINR:
  984.             UnOp(r1);
  985.             Emit(opINC, r1, param2)
  986.  
  987.         |IL.opERR:
  988.             CallRTL(IL._error, 4)
  989.  
  990.         |IL.opEQS .. IL.opGES:
  991.             PushAll(4);
  992.             pushc(opcode - IL.opEQS);
  993.             CallRTL(IL._strcmp, 5);
  994.             GetAcc
  995.  
  996.         |IL.opEQSW .. IL.opGESW:
  997.             PushAll(4);
  998.             pushc(opcode - IL.opEQSW);
  999.             CallRTL(IL._strcmpw, 5);
  1000.             GetAcc
  1001.  
  1002.         |IL.opCOPY:
  1003.             PushAll(2);
  1004.             pushc(param2);
  1005.             CallRTL(IL._move, 3)
  1006.  
  1007.         |IL.opMOVE:
  1008.             PushAll(3);
  1009.             CallRTL(IL._move, 3)
  1010.  
  1011.         |IL.opCOPYA:
  1012.             PushAll(4);
  1013.             pushc(param2);
  1014.             CallRTL(IL._arrcpy, 5);
  1015.             GetAcc
  1016.  
  1017.         |IL.opCOPYS:
  1018.             PushAll(4);
  1019.             pushc(param2);
  1020.             CallRTL(IL._strcpy, 5)
  1021.  
  1022.         |IL.opROT:
  1023.             PushAll(0);
  1024.             mov(ACC, SP);
  1025.             push(ACC);
  1026.             pushc(param2);
  1027.             CallRTL(IL._rot, 2)
  1028.  
  1029.         |IL.opLENGTH:
  1030.             PushAll(2);
  1031.             CallRTL(IL._length, 2);
  1032.             GetAcc
  1033.  
  1034.         |IL.opLENGTHW:
  1035.             PushAll(2);
  1036.             CallRTL(IL._lengthw, 2);
  1037.             GetAcc
  1038.  
  1039.         |IL.opSAVES:
  1040.             UnOp(r2);
  1041.             REG.PushAll_1(R);
  1042.             r1 := GetAnyReg();
  1043.             StrAdr(r1, param2);
  1044.             push(r1);
  1045.             drop;
  1046.             push(r2);
  1047.             drop;
  1048.             pushc(param1);
  1049.             CallRTL(IL._move, 3)
  1050.  
  1051.         |IL.opRSET:
  1052.             PushAll(2);
  1053.             CallRTL(IL._set, 2);
  1054.             GetAcc
  1055.  
  1056.         |IL.opRSETR:
  1057.             PushAll(1);
  1058.             pushc(param2);
  1059.             CallRTL(IL._set, 2);
  1060.             GetAcc
  1061.  
  1062.         |IL.opRSETL:
  1063.             UnOp(r1);
  1064.             REG.PushAll_1(R);
  1065.             pushc(param2);
  1066.             push(r1);
  1067.             drop;
  1068.             CallRTL(IL._set, 2);
  1069.             GetAcc
  1070.  
  1071.         |IL.opRSET1:
  1072.             PushAll(1);
  1073.             CallRTL(IL._set1, 1);
  1074.             GetAcc
  1075.  
  1076.         |IL.opNEW:
  1077.             PushAll(1);
  1078.             INC(param2, 8);
  1079.             ASSERT(UTILS.Align(param2, 32));
  1080.             pushc(param2);
  1081.             pushc(param1);
  1082.             CallRTL(IL._new, 3)
  1083.  
  1084.         |IL.opTYPEGP:
  1085.             UnOp(r1);
  1086.             PushAll(0);
  1087.             push(r1);
  1088.             pushc(param2);
  1089.             CallRTL(IL._guard, 2);
  1090.             GetAcc
  1091.  
  1092.         |IL.opIS:
  1093.             PushAll(1);
  1094.             pushc(param2);
  1095.             CallRTL(IL._is, 2);
  1096.             GetAcc
  1097.  
  1098.         |IL.opISREC:
  1099.             PushAll(2);
  1100.             pushc(param2);
  1101.             CallRTL(IL._guardrec, 3);
  1102.             GetAcc
  1103.  
  1104.         |IL.opTYPEGR:
  1105.             PushAll(1);
  1106.             pushc(param2);
  1107.             CallRTL(IL._guardrec, 2);
  1108.             GetAcc
  1109.  
  1110.         |IL.opTYPEGD:
  1111.             UnOp(r1);
  1112.             PushAll(0);
  1113.             subrc(r1, 4);
  1114.             ldr32(r1, r1);
  1115.             push(r1);
  1116.             pushc(param2);
  1117.             CallRTL(IL._guardrec, 2);
  1118.             GetAcc
  1119.  
  1120.         |IL.opCASET:
  1121.             push(R1);
  1122.             push(R1);
  1123.             pushc(param2);
  1124.             CallRTL(IL._guardrec, 2);
  1125.             pop(R1);
  1126.             jnz(ACC, param1)
  1127.  
  1128.         |IL.opCONSTF:
  1129.             movrc(GetAnyReg(), UTILS.d2s(cmd.float))
  1130.  
  1131.         |IL.opMULF:
  1132.             PushAll(2);
  1133.             CallRTL(IL._fmul, 2);
  1134.             GetAcc
  1135.  
  1136.         |IL.opDIVF:
  1137.             PushAll(2);
  1138.             CallRTL(IL._fdiv, 2);
  1139.             GetAcc
  1140.  
  1141.         |IL.opDIVFI:
  1142.             PushAll(2);
  1143.             CallRTL(IL._fdivi, 2);
  1144.             GetAcc
  1145.  
  1146.         |IL.opADDF:
  1147.             PushAll(2);
  1148.             CallRTL(IL._fadd, 2);
  1149.             GetAcc
  1150.  
  1151.         |IL.opSUBFI:
  1152.             PushAll(2);
  1153.             CallRTL(IL._fsubi, 2);
  1154.             GetAcc
  1155.  
  1156.         |IL.opSUBF:
  1157.             PushAll(2);
  1158.             CallRTL(IL._fsub, 2);
  1159.             GetAcc
  1160.  
  1161.         |IL.opEQF..IL.opGEF:
  1162.             PushAll(2);
  1163.             pushc(opcode - IL.opEQF);
  1164.             CallRTL(IL._fcmp, 3);
  1165.             GetAcc
  1166.  
  1167.         |IL.opFLOOR:
  1168.             PushAll(1);
  1169.             CallRTL(IL._floor, 1);
  1170.             GetAcc
  1171.  
  1172.         |IL.opFLT:
  1173.             PushAll(1);
  1174.             CallRTL(IL._flt, 1);
  1175.             GetAcc
  1176.  
  1177.         |IL.opUMINF:
  1178.             UnOp(r1);
  1179.             Emit(opXORC, r1, ORD({31}))
  1180.  
  1181.         |IL.opFABS:
  1182.             UnOp(r1);
  1183.             Emit(opANDC, r1, ORD({0..30}))
  1184.  
  1185.         |IL.opINF:
  1186.             movrc(GetAnyReg(), inf)
  1187.  
  1188.         |IL.opPUSHF:
  1189.             UnOp(r1);
  1190.             push(r1);
  1191.             drop
  1192.  
  1193.         |IL.opPACK:
  1194.             PushAll(2);
  1195.             CallRTL(IL._pack, 2)
  1196.  
  1197.         |IL.opPACKC:
  1198.             PushAll(1);
  1199.             pushc(param2);
  1200.             CallRTL(IL._pack, 2)
  1201.  
  1202.         |IL.opUNPK:
  1203.             PushAll(2);
  1204.             CallRTL(IL._unpk, 2)
  1205.  
  1206.         |IL.opCODE:
  1207.             OutInt(param2)
  1208.  
  1209.         END;
  1210.  
  1211.         cmd := cmd.next(IL.COMMAND)
  1212.     END;
  1213.  
  1214.     ASSERT(R.pushed = 0);
  1215.     ASSERT(R.top = -1)
  1216. END translate;
  1217.  
  1218.  
  1219. PROCEDURE prolog;
  1220. BEGIN
  1221.     Emit(opLEA, SP + LStack * 256, 0);
  1222.     Emit(opLEA, ACC + LTypes * 256, 0);
  1223.     push(ACC);
  1224.     Emit(opLEA, ACC + LHeap * 256, 0);
  1225.     push(ACC);
  1226.     pushc(CHL.Length(IL.codes.types));
  1227.     CallRTL(IL._init, 3)
  1228. END prolog;
  1229.  
  1230.  
  1231. PROCEDURE epilog (ram: INTEGER);
  1232. VAR
  1233.     tcount, dcount, i, offTypes, offStrings, szData, szGlobal, szHeapStack: INTEGER;
  1234.  
  1235. BEGIN
  1236.     Emit(opSTOP, 0, 0);
  1237.  
  1238.     offTypes := count;
  1239.  
  1240.     tcount := CHL.Length(IL.codes.types);
  1241.     FOR i := 0 TO tcount - 1 DO
  1242.         OutInt(CHL.GetInt(IL.codes.types, i))
  1243.     END;
  1244.  
  1245.     offStrings := count;
  1246.     dcount := CHL.Length(IL.codes.data);
  1247.     FOR i := 0 TO dcount - 1 DO
  1248.         OutByte(CHL.GetByte(IL.codes.data, i))
  1249.     END;
  1250.  
  1251.     IF dcount MOD 4 # 0 THEN
  1252.         i := 4 - dcount MOD 4;
  1253.         WHILE i > 0 DO
  1254.             OutByte(0);
  1255.             DEC(i)
  1256.         END
  1257.     END;
  1258.  
  1259.     szData := count - offTypes;
  1260.     szGlobal := (IL.codes.bss DIV 4 + 1) * 4;
  1261.     szHeapStack := ram - szData - szGlobal;
  1262.  
  1263.     OutInt(offTypes);
  1264.     OutInt(offStrings);
  1265.     OutInt(szGlobal DIV 4);
  1266.     OutInt(szHeapStack DIV 4);
  1267.     FOR i := 1 TO 8 DO
  1268.         OutInt(0)
  1269.     END
  1270. END epilog;
  1271.  
  1272.  
  1273. PROCEDURE CodeGen* (outname: ARRAY OF CHAR; target: INTEGER; options: PROG.OPTIONS);
  1274. CONST
  1275.     minRAM = 32*1024;
  1276.     maxRAM = 256*1024;
  1277.  
  1278. VAR
  1279.     szData, szRAM: INTEGER;
  1280.  
  1281. BEGIN
  1282.     szData := (CHL.Length(IL.codes.types) + CHL.Length(IL.codes.data) DIV 4 + IL.codes.bss DIV 4 + 2) * 4;
  1283.     szRAM := MIN(MAX(options.ram, minRAM), maxRAM) * 1024;
  1284.  
  1285.     IF szRAM - szData < 1024*1024 THEN
  1286.         ERRORS.Error(208)
  1287.     END;
  1288.  
  1289.     count := 0;
  1290.     WR.Create(outname);
  1291.  
  1292.     REG.Init(R, push, pop, mov, xchg, NIL, NIL, GPRs, {});
  1293.  
  1294.     prolog;
  1295.     translate;
  1296.     epilog(szRAM);
  1297.  
  1298.     WR.Close
  1299. END CodeGen;
  1300.  
  1301.  
  1302. END RVM32I.