xref: /inferno-os/utils/vc/swt.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
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  cas(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  		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
349  			gpseudo(ADATA, s, nod32const(a->vconst>>32));
350  		else
351  			gpseudo(ADATA, s, nod32const(a->vconst));
352  		p->from.offset += o;
353  		p->reg = 4;
354  		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
355  			gpseudo(ADATA, s, nod32const(a->vconst));
356  		else
357  			gpseudo(ADATA, s, nod32const(a->vconst>>32));
358  		p->from.offset += o + 4;
359  		p->reg = 4;
360  		return;
361  	}
362  	gpseudo(ADATA, s, a);
363  	p->from.offset += o;
364  	p->reg = w;
365  	if(p->to.type == D_OREG)
366  		p->to.type = D_CONST;
367  }
368  
369  void	zname(Biobuf*, Sym*, int);
370  char*	zaddr(char*, Adr*, int);
371  void	zwrite(Biobuf*, Prog*, int, int);
372  void	outhist(Biobuf*);
373  
374  void
375  zwrite(Biobuf *b, Prog *p, int sf, int st)
376  {
377  	char bf[100], *bp;
378  
379  	bf[0] = p->as;
380  	bf[1] = p->reg;
381  	bf[2] = p->lineno;
382  	bf[3] = p->lineno>>8;
383  	bf[4] = p->lineno>>16;
384  	bf[5] = p->lineno>>24;
385  	bp = zaddr(bf+6, &p->from, sf);
386  	bp = zaddr(bp, &p->to, st);
387  	Bwrite(b, bf, bp-bf);
388  }
389  
390  void
391  outcode(void)
392  {
393  	struct { Sym *sym; short type; } h[NSYM];
394  	Prog *p;
395  	Sym *s;
396  	int sf, st, t, sym;
397  
398  	if(debug['S']) {
399  		for(p = firstp; p != P; p = p->link)
400  			if(p->as != ADATA && p->as != AGLOBL)
401  				pc--;
402  		for(p = firstp; p != P; p = p->link) {
403  			print("%P\n", p);
404  			if(p->as != ADATA && p->as != AGLOBL)
405  				pc++;
406  		}
407  	}
408  	outhist(&outbuf);
409  	for(sym=0; sym<NSYM; sym++) {
410  		h[sym].sym = S;
411  		h[sym].type = 0;
412  	}
413  	sym = 1;
414  	for(p = firstp; p != P; p = p->link) {
415  	jackpot:
416  		sf = 0;
417  		s = p->from.sym;
418  		while(s != S) {
419  			sf = s->sym;
420  			if(sf < 0 || sf >= NSYM)
421  				sf = 0;
422  			t = p->from.name;
423  			if(h[sf].type == t)
424  			if(h[sf].sym == s)
425  				break;
426  			s->sym = sym;
427  			zname(&outbuf, s, t);
428  			h[sym].sym = s;
429  			h[sym].type = t;
430  			sf = sym;
431  			sym++;
432  			if(sym >= NSYM)
433  				sym = 1;
434  			break;
435  		}
436  		st = 0;
437  		s = p->to.sym;
438  		while(s != S) {
439  			st = s->sym;
440  			if(st < 0 || st >= NSYM)
441  				st = 0;
442  			t = p->to.name;
443  			if(h[st].type == t)
444  			if(h[st].sym == s)
445  				break;
446  			s->sym = sym;
447  			zname(&outbuf, s, t);
448  			h[sym].sym = s;
449  			h[sym].type = t;
450  			st = sym;
451  			sym++;
452  			if(sym >= NSYM)
453  				sym = 1;
454  			if(st == sf)
455  				goto jackpot;
456  			break;
457  		}
458  		zwrite(&outbuf, p, sf, st);
459  	}
460  	firstp = P;
461  	lastp = P;
462  }
463  
464  void
465  outhist(Biobuf *b)
466  {
467  	Hist *h;
468  	char *p, *q, *op, c;
469  	Prog pg;
470  	int n;
471  
472  	pg = zprog;
473  	pg.as = AHISTORY;
474  	c = pathchar();
475  	for(h = hist; h != H; h = h->link) {
476  		p = h->name;
477  		op = 0;
478  		/* on windows skip drive specifier in pathname */
479  		if(systemtype(Windows) && p && p[1] == ':'){
480  			p += 2;
481  			c = *p;
482  		}
483  		if(p && p[0] != c && h->offset == 0 && pathname){
484  			/* on windows skip drive specifier in pathname */
485  			if(systemtype(Windows) && pathname[1] == ':') {
486  				op = p;
487  				p = pathname+2;
488  				c = *p;
489  			} else if(pathname[0] == c){
490  				op = p;
491  				p = pathname;
492  			}
493  		}
494  		while(p) {
495  			q = utfrune(p, c);
496  			if(q) {
497  				n = q-p;
498  				if(n == 0){
499  					n = 1;	/* leading "/" */
500  					*p = '/';	/* don't emit "\" on windows */
501  				}
502  				q++;
503  			} else {
504  				n = strlen(p);
505  				q = 0;
506  			}
507  			if(n) {
508  				Bputc(b, ANAME);
509  				Bputc(b, D_FILE);
510  				Bputc(b, 1);
511  				Bputc(b, '<');
512  				Bwrite(b, p, n);
513  				Bputc(b, 0);
514  			}
515  			p = q;
516  			if(p == 0 && op) {
517  				p = op;
518  				op = 0;
519  			}
520  		}
521  		pg.lineno = h->line;
522  		pg.to.type = zprog.to.type;
523  		pg.to.offset = h->offset;
524  		if(h->offset)
525  			pg.to.type = D_CONST;
526  
527  		zwrite(b, &pg, 0, 0);
528  	}
529  }
530  
531  void
532  zname(Biobuf *b, Sym *s, int t)
533  {
534  	char *n, bf[7];
535  	ulong sig;
536  
537  	n = s->name;
538  	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
539  		sig = sign(s);
540  		bf[0] = ASIGNAME;
541  		bf[1] = sig;
542  		bf[2] = sig>>8;
543  		bf[3] = sig>>16;
544  		bf[4] = sig>>24;
545  		bf[5] = t;
546  		bf[6] = s->sym;
547  		Bwrite(b, bf, 7);
548  		s->sig = SIGDONE;
549  	}
550  	else{
551  		bf[0] = ANAME;
552  		bf[1] = t;	/* type */
553  		bf[2] = s->sym;	/* sym */
554  		Bwrite(b, bf, 3);
555  	}
556  	Bwrite(b, n, strlen(n)+1);
557  }
558  
559  char*
560  zaddr(char *bp, Adr *a, int s)
561  {
562  	long l;
563  	Ieee e;
564  
565  	bp[0] = a->type;
566  	bp[1] = a->reg;
567  	bp[2] = s;
568  	bp[3] = a->name;
569  	bp += 4;
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_MREG:
578  	case D_FCREG:
579  	case D_LO:
580  	case D_HI:
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  		o += SZ_LONG - w;	/* big endian adjustment */
691  		w = 1;
692  		break;
693  
694  	case Aarg2:	/* width of a parameter */
695  		o += t->width;
696  		w = SZ_LONG;
697  		break;
698  
699  	case Aaut3:	/* total allign of automatic */
700  		o = align(o, t, Ael1);
701  		o = align(o, t, Ael2);
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 += SZ_LONG-1;
714  	if(v > max)
715  		max = round(v, SZ_LONG);
716  	return max;
717  }
718