xref: /inferno-os/utils/vc/swt.c (revision 90ccc69f5be0b7e26c3607dac07340fe3e271509)
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['W'])
23 				print("case = %.8lux\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['W'])
36 		print("case > %.8lux\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['W'])
45 		print("case < %.8lux\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 sextern(Sym *s, Node *a, long o, long w)
238 {
239 	long e, lw;
240 
241 	for(e=0; e<w; e+=NSNAME) {
242 		lw = NSNAME;
243 		if(w-e < lw)
244 			lw = w-e;
245 		gpseudo(ADATA, s, nodconst(0));
246 		p->from.offset += o+e;
247 		p->reg = lw;
248 		p->to.type = D_SCONST;
249 		memmove(p->to.sval, a->cstring+e, lw);
250 	}
251 }
252 
253 void
254 gextern(Sym *s, Node *a, long o, long w)
255 {
256 
257 	if(a->op == OCONST && typev[a->type->etype]) {
258 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
259 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
260 		else
261 			gpseudo(ADATA, s, nod32const(a->vconst));
262 		p->from.offset += o;
263 		p->reg = 4;
264 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
265 			gpseudo(ADATA, s, nod32const(a->vconst));
266 		else
267 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
268 		p->from.offset += o + 4;
269 		p->reg = 4;
270 		return;
271 	}
272 	gpseudo(ADATA, s, a);
273 	p->from.offset += o;
274 	p->reg = w;
275 	if(p->to.type == D_OREG)
276 		p->to.type = D_CONST;
277 }
278 
279 void	zname(Biobuf*, Sym*, int);
280 char*	zaddr(char*, Adr*, int);
281 void	zwrite(Biobuf*, Prog*, int, int);
282 void	outhist(Biobuf*);
283 
284 void
285 zwrite(Biobuf *b, Prog *p, int sf, int st)
286 {
287 	char bf[100], *bp;
288 
289 	bf[0] = p->as;
290 	bf[1] = p->reg;
291 	bf[2] = p->lineno;
292 	bf[3] = p->lineno>>8;
293 	bf[4] = p->lineno>>16;
294 	bf[5] = p->lineno>>24;
295 	bp = zaddr(bf+6, &p->from, sf);
296 	bp = zaddr(bp, &p->to, st);
297 	Bwrite(b, bf, bp-bf);
298 }
299 
300 void
301 outcode(void)
302 {
303 	struct { Sym *sym; short type; } h[NSYM];
304 	Prog *p;
305 	Sym *s;
306 	int sf, st, t, sym;
307 
308 	if(debug['S']) {
309 		for(p = firstp; p != P; p = p->link)
310 			if(p->as != ADATA && p->as != AGLOBL)
311 				pc--;
312 		for(p = firstp; p != P; p = p->link) {
313 			print("%P\n", p);
314 			if(p->as != ADATA && p->as != AGLOBL)
315 				pc++;
316 		}
317 	}
318 	outhist(&outbuf);
319 	for(sym=0; sym<NSYM; sym++) {
320 		h[sym].sym = S;
321 		h[sym].type = 0;
322 	}
323 	sym = 1;
324 	for(p = firstp; p != P; p = p->link) {
325 	jackpot:
326 		sf = 0;
327 		s = p->from.sym;
328 		while(s != S) {
329 			sf = s->sym;
330 			if(sf < 0 || sf >= NSYM)
331 				sf = 0;
332 			t = p->from.name;
333 			if(h[sf].type == t)
334 			if(h[sf].sym == s)
335 				break;
336 			s->sym = sym;
337 			zname(&outbuf, s, t);
338 			h[sym].sym = s;
339 			h[sym].type = t;
340 			sf = sym;
341 			sym++;
342 			if(sym >= NSYM)
343 				sym = 1;
344 			break;
345 		}
346 		st = 0;
347 		s = p->to.sym;
348 		while(s != S) {
349 			st = s->sym;
350 			if(st < 0 || st >= NSYM)
351 				st = 0;
352 			t = p->to.name;
353 			if(h[st].type == t)
354 			if(h[st].sym == s)
355 				break;
356 			s->sym = sym;
357 			zname(&outbuf, s, t);
358 			h[sym].sym = s;
359 			h[sym].type = t;
360 			st = sym;
361 			sym++;
362 			if(sym >= NSYM)
363 				sym = 1;
364 			if(st == sf)
365 				goto jackpot;
366 			break;
367 		}
368 		zwrite(&outbuf, p, sf, st);
369 	}
370 	firstp = P;
371 	lastp = P;
372 }
373 
374 void
375 outhist(Biobuf *b)
376 {
377 	Hist *h;
378 	char *p, *q, *op, c;
379 	Prog pg;
380 	int n;
381 
382 	pg = zprog;
383 	pg.as = AHISTORY;
384 	c = pathchar();
385 	for(h = hist; h != H; h = h->link) {
386 		p = h->name;
387 		op = 0;
388 		/* on windows skip drive specifier in pathname */
389 		if(systemtype(Windows) && p && p[1] == ':'){
390 			p += 2;
391 			c = *p;
392 		}
393 		if(p && p[0] != c && h->offset == 0 && pathname){
394 			/* on windows skip drive specifier in pathname */
395 			if(systemtype(Windows) && pathname[1] == ':') {
396 				op = p;
397 				p = pathname+2;
398 				c = *p;
399 			} else if(pathname[0] == c){
400 				op = p;
401 				p = pathname;
402 			}
403 		}
404 		while(p) {
405 			q = utfrune(p, c);
406 			if(q) {
407 				n = q-p;
408 				if(n == 0){
409 					n = 1;	/* leading "/" */
410 					*p = '/';	/* don't emit "\" on windows */
411 				}
412 				q++;
413 			} else {
414 				n = strlen(p);
415 				q = 0;
416 			}
417 			if(n) {
418 				Bputc(b, ANAME);
419 				Bputc(b, D_FILE);
420 				Bputc(b, 1);
421 				Bputc(b, '<');
422 				Bwrite(b, p, n);
423 				Bputc(b, 0);
424 			}
425 			p = q;
426 			if(p == 0 && op) {
427 				p = op;
428 				op = 0;
429 			}
430 		}
431 		pg.lineno = h->line;
432 		pg.to.type = zprog.to.type;
433 		pg.to.offset = h->offset;
434 		if(h->offset)
435 			pg.to.type = D_CONST;
436 
437 		zwrite(b, &pg, 0, 0);
438 	}
439 }
440 
441 void
442 zname(Biobuf *b, Sym *s, int t)
443 {
444 	char *n, bf[7];
445 	ulong sig;
446 
447 	n = s->name;
448 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
449 		sig = sign(s);
450 		bf[0] = ASIGNAME;
451 		bf[1] = sig;
452 		bf[2] = sig>>8;
453 		bf[3] = sig>>16;
454 		bf[4] = sig>>24;
455 		bf[5] = t;
456 		bf[6] = s->sym;
457 		Bwrite(b, bf, 7);
458 		s->sig = SIGDONE;
459 	}
460 	else{
461 		bf[0] = ANAME;
462 		bf[1] = t;	/* type */
463 		bf[2] = s->sym;	/* sym */
464 		Bwrite(b, bf, 3);
465 	}
466 	Bwrite(b, n, strlen(n)+1);
467 }
468 
469 char*
470 zaddr(char *bp, Adr *a, int s)
471 {
472 	long l;
473 	Ieee e;
474 
475 	bp[0] = a->type;
476 	bp[1] = a->reg;
477 	bp[2] = s;
478 	bp[3] = a->name;
479 	bp += 4;
480 	switch(a->type) {
481 	default:
482 		diag(Z, "unknown type %d in zaddr", a->type);
483 
484 	case D_NONE:
485 	case D_REG:
486 	case D_FREG:
487 	case D_MREG:
488 	case D_FCREG:
489 	case D_LO:
490 	case D_HI:
491 		break;
492 
493 	case D_OREG:
494 	case D_CONST:
495 	case D_BRANCH:
496 		l = a->offset;
497 		bp[0] = l;
498 		bp[1] = l>>8;
499 		bp[2] = l>>16;
500 		bp[3] = l>>24;
501 		bp += 4;
502 		break;
503 
504 	case D_SCONST:
505 		memmove(bp, a->sval, NSNAME);
506 		bp += NSNAME;
507 		break;
508 
509 	case D_FCONST:
510 		ieeedtod(&e, a->dval);
511 		l = e.l;
512 		bp[0] = l;
513 		bp[1] = l>>8;
514 		bp[2] = l>>16;
515 		bp[3] = l>>24;
516 		bp += 4;
517 		l = e.h;
518 		bp[0] = l;
519 		bp[1] = l>>8;
520 		bp[2] = l>>16;
521 		bp[3] = l>>24;
522 		bp += 4;
523 		break;
524 	}
525 	return bp;
526 }
527 
528 long
529 align(long i, Type *t, int op)
530 {
531 	long o;
532 	Type *v;
533 	int w;
534 
535 	o = i;
536 	w = 1;
537 	switch(op) {
538 	default:
539 		diag(Z, "unknown align opcode %d", op);
540 		break;
541 
542 	case Asu2:	/* padding at end of a struct */
543 		w = SZ_LONG;
544 		if(packflg)
545 			w = packflg;
546 		break;
547 
548 	case Ael1:	/* initial allign of struct element */
549 		for(v=t; v->etype==TARRAY; v=v->link)
550 			;
551 		w = ewidth[v->etype];
552 		if(w <= 0 || w >= SZ_LONG)
553 			w = SZ_LONG;
554 		if(packflg)
555 			w = packflg;
556 		break;
557 
558 	case Ael2:	/* width of a struct element */
559 		o += t->width;
560 		break;
561 
562 	case Aarg0:	/* initial passbyptr argument in arg list */
563 		if(typesuv[t->etype]) {
564 			o = align(o, types[TIND], Aarg1);
565 			o = align(o, types[TIND], Aarg2);
566 		}
567 		break;
568 
569 	case Aarg1:	/* initial allign of parameter */
570 		w = ewidth[t->etype];
571 		if(w <= 0 || w >= SZ_LONG) {
572 			w = SZ_LONG;
573 			break;
574 		}
575 		if(thechar == 'v')
576 			o += SZ_LONG - w;	/* big endian adjustment */
577 		w = 1;
578 		break;
579 
580 	case Aarg2:	/* width of a parameter */
581 		o += t->width;
582 		w = SZ_LONG;
583 		break;
584 
585 	case Aaut3:	/* total allign of automatic */
586 		o = align(o, t, Ael1);
587 		o = align(o, t, Ael2);
588 		break;
589 	}
590 	o = round(o, w);
591 	if(debug['A'])
592 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
593 	return o;
594 }
595 
596 long
597 maxround(long max, long v)
598 {
599 	v += SZ_LONG-1;
600 	if(v > max)
601 		max = round(v, SZ_LONG);
602 	return max;
603 }
604