Subversion Repositories Kolibri OS

Rev

Rev 8097 | 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
 
8859 leency 4
    Copyright (c) 2018-2021, 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
 
21
TYPE
22
 
23
    OP1 = PROCEDURE (arg: INTEGER);
24
    OP2 = PROCEDURE (arg1, arg2: INTEGER);
25
 
7693 akron1 26
    REGS* = RECORD
7597 akron1 27
 
28
        regs*:   SET;
29
        stk*:    ARRAY N OF INTEGER;
30
        top*:    INTEGER;
31
        pushed*: INTEGER;
32
 
33
        push, pop:  OP1;
8859 leency 34
        mov,  xch:  OP2
7597 akron1 35
 
36
    END;
37
 
38
 
7693 akron1 39
PROCEDURE push (VAR R: REGS);
7597 akron1 40
VAR
41
    i, reg: INTEGER;
42
 
43
BEGIN
44
    reg := R.stk[0];
45
    INCL(R.regs, reg);
46
    R.push(reg);
47
    FOR i := 0 TO R.top - 1 DO
48
        R.stk[i] := R.stk[i + 1]
49
    END;
50
    DEC(R.top);
51
    INC(R.pushed)
52
END push;
53
 
54
 
7693 akron1 55
PROCEDURE pop (VAR R: REGS; reg: INTEGER);
7597 akron1 56
VAR
57
    i: INTEGER;
58
 
59
BEGIN
60
    FOR i := R.top + 1 TO 1 BY -1 DO
61
        R.stk[i] := R.stk[i - 1]
62
    END;
63
    R.stk[0] := reg;
64
    EXCL(R.regs, reg);
65
    R.pop(reg);
66
    INC(R.top);
67
    DEC(R.pushed)
68
END pop;
69
 
70
 
71
PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER;
72
VAR
8859 leency 73
    i: INTEGER;
7597 akron1 74
 
75
BEGIN
8859 leency 76
    i := R.top;
77
    WHILE (i >= 0) & (R.stk[i] # reg) DO
78
        DEC(i)
7597 akron1 79
    END
80
 
81
    RETURN i
82
END InStk;
83
 
84
 
85
PROCEDURE GetFreeReg (R: REGS): INTEGER;
86
VAR
87
    i: INTEGER;
88
 
89
BEGIN
90
    i := 0;
91
    WHILE (i < N) & ~(i IN R.regs) DO
92
        INC(i)
93
    END;
94
 
95
    IF i = N THEN
96
        i := -1
97
    END
98
 
99
    RETURN i
100
END GetFreeReg;
101
 
102
 
7693 akron1 103
PROCEDURE Put (VAR R: REGS; reg: INTEGER);
7597 akron1 104
BEGIN
105
    EXCL(R.regs, reg);
106
    INC(R.top);
107
    R.stk[R.top] := reg
108
END Put;
109
 
110
 
7693 akron1 111
PROCEDURE PopAnyReg (VAR R: REGS): INTEGER;
7597 akron1 112
VAR
113
    reg: INTEGER;
114
 
115
BEGIN
116
    reg := GetFreeReg(R);
117
    ASSERT(reg # -1);
118
    ASSERT(R.top < LEN(R.stk) - 1);
119
    ASSERT(R.pushed > 0);
120
    pop(R, reg)
121
 
122
    RETURN reg
123
END PopAnyReg;
124
 
125
 
7693 akron1 126
PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER;
7597 akron1 127
VAR
128
    reg: INTEGER;
129
 
130
BEGIN
131
    reg := GetFreeReg(R);
132
    IF reg = -1 THEN
133
        ASSERT(R.top >= 0);
134
        reg := R.stk[0];
135
        push(R)
136
    END;
137
 
138
    Put(R, reg)
139
 
140
    RETURN reg
141
END GetAnyReg;
142
 
143
 
7693 akron1 144
PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN;
7597 akron1 145
VAR
8097 maxcodehac 146
    free: INTEGER;
147
    res:  BOOLEAN;
7597 akron1 148
 
149
 
7693 akron1 150
    PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER);
7597 akron1 151
    VAR
152
        n1, n2: INTEGER;
153
 
154
    BEGIN
155
        n1 := InStk(R, reg1);
156
        n2 := InStk(R, reg2);
157
        R.stk[n1] := reg2;
158
        R.stk[n2] := reg1;
159
        R.xch(reg1, reg2)
160
    END exch;
161
 
162
 
163
BEGIN
164
    IF reg IN R.regs THEN
165
        Put(R, reg);
166
        res := TRUE
167
    ELSE
8097 maxcodehac 168
        res := InStk(R, reg) # -1;
169
        IF res THEN
7597 akron1 170
            free := GetFreeReg(R);
171
            IF free # -1 THEN
172
                Put(R, free);
173
                exch(R, reg, free)
174
            ELSE
175
                push(R);
176
                free := GetFreeReg(R);
177
                ASSERT(free # -1);
178
                Put(R, free);
179
                IF free # reg THEN
180
                    exch(R, reg, free)
181
                END
8097 maxcodehac 182
            END
7597 akron1 183
        END
184
    END
185
 
186
    RETURN res
187
END GetReg;
188
 
189
 
7693 akron1 190
PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
7597 akron1 191
VAR
192
    n1, n2: INTEGER;
193
    res: BOOLEAN;
194
 
195
BEGIN
8859 leency 196
    res := TRUE;
7597 akron1 197
 
198
    IF reg1 # reg2 THEN
199
        n1 := InStk(R, reg1);
200
        n2 := InStk(R, reg2);
201
 
202
        IF (n1 # -1) & (n2 # -1) THEN
203
            R.stk[n1] := reg2;
204
            R.stk[n2] := reg1;
8859 leency 205
            R.xch(reg2, reg1)
7597 akron1 206
        ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
207
            R.stk[n1] := reg2;
208
            INCL(R.regs, reg1);
209
            EXCL(R.regs, reg2);
8859 leency 210
            R.mov(reg2, reg1)
7597 akron1 211
        ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
212
            R.stk[n2] := reg1;
213
            EXCL(R.regs, reg1);
214
            INCL(R.regs, reg2);
8859 leency 215
            R.mov(reg1, reg2)
216
        ELSE
217
            res := FALSE
7597 akron1 218
        END
219
    END
220
 
221
    RETURN res
222
END Exchange;
223
 
224
 
7693 akron1 225
PROCEDURE Drop* (VAR R: REGS);
7597 akron1 226
BEGIN
227
    INCL(R.regs, R.stk[R.top]);
228
    DEC(R.top)
229
END Drop;
230
 
231
 
7693 akron1 232
PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
7597 akron1 233
BEGIN
234
    IF R.top > 0 THEN
235
        reg1 := R.stk[R.top - 1];
236
        reg2 := R.stk[R.top]
237
    ELSIF R.top = 0 THEN
238
        reg1 := PopAnyReg(R);
8859 leency 239
        reg2 := R.stk[1]
240
    ELSE (* R.top = -1 *)
7597 akron1 241
        reg2 := PopAnyReg(R);
242
        reg1 := PopAnyReg(R)
243
    END
244
END BinOp;
245
 
246
 
7693 akron1 247
PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
7597 akron1 248
BEGIN
249
    IF R.top >= 0 THEN
250
        reg := R.stk[R.top]
251
    ELSE
252
        reg := PopAnyReg(R)
253
    END
254
END UnOp;
255
 
256
 
7693 akron1 257
PROCEDURE PushAll* (VAR R: REGS);
7597 akron1 258
BEGIN
259
    WHILE R.top >= 0 DO
260
        push(R)
261
    END
262
END PushAll;
263
 
264
 
7693 akron1 265
PROCEDURE PushAll_1* (VAR R: REGS);
7597 akron1 266
BEGIN
7693 akron1 267
    WHILE R.top >= 1 DO
268
        push(R)
269
    END
270
END PushAll_1;
271
 
272
 
8859 leency 273
PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET);
7693 akron1 274
BEGIN
7597 akron1 275
    R.regs := regs;
276
    R.pushed := 0;
277
    R.top := -1;
278
 
279
    R.push := push;
280
    R.pop  := pop;
281
    R.mov  := mov;
282
    R.xch  := xch;
7693 akron1 283
END Init;
7597 akron1 284
 
285
 
7983 leency 286
END REG.