xref: /inferno-os/utils/vc/swt.c (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1  #include "gc.h"
2  
3  void
4  swit1(C1 *q, int nc, long def, Node *n)
5  {
6  	Node tn;
7  
8  	regalloc(&tn, &regnode, Z);
9  	swit2(q, nc, def, n, &tn);
10  	regfree(&tn);
11  }
12  
13  void
14  swit2(C1 *q, int nc, long def, Node *n, Node *tn)
15  {
16  	C1 *r;
17  	int i;
18  	Prog *sp;
19  
20  	if(nc < 5) {
21  		for(i=0; i<nc; i++) {
22  			if(debug['K'])
23  				print("case = %.8llux\n", q->val);
24  			gmove(nodconst(q->val), tn);
25  			gopcode(OEQ, n, tn, Z);
26  			patch(p, q->label);
27  			q++;
28  		}
29  		gbranch(OGOTO);
30  		patch(p, def);
31  		return;
32  	}
33  	i = nc / 2;
34  	r = q+i;
35  	if(debug['K'])
36  		print("case > %.8llux\n", r->val);
37  	gmove(nodconst(r->val), tn);
38  	gopcode(OLT, tn, n, Z);
39  	sp = p;
40  	gopcode(OEQ, n, tn, Z);
41  	patch(p, r->label);
42  	swit2(q, i, def, n, tn);
43  
44  	if(debug['K'])
45  		print("case < %.8llux\n", r->val);
46  	patch(sp, pc);
47  	swit2(r+1, nc-i-1, def, n, tn);
48  }
49  
50  void
51  bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
52  {
53  	int sh;
54  	long v;
55  	Node *l;
56  
57  	/*
58  	 * n1 gets adjusted/masked value
59  	 * n2 gets address of cell
60  	 * n3 gets contents of cell
61  	 */
62  	l = b->left;
63  	if(n2 != Z) {
64  		regalloc(n1, l, nn);
65  		reglcgen(n2, l, Z);
66  		regalloc(n3, l, Z);
67  		gopcode(OAS, n2, Z, n3);
68  		gopcode(OAS, n3, Z, n1);
69  	} else {
70  		regalloc(n1, l, nn);
71  		cgen(l, n1);
72  	}
73  	if(b->type->shift == 0 && typeu[b->type->etype]) {
74  		v = ~0 + (1L << b->type->nbits);
75  		gopcode(OAND, nodconst(v), Z, n1);
76  	} else {
77  		sh = 32 - b->type->shift - b->type->nbits;
78  		if(sh > 0)
79  			gopcode(OASHL, nodconst(sh), Z, n1);
80  		sh += b->type->shift;
81  		if(sh > 0)
82  			if(typeu[b->type->etype])
83  				gopcode(OLSHR, nodconst(sh), Z, n1);
84  			else
85  				gopcode(OASHR, nodconst(sh), Z, n1);
86  	}
87  }
88  
89  void
90  bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
91  {
92  	long v;
93  	Node nod, *l;
94  	int sh;
95  
96  	/*
97  	 * n1 has adjusted/masked value
98  	 * n2 has address of cell
99  	 * n3 has contents of cell
100  	 */
101  	l = b->left;
102  	regalloc(&nod, l, Z);
103  	v = ~0 + (1L << b->type->nbits);
104  	gopcode(OAND, nodconst(v), Z, n1);
105  	gopcode(OAS, n1, Z, &nod);
106  	if(nn != Z)
107  		gopcode(OAS, n1, Z, nn);
108  	sh = b->type->shift;
109  	if(sh > 0)
110  		gopcode(OASHL, nodconst(sh), Z, &nod);
111  	v <<= sh;
112  	gopcode(OAND, nodconst(~v), Z, n3);
113  	gopcode(OOR, n3, Z, &nod);
114  	gopcode(OAS, &nod, Z, n2);
115  
116  	regfree(&nod);
117  	regfree(n1);
118  	regfree(n2);
119  	regfree(n3);
120  }
121  
122  long
123  outstring(char *s, long n)
124  {
125  	long r;
126  
127  	r = nstring;
128  	while(n) {
129  		string[mnstring] = *s++;
130  		mnstring++;
131  		nstring++;
132  		if(mnstring >= NSNAME) {
133  			gpseudo(ADATA, symstring, nodconst(0L));
134  			p->from.offset += nstring - NSNAME;
135  			p->reg = NSNAME;
136  			p->to.type = D_SCONST;
137  			memmove(p->to.sval, string, NSNAME);
138  			mnstring = 0;
139  		}
140  		n--;
141  	}
142  	return r;
143  }
144  
145  int
146  mulcon(Node *n, Node *nn)
147  {
148  	Node *l, *r, nod1, nod2;
149  	Multab *m;
150  	long v;
151  	int o;
152  	char code[sizeof(m->code)+2], *p;
153  
154  	if(typefd[n->type->etype])
155  		return 0;
156  	l = n->left;
157  	r = n->right;
158  	if(l->op == OCONST) {
159  		l = r;
160  		r = n->left;
161  	}
162  	if(r->op != OCONST)
163  		return 0;
164  	v = convvtox(r->vconst, n->type->etype);
165  	if(v != r->vconst) {
166  		if(debug['M'])
167  			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
168  		return 0;
169  	}
170  	m = mulcon0(v);
171  	if(!m) {
172  		if(debug['M'])
173  			print("%L multiply table: %lld\n", n->lineno, r->vconst);
174  		return 0;
175  	}
176  	if(debug['M'] && debug['v'])
177  		print("%L multiply: %ld\n", n->lineno, v);
178  
179  	memmove(code, m->code, sizeof(m->code));
180  	code[sizeof(m->code)] = 0;
181  
182  	p = code;
183  	if(p[1] == 'i')
184  		p += 2;
185  	regalloc(&nod1, n, nn);
186  	cgen(l, &nod1);
187  	if(v < 0)
188  		gopcode(OSUB, &nod1, nodconst(0), &nod1);
189  	regalloc(&nod2, n, Z);
190  
191  loop:
192  	switch(*p) {
193  	case 0:
194  		regfree(&nod2);
195  		gopcode(OAS, &nod1, Z, nn);
196  		regfree(&nod1);
197  		return 1;
198  	case '+':
199  		o = OADD;
200  		goto addsub;
201  	case '-':
202  		o = OSUB;
203  	addsub:	/* number is r,n,l */
204  		v = p[1] - '0';
205  		r = &nod1;
206  		if(v&4)
207  			r = &nod2;
208  		n = &nod1;
209  		if(v&2)
210  			n = &nod2;
211  		l = &nod1;
212  		if(v&1)
213  			l = &nod2;
214  		gopcode(o, l, n, r);
215  		break;
216  	default: /* op is shiftcount, number is r,l */
217  		v = p[1] - '0';
218  		r = &nod1;
219  		if(v&2)
220  			r = &nod2;
221  		l = &nod1;
222  		if(v&1)
223  			l = &nod2;
224  		v = *p - 'a';
225  		if(v < 0 || v >= 32) {
226  			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
227  			break;
228  		}
229  		gopcode(OASHL, nodconst(v), l, r);
230  		break;
231  	}
232  	p += 2;
233  	goto loop;
234  }
235  
236  void
237  gextern(Sym *s, Node *a, long o, long w)
238  {
239  
240  	if(a->op == OCONST && typev[a->type->etype]) {
241  		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
242  			gpseudo(ADATA, s, nod32const(a->vconst>>32));
243  		else
244  			gpseudo(ADATA, s, nod32const(a->vconst));
245  		p->from.offset += o;
246  		p->reg = 4;
247  		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
248  			gpseudo(ADATA, s, nod32const(a->vconst));
249  		else
250  			gpseudo(ADATA, s, nod32const(a->vconst>>32));
251  		p->from.offset += o + 4;
252  		p->reg = 4;
253  		return;
254  	}
255  	gpseudo(ADATA, s, a);
256  	p->from.offset += o;
257  	p->reg = w;
258  	if(p->to.type == D_OREG)
259  		p->to.type = D_CONST;
260  }
261  
262  void	zname(Biobuf*, Sym*, int);
263  char*	zaddr(char*, Adr*, int);
264  void	zwrite(Biobuf*, Prog*, int, int);
265  void	outhist(Biobuf*);
266  
267  void
268  zwrite(Biobuf *b, Prog *p, int sf, int st)
269  {
270  	char bf[100], *bp;
271  
272  	bf[0] = p->as;
273  	bf[1] = p->reg;
274  	bf[2] = p->lineno;
275  	bf[3] = p->lineno>>8;
276  	bf[4] = p->lineno>>16;
277  	bf[5] = p->lineno>>24;
278  	bp = zaddr(bf+6, &p->from, sf);
279  	bp = zaddr(bp, &p->to, st);
280  	Bwrite(b, bf, bp-bf);
281  }
282  
283  void
284  outcode(void)
285  {
286  	struct { Sym *sym; short type; } h[NSYM];
287  	Prog *p;
288  	Sym *s;
289  	int sf, st, t, sym;
290  
291  	if(debug['S']) {
292  		for(p = firstp; p != P; p = p->link)
293  			if(p->as != ADATA && p->as != AGLOBL)
294  				pc--;
295  		for(p = firstp; p != P; p = p->link) {
296  			print("%P\n", p);
297  			if(p->as != ADATA && p->as != AGLOBL)
298  				pc++;
299  		}
300  	}
301  	outhist(&outbuf);
302  	for(sym=0; sym<NSYM; sym++) {
303  		h[sym].sym = S;
304  		h[sym].type = 0;
305  	}
306  	sym = 1;
307  	for(p = firstp; p != P; p = p->link) {
308  	jackpot:
309  		sf = 0;
310  		s = p->from.sym;
311  		while(s != S) {
312  			sf = s->sym;
313  			if(sf < 0 || sf >= NSYM)
314  				sf = 0;
315  			t = p->from.name;
316  			if(h[sf].type == t)
317  			if(h[sf].sym == s)
318  				break;
319  			s->sym = sym;
320  			zname(&outbuf, s, t);
321  			h[sym].sym = s;
322  			h[sym].type = t;
323  			sf = sym;
324  			sym++;
325  			if(sym >= NSYM)
326  				sym = 1;
327  			break;
328  		}
329  		st = 0;
330  		s = p->to.sym;
331  		while(s != S) {
332  			st = s->sym;
333  			if(st < 0 || st >= NSYM)
334  				st = 0;
335  			t = p->to.name;
336  			if(h[st].type == t)
337  			if(h[st].sym == s)
338  				break;
339  			s->sym = sym;
340  			zname(&outbuf, s, t);
341  			h[sym].sym = s;
342  			h[sym].type = t;
343  			st = sym;
344  			sym++;
345  			if(sym >= NSYM)
346  				sym = 1;
347  			if(st == sf)
348  				goto jackpot;
349  			break;
350  		}
351  		zwrite(&outbuf, p, sf, st);
352  	}
353  	firstp = P;
354  	lastp = P;
355  }
356  
357  void
358  outhist(Biobuf *b)
359  {
360  	Hist *h;
361  	char *p, *q, *op, c;
362  	Prog pg;
363  	int n;
364  
365  	pg = zprog;
366  	pg.as = AHISTORY;
367  	c = pathchar();
368  	for(h = hist; h != H; h = h->link) {
369  		p = h->name;
370  		op = 0;
371  		/* on windows skip drive specifier in pathname */
372  		if(systemtype(Windows) && p && p[1] == ':'){
373  			p += 2;
374  			c = *p;
375  		}
376  		if(p && p[0] != c && h->offset == 0 && pathname){
377  			/* on windows skip drive specifier in pathname */
378  			if(systemtype(Windows) && pathname[1] == ':') {
379  				op = p;
380  				p = pathname+2;
381  				c = *p;
382  			} else if(pathname[0] == c){
383  				op = p;
384  				p = pathname;
385  			}
386  		}
387  		while(p) {
388  			q = utfrune(p, c);
389  			if(q) {
390  				n = q-p;
391  				if(n == 0){
392  					n = 1;	/* leading "/" */
393  					*p = '/';	/* don't emit "\" on windows */
394  				}
395  				q++;
396  			} else {
397  				n = strlen(p);
398  				q = 0;
399  			}
400  			if(n) {
401  				Bputc(b, ANAME);
402  				Bputc(b, D_FILE);
403  				Bputc(b, 1);
404  				Bputc(b, '<');
405  				Bwrite(b, p, n);
406  				Bputc(b, 0);
407  			}
408  			p = q;
409  			if(p == 0 && op) {
410  				p = op;
411  				op = 0;
412  			}
413  		}
414  		pg.lineno = h->line;
415  		pg.to.type = zprog.to.type;
416  		pg.to.offset = h->offset;
417  		if(h->offset)
418  			pg.to.type = D_CONST;
419  
420  		zwrite(b, &pg, 0, 0);
421  	}
422  }
423  
424  void
425  zname(Biobuf *b, Sym *s, int t)
426  {
427  	char *n, bf[7];
428  	ulong sig;
429  
430  	n = s->name;
431  	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
432  		sig = sign(s);
433  		bf[0] = ASIGNAME;
434  		bf[1] = sig;
435  		bf[2] = sig>>8;
436  		bf[3] = sig>>16;
437  		bf[4] = sig>>24;
438  		bf[5] = t;
439  		bf[6] = s->sym;
440  		Bwrite(b, bf, 7);
441  		s->sig = SIGDONE;
442  	}
443  	else{
444  		bf[0] = ANAME;
445  		bf[1] = t;	/* type */
446  		bf[2] = s->sym;	/* sym */
447  		Bwrite(b, bf, 3);
448  	}
449  	Bwrite(b, n, strlen(n)+1);
450  }
451  
452  char*
453  zaddr(char *bp, Adr *a, int s)
454  {
455  	long l;
456  	Ieee e;
457  
458  	bp[0] = a->type;
459  	bp[1] = a->reg;
460  	bp[2] = s;
461  	bp[3] = a->name;
462  	bp += 4;
463  	switch(a->type) {
464  	default:
465  		diag(Z, "unknown type %d in zaddr", a->type);
466  
467  	case D_NONE:
468  	case D_REG:
469  	case D_FREG:
470  	case D_MREG:
471  	case D_FCREG:
472  	case D_LO:
473  	case D_HI:
474  		break;
475  
476  	case D_OREG:
477  	case D_CONST:
478  	case D_BRANCH:
479  		l = a->offset;
480  		bp[0] = l;
481  		bp[1] = l>>8;
482  		bp[2] = l>>16;
483  		bp[3] = l>>24;
484  		bp += 4;
485  		break;
486  
487  	case D_SCONST:
488  		memmove(bp, a->sval, NSNAME);
489  		bp += NSNAME;
490  		break;
491  
492  	case D_FCONST:
493  		ieeedtod(&e, a->dval);
494  		l = e.l;
495  		bp[0] = l;
496  		bp[1] = l>>8;
497  		bp[2] = l>>16;
498  		bp[3] = l>>24;
499  		bp += 4;
500  		l = e.h;
501  		bp[0] = l;
502  		bp[1] = l>>8;
503  		bp[2] = l>>16;
504  		bp[3] = l>>24;
505  		bp += 4;
506  		break;
507  	}
508  	return bp;
509  }
510  
511  long
512  align(long i, Type *t, int op)
513  {
514  	long o;
515  	Type *v;
516  	int w;
517  
518  	o = i;
519  	w = 1;
520  	switch(op) {
521  	default:
522  		diag(Z, "unknown align opcode %d", op);
523  		break;
524  
525  	case Asu2:	/* padding at end of a struct */
526  		w = SZ_LONG;
527  		if(packflg)
528  			w = packflg;
529  		break;
530  
531  	case Ael1:	/* initial allign of struct element */
532  		for(v=t; v->etype==TARRAY; v=v->link)
533  			;
534  		w = ewidth[v->etype];
535  		if(w <= 0 || w >= SZ_LONG)
536  			w = SZ_LONG;
537  		if(packflg)
538  			w = packflg;
539  		break;
540  
541  	case Ael2:	/* width of a struct element */
542  		o += t->width;
543  		break;
544  
545  	case Aarg0:	/* initial passbyptr argument in arg list */
546  		if(typesuv[t->etype]) {
547  			o = align(o, types[TIND], Aarg1);
548  			o = align(o, types[TIND], Aarg2);
549  		}
550  		break;
551  
552  	case Aarg1:	/* initial allign of parameter */
553  		w = ewidth[t->etype];
554  		if(w <= 0 || w >= SZ_LONG) {
555  			w = SZ_LONG;
556  			break;
557  		}
558  		if(thechar == 'v')
559  			o += SZ_LONG - w;	/* big endian adjustment */
560  		w = 1;
561  		break;
562  
563  	case Aarg2:	/* width of a parameter */
564  		o += t->width;
565  		w = SZ_LONG;
566  		break;
567  
568  	case Aaut3:	/* total allign of automatic */
569  		o = align(o, t, Ael1);
570  		o = align(o, t, Ael2);
571  		break;
572  	}
573  	o = round(o, w);
574  	if(debug['A'])
575  		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
576  	return o;
577  }
578  
579  long
580  maxround(long max, long v)
581  {
582  	v = round(v, SZ_LONG);
583  	if(v > max)
584  		return v;
585  	return max;
586  }
587