REG.ob07 5.6 KB

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