xref: /plan9-contrib/sys/src/cmd/8c/swt.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "gc.h"
2 
3 int
4 swcmp(void *a1, void *a2)
5 {
6 	C1 *p1, *p2;
7 
8 	p1 = a1;
9 	p2 = a2;
10 	if(p1->val < p2->val)
11 		return -1;
12 	return  p1->val > p2->val;
13 }
14 
15 void
16 doswit(Node *n)
17 {
18 	Case *c;
19 	C1 *q, *iq;
20 	long def, nc, i;
21 
22 	def = 0;
23 	nc = 0;
24 	for(c = cases; c->link != C; c = c->link) {
25 		if(c->def) {
26 			if(def)
27 				diag(n, "more than one default in switch");
28 			def = c->label;
29 			continue;
30 		}
31 		nc++;
32 	}
33 
34 	i = nc*sizeof(C1);
35 	while(nhunk < i)
36 		gethunk();
37 	iq = (C1*)hunk;
38 	nhunk -= i;
39 	hunk += i;
40 
41 	q = iq;
42 	for(c = cases; c->link != C; c = c->link) {
43 		if(c->def)
44 			continue;
45 		q->label = c->label;
46 		q->val = c->val;
47 		q++;
48 	}
49 	qsort(iq, nc, sizeof(C1), swcmp);
50 	if(debug['W'])
51 	for(i=0; i<nc; i++)
52 		print("case %2d: = %.8lux\n", i, iq[i].val);
53 	if(def == 0)
54 		def = breakpc;
55 	for(i=0; i<nc-1; i++)
56 		if(iq[i].val == iq[i+1].val)
57 			diag(n, "duplicate cases in switch %ld", iq[i].val);
58 	swit1(iq, nc, def, n);
59 }
60 
61 void
62 swit1(C1 *q, int nc, long def, Node *n)
63 {
64 	C1 *r;
65 	int i;
66 	Prog *sp;
67 
68 	if(nc < 5) {
69 		for(i=0; i<nc; i++) {
70 			if(debug['W'])
71 				print("case = %.8lux\n", q->val);
72 			gopcode(OEQ, n->type, n, nodconst(q->val));
73 			patch(p, q->label);
74 			q++;
75 		}
76 		gbranch(OGOTO);
77 		patch(p, def);
78 		return;
79 	}
80 	i = nc / 2;
81 	r = q+i;
82 	if(debug['W'])
83 		print("case > %.8lux\n", r->val);
84 	gopcode(OGT, n->type, n, nodconst(r->val));
85 	sp = p;
86 	gbranch(OGOTO);
87 	p->as = AJEQ;
88 	patch(p, r->label);
89 	swit1(q, i, def, n);
90 
91 	if(debug['W'])
92 		print("case < %.8lux\n", r->val);
93 	patch(sp, pc);
94 	swit1(r+1, nc-i-1, def, n);
95 }
96 
97 void
98 cas(void)
99 {
100 	Case *c;
101 
102 	ALLOC(c, Case);
103 	c->link = cases;
104 	cases = c;
105 }
106 
107 void
108 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
109 {
110 	int sh;
111 	long v;
112 	Node *l;
113 
114 	/*
115 	 * n1 gets adjusted/masked value
116 	 * n2 gets address of cell
117 	 * n3 gets contents of cell
118 	 */
119 	l = b->left;
120 	if(n2 != Z) {
121 		regalloc(n1, l, nn);
122 		reglcgen(n2, l, Z);
123 		regalloc(n3, l, Z);
124 		gmove(n2, n3);
125 		gmove(n3, n1);
126 	} else {
127 		regalloc(n1, l, nn);
128 		cgen(l, n1);
129 	}
130 	if(b->type->shift == 0 && typeu[b->type->etype]) {
131 		v = ~0 + (1L << b->type->nbits);
132 		gopcode(OAND, types[TLONG], nodconst(v), n1);
133 	} else {
134 		sh = 32 - b->type->shift - b->type->nbits;
135 		if(sh > 0)
136 			gopcode(OASHL, types[TLONG], nodconst(sh), n1);
137 		sh += b->type->shift;
138 		if(sh > 0)
139 			if(typeu[b->type->etype])
140 				gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
141 			else
142 				gopcode(OASHR, types[TLONG], nodconst(sh), n1);
143 	}
144 }
145 
146 void
147 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
148 {
149 	long v;
150 	Node nod;
151 	int sh;
152 
153 	regalloc(&nod, b->left, Z);
154 	v = ~0 + (1L << b->type->nbits);
155 	gopcode(OAND, types[TLONG], nodconst(v), n1);
156 	gmove(n1, &nod);
157 	if(nn != Z)
158 		gmove(n1, nn);
159 	sh = b->type->shift;
160 	if(sh > 0)
161 		gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
162 	v <<= sh;
163 	gopcode(OAND, types[TLONG], nodconst(~v), n3);
164 	gopcode(OOR, types[TLONG], n3, &nod);
165 	gmove(&nod, n2);
166 
167 	regfree(&nod);
168 	regfree(n1);
169 	regfree(n2);
170 	regfree(n3);
171 }
172 
173 long
174 outstring(char *s, long n)
175 {
176 	long r;
177 
178 	r = nstring;
179 	while(n) {
180 		string[mnstring] = *s++;
181 		mnstring++;
182 		nstring++;
183 		if(mnstring >= NSNAME) {
184 			gpseudo(ADATA, symstring, nodconst(0L));
185 			p->from.offset += nstring - NSNAME;
186 			p->from.scale = NSNAME;
187 			p->to.type = D_SCONST;
188 			memmove(p->to.sval, string, NSNAME);
189 			mnstring = 0;
190 		}
191 		n--;
192 	}
193 	return r;
194 }
195 
196 long
197 outlstring(ushort *s, long n)
198 {
199 	char buf[2];
200 	int c;
201 	long r;
202 
203 	while(nstring & 1)
204 		outstring("", 1);
205 	r = nstring;
206 	while(n > 0) {
207 		c = *s++;
208 		if(endian(0)) {
209 			buf[0] = c>>8;
210 			buf[1] = c;
211 		} else {
212 			buf[0] = c;
213 			buf[1] = c>>8;
214 		}
215 		outstring(buf, 2);
216 		n -= sizeof(ushort);
217 	}
218 	return r;
219 }
220 
221 int
222 vlog(Node *n)
223 {
224 
225 	int s, i;
226 	ulong m, v;
227 
228 	if(n->op != OCONST)
229 		goto bad;
230 	if(!typechlp[n->type->etype])
231 		goto bad;
232 
233 	v = n->vconst;
234 
235 	s = 0;
236 	m = MASK(64);
237 	for(i=32; i; i>>=1) {
238 		m >>= i;
239 		if(!(v & m)) {
240 			v >>= i;
241 			s += i;
242 		}
243 	}
244 	if(v == 1)
245 		return s;
246 
247 bad:
248 	return -1;
249 }
250 
251 void
252 nullwarn(Node *l, Node *r)
253 {
254 	warn(Z, "result of operation not used");
255 	if(l != Z)
256 		cgen(l, Z);
257 	if(r != Z)
258 		cgen(r, Z);
259 }
260 
261 void
262 sextern(Sym *s, Node *a, long o, long w)
263 {
264 	long e, lw;
265 
266 	for(e=0; e<w; e+=NSNAME) {
267 		lw = NSNAME;
268 		if(w-e < lw)
269 			lw = w-e;
270 		gpseudo(ADATA, s, nodconst(0L));
271 		p->from.offset += o+e;
272 		p->from.scale = lw;
273 		p->to.type = D_SCONST;
274 		memmove(p->to.sval, a->cstring+e, lw);
275 	}
276 }
277 
278 void
279 gextern(Sym *s, Node *a, long o, long w)
280 {
281 	if(a->op == OCONST && typev[a->type->etype]) {
282 		gpseudo(ADATA, s, nodconst((long)(a->vconst>>32)));
283 		p->from.offset += o;
284 		p->from.scale = 4;
285 		gpseudo(ADATA, s, nodconst((long)(a->vconst)));
286 		p->from.offset += o + 4;
287 		p->from.scale = 4;
288 		return;
289 	}
290 	gpseudo(ADATA, s, a);
291 	p->from.offset += o;
292 	p->from.scale = w;
293 	switch(p->to.type) {
294 	default:
295 		p->to.index = p->to.type;
296 		p->to.type = D_ADDR;
297 	case D_CONST:
298 	case D_FCONST:
299 	case D_ADDR:
300 		break;
301 	}
302 }
303 
304 void	zname(Biobuf*, char*, int, int);
305 void	zaddr(Biobuf*, Adr*, int);
306 void	outhist(Biobuf*);
307 
308 void
309 outcode(void)
310 {
311 	struct { Sym *sym; short type; } h[NSYM];
312 	Prog *p;
313 	Sym *s;
314 	int f, sf, st, t, sym;
315 	Biobuf b;
316 
317 	if(debug['S']) {
318 		for(p = firstp; p != P; p = p->link)
319 			if(p->as != ADATA && p->as != AGLOBL)
320 				pc--;
321 		for(p = firstp; p != P; p = p->link) {
322 			print("%P\n", p);
323 			if(p->as != ADATA && p->as != AGLOBL)
324 				pc++;
325 		}
326 	}
327 	f = open(outfile, OWRITE);
328 	if(f < 0) {
329 		diag(Z, "cannot open %s", outfile);
330 		return;
331 	}
332 	Binit(&b, f, OWRITE);
333 	Bseek(&b, 0L, 2);
334 	outhist(&b);
335 	for(sym=0; sym<NSYM; sym++) {
336 		h[sym].sym = S;
337 		h[sym].type = 0;
338 	}
339 	sym = 1;
340 	for(p = firstp; p != P; p = p->link) {
341 	jackpot:
342 		sf = 0;
343 		s = p->from.sym;
344 		while(s != S) {
345 			sf = s->sym;
346 			if(sf < 0 || sf >= NSYM)
347 				sf = 0;
348 			t = p->from.type;
349 			if(t == D_ADDR)
350 				t = p->from.index;
351 			if(h[sf].type == t)
352 			if(h[sf].sym == s)
353 				break;
354 			zname(&b, s->name, t, sym);
355 			s->sym = sym;
356 			h[sym].sym = s;
357 			h[sym].type = t;
358 			sf = sym;
359 			sym++;
360 			if(sym >= NSYM)
361 				sym = 1;
362 			break;
363 		}
364 		st = 0;
365 		s = p->to.sym;
366 		while(s != S) {
367 			st = s->sym;
368 			if(st < 0 || st >= NSYM)
369 				st = 0;
370 			t = p->to.type;
371 			if(t == D_ADDR)
372 				t = p->to.index;
373 			if(h[st].type == t)
374 			if(h[st].sym == s)
375 				break;
376 			zname(&b, s->name, t, sym);
377 			s->sym = sym;
378 			h[sym].sym = s;
379 			h[sym].type = t;
380 			st = sym;
381 			sym++;
382 			if(sym >= NSYM)
383 				sym = 1;
384 			if(st == sf)
385 				goto jackpot;
386 			break;
387 		}
388 		Bputc(&b, p->as);
389 		Bputc(&b, p->as>>8);
390 		Bputc(&b, p->lineno);
391 		Bputc(&b, p->lineno>>8);
392 		Bputc(&b, p->lineno>>16);
393 		Bputc(&b, p->lineno>>24);
394 		zaddr(&b, &p->from, sf);
395 		zaddr(&b, &p->to, st);
396 	}
397 	Bflush(&b);
398 	close(f);
399 	firstp = P;
400 	lastp = P;
401 }
402 
403 
404 
405 void
406 outhist(Biobuf *b)
407 {
408 	Hist *h;
409 	char *p, *q, *op;
410 	Prog pg;
411 	int n;
412 
413 	pg = zprog;
414 	pg.as = AHISTORY;
415 	for(h = hist; h != H; h = h->link) {
416 		p = h->name;
417 		op = 0;
418 		if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
419 			op = p;
420 			p = pathname;
421 		}
422 		while(p) {
423 			q = utfrune(p, '/');
424 			if(q) {
425 				n = q-p;
426 				if(n == 0)
427 					n = 1;	/* leading "/" */
428 				q++;
429 			} else {
430 				n = strlen(p);
431 				q = 0;
432 			}
433 			if(n) {
434 				Bputc(b, ANAME);
435 				Bputc(b, ANAME>>8);
436 				Bputc(b, D_FILE);
437 				Bputc(b, 1);
438 				Bputc(b, '<');
439 				Bwrite(b, p, n);
440 				Bputc(b, 0);
441 			}
442 			p = q;
443 			if(p == 0 && op) {
444 				p = op;
445 				op = 0;
446 			}
447 		}
448 		pg.lineno = h->line;
449 		pg.to.type = zprog.to.type;
450 		pg.to.offset = h->offset;
451 		if(h->offset)
452 			pg.to.type = D_CONST;
453 
454 		Bputc(b, pg.as);
455 		Bputc(b, pg.as>>8);
456 		Bputc(b, pg.lineno);
457 		Bputc(b, pg.lineno>>8);
458 		Bputc(b, pg.lineno>>16);
459 		Bputc(b, pg.lineno>>24);
460 		zaddr(b, &pg.from, 0);
461 		zaddr(b, &pg.to, 0);
462 	}
463 }
464 
465 void
466 zname(Biobuf *b, char *n, int t, int s)
467 {
468 
469 	Bputc(b, ANAME);	/* as */
470 	Bputc(b, ANAME>>8);	/* as */
471 	Bputc(b, t);		/* type */
472 	Bputc(b, s);		/* sym */
473 	while(*n) {
474 		Bputc(b, *n);
475 		n++;
476 	}
477 	Bputc(b, 0);
478 }
479 
480 void
481 zaddr(Biobuf *b, Adr *a, int s)
482 {
483 	long l;
484 	int i, t;
485 	char *n;
486 	Ieee e;
487 
488 	t = 0;
489 	if(a->index != D_NONE || a->scale != 0)
490 		t |= T_INDEX;
491 	if(s != 0)
492 		t |= T_SYM;
493 
494 	switch(a->type) {
495 	default:
496 		t |= T_TYPE;
497 	case D_NONE:
498 		if(a->offset != 0)
499 			t |= T_OFFSET;
500 		break;
501 	case D_FCONST:
502 		t |= T_FCONST;
503 		break;
504 	case D_SCONST:
505 		t |= T_SCONST;
506 		break;
507 	}
508 	Bputc(b, t);
509 
510 	if(t & T_INDEX) {	/* implies index, scale */
511 		Bputc(b, a->index);
512 		Bputc(b, a->scale);
513 	}
514 	if(t & T_OFFSET) {	/* implies offset */
515 		l = a->offset;
516 		Bputc(b, l);
517 		Bputc(b, l>>8);
518 		Bputc(b, l>>16);
519 		Bputc(b, l>>24);
520 	}
521 	if(t & T_SYM)		/* implies sym */
522 		Bputc(b, s);
523 	if(t & T_FCONST) {
524 		ieeedtod(&e, a->dval);
525 		l = e.l;
526 		Bputc(b, l);
527 		Bputc(b, l>>8);
528 		Bputc(b, l>>16);
529 		Bputc(b, l>>24);
530 		l = e.h;
531 		Bputc(b, l);
532 		Bputc(b, l>>8);
533 		Bputc(b, l>>16);
534 		Bputc(b, l>>24);
535 		return;
536 	}
537 	if(t & T_SCONST) {
538 		n = a->sval;
539 		for(i=0; i<NSNAME; i++) {
540 			Bputc(b, *n);
541 			n++;
542 		}
543 		return;
544 	}
545 	if(t & T_TYPE)
546 		Bputc(b, a->type);
547 }
548 
549 void
550 ieeedtod(Ieee *ieee, double native)
551 {
552 	double fr, ho, f;
553 	int exp;
554 
555 	if(native < 0) {
556 		ieeedtod(ieee, -native);
557 		ieee->h |= 0x80000000L;
558 		return;
559 	}
560 	if(native == 0) {
561 		ieee->l = 0;
562 		ieee->h = 0;
563 		return;
564 	}
565 	fr = frexp(native, &exp);
566 	f = 2097152L;		/* shouldnt use fp constants here */
567 	fr = modf(fr*f, &ho);
568 	ieee->h = ho;
569 	ieee->h &= 0xfffffL;
570 	ieee->h |= (exp+1022L) << 20;
571 	f = 65536L;
572 	fr = modf(fr*f, &ho);
573 	ieee->l = ho;
574 	ieee->l <<= 16;
575 	ieee->l |= (long)(fr*f);
576 }
577 
578 char*	xonames[] =
579 {
580 	"INDEX",
581 	"XEND",
582 };
583 
584 char*
585 xOconv(int a)
586 {
587 	if(a <= OEND || a > OXEND)
588 		return "**badO**";
589 	return xonames[a-OEND-1];
590 }
591 
592 int
593 endian(int w)
594 {
595 
596 	USED(w);
597 	return 0;
598 }
599 
600 int
601 passbypointer(int et)
602 {
603 
604 	return typesuv[et];
605 }
606 
607 int
608 argalign(long typewidth, long offset, int offsp)
609 {
610 	USED(typewidth,offset,offsp);
611 	return 0;
612 }
613