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