blob: fceb332b25e12f8505b48d7495fb3706406fb938 [file] [log] [blame]
Colin Cross7bb052a2015-02-03 12:59:37 -08001// Inferno utils/6c/sgen.c
2// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
3//
4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6// Portions Copyright © 1997-1999 Vita Nuova Limited
7// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8// Portions Copyright © 2004,2006 Bruce Ellis
9// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11// Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
31#include "gc.h"
32#include "../../runtime/funcdata.h"
33
34Prog*
35gtext(Sym *s, int32 stkoff)
36{
37 vlong v;
38
39 v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
40 if((textflag & NOSPLIT) && stkoff >= 128)
41 yyerror("stack frame too large for NOSPLIT function");
42
43 gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
44 return p;
45}
46
47void
48noretval(int n)
49{
50
51 if(n & 1) {
52 gins(ANOP, Z, Z);
53 p->to.type = REGRET;
54 }
55 if(n & 2) {
56 gins(ANOP, Z, Z);
57 p->to.type = FREGRET;
58 }
59}
60
61/* welcome to commute */
62static void
63commute(Node *n)
64{
65 Node *l, *r;
66
67 l = n->left;
68 r = n->right;
69 if(r->complex > l->complex) {
70 n->left = r;
71 n->right = l;
72 }
73}
74
75void
76indexshift(Node *n)
77{
78 int g;
79
80 if(!typechlpv[n->type->etype])
81 return;
82 simplifyshift(n);
83 if(n->op == OASHL && n->right->op == OCONST){
84 g = vconst(n->right);
85 if(g >= 0 && g <= 3)
86 n->addable = 7;
87 }
88}
89
90/*
91 * calculate addressability as follows
92 * NAME ==> 10/11 name+value(SB/SP)
93 * REGISTER ==> 12 register
94 * CONST ==> 20 $value
95 * *(20) ==> 21 value
96 * &(10) ==> 13 $name+value(SB)
97 * &(11) ==> 1 $name+value(SP)
98 * (13) + (20) ==> 13 fold constants
99 * (1) + (20) ==> 1 fold constants
100 * *(13) ==> 10 back to name
101 * *(1) ==> 11 back to name
102 *
103 * (20) * (X) ==> 7 multiplier in indexing
104 * (X,7) + (13,1) ==> 8 adder in indexing (addresses)
105 * (8) ==> &9(OINDEX) index, almost addressable
106 *
107 * calculate complexity (number of registers)
108 */
109void
110xcom(Node *n)
111{
112 Node *l, *r;
113 int g;
114
115 if(n == Z)
116 return;
117 l = n->left;
118 r = n->right;
119 n->complex = 0;
120 n->addable = 0;
121 switch(n->op) {
122 case OCONST:
123 n->addable = 20;
124 break;
125
126 case ONAME:
127 n->addable = 9;
128 if(n->class == CPARAM || n->class == CAUTO)
129 n->addable = 11;
130 break;
131
132 case OEXREG:
133 n->addable = 0;
134 break;
135
136 case OREGISTER:
137 n->addable = 12;
138 break;
139
140 case OINDREG:
141 n->addable = 12;
142 break;
143
144 case OADDR:
145 xcom(l);
146 if(l->addable == 10)
147 n->addable = 13;
148 else
149 if(l->addable == 11)
150 n->addable = 1;
151 break;
152
153 case OADD:
154 xcom(l);
155 xcom(r);
156 if(n->type->etype != TIND)
157 break;
158
159 switch(r->addable) {
160 case 20:
161 switch(l->addable) {
162 case 1:
163 case 13:
164 commadd:
165 l->type = n->type;
166 *n = *l;
167 l = new(0, Z, Z);
168 *l = *(n->left);
169 l->xoffset += r->vconst;
170 n->left = l;
171 r = n->right;
172 goto brk;
173 }
174 break;
175
176 case 1:
177 case 13:
178 case 10:
179 case 11:
180 /* l is the base, r is the index */
181 if(l->addable != 20)
182 n->addable = 8;
183 break;
184 }
185 switch(l->addable) {
186 case 20:
187 switch(r->addable) {
188 case 13:
189 case 1:
190 r = n->left;
191 l = n->right;
192 n->left = l;
193 n->right = r;
194 goto commadd;
195 }
196 break;
197
198 case 13:
199 case 1:
200 case 10:
201 case 11:
202 /* r is the base, l is the index */
203 if(r->addable != 20)
204 n->addable = 8;
205 break;
206 }
207 if(n->addable == 8 && !side(n) && !nacl) {
208 indx(n);
209 l = new1(OINDEX, idx.basetree, idx.regtree);
210 l->scale = idx.scale;
211 l->addable = 9;
212 l->complex = l->right->complex;
213 l->type = l->left->type;
214 n->op = OADDR;
215 n->left = l;
216 n->right = Z;
217 n->addable = 8;
218 break;
219 }
220 break;
221
222 case OINDEX:
223 xcom(l);
224 xcom(r);
225 n->addable = 9;
226 break;
227
228 case OIND:
229 xcom(l);
230 if(l->op == OADDR) {
231 l = l->left;
232 l->type = n->type;
233 *n = *l;
234 return;
235 }
236 switch(l->addable) {
237 case 20:
238 n->addable = 21;
239 break;
240 case 1:
241 n->addable = 11;
242 break;
243 case 13:
244 n->addable = 10;
245 break;
246 }
247 break;
248
249 case OASHL:
250 xcom(l);
251 xcom(r);
252 indexshift(n);
253 break;
254
255 case OMUL:
256 case OLMUL:
257 xcom(l);
258 xcom(r);
259 g = vlog(l);
260 if(g >= 0) {
261 n->left = r;
262 n->right = l;
263 l = r;
264 r = n->right;
265 }
266 g = vlog(r);
267 if(g >= 0) {
268 n->op = OASHL;
269 r->vconst = g;
270 r->type = types[TINT];
271 indexshift(n);
272 break;
273 }
274 commute(n);
275 break;
276
277 case OASLDIV:
278 xcom(l);
279 xcom(r);
280 g = vlog(r);
281 if(g >= 0) {
282 n->op = OASLSHR;
283 r->vconst = g;
284 r->type = types[TINT];
285 }
286 break;
287
288 case OLDIV:
289 xcom(l);
290 xcom(r);
291 g = vlog(r);
292 if(g >= 0) {
293 n->op = OLSHR;
294 r->vconst = g;
295 r->type = types[TINT];
296 indexshift(n);
297 break;
298 }
299 break;
300
301 case OASLMOD:
302 xcom(l);
303 xcom(r);
304 g = vlog(r);
305 if(g >= 0) {
306 n->op = OASAND;
307 r->vconst--;
308 }
309 break;
310
311 case OLMOD:
312 xcom(l);
313 xcom(r);
314 g = vlog(r);
315 if(g >= 0) {
316 n->op = OAND;
317 r->vconst--;
318 }
319 break;
320
321 case OASMUL:
322 case OASLMUL:
323 xcom(l);
324 xcom(r);
325 g = vlog(r);
326 if(g >= 0) {
327 n->op = OASASHL;
328 r->vconst = g;
329 }
330 break;
331
332 case OLSHR:
333 case OASHR:
334 xcom(l);
335 xcom(r);
336 indexshift(n);
337 break;
338
339 default:
340 if(l != Z)
341 xcom(l);
342 if(r != Z)
343 xcom(r);
344 break;
345 }
346brk:
347 if(n->addable >= 10)
348 return;
349 if(l != Z)
350 n->complex = l->complex;
351 if(r != Z) {
352 if(r->complex == n->complex)
353 n->complex = r->complex+1;
354 else
355 if(r->complex > n->complex)
356 n->complex = r->complex;
357 }
358 if(n->complex == 0)
359 n->complex++;
360
361 switch(n->op) {
362
363 case OFUNC:
364 n->complex = FNX;
365 break;
366
367 case OCAST:
368 if(l->type->etype == TUVLONG && typefd[n->type->etype])
369 n->complex += 2;
370 break;
371
372 case OLMOD:
373 case OMOD:
374 case OLMUL:
375 case OLDIV:
376 case OMUL:
377 case ODIV:
378 case OASLMUL:
379 case OASLDIV:
380 case OASLMOD:
381 case OASMUL:
382 case OASDIV:
383 case OASMOD:
384 if(r->complex >= l->complex) {
385 n->complex = l->complex + 3;
386 if(r->complex > n->complex)
387 n->complex = r->complex;
388 } else {
389 n->complex = r->complex + 3;
390 if(l->complex > n->complex)
391 n->complex = l->complex;
392 }
393 break;
394
395 case OLSHR:
396 case OASHL:
397 case OASHR:
398 case OASLSHR:
399 case OASASHL:
400 case OASASHR:
401 if(r->complex >= l->complex) {
402 n->complex = l->complex + 2;
403 if(r->complex > n->complex)
404 n->complex = r->complex;
405 } else {
406 n->complex = r->complex + 2;
407 if(l->complex > n->complex)
408 n->complex = l->complex;
409 }
410 break;
411
412 case OADD:
413 case OXOR:
414 case OAND:
415 case OOR:
416 /*
417 * immediate operators, make const on right
418 */
419 if(l->op == OCONST) {
420 n->left = r;
421 n->right = l;
422 }
423 break;
424
425 case OEQ:
426 case ONE:
427 case OLE:
428 case OLT:
429 case OGE:
430 case OGT:
431 case OHI:
432 case OHS:
433 case OLO:
434 case OLS:
435 /*
436 * compare operators, make const on left
437 */
438 if(r->op == OCONST) {
439 n->left = r;
440 n->right = l;
441 n->op = invrel[relindex(n->op)];
442 }
443 break;
444 }
445}
446
447void
448indx(Node *n)
449{
450 Node *l, *r;
451
452 if(debug['x'])
453 prtree(n, "indx");
454
455 l = n->left;
456 r = n->right;
457 if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
458 n->right = l;
459 n->left = r;
460 l = r;
461 r = n->right;
462 }
463 if(l->addable != 7) {
464 idx.regtree = l;
465 idx.scale = 1;
466 } else
467 if(l->right->addable == 20) {
468 idx.regtree = l->left;
469 idx.scale = 1 << l->right->vconst;
470 } else
471 if(l->left->addable == 20) {
472 idx.regtree = l->right;
473 idx.scale = 1 << l->left->vconst;
474 } else
475 diag(n, "bad index");
476
477 idx.basetree = r;
478 if(debug['x']) {
479 print("scale = %d\n", idx.scale);
480 prtree(idx.regtree, "index");
481 prtree(idx.basetree, "base");
482 }
483}