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