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