xref: /inferno-os/utils/8c/swt.c (revision 9dbf735d35c339c90deaed43fc0ae17f16c122f7)
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['K'])
13 				print("case = %.8llux\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['K'])
25 		print("case > %.8llux\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['K'])
34 		print("case < %.8llux\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 gextern(Sym *s, Node *a, long o, long w)
132 {
133 	if(a->op == OCONST && typev[a->type->etype]) {
134 		gpseudo(ADATA, s, lo64(a));
135 		p->from.offset += o;
136 		p->from.scale = 4;
137 		gpseudo(ADATA, s, hi64(a));
138 		p->from.offset += o + 4;
139 		p->from.scale = 4;
140 		return;
141 	}
142 	gpseudo(ADATA, s, a);
143 	p->from.offset += o;
144 	p->from.scale = w;
145 	switch(p->to.type) {
146 	default:
147 		p->to.index = p->to.type;
148 		p->to.type = D_ADDR;
149 	case D_CONST:
150 	case D_FCONST:
151 	case D_ADDR:
152 		break;
153 	}
154 }
155 
156 void	zname(Biobuf*, Sym*, int);
157 void	zaddr(Biobuf*, Adr*, int);
158 void	outhist(Biobuf*);
159 
160 void
161 outcode(void)
162 {
163 	struct { Sym *sym; short type; } h[NSYM];
164 	Prog *p;
165 	Sym *s;
166 	int f, sf, st, t, sym;
167 	Biobuf b;
168 
169 	if(debug['S']) {
170 		for(p = firstp; p != P; p = p->link)
171 			if(p->as != ADATA && p->as != AGLOBL)
172 				pc--;
173 		for(p = firstp; p != P; p = p->link) {
174 			print("%P\n", p);
175 			if(p->as != ADATA && p->as != AGLOBL)
176 				pc++;
177 		}
178 	}
179 	f = open(outfile, OWRITE);
180 	if(f < 0) {
181 		diag(Z, "cannot open %s", outfile);
182 		return;
183 	}
184 	Binit(&b, f, OWRITE);
185 	Bseek(&b, 0L, 2);
186 	outhist(&b);
187 	for(sym=0; sym<NSYM; sym++) {
188 		h[sym].sym = S;
189 		h[sym].type = 0;
190 	}
191 	sym = 1;
192 	for(p = firstp; p != P; p = p->link) {
193 	jackpot:
194 		sf = 0;
195 		s = p->from.sym;
196 		while(s != S) {
197 			sf = s->sym;
198 			if(sf < 0 || sf >= NSYM)
199 				sf = 0;
200 			t = p->from.type;
201 			if(t == D_ADDR)
202 				t = p->from.index;
203 			if(h[sf].type == t)
204 			if(h[sf].sym == s)
205 				break;
206 			s->sym = sym;
207 			zname(&b, s, t);
208 			h[sym].sym = s;
209 			h[sym].type = t;
210 			sf = sym;
211 			sym++;
212 			if(sym >= NSYM)
213 				sym = 1;
214 			break;
215 		}
216 		st = 0;
217 		s = p->to.sym;
218 		while(s != S) {
219 			st = s->sym;
220 			if(st < 0 || st >= NSYM)
221 				st = 0;
222 			t = p->to.type;
223 			if(t == D_ADDR)
224 				t = p->to.index;
225 			if(h[st].type == t)
226 			if(h[st].sym == s)
227 				break;
228 			s->sym = sym;
229 			zname(&b, s, t);
230 			h[sym].sym = s;
231 			h[sym].type = t;
232 			st = sym;
233 			sym++;
234 			if(sym >= NSYM)
235 				sym = 1;
236 			if(st == sf)
237 				goto jackpot;
238 			break;
239 		}
240 		Bputc(&b, p->as);
241 		Bputc(&b, p->as>>8);
242 		Bputc(&b, p->lineno);
243 		Bputc(&b, p->lineno>>8);
244 		Bputc(&b, p->lineno>>16);
245 		Bputc(&b, p->lineno>>24);
246 		zaddr(&b, &p->from, sf);
247 		zaddr(&b, &p->to, st);
248 	}
249 	Bflush(&b);
250 	close(f);
251 	firstp = P;
252 	lastp = P;
253 }
254 
255 void
256 outhist(Biobuf *b)
257 {
258 	Hist *h;
259 	char *p, *q, *op, c;
260 	Prog pg;
261 	int n;
262 
263 	pg = zprog;
264 	pg.as = AHISTORY;
265 	c = pathchar();
266 	for(h = hist; h != H; h = h->link) {
267 		p = h->name;
268 		op = 0;
269 		/* on windows skip drive specifier in pathname */
270 		if(systemtype(Windows) && p && p[1] == ':'){
271 			p += 2;
272 			c = *p;
273 		}
274 		if(p && p[0] != c && h->offset == 0 && pathname){
275 			/* on windows skip drive specifier in pathname */
276 			if(systemtype(Windows) && pathname[1] == ':') {
277 				op = p;
278 				p = pathname+2;
279 				c = *p;
280 			} else if(pathname[0] == c){
281 				op = p;
282 				p = pathname;
283 			}
284 		}
285 		while(p) {
286 			q = utfrune(p, c);
287 			if(q) {
288 				n = q-p;
289 				if(n == 0){
290 					n = 1;	/* leading "/" */
291 					*p = '/';	/* don't emit "\" on windows */
292 				}
293 				q++;
294 			} else {
295 				n = strlen(p);
296 				q = 0;
297 			}
298 			if(n) {
299 				Bputc(b, ANAME);
300 				Bputc(b, ANAME>>8);
301 				Bputc(b, D_FILE);
302 				Bputc(b, 1);
303 				Bputc(b, '<');
304 				Bwrite(b, p, n);
305 				Bputc(b, 0);
306 			}
307 			p = q;
308 			if(p == 0 && op) {
309 				p = op;
310 				op = 0;
311 			}
312 		}
313 		pg.lineno = h->line;
314 		pg.to.type = zprog.to.type;
315 		pg.to.offset = h->offset;
316 		if(h->offset)
317 			pg.to.type = D_CONST;
318 
319 		Bputc(b, pg.as);
320 		Bputc(b, pg.as>>8);
321 		Bputc(b, pg.lineno);
322 		Bputc(b, pg.lineno>>8);
323 		Bputc(b, pg.lineno>>16);
324 		Bputc(b, pg.lineno>>24);
325 		zaddr(b, &pg.from, 0);
326 		zaddr(b, &pg.to, 0);
327 	}
328 }
329 
330 void
331 zname(Biobuf *b, Sym *s, int t)
332 {
333 	char *n;
334 	ulong sig;
335 
336 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
337 		sig = sign(s);
338 		Bputc(b, ASIGNAME);
339 		Bputc(b, ASIGNAME>>8);
340 		Bputc(b, sig);
341 		Bputc(b, sig>>8);
342 		Bputc(b, sig>>16);
343 		Bputc(b, sig>>24);
344 		s->sig = SIGDONE;
345 	}
346 	else{
347 		Bputc(b, ANAME);	/* as */
348 		Bputc(b, ANAME>>8);	/* as */
349 	}
350 	Bputc(b, t);			/* type */
351 	Bputc(b, s->sym);		/* sym */
352 	n = s->name;
353 	while(*n) {
354 		Bputc(b, *n);
355 		n++;
356 	}
357 	Bputc(b, 0);
358 }
359 
360 void
361 zaddr(Biobuf *b, Adr *a, int s)
362 {
363 	long l;
364 	int i, t;
365 	char *n;
366 	Ieee e;
367 
368 	t = 0;
369 	if(a->index != D_NONE || a->scale != 0)
370 		t |= T_INDEX;
371 	if(s != 0)
372 		t |= T_SYM;
373 
374 	switch(a->type) {
375 	default:
376 		t |= T_TYPE;
377 	case D_NONE:
378 		if(a->offset != 0)
379 			t |= T_OFFSET;
380 		break;
381 	case D_FCONST:
382 		t |= T_FCONST;
383 		break;
384 	case D_SCONST:
385 		t |= T_SCONST;
386 		break;
387 	}
388 	Bputc(b, t);
389 
390 	if(t & T_INDEX) {	/* implies index, scale */
391 		Bputc(b, a->index);
392 		Bputc(b, a->scale);
393 	}
394 	if(t & T_OFFSET) {	/* implies offset */
395 		l = a->offset;
396 		Bputc(b, l);
397 		Bputc(b, l>>8);
398 		Bputc(b, l>>16);
399 		Bputc(b, l>>24);
400 	}
401 	if(t & T_SYM)		/* implies sym */
402 		Bputc(b, s);
403 	if(t & T_FCONST) {
404 		ieeedtod(&e, a->dval);
405 		l = e.l;
406 		Bputc(b, l);
407 		Bputc(b, l>>8);
408 		Bputc(b, l>>16);
409 		Bputc(b, l>>24);
410 		l = e.h;
411 		Bputc(b, l);
412 		Bputc(b, l>>8);
413 		Bputc(b, l>>16);
414 		Bputc(b, l>>24);
415 		return;
416 	}
417 	if(t & T_SCONST) {
418 		n = a->sval;
419 		for(i=0; i<NSNAME; i++) {
420 			Bputc(b, *n);
421 			n++;
422 		}
423 		return;
424 	}
425 	if(t & T_TYPE)
426 		Bputc(b, a->type);
427 }
428 
429 long
430 align(long i, Type *t, int op)
431 {
432 	long o;
433 	Type *v;
434 	int w;
435 
436 	o = i;
437 	w = 1;
438 	switch(op) {
439 	default:
440 		diag(Z, "unknown align opcode %d", op);
441 		break;
442 
443 	case Asu2:	/* padding at end of a struct */
444 		w = SZ_LONG;
445 		if(packflg)
446 			w = packflg;
447 		break;
448 
449 	case Ael1:	/* initial allign of struct element */
450 		for(v=t; v->etype==TARRAY; v=v->link)
451 			;
452 		w = ewidth[v->etype];
453 		if(w <= 0 || w >= SZ_LONG)
454 			w = SZ_LONG;
455 		if(packflg)
456 			w = packflg;
457 		break;
458 
459 	case Ael2:	/* width of a struct element */
460 		o += t->width;
461 		break;
462 
463 	case Aarg0:	/* initial passbyptr argument in arg list */
464 		if(typesuv[t->etype]) {
465 			o = align(o, types[TIND], Aarg1);
466 			o = align(o, types[TIND], Aarg2);
467 		}
468 		break;
469 
470 	case Aarg1:	/* initial allign of parameter */
471 		w = ewidth[t->etype];
472 		if(w <= 0 || w >= SZ_LONG) {
473 			w = SZ_LONG;
474 			break;
475 		}
476 		w = 1;		/* little endian no adjustment */
477 		break;
478 
479 	case Aarg2:	/* width of a parameter */
480 		o += t->width;
481 		w = SZ_LONG;
482 		break;
483 
484 	case Aaut3:	/* total allign of automatic */
485 		o = align(o, t, Ael1);
486 		o = align(o, t, Ael2);
487 		break;
488 	}
489 	o = round(o, w);
490 	if(debug['A'])
491 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
492 	return o;
493 }
494 
495 long
496 maxround(long max, long v)
497 {
498 	v = round(v, SZ_LONG);
499 	if(v > max)
500 		return v;
501 	return max;
502 }
503