xref: /inferno-os/utils/6c/swt.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
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 			gcmp(OEQ, n, 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 	gcmp(OGT, n, 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, tfield, nodconst(v), n1);
65 	} else {
66 		sh = 32 - b->type->shift - b->type->nbits;
67 		if(sh > 0)
68 			gopcode(OASHL, tfield, nodconst(sh), n1);
69 		sh += b->type->shift;
70 		if(sh > 0)
71 			if(typeu[b->type->etype])
72 				gopcode(OLSHR, tfield, nodconst(sh), n1);
73 			else
74 				gopcode(OASHR, tfield, 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(0 && 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 			l = a->offset;
381 			if((vlong)l != a->offset)
382 				t |= T_64;
383 		}
384 		break;
385 	case D_FCONST:
386 		t |= T_FCONST;
387 		break;
388 	case D_SCONST:
389 		t |= T_SCONST;
390 		break;
391 	}
392 	Bputc(b, t);
393 
394 	if(t & T_INDEX) {	/* implies index, scale */
395 		Bputc(b, a->index);
396 		Bputc(b, a->scale);
397 	}
398 	if(t & T_OFFSET) {	/* implies offset */
399 		l = a->offset;
400 		Bputc(b, l);
401 		Bputc(b, l>>8);
402 		Bputc(b, l>>16);
403 		Bputc(b, l>>24);
404 		if(t & T_64) {
405 			l = a->offset>>32;
406 			Bputc(b, l);
407 			Bputc(b, l>>8);
408 			Bputc(b, l>>16);
409 			Bputc(b, l>>24);
410 		}
411 	}
412 	if(t & T_SYM)		/* implies sym */
413 		Bputc(b, s);
414 	if(t & T_FCONST) {
415 		ieeedtod(&e, a->dval);
416 		l = e.l;
417 		Bputc(b, l);
418 		Bputc(b, l>>8);
419 		Bputc(b, l>>16);
420 		Bputc(b, l>>24);
421 		l = e.h;
422 		Bputc(b, l);
423 		Bputc(b, l>>8);
424 		Bputc(b, l>>16);
425 		Bputc(b, l>>24);
426 		return;
427 	}
428 	if(t & T_SCONST) {
429 		n = a->sval;
430 		for(i=0; i<NSNAME; i++) {
431 			Bputc(b, *n);
432 			n++;
433 		}
434 		return;
435 	}
436 	if(t & T_TYPE)
437 		Bputc(b, a->type);
438 }
439 
440 long
441 align(long i, Type *t, int op)
442 {
443 	long o;
444 	Type *v;
445 	int w;
446 
447 	o = i;
448 	w = 1;
449 	switch(op) {
450 	default:
451 		diag(Z, "unknown align opcode %d", op);
452 		break;
453 
454 	case Asu2:	/* padding at end of a struct */
455 		w = SZ_VLONG;
456 		if(packflg)
457 			w = packflg;
458 		break;
459 
460 	case Ael1:	/* initial align of struct element */
461 		for(v=t; v->etype==TARRAY; v=v->link)
462 			;
463 		w = ewidth[v->etype];
464 		if(w <= 0 || w >= SZ_VLONG)
465 			w = SZ_VLONG;
466 		if(packflg)
467 			w = packflg;
468 		break;
469 
470 	case Ael2:	/* width of a struct element */
471 		o += t->width;
472 		break;
473 
474 	case Aarg0:	/* initial passbyptr argument in arg list */
475 		if(typesu[t->etype]) {
476 			o = align(o, types[TIND], Aarg1);
477 			o = align(o, types[TIND], Aarg2);
478 		}
479 		break;
480 
481 	case Aarg1:	/* initial align of parameter */
482 		w = ewidth[t->etype];
483 		if(w <= 0 || w >= SZ_VLONG) {
484 			w = SZ_VLONG;
485 			break;
486 		}
487 		w = 1;		/* little endian no adjustment */
488 		break;
489 
490 	case Aarg2:	/* width of a parameter */
491 		o += t->width;
492 		w = SZ_VLONG;
493 		break;
494 
495 	case Aaut3:	/* total allign of automatic */
496 		o = align(o, t, Ael1);
497 		o = align(o, t, Ael2);
498 		break;
499 	}
500 	o = round(o, w);
501 	if(debug['A'])
502 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
503 	return o;
504 }
505 
506 long
507 maxround(long max, long v)
508 {
509 	v = round(v, SZ_VLONG);
510 	if(v > max)
511 		return v;
512 	return max;
513 }
514