xref: /inferno-os/utils/0c/swt.c (revision 50b0dbb170df61467e42c7ea4deb0b5692d15f4c)
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 	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(TRune *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 
327 void
328 gextern(Sym *s, Node *a, long o, long w)
329 {
330 
331 	if(a->op == OCONST && typev[a->type->etype]) {
332 		gpseudo(ADATA, s, nodconst(a->vconst));
333 		p->from.offset += o;
334 		p->reg = 4;
335 		gpseudo(ADATA, s, nodconst(a->vconst>>32));
336 		p->from.offset += o + 4;
337 		p->reg = 4;
338 		return;
339 	}
340 	gpseudo(ADATA, s, a);
341 	p->from.offset += o;
342 	p->reg = w;
343 	if(p->to.type == D_OREG)
344 		p->to.type = D_CONST;
345 }
346 
347 void	zname(Biobuf*, Sym*, int);
348 char*	zaddr(char*, Adr*, int);
349 void	zwrite(Biobuf*, Prog*, int, int);
350 void	outhist(Biobuf*);
351 
352 void
353 zwrite(Biobuf *b, Prog *p, int sf, int st)
354 {
355 	char bf[100], *bp;
356 
357 	bf[0] = p->as;
358 	bf[1] = p->reg;
359 	bf[2] = p->lineno;
360 	bf[3] = p->lineno>>8;
361 	bf[4] = p->lineno>>16;
362 	bf[5] = p->lineno>>24;
363 	bp = zaddr(bf+6, &p->from, sf);
364 	bp = zaddr(bp, &p->to, st);
365 	Bwrite(b, bf, bp-bf);
366 }
367 
368 void
369 outcode(void)
370 {
371 	struct { Sym *sym; short type; } h[NSYM];
372 	Prog *p;
373 	Sym *s;
374 	int sf, st, t, sym;
375 
376 	if(debug['S']) {
377 		for(p = firstp; p != P; p = p->link)
378 			if(p->as != ADATA && p->as != AGLOBL)
379 				pc--;
380 		for(p = firstp; p != P; p = p->link) {
381 			print("%P\n", p);
382 			if(p->as != ADATA && p->as != AGLOBL)
383 				pc++;
384 		}
385 	}
386 	outhist(&outbuf);
387 	for(sym=0; sym<NSYM; sym++) {
388 		h[sym].sym = S;
389 		h[sym].type = 0;
390 	}
391 	sym = 1;
392 	for(p = firstp; p != P; p = p->link) {
393 	jackpot:
394 		sf = 0;
395 		s = p->from.sym;
396 		while(s != S) {
397 			sf = s->sym;
398 			if(sf < 0 || sf >= NSYM)
399 				sf = 0;
400 			t = p->from.name;
401 			if(h[sf].type == t)
402 			if(h[sf].sym == s)
403 				break;
404 			s->sym = sym;
405 			zname(&outbuf, s, t);
406 			h[sym].sym = s;
407 			h[sym].type = t;
408 			sf = sym;
409 			sym++;
410 			if(sym >= NSYM)
411 				sym = 1;
412 			break;
413 		}
414 		st = 0;
415 		s = p->to.sym;
416 		while(s != S) {
417 			st = s->sym;
418 			if(st < 0 || st >= NSYM)
419 				st = 0;
420 			t = p->to.name;
421 			if(h[st].type == t)
422 			if(h[st].sym == s)
423 				break;
424 			s->sym = sym;
425 			zname(&outbuf, s, t);
426 			h[sym].sym = s;
427 			h[sym].type = t;
428 			st = sym;
429 			sym++;
430 			if(sym >= NSYM)
431 				sym = 1;
432 			if(st == sf)
433 				goto jackpot;
434 			break;
435 		}
436 		zwrite(&outbuf, p, sf, st);
437 	}
438 	firstp = P;
439 	lastp = P;
440 }
441 
442 void
443 outhist(Biobuf *b)
444 {
445 	Hist *h;
446 	char *p, *q, *op, c;
447 	Prog pg;
448 	int n;
449 
450 	pg = zprog;
451 	pg.as = AHISTORY;
452 	c = pathchar();
453 	for(h = hist; h != H; h = h->link) {
454 		p = h->name;
455 		op = 0;
456 		/* on windows skip drive specifier in pathname */
457 		if(systemtype(Windows) && p && p[1] == ':'){
458 			p += 2;
459 			c = *p;
460 		}
461 		if(p && p[0] != c && h->offset == 0 && pathname){
462 			/* on windows skip drive specifier in pathname */
463 			if(systemtype(Windows) && pathname[1] == ':') {
464 				op = p;
465 				p = pathname+2;
466 				c = *p;
467 			} else if(pathname[0] == c){
468 				op = p;
469 				p = pathname;
470 			}
471 		}
472 		while(p) {
473 			q = utfrune(p, c);
474 			if(q) {
475 				n = q-p;
476 				if(n == 0){
477 					n = 1;	/* leading "/" */
478 					*p = '/';	/* don't emit "\" on windows */
479 				}
480 				q++;
481 			} else {
482 				n = strlen(p);
483 				q = 0;
484 			}
485 			if(n) {
486 				Bputc(b, ANAME);
487 				Bputc(b, D_FILE);
488 				Bputc(b, 1);
489 				Bputc(b, '<');
490 				Bwrite(b, p, n);
491 				Bputc(b, 0);
492 			}
493 			p = q;
494 			if(p == 0 && op) {
495 				p = op;
496 				op = 0;
497 			}
498 		}
499 		pg.lineno = h->line;
500 		pg.to.type = zprog.to.type;
501 		pg.to.offset = h->offset;
502 		if(h->offset)
503 			pg.to.type = D_CONST;
504 
505 		zwrite(b, &pg, 0, 0);
506 	}
507 }
508 
509 void
510 zname(Biobuf *b, Sym *s, int t)
511 {
512 	char *n, bf[7];
513 	ulong sig;
514 
515 	n = s->name;
516 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
517 		sig = sign(s);
518 		bf[0] = ASIGNAME;
519 		bf[1] = sig;
520 		bf[2] = sig>>8;
521 		bf[3] = sig>>16;
522 		bf[4] = sig>>24;
523 		bf[5] = t;
524 		bf[6] = s->sym;
525 		Bwrite(b, bf, 7);
526 		s->sig = SIGDONE;
527 	}
528 	else{
529 		bf[0] = ANAME;
530 		bf[1] = t;	/* type */
531 		bf[2] = s->sym;	/* sym */
532 		Bwrite(b, bf, 3);
533 	}
534 	Bwrite(b, n, strlen(n)+1);
535 }
536 
537 char*
538 zaddr(char *bp, Adr *a, int s)
539 {
540 	vlong v;
541 	long l;
542 	Ieee e;
543 
544 	bp[0] = a->type;
545 	bp[1] = a->reg;
546 	bp[2] = s;
547 	bp[3] = a->name;
548 	bp += 4;
549 	switch(a->type) {
550 	default:
551 		diag(Z, "unknown type %d in zaddr", a->type);
552 
553 	case D_NONE:
554 	case D_REG:
555 	case D_FREG:
556 	case D_MREG:
557 	case D_FCREG:
558 	case D_LO:
559 	case D_HI:
560 		break;
561 
562 	case D_CONST:
563 	case D_OREG:
564 	case D_BRANCH:
565 		l = a->offset;
566 		bp[0] = l;
567 		bp[1] = l>>8;
568 		bp[2] = l>>16;
569 		bp[3] = l>>24;
570 		bp += 4;
571 		break;
572 
573 	case D_SCONST:
574 		memmove(bp, a->sval, NSNAME);
575 		bp += NSNAME;
576 		break;
577 
578 	case D_FCONST:
579 		ieeedtod(&e, a->dval);
580 		l = e.l;
581 		bp[0] = l;
582 		bp[1] = l>>8;
583 		bp[2] = l>>16;
584 		bp[3] = l>>24;
585 		bp += 4;
586 		l = e.h;
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 	case D_VCONST:
594 		v = a->vval;
595 		bp[0] = v;
596 		bp[1] = v>>8;
597 		bp[2] = v>>16;
598 		bp[3] = v>>24;
599 		bp[4] = v>>32;
600 		bp[5] = v>>40;
601 		bp[6] = v>>48;
602 		bp[7] = v>>56;
603 		bp += 8;
604 		break;
605 	}
606 	return bp;
607 }
608 
609 void
610 ieeedtod(Ieee *ieee, double native)
611 {
612 	double fr, ho, f;
613 	int exp;
614 
615 	if(native < 0) {
616 		ieeedtod(ieee, -native);
617 		ieee->h |= 0x80000000L;
618 		return;
619 	}
620 	if(native == 0) {
621 		ieee->l = 0;
622 		ieee->h = 0;
623 		return;
624 	}
625 	fr = frexp(native, &exp);
626 	f = 2097152L;		/* shouldnt use fp constants here */
627 	fr = modf(fr*f, &ho);
628 	ieee->h = ho;
629 	ieee->h &= 0xfffffL;
630 	ieee->h |= (exp+1022L) << 20;
631 	f = 65536L;
632 	fr = modf(fr*f, &ho);
633 	ieee->l = ho;
634 	ieee->l <<= 16;
635 	ieee->l |= (long)(fr*f);
636 }
637 
638 long
639 align(long i, Type *t, int op)
640 {
641 	long o;
642 	Type *v;
643 	int w;
644 
645 	o = i;
646 	w = 1;
647 	switch(op) {
648 	default:
649 		diag(Z, "unknown align opcode %d", op);
650 		break;
651 
652 	case Asu2:	/* padding at end of a struct */
653 		w = SZ_VLONG;
654 		if(packflg)
655 			w = packflg;
656 		break;
657 
658 	case Ael1:	/* initial allign of struct element */
659 		for(v=t; v->etype==TARRAY; v=v->link)
660 			;
661 		w = ewidth[v->etype];
662 		if(w <= 0 || w >= SZ_VLONG)
663 			w = SZ_VLONG;
664 		if(packflg)
665 			w = packflg;
666 		break;
667 
668 	case Ael2:	/* width of a struct element */
669 		o += t->width;
670 		break;
671 
672 	case Aarg0:	/* initial passbyptr argument in arg list */
673 		if(typesu[t->etype]) {
674 			o = align(o, types[TIND], Aarg1);
675 			o = align(o, types[TIND], Aarg2);
676 		}
677 		break;
678 
679 	case Aarg1:	/* initial allign of parameter */
680 		w = ewidth[t->etype];
681 		if(w <= 0 || w >= SZ_VLONG) {
682 			w = SZ_VLONG;
683 			break;
684 		}
685 		w = 1;		/* little endian no adjustment */
686 		break;
687 
688 	case Aarg2:	/* width of a parameter */
689 		o += t->width;
690 		w = SZ_LONG;
691 		break;
692 
693 	case Aaut3:	/* total allign of automatic */
694 		o = align(o, t, Ael1);
695 		o = align(o, t, Ael2);
696 		break;
697 	}
698 	o = round(o, w);
699 	if(debug['A'])
700 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
701 	return o;
702 }
703 
704 long
705 maxround(long max, long v)
706 {
707 	v += SZ_VLONG-1;
708 	if(v > max)
709 		max = round(v, SZ_VLONG);
710 	return max;
711 }
712