Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018-2020, 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: 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.         res := InStk(R, reg) # -1;
  182.         IF res 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.         END
  197.     END
  198.  
  199.     RETURN res
  200. END GetReg;
  201.  
  202.  
  203. PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
  204. VAR
  205.     n1, n2: INTEGER;
  206.     res: BOOLEAN;
  207.  
  208. BEGIN
  209.     res := FALSE;
  210.  
  211.     IF reg1 # reg2 THEN
  212.         n1 := InStk(R, reg1);
  213.         n2 := InStk(R, reg2);
  214.  
  215.         IF (n1 # -1) & (n2 # -1) THEN
  216.             R.stk[n1] := reg2;
  217.             R.stk[n2] := reg1;
  218.             R.xch(reg2, reg1);
  219.             res := TRUE
  220.         ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
  221.             R.stk[n1] := reg2;
  222.             INCL(R.regs, reg1);
  223.             EXCL(R.regs, reg2);
  224.             R.mov(reg2, reg1);
  225.             res := TRUE
  226.         ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
  227.             R.stk[n2] := reg1;
  228.             EXCL(R.regs, reg1);
  229.             INCL(R.regs, reg2);
  230.             R.mov(reg1, reg2);
  231.             res := TRUE
  232.         END
  233.     ELSE
  234.         res := TRUE
  235.     END
  236.  
  237.     RETURN res
  238. END Exchange;
  239.  
  240.  
  241. PROCEDURE Drop* (VAR R: REGS);
  242. BEGIN
  243.     INCL(R.regs, R.stk[R.top]);
  244.     DEC(R.top)
  245. END Drop;
  246.  
  247.  
  248. PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
  249. BEGIN
  250.     IF R.top > 0 THEN
  251.         reg1 := R.stk[R.top - 1];
  252.         reg2 := R.stk[R.top]
  253.     ELSIF R.top = 0 THEN
  254.         reg1 := PopAnyReg(R);
  255.         reg2 := R.stk[R.top]
  256.     ELSIF R.top < 0 THEN
  257.         reg2 := PopAnyReg(R);
  258.         reg1 := PopAnyReg(R)
  259.     END
  260. END BinOp;
  261.  
  262.  
  263. PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
  264. BEGIN
  265.     IF R.top >= 0 THEN
  266.         reg := R.stk[R.top]
  267.     ELSE
  268.         reg := PopAnyReg(R)
  269.     END
  270. END UnOp;
  271.  
  272.  
  273. PROCEDURE PushAll* (VAR R: REGS);
  274. BEGIN
  275.     WHILE R.top >= 0 DO
  276.         push(R)
  277.     END
  278. END PushAll;
  279.  
  280.  
  281. PROCEDURE PushAll_1* (VAR R: REGS);
  282. BEGIN
  283.     WHILE R.top >= 1 DO
  284.         push(R)
  285.     END
  286. END PushAll_1;
  287.  
  288.  
  289. PROCEDURE Lock* (VAR R: REGS; reg, offs, size: INTEGER);
  290. BEGIN
  291.     ASSERT(reg IN R.vregs);
  292.     ASSERT(offs # 0);
  293.     ASSERT(size IN {1, 2, 4, 8});
  294.     R.offs[reg] := offs;
  295.     R.size[reg] := size
  296. END Lock;
  297.  
  298.  
  299. PROCEDURE Release* (VAR R: REGS; reg: INTEGER);
  300. BEGIN
  301.     ASSERT(reg IN R.vregs);
  302.     R.offs[reg] := 0
  303. END Release;
  304.  
  305.  
  306. PROCEDURE Load* (R: REGS; reg: INTEGER);
  307. VAR
  308.     offs: INTEGER;
  309.  
  310. BEGIN
  311.     ASSERT(reg IN R.vregs);
  312.     offs := R.offs[reg];
  313.     IF offs # 0 THEN
  314.         R.load(reg, offs, R.size[reg])
  315.     END
  316. END Load;
  317.  
  318.  
  319. PROCEDURE Save* (R: REGS; reg: INTEGER);
  320. VAR
  321.     offs: INTEGER;
  322.  
  323. BEGIN
  324.     ASSERT(reg IN R.vregs);
  325.     offs := R.offs[reg];
  326.     IF offs # 0 THEN
  327.         R.save(reg, offs, R.size[reg])
  328.     END
  329. END Save;
  330.  
  331.  
  332. PROCEDURE Store* (R: REGS);
  333. VAR
  334.     i: INTEGER;
  335.  
  336. BEGIN
  337.     FOR i := 0 TO NVR - 1 DO
  338.         IF i IN R.vregs THEN
  339.             Save(R, i)
  340.         END
  341.     END
  342. END Store;
  343.  
  344.  
  345. PROCEDURE Restore* (R: REGS);
  346. VAR
  347.     i: INTEGER;
  348.  
  349. BEGIN
  350.     FOR i := 0 TO NVR - 1 DO
  351.         IF i IN R.vregs THEN
  352.             Load(R, i)
  353.         END
  354.     END
  355. END Restore;
  356.  
  357.  
  358. PROCEDURE Reset* (VAR R: REGS);
  359. VAR
  360.     i: INTEGER;
  361.  
  362. BEGIN
  363.     FOR i := 0 TO NVR - 1 DO
  364.         IF i IN R.vregs THEN
  365.             R.offs[i] := 0
  366.         END
  367.     END
  368. END Reset;
  369.  
  370.  
  371. PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER;
  372. VAR
  373.     i, res: INTEGER;
  374.  
  375. BEGIN
  376.     res := -1;
  377.     i := 0;
  378.     WHILE i < NVR DO
  379.         IF (i IN R.vregs) & (R.offs[i] = offs) THEN
  380.             res := i;
  381.             i := NVR
  382.         END;
  383.         INC(i)
  384.     END
  385.  
  386.     RETURN res
  387. END GetVarReg;
  388.  
  389.  
  390. PROCEDURE GetAnyVarReg* (R: REGS): INTEGER;
  391. VAR
  392.     i, res: INTEGER;
  393.  
  394. BEGIN
  395.     res := -1;
  396.     i := 0;
  397.     WHILE i < NVR DO
  398.         IF (i IN R.vregs) & (R.offs[i] = 0) THEN
  399.             res := i;
  400.             i := NVR
  401.         END;
  402.         INC(i)
  403.     END
  404.  
  405.     RETURN res
  406. END GetAnyVarReg;
  407.  
  408.  
  409. PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET);
  410. VAR
  411.     i: INTEGER;
  412.  
  413. BEGIN
  414.     R.regs := regs;
  415.     R.pushed := 0;
  416.     R.top := -1;
  417.  
  418.     R.push := push;
  419.     R.pop  := pop;
  420.     R.mov  := mov;
  421.     R.xch  := xch;
  422.     R.load := load;
  423.     R.save := save;
  424.  
  425.     R.vregs := vregs;
  426.  
  427.     FOR i := 0 TO NVR - 1 DO
  428.         R.offs[i] := 0;
  429.         R.size[i] := 0
  430.     END
  431.  
  432. END Init;
  433.  
  434.  
  435. END REG.