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