xref: /plan9/sys/src/cmd/kc/swt.c (revision 178702b161d3fe3e021aa6cb2f305be898e56ca0)
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 = ABE;
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 	r = nstring;
132 	while(n) {
133 		string[mnstring] = *s++;
134 		mnstring++;
135 		nstring++;
136 		if(mnstring >= NSNAME) {
137 			gpseudo(ADATA, symstring, nodconst(0L));
138 			p->from.offset += nstring - NSNAME;
139 			p->reg = NSNAME;
140 			p->to.type = D_SCONST;
141 			memmove(p->to.sval, string, NSNAME);
142 			mnstring = 0;
143 		}
144 		n--;
145 	}
146 	return r;
147 }
148 
149 int
mulcon(Node * n,Node * nn)150 mulcon(Node *n, Node *nn)
151 {
152 	Node *l, *r, nod1, nod2;
153 	Multab *m;
154 	long v;
155 	int o;
156 	char code[sizeof(m->code)+2], *p;
157 
158 	if(typefd[n->type->etype])
159 		return 0;
160 	l = n->left;
161 	r = n->right;
162 	if(l->op == OCONST) {
163 		l = r;
164 		r = n->left;
165 	}
166 	if(r->op != OCONST)
167 		return 0;
168 	v = convvtox(r->vconst, n->type->etype);
169 	if(v != r->vconst) {
170 		if(debug['M'])
171 			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
172 		return 0;
173 	}
174 	m = mulcon0(n, v);
175 	if(!m) {
176 		if(debug['M'])
177 			print("%L multiply table: %lld\n", n->lineno, r->vconst);
178 		return 0;
179 	}
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 	if(a->op == OCONST && typev[a->type->etype]) {
242 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
243 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
244 		else
245 			gpseudo(ADATA, s, nod32const(a->vconst));
246 		p->from.offset += o;
247 		p->reg = 4;
248 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
249 			gpseudo(ADATA, s, nod32const(a->vconst));
250 		else
251 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
252 		p->from.offset += o + 4;
253 		p->reg = 4;
254 		return;
255 	}
256 	gpseudo(ADATA, s, a);
257 	p->from.offset += o;
258 	p->reg = w;
259 	if(p->to.type == D_OREG)
260 		p->to.type = D_CONST;
261 }
262 
263 void	zname(Biobuf*, Sym*, int);
264 void	zaddr(Biobuf*, Adr*, int);
265 void	zwrite(Biobuf*, Prog*, int, int);
266 void	outhist(Biobuf*);
267 
268 void
outcode(void)269 outcode(void)
270 {
271 	struct { Sym *sym; short type; } h[NSYM];
272 	Prog *p;
273 	Sym *s;
274 	int sf, st, t, sym;
275 
276 	if(debug['S']) {
277 		for(p = firstp; p != P; p = p->link)
278 			if(p->as != ADATA && p->as != AGLOBL)
279 				pc--;
280 		for(p = firstp; p != P; p = p->link) {
281 			print("%P\n", p);
282 			if(p->as != ADATA && p->as != AGLOBL)
283 				pc++;
284 		}
285 	}
286 	outhist(&outbuf);
287 	for(sym=0; sym<NSYM; sym++) {
288 		h[sym].sym = S;
289 		h[sym].type = 0;
290 	}
291 	sym = 1;
292 	for(p = firstp; p != P; p = p->link) {
293 	jackpot:
294 		sf = 0;
295 		s = p->from.sym;
296 		while(s != S) {
297 			sf = s->sym;
298 			if(sf < 0 || sf >= NSYM)
299 				sf = 0;
300 			t = p->from.name;
301 			if(h[sf].type == t)
302 			if(h[sf].sym == s)
303 				break;
304 			s->sym = sym;
305 			zname(&outbuf, s, t);
306 			h[sym].sym = s;
307 			h[sym].type = t;
308 			sf = sym;
309 			sym++;
310 			if(sym >= NSYM)
311 				sym = 1;
312 			break;
313 		}
314 		st = 0;
315 		s = p->to.sym;
316 		while(s != S) {
317 			st = s->sym;
318 			if(st < 0 || st >= NSYM)
319 				st = 0;
320 			t = p->to.name;
321 			if(h[st].type == t)
322 			if(h[st].sym == s)
323 				break;
324 			s->sym = sym;
325 			zname(&outbuf, s, t);
326 			h[sym].sym = s;
327 			h[sym].type = t;
328 			st = sym;
329 			sym++;
330 			if(sym >= NSYM)
331 				sym = 1;
332 			if(st == sf)
333 				goto jackpot;
334 			break;
335 		}
336 		zwrite(&outbuf, p, sf, st);
337 	}
338 	firstp = P;
339 	lastp = P;
340 }
341 
342 void
zwrite(Biobuf * b,Prog * p,int sf,int st)343 zwrite(Biobuf *b, Prog *p, int sf, int st)
344 {
345 	long l;
346 
347 	Bputc(b, p->as);
348 	Bputc(b, p->reg);
349 	l = p->lineno;
350 	Bputc(b, l);
351 	Bputc(b, l>>8);
352 	Bputc(b, l>>16);
353 	Bputc(b, l>>24);
354 	zaddr(b, &p->from, sf);
355 	zaddr(b, &p->to, st);
356 }
357 
358 void
outhist(Biobuf * b)359 outhist(Biobuf *b)
360 {
361 	Hist *h;
362 	char *p, *q, *op, c;
363 	Prog pg;
364 	int n;
365 
366 	pg = zprog;
367 	pg.as = AHISTORY;
368 	c = pathchar();
369 	for(h = hist; h != H; h = h->link) {
370 		p = h->name;
371 		op = 0;
372 		/* on windows skip drive specifier in pathname */
373 		if(systemtype(Windows) && p && p[1] == ':'){
374 			p += 2;
375 			c = *p;
376 		}
377 		if(p && p[0] != c && h->offset == 0 && pathname){
378 			/* on windows skip drive specifier in pathname */
379 			if(systemtype(Windows) && pathname[1] == ':') {
380 				op = p;
381 				p = pathname+2;
382 				c = *p;
383 			} else if(pathname[0] == c){
384 				op = p;
385 				p = pathname;
386 			}
387 		}
388 		while(p) {
389 			q = utfrune(p, c);
390 			if(q) {
391 				n = q-p;
392 				if(n == 0){
393 					n = 1;	/* leading "/" */
394 					*p = '/';	/* don't emit "\" on windows */
395 				}
396 				q++;
397 			} else {
398 				n = strlen(p);
399 				q = 0;
400 			}
401 			if(n) {
402 				Bputc(b, ANAME);
403 				Bputc(b, D_FILE);
404 				Bputc(b, 1);
405 				Bputc(b, '<');
406 				Bwrite(b, p, n);
407 				Bputc(b, 0);
408 			}
409 			p = q;
410 			if(p == 0 && op) {
411 				p = op;
412 				op = 0;
413 			}
414 		}
415 		pg.lineno = h->line;
416 		pg.to.type = zprog.to.type;
417 		pg.to.offset = h->offset;
418 		if(h->offset)
419 			pg.to.type = D_CONST;
420 
421 		zwrite(b, &pg, 0, 0);
422 	}
423 }
424 
425 void
zname(Biobuf * b,Sym * s,int t)426 zname(Biobuf *b, Sym *s, int t)
427 {
428 	char *n;
429 	ulong sig;
430 
431 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
432 		sig = sign(s);
433 		Bputc(b, ASIGNAME);
434 		Bputc(b, sig);
435 		Bputc(b, sig>>8);
436 		Bputc(b, sig>>16);
437 		Bputc(b, sig>>24);
438 		s->sig = SIGDONE;
439 	}
440 	else
441 		Bputc(b, ANAME);	/* as */
442 	Bputc(b, t);		/* type */
443 	Bputc(b, s->sym);		/* sym */
444 	n = s->name;
445 	while(*n) {
446 		Bputc(b, *n);
447 		n++;
448 	}
449 	Bputc(b, 0);
450 }
451 
452 void
zaddr(Biobuf * b,Adr * a,int s)453 zaddr(Biobuf *b, Adr *a, int s)
454 {
455 	long l;
456 	int i;
457 	char *n;
458 	Ieee e;
459 
460 	Bputc(b, a->type);
461 	Bputc(b, a->reg);
462 	Bputc(b, s);
463 	Bputc(b, a->name);
464 	switch(a->type) {
465 	default:
466 		diag(Z, "unknown type %d in zaddr", a->type);
467 
468 	case D_NONE:
469 	case D_REG:
470 	case D_FREG:
471 	case D_CREG:
472 		break;
473 
474 	case D_OREG:
475 	case D_CONST:
476 	case D_BRANCH:
477 		l = a->offset;
478 		Bputc(b, l);
479 		Bputc(b, l>>8);
480 		Bputc(b, l>>16);
481 		Bputc(b, l>>24);
482 		break;
483 
484 	case D_SCONST:
485 		n = a->sval;
486 		for(i=0; i<NSNAME; i++) {
487 			Bputc(b, *n);
488 			n++;
489 		}
490 		break;
491 
492 	case D_FCONST:
493 		ieeedtod(&e, a->dval);
494 		l = e.l;
495 		Bputc(b, l);
496 		Bputc(b, l>>8);
497 		Bputc(b, l>>16);
498 		Bputc(b, l>>24);
499 		l = e.h;
500 		Bputc(b, l);
501 		Bputc(b, l>>8);
502 		Bputc(b, l>>16);
503 		Bputc(b, l>>24);
504 		break;
505 	}
506 }
507 
508 long
align(long i,Type * t,int op)509 align(long i, Type *t, int op)
510 {
511 	long o;
512 	Type *v;
513 	int w;
514 
515 	o = i;
516 	w = 1;
517 	switch(op) {
518 	default:
519 		diag(Z, "unknown align opcode %d", op);
520 		break;
521 
522 	case Asu2:	/* padding at end of a struct */
523 		w = SZ_LONG;
524 		if(packflg)
525 			w = packflg;
526 		break;
527 
528 	case Ael1:	/* initial allign of struct element */
529 		for(v=t; v->etype==TARRAY; v=v->link)
530 			;
531 		w = ewidth[v->etype];
532 		if(w <= 0 || w >= SZ_LONG)
533 			w = SZ_LONG;
534 		if(packflg)
535 			w = packflg;
536 		break;
537 
538 	case Ael2:	/* width of a struct element */
539 		o += t->width;
540 		break;
541 
542 	case Aarg0:	/* initial passbyptr argument in arg list */
543 		if(typesuv[t->etype]) {
544 			o = align(o, types[TIND], Aarg1);
545 			o = align(o, types[TIND], Aarg2);
546 		}
547 		break;
548 
549 	case Aarg1:	/* initial allign of parameter */
550 		w = ewidth[t->etype];
551 		if(w <= 0 || w >= SZ_LONG) {
552 			w = SZ_LONG;
553 			break;
554 		}
555 		o += SZ_LONG - w;	/* big endian adjustment */
556 		w = 1;
557 		break;
558 
559 	case Aarg2:	/* width of a parameter */
560 		o += t->width;
561 		w = SZ_LONG;
562 		break;
563 
564 	case Aaut3:	/* total allign of automatic */
565 		o = align(o, t, Ael1);
566 		o = align(o, t, Ael2);
567 		break;
568 	}
569 	o = round(o, w);
570 	if(debug['A'])
571 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
572 	return o;
573 }
574 
575 long
maxround(long max,long v)576 maxround(long max, long v)
577 {
578 	v = round(v, SZ_LONG);
579 	if(v > max)
580 		return v;
581 	return max;
582 }
583