Subversion Repositories Kolibri OS

Rev

Rev 7597 | 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.     R.offs[reg] := offs;
  297.     IF size = 0 THEN
  298.         size := 8
  299.     END;
  300.     R.size[reg] := size
  301. END Lock;
  302.  
  303.  
  304. PROCEDURE Release* (VAR R: REGS; reg: INTEGER);
  305. BEGIN
  306.     ASSERT(reg IN R.vregs);
  307.     R.offs[reg] := 0
  308. END Release;
  309.  
  310.  
  311. PROCEDURE Load* (R: REGS; reg: INTEGER);
  312. VAR
  313.     offs: INTEGER;
  314.  
  315. BEGIN
  316.     ASSERT(reg IN R.vregs);
  317.     offs := R.offs[reg];
  318.     IF offs # 0 THEN
  319.         R.load(reg, offs, R.size[reg])
  320.     END
  321. END Load;
  322.  
  323.  
  324. PROCEDURE Save* (R: REGS; reg: INTEGER);
  325. VAR
  326.     offs: INTEGER;
  327.  
  328. BEGIN
  329.     ASSERT(reg IN R.vregs);
  330.     offs := R.offs[reg];
  331.     IF offs # 0 THEN
  332.         R.save(reg, offs, R.size[reg])
  333.     END
  334. END Save;
  335.  
  336.  
  337. PROCEDURE Store* (R: REGS);
  338. VAR
  339.     i: INTEGER;
  340.  
  341. BEGIN
  342.     FOR i := 0 TO NVR - 1 DO
  343.         IF i IN R.vregs THEN
  344.             Save(R, i)
  345.         END
  346.     END
  347. END Store;
  348.  
  349.  
  350. PROCEDURE Restore* (R: REGS);
  351. VAR
  352.     i: INTEGER;
  353.  
  354. BEGIN
  355.     FOR i := 0 TO NVR - 1 DO
  356.         IF i IN R.vregs THEN
  357.             Load(R, i)
  358.         END
  359.     END
  360. END Restore;
  361.  
  362.  
  363. PROCEDURE Reset* (VAR R: REGS);
  364. VAR
  365.     i: INTEGER;
  366.  
  367. BEGIN
  368.     FOR i := 0 TO NVR - 1 DO
  369.         IF i IN R.vregs THEN
  370.             R.offs[i] := 0
  371.         END
  372.     END
  373. END Reset;
  374.  
  375.  
  376. PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER;
  377. VAR
  378.     i, res: INTEGER;
  379.  
  380. BEGIN
  381.     res := -1;
  382.     i := 0;
  383.     WHILE i < NVR DO
  384.         IF (i IN R.vregs) & (R.offs[i] = offs) THEN
  385.             res := i;
  386.             i := NVR
  387.         END;
  388.         INC(i)
  389.     END
  390.  
  391.     RETURN res
  392. END GetVarReg;
  393.  
  394.  
  395. PROCEDURE GetAnyVarReg* (R: REGS): INTEGER;
  396. VAR
  397.     i, res: INTEGER;
  398.  
  399. BEGIN
  400.     res := -1;
  401.     i := 0;
  402.     WHILE i < NVR DO
  403.         IF (i IN R.vregs) & (R.offs[i] = 0) THEN
  404.             res := i;
  405.             i := NVR
  406.         END;
  407.         INC(i)
  408.     END
  409.  
  410.     RETURN res
  411. END GetAnyVarReg;
  412.  
  413.  
  414. PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET);
  415. VAR
  416.     i: INTEGER;
  417.  
  418. BEGIN
  419.     R.regs := regs;
  420.     R.pushed := 0;
  421.     R.top := -1;
  422.  
  423.     R.push := push;
  424.     R.pop  := pop;
  425.     R.mov  := mov;
  426.     R.xch  := xch;
  427.     R.load := load;
  428.     R.save := save;
  429.  
  430.     R.vregs := vregs;
  431.  
  432.     FOR i := 0 TO NVR - 1 DO
  433.         R.offs[i] := 0;
  434.         R.size[i] := 0
  435.     END
  436.  
  437. END Init;
  438.  
  439.  
  440. END REG.