Rev 8097 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7983 | leency | 1 | (* |
7597 | akron1 | 2 | BSD 2-Clause License |
3 | |||
8859 | leency | 4 | Copyright (c) 2018-2021, Anton Krotov |
7597 | akron1 | 5 | All rights reserved. |
6 | *) |
||
7 | |||
8 | MODULE REG; |
||
9 | |||
10 | |||
11 | CONST |
||
12 | |||
13 | N = 16; |
||
14 | |||
7693 | akron1 | 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; |
||
7597 | akron1 | 19 | |
20 | |||
21 | TYPE |
||
22 | |||
23 | OP1 = PROCEDURE (arg: INTEGER); |
||
24 | OP2 = PROCEDURE (arg1, arg2: INTEGER); |
||
25 | |||
7693 | akron1 | 26 | REGS* = RECORD |
7597 | akron1 | 27 | |
28 | regs*: SET; |
||
29 | stk*: ARRAY N OF INTEGER; |
||
30 | top*: INTEGER; |
||
31 | pushed*: INTEGER; |
||
32 | |||
33 | push, pop: OP1; |
||
8859 | leency | 34 | mov, xch: OP2 |
7597 | akron1 | 35 | |
36 | END; |
||
37 | |||
38 | |||
7693 | akron1 | 39 | PROCEDURE push (VAR R: REGS); |
7597 | akron1 | 40 | VAR |
41 | i, reg: INTEGER; |
||
42 | |||
43 | BEGIN |
||
44 | reg := R.stk[0]; |
||
45 | INCL(R.regs, reg); |
||
46 | R.push(reg); |
||
47 | FOR i := 0 TO R.top - 1 DO |
||
48 | R.stk[i] := R.stk[i + 1] |
||
49 | END; |
||
50 | DEC(R.top); |
||
51 | INC(R.pushed) |
||
52 | END push; |
||
53 | |||
54 | |||
7693 | akron1 | 55 | PROCEDURE pop (VAR R: REGS; reg: INTEGER); |
7597 | akron1 | 56 | VAR |
57 | i: INTEGER; |
||
58 | |||
59 | BEGIN |
||
60 | FOR i := R.top + 1 TO 1 BY -1 DO |
||
61 | R.stk[i] := R.stk[i - 1] |
||
62 | END; |
||
63 | R.stk[0] := reg; |
||
64 | EXCL(R.regs, reg); |
||
65 | R.pop(reg); |
||
66 | INC(R.top); |
||
67 | DEC(R.pushed) |
||
68 | END pop; |
||
69 | |||
70 | |||
71 | PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER; |
||
72 | VAR |
||
8859 | leency | 73 | i: INTEGER; |
7597 | akron1 | 74 | |
75 | BEGIN |
||
8859 | leency | 76 | i := R.top; |
77 | WHILE (i >= 0) & (R.stk[i] # reg) DO |
||
78 | DEC(i) |
||
7597 | akron1 | 79 | END |
80 | |||
81 | RETURN i |
||
82 | END InStk; |
||
83 | |||
84 | |||
85 | PROCEDURE GetFreeReg (R: REGS): INTEGER; |
||
86 | VAR |
||
87 | i: INTEGER; |
||
88 | |||
89 | BEGIN |
||
90 | i := 0; |
||
91 | WHILE (i < N) & ~(i IN R.regs) DO |
||
92 | INC(i) |
||
93 | END; |
||
94 | |||
95 | IF i = N THEN |
||
96 | i := -1 |
||
97 | END |
||
98 | |||
99 | RETURN i |
||
100 | END GetFreeReg; |
||
101 | |||
102 | |||
7693 | akron1 | 103 | PROCEDURE Put (VAR R: REGS; reg: INTEGER); |
7597 | akron1 | 104 | BEGIN |
105 | EXCL(R.regs, reg); |
||
106 | INC(R.top); |
||
107 | R.stk[R.top] := reg |
||
108 | END Put; |
||
109 | |||
110 | |||
7693 | akron1 | 111 | PROCEDURE PopAnyReg (VAR R: REGS): INTEGER; |
7597 | akron1 | 112 | VAR |
113 | reg: INTEGER; |
||
114 | |||
115 | BEGIN |
||
116 | reg := GetFreeReg(R); |
||
117 | ASSERT(reg # -1); |
||
118 | ASSERT(R.top < LEN(R.stk) - 1); |
||
119 | ASSERT(R.pushed > 0); |
||
120 | pop(R, reg) |
||
121 | |||
122 | RETURN reg |
||
123 | END PopAnyReg; |
||
124 | |||
125 | |||
7693 | akron1 | 126 | PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER; |
7597 | akron1 | 127 | VAR |
128 | reg: INTEGER; |
||
129 | |||
130 | BEGIN |
||
131 | reg := GetFreeReg(R); |
||
132 | IF reg = -1 THEN |
||
133 | ASSERT(R.top >= 0); |
||
134 | reg := R.stk[0]; |
||
135 | push(R) |
||
136 | END; |
||
137 | |||
138 | Put(R, reg) |
||
139 | |||
140 | RETURN reg |
||
141 | END GetAnyReg; |
||
142 | |||
143 | |||
7693 | akron1 | 144 | PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN; |
7597 | akron1 | 145 | VAR |
8097 | maxcodehac | 146 | free: INTEGER; |
147 | res: BOOLEAN; |
||
7597 | akron1 | 148 | |
149 | |||
7693 | akron1 | 150 | PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER); |
7597 | akron1 | 151 | VAR |
152 | n1, n2: INTEGER; |
||
153 | |||
154 | BEGIN |
||
155 | n1 := InStk(R, reg1); |
||
156 | n2 := InStk(R, reg2); |
||
157 | R.stk[n1] := reg2; |
||
158 | R.stk[n2] := reg1; |
||
159 | R.xch(reg1, reg2) |
||
160 | END exch; |
||
161 | |||
162 | |||
163 | BEGIN |
||
164 | IF reg IN R.regs THEN |
||
165 | Put(R, reg); |
||
166 | res := TRUE |
||
167 | ELSE |
||
8097 | maxcodehac | 168 | res := InStk(R, reg) # -1; |
169 | IF res THEN |
||
7597 | akron1 | 170 | free := GetFreeReg(R); |
171 | IF free # -1 THEN |
||
172 | Put(R, free); |
||
173 | exch(R, reg, free) |
||
174 | ELSE |
||
175 | push(R); |
||
176 | free := GetFreeReg(R); |
||
177 | ASSERT(free # -1); |
||
178 | Put(R, free); |
||
179 | IF free # reg THEN |
||
180 | exch(R, reg, free) |
||
181 | END |
||
8097 | maxcodehac | 182 | END |
7597 | akron1 | 183 | END |
184 | END |
||
185 | |||
186 | RETURN res |
||
187 | END GetReg; |
||
188 | |||
189 | |||
7693 | akron1 | 190 | PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN; |
7597 | akron1 | 191 | VAR |
192 | n1, n2: INTEGER; |
||
193 | res: BOOLEAN; |
||
194 | |||
195 | BEGIN |
||
8859 | leency | 196 | res := TRUE; |
7597 | akron1 | 197 | |
198 | IF reg1 # reg2 THEN |
||
199 | n1 := InStk(R, reg1); |
||
200 | n2 := InStk(R, reg2); |
||
201 | |||
202 | IF (n1 # -1) & (n2 # -1) THEN |
||
203 | R.stk[n1] := reg2; |
||
204 | R.stk[n2] := reg1; |
||
8859 | leency | 205 | R.xch(reg2, reg1) |
7597 | akron1 | 206 | ELSIF (n1 # -1) & (reg2 IN R.regs) THEN |
207 | R.stk[n1] := reg2; |
||
208 | INCL(R.regs, reg1); |
||
209 | EXCL(R.regs, reg2); |
||
8859 | leency | 210 | R.mov(reg2, reg1) |
7597 | akron1 | 211 | ELSIF (n2 # -1) & (reg1 IN R.regs) THEN |
212 | R.stk[n2] := reg1; |
||
213 | EXCL(R.regs, reg1); |
||
214 | INCL(R.regs, reg2); |
||
8859 | leency | 215 | R.mov(reg1, reg2) |
216 | ELSE |
||
217 | res := FALSE |
||
7597 | akron1 | 218 | END |
219 | END |
||
220 | |||
221 | RETURN res |
||
222 | END Exchange; |
||
223 | |||
224 | |||
7693 | akron1 | 225 | PROCEDURE Drop* (VAR R: REGS); |
7597 | akron1 | 226 | BEGIN |
227 | INCL(R.regs, R.stk[R.top]); |
||
228 | DEC(R.top) |
||
229 | END Drop; |
||
230 | |||
231 | |||
7693 | akron1 | 232 | PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER); |
7597 | akron1 | 233 | BEGIN |
234 | IF R.top > 0 THEN |
||
235 | reg1 := R.stk[R.top - 1]; |
||
236 | reg2 := R.stk[R.top] |
||
237 | ELSIF R.top = 0 THEN |
||
238 | reg1 := PopAnyReg(R); |
||
8859 | leency | 239 | reg2 := R.stk[1] |
240 | ELSE (* R.top = -1 *) |
||
7597 | akron1 | 241 | reg2 := PopAnyReg(R); |
242 | reg1 := PopAnyReg(R) |
||
243 | END |
||
244 | END BinOp; |
||
245 | |||
246 | |||
7693 | akron1 | 247 | PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER); |
7597 | akron1 | 248 | BEGIN |
249 | IF R.top >= 0 THEN |
||
250 | reg := R.stk[R.top] |
||
251 | ELSE |
||
252 | reg := PopAnyReg(R) |
||
253 | END |
||
254 | END UnOp; |
||
255 | |||
256 | |||
7693 | akron1 | 257 | PROCEDURE PushAll* (VAR R: REGS); |
7597 | akron1 | 258 | BEGIN |
259 | WHILE R.top >= 0 DO |
||
260 | push(R) |
||
261 | END |
||
262 | END PushAll; |
||
263 | |||
264 | |||
7693 | akron1 | 265 | PROCEDURE PushAll_1* (VAR R: REGS); |
7597 | akron1 | 266 | BEGIN |
7693 | akron1 | 267 | WHILE R.top >= 1 DO |
268 | push(R) |
||
269 | END |
||
270 | END PushAll_1; |
||
271 | |||
272 | |||
8859 | leency | 273 | PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET); |
7693 | akron1 | 274 | BEGIN |
7597 | akron1 | 275 | R.regs := regs; |
276 | R.pushed := 0; |
||
277 | R.top := -1; |
||
278 | |||
279 | R.push := push; |
||
280 | R.pop := pop; |
||
281 | R.mov := mov; |
||
282 | R.xch := xch; |
||
7693 | akron1 | 283 | END Init; |
7597 | akron1 | 284 | |
285 | |||
7983 | leency | 286 | END REG.>> |