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