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