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