Subversion Repositories Kolibri OS

Rev

Rev 8097 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2021, 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.  
  21. TYPE
  22.  
  23.     OP1 = PROCEDURE (arg: INTEGER);
  24.     OP2 = PROCEDURE (arg1, arg2: INTEGER);
  25.  
  26.     REGS* = RECORD
  27.  
  28.         regs*:   SET;
  29.         stk*:    ARRAY N OF INTEGER;
  30.         top*:    INTEGER;
  31.         pushed*: INTEGER;
  32.  
  33.         push, pop:  OP1;
  34.         mov,  xch:  OP2
  35.  
  36.     END;
  37.  
  38.  
  39. PROCEDURE push (VAR R: REGS);
  40. VAR
  41.     i, reg: INTEGER;
  42.  
  43. BEGIN
  44.     reg := R.stk[0];
  45.     INCL(R.regs, reg);
  46.     R.push(reg);
  47.     FOR i := 0 TO R.top - 1 DO
  48.         R.stk[i] := R.stk[i + 1]
  49.     END;
  50.     DEC(R.top);
  51.     INC(R.pushed)
  52. END push;
  53.  
  54.  
  55. PROCEDURE pop (VAR R: REGS; reg: INTEGER);
  56. VAR
  57.     i: INTEGER;
  58.  
  59. BEGIN
  60.     FOR i := R.top + 1 TO 1 BY -1 DO
  61.         R.stk[i] := R.stk[i - 1]
  62.     END;
  63.     R.stk[0] := reg;
  64.     EXCL(R.regs, reg);
  65.     R.pop(reg);
  66.     INC(R.top);
  67.     DEC(R.pushed)
  68. END pop;
  69.  
  70.  
  71. PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER;
  72. VAR
  73.     i: INTEGER;
  74.  
  75. BEGIN
  76.     i := R.top;
  77.     WHILE (i >= 0) & (R.stk[i] # reg) DO
  78.         DEC(i)
  79.     END
  80.  
  81.     RETURN i
  82. END InStk;
  83.  
  84.  
  85. PROCEDURE GetFreeReg (R: REGS): INTEGER;
  86. VAR
  87.     i: INTEGER;
  88.  
  89. BEGIN
  90.     i := 0;
  91.     WHILE (i < N) & ~(i IN R.regs) DO
  92.         INC(i)
  93.     END;
  94.  
  95.     IF i = N THEN
  96.         i := -1
  97.     END
  98.  
  99.     RETURN i
  100. END GetFreeReg;
  101.  
  102.  
  103. PROCEDURE Put (VAR R: REGS; reg: INTEGER);
  104. BEGIN
  105.     EXCL(R.regs, reg);
  106.     INC(R.top);
  107.     R.stk[R.top] := reg
  108. END Put;
  109.  
  110.  
  111. PROCEDURE PopAnyReg (VAR R: REGS): INTEGER;
  112. VAR
  113.     reg: INTEGER;
  114.  
  115. BEGIN
  116.     reg := GetFreeReg(R);
  117.     ASSERT(reg # -1);
  118.     ASSERT(R.top < LEN(R.stk) - 1);
  119.     ASSERT(R.pushed > 0);
  120.     pop(R, reg)
  121.  
  122.     RETURN reg
  123. END PopAnyReg;
  124.  
  125.  
  126. PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER;
  127. VAR
  128.     reg: INTEGER;
  129.  
  130. BEGIN
  131.     reg := GetFreeReg(R);
  132.     IF reg = -1 THEN
  133.         ASSERT(R.top >= 0);
  134.         reg := R.stk[0];
  135.         push(R)
  136.     END;
  137.  
  138.     Put(R, reg)
  139.  
  140.     RETURN reg
  141. END GetAnyReg;
  142.  
  143.  
  144. PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN;
  145. VAR
  146.     free: INTEGER;
  147.     res:  BOOLEAN;
  148.  
  149.  
  150.     PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER);
  151.     VAR
  152.         n1, n2: INTEGER;
  153.  
  154.     BEGIN
  155.         n1 := InStk(R, reg1);
  156.         n2 := InStk(R, reg2);
  157.         R.stk[n1] := reg2;
  158.         R.stk[n2] := reg1;
  159.         R.xch(reg1, reg2)
  160.     END exch;
  161.  
  162.  
  163. BEGIN
  164.     IF reg IN R.regs THEN
  165.         Put(R, reg);
  166.         res := TRUE
  167.     ELSE
  168.         res := InStk(R, reg) # -1;
  169.         IF res THEN
  170.             free := GetFreeReg(R);
  171.             IF free # -1 THEN
  172.                 Put(R, free);
  173.                 exch(R, reg, free)
  174.             ELSE
  175.                 push(R);
  176.                 free := GetFreeReg(R);
  177.                 ASSERT(free # -1);
  178.                 Put(R, free);
  179.                 IF free # reg THEN
  180.                     exch(R, reg, free)
  181.                 END
  182.             END
  183.         END
  184.     END
  185.  
  186.     RETURN res
  187. END GetReg;
  188.  
  189.  
  190. PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
  191. VAR
  192.     n1, n2: INTEGER;
  193.     res: BOOLEAN;
  194.  
  195. BEGIN
  196.     res := TRUE;
  197.  
  198.     IF reg1 # reg2 THEN
  199.         n1 := InStk(R, reg1);
  200.         n2 := InStk(R, reg2);
  201.  
  202.         IF (n1 # -1) & (n2 # -1) THEN
  203.             R.stk[n1] := reg2;
  204.             R.stk[n2] := reg1;
  205.             R.xch(reg2, reg1)
  206.         ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
  207.             R.stk[n1] := reg2;
  208.             INCL(R.regs, reg1);
  209.             EXCL(R.regs, reg2);
  210.             R.mov(reg2, reg1)
  211.         ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
  212.             R.stk[n2] := reg1;
  213.             EXCL(R.regs, reg1);
  214.             INCL(R.regs, reg2);
  215.             R.mov(reg1, reg2)
  216.         ELSE
  217.             res := FALSE
  218.         END
  219.     END
  220.  
  221.     RETURN res
  222. END Exchange;
  223.  
  224.  
  225. PROCEDURE Drop* (VAR R: REGS);
  226. BEGIN
  227.     INCL(R.regs, R.stk[R.top]);
  228.     DEC(R.top)
  229. END Drop;
  230.  
  231.  
  232. PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
  233. BEGIN
  234.     IF R.top > 0 THEN
  235.         reg1 := R.stk[R.top - 1];
  236.         reg2 := R.stk[R.top]
  237.     ELSIF R.top = 0 THEN
  238.         reg1 := PopAnyReg(R);
  239.         reg2 := R.stk[1]
  240.     ELSE (* R.top = -1 *)
  241.         reg2 := PopAnyReg(R);
  242.         reg1 := PopAnyReg(R)
  243.     END
  244. END BinOp;
  245.  
  246.  
  247. PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
  248. BEGIN
  249.     IF R.top >= 0 THEN
  250.         reg := R.stk[R.top]
  251.     ELSE
  252.         reg := PopAnyReg(R)
  253.     END
  254. END UnOp;
  255.  
  256.  
  257. PROCEDURE PushAll* (VAR R: REGS);
  258. BEGIN
  259.     WHILE R.top >= 0 DO
  260.         push(R)
  261.     END
  262. END PushAll;
  263.  
  264.  
  265. PROCEDURE PushAll_1* (VAR R: REGS);
  266. BEGIN
  267.     WHILE R.top >= 1 DO
  268.         push(R)
  269.     END
  270. END PushAll_1;
  271.  
  272.  
  273. PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET);
  274. BEGIN
  275.     R.regs := regs;
  276.     R.pushed := 0;
  277.     R.top := -1;
  278.  
  279.     R.push := push;
  280.     R.pop  := pop;
  281.     R.mov  := mov;
  282.     R.xch  := xch;
  283. END Init;
  284.  
  285.  
  286. END REG.