Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
				r = n->right;
131
				goto brk;
132
			}
133
			break;
134
 
135
		case 1:
136
		case 13:
137
		case 10:
138
		case 11:
139
			/* l is the base, r is the index */
140
			if(l->addable != 20)
141
				n->addable = 8;
142
			break;
143
		}
144
		switch(l->addable) {
145
		case 20:
146
			switch(r->addable) {
147
			case 13:
148
			case 1:
149
				r = n->left;
150
				l = n->right;
151
				n->left = l;
152
				n->right = r;
153
				goto commadd;
154
			}
155
			break;
156
 
157
		case 13:
158
		case 1:
159
		case 10:
160
		case 11:
161
			/* r is the base, l is the index */
162
			if(r->addable != 20)
163
				n->addable = 8;
164
			break;
165
		}
166
		if(n->addable == 8 && !side(n)) {
167
			indx(n);
168
			l = new1(OINDEX, idx.basetree, idx.regtree);
169
			l->scale = idx.scale;
170
			l->addable = 9;
171
			l->complex = l->right->complex;
172
			l->type = l->left->type;
173
			n->op = OADDR;
174
			n->left = l;
175
			n->right = Z;
176
			n->addable = 8;
177
			break;
178
		}
179
		break;
180
 
181
	case OINDEX:
182
		xcom(l);
183
		xcom(r);
184
		n->addable = 9;
185
		break;
186
 
187
	case OIND:
188
		xcom(l);
189
		if(l->op == OADDR) {
190
			l = l->left;
191
			l->type = n->type;
192
			*n = *l;
193
			return;
194
		}
195
		switch(l->addable) {
196
		case 20:
197
			n->addable = 21;
198
			break;
199
		case 1:
200
			n->addable = 11;
201
			break;
202
		case 13:
203
			n->addable = 10;
204
			break;
205
		}
206
		break;
207
 
208
	case OASHL:
209
		xcom(l);
210
		xcom(r);
211
		indexshift(n);
212
		break;
213
 
214
	case OMUL:
215
	case OLMUL:
216
		xcom(l);
217
		xcom(r);
218
		g = vlog(l);
219
		if(g >= 0) {
220
			n->left = r;
221
			n->right = l;
222
			l = r;
223
			r = n->right;
224
		}
225
		g = vlog(r);
226
		if(g >= 0) {
227
			n->op = OASHL;
228
			r->vconst = g;
229
			r->type = types[TINT];
230
			indexshift(n);
231
			break;
232
		}
233
commute(n);
234
		break;
235
 
236
	case OASLDIV:
237
		xcom(l);
238
		xcom(r);
239
		g = vlog(r);
240
		if(g >= 0) {
241
			n->op = OASLSHR;
242
			r->vconst = g;
243
			r->type = types[TINT];
244
		}
245
		break;
246
 
247
	case OLDIV:
248
		xcom(l);
249
		xcom(r);
250
		g = vlog(r);
251
		if(g >= 0) {
252
			n->op = OLSHR;
253
			r->vconst = g;
254
			r->type = types[TINT];
255
			indexshift(n);
256
			break;
257
		}
258
		break;
259
 
260
	case OASLMOD:
261
		xcom(l);
262
		xcom(r);
263
		g = vlog(r);
264
		if(g >= 0) {
265
			n->op = OASAND;
266
			r->vconst--;
267
		}
268
		break;
269
 
270
	case OLMOD:
271
		xcom(l);
272
		xcom(r);
273
		g = vlog(r);
274
		if(g >= 0) {
275
			n->op = OAND;
276
			r->vconst--;
277
		}
278
		break;
279
 
280
	case OASMUL:
281
	case OASLMUL:
282
		xcom(l);
283
		xcom(r);
284
		g = vlog(r);
285
		if(g >= 0) {
286
			n->op = OASASHL;
287
			r->vconst = g;
288
		}
289
		break;
290
 
291
	case OLSHR:
292
	case OASHR:
293
		xcom(l);
294
		xcom(r);
295
		indexshift(n);
296
		break;
297
 
298
	default:
299
		if(l != Z)
300
			xcom(l);
301
		if(r != Z)
302
			xcom(r);
303
		break;
304
	}
305
brk:
306
	if(n->addable >= 10)
307
		return;
308
	if(l != Z)
309
		n->complex = l->complex;
310
	if(r != Z) {
311
		if(r->complex == n->complex)
312
			n->complex = r->complex+1;
313
		else
314
		if(r->complex > n->complex)
315
			n->complex = r->complex;
316
	}
317
	if(n->complex == 0)
318
		n->complex++;
319
 
320
	if(com64(n))
321
		return;
322
 
323
	switch(n->op) {
324
 
325
	case OFUNC:
326
		n->complex = FNX;
327
		break;
328
 
329
	case OLMOD:
330
	case OMOD:
331
	case OLMUL:
332
	case OLDIV:
333
	case OMUL:
334
	case ODIV:
335
	case OASLMUL:
336
	case OASLDIV:
337
	case OASLMOD:
338
	case OASMUL:
339
	case OASDIV:
340
	case OASMOD:
341
		if(r->complex >= l->complex) {
342
			n->complex = l->complex + 3;
343
			if(r->complex > n->complex)
344
				n->complex = r->complex;
345
		} else {
346
			n->complex = r->complex + 3;
347
			if(l->complex > n->complex)
348
				n->complex = l->complex;
349
		}
350
		break;
351
 
352
	case OLSHR:
353
	case OASHL:
354
	case OASHR:
355
	case OASLSHR:
356
	case OASASHL:
357
	case OASASHR:
358
		if(r->complex >= l->complex) {
359
			n->complex = l->complex + 2;
360
			if(r->complex > n->complex)
361
				n->complex = r->complex;
362
		} else {
363
			n->complex = r->complex + 2;
364
			if(l->complex > n->complex)
365
				n->complex = l->complex;
366
		}
367
		break;
368
 
369
	case OADD:
370
	case OXOR:
371
	case OAND:
372
	case OOR:
373
		/*
374
		 * immediate operators, make const on right
375
		 */
376
		if(l->op == OCONST) {
377
			n->left = r;
378
			n->right = l;
379
		}
380
		break;
381
 
382
	case OEQ:
383
	case ONE:
384
	case OLE:
385
	case OLT:
386
	case OGE:
387
	case OGT:
388
	case OHI:
389
	case OHS:
390
	case OLO:
391
	case OLS:
392
		/*
393
		 * compare operators, make const on left
394
		 */
395
		if(r->op == OCONST) {
396
			n->left = r;
397
			n->right = l;
398
			n->op = invrel[relindex(n->op)];
399
		}
400
		break;
401
	}
402
}
403
 
404
void
405
indx(Node *n)
406
{
407
	Node *l, *r;
408
 
409
	if(debug['x'])
410
		prtree(n, "indx");
411
 
412
	l = n->left;
413
	r = n->right;
414
	if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
415
		n->right = l;
416
		n->left = r;
417
		l = r;
418
		r = n->right;
419
	}
420
	if(l->addable != 7) {
421
		idx.regtree = l;
422
		idx.scale = 1;
423
	} else
424
	if(l->right->addable == 20) {
425
		idx.regtree = l->left;
426
		idx.scale = 1 << l->right->vconst;
427
	} else
428
	if(l->left->addable == 20) {
429
		idx.regtree = l->right;
430
		idx.scale = 1 << l->left->vconst;
431
	} else
432
		diag(n, "bad index");
433
 
434
	idx.basetree = r;
435
	if(debug['x']) {
436
		print("scale = %d\n", idx.scale);
437
		prtree(idx.regtree, "index");
438
		prtree(idx.basetree, "base");
439
	}
440
}