]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/8c/sgen.c
6fc0ffba71b7a944d6045d4e7a5d5938086e5ef9
[plan9front.git] / sys / src / cmd / 8c / sgen.c
1 #include "gc.h"
2
3 void
4 noretval(int n)
5 {
6
7         if(n & 1) {
8                 gins(ANOP, Z, Z);
9                 p->to.type = REGRET;
10         }
11         if(n & 2) {
12                 gins(ANOP, Z, Z);
13                 p->to.type = FREGRET;
14         }
15         if((n&3) == 3)
16         if(thisfn && thisfn->link && typefd[thisfn->link->etype])
17                 gins(AFLDZ, Z, Z);
18 }
19
20 /* welcome to commute */
21 static void
22 commute(Node *n)
23 {
24         Node *l, *r;
25
26         l = n->left;
27         r = n->right;
28         if(r->complex > l->complex) {
29                 n->left = r;
30                 n->right = l;
31         }
32 }
33
34 void
35 indexshift(Node *n)
36 {
37         int g;
38
39         if(!typechlp[n->type->etype])
40                 return;
41         simplifyshift(n);
42         if(n->op == OASHL && n->right->op == OCONST){
43                 g = vconst(n->right);
44                 if(g >= 0 && g < 4)
45                         n->addable = 7;
46         }
47 }
48
49 /*
50  *      calculate addressability as follows
51  *              NAME ==> 10/11          name+value(SB/SP)
52  *              REGISTER ==> 12         register
53  *              CONST ==> 20            $value
54  *              *(20) ==> 21            value
55  *              &(10) ==> 13            $name+value(SB)
56  *              &(11) ==> 1             $name+value(SP)
57  *              (13) + (20) ==> 13      fold constants
58  *              (1) + (20) ==> 1        fold constants
59  *              *(13) ==> 10            back to name
60  *              *(1) ==> 11             back to name
61  *
62  *              (20) * (X) ==> 7        multiplier in indexing
63  *              (X,7) + (13,1) ==> 8    adder in indexing (addresses)
64  *              (8) ==> &9(OINDEX)      index, almost addressable
65  *
66  *      calculate complexity (number of registers)
67  */
68 void
69 xcom(Node *n)
70 {
71         Node *l, *r;
72         int g;
73
74         if(n == Z)
75                 return;
76         l = n->left;
77         r = n->right;
78         n->complex = 0;
79         n->addable = 0;
80         switch(n->op) {
81         case OCONST:
82                 n->addable = 20;
83                 break;
84
85         case ONAME:
86                 n->addable = 10;
87                 if(n->class == CPARAM || n->class == CAUTO)
88                         n->addable = 11;
89                 break;
90
91         case OEXREG:
92                 n->addable = 12;
93                 break;
94
95         case OREGISTER:
96                 n->addable = 12;
97                 break;
98
99         case OINDREG:
100                 n->addable = 12;
101                 break;
102
103         case OADDR:
104                 xcom(l);
105                 if(l->addable == 10)
106                         n->addable = 13;
107                 else
108                 if(l->addable == 11)
109                         n->addable = 1;
110                 break;
111
112         case OADD:
113                 xcom(l);
114                 xcom(r);
115                 if(n->type->etype != TIND)
116                         break;
117
118                 switch(r->addable) {
119                 case 20:
120                         switch(l->addable) {
121                         case 1:
122                         case 13:
123                         commadd:
124                                 l->type = n->type;
125                                 *n = *l;
126                                 l = new(0, Z, Z);
127                                 *l = *(n->left);
128                                 l->xoffset += r->vconst;
129                                 n->left = l;
130                                 goto brk;
131                         }
132                         break;
133
134                 case 1:
135                 case 13:
136                 case 10:
137                 case 11:
138                         /* l is the base, r is the index */
139                         if(l->addable != 20)
140                                 n->addable = 8;
141                         break;
142                 }
143                 switch(l->addable) {
144                 case 20:
145                         switch(r->addable) {
146                         case 13:
147                         case 1:
148                                 r = n->left;
149                                 l = n->right;
150                                 n->left = l;
151                                 n->right = r;
152                                 goto commadd;
153                         }
154                         break;
155
156                 case 13:
157                 case 1:
158                 case 10:
159                 case 11:
160                         /* r is the base, l is the index */
161                         if(r->addable != 20)
162                                 n->addable = 8;
163                         break;
164                 }
165                 if(n->addable == 8 && !side(n)) {
166                         indx(n);
167                         l = new1(OINDEX, idx.basetree, idx.regtree);
168                         l->scale = idx.scale;
169                         l->addable = 9;
170                         l->complex = l->right->complex;
171                         l->type = l->left->type;
172                         n->op = OADDR;
173                         n->left = l;
174                         n->right = Z;
175                         n->addable = 8;
176                         break;
177                 }
178                 break;
179
180         case OINDEX:
181                 xcom(l);
182                 xcom(r);
183                 n->addable = 9;
184                 break;
185
186         case OIND:
187                 xcom(l);
188                 if(l->op == OADDR) {
189                         l = l->left;
190                         l->type = n->type;
191                         *n = *l;
192                         return;
193                 }
194                 switch(l->addable) {
195                 case 20:
196                         n->addable = 21;
197                         break;
198                 case 1:
199                         n->addable = 11;
200                         break;
201                 case 13:
202                         n->addable = 10;
203                         break;
204                 }
205                 break;
206
207         case OASHL:
208                 xcom(l);
209                 xcom(r);
210                 indexshift(n);
211                 break;
212
213         case OMUL:
214         case OLMUL:
215                 xcom(l);
216                 xcom(r);
217                 g = vlog(l);
218                 if(g >= 0) {
219                         n->left = r;
220                         n->right = l;
221                         r = n->right;
222                 }
223                 g = vlog(r);
224                 if(g >= 0) {
225                         n->op = OASHL;
226                         r->vconst = g;
227                         r->type = types[TINT];
228                         indexshift(n);
229                         break;
230                 }
231                 commute(n);
232                 break;
233
234         case OASLDIV:
235                 xcom(l);
236                 xcom(r);
237                 g = vlog(r);
238                 if(g >= 0) {
239                         n->op = OASLSHR;
240                         r->vconst = g;
241                         r->type = types[TINT];
242                 }
243                 break;
244
245         case OLDIV:
246                 xcom(l);
247                 xcom(r);
248                 g = vlog(r);
249                 if(g >= 0) {
250                         n->op = OLSHR;
251                         r->vconst = g;
252                         r->type = types[TINT];
253                         indexshift(n);
254                         break;
255                 }
256                 break;
257
258         case OASLMOD:
259                 xcom(l);
260                 xcom(r);
261                 g = vlog(r);
262                 if(g >= 0) {
263                         n->op = OASAND;
264                         r->vconst--;
265                 }
266                 break;
267
268         case OLMOD:
269                 xcom(l);
270                 xcom(r);
271                 g = vlog(r);
272                 if(g >= 0) {
273                         n->op = OAND;
274                         r->vconst--;
275                 }
276                 break;
277
278         case OASMUL:
279         case OASLMUL:
280                 xcom(l);
281                 xcom(r);
282                 g = vlog(r);
283                 if(g >= 0) {
284                         n->op = OASASHL;
285                         r->vconst = g;
286                 }
287                 break;
288
289         case OLSHR:
290         case OASHR:
291                 xcom(l);
292                 xcom(r);
293                 indexshift(n);
294                 break;
295
296         case OOR:
297                 xcom(l);
298                 xcom(r);
299                 if(typechl[n->type->etype])
300                         rolor(n);
301                 break;
302
303         default:
304                 if(l != Z)
305                         xcom(l);
306                 if(r != Z)
307                         xcom(r);
308                 break;
309         }
310 brk:
311         if(n->addable >= 10)
312                 return;
313         l = n->left;
314         r = n->right;
315         if(l != Z)
316                 n->complex = l->complex;
317         if(r != Z) {
318                 if(r->complex == n->complex)
319                         n->complex = r->complex+1;
320                 else
321                 if(r->complex > n->complex)
322                         n->complex = r->complex;
323         }
324         if(n->complex == 0)
325                 n->complex++;
326
327         if(com64(n))
328                 return;
329
330         switch(n->op) {
331
332         case OFUNC:
333                 n->complex = FNX;
334                 break;
335
336         case OLMOD:
337         case OMOD:
338         case OLMUL:
339         case OLDIV:
340         case OMUL:
341         case ODIV:
342         case OASLMUL:
343         case OASLDIV:
344         case OASLMOD:
345         case OASMUL:
346         case OASDIV:
347         case OASMOD:
348                 if(r->complex >= l->complex) {
349                         n->complex = l->complex + 3;
350                         if(r->complex > n->complex)
351                                 n->complex = r->complex;
352                 } else {
353                         n->complex = r->complex + 3;
354                         if(l->complex > n->complex)
355                                 n->complex = l->complex;
356                 }
357                 break;
358
359         case OROL:
360         case OLSHR:
361         case OASHL:
362         case OASHR:
363         case OASLSHR:
364         case OASASHL:
365         case OASASHR:
366                 if(r->complex >= l->complex) {
367                         n->complex = l->complex + 2;
368                         if(r->complex > n->complex)
369                                 n->complex = r->complex;
370                 } else {
371                         n->complex = r->complex + 2;
372                         if(l->complex > n->complex)
373                                 n->complex = l->complex;
374                 }
375                 break;
376
377         case OADD:
378         case OXOR:
379         case OAND:
380         case OOR:
381                 /*
382                  * immediate operators, make const on right
383                  */
384                 if(l->op == OCONST) {
385                         n->left = r;
386                         n->right = l;
387                 }
388                 break;
389
390         case OEQ:
391         case ONE:
392         case OLE:
393         case OLT:
394         case OGE:
395         case OGT:
396         case OHI:
397         case OHS:
398         case OLO:
399         case OLS:
400                 /*
401                  * compare operators, make const on left
402                  */
403                 if(r->op == OCONST) {
404                         n->left = r;
405                         n->right = l;
406                         n->op = invrel[relindex(n->op)];
407                 }
408                 break;
409         }
410 }
411
412 void
413 indx(Node *n)
414 {
415         Node *l, *r;
416
417         if(debug['x'])
418                 prtree(n, "indx");
419
420         l = n->left;
421         r = n->right;
422         if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
423                 n->right = l;
424                 n->left = r;
425                 l = r;
426                 r = n->right;
427         }
428         if(l->addable != 7) {
429                 idx.regtree = l;
430                 idx.scale = 1;
431         } else
432         if(l->right->addable == 20) {
433                 idx.regtree = l->left;
434                 idx.scale = 1 << l->right->vconst;
435         } else
436         if(l->left->addable == 20) {
437                 idx.regtree = l->right;
438                 idx.scale = 1 << l->left->vconst;
439         } else
440                 diag(n, "bad index");
441
442         idx.basetree = r;
443         if(debug['x']) {
444                 print("scale = %d\n", idx.scale);
445                 prtree(idx.regtree, "index");
446                 prtree(idx.basetree, "base");
447         }
448 }