REG.ob07 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2021, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE REG;
  7. CONST
  8. N = 16;
  9. R0* = 0; R1* = 1; R2* = 2; R3* = 3;
  10. R4* = 4; R5* = 5; R6* = 6; R7* = 7;
  11. R8* = 8; R9* = 9; R10* = 10; R11* = 11;
  12. R12* = 12; R13* = 13; R14* = 14; R15* = 15;
  13. TYPE
  14. OP1 = PROCEDURE (arg: INTEGER);
  15. OP2 = PROCEDURE (arg1, arg2: INTEGER);
  16. REGS* = RECORD
  17. regs*: SET;
  18. stk*: ARRAY N OF INTEGER;
  19. top*: INTEGER;
  20. pushed*: INTEGER;
  21. push, pop: OP1;
  22. mov, xch: OP2
  23. END;
  24. PROCEDURE push (VAR R: REGS);
  25. VAR
  26. i, reg: INTEGER;
  27. BEGIN
  28. reg := R.stk[0];
  29. INCL(R.regs, reg);
  30. R.push(reg);
  31. FOR i := 0 TO R.top - 1 DO
  32. R.stk[i] := R.stk[i + 1]
  33. END;
  34. DEC(R.top);
  35. INC(R.pushed)
  36. END push;
  37. PROCEDURE pop (VAR R: REGS; reg: INTEGER);
  38. VAR
  39. i: INTEGER;
  40. BEGIN
  41. FOR i := R.top + 1 TO 1 BY -1 DO
  42. R.stk[i] := R.stk[i - 1]
  43. END;
  44. R.stk[0] := reg;
  45. EXCL(R.regs, reg);
  46. R.pop(reg);
  47. INC(R.top);
  48. DEC(R.pushed)
  49. END pop;
  50. PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER;
  51. VAR
  52. i: INTEGER;
  53. BEGIN
  54. i := R.top;
  55. WHILE (i >= 0) & (R.stk[i] # reg) DO
  56. DEC(i)
  57. END
  58. RETURN i
  59. END InStk;
  60. PROCEDURE GetFreeReg (R: REGS): INTEGER;
  61. VAR
  62. i: INTEGER;
  63. BEGIN
  64. i := 0;
  65. WHILE (i < N) & ~(i IN R.regs) DO
  66. INC(i)
  67. END;
  68. IF i = N THEN
  69. i := -1
  70. END
  71. RETURN i
  72. END GetFreeReg;
  73. PROCEDURE Put (VAR R: REGS; reg: INTEGER);
  74. BEGIN
  75. EXCL(R.regs, reg);
  76. INC(R.top);
  77. R.stk[R.top] := reg
  78. END Put;
  79. PROCEDURE PopAnyReg (VAR R: REGS): INTEGER;
  80. VAR
  81. reg: INTEGER;
  82. BEGIN
  83. reg := GetFreeReg(R);
  84. ASSERT(reg # -1);
  85. ASSERT(R.top < LEN(R.stk) - 1);
  86. ASSERT(R.pushed > 0);
  87. pop(R, reg)
  88. RETURN reg
  89. END PopAnyReg;
  90. PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER;
  91. VAR
  92. reg: INTEGER;
  93. BEGIN
  94. reg := GetFreeReg(R);
  95. IF reg = -1 THEN
  96. ASSERT(R.top >= 0);
  97. reg := R.stk[0];
  98. push(R)
  99. END;
  100. Put(R, reg)
  101. RETURN reg
  102. END GetAnyReg;
  103. PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN;
  104. VAR
  105. free: INTEGER;
  106. res: BOOLEAN;
  107. PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER);
  108. VAR
  109. n1, n2: INTEGER;
  110. BEGIN
  111. n1 := InStk(R, reg1);
  112. n2 := InStk(R, reg2);
  113. R.stk[n1] := reg2;
  114. R.stk[n2] := reg1;
  115. R.xch(reg1, reg2)
  116. END exch;
  117. BEGIN
  118. IF reg IN R.regs THEN
  119. Put(R, reg);
  120. res := TRUE
  121. ELSE
  122. res := InStk(R, reg) # -1;
  123. IF res THEN
  124. free := GetFreeReg(R);
  125. IF free # -1 THEN
  126. Put(R, free);
  127. exch(R, reg, free)
  128. ELSE
  129. push(R);
  130. free := GetFreeReg(R);
  131. ASSERT(free # -1);
  132. Put(R, free);
  133. IF free # reg THEN
  134. exch(R, reg, free)
  135. END
  136. END
  137. END
  138. END
  139. RETURN res
  140. END GetReg;
  141. PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
  142. VAR
  143. n1, n2: INTEGER;
  144. res: BOOLEAN;
  145. BEGIN
  146. res := TRUE;
  147. IF reg1 # reg2 THEN
  148. n1 := InStk(R, reg1);
  149. n2 := InStk(R, reg2);
  150. IF (n1 # -1) & (n2 # -1) THEN
  151. R.stk[n1] := reg2;
  152. R.stk[n2] := reg1;
  153. R.xch(reg2, reg1)
  154. ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
  155. R.stk[n1] := reg2;
  156. INCL(R.regs, reg1);
  157. EXCL(R.regs, reg2);
  158. R.mov(reg2, reg1)
  159. ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
  160. R.stk[n2] := reg1;
  161. EXCL(R.regs, reg1);
  162. INCL(R.regs, reg2);
  163. R.mov(reg1, reg2)
  164. ELSE
  165. res := FALSE
  166. END
  167. END
  168. RETURN res
  169. END Exchange;
  170. PROCEDURE Drop* (VAR R: REGS);
  171. BEGIN
  172. INCL(R.regs, R.stk[R.top]);
  173. DEC(R.top)
  174. END Drop;
  175. PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
  176. BEGIN
  177. IF R.top > 0 THEN
  178. reg1 := R.stk[R.top - 1];
  179. reg2 := R.stk[R.top]
  180. ELSIF R.top = 0 THEN
  181. reg1 := PopAnyReg(R);
  182. reg2 := R.stk[1]
  183. ELSE (* R.top = -1 *)
  184. reg2 := PopAnyReg(R);
  185. reg1 := PopAnyReg(R)
  186. END
  187. END BinOp;
  188. PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
  189. BEGIN
  190. IF R.top >= 0 THEN
  191. reg := R.stk[R.top]
  192. ELSE
  193. reg := PopAnyReg(R)
  194. END
  195. END UnOp;
  196. PROCEDURE PushAll* (VAR R: REGS);
  197. BEGIN
  198. WHILE R.top >= 0 DO
  199. push(R)
  200. END
  201. END PushAll;
  202. PROCEDURE PushAll_1* (VAR R: REGS);
  203. BEGIN
  204. WHILE R.top >= 1 DO
  205. push(R)
  206. END
  207. END PushAll_1;
  208. PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET);
  209. BEGIN
  210. R.regs := regs;
  211. R.pushed := 0;
  212. R.top := -1;
  213. R.push := push;
  214. R.pop := pop;
  215. R.mov := mov;
  216. R.xch := xch;
  217. END Init;
  218. END REG.