xref: /inferno-os/utils/vc/swt.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
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