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