xref: /plan9/sys/src/cmd/qc/swt.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
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 	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
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
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
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
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
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
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
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
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->reg;
369 	l = p->lineno;
370 	bf[2] = l;
371 	bf[3] = l>>8;
372 	bf[4] = l>>16;
373 	bf[5] = l>>24;
374 	bp = zaddr(bf+6, &p->from, sf);
375 	bp = zaddr(bp, &p->to, st);
376 	Bwrite(b, bf, bp-bf);
377 }
378 
379 void
380 outhist(Biobuf *b)
381 {
382 	Hist *h;
383 	char *p, *q, *op, c;
384 	Prog pg;
385 	int n;
386 
387 	pg = zprog;
388 	pg.as = AHISTORY;
389 	c = pathchar();
390 	for(h = hist; h != H; h = h->link) {
391 		p = h->name;
392 		op = 0;
393 		/* on windows skip drive specifier in pathname */
394 		if(systemtype(Windows) && p && p[1] == ':'){
395 			p += 2;
396 			c = *p;
397 		}
398 		if(p && p[0] != c && h->offset == 0 && pathname){
399 			/* on windows skip drive specifier in pathname */
400 			if(systemtype(Windows) && pathname[1] == ':') {
401 				op = p;
402 				p = pathname+2;
403 				c = *p;
404 			} else if(pathname[0] == c){
405 				op = p;
406 				p = pathname;
407 			}
408 		}
409 		while(p) {
410 			q = utfrune(p, c);
411 			if(q) {
412 				n = q-p;
413 				if(n == 0){
414 					n = 1;	/* leading "/" */
415 					*p = '/';	/* don't emit "\" on windows */
416 				}
417 				q++;
418 			} else {
419 				n = strlen(p);
420 				q = 0;
421 			}
422 			if(n) {
423 				Bputc(b, ANAME);
424 				Bputc(b, D_FILE);
425 				Bputc(b, 1);
426 				Bputc(b, '<');
427 				Bwrite(b, p, n);
428 				Bputc(b, 0);
429 			}
430 			p = q;
431 			if(p == 0 && op) {
432 				p = op;
433 				op = 0;
434 			}
435 		}
436 		pg.lineno = h->line;
437 		pg.to.type = zprog.to.type;
438 		pg.to.offset = h->offset;
439 		if(h->offset)
440 			pg.to.type = D_CONST;
441 
442 		zwrite(b, &pg, 0, 0);
443 	}
444 }
445 
446 void
447 zname(Biobuf *b, Sym *s, int t)
448 {
449 	char *n, bf[7];
450 	ulong sig;
451 
452 	n = s->name;
453 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
454 		sig = sign(s);
455 		bf[0] = ASIGNAME;
456 		bf[1] = sig;
457 		bf[2] = sig>>8;
458 		bf[3] = sig>>16;
459 		bf[4] = sig>>24;
460 		bf[5] = t;
461 		bf[6] = s->sym;
462 		Bwrite(b, bf, 7);
463 		s->sig = SIGDONE;
464 	}
465 	else{
466 		bf[0] = ANAME;
467 		bf[1] = t;	/* type */
468 		bf[2] = s->sym;	/* sym */
469 		Bwrite(b, bf, 3);
470 	}
471 	Bwrite(b, n, strlen(n)+1);
472 }
473 
474 char*
475 zaddr(char *bp, Adr *a, int s)
476 {
477 	long l;
478 	Ieee e;
479 
480 	bp[0] = a->type;
481 	bp[1] = a->reg;
482 	bp[2] = s;
483 	bp[3] = a->name;
484 	bp += 4;
485 	switch(a->type) {
486 	default:
487 		diag(Z, "unknown type %d in zaddr", a->type);
488 
489 	case D_NONE:
490 	case D_REG:
491 	case D_FREG:
492 	case D_CREG:
493 		break;
494 
495 	case D_OREG:
496 	case D_CONST:
497 	case D_BRANCH:
498 		l = a->offset;
499 		bp[0] = l;
500 		bp[1] = l>>8;
501 		bp[2] = l>>16;
502 		bp[3] = l>>24;
503 		bp += 4;
504 		break;
505 
506 	case D_SCONST:
507 		memmove(bp, a->sval, NSNAME);
508 		bp += NSNAME;
509 		break;
510 
511 	case D_FCONST:
512 		ieeedtod(&e, a->dval);
513 		l = e.l;
514 		bp[0] = l;
515 		bp[1] = l>>8;
516 		bp[2] = l>>16;
517 		bp[3] = l>>24;
518 		bp += 4;
519 		l = e.h;
520 		bp[0] = l;
521 		bp[1] = l>>8;
522 		bp[2] = l>>16;
523 		bp[3] = l>>24;
524 		bp += 4;
525 		break;
526 	}
527 	return bp;
528 }
529 
530 long
531 align(long i, Type *t, int op)
532 {
533 	long o;
534 	Type *v;
535 	int w;
536 
537 	o = i;
538 	w = 1;
539 	switch(op) {
540 	default:
541 		diag(Z, "unknown align opcode %d", op);
542 		break;
543 
544 	case Asu2:	/* padding at end of a struct */
545 		w = SZ_LONG;
546 		if(packflg)
547 			w = packflg;
548 		break;
549 
550 	case Ael1:	/* initial allign of struct element */
551 		for(v=t; v->etype==TARRAY; v=v->link)
552 			;
553 		w = ewidth[v->etype];
554 		if(w <= 0 || w >= SZ_LONG)
555 			w = SZ_LONG;
556 		if(packflg)
557 			w = packflg;
558 		break;
559 
560 	case Ael2:	/* width of a struct element */
561 		o += t->width;
562 		break;
563 
564 	case Aarg0:	/* initial passbyptr argument in arg list */
565 		if(typesuv[t->etype]) {
566 			o = align(o, types[TIND], Aarg1);
567 			o = align(o, types[TIND], Aarg2);
568 		}
569 		break;
570 
571 	case Aarg1:	/* initial allign of parameter */
572 		w = ewidth[t->etype];
573 		if(w <= 0 || w >= SZ_LONG) {
574 			w = SZ_LONG;
575 			break;
576 		}
577 		o += SZ_LONG - w;	/* big endian adjustment */
578 		w = 1;
579 		break;
580 
581 	case Aarg2:	/* width of a parameter */
582 		o += t->width;
583 		w = SZ_LONG;
584 		break;
585 
586 	case Aaut3:	/* total allign of automatic */
587 		o = align(o, t, Ael1);
588 		o = align(o, t, Ael2);
589 		break;
590 	}
591 	o = round(o, w);
592 	if(debug['A'])
593 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
594 	return o;
595 }
596 
597 long
598 maxround(long max, long v)
599 {
600 	v += SZ_LONG-1;
601 	if(v > max)
602 		max = round(v, SZ_LONG);
603 	return max;
604 }
605