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