Subversion Repositories Kolibri OS

Rev

Rev 7597 | Go to most recent revision | Details | Compare with Previous | 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
 
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);
296
    R.offs[reg] := offs;
297
    IF size = 0 THEN
298
        size := 8
299
    END;
300
    R.size[reg] := size
301
END Lock;
302
 
303
 
7693 akron1 304
PROCEDURE Release* (VAR R: REGS; reg: INTEGER);
7597 akron1 305
BEGIN
306
    ASSERT(reg IN R.vregs);
307
    R.offs[reg] := 0
308
END Release;
309
 
310
 
311
PROCEDURE Load* (R: REGS; reg: INTEGER);
312
VAR
313
    offs: INTEGER;
314
 
315
BEGIN
316
    ASSERT(reg IN R.vregs);
317
    offs := R.offs[reg];
318
    IF offs # 0 THEN
319
        R.load(reg, offs, R.size[reg])
320
    END
321
END Load;
322
 
323
 
324
PROCEDURE Save* (R: REGS; reg: INTEGER);
325
VAR
326
    offs: INTEGER;
327
 
328
BEGIN
329
    ASSERT(reg IN R.vregs);
330
    offs := R.offs[reg];
331
    IF offs # 0 THEN
332
        R.save(reg, offs, R.size[reg])
333
    END
334
END Save;
335
 
336
 
337
PROCEDURE Store* (R: REGS);
338
VAR
339
    i: INTEGER;
340
 
341
BEGIN
342
    FOR i := 0 TO NVR - 1 DO
343
        IF i IN R.vregs THEN
344
            Save(R, i)
345
        END
346
    END
347
END Store;
348
 
349
 
350
PROCEDURE Restore* (R: REGS);
351
VAR
352
    i: INTEGER;
353
 
354
BEGIN
355
    FOR i := 0 TO NVR - 1 DO
356
        IF i IN R.vregs THEN
357
            Load(R, i)
358
        END
359
    END
360
END Restore;
361
 
362
 
7693 akron1 363
PROCEDURE Reset* (VAR R: REGS);
7597 akron1 364
VAR
365
    i: INTEGER;
366
 
367
BEGIN
368
    FOR i := 0 TO NVR - 1 DO
369
        IF i IN R.vregs THEN
370
            R.offs[i] := 0
371
        END
372
    END
373
END Reset;
374
 
375
 
376
PROCEDURE GetVarReg* (R: REGS; offs: INTEGER): INTEGER;
377
VAR
378
    i, res: INTEGER;
379
 
380
BEGIN
381
    res := -1;
382
    i := 0;
383
    WHILE i < NVR DO
384
        IF (i IN R.vregs) & (R.offs[i] = offs) THEN
385
            res := i;
386
            i := NVR
387
        END;
388
        INC(i)
389
    END
390
 
391
    RETURN res
392
END GetVarReg;
393
 
394
 
395
PROCEDURE GetAnyVarReg* (R: REGS): INTEGER;
396
VAR
397
    i, res: INTEGER;
398
 
399
BEGIN
400
    res := -1;
401
    i := 0;
402
    WHILE i < NVR DO
403
        IF (i IN R.vregs) & (R.offs[i] = 0) THEN
404
            res := i;
405
            i := NVR
406
        END;
407
        INC(i)
408
    END
409
 
410
    RETURN res
411
END GetAnyVarReg;
412
 
413
 
7693 akron1 414
PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; load, save: OP3; regs, vregs: SET);
7597 akron1 415
VAR
416
    i: INTEGER;
417
 
418
BEGIN
419
    R.regs := regs;
420
    R.pushed := 0;
421
    R.top := -1;
422
 
423
    R.push := push;
424
    R.pop  := pop;
425
    R.mov  := mov;
426
    R.xch  := xch;
427
    R.load := load;
428
    R.save := save;
429
 
430
    R.vregs := vregs;
431
 
432
    FOR i := 0 TO NVR - 1 DO
433
        R.offs[i] := 0;
434
        R.size[i] := 0
435
    END
436
 
7693 akron1 437
END Init;
7597 akron1 438
 
439
 
440
END REG.