Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "gc.h"
2
 
3
void
4
swit1(C1 *q, int nc, long def, Node *n)
5
{
6
	Node tn;
7
 
8
	regalloc(&tn, &regnode, Z);
9
	swit2(q, nc, def, n, &tn);
10
	regfree(&tn);
11
}
12
 
13
void
14
swit2(C1 *q, int nc, long def, Node *n, Node *tn)
15
{
16
	C1 *r;
17
	int i;
18
	long v;
19
	Prog *sp;
20
 
21
	if(nc >= 3) {
22
		i = (q+nc-1)->val - (q+0)->val;
23
		if(i > 0 && i < nc*2)
24
			goto direct;
25
	}
26
	if(nc < 5) {
27
		for(i=0; i<nc; i++) {
28
			if(debug['K'])
29
				print("case = %.8llux\n", q->val);
30
			gopcode(OEQ, nodconst(q->val), n, Z);
31
			patch(p, q->label);
32
			q++;
33
		}
34
		gbranch(OGOTO);
35
		patch(p, def);
36
		return;
37
	}
38
 
39
	i = nc / 2;
40
	r = q+i;
41
	if(debug['K'])
42
		print("case > %.8llux\n", r->val);
43
	gopcode(OGT, nodconst(r->val), n, Z);
44
	sp = p;
45
	gopcode(OEQ, nodconst(r->val), n, Z);	/* just gen the B.EQ */
46
	patch(p, r->label);
47
	swit2(q, i, def, n, tn);
48
 
49
	if(debug['K'])
50
		print("case < %.8llux\n", r->val);
51
	patch(sp, pc);
52
	swit2(r+1, nc-i-1, def, n, tn);
53
	return;
54
 
55
direct:
56
	v = q->val;
57
	if(v != 0)
58
		gopcode(OSUB, nodconst(v), Z, n);
59
	gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
60
	patch(p, def);
61
	for(i=0; i<nc; i++) {
62
		if(debug['K'])
63
			print("case = %.8llux\n", q->val);
64
		while(q->val != v) {
65
			nextpc();
66
			p->as = ABCASE;
67
			patch(p, def);
68
			v++;
69
		}
70
		nextpc();
71
		p->as = ABCASE;
72
		patch(p, q->label);
73
		q++;
74
		v++;
75
	}
76
	gbranch(OGOTO);		/* so that regopt() won't be confused */
77
	patch(p, def);
78
}
79
 
80
void
81
bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
82
{
83
	int sh;
84
	long v;
85
	Node *l;
86
 
87
	/*
88
	 * n1 gets adjusted/masked value
89
	 * n2 gets address of cell
90
	 * n3 gets contents of cell
91
	 */
92
	l = b->left;
93
	if(n2 != Z) {
94
		regalloc(n1, l, nn);
95
		reglcgen(n2, l, Z);
96
		regalloc(n3, l, Z);
97
		gopcode(OAS, n2, Z, n3);
98
		gopcode(OAS, n3, Z, n1);
99
	} else {
100
		regalloc(n1, l, nn);
101
		cgen(l, n1);
102
	}
103
	if(b->type->shift == 0 && typeu[b->type->etype]) {
104
		v = ~0 + (1L << b->type->nbits);
105
		gopcode(OAND, nodconst(v), Z, n1);
106
	} else {
107
		sh = 32 - b->type->shift - b->type->nbits;
108
		if(sh > 0)
109
			gopcode(OASHL, nodconst(sh), Z, n1);
110
		sh += b->type->shift;
111
		if(sh > 0)
112
			if(typeu[b->type->etype])
113
				gopcode(OLSHR, nodconst(sh), Z, n1);
114
			else
115
				gopcode(OASHR, nodconst(sh), Z, n1);
116
	}
117
}
118
 
119
void
120
bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
121
{
122
	long v;
123
	Node nod, *l;
124
	int sh;
125
 
126
	/*
127
	 * n1 has adjusted/masked value
128
	 * n2 has address of cell
129
	 * n3 has contents of cell
130
	 */
131
	l = b->left;
132
	regalloc(&nod, l, Z);
133
	v = ~0 + (1L << b->type->nbits);
134
	gopcode(OAND, nodconst(v), Z, n1);
135
	gopcode(OAS, n1, Z, &nod);
136
	if(nn != Z)
137
		gopcode(OAS, n1, Z, nn);
138
	sh = b->type->shift;
139
	if(sh > 0)
140
		gopcode(OASHL, nodconst(sh), Z, &nod);
141
	v <<= sh;
142
	gopcode(OAND, nodconst(~v), Z, n3);
143
	gopcode(OOR, n3, Z, &nod);
144
	gopcode(OAS, &nod, Z, n2);
145
 
146
	regfree(&nod);
147
	regfree(n1);
148
	regfree(n2);
149
	regfree(n3);
150
}
151
 
152
long
153
outstring(char *s, long n)
154
{
155
	long r;
156
 
157
	if(suppress)
158
		return nstring;
159
	r = nstring;
160
	while(n) {
161
		string[mnstring] = *s++;
162
		mnstring++;
163
		nstring++;
164
		if(mnstring >= NSNAME) {
165
			gpseudo(ADATA, symstring, nodconst(0L));
166
			p->from.offset += nstring - NSNAME;
167
			p->reg = NSNAME;
168
			p->to.type = D_SCONST;
169
			memmove(p->to.sval, string, NSNAME);
170
			mnstring = 0;
171
		}
172
		n--;
173
	}
174
	return r;
175
}
176
 
177
int
178
mulcon(Node *n, Node *nn)
179
{
180
	Node *l, *r, nod1, nod2;
181
	Multab *m;
182
	long v, vs;
183
	int o;
184
	char code[sizeof(m->code)+2], *p;
185
 
186
	if(typefd[n->type->etype])
187
		return 0;
188
	l = n->left;
189
	r = n->right;
190
	if(l->op == OCONST) {
191
		l = r;
192
		r = n->left;
193
	}
194
	if(r->op != OCONST)
195
		return 0;
196
	v = convvtox(r->vconst, n->type->etype);
197
	if(v != r->vconst) {
198
		if(debug['M'])
199
			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
200
		return 0;
201
	}
202
	m = mulcon0(v);
203
	if(!m) {
204
		if(debug['M'])
205
			print("%L multiply table: %lld\n", n->lineno, r->vconst);
206
		return 0;
207
	}
208
	if(debug['M'] && debug['v'])
209
		print("%L multiply: %ld\n", n->lineno, v);
210
 
211
	memmove(code, m->code, sizeof(m->code));
212
	code[sizeof(m->code)] = 0;
213
 
214
	p = code;
215
	if(p[1] == 'i')
216
		p += 2;
217
	regalloc(&nod1, n, nn);
218
	cgen(l, &nod1);
219
	vs = v;
220
	regalloc(&nod2, n, Z);
221
 
222
loop:
223
	switch(*p) {
224
	case 0:
225
		regfree(&nod2);
226
		if(vs < 0) {
227
			gopcode(OAS, &nod1, Z, &nod1);
228
			gopcode(OSUB, &nod1, nodconst(0), nn);
229
		} else 
230
			gopcode(OAS, &nod1, Z, nn);
231
		regfree(&nod1);
232
		return 1;
233
	case '+':
234
		o = OADD;
235
		goto addsub;
236
	case '-':
237
		o = OSUB;
238
	addsub:	/* number is r,n,l */
239
		v = p[1] - '0';
240
		r = &nod1;
241
		if(v&4)
242
			r = &nod2;
243
		n = &nod1;
244
		if(v&2)
245
			n = &nod2;
246
		l = &nod1;
247
		if(v&1)
248
			l = &nod2;
249
		gopcode(o, l, n, r);
250
		break;
251
	default: /* op is shiftcount, number is r,l */
252
		v = p[1] - '0';
253
		r = &nod1;
254
		if(v&2)
255
			r = &nod2;
256
		l = &nod1;
257
		if(v&1)
258
			l = &nod2;
259
		v = *p - 'a';
260
		if(v < 0 || v >= 32) {
261
			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
262
			break;
263
		}
264
		gopcode(OASHL, nodconst(v), l, r);
265
		break;
266
	}
267
	p += 2;
268
	goto loop;
269
}
270
 
271
void
272
gextern(Sym *s, Node *a, long o, long w)
273
{
274
 
275
	if(a->op == OCONST && typev[a->type->etype]) {
276
		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
277
			gpseudo(ADATA, s, nod32const(a->vconst>>32));
278
		else
279
			gpseudo(ADATA, s, nod32const(a->vconst));
280
		p->from.offset += o;
281
		p->reg = 4;
282
		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
283
			gpseudo(ADATA, s, nod32const(a->vconst));
284
		else
285
			gpseudo(ADATA, s, nod32const(a->vconst>>32));
286
		p->from.offset += o + 4;
287
		p->reg = 4;
288
		return;
289
	}
290
	gpseudo(ADATA, s, a);
291
	p->from.offset += o;
292
	p->reg = w;
293
	if(p->to.type == D_OREG)
294
		p->to.type = D_CONST;
295
}
296
 
297
void	zname(Biobuf*, Sym*, int);
298
char*	zaddr(char*, Adr*, int);
299
void	zwrite(Biobuf*, Prog*, int, int);
300
void	outhist(Biobuf*);
301
 
302
void
303
zwrite(Biobuf *b, Prog *p, int sf, int st)
304
{
305
	char bf[100], *bp;
306
 
307
	bf[0] = p->as;
308
	bf[1] = p->scond;
309
	bf[2] = p->reg;
310
	bf[3] = p->lineno;
311
	bf[4] = p->lineno>>8;
312
	bf[5] = p->lineno>>16;
313
	bf[6] = p->lineno>>24;
314
	bp = zaddr(bf+7, &p->from, sf);
315
	bp = zaddr(bp, &p->to, st);
316
	Bwrite(b, bf, bp-bf);
317
}
318
 
319
void
320
outcode(void)
321
{
322
	struct { Sym *sym; short type; } h[NSYM];
323
	Prog *p;
324
	Sym *s;
325
	int sf, st, t, sym;
326
 
327
	if(debug['S']) {
328
		for(p = firstp; p != P; p = p->link)
329
			if(p->as != ADATA && p->as != AGLOBL)
330
				pc--;
331
		for(p = firstp; p != P; p = p->link) {
332
			print("%P\n", p);
333
			if(p->as != ADATA && p->as != AGLOBL)
334
				pc++;
335
		}
336
	}
337
	outhist(&outbuf);
338
	for(sym=0; sym<NSYM; sym++) {
339
		h[sym].sym = S;
340
		h[sym].type = 0;
341
	}
342
	sym = 1;
343
	for(p = firstp; p != P; p = p->link) {
344
	jackpot:
345
		sf = 0;
346
		s = p->from.sym;
347
		while(s != S) {
348
			sf = s->sym;
349
			if(sf < 0 || sf >= NSYM)
350
				sf = 0;
351
			t = p->from.name;
352
			if(h[sf].type == t)
353
			if(h[sf].sym == s)
354
				break;
355
			s->sym = sym;
356
			zname(&outbuf, s, t);
357
			h[sym].sym = s;
358
			h[sym].type = t;
359
			sf = sym;
360
			sym++;
361
			if(sym >= NSYM)
362
				sym = 1;
363
			break;
364
		}
365
		st = 0;
366
		s = p->to.sym;
367
		while(s != S) {
368
			st = s->sym;
369
			if(st < 0 || st >= NSYM)
370
				st = 0;
371
			t = p->to.name;
372
			if(h[st].type == t)
373
			if(h[st].sym == s)
374
				break;
375
			s->sym = sym;
376
			zname(&outbuf, s, t);
377
			h[sym].sym = s;
378
			h[sym].type = t;
379
			st = sym;
380
			sym++;
381
			if(sym >= NSYM)
382
				sym = 1;
383
			if(st == sf)
384
				goto jackpot;
385
			break;
386
		}
387
		zwrite(&outbuf, p, sf, st);
388
	}
389
	firstp = P;
390
	lastp = P;
391
}
392
 
393
void
394
outhist(Biobuf *b)
395
{
396
	Hist *h;
397
	char *p, *q, *op, c;
398
	Prog pg;
399
	int n;
400
 
401
	pg = zprog;
402
	pg.as = AHISTORY;
403
	c = pathchar();
404
	for(h = hist; h != H; h = h->link) {
405
		p = h->name;
406
		op = 0;
407
		/* on windows skip drive specifier in pathname */
408
		if(systemtype(Windows) && p && p[1] == ':'){
409
			p += 2;
410
			c = *p;
411
		}
412
		if(p && p[0] != c && h->offset == 0 && pathname){
413
			/* on windows skip drive specifier in pathname */
414
			if(systemtype(Windows) && pathname[1] == ':') {
415
				op = p;
416
				p = pathname+2;
417
				c = *p;
418
			} else if(pathname[0] == c){
419
				op = p;
420
				p = pathname;
421
			}
422
		}
423
		while(p) {
424
			q = utfrune(p, c);
425
			if(q) {
426
				n = q-p;
427
				if(n == 0){
428
					n = 1;	/* leading "/" */
429
					*p = '/';	/* don't emit "\" on windows */
430
				}
431
				q++;
432
			} else {
433
				n = strlen(p);
434
				q = 0;
435
			}
436
			if(n) {
437
				Bputc(b, ANAME);
438
				Bputc(b, D_FILE);
439
				Bputc(b, 1);
440
				Bputc(b, '<');
441
				Bwrite(b, p, n);
442
				Bputc(b, 0);
443
			}
444
			p = q;
445
			if(p == 0 && op) {
446
				p = op;
447
				op = 0;
448
			}
449
		}
450
		pg.lineno = h->line;
451
		pg.to.type = zprog.to.type;
452
		pg.to.offset = h->offset;
453
		if(h->offset)
454
			pg.to.type = D_CONST;
455
 
456
		zwrite(b, &pg, 0, 0);
457
	}
458
}
459
 
460
void
461
zname(Biobuf *b, Sym *s, int t)
462
{
463
	char *n, bf[7];
464
	ulong sig;
465
 
466
	n = s->name;
467
	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
468
		sig = sign(s);
469
		bf[0] = ASIGNAME;
470
		bf[1] = sig;
471
		bf[2] = sig>>8;
472
		bf[3] = sig>>16;
473
		bf[4] = sig>>24;
474
		bf[5] = t;
475
		bf[6] = s->sym;
476
		Bwrite(b, bf, 7);
477
		s->sig = SIGDONE;
478
	}
479
	else{
480
		bf[0] = ANAME;
481
		bf[1] = t;	/* type */
482
		bf[2] = s->sym;	/* sym */
483
		Bwrite(b, bf, 3);
484
	}
485
	Bwrite(b, n, strlen(n)+1);
486
}
487
 
488
char*
489
zaddr(char *bp, Adr *a, int s)
490
{
491
	long l;
492
	Ieee e;
493
 
494
	bp[0] = a->type;
495
	bp[1] = a->reg;
496
	bp[2] = s;
497
	bp[3] = a->name;
498
	bp += 4;
499
	switch(a->type) {
500
	default:
501
		diag(Z, "unknown type %d in zaddr", a->type);
502
 
503
	case D_NONE:
504
	case D_REG:
505
	case D_FREG:
506
	case D_PSR:
507
		break;
508
 
509
	case D_OREG:
510
	case D_CONST:
511
	case D_BRANCH:
512
	case D_SHIFT:
513
		l = a->offset;
514
		bp[0] = l;
515
		bp[1] = l>>8;
516
		bp[2] = l>>16;
517
		bp[3] = l>>24;
518
		bp += 4;
519
		break;
520
 
521
	case D_SCONST:
522
		memmove(bp, a->sval, NSNAME);
523
		bp += NSNAME;
524
		break;
525
 
526
	case D_FCONST:
527
		ieeedtod(&e, a->dval);
528
		l = e.l;
529
		bp[0] = l;
530
		bp[1] = l>>8;
531
		bp[2] = l>>16;
532
		bp[3] = l>>24;
533
		bp += 4;
534
		l = e.h;
535
		bp[0] = l;
536
		bp[1] = l>>8;
537
		bp[2] = l>>16;
538
		bp[3] = l>>24;
539
		bp += 4;
540
		break;
541
	}
542
	return bp;
543
}
544
 
545
long
546
align(long i, Type *t, int op)
547
{
548
	long o;
549
	Type *v;
550
	int w;
551
 
552
	o = i;
553
	w = 1;
554
	switch(op) {
555
	default:
556
		diag(Z, "unknown align opcode %d", op);
557
		break;
558
 
559
	case Asu2:	/* padding at end of a struct */
560
		w = SZ_LONG;
561
		if(packflg)
562
			w = packflg;
563
		break;
564
 
565
	case Ael1:	/* initial align of struct element */
566
		for(v=t; v->etype==TARRAY; v=v->link)
567
			;
568
		w = ewidth[v->etype];
569
		if(w <= 0 || w >= SZ_LONG)
570
			w = SZ_LONG;
571
		if(packflg)
572
			w = packflg;
573
		break;
574
 
575
	case Ael2:	/* width of a struct element */
576
		o += t->width;
577
		break;
578
 
579
	case Aarg0:	/* initial passbyptr argument in arg list */
580
		if(typesuv[t->etype]) {
581
			o = align(o, types[TIND], Aarg1);
582
			o = align(o, types[TIND], Aarg2);
583
		}
584
		break;
585
 
586
	case Aarg1:	/* initial align of parameter */
587
		w = ewidth[t->etype];
588
		if(w <= 0 || w >= SZ_LONG) {
589
			w = SZ_LONG;
590
			break;
591
		}
592
		w = 1;		/* little endian no adjustment */
593
		break;
594
 
595
	case Aarg2:	/* width of a parameter */
596
		o += t->width;
597
		w = SZ_LONG;
598
		break;
599
 
600
	case Aaut3:	/* total align of automatic */
601
		o = align(o, t, Ael2);
602
		o = align(o, t, Ael1);
603
		w = SZ_LONG;	/* because of a pun in cc/dcl.c:contig() */
604
		break;
605
	}
606
	o = round(o, w);
607
	if(debug['A'])
608
		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
609
	return o;
610
}
611
 
612
long
613
maxround(long max, long v)
614
{
615
	v = round(v, SZ_LONG);
616
	if(v > max)
617
		return v;
618
	return max;
619
}