xref: /plan9/sys/src/cmd/kc/swt.c (revision 178702b161d3fe3e021aa6cb2f305be898e56ca0)
13e12c5d1SDavid du Colombier #include "gc.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier void
swit1(C1 * q,int nc,long def,Node * n)44ac975e2SDavid du Colombier swit1(C1 *q, int nc, long def, Node *n)
53e12c5d1SDavid du Colombier {
63e12c5d1SDavid du Colombier 	Node tn;
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier 	regalloc(&tn, &regnode, Z);
94ac975e2SDavid du Colombier 	swit2(q, nc, def, n, &tn);
103e12c5d1SDavid du Colombier 	regfree(&tn);
113e12c5d1SDavid du Colombier }
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier void
swit2(C1 * q,int nc,long def,Node * n,Node * tn)144ac975e2SDavid du Colombier swit2(C1 *q, int nc, long def, Node *n, Node *tn)
153e12c5d1SDavid du Colombier {
163e12c5d1SDavid du Colombier 	C1 *r;
173e12c5d1SDavid du Colombier 	int i;
183e12c5d1SDavid du Colombier 	Prog *sp;
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	if(nc < 5) {
213e12c5d1SDavid du Colombier 		for(i=0; i<nc; i++) {
223e12c5d1SDavid du Colombier 			if(sval(q->val)) {
233e12c5d1SDavid du Colombier 				gopcode(OEQ, n, Z, nodconst(q->val));
243e12c5d1SDavid du Colombier 			} else {
253e12c5d1SDavid du Colombier 				gopcode(OSUB, nodconst(q->val), n, tn);
263e12c5d1SDavid du Colombier 				gopcode(OEQ, tn, Z, nodconst(0));
273e12c5d1SDavid du Colombier 			}
283e12c5d1SDavid du Colombier 			patch(p, q->label);
293e12c5d1SDavid du Colombier 			q++;
303e12c5d1SDavid du Colombier 		}
313e12c5d1SDavid du Colombier 		gbranch(OGOTO);
323e12c5d1SDavid du Colombier 		patch(p, def);
333e12c5d1SDavid du Colombier 		return;
343e12c5d1SDavid du Colombier 	}
353e12c5d1SDavid du Colombier 	i = nc / 2;
363e12c5d1SDavid du Colombier 	r = q+i;
373e12c5d1SDavid du Colombier 	if(sval(r->val)) {
383e12c5d1SDavid du Colombier 		gopcode(OGT, n, Z, nodconst(r->val));
393e12c5d1SDavid du Colombier 		sp = p;
403e12c5d1SDavid du Colombier 	} else {
413e12c5d1SDavid du Colombier 		gopcode(OSUB, nodconst(r->val), n, tn);
423e12c5d1SDavid du Colombier 		gopcode(OGT, tn, Z, nodconst(0));
433e12c5d1SDavid du Colombier 		sp = p;
443e12c5d1SDavid du Colombier 	}
453e12c5d1SDavid du Colombier 	gbranch(OGOTO);
463e12c5d1SDavid du Colombier 	p->as = ABE;
473e12c5d1SDavid du Colombier 	patch(p, r->label);
484ac975e2SDavid du Colombier 	swit2(q, i, def, n, tn);
493e12c5d1SDavid du Colombier 
503e12c5d1SDavid du Colombier 	patch(sp, pc);
514ac975e2SDavid du Colombier 	swit2(r+1, nc-i-1, def, n, tn);
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier void
bitload(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)553e12c5d1SDavid du Colombier bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
563e12c5d1SDavid du Colombier {
573e12c5d1SDavid du Colombier 	int sh;
583e12c5d1SDavid du Colombier 	long v;
593e12c5d1SDavid du Colombier 	Node *l;
603e12c5d1SDavid du Colombier 
613e12c5d1SDavid du Colombier 	/*
623e12c5d1SDavid du Colombier 	 * n1 gets adjusted/masked value
633e12c5d1SDavid du Colombier 	 * n2 gets address of cell
643e12c5d1SDavid du Colombier 	 * n3 gets contents of cell
653e12c5d1SDavid du Colombier 	 */
663e12c5d1SDavid du Colombier 	l = b->left;
673e12c5d1SDavid du Colombier 	if(n2 != Z) {
683e12c5d1SDavid du Colombier 		regalloc(n1, l, nn);
693e12c5d1SDavid du Colombier 		reglcgen(n2, l, Z);
703e12c5d1SDavid du Colombier 		regalloc(n3, l, Z);
713e12c5d1SDavid du Colombier 		gopcode(OAS, n2, Z, n3);
723e12c5d1SDavid du Colombier 		gopcode(OAS, n3, Z, n1);
733e12c5d1SDavid du Colombier 	} else {
743e12c5d1SDavid du Colombier 		regalloc(n1, l, nn);
753e12c5d1SDavid du Colombier 		cgen(l, n1);
763e12c5d1SDavid du Colombier 	}
773e12c5d1SDavid du Colombier 	if(b->type->shift == 0 && typeu[b->type->etype]) {
783e12c5d1SDavid du Colombier 		v = ~0 + (1L << b->type->nbits);
793e12c5d1SDavid du Colombier 		gopcode(OAND, nodconst(v), Z, n1);
803e12c5d1SDavid du Colombier 	} else {
813e12c5d1SDavid du Colombier 		sh = 32 - b->type->shift - b->type->nbits;
823e12c5d1SDavid du Colombier 		if(sh > 0)
833e12c5d1SDavid du Colombier 			gopcode(OASHL, nodconst(sh), Z, n1);
843e12c5d1SDavid du Colombier 		sh += b->type->shift;
853e12c5d1SDavid du Colombier 		if(sh > 0)
863e12c5d1SDavid du Colombier 			if(typeu[b->type->etype])
873e12c5d1SDavid du Colombier 				gopcode(OLSHR, nodconst(sh), Z, n1);
883e12c5d1SDavid du Colombier 			else
893e12c5d1SDavid du Colombier 				gopcode(OASHR, nodconst(sh), Z, n1);
903e12c5d1SDavid du Colombier 	}
913e12c5d1SDavid du Colombier }
923e12c5d1SDavid du Colombier 
933e12c5d1SDavid du Colombier void
bitstore(Node * b,Node * n1,Node * n2,Node * n3,Node * nn)943e12c5d1SDavid du Colombier bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
953e12c5d1SDavid du Colombier {
963e12c5d1SDavid du Colombier 	long v;
973e12c5d1SDavid du Colombier 	Node nod, *l;
983e12c5d1SDavid du Colombier 	int sh;
993e12c5d1SDavid du Colombier 
1003e12c5d1SDavid du Colombier 	/*
1013e12c5d1SDavid du Colombier 	 * n1 has adjusted/masked value
1023e12c5d1SDavid du Colombier 	 * n2 has address of cell
1033e12c5d1SDavid du Colombier 	 * n3 has contents of cell
1043e12c5d1SDavid du Colombier 	 */
1053e12c5d1SDavid du Colombier 	l = b->left;
1063e12c5d1SDavid du Colombier 	regalloc(&nod, l, Z);
1073e12c5d1SDavid du Colombier 	v = ~0 + (1L << b->type->nbits);
1083e12c5d1SDavid du Colombier 	gopcode(OAND, nodconst(v), Z, n1);
1093e12c5d1SDavid du Colombier 	gopcode(OAS, n1, Z, &nod);
1103e12c5d1SDavid du Colombier 	if(nn != Z)
1113e12c5d1SDavid du Colombier 		gopcode(OAS, n1, Z, nn);
1123e12c5d1SDavid du Colombier 	sh = b->type->shift;
1133e12c5d1SDavid du Colombier 	if(sh > 0)
1143e12c5d1SDavid du Colombier 		gopcode(OASHL, nodconst(sh), Z, &nod);
1153e12c5d1SDavid du Colombier 	v <<= sh;
1163e12c5d1SDavid du Colombier 	gopcode(OAND, nodconst(~v), Z, n3);
1173e12c5d1SDavid du Colombier 	gopcode(OOR, n3, Z, &nod);
1183e12c5d1SDavid du Colombier 	gopcode(OAS, &nod, Z, n2);
1193e12c5d1SDavid du Colombier 
1203e12c5d1SDavid du Colombier 	regfree(&nod);
1213e12c5d1SDavid du Colombier 	regfree(n1);
1223e12c5d1SDavid du Colombier 	regfree(n2);
1233e12c5d1SDavid du Colombier 	regfree(n3);
1243e12c5d1SDavid du Colombier }
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier long
outstring(char * s,long n)1273e12c5d1SDavid du Colombier outstring(char *s, long n)
1283e12c5d1SDavid du Colombier {
1293e12c5d1SDavid du Colombier 	long r;
1303e12c5d1SDavid du Colombier 
1313e12c5d1SDavid du Colombier 	r = nstring;
1323e12c5d1SDavid du Colombier 	while(n) {
1333e12c5d1SDavid du Colombier 		string[mnstring] = *s++;
1343e12c5d1SDavid du Colombier 		mnstring++;
1353e12c5d1SDavid du Colombier 		nstring++;
1363e12c5d1SDavid du Colombier 		if(mnstring >= NSNAME) {
1373e12c5d1SDavid du Colombier 			gpseudo(ADATA, symstring, nodconst(0L));
1383e12c5d1SDavid du Colombier 			p->from.offset += nstring - NSNAME;
1393e12c5d1SDavid du Colombier 			p->reg = NSNAME;
1403e12c5d1SDavid du Colombier 			p->to.type = D_SCONST;
1413e12c5d1SDavid du Colombier 			memmove(p->to.sval, string, NSNAME);
1423e12c5d1SDavid du Colombier 			mnstring = 0;
1433e12c5d1SDavid du Colombier 		}
1443e12c5d1SDavid du Colombier 		n--;
1453e12c5d1SDavid du Colombier 	}
1463e12c5d1SDavid du Colombier 	return r;
1473e12c5d1SDavid du Colombier }
1483e12c5d1SDavid du Colombier 
1493e12c5d1SDavid du Colombier int
mulcon(Node * n,Node * nn)1503e12c5d1SDavid du Colombier mulcon(Node *n, Node *nn)
1513e12c5d1SDavid du Colombier {
1523e12c5d1SDavid du Colombier 	Node *l, *r, nod1, nod2;
1533e12c5d1SDavid du Colombier 	Multab *m;
1543e12c5d1SDavid du Colombier 	long v;
1553e12c5d1SDavid du Colombier 	int o;
1563e12c5d1SDavid du Colombier 	char code[sizeof(m->code)+2], *p;
1573e12c5d1SDavid du Colombier 
158219b2ee8SDavid du Colombier 	if(typefd[n->type->etype])
1593e12c5d1SDavid du Colombier 		return 0;
1603e12c5d1SDavid du Colombier 	l = n->left;
1613e12c5d1SDavid du Colombier 	r = n->right;
1623e12c5d1SDavid du Colombier 	if(l->op == OCONST) {
1633e12c5d1SDavid du Colombier 		l = r;
1643e12c5d1SDavid du Colombier 		r = n->left;
1653e12c5d1SDavid du Colombier 	}
1663e12c5d1SDavid du Colombier 	if(r->op != OCONST)
1673e12c5d1SDavid du Colombier 		return 0;
168219b2ee8SDavid du Colombier 	v = convvtox(r->vconst, n->type->etype);
169219b2ee8SDavid du Colombier 	if(v != r->vconst) {
170219b2ee8SDavid du Colombier 		if(debug['M'])
171219b2ee8SDavid du Colombier 			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
1723e12c5d1SDavid du Colombier 		return 0;
173219b2ee8SDavid du Colombier 	}
174219b2ee8SDavid du Colombier 	m = mulcon0(n, v);
175219b2ee8SDavid du Colombier 	if(!m) {
176219b2ee8SDavid du Colombier 		if(debug['M'])
177219b2ee8SDavid du Colombier 			print("%L multiply table: %lld\n", n->lineno, r->vconst);
178219b2ee8SDavid du Colombier 		return 0;
179219b2ee8SDavid du Colombier 	}
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier 	memmove(code, m->code, sizeof(m->code));
1823e12c5d1SDavid du Colombier 	code[sizeof(m->code)] = 0;
1833e12c5d1SDavid du Colombier 
1843e12c5d1SDavid du Colombier 	p = code;
1853e12c5d1SDavid du Colombier 	if(p[1] == 'i')
1863e12c5d1SDavid du Colombier 		p += 2;
1873e12c5d1SDavid du Colombier 	regalloc(&nod1, n, nn);
1883e12c5d1SDavid du Colombier 	cgen(l, &nod1);
1893e12c5d1SDavid du Colombier 	if(v < 0)
1903e12c5d1SDavid du Colombier 		gopcode(OSUB, &nod1, nodconst(0), &nod1);
1913e12c5d1SDavid du Colombier 	regalloc(&nod2, n, Z);
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier loop:
1943e12c5d1SDavid du Colombier 	switch(*p) {
1953e12c5d1SDavid du Colombier 	case 0:
1963e12c5d1SDavid du Colombier 		regfree(&nod2);
1973e12c5d1SDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
1983e12c5d1SDavid du Colombier 		regfree(&nod1);
1993e12c5d1SDavid du Colombier 		return 1;
2003e12c5d1SDavid du Colombier 	case '+':
2013e12c5d1SDavid du Colombier 		o = OADD;
2023e12c5d1SDavid du Colombier 		goto addsub;
2033e12c5d1SDavid du Colombier 	case '-':
2043e12c5d1SDavid du Colombier 		o = OSUB;
2053e12c5d1SDavid du Colombier 	addsub:	/* number is r,n,l */
2063e12c5d1SDavid du Colombier 		v = p[1] - '0';
2073e12c5d1SDavid du Colombier 		r = &nod1;
2083e12c5d1SDavid du Colombier 		if(v&4)
2093e12c5d1SDavid du Colombier 			r = &nod2;
2103e12c5d1SDavid du Colombier 		n = &nod1;
2113e12c5d1SDavid du Colombier 		if(v&2)
2123e12c5d1SDavid du Colombier 			n = &nod2;
2133e12c5d1SDavid du Colombier 		l = &nod1;
2143e12c5d1SDavid du Colombier 		if(v&1)
2153e12c5d1SDavid du Colombier 			l = &nod2;
2163e12c5d1SDavid du Colombier 		gopcode(o, l, n, r);
2173e12c5d1SDavid du Colombier 		break;
2183e12c5d1SDavid du Colombier 	default: /* op is shiftcount, number is r,l */
2193e12c5d1SDavid du Colombier 		v = p[1] - '0';
2203e12c5d1SDavid du Colombier 		r = &nod1;
2213e12c5d1SDavid du Colombier 		if(v&2)
2223e12c5d1SDavid du Colombier 			r = &nod2;
2233e12c5d1SDavid du Colombier 		l = &nod1;
2243e12c5d1SDavid du Colombier 		if(v&1)
2253e12c5d1SDavid du Colombier 			l = &nod2;
2263e12c5d1SDavid du Colombier 		v = *p - 'a';
2273e12c5d1SDavid du Colombier 		if(v < 0 || v >= 32) {
2283e12c5d1SDavid du Colombier 			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
2293e12c5d1SDavid du Colombier 			break;
2303e12c5d1SDavid du Colombier 		}
2313e12c5d1SDavid du Colombier 		gopcode(OASHL, nodconst(v), l, r);
2323e12c5d1SDavid du Colombier 		break;
2333e12c5d1SDavid du Colombier 	}
2343e12c5d1SDavid du Colombier 	p += 2;
2353e12c5d1SDavid du Colombier 	goto loop;
2363e12c5d1SDavid du Colombier }
2373e12c5d1SDavid du Colombier 
2383e12c5d1SDavid du Colombier void
gextern(Sym * s,Node * a,long o,long w)2393e12c5d1SDavid du Colombier gextern(Sym *s, Node *a, long o, long w)
2403e12c5d1SDavid du Colombier {
241219b2ee8SDavid du Colombier 	if(a->op == OCONST && typev[a->type->etype]) {
24280ee5cbfSDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
243219b2ee8SDavid du Colombier 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
24480ee5cbfSDavid du Colombier 		else
24580ee5cbfSDavid du Colombier 			gpseudo(ADATA, s, nod32const(a->vconst));
246219b2ee8SDavid du Colombier 		p->from.offset += o;
247219b2ee8SDavid du Colombier 		p->reg = 4;
24880ee5cbfSDavid du Colombier 		if(align(0, types[TCHAR], Aarg1))	/* isbigendian */
249219b2ee8SDavid du Colombier 			gpseudo(ADATA, s, nod32const(a->vconst));
25080ee5cbfSDavid du Colombier 		else
25180ee5cbfSDavid du Colombier 			gpseudo(ADATA, s, nod32const(a->vconst>>32));
252219b2ee8SDavid du Colombier 		p->from.offset += o + 4;
253219b2ee8SDavid du Colombier 		p->reg = 4;
254219b2ee8SDavid du Colombier 		return;
255219b2ee8SDavid du Colombier 	}
2563e12c5d1SDavid du Colombier 	gpseudo(ADATA, s, a);
2573e12c5d1SDavid du Colombier 	p->from.offset += o;
2583e12c5d1SDavid du Colombier 	p->reg = w;
2593e12c5d1SDavid du Colombier 	if(p->to.type == D_OREG)
2603e12c5d1SDavid du Colombier 		p->to.type = D_CONST;
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier 
263375daca8SDavid du Colombier void	zname(Biobuf*, Sym*, int);
2643e12c5d1SDavid du Colombier void	zaddr(Biobuf*, Adr*, int);
2653e12c5d1SDavid du Colombier void	zwrite(Biobuf*, Prog*, int, int);
2663e12c5d1SDavid du Colombier void	outhist(Biobuf*);
2673e12c5d1SDavid du Colombier 
2683e12c5d1SDavid du Colombier void
outcode(void)2693e12c5d1SDavid du Colombier outcode(void)
2703e12c5d1SDavid du Colombier {
2713e12c5d1SDavid du Colombier 	struct { Sym *sym; short type; } h[NSYM];
2723e12c5d1SDavid du Colombier 	Prog *p;
2733e12c5d1SDavid du Colombier 	Sym *s;
274219b2ee8SDavid du Colombier 	int sf, st, t, sym;
2753e12c5d1SDavid du Colombier 
2763e12c5d1SDavid du Colombier 	if(debug['S']) {
2773e12c5d1SDavid du Colombier 		for(p = firstp; p != P; p = p->link)
2783e12c5d1SDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
2793e12c5d1SDavid du Colombier 				pc--;
2803e12c5d1SDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
2813e12c5d1SDavid du Colombier 			print("%P\n", p);
2823e12c5d1SDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
2833e12c5d1SDavid du Colombier 				pc++;
2843e12c5d1SDavid du Colombier 		}
2853e12c5d1SDavid du Colombier 	}
286219b2ee8SDavid du Colombier 	outhist(&outbuf);
2873e12c5d1SDavid du Colombier 	for(sym=0; sym<NSYM; sym++) {
2883e12c5d1SDavid du Colombier 		h[sym].sym = S;
2893e12c5d1SDavid du Colombier 		h[sym].type = 0;
2903e12c5d1SDavid du Colombier 	}
2913e12c5d1SDavid du Colombier 	sym = 1;
2923e12c5d1SDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
2933e12c5d1SDavid du Colombier 	jackpot:
2943e12c5d1SDavid du Colombier 		sf = 0;
2953e12c5d1SDavid du Colombier 		s = p->from.sym;
2963e12c5d1SDavid du Colombier 		while(s != S) {
2973e12c5d1SDavid du Colombier 			sf = s->sym;
2983e12c5d1SDavid du Colombier 			if(sf < 0 || sf >= NSYM)
2993e12c5d1SDavid du Colombier 				sf = 0;
3003e12c5d1SDavid du Colombier 			t = p->from.name;
3013e12c5d1SDavid du Colombier 			if(h[sf].type == t)
3023e12c5d1SDavid du Colombier 			if(h[sf].sym == s)
3033e12c5d1SDavid du Colombier 				break;
3043e12c5d1SDavid du Colombier 			s->sym = sym;
305375daca8SDavid du Colombier 			zname(&outbuf, s, t);
3063e12c5d1SDavid du Colombier 			h[sym].sym = s;
3073e12c5d1SDavid du Colombier 			h[sym].type = t;
3083e12c5d1SDavid du Colombier 			sf = sym;
3093e12c5d1SDavid du Colombier 			sym++;
3103e12c5d1SDavid du Colombier 			if(sym >= NSYM)
3113e12c5d1SDavid du Colombier 				sym = 1;
3123e12c5d1SDavid du Colombier 			break;
3133e12c5d1SDavid du Colombier 		}
3143e12c5d1SDavid du Colombier 		st = 0;
3153e12c5d1SDavid du Colombier 		s = p->to.sym;
3163e12c5d1SDavid du Colombier 		while(s != S) {
3173e12c5d1SDavid du Colombier 			st = s->sym;
3183e12c5d1SDavid du Colombier 			if(st < 0 || st >= NSYM)
3193e12c5d1SDavid du Colombier 				st = 0;
3203e12c5d1SDavid du Colombier 			t = p->to.name;
3213e12c5d1SDavid du Colombier 			if(h[st].type == t)
3223e12c5d1SDavid du Colombier 			if(h[st].sym == s)
3233e12c5d1SDavid du Colombier 				break;
3243e12c5d1SDavid du Colombier 			s->sym = sym;
325375daca8SDavid du Colombier 			zname(&outbuf, s, t);
3263e12c5d1SDavid du Colombier 			h[sym].sym = s;
3273e12c5d1SDavid du Colombier 			h[sym].type = t;
3283e12c5d1SDavid du Colombier 			st = sym;
3293e12c5d1SDavid du Colombier 			sym++;
3303e12c5d1SDavid du Colombier 			if(sym >= NSYM)
3313e12c5d1SDavid du Colombier 				sym = 1;
3323e12c5d1SDavid du Colombier 			if(st == sf)
3333e12c5d1SDavid du Colombier 				goto jackpot;
3343e12c5d1SDavid du Colombier 			break;
3353e12c5d1SDavid du Colombier 		}
336219b2ee8SDavid du Colombier 		zwrite(&outbuf, p, sf, st);
3373e12c5d1SDavid du Colombier 	}
3383e12c5d1SDavid du Colombier 	firstp = P;
3393e12c5d1SDavid du Colombier 	lastp = P;
3403e12c5d1SDavid du Colombier }
3413e12c5d1SDavid du Colombier 
3423e12c5d1SDavid du Colombier void
zwrite(Biobuf * b,Prog * p,int sf,int st)3433e12c5d1SDavid du Colombier zwrite(Biobuf *b, Prog *p, int sf, int st)
3443e12c5d1SDavid du Colombier {
3453e12c5d1SDavid du Colombier 	long l;
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	Bputc(b, p->as);
3483e12c5d1SDavid du Colombier 	Bputc(b, p->reg);
3493e12c5d1SDavid du Colombier 	l = p->lineno;
3503e12c5d1SDavid du Colombier 	Bputc(b, l);
3513e12c5d1SDavid du Colombier 	Bputc(b, l>>8);
3523e12c5d1SDavid du Colombier 	Bputc(b, l>>16);
3533e12c5d1SDavid du Colombier 	Bputc(b, l>>24);
3543e12c5d1SDavid du Colombier 	zaddr(b, &p->from, sf);
3553e12c5d1SDavid du Colombier 	zaddr(b, &p->to, st);
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier 
3583e12c5d1SDavid du Colombier void
outhist(Biobuf * b)3593e12c5d1SDavid du Colombier outhist(Biobuf *b)
3603e12c5d1SDavid du Colombier {
3613e12c5d1SDavid du Colombier 	Hist *h;
3627dd7cddfSDavid du Colombier 	char *p, *q, *op, c;
3633e12c5d1SDavid du Colombier 	Prog pg;
3643e12c5d1SDavid du Colombier 	int n;
3653e12c5d1SDavid du Colombier 
3663e12c5d1SDavid du Colombier 	pg = zprog;
3673e12c5d1SDavid du Colombier 	pg.as = AHISTORY;
3687dd7cddfSDavid du Colombier 	c = pathchar();
3693e12c5d1SDavid du Colombier 	for(h = hist; h != H; h = h->link) {
3703e12c5d1SDavid du Colombier 		p = h->name;
371219b2ee8SDavid du Colombier 		op = 0;
372375daca8SDavid du Colombier 		/* on windows skip drive specifier in pathname */
373375daca8SDavid du Colombier 		if(systemtype(Windows) && p && p[1] == ':'){
374375daca8SDavid du Colombier 			p += 2;
375375daca8SDavid du Colombier 			c = *p;
376375daca8SDavid du Colombier 		}
3777dd7cddfSDavid du Colombier 		if(p && p[0] != c && h->offset == 0 && pathname){
3787dd7cddfSDavid du Colombier 			/* on windows skip drive specifier in pathname */
379375daca8SDavid du Colombier 			if(systemtype(Windows) && pathname[1] == ':') {
3807dd7cddfSDavid du Colombier 				op = p;
3817dd7cddfSDavid du Colombier 				p = pathname+2;
382375daca8SDavid du Colombier 				c = *p;
3837dd7cddfSDavid du Colombier 			} else if(pathname[0] == c){
384219b2ee8SDavid du Colombier 				op = p;
385219b2ee8SDavid du Colombier 				p = pathname;
386219b2ee8SDavid du Colombier 			}
3877dd7cddfSDavid du Colombier 		}
3883e12c5d1SDavid du Colombier 		while(p) {
3897dd7cddfSDavid du Colombier 			q = utfrune(p, c);
3903e12c5d1SDavid du Colombier 			if(q) {
3913e12c5d1SDavid du Colombier 				n = q-p;
392375daca8SDavid du Colombier 				if(n == 0){
3933e12c5d1SDavid du Colombier 					n = 1;	/* leading "/" */
394375daca8SDavid du Colombier 					*p = '/';	/* don't emit "\" on windows */
395375daca8SDavid du Colombier 				}
3963e12c5d1SDavid du Colombier 				q++;
3973e12c5d1SDavid du Colombier 			} else {
3983e12c5d1SDavid du Colombier 				n = strlen(p);
3993e12c5d1SDavid du Colombier 				q = 0;
4003e12c5d1SDavid du Colombier 			}
4013e12c5d1SDavid du Colombier 			if(n) {
402219b2ee8SDavid du Colombier 				Bputc(b, ANAME);
403219b2ee8SDavid du Colombier 				Bputc(b, D_FILE);
404219b2ee8SDavid du Colombier 				Bputc(b, 1);
405219b2ee8SDavid du Colombier 				Bputc(b, '<');
406219b2ee8SDavid du Colombier 				Bwrite(b, p, n);
407219b2ee8SDavid du Colombier 				Bputc(b, 0);
4083e12c5d1SDavid du Colombier 			}
4093e12c5d1SDavid du Colombier 			p = q;
410219b2ee8SDavid du Colombier 			if(p == 0 && op) {
411219b2ee8SDavid du Colombier 				p = op;
412219b2ee8SDavid du Colombier 				op = 0;
413219b2ee8SDavid du Colombier 			}
4143e12c5d1SDavid du Colombier 		}
4153e12c5d1SDavid du Colombier 		pg.lineno = h->line;
4163e12c5d1SDavid du Colombier 		pg.to.type = zprog.to.type;
4173e12c5d1SDavid du Colombier 		pg.to.offset = h->offset;
4183e12c5d1SDavid du Colombier 		if(h->offset)
4193e12c5d1SDavid du Colombier 			pg.to.type = D_CONST;
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier 		zwrite(b, &pg, 0, 0);
4223e12c5d1SDavid du Colombier 	}
4233e12c5d1SDavid du Colombier }
4243e12c5d1SDavid du Colombier 
4253e12c5d1SDavid du Colombier void
zname(Biobuf * b,Sym * s,int t)426375daca8SDavid du Colombier zname(Biobuf *b, Sym *s, int t)
4273e12c5d1SDavid du Colombier {
428375daca8SDavid du Colombier 	char *n;
429375daca8SDavid du Colombier 	ulong sig;
4303e12c5d1SDavid du Colombier 
431375daca8SDavid du Colombier 	if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
432375daca8SDavid du Colombier 		sig = sign(s);
433375daca8SDavid du Colombier 		Bputc(b, ASIGNAME);
434375daca8SDavid du Colombier 		Bputc(b, sig);
435375daca8SDavid du Colombier 		Bputc(b, sig>>8);
436375daca8SDavid du Colombier 		Bputc(b, sig>>16);
437375daca8SDavid du Colombier 		Bputc(b, sig>>24);
438375daca8SDavid du Colombier 		s->sig = SIGDONE;
439375daca8SDavid du Colombier 	}
440375daca8SDavid du Colombier 	else
441375daca8SDavid du Colombier 		Bputc(b, ANAME);	/* as */
4423e12c5d1SDavid du Colombier 	Bputc(b, t);		/* type */
443375daca8SDavid du Colombier 	Bputc(b, s->sym);		/* sym */
444375daca8SDavid du Colombier 	n = s->name;
4453e12c5d1SDavid du Colombier 	while(*n) {
4463e12c5d1SDavid du Colombier 		Bputc(b, *n);
4473e12c5d1SDavid du Colombier 		n++;
4483e12c5d1SDavid du Colombier 	}
4493e12c5d1SDavid du Colombier 	Bputc(b, 0);
4503e12c5d1SDavid du Colombier }
4513e12c5d1SDavid du Colombier 
4523e12c5d1SDavid du Colombier void
zaddr(Biobuf * b,Adr * a,int s)4533e12c5d1SDavid du Colombier zaddr(Biobuf *b, Adr *a, int s)
4543e12c5d1SDavid du Colombier {
4553e12c5d1SDavid du Colombier 	long l;
4563e12c5d1SDavid du Colombier 	int i;
4573e12c5d1SDavid du Colombier 	char *n;
4583e12c5d1SDavid du Colombier 	Ieee e;
4593e12c5d1SDavid du Colombier 
4603e12c5d1SDavid du Colombier 	Bputc(b, a->type);
4613e12c5d1SDavid du Colombier 	Bputc(b, a->reg);
4623e12c5d1SDavid du Colombier 	Bputc(b, s);
4633e12c5d1SDavid du Colombier 	Bputc(b, a->name);
4643e12c5d1SDavid du Colombier 	switch(a->type) {
4653e12c5d1SDavid du Colombier 	default:
4663e12c5d1SDavid du Colombier 		diag(Z, "unknown type %d in zaddr", a->type);
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier 	case D_NONE:
4693e12c5d1SDavid du Colombier 	case D_REG:
4703e12c5d1SDavid du Colombier 	case D_FREG:
4713e12c5d1SDavid du Colombier 	case D_CREG:
4723e12c5d1SDavid du Colombier 		break;
4733e12c5d1SDavid du Colombier 
4743e12c5d1SDavid du Colombier 	case D_OREG:
4753e12c5d1SDavid du Colombier 	case D_CONST:
4763e12c5d1SDavid du Colombier 	case D_BRANCH:
4773e12c5d1SDavid du Colombier 		l = a->offset;
4783e12c5d1SDavid du Colombier 		Bputc(b, l);
4793e12c5d1SDavid du Colombier 		Bputc(b, l>>8);
4803e12c5d1SDavid du Colombier 		Bputc(b, l>>16);
4813e12c5d1SDavid du Colombier 		Bputc(b, l>>24);
4823e12c5d1SDavid du Colombier 		break;
4833e12c5d1SDavid du Colombier 
4843e12c5d1SDavid du Colombier 	case D_SCONST:
4853e12c5d1SDavid du Colombier 		n = a->sval;
4863e12c5d1SDavid du Colombier 		for(i=0; i<NSNAME; i++) {
4873e12c5d1SDavid du Colombier 			Bputc(b, *n);
4883e12c5d1SDavid du Colombier 			n++;
4893e12c5d1SDavid du Colombier 		}
4903e12c5d1SDavid du Colombier 		break;
4913e12c5d1SDavid du Colombier 
4923e12c5d1SDavid du Colombier 	case D_FCONST:
4933e12c5d1SDavid du Colombier 		ieeedtod(&e, a->dval);
4943e12c5d1SDavid du Colombier 		l = e.l;
4953e12c5d1SDavid du Colombier 		Bputc(b, l);
4963e12c5d1SDavid du Colombier 		Bputc(b, l>>8);
4973e12c5d1SDavid du Colombier 		Bputc(b, l>>16);
4983e12c5d1SDavid du Colombier 		Bputc(b, l>>24);
4993e12c5d1SDavid du Colombier 		l = e.h;
5003e12c5d1SDavid du Colombier 		Bputc(b, l);
5013e12c5d1SDavid du Colombier 		Bputc(b, l>>8);
5023e12c5d1SDavid du Colombier 		Bputc(b, l>>16);
5033e12c5d1SDavid du Colombier 		Bputc(b, l>>24);
5043e12c5d1SDavid du Colombier 		break;
5053e12c5d1SDavid du Colombier 	}
5063e12c5d1SDavid du Colombier }
5073e12c5d1SDavid du Colombier 
5087dd7cddfSDavid du Colombier long
align(long i,Type * t,int op)5097dd7cddfSDavid du Colombier align(long i, Type *t, int op)
5103e12c5d1SDavid du Colombier {
5117dd7cddfSDavid du Colombier 	long o;
5127dd7cddfSDavid du Colombier 	Type *v;
5137dd7cddfSDavid du Colombier 	int w;
5143e12c5d1SDavid du Colombier 
5157dd7cddfSDavid du Colombier 	o = i;
5167dd7cddfSDavid du Colombier 	w = 1;
5177dd7cddfSDavid du Colombier 	switch(op) {
5187dd7cddfSDavid du Colombier 	default:
5197dd7cddfSDavid du Colombier 		diag(Z, "unknown align opcode %d", op);
5207dd7cddfSDavid du Colombier 		break;
5217dd7cddfSDavid du Colombier 
5227dd7cddfSDavid du Colombier 	case Asu2:	/* padding at end of a struct */
5237dd7cddfSDavid du Colombier 		w = SZ_LONG;
5249847521cSDavid du Colombier 		if(packflg)
5259847521cSDavid du Colombier 			w = packflg;
5267dd7cddfSDavid du Colombier 		break;
5277dd7cddfSDavid du Colombier 
5287dd7cddfSDavid du Colombier 	case Ael1:	/* initial allign of struct element */
5297dd7cddfSDavid du Colombier 		for(v=t; v->etype==TARRAY; v=v->link)
5307dd7cddfSDavid du Colombier 			;
5317dd7cddfSDavid du Colombier 		w = ewidth[v->etype];
5327dd7cddfSDavid du Colombier 		if(w <= 0 || w >= SZ_LONG)
5337dd7cddfSDavid du Colombier 			w = SZ_LONG;
5349847521cSDavid du Colombier 		if(packflg)
5359847521cSDavid du Colombier 			w = packflg;
5367dd7cddfSDavid du Colombier 		break;
5377dd7cddfSDavid du Colombier 
5387dd7cddfSDavid du Colombier 	case Ael2:	/* width of a struct element */
5397dd7cddfSDavid du Colombier 		o += t->width;
5407dd7cddfSDavid du Colombier 		break;
5417dd7cddfSDavid du Colombier 
5427dd7cddfSDavid du Colombier 	case Aarg0:	/* initial passbyptr argument in arg list */
5437dd7cddfSDavid du Colombier 		if(typesuv[t->etype]) {
5447dd7cddfSDavid du Colombier 			o = align(o, types[TIND], Aarg1);
5457dd7cddfSDavid du Colombier 			o = align(o, types[TIND], Aarg2);
5467dd7cddfSDavid du Colombier 		}
5477dd7cddfSDavid du Colombier 		break;
5487dd7cddfSDavid du Colombier 
5497dd7cddfSDavid du Colombier 	case Aarg1:	/* initial allign of parameter */
5507dd7cddfSDavid du Colombier 		w = ewidth[t->etype];
5517dd7cddfSDavid du Colombier 		if(w <= 0 || w >= SZ_LONG) {
5527dd7cddfSDavid du Colombier 			w = SZ_LONG;
5537dd7cddfSDavid du Colombier 			break;
5547dd7cddfSDavid du Colombier 		}
5557dd7cddfSDavid du Colombier 		o += SZ_LONG - w;	/* big endian adjustment */
5567dd7cddfSDavid du Colombier 		w = 1;
5577dd7cddfSDavid du Colombier 		break;
5587dd7cddfSDavid du Colombier 
5597dd7cddfSDavid du Colombier 	case Aarg2:	/* width of a parameter */
5607dd7cddfSDavid du Colombier 		o += t->width;
5617dd7cddfSDavid du Colombier 		w = SZ_LONG;
5627dd7cddfSDavid du Colombier 		break;
5637dd7cddfSDavid du Colombier 
5647dd7cddfSDavid du Colombier 	case Aaut3:	/* total allign of automatic */
5657dd7cddfSDavid du Colombier 		o = align(o, t, Ael1);
5667dd7cddfSDavid du Colombier 		o = align(o, t, Ael2);
5677dd7cddfSDavid du Colombier 		break;
5687dd7cddfSDavid du Colombier 	}
5697dd7cddfSDavid du Colombier 	o = round(o, w);
5707dd7cddfSDavid du Colombier 	if(debug['A'])
5717dd7cddfSDavid du Colombier 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
5727dd7cddfSDavid du Colombier 	return o;
5733e12c5d1SDavid du Colombier }
574219b2ee8SDavid du Colombier 
5757dd7cddfSDavid du Colombier long
maxround(long max,long v)5767dd7cddfSDavid du Colombier maxround(long max, long v)
577219b2ee8SDavid du Colombier {
578*85e2e562SDavid du Colombier 	v = round(v, SZ_LONG);
5797dd7cddfSDavid du Colombier 	if(v > max)
580*85e2e562SDavid du Colombier 		return v;
5817dd7cddfSDavid du Colombier 	return max;
582219b2ee8SDavid du Colombier }
583