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