Subversion Repositories Kolibri OS

Rev

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.