Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2019, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE REG;
  9.  
  10.  
  11. CONST
  12.  
  13.     N = 16;
  14.  
  15.     R0*  =  0;  R1*  =  1;  R2*  =  2;  R3*  =  3;
  16.     R4*  =  4;  R5*  =  5;  R6*  =  6;  R7*  =  7;
  17.     R8*  =  8;  R9*  =  9;  R10* = 10;  R11* = 11;
  18.     R12* = 12;  R13* = 13;  R14* = 14;  R15* = 15;
  19.  
  20.     NVR = 32;
  21.  
  22.  
  23. TYPE
  24.  
  25.     OP1 = PROCEDURE (arg: INTEGER);
  26.     OP2 = PROCEDURE (arg1, arg2: INTEGER);
  27.     OP3 = PROCEDURE (arg1, arg2, arg3: INTEGER);
  28.  
  29.     REGS* = RECORD
  30.  
  31.         regs*:   SET;
  32.         stk*:    ARRAY N OF INTEGER;
  33.         top*:    INTEGER;
  34.         pushed*: INTEGER;
  35.  
  36.         vregs*:  SET;
  37.         offs:    ARRAY NVR OF INTEGER;
  38.         size:    ARRAY NVR OF INTEGER;
  39.  
  40.         push, pop:  OP1;
  41.         mov,  xch:  OP2;
  42.         load, save: OP3
  43.  
  44.     END;
  45.  
  46.  
  47. PROCEDURE push (VAR R: REGS);
  48. VAR
  49.     i, reg: INTEGER;
  50.  
  51. BEGIN
  52.     reg := R.stk[0];
  53.     INCL(R.regs, reg);
  54.     R.push(reg);
  55.     FOR i := 0 TO R.top - 1 DO
  56.         R.stk[i] := R.stk[i + 1]
  57.     END;
  58.     DEC(R.top);
  59.     INC(R.pushed)
  60. END push;
  61.  
  62.  
  63. PROCEDURE pop (VAR R: REGS; reg: INTEGER);
  64. VAR
  65.     i: INTEGER;
  66.  
  67. BEGIN
  68.     FOR i := R.top + 1 TO 1 BY -1 DO
  69.         R.stk[i] := R.stk[i - 1]
  70.     END;
  71.     R.stk[0] := reg;
  72.     EXCL(R.regs, reg);
  73.     R.pop(reg);
  74.     INC(R.top);
  75.     DEC(R.pushed)
  76. END pop;
  77.  
  78.  
  79. PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER;
  80. VAR
  81.     i, n: INTEGER;
  82.  
  83. BEGIN
  84.     i := 0;
  85.     n := R.top;
  86.     WHILE (i <= n) & (R.stk[i] # reg) DO
  87.         INC(i)
  88.     END;
  89.  
  90.     IF i > n THEN
  91.         i := -1
  92.     END
  93.  
  94.     RETURN i
  95. END InStk;
  96.  
  97.  
  98. PROCEDURE GetFreeReg (R: REGS): INTEGER;
  99. VAR
  100.     i: INTEGER;
  101.  
  102. BEGIN
  103.     i := 0;
  104.     WHILE (i < N) & ~(i IN R.regs) DO
  105.         INC(i)
  106.     END;
  107.  
  108.     IF i = N THEN
  109.         i := -1
  110.     END
  111.  
  112.     RETURN i
  113. END GetFreeReg;
  114.  
  115.  
  116. PROCEDURE Put (VAR R: REGS; reg: INTEGER);
  117. BEGIN
  118.     EXCL(R.regs, reg);
  119.     INC(R.top);
  120.     R.stk[R.top] := reg
  121. END Put;
  122.  
  123.  
  124. PROCEDURE PopAnyReg (VAR R: REGS): INTEGER;
  125. VAR
  126.     reg: INTEGER;
  127.  
  128. BEGIN
  129.     reg := GetFreeReg(R);
  130.     ASSERT(reg # -1);
  131.     ASSERT(R.top < LEN(R.stk) - 1);
  132.     ASSERT(R.pushed > 0);
  133.     pop(R, reg)
  134.  
  135.     RETURN reg
  136. END PopAnyReg;
  137.  
  138.  
  139. PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER;
  140. VAR
  141.     reg: INTEGER;
  142.  
  143. BEGIN
  144.     reg := GetFreeReg(R);
  145.     IF reg = -1 THEN
  146.         ASSERT(R.top >= 0);
  147.         reg := R.stk[0];
  148.         push(R)
  149.     END;
  150.  
  151.     Put(R, reg)
  152.  
  153.     RETURN reg
  154. END GetAnyReg;
  155.  
  156.  
  157. PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN;
  158. VAR
  159.     free, n: INTEGER;
  160.     res: BOOLEAN;
  161.  
  162.  
  163.     PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER);
  164.     VAR
  165.         n1, n2: INTEGER;
  166.  
  167.     BEGIN
  168.         n1 := InStk(R, reg1);
  169.         n2 := InStk(R, reg2);
  170.         R.stk[n1] := reg2;
  171.         R.stk[n2] := reg1;
  172.         R.xch(reg1, reg2)
  173.     END exch;
  174.  
  175.  
  176. BEGIN
  177.     IF reg IN R.regs THEN
  178.         Put(R, reg);
  179.         res := TRUE
  180.     ELSE
  181.         n := InStk(R, reg);
  182.         IF n # -1 THEN
  183.             free := GetFreeReg(R);
  184.             IF free # -1 THEN
  185.                 Put(R, free);
  186.                 exch(R, reg, free)
  187.             ELSE
  188.                 push(R);
  189.                 free := GetFreeReg(R);
  190.                 ASSERT(free # -1);
  191.                 Put(R, free);
  192.                 IF free # reg THEN
  193.                     exch(R, reg, free)
  194.                 END
  195.             END;
  196.             res := TRUE
  197.         ELSE
  198.             res := FALSE
  199.         END
  200.     END
  201.  
  202.     RETURN res
  203. END GetReg;
  204.  
  205.  
  206. PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
  207. VAR
  208.     n1, n2: INTEGER;
  209.     res: BOOLEAN;
  210.  
  211. BEGIN
  212.     res := FALSE;
  213.  
  214.     IF reg1 # reg2 THEN
  215.         n1 := InStk(R, reg1);
  216.         n2 := InStk(R, reg2);
  217.  
  218.         IF (n1 # -1) & (n2 # -1) THEN
  219.             R.stk[n1] := reg2;
  220.             R.stk[n2] := reg1;
  221.             R.xch(reg2, reg1);
  222.             res := TRUE
  223.         ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
  224.             R.stk[n1] := reg2;
  225.             INCL(R.regs, reg1);
  226.             EXCL(R.regs, reg2);
  227.             R.mov(reg2, reg1);
  228.             res := TRUE
  229.         ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
  230.             R.stk[n2] := reg1;
  231.             EXCL(R.regs, reg1);
  232.             INCL(R.regs, reg2);
  233.             R.mov(reg1, reg2);
  234.             res := TRUE
  235.         END
  236.     ELSE
  237.         res := TRUE
  238.     END
  239.  
  240.     RETURN res
  241. END Exchange;
  242.  
  243.  
  244. PROCEDURE Drop* (VAR R: REGS);
  245. BEGIN
  246.     INCL(R.regs, R.stk[R.top]);
  247.     DEC(R.top)
  248. END Drop;
  249.  
  250.  
  251. PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
  252. BEGIN
  253.     IF R.top > 0 THEN
  254.         reg1 := R.stk[R.top - 1];
  255.         reg2 := R.stk[R.top]
  256.     ELSIF R.top = 0 THEN
  257.         reg1 := PopAnyReg(R);
  258.         reg2 := R.stk[R.top]
  259.     ELSIF R.top < 0 THEN
  260.         reg2 := PopAnyReg(R);
  261.         reg1 := PopAnyReg(R)
  262.     END
  263. END BinOp;
  264.  
  265.  
  266. PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
  267. BEGIN
  268.     IF R.top >= 0 THEN
  269.         reg := R.stk[R.top]
  270.     ELSE
  271.         reg := PopAnyReg(R)
  272.     END
  273. END UnOp;
  274.  
  275.  
  276. PROCEDURE PushAll* (VAR R: REGS);
  277. BEGIN
  278.     WHILE R.top >= 0 DO
  279.         push(R)
  280.     END
  281. END PushAll;
  282.  
  283.  
  284. PROCEDURE PushAll_1* (VAR R: REGS);
  285. BEGIN
  286.     WHILE R.top >= 1 DO
  287.         push(R)
  288.     END
  289. END PushAll_1;
  290.  
  291.  
  292. PROCEDURE Lock* (VAR R: REGS; reg, offs, size: INTEGER);
  293. BEGIN
  294.     ASSERT(reg IN R.vregs);
  295.     ASSERT(offs # 0);
  296.     ASSERT(size IN {1, 2, 4, 8});
  297.     R.offs[reg] := offs;
  298.     R.size[reg] := size
  299. END Lock;
  300.  
  301.  
  302. PROCEDURE Release* (VAR R: REGS; reg: INTEGER);
  303. BEGIN
  304.     ASSERT(reg IN R.vregs);
  305.     R.offs[reg] := 0
  306. END Release;
  307.  
  308.  
  309. PROCEDURE Load* (R: REGS; reg: INTEGER);
  310. VAR
  311.     offs: INTEGER;
  312.  
  313. BEGIN
  314.     ASSERT(reg IN R.vregs);
  315.     offs := R.offs[reg];
  316.     IF offs # 0 THEN
  317.         R.load(reg, offs, R.size[reg])
  318.     END
  319. END Load;
  320.  
  321.  
  322. PROCEDURE Save* (R: REGS; reg: INTEGER);
  323. VAR
  324.     offs: INTEGER;
  325.  
  326. BEGIN
  327.     ASSERT(reg IN R.vregs);
  328.     offs := R.offs[reg];
  329.     IF offs # 0 THEN
  330.         R.save(reg, offs, R.size[reg])
  331.     END
  332. END Save;
  333.  
  334.  
  335. PROCEDURE Store* (R: REGS);
  336. VAR
  337.     i: INTEGER;
  338.  
  339. BEGIN
  340.     FOR i := 0 TO NVR - 1 DO
  341.         IF i IN R.vregs THEN
  342.             Save(R, i)
  343.         END
  344.     END
  345. END Store;
  346.  
  347.  
  348. PROCEDURE Restore* (R: REGS);
  349. VAR
  350.     i: INTEGER;
  351.  
  352. BEGIN
  353.     FOR i := 0 TO NVR - 1 DO
  354.         IF i IN R.vregs THEN
  355.             Load(R, i)
  356.         END
  357.     END
  358. END Restore;
  359.  
  360.  
  361. PROCEDURE Reset* (VAR R: REGS);
  362. VAR
  363.     i: INTEGER;
  364.  
  365. BEGIN
  366.     FOR i := 0 TO NVR - 1 DO
  367.         IF i IN R.vregs THEN
  368.             R.offs[i] := 0
  369.         END
  370.     END
  371. END Reset;
  372.  
  373.  
  374. PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER;
  375. VAR
  376.     i, res: INTEGER;
  377.  
  378. BEGIN
  379.     res := -1;
  380.     i := 0;
  381.     WHILE i < NVR DO
  382.         IF (i IN R.vregs) & (R.offs[i] = offs) THEN
  383.             res := i;
  384.             i := NVR
  385.         END;
  386.         INC(i)
  387.     END
  388.  
  389.     RETURN res
  390. END GetVarReg;
  391.  
  392.  
  393. PROCEDURE GetAnyVarReg* (R: REGS): INTEGER;
  394. VAR
  395.     i, res: INTEGER;
  396.  
  397. BEGIN
  398.     res := -1;
  399.     i := 0;
  400.     WHILE i < NVR DO
  401.         IF (i IN R.vregs) & (R.offs[i] = 0) THEN
  402.             res := i;
  403.             i := NVR
  404.         END;
  405.         INC(i)
  406.     END
  407.  
  408.     RETURN res
  409. END GetAnyVarReg;
  410.  
  411.  
  412. PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET);
  413. VAR
  414.     i: INTEGER;
  415.  
  416. BEGIN
  417.     R.regs := regs;
  418.     R.pushed := 0;
  419.     R.top := -1;
  420.  
  421.     R.push := push;
  422.     R.pop  := pop;
  423.     R.mov  := mov;
  424.     R.xch  := xch;
  425.     R.load := load;
  426.     R.save := save;
  427.  
  428.     R.vregs := vregs;
  429.  
  430.     FOR i := 0 TO NVR - 1 DO
  431.         R.offs[i] := 0;
  432.         R.size[i] := 0
  433.     END
  434.  
  435. END Init;
  436.  
  437.  
  438. END REG.