Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7597 | akron1 | 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.>>>>>=> |