Subversion Repositories Kolibri OS

Rev

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.