Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / util.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5
6 /* M I S C E L L A N E O U S   U T I L I T I E S */
7
8 /* $Id: util.c,v 1.7 1994/06/27 08:03:14 ceriel Exp $ */
9
10 /*      Code for the allocation and de-allocation of temporary variables,
11         allowing re-use.
12 */
13
14 #include        "lint.h"
15 #ifndef LINT
16 #include        <em.h>
17 #else
18 #include        "l_em.h"
19 #endif  /* LINT */
20 #include        <em_arith.h>
21 #include        <em_reg.h>
22 #include        <alloc.h>
23 #include        <em_mes.h>
24
25 #include        "debug.h"
26 #include        "util.h"
27 #include        "use_tmp.h"
28 #include        "regcount.h"
29 #include        "sizes.h"
30 #include        "align.h"
31 #include        "stack.h"
32 #include        "Lpars.h"
33 #include        "def.h"
34
35 static struct localvar  *FreeTmps;
36 #ifdef USE_TMP
37 static int      loc_id;
38 #endif /* USE_TMP */
39
40 #ifdef PEEPHOLE
41 #undef REGCOUNT
42 #define REGCOUNT 1
43 #endif
44
45 extern char options[];
46
47 LocalInit()
48 {
49 #ifdef USE_TMP
50         C_insertpart(loc_id = C_getid());
51 #endif /* USE_TMP */
52 }
53
54 arith
55 LocalSpace(sz, al)
56         arith sz;
57 {
58         register struct stack_level *stl = local_level;
59
60         stl->sl_max_block = - align(sz - stl->sl_max_block, al);
61         return stl->sl_max_block;
62 }
63
64 #define TABSIZ 32
65 static struct localvar *regs[TABSIZ];
66
67 arith
68 NewLocal(sz, al, regtype, sc)
69         arith sz;
70 {
71         register struct localvar *tmp = FreeTmps;
72         struct localvar *prev = 0;
73         int index;
74
75         while (tmp) {
76                 if (tmp->t_align >= al &&
77                     tmp->t_size >= sz &&
78                     tmp->t_sc == sc &&
79                     tmp->t_regtype == regtype) {
80                         if (prev) {
81                                 prev->next = tmp->next;
82                         }
83                         else    FreeTmps = tmp->next;
84                         break;
85                 }
86                 prev = tmp;
87                 tmp = tmp->next;
88         }
89         if (! tmp) {
90                 tmp = new_localvar();
91                 tmp->t_offset = LocalSpace(sz, al);
92                 tmp->t_align = al;
93                 tmp->t_size = sz;
94                 tmp->t_sc = sc;
95                 tmp->t_regtype = regtype;
96                 tmp->t_count = REG_DEFAULT;
97         }
98         index = (int) (tmp->t_offset >> 2) & (TABSIZ - 1);
99         tmp->next = regs[index];
100         regs[index] = tmp;
101         return tmp->t_offset;
102 }
103
104 FreeLocal(off)
105         arith off;
106 {
107         int index = (int) (off >> 2) & (TABSIZ - 1);
108         register struct localvar *tmp = regs[index];
109         struct localvar *prev = 0;
110
111         while (tmp && tmp->t_offset != off) {
112                 prev = tmp;
113                 tmp = tmp->next;
114         }
115         if (tmp) {
116                 if (prev)       prev->next = tmp->next;
117                 else            regs[index] = tmp->next;
118                 tmp->next = FreeTmps;
119                 FreeTmps = tmp;
120         }
121 }
122
123 LocalFinish()
124 {
125         register struct localvar *tmp, *tmp1;
126         register int i;
127
128 #ifdef USE_TMP
129         C_beginpart(loc_id);
130 #endif
131         tmp = FreeTmps;
132         while (tmp) {
133                 tmp1 = tmp;
134                 if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
135                 if (! options['n'] && tmp->t_regtype >= 0) {
136                         C_ms_reg(tmp->t_offset, tmp->t_size, tmp->t_regtype, tmp->t_count);
137                 }
138                 tmp = tmp->next;
139                 free_localvar(tmp1);
140         }
141         FreeTmps = 0;
142         for (i = 0; i < TABSIZ; i++) {
143                 tmp = regs[i];
144                 while (tmp) {
145                         if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
146                         tmp1 = tmp;
147                         if (! options['n'] && tmp->t_regtype >= 0) {
148                                 C_ms_reg(tmp->t_offset,
149                                          tmp->t_size,
150                                          tmp->t_regtype,
151                                          tmp->t_count);
152                         }
153                         tmp = tmp->next;
154                         free_localvar(tmp1);
155                 }
156                 regs[i] = 0;
157         }
158 #ifdef PEEPHOLE
159         if (! options['n']) {
160                 C_mes_begin(ms_reg);
161                 C_mes_end();
162         }
163 #endif
164 #ifdef USE_TMP
165         C_endpart(loc_id);
166 #endif
167 }
168
169 RegisterAccount(offset, size, regtype, sc)
170         arith offset, size;
171 {
172         register struct localvar *p;
173         int index;
174
175         if (regtype < 0) return;
176
177         p = new_localvar();
178         index = (int) (offset >> 2) & (TABSIZ - 1);
179         p->t_offset = offset;
180         p->t_regtype = regtype;
181         p->t_count = REG_DEFAULT;
182         p->t_sc = sc;
183         p->t_size = size;
184         p->next = regs[index];
185         regs[index] = p;
186 }
187
188 static struct localvar *
189 find_reg(off)
190         arith off;
191 {
192         register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)];
193
194         while (p && p->t_offset != off) p = p->next;
195         return p;
196 }
197
198 LoadLocal(off, sz)
199         arith off, sz;
200 {
201         register struct localvar *p = find_reg(off);
202
203 #ifdef USE_TMP
204 #ifdef REGCOUNT
205         if (p) p->t_count++;
206 #endif
207 #endif
208         if (p && p->t_size != sz) p->t_regtype = -1;
209         if (sz == word_size) C_lol(off);
210         else if (sz == dword_size) C_ldl(off);
211         else {
212                 if (p) p->t_regtype = -1;
213                 C_lal(off);
214                 C_loi(sz);
215         }
216 }
217
218 StoreLocal(off, sz)
219         arith off, sz;
220 {
221         register struct localvar *p = find_reg(off);
222
223 #ifdef USE_TMP
224 #ifdef REGCOUNT
225         if (p) p->t_count++;
226 #endif
227 #endif
228         if (p && p->t_size != sz) p->t_regtype = -1;
229         if (sz == word_size) C_stl(off);
230         else if (sz == dword_size) C_sdl(off);
231         else {
232                 if (p) p->t_regtype = -1;
233                 C_lal(off);
234                 C_sti(sz);
235         }
236 }
237
238 #ifndef LINT
239 AddrLocal(off)
240         arith off;
241 {
242         register struct localvar *p = find_reg(off);
243
244         if (p) p->t_regtype = -1;
245         C_lal(off);
246 }
247 #endif  /* LINT */