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