xref: /plan9/sys/src/cmd/vc/swt.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier int
43e12c5d1SDavid du Colombier swcmp(void *a1, void *a2)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	C1 *p1, *p2;
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier 	p1 = a1;
93e12c5d1SDavid du Colombier 	p2 = a2;
103e12c5d1SDavid du Colombier 	if(p1->val < p2->val)
113e12c5d1SDavid du Colombier 		return -1;
123e12c5d1SDavid du Colombier 	return  p1->val > p2->val;
133e12c5d1SDavid du Colombier }
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier void
163e12c5d1SDavid du Colombier doswit(Node *n)
173e12c5d1SDavid du Colombier {
183e12c5d1SDavid du Colombier 	Case *c;
193e12c5d1SDavid du Colombier 	C1 *q, *iq;
203e12c5d1SDavid du Colombier 	long def, nc, i;
213e12c5d1SDavid du Colombier 	Node tn;
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier 	def = 0;
243e12c5d1SDavid du Colombier 	nc = 0;
253e12c5d1SDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
263e12c5d1SDavid du Colombier 		if(c->def) {
273e12c5d1SDavid du Colombier 			if(def)
283e12c5d1SDavid du Colombier 				diag(n, "more than one default in switch");
293e12c5d1SDavid du Colombier 			def = c->label;
303e12c5d1SDavid du Colombier 			continue;
313e12c5d1SDavid du Colombier 		}
323e12c5d1SDavid du Colombier 		nc++;
333e12c5d1SDavid du Colombier 	}
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier 	i = nc*sizeof(C1);
363e12c5d1SDavid du Colombier 	while(nhunk < i)
373e12c5d1SDavid du Colombier 		gethunk();
383e12c5d1SDavid du Colombier 	iq = (C1*)hunk;
393e12c5d1SDavid du Colombier 	nhunk -= i;
403e12c5d1SDavid du Colombier 	hunk += i;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	q = iq;
433e12c5d1SDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
443e12c5d1SDavid du Colombier 		if(c->def)
453e12c5d1SDavid du Colombier 			continue;
463e12c5d1SDavid du Colombier 		q->label = c->label;
473e12c5d1SDavid du Colombier 		q->val = c->val;
483e12c5d1SDavid du Colombier 		q++;
493e12c5d1SDavid du Colombier 	}
503e12c5d1SDavid du Colombier 	qsort(iq, nc, sizeof(C1), swcmp);
513e12c5d1SDavid du Colombier 	if(debug['W'])
523e12c5d1SDavid du Colombier 	for(i=0; i<nc; i++)
533e12c5d1SDavid du Colombier 		print("case %2d: = %.8lux\n", i, iq[i].val);
543e12c5d1SDavid du Colombier 	if(def == 0)
553e12c5d1SDavid du Colombier 		def = breakpc;
563e12c5d1SDavid du Colombier 	for(i=0; i<nc-1; i++)
573e12c5d1SDavid du Colombier 		if(iq[i].val == iq[i+1].val)
583e12c5d1SDavid du Colombier 			diag(n, "duplicate cases in switch %ld", iq[i].val);
593e12c5d1SDavid du Colombier 	regalloc(&tn, &regnode, Z);
603e12c5d1SDavid du Colombier 	swit1(iq, nc, def, n, &tn);
613e12c5d1SDavid du Colombier 	regfree(&tn);
623e12c5d1SDavid du Colombier }
633e12c5d1SDavid du Colombier 
643e12c5d1SDavid du Colombier void
653e12c5d1SDavid du Colombier swit1(C1 *q, int nc, long def, Node *n, Node *tn)
663e12c5d1SDavid du Colombier {
673e12c5d1SDavid du Colombier 	C1 *r;
683e12c5d1SDavid du Colombier 	int i;
693e12c5d1SDavid du Colombier 	Prog *sp;
703e12c5d1SDavid du Colombier 
713e12c5d1SDavid du Colombier 	if(nc < 5) {
723e12c5d1SDavid du Colombier 		for(i=0; i<nc; i++) {
733e12c5d1SDavid du Colombier 			if(debug['W'])
743e12c5d1SDavid du Colombier 				print("case = %.8lux\n", q->val);
753e12c5d1SDavid du Colombier 			gmove(nodconst(q->val), tn);
763e12c5d1SDavid du Colombier 			gopcode(OEQ, n, tn, Z);
773e12c5d1SDavid du Colombier 			patch(p, q->label);
783e12c5d1SDavid du Colombier 			q++;
793e12c5d1SDavid du Colombier 		}
803e12c5d1SDavid du Colombier 		gbranch(OGOTO);
813e12c5d1SDavid du Colombier 		patch(p, def);
823e12c5d1SDavid du Colombier 		return;
833e12c5d1SDavid du Colombier 	}
843e12c5d1SDavid du Colombier 	i = nc / 2;
853e12c5d1SDavid du Colombier 	r = q+i;
863e12c5d1SDavid du Colombier 	if(debug['W'])
873e12c5d1SDavid du Colombier 		print("case > %.8lux\n", r->val);
883e12c5d1SDavid du Colombier 	gmove(nodconst(r->val), tn);
893e12c5d1SDavid du Colombier 	gopcode(OLT, tn, n, Z);
903e12c5d1SDavid du Colombier 	sp = p;
913e12c5d1SDavid du Colombier 	gopcode(OEQ, n, tn, Z);
923e12c5d1SDavid du Colombier 	patch(p, r->label);
933e12c5d1SDavid du Colombier 	swit1(q, i, def, n, tn);
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	if(debug['W'])
963e12c5d1SDavid du Colombier 		print("case < %.8lux\n", r->val);
973e12c5d1SDavid du Colombier 	patch(sp, pc);
983e12c5d1SDavid du Colombier 	swit1(r+1, nc-i-1, def, n, tn);
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier void
1023e12c5d1SDavid du Colombier cas(void)
1033e12c5d1SDavid du Colombier {
1043e12c5d1SDavid du Colombier 	Case *c;
1053e12c5d1SDavid du Colombier 
1063e12c5d1SDavid du Colombier 	ALLOC(c, Case);
1073e12c5d1SDavid du Colombier 	c->link = cases;
1083e12c5d1SDavid du Colombier 	cases = c;
1093e12c5d1SDavid du Colombier }
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier void
1123e12c5d1SDavid du Colombier bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
1133e12c5d1SDavid du Colombier {
1143e12c5d1SDavid du Colombier 	int sh;
1153e12c5d1SDavid du Colombier 	long v;
1163e12c5d1SDavid du Colombier 	Node *l;
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier 	/*
1193e12c5d1SDavid du Colombier 	 * n1 gets adjusted/masked value
1203e12c5d1SDavid du Colombier 	 * n2 gets address of cell
1213e12c5d1SDavid du Colombier 	 * n3 gets contents of cell
1223e12c5d1SDavid du Colombier 	 */
1233e12c5d1SDavid du Colombier 	l = b->left;
1243e12c5d1SDavid du Colombier 	if(n2 != Z) {
1253e12c5d1SDavid du Colombier 		regalloc(n1, l, nn);
1263e12c5d1SDavid du Colombier 		reglcgen(n2, l, Z);
1273e12c5d1SDavid du Colombier 		regalloc(n3, l, Z);
1283e12c5d1SDavid du Colombier 		gopcode(OAS, n2, Z, n3);
1293e12c5d1SDavid du Colombier 		gopcode(OAS, n3, Z, n1);
1303e12c5d1SDavid du Colombier 	} else {
1313e12c5d1SDavid du Colombier 		regalloc(n1, l, nn);
1323e12c5d1SDavid du Colombier 		cgen(l, n1);
1333e12c5d1SDavid du Colombier 	}
1343e12c5d1SDavid du Colombier 	if(b->type->shift == 0 && typeu[b->type->etype]) {
1353e12c5d1SDavid du Colombier 		v = ~0 + (1L << b->type->nbits);
1363e12c5d1SDavid du Colombier 		gopcode(OAND, nodconst(v), Z, n1);
1373e12c5d1SDavid du Colombier 	} else {
1383e12c5d1SDavid du Colombier 		sh = 32 - b->type->shift - b->type->nbits;
1393e12c5d1SDavid du Colombier 		if(sh > 0)
1403e12c5d1SDavid du Colombier 			gopcode(OASHL, nodconst(sh), Z, n1);
1413e12c5d1SDavid du Colombier 		sh += b->type->shift;
1423e12c5d1SDavid du Colombier 		if(sh > 0)
1433e12c5d1SDavid du Colombier 			if(typeu[b->type->etype])
1443e12c5d1SDavid du Colombier 				gopcode(OLSHR, nodconst(sh), Z, n1);
1453e12c5d1SDavid du Colombier 			else
1463e12c5d1SDavid du Colombier 				gopcode(OASHR, nodconst(sh), Z, n1);
1473e12c5d1SDavid du Colombier 	}
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier 
1503e12c5d1SDavid du Colombier void
1513e12c5d1SDavid du Colombier bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
1523e12c5d1SDavid du Colombier {
1533e12c5d1SDavid du Colombier 	long v;
1543e12c5d1SDavid du Colombier 	Node nod, *l;
1553e12c5d1SDavid du Colombier 	int sh;
1563e12c5d1SDavid du Colombier 
1573e12c5d1SDavid du Colombier 	/*
1583e12c5d1SDavid du Colombier 	 * n1 has adjusted/masked value
1593e12c5d1SDavid du Colombier 	 * n2 has address of cell
1603e12c5d1SDavid du Colombier 	 * n3 has contents of cell
1613e12c5d1SDavid du Colombier 	 */
1623e12c5d1SDavid du Colombier 	l = b->left;
1633e12c5d1SDavid du Colombier 	regalloc(&nod, l, Z);
1643e12c5d1SDavid du Colombier 	v = ~0 + (1L << b->type->nbits);
1653e12c5d1SDavid du Colombier 	gopcode(OAND, nodconst(v), Z, n1);
1663e12c5d1SDavid du Colombier 	gopcode(OAS, n1, Z, &nod);
1673e12c5d1SDavid du Colombier 	if(nn != Z)
1683e12c5d1SDavid du Colombier 		gopcode(OAS, n1, Z, nn);
1693e12c5d1SDavid du Colombier 	sh = b->type->shift;
1703e12c5d1SDavid du Colombier 	if(sh > 0)
1713e12c5d1SDavid du Colombier 		gopcode(OASHL, nodconst(sh), Z, &nod);
1723e12c5d1SDavid du Colombier 	v <<= sh;
1733e12c5d1SDavid du Colombier 	gopcode(OAND, nodconst(~v), Z, n3);
1743e12c5d1SDavid du Colombier 	gopcode(OOR, n3, Z, &nod);
1753e12c5d1SDavid du Colombier 	gopcode(OAS, &nod, Z, n2);
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	regfree(&nod);
1783e12c5d1SDavid du Colombier 	regfree(n1);
1793e12c5d1SDavid du Colombier 	regfree(n2);
1803e12c5d1SDavid du Colombier 	regfree(n3);
1813e12c5d1SDavid du Colombier }
1823e12c5d1SDavid du Colombier 
1833e12c5d1SDavid du Colombier long
1843e12c5d1SDavid du Colombier outstring(char *s, long n)
1853e12c5d1SDavid du Colombier {
1863e12c5d1SDavid du Colombier 	long r;
1873e12c5d1SDavid du Colombier 
1883e12c5d1SDavid du Colombier 	r = nstring;
1893e12c5d1SDavid du Colombier 	while(n) {
1903e12c5d1SDavid du Colombier 		string[mnstring] = *s++;
1913e12c5d1SDavid du Colombier 		mnstring++;
1923e12c5d1SDavid du Colombier 		nstring++;
1933e12c5d1SDavid du Colombier 		if(mnstring >= NSNAME) {
1943e12c5d1SDavid du Colombier 			gpseudo(ADATA, symstring, nodconst(0L));
1953e12c5d1SDavid du Colombier 			p->from.offset += nstring - NSNAME;
1963e12c5d1SDavid du Colombier 			p->reg = NSNAME;
1973e12c5d1SDavid du Colombier 			p->to.type = D_SCONST;
1983e12c5d1SDavid du Colombier 			memmove(p->to.sval, string, NSNAME);
1993e12c5d1SDavid du Colombier 			mnstring = 0;
2003e12c5d1SDavid du Colombier 		}
2013e12c5d1SDavid du Colombier 		n--;
2023e12c5d1SDavid du Colombier 	}
2033e12c5d1SDavid du Colombier 	return r;
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier long
2073e12c5d1SDavid du Colombier outlstring(ushort *s, long n)
2083e12c5d1SDavid du Colombier {
2093e12c5d1SDavid du Colombier 	char buf[2];
2103e12c5d1SDavid du Colombier 	int c;
2113e12c5d1SDavid du Colombier 	long r;
2123e12c5d1SDavid du Colombier 
2133e12c5d1SDavid du Colombier 	while(nstring & 1)
2143e12c5d1SDavid du Colombier 		outstring("", 1);
2153e12c5d1SDavid du Colombier 	r = nstring;
2163e12c5d1SDavid du Colombier 	while(n > 0) {
2173e12c5d1SDavid du Colombier 		c = *s++;
2183e12c5d1SDavid du Colombier 		if(endian(0)) {
2193e12c5d1SDavid du Colombier 			buf[0] = c>>8;
2203e12c5d1SDavid du Colombier 			buf[1] = c;
2213e12c5d1SDavid du Colombier 		} else {
2223e12c5d1SDavid du Colombier 			buf[0] = c;
2233e12c5d1SDavid du Colombier 			buf[1] = c>>8;
2243e12c5d1SDavid du Colombier 		}
2253e12c5d1SDavid du Colombier 		outstring(buf, 2);
2263e12c5d1SDavid du Colombier 		n -= sizeof(ushort);
2273e12c5d1SDavid du Colombier 	}
2283e12c5d1SDavid du Colombier 	return r;
2293e12c5d1SDavid du Colombier }
2303e12c5d1SDavid du Colombier 
2313e12c5d1SDavid du Colombier int
2323e12c5d1SDavid du Colombier vlog(Node *n)
2333e12c5d1SDavid du Colombier {
234*219b2ee8SDavid du Colombier 	int s, i;
235*219b2ee8SDavid du Colombier 	ulong m, v;
2363e12c5d1SDavid du Colombier 
2373e12c5d1SDavid du Colombier 	if(n->op != OCONST)
2383e12c5d1SDavid du Colombier 		goto bad;
239*219b2ee8SDavid du Colombier 	if(typefd[n->type->etype])
2403e12c5d1SDavid du Colombier 		goto bad;
241*219b2ee8SDavid du Colombier 
242*219b2ee8SDavid du Colombier 	v = n->vconst;
243*219b2ee8SDavid du Colombier 
244*219b2ee8SDavid du Colombier 	s = 0;
245*219b2ee8SDavid du Colombier 	m = MASK(64);
246*219b2ee8SDavid du Colombier 	for(i=32; i; i>>=1) {
247*219b2ee8SDavid du Colombier 		m >>= i;
248*219b2ee8SDavid du Colombier 		if(!(v & m)) {
249*219b2ee8SDavid du Colombier 			v >>= i;
250*219b2ee8SDavid du Colombier 			s += i;
2513e12c5d1SDavid du Colombier 		}
2523e12c5d1SDavid du Colombier 	}
253*219b2ee8SDavid du Colombier 	if(v == 1)
254*219b2ee8SDavid du Colombier 		return s;
2553e12c5d1SDavid du Colombier 
2563e12c5d1SDavid du Colombier bad:
2573e12c5d1SDavid du Colombier 	return -1;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier 
260*219b2ee8SDavid du Colombier int
261*219b2ee8SDavid du Colombier mulcon(Node *n, Node *nn)
262*219b2ee8SDavid du Colombier {
263*219b2ee8SDavid du Colombier 	Node *l, *r, nod1, nod2;
264*219b2ee8SDavid du Colombier 	Multab *m;
265*219b2ee8SDavid du Colombier 	long v;
266*219b2ee8SDavid du Colombier 	int o;
267*219b2ee8SDavid du Colombier 	char code[sizeof(m->code)+2], *p;
268*219b2ee8SDavid du Colombier 
269*219b2ee8SDavid du Colombier 	if(typefd[n->type->etype])
270*219b2ee8SDavid du Colombier 		return 0;
271*219b2ee8SDavid du Colombier 	l = n->left;
272*219b2ee8SDavid du Colombier 	r = n->right;
273*219b2ee8SDavid du Colombier 	if(l->op == OCONST) {
274*219b2ee8SDavid du Colombier 		l = r;
275*219b2ee8SDavid du Colombier 		r = n->left;
276*219b2ee8SDavid du Colombier 	}
277*219b2ee8SDavid du Colombier 	if(r->op != OCONST)
278*219b2ee8SDavid du Colombier 		return 0;
279*219b2ee8SDavid du Colombier 	v = convvtox(r->vconst, n->type->etype);
280*219b2ee8SDavid du Colombier 	if(v != r->vconst) {
281*219b2ee8SDavid du Colombier 		if(debug['M'])
282*219b2ee8SDavid du Colombier 			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
283*219b2ee8SDavid du Colombier 		return 0;
284*219b2ee8SDavid du Colombier 	}
285*219b2ee8SDavid du Colombier 	m = mulcon0(v);
286*219b2ee8SDavid du Colombier 	if(!m) {
287*219b2ee8SDavid du Colombier 		if(debug['M'])
288*219b2ee8SDavid du Colombier 			print("%L multiply table: %lld\n", n->lineno, r->vconst);
289*219b2ee8SDavid du Colombier 		return 0;
290*219b2ee8SDavid du Colombier 	}
291*219b2ee8SDavid du Colombier 	if(debug['M'] && debug['v'])
292*219b2ee8SDavid du Colombier 		print("%L multiply: %ld\n", n->lineno, v);
293*219b2ee8SDavid du Colombier 
294*219b2ee8SDavid du Colombier 	memmove(code, m->code, sizeof(m->code));
295*219b2ee8SDavid du Colombier 	code[sizeof(m->code)] = 0;
296*219b2ee8SDavid du Colombier 
297*219b2ee8SDavid du Colombier 	p = code;
298*219b2ee8SDavid du Colombier 	if(p[1] == 'i')
299*219b2ee8SDavid du Colombier 		p += 2;
300*219b2ee8SDavid du Colombier 	regalloc(&nod1, n, nn);
301*219b2ee8SDavid du Colombier 	cgen(l, &nod1);
302*219b2ee8SDavid du Colombier 	if(v < 0)
303*219b2ee8SDavid du Colombier 		gopcode(OSUB, &nod1, nodconst(0), &nod1);
304*219b2ee8SDavid du Colombier 	regalloc(&nod2, n, Z);
305*219b2ee8SDavid du Colombier 
306*219b2ee8SDavid du Colombier loop:
307*219b2ee8SDavid du Colombier 	switch(*p) {
308*219b2ee8SDavid du Colombier 	case 0:
309*219b2ee8SDavid du Colombier 		regfree(&nod2);
310*219b2ee8SDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
311*219b2ee8SDavid du Colombier 		regfree(&nod1);
312*219b2ee8SDavid du Colombier 		return 1;
313*219b2ee8SDavid du Colombier 	case '+':
314*219b2ee8SDavid du Colombier 		o = OADD;
315*219b2ee8SDavid du Colombier 		goto addsub;
316*219b2ee8SDavid du Colombier 	case '-':
317*219b2ee8SDavid du Colombier 		o = OSUB;
318*219b2ee8SDavid du Colombier 	addsub:	/* number is r,n,l */
319*219b2ee8SDavid du Colombier 		v = p[1] - '0';
320*219b2ee8SDavid du Colombier 		r = &nod1;
321*219b2ee8SDavid du Colombier 		if(v&4)
322*219b2ee8SDavid du Colombier 			r = &nod2;
323*219b2ee8SDavid du Colombier 		n = &nod1;
324*219b2ee8SDavid du Colombier 		if(v&2)
325*219b2ee8SDavid du Colombier 			n = &nod2;
326*219b2ee8SDavid du Colombier 		l = &nod1;
327*219b2ee8SDavid du Colombier 		if(v&1)
328*219b2ee8SDavid du Colombier 			l = &nod2;
329*219b2ee8SDavid du Colombier 		gopcode(o, l, n, r);
330*219b2ee8SDavid du Colombier 		break;
331*219b2ee8SDavid du Colombier 	default: /* op is shiftcount, number is r,l */
332*219b2ee8SDavid du Colombier 		v = p[1] - '0';
333*219b2ee8SDavid du Colombier 		r = &nod1;
334*219b2ee8SDavid du Colombier 		if(v&2)
335*219b2ee8SDavid du Colombier 			r = &nod2;
336*219b2ee8SDavid du Colombier 		l = &nod1;
337*219b2ee8SDavid du Colombier 		if(v&1)
338*219b2ee8SDavid du Colombier 			l = &nod2;
339*219b2ee8SDavid du Colombier 		v = *p - 'a';
340*219b2ee8SDavid du Colombier 		if(v < 0 || v >= 32) {
341*219b2ee8SDavid du Colombier 			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
342*219b2ee8SDavid du Colombier 			break;
343*219b2ee8SDavid du Colombier 		}
344*219b2ee8SDavid du Colombier 		gopcode(OASHL, nodconst(v), l, r);
345*219b2ee8SDavid du Colombier 		break;
346*219b2ee8SDavid du Colombier 	}
347*219b2ee8SDavid du Colombier 	p += 2;
348*219b2ee8SDavid du Colombier 	goto loop;
349*219b2ee8SDavid du Colombier }
350*219b2ee8SDavid du Colombier 
3513e12c5d1SDavid du Colombier void
3523e12c5d1SDavid du Colombier nullwarn(Node *l, Node *r)
3533e12c5d1SDavid du Colombier {
3543e12c5d1SDavid du Colombier 	warn(Z, "result of operation not used");
3553e12c5d1SDavid du Colombier 	if(l != Z)
3563e12c5d1SDavid du Colombier 		cgen(l, Z);
3573e12c5d1SDavid du Colombier 	if(r != Z)
3583e12c5d1SDavid du Colombier 		cgen(r, Z);
3593e12c5d1SDavid du Colombier }
3603e12c5d1SDavid du Colombier 
3613e12c5d1SDavid du Colombier void
3623e12c5d1SDavid du Colombier sextern(Sym *s, Node *a, long o, long w)
3633e12c5d1SDavid du Colombier {
3643e12c5d1SDavid du Colombier 	long e, lw;
3653e12c5d1SDavid du Colombier 
3663e12c5d1SDavid du Colombier 	for(e=0; e<w; e+=NSNAME) {
3673e12c5d1SDavid du Colombier 		lw = NSNAME;
3683e12c5d1SDavid du Colombier 		if(w-e < lw)
3693e12c5d1SDavid du Colombier 			lw = w-e;
370*219b2ee8SDavid du Colombier 		gpseudo(ADATA, s, nodconst(0));
3713e12c5d1SDavid du Colombier 		p->from.offset += o+e;
3723e12c5d1SDavid du Colombier 		p->reg = lw;
3733e12c5d1SDavid du Colombier 		p->to.type = D_SCONST;
374*219b2ee8SDavid du Colombier 		memmove(p->to.sval, a->cstring+e, lw);
3753e12c5d1SDavid du Colombier 	}
3763e12c5d1SDavid du Colombier }
3773e12c5d1SDavid du Colombier 
3783e12c5d1SDavid du Colombier void
3793e12c5d1SDavid du Colombier gextern(Sym *s, Node *a, long o, long w)
3803e12c5d1SDavid du Colombier {
381*219b2ee8SDavid du Colombier 
382*219b2ee8SDavid du Colombier 	if(a->op == OCONST && typev[a->type->etype]) {
383*219b2ee8SDavid du Colombier 		gpseudo(ADATA, s, nod32const(a->vconst>>32));
384*219b2ee8SDavid du Colombier 		p->from.offset += o;
385*219b2ee8SDavid du Colombier 		p->reg = 4;
386*219b2ee8SDavid du Colombier 		gpseudo(ADATA, s, nod32const(a->vconst));
387*219b2ee8SDavid du Colombier 		p->from.offset += o + 4;
388*219b2ee8SDavid du Colombier 		p->reg = 4;
389*219b2ee8SDavid du Colombier 		return;
390*219b2ee8SDavid du Colombier 	}
3913e12c5d1SDavid du Colombier 	gpseudo(ADATA, s, a);
3923e12c5d1SDavid du Colombier 	p->from.offset += o;
3933e12c5d1SDavid du Colombier 	p->reg = w;
3943e12c5d1SDavid du Colombier 	if(p->to.type == D_OREG)
3953e12c5d1SDavid du Colombier 		p->to.type = D_CONST;
3963e12c5d1SDavid du Colombier }
3973e12c5d1SDavid du Colombier 
3983e12c5d1SDavid du Colombier void	zname(Biobuf*, char*, int, int);
3993e12c5d1SDavid du Colombier char*	zaddr(char*, Adr*, int);
4003e12c5d1SDavid du Colombier void	zwrite(Biobuf*, Prog*, int, int);
4013e12c5d1SDavid du Colombier void	outhist(Biobuf*);
4023e12c5d1SDavid du Colombier 
4033e12c5d1SDavid du Colombier void
4043e12c5d1SDavid du Colombier zwrite(Biobuf *b, Prog *p, int sf, int st)
4053e12c5d1SDavid du Colombier {
4063e12c5d1SDavid du Colombier 	char bf[100], *bp;
4073e12c5d1SDavid du Colombier 
4083e12c5d1SDavid du Colombier 	bf[0] = p->as;
4093e12c5d1SDavid du Colombier 	bf[1] = p->reg;
4103e12c5d1SDavid du Colombier 	bf[2] = p->lineno;
4113e12c5d1SDavid du Colombier 	bf[3] = p->lineno>>8;
4123e12c5d1SDavid du Colombier 	bf[4] = p->lineno>>16;
4133e12c5d1SDavid du Colombier 	bf[5] = p->lineno>>24;
4143e12c5d1SDavid du Colombier 	bp = zaddr(bf+6, &p->from, sf);
4153e12c5d1SDavid du Colombier 	bp = zaddr(bp, &p->to, st);
4163e12c5d1SDavid du Colombier 	Bwrite(b, bf, bp-bf);
4173e12c5d1SDavid du Colombier }
4183e12c5d1SDavid du Colombier 
4193e12c5d1SDavid du Colombier void
4203e12c5d1SDavid du Colombier outcode(void)
4213e12c5d1SDavid du Colombier {
4223e12c5d1SDavid du Colombier 	struct { Sym *sym; short type; } h[NSYM];
4233e12c5d1SDavid du Colombier 	Prog *p;
4243e12c5d1SDavid du Colombier 	Sym *s;
425*219b2ee8SDavid du Colombier 	int sf, st, t, sym;
4263e12c5d1SDavid du Colombier 
4273e12c5d1SDavid du Colombier 	if(debug['S']) {
4283e12c5d1SDavid du Colombier 		for(p = firstp; p != P; p = p->link)
4293e12c5d1SDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
4303e12c5d1SDavid du Colombier 				pc--;
4313e12c5d1SDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
4323e12c5d1SDavid du Colombier 			print("%P\n", p);
4333e12c5d1SDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
4343e12c5d1SDavid du Colombier 				pc++;
4353e12c5d1SDavid du Colombier 		}
4363e12c5d1SDavid du Colombier 	}
437*219b2ee8SDavid du Colombier 	outhist(&outbuf);
4383e12c5d1SDavid du Colombier 	for(sym=0; sym<NSYM; sym++) {
4393e12c5d1SDavid du Colombier 		h[sym].sym = S;
4403e12c5d1SDavid du Colombier 		h[sym].type = 0;
4413e12c5d1SDavid du Colombier 	}
4423e12c5d1SDavid du Colombier 	sym = 1;
4433e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
4443e12c5d1SDavid du Colombier 	jackpot:
4453e12c5d1SDavid du Colombier 		sf = 0;
4463e12c5d1SDavid du Colombier 		s = p->from.sym;
4473e12c5d1SDavid du Colombier 		while(s != S) {
4483e12c5d1SDavid du Colombier 			sf = s->sym;
4493e12c5d1SDavid du Colombier 			if(sf < 0 || sf >= NSYM)
4503e12c5d1SDavid du Colombier 				sf = 0;
4513e12c5d1SDavid du Colombier 			t = p->from.name;
4523e12c5d1SDavid du Colombier 			if(h[sf].type == t)
4533e12c5d1SDavid du Colombier 			if(h[sf].sym == s)
4543e12c5d1SDavid du Colombier 				break;
455*219b2ee8SDavid du Colombier 			zname(&outbuf, s->name, t, sym);
4563e12c5d1SDavid du Colombier 			s->sym = sym;
4573e12c5d1SDavid du Colombier 			h[sym].sym = s;
4583e12c5d1SDavid du Colombier 			h[sym].type = t;
4593e12c5d1SDavid du Colombier 			sf = sym;
4603e12c5d1SDavid du Colombier 			sym++;
4613e12c5d1SDavid du Colombier 			if(sym >= NSYM)
4623e12c5d1SDavid du Colombier 				sym = 1;
4633e12c5d1SDavid du Colombier 			break;
4643e12c5d1SDavid du Colombier 		}
4653e12c5d1SDavid du Colombier 		st = 0;
4663e12c5d1SDavid du Colombier 		s = p->to.sym;
4673e12c5d1SDavid du Colombier 		while(s != S) {
4683e12c5d1SDavid du Colombier 			st = s->sym;
4693e12c5d1SDavid du Colombier 			if(st < 0 || st >= NSYM)
4703e12c5d1SDavid du Colombier 				st = 0;
4713e12c5d1SDavid du Colombier 			t = p->to.name;
4723e12c5d1SDavid du Colombier 			if(h[st].type == t)
4733e12c5d1SDavid du Colombier 			if(h[st].sym == s)
4743e12c5d1SDavid du Colombier 				break;
475*219b2ee8SDavid du Colombier 			zname(&outbuf, s->name, t, sym);
4763e12c5d1SDavid du Colombier 			s->sym = sym;
4773e12c5d1SDavid du Colombier 			h[sym].sym = s;
4783e12c5d1SDavid du Colombier 			h[sym].type = t;
4793e12c5d1SDavid du Colombier 			st = sym;
4803e12c5d1SDavid du Colombier 			sym++;
4813e12c5d1SDavid du Colombier 			if(sym >= NSYM)
4823e12c5d1SDavid du Colombier 				sym = 1;
4833e12c5d1SDavid du Colombier 			if(st == sf)
4843e12c5d1SDavid du Colombier 				goto jackpot;
4853e12c5d1SDavid du Colombier 			break;
4863e12c5d1SDavid du Colombier 		}
487*219b2ee8SDavid du Colombier 		zwrite(&outbuf, p, sf, st);
4883e12c5d1SDavid du Colombier 	}
4893e12c5d1SDavid du Colombier 	firstp = P;
4903e12c5d1SDavid du Colombier 	lastp = P;
4913e12c5d1SDavid du Colombier }
4923e12c5d1SDavid du Colombier 
4933e12c5d1SDavid du Colombier void
4943e12c5d1SDavid du Colombier outhist(Biobuf *b)
4953e12c5d1SDavid du Colombier {
4963e12c5d1SDavid du Colombier 	Hist *h;
497*219b2ee8SDavid du Colombier 	char *p, *q, *op;
4983e12c5d1SDavid du Colombier 	Prog pg;
4993e12c5d1SDavid du Colombier 	int n;
5003e12c5d1SDavid du Colombier 
5013e12c5d1SDavid du Colombier 	pg = zprog;
5023e12c5d1SDavid du Colombier 	pg.as = AHISTORY;
5033e12c5d1SDavid du Colombier 	for(h = hist; h != H; h = h->link) {
5043e12c5d1SDavid du Colombier 		p = h->name;
505*219b2ee8SDavid du Colombier 		op = 0;
506*219b2ee8SDavid du Colombier 		if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
507*219b2ee8SDavid du Colombier 			op = p;
508*219b2ee8SDavid du Colombier 			p = pathname;
509*219b2ee8SDavid du Colombier 		}
5103e12c5d1SDavid du Colombier 		while(p) {
5113e12c5d1SDavid du Colombier 			q = utfrune(p, '/');
5123e12c5d1SDavid du Colombier 			if(q) {
5133e12c5d1SDavid du Colombier 				n = q-p;
5143e12c5d1SDavid du Colombier 				if(n == 0)
5153e12c5d1SDavid du Colombier 					n = 1;	/* leading "/" */
5163e12c5d1SDavid du Colombier 				q++;
5173e12c5d1SDavid du Colombier 			} else {
5183e12c5d1SDavid du Colombier 				n = strlen(p);
5193e12c5d1SDavid du Colombier 				q = 0;
5203e12c5d1SDavid du Colombier 			}
5213e12c5d1SDavid du Colombier 			if(n) {
522*219b2ee8SDavid du Colombier 				Bputc(b, ANAME);
523*219b2ee8SDavid du Colombier 				Bputc(b, D_FILE);
524*219b2ee8SDavid du Colombier 				Bputc(b, 1);
525*219b2ee8SDavid du Colombier 				Bputc(b, '<');
526*219b2ee8SDavid du Colombier 				Bwrite(b, p, n);
527*219b2ee8SDavid du Colombier 				Bputc(b, 0);
5283e12c5d1SDavid du Colombier 			}
5293e12c5d1SDavid du Colombier 			p = q;
530*219b2ee8SDavid du Colombier 			if(p == 0 && op) {
531*219b2ee8SDavid du Colombier 				p = op;
532*219b2ee8SDavid du Colombier 				op = 0;
533*219b2ee8SDavid du Colombier 			}
5343e12c5d1SDavid du Colombier 		}
5353e12c5d1SDavid du Colombier 		pg.lineno = h->line;
5363e12c5d1SDavid du Colombier 		pg.to.type = zprog.to.type;
5373e12c5d1SDavid du Colombier 		pg.to.offset = h->offset;
5383e12c5d1SDavid du Colombier 		if(h->offset)
5393e12c5d1SDavid du Colombier 			pg.to.type = D_CONST;
5403e12c5d1SDavid du Colombier 
5413e12c5d1SDavid du Colombier 		zwrite(b, &pg, 0, 0);
5423e12c5d1SDavid du Colombier 	}
5433e12c5d1SDavid du Colombier }
5443e12c5d1SDavid du Colombier 
5453e12c5d1SDavid du Colombier void
5463e12c5d1SDavid du Colombier zname(Biobuf *b, char *n, int t, int s)
5473e12c5d1SDavid du Colombier {
548*219b2ee8SDavid du Colombier 	char bf[3];
5493e12c5d1SDavid du Colombier 
550*219b2ee8SDavid du Colombier 	bf[0] = ANAME;
551*219b2ee8SDavid du Colombier 	bf[1] = t;	/* type */
552*219b2ee8SDavid du Colombier 	bf[2] = s;	/* sym */
553*219b2ee8SDavid du Colombier 	Bwrite(b, bf, 3);
554*219b2ee8SDavid du Colombier 	Bwrite(b, n, strlen(n)+1);
5553e12c5d1SDavid du Colombier }
5563e12c5d1SDavid du Colombier 
5573e12c5d1SDavid du Colombier char*
5583e12c5d1SDavid du Colombier zaddr(char *bp, Adr *a, int s)
5593e12c5d1SDavid du Colombier {
5603e12c5d1SDavid du Colombier 	long l;
5613e12c5d1SDavid du Colombier 	Ieee e;
5623e12c5d1SDavid du Colombier 
5633e12c5d1SDavid du Colombier 	bp[0] = a->type;
5643e12c5d1SDavid du Colombier 	bp[1] = a->reg;
5653e12c5d1SDavid du Colombier 	bp[2] = s;
5663e12c5d1SDavid du Colombier 	bp[3] = a->name;
5673e12c5d1SDavid du Colombier 	bp += 4;
5683e12c5d1SDavid du Colombier 	switch(a->type) {
5693e12c5d1SDavid du Colombier 	default:
5703e12c5d1SDavid du Colombier 		diag(Z, "unknown type %d in zaddr", a->type);
5713e12c5d1SDavid du Colombier 
5723e12c5d1SDavid du Colombier 	case D_NONE:
5733e12c5d1SDavid du Colombier 	case D_REG:
5743e12c5d1SDavid du Colombier 	case D_FREG:
5753e12c5d1SDavid du Colombier 	case D_MREG:
5763e12c5d1SDavid du Colombier 	case D_FCREG:
5773e12c5d1SDavid du Colombier 	case D_LO:
5783e12c5d1SDavid du Colombier 	case D_HI:
5793e12c5d1SDavid du Colombier 		break;
5803e12c5d1SDavid du Colombier 
5813e12c5d1SDavid du Colombier 	case D_OREG:
5823e12c5d1SDavid du Colombier 	case D_CONST:
5833e12c5d1SDavid du Colombier 	case D_BRANCH:
5843e12c5d1SDavid du Colombier 		l = a->offset;
5853e12c5d1SDavid du Colombier 		bp[0] = l;
5863e12c5d1SDavid du Colombier 		bp[1] = l>>8;
5873e12c5d1SDavid du Colombier 		bp[2] = l>>16;
5883e12c5d1SDavid du Colombier 		bp[3] = l>>24;
5893e12c5d1SDavid du Colombier 		bp += 4;
5903e12c5d1SDavid du Colombier 		break;
5913e12c5d1SDavid du Colombier 
5923e12c5d1SDavid du Colombier 	case D_SCONST:
5933e12c5d1SDavid du Colombier 		memmove(bp, a->sval, NSNAME);
5943e12c5d1SDavid du Colombier 		bp += NSNAME;
5953e12c5d1SDavid du Colombier 		break;
5963e12c5d1SDavid du Colombier 
5973e12c5d1SDavid du Colombier 	case D_FCONST:
5983e12c5d1SDavid du Colombier 		ieeedtod(&e, a->dval);
5993e12c5d1SDavid du Colombier 		l = e.l;
6003e12c5d1SDavid du Colombier 		bp[0] = l;
6013e12c5d1SDavid du Colombier 		bp[1] = l>>8;
6023e12c5d1SDavid du Colombier 		bp[2] = l>>16;
6033e12c5d1SDavid du Colombier 		bp[3] = l>>24;
6043e12c5d1SDavid du Colombier 		bp += 4;
6053e12c5d1SDavid du Colombier 		l = e.h;
6063e12c5d1SDavid du Colombier 		bp[0] = l;
6073e12c5d1SDavid du Colombier 		bp[1] = l>>8;
6083e12c5d1SDavid du Colombier 		bp[2] = l>>16;
6093e12c5d1SDavid du Colombier 		bp[3] = l>>24;
6103e12c5d1SDavid du Colombier 		bp += 4;
6113e12c5d1SDavid du Colombier 		break;
6123e12c5d1SDavid du Colombier 	}
6133e12c5d1SDavid du Colombier 	return bp;
6143e12c5d1SDavid du Colombier }
6153e12c5d1SDavid du Colombier 
6163e12c5d1SDavid du Colombier void
6173e12c5d1SDavid du Colombier ieeedtod(Ieee *ieee, double native)
6183e12c5d1SDavid du Colombier {
6193e12c5d1SDavid du Colombier 	double fr, ho, f;
6203e12c5d1SDavid du Colombier 	int exp;
6213e12c5d1SDavid du Colombier 
6223e12c5d1SDavid du Colombier 	if(native < 0) {
6233e12c5d1SDavid du Colombier 		ieeedtod(ieee, -native);
6243e12c5d1SDavid du Colombier 		ieee->h |= 0x80000000L;
6253e12c5d1SDavid du Colombier 		return;
6263e12c5d1SDavid du Colombier 	}
6273e12c5d1SDavid du Colombier 	if(native == 0) {
6283e12c5d1SDavid du Colombier 		ieee->l = 0;
6293e12c5d1SDavid du Colombier 		ieee->h = 0;
6303e12c5d1SDavid du Colombier 		return;
6313e12c5d1SDavid du Colombier 	}
6323e12c5d1SDavid du Colombier 	fr = frexp(native, &exp);
6333e12c5d1SDavid du Colombier 	f = 2097152L;		/* shouldnt use fp constants here */
6343e12c5d1SDavid du Colombier 	fr = modf(fr*f, &ho);
6353e12c5d1SDavid du Colombier 	ieee->h = ho;
6363e12c5d1SDavid du Colombier 	ieee->h &= 0xfffffL;
6373e12c5d1SDavid du Colombier 	ieee->h |= (exp+1022L) << 20;
6383e12c5d1SDavid du Colombier 	f = 65536L;
6393e12c5d1SDavid du Colombier 	fr = modf(fr*f, &ho);
6403e12c5d1SDavid du Colombier 	ieee->l = ho;
6413e12c5d1SDavid du Colombier 	ieee->l <<= 16;
6423e12c5d1SDavid du Colombier 	ieee->l |= (long)(fr*f);
6433e12c5d1SDavid du Colombier }
6443e12c5d1SDavid du Colombier 
6453e12c5d1SDavid du Colombier int
6463e12c5d1SDavid du Colombier endian(int w)
6473e12c5d1SDavid du Colombier {
6483e12c5d1SDavid du Colombier 
6493e12c5d1SDavid du Colombier 	return tint->width - w;
6503e12c5d1SDavid du Colombier }
651*219b2ee8SDavid du Colombier 
652*219b2ee8SDavid du Colombier int
653*219b2ee8SDavid du Colombier passbypointer(int et)
654*219b2ee8SDavid du Colombier {
655*219b2ee8SDavid du Colombier 
656*219b2ee8SDavid du Colombier 	return typesuv[et];
657*219b2ee8SDavid du Colombier }
658*219b2ee8SDavid du Colombier 
659*219b2ee8SDavid du Colombier int
660*219b2ee8SDavid du Colombier argalign(long typewidth, long offset, int offsp)
661*219b2ee8SDavid du Colombier {
662*219b2ee8SDavid du Colombier 	USED(typewidth,offset,offsp);
663*219b2ee8SDavid du Colombier 	return 0;
664*219b2ee8SDavid du Colombier }
665