Rev 7983 | 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 | |||
8097 | maxcodehac | 4 | Copyright (c) 2018-2020, 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 |
8097 | maxcodehac | 159 | free: INTEGER; |
160 | res: BOOLEAN; |
||
7597 | akron1 | 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 |
||
8097 | maxcodehac | 181 | res := InStk(R, reg) # -1; |
182 | IF res THEN |
||
7597 | akron1 | 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 |
||
8097 | maxcodehac | 195 | END |
7597 | akron1 | 196 | END |
197 | END |
||
198 | |||
199 | RETURN res |
||
200 | END GetReg; |
||
201 | |||
202 | |||
7693 | akron1 | 203 | PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN; |
7597 | akron1 | 204 | VAR |
205 | n1, n2: INTEGER; |
||
206 | res: BOOLEAN; |
||
207 | |||
208 | BEGIN |
||
209 | res := FALSE; |
||
210 | |||
211 | IF reg1 # reg2 THEN |
||
212 | n1 := InStk(R, reg1); |
||
213 | n2 := InStk(R, reg2); |
||
214 | |||
215 | IF (n1 # -1) & (n2 # -1) THEN |
||
216 | R.stk[n1] := reg2; |
||
217 | R.stk[n2] := reg1; |
||
218 | R.xch(reg2, reg1); |
||
219 | res := TRUE |
||
220 | ELSIF (n1 # -1) & (reg2 IN R.regs) THEN |
||
221 | R.stk[n1] := reg2; |
||
222 | INCL(R.regs, reg1); |
||
223 | EXCL(R.regs, reg2); |
||
224 | R.mov(reg2, reg1); |
||
225 | res := TRUE |
||
226 | ELSIF (n2 # -1) & (reg1 IN R.regs) THEN |
||
227 | R.stk[n2] := reg1; |
||
228 | EXCL(R.regs, reg1); |
||
229 | INCL(R.regs, reg2); |
||
230 | R.mov(reg1, reg2); |
||
231 | res := TRUE |
||
232 | END |
||
233 | ELSE |
||
234 | res := TRUE |
||
235 | END |
||
236 | |||
237 | RETURN res |
||
238 | END Exchange; |
||
239 | |||
240 | |||
7693 | akron1 | 241 | PROCEDURE Drop* (VAR R: REGS); |
7597 | akron1 | 242 | BEGIN |
243 | INCL(R.regs, R.stk[R.top]); |
||
244 | DEC(R.top) |
||
245 | END Drop; |
||
246 | |||
247 | |||
7693 | akron1 | 248 | PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER); |
7597 | akron1 | 249 | BEGIN |
250 | IF R.top > 0 THEN |
||
251 | reg1 := R.stk[R.top - 1]; |
||
252 | reg2 := R.stk[R.top] |
||
253 | ELSIF R.top = 0 THEN |
||
254 | reg1 := PopAnyReg(R); |
||
255 | reg2 := R.stk[R.top] |
||
256 | ELSIF R.top < 0 THEN |
||
257 | reg2 := PopAnyReg(R); |
||
258 | reg1 := PopAnyReg(R) |
||
259 | END |
||
260 | END BinOp; |
||
261 | |||
262 | |||
7693 | akron1 | 263 | PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER); |
7597 | akron1 | 264 | BEGIN |
265 | IF R.top >= 0 THEN |
||
266 | reg := R.stk[R.top] |
||
267 | ELSE |
||
268 | reg := PopAnyReg(R) |
||
269 | END |
||
270 | END UnOp; |
||
271 | |||
272 | |||
7693 | akron1 | 273 | PROCEDURE PushAll* (VAR R: REGS); |
7597 | akron1 | 274 | BEGIN |
275 | WHILE R.top >= 0 DO |
||
276 | push(R) |
||
277 | END |
||
278 | END PushAll; |
||
279 | |||
280 | |||
7693 | akron1 | 281 | PROCEDURE PushAll_1* (VAR R: REGS); |
7597 | akron1 | 282 | BEGIN |
7693 | akron1 | 283 | WHILE R.top >= 1 DO |
284 | push(R) |
||
285 | END |
||
286 | END PushAll_1; |
||
287 | |||
288 | |||
289 | PROCEDURE Lock* (VAR R: REGS; reg, offs, size: INTEGER); |
||
290 | BEGIN |
||
7597 | akron1 | 291 | ASSERT(reg IN R.vregs); |
292 | ASSERT(offs # 0); |
||
7696 | akron1 | 293 | ASSERT(size IN {1, 2, 4, 8}); |
7597 | akron1 | 294 | R.offs[reg] := offs; |
295 | R.size[reg] := size |
||
296 | END Lock; |
||
297 | |||
298 | |||
7693 | akron1 | 299 | PROCEDURE Release* (VAR R: REGS; reg: INTEGER); |
7597 | akron1 | 300 | BEGIN |
301 | ASSERT(reg IN R.vregs); |
||
302 | R.offs[reg] := 0 |
||
303 | END Release; |
||
304 | |||
305 | |||
306 | PROCEDURE Load* (R: REGS; reg: INTEGER); |
||
307 | VAR |
||
308 | offs: INTEGER; |
||
309 | |||
310 | BEGIN |
||
311 | ASSERT(reg IN R.vregs); |
||
312 | offs := R.offs[reg]; |
||
313 | IF offs # 0 THEN |
||
314 | R.load(reg, offs, R.size[reg]) |
||
315 | END |
||
316 | END Load; |
||
317 | |||
318 | |||
319 | PROCEDURE Save* (R: REGS; reg: INTEGER); |
||
320 | VAR |
||
321 | offs: INTEGER; |
||
322 | |||
323 | BEGIN |
||
324 | ASSERT(reg IN R.vregs); |
||
325 | offs := R.offs[reg]; |
||
326 | IF offs # 0 THEN |
||
327 | R.save(reg, offs, R.size[reg]) |
||
328 | END |
||
329 | END Save; |
||
330 | |||
331 | |||
332 | PROCEDURE Store* (R: REGS); |
||
333 | VAR |
||
334 | i: INTEGER; |
||
335 | |||
336 | BEGIN |
||
337 | FOR i := 0 TO NVR - 1 DO |
||
338 | IF i IN R.vregs THEN |
||
339 | Save(R, i) |
||
340 | END |
||
341 | END |
||
342 | END Store; |
||
343 | |||
344 | |||
345 | PROCEDURE Restore* (R: REGS); |
||
346 | VAR |
||
347 | i: INTEGER; |
||
348 | |||
349 | BEGIN |
||
350 | FOR i := 0 TO NVR - 1 DO |
||
351 | IF i IN R.vregs THEN |
||
352 | Load(R, i) |
||
353 | END |
||
354 | END |
||
355 | END Restore; |
||
356 | |||
357 | |||
7693 | akron1 | 358 | PROCEDURE Reset* (VAR R: REGS); |
7597 | akron1 | 359 | VAR |
360 | i: INTEGER; |
||
361 | |||
362 | BEGIN |
||
363 | FOR i := 0 TO NVR - 1 DO |
||
364 | IF i IN R.vregs THEN |
||
365 | R.offs[i] := 0 |
||
366 | END |
||
367 | END |
||
368 | END Reset; |
||
369 | |||
370 | |||
371 | PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER; |
||
372 | VAR |
||
373 | i, res: INTEGER; |
||
374 | |||
375 | BEGIN |
||
376 | res := -1; |
||
377 | i := 0; |
||
378 | WHILE i < NVR DO |
||
379 | IF (i IN R.vregs) & (R.offs[i] = offs) THEN |
||
380 | res := i; |
||
381 | i := NVR |
||
382 | END; |
||
383 | INC(i) |
||
384 | END |
||
385 | |||
386 | RETURN res |
||
387 | END GetVarReg; |
||
388 | |||
389 | |||
390 | PROCEDURE GetAnyVarReg* (R: REGS): INTEGER; |
||
391 | VAR |
||
392 | i, res: INTEGER; |
||
393 | |||
394 | BEGIN |
||
395 | res := -1; |
||
396 | i := 0; |
||
397 | WHILE i < NVR DO |
||
398 | IF (i IN R.vregs) & (R.offs[i] = 0) THEN |
||
399 | res := i; |
||
400 | i := NVR |
||
401 | END; |
||
402 | INC(i) |
||
403 | END |
||
404 | |||
405 | RETURN res |
||
406 | END GetAnyVarReg; |
||
407 | |||
408 | |||
7693 | akron1 | 409 | PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET); |
7597 | akron1 | 410 | VAR |
411 | i: INTEGER; |
||
412 | |||
413 | BEGIN |
||
414 | R.regs := regs; |
||
415 | R.pushed := 0; |
||
416 | R.top := -1; |
||
417 | |||
418 | R.push := push; |
||
419 | R.pop := pop; |
||
420 | R.mov := mov; |
||
421 | R.xch := xch; |
||
422 | R.load := load; |
||
423 | R.save := save; |
||
424 | |||
425 | R.vregs := vregs; |
||
426 | |||
427 | FOR i := 0 TO NVR - 1 DO |
||
428 | R.offs[i] := 0; |
||
429 | R.size[i] := 0 |
||
430 | END |
||
431 | |||
7693 | akron1 | 432 | END Init; |
7597 | akron1 | 433 | |
434 | |||
7983 | leency | 435 | END REG.>>>>>=> |