xref: /plan9/sys/src/cmd/qc/swt.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include "gc.h"
2*7dd7cddfSDavid du Colombier 
3*7dd7cddfSDavid du Colombier int
4*7dd7cddfSDavid du Colombier swcmp(void *a1, void *a2)
5*7dd7cddfSDavid du Colombier {
6*7dd7cddfSDavid du Colombier 	C1 *p1, *p2;
7*7dd7cddfSDavid du Colombier 
8*7dd7cddfSDavid du Colombier 	p1 = a1;
9*7dd7cddfSDavid du Colombier 	p2 = a2;
10*7dd7cddfSDavid du Colombier 	if(p1->val < p2->val)
11*7dd7cddfSDavid du Colombier 		return -1;
12*7dd7cddfSDavid du Colombier 	return  p1->val > p2->val;
13*7dd7cddfSDavid du Colombier }
14*7dd7cddfSDavid du Colombier 
15*7dd7cddfSDavid du Colombier void
16*7dd7cddfSDavid du Colombier doswit(Node *n)
17*7dd7cddfSDavid du Colombier {
18*7dd7cddfSDavid du Colombier 	Case *c;
19*7dd7cddfSDavid du Colombier 	C1 *q, *iq;
20*7dd7cddfSDavid du Colombier 	long def, nc, i;
21*7dd7cddfSDavid du Colombier 	Node tn;
22*7dd7cddfSDavid du Colombier 
23*7dd7cddfSDavid du Colombier 	def = 0;
24*7dd7cddfSDavid du Colombier 	nc = 0;
25*7dd7cddfSDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
26*7dd7cddfSDavid du Colombier 		if(c->def) {
27*7dd7cddfSDavid du Colombier 			if(def)
28*7dd7cddfSDavid du Colombier 				diag(n, "more than one default in switch");
29*7dd7cddfSDavid du Colombier 			def = c->label;
30*7dd7cddfSDavid du Colombier 			continue;
31*7dd7cddfSDavid du Colombier 		}
32*7dd7cddfSDavid du Colombier 		nc++;
33*7dd7cddfSDavid du Colombier 	}
34*7dd7cddfSDavid du Colombier 
35*7dd7cddfSDavid du Colombier 	iq = alloc(nc*sizeof(C1));
36*7dd7cddfSDavid du Colombier 	q = iq;
37*7dd7cddfSDavid du Colombier 	for(c = cases; c->link != C; c = c->link) {
38*7dd7cddfSDavid du Colombier 		if(c->def)
39*7dd7cddfSDavid du Colombier 			continue;
40*7dd7cddfSDavid du Colombier 		q->label = c->label;
41*7dd7cddfSDavid du Colombier 		q->val = c->val;
42*7dd7cddfSDavid du Colombier 		q++;
43*7dd7cddfSDavid du Colombier 	}
44*7dd7cddfSDavid du Colombier 	qsort(iq, nc, sizeof(C1), swcmp);
45*7dd7cddfSDavid du Colombier 	if(def == 0)
46*7dd7cddfSDavid du Colombier 		def = breakpc;
47*7dd7cddfSDavid du Colombier 	for(i=0; i<nc-1; i++)
48*7dd7cddfSDavid du Colombier 		if(iq[i].val == iq[i+1].val)
49*7dd7cddfSDavid du Colombier 			diag(n, "duplicate cases in switch %ld", iq[i].val);
50*7dd7cddfSDavid du Colombier 	regalloc(&tn, &regnode, Z);
51*7dd7cddfSDavid du Colombier 	swit1(iq, nc, def, n, &tn);
52*7dd7cddfSDavid du Colombier 	regfree(&tn);
53*7dd7cddfSDavid du Colombier }
54*7dd7cddfSDavid du Colombier 
55*7dd7cddfSDavid du Colombier void
56*7dd7cddfSDavid du Colombier swit1(C1 *q, int nc, long def, Node *n, Node *tn)
57*7dd7cddfSDavid du Colombier {
58*7dd7cddfSDavid du Colombier 	C1 *r;
59*7dd7cddfSDavid du Colombier 	int i;
60*7dd7cddfSDavid du Colombier 	Prog *sp;
61*7dd7cddfSDavid du Colombier 
62*7dd7cddfSDavid du Colombier 	if(nc < 5) {
63*7dd7cddfSDavid du Colombier 		for(i=0; i<nc; i++) {
64*7dd7cddfSDavid du Colombier 			if(sval(q->val)) {
65*7dd7cddfSDavid du Colombier 				gopcode(OEQ, n, Z, nodconst(q->val));
66*7dd7cddfSDavid du Colombier 			} else {
67*7dd7cddfSDavid du Colombier 				gopcode(OSUB, nodconst(q->val), n, tn);
68*7dd7cddfSDavid du Colombier 				gopcode(OEQ, tn, Z, nodconst(0));
69*7dd7cddfSDavid du Colombier 			}
70*7dd7cddfSDavid du Colombier 			patch(p, q->label);
71*7dd7cddfSDavid du Colombier 			q++;
72*7dd7cddfSDavid du Colombier 		}
73*7dd7cddfSDavid du Colombier 		gbranch(OGOTO);
74*7dd7cddfSDavid du Colombier 		patch(p, def);
75*7dd7cddfSDavid du Colombier 		return;
76*7dd7cddfSDavid du Colombier 	}
77*7dd7cddfSDavid du Colombier 	i = nc / 2;
78*7dd7cddfSDavid du Colombier 	r = q+i;
79*7dd7cddfSDavid du Colombier 	if(sval(r->val)) {
80*7dd7cddfSDavid du Colombier 		gopcode(OGT, n, Z, nodconst(r->val));
81*7dd7cddfSDavid du Colombier 		sp = p;
82*7dd7cddfSDavid du Colombier 	} else {
83*7dd7cddfSDavid du Colombier 		gopcode(OSUB, nodconst(r->val), n, tn);
84*7dd7cddfSDavid du Colombier 		gopcode(OGT, tn, Z, nodconst(0));
85*7dd7cddfSDavid du Colombier 		sp = p;
86*7dd7cddfSDavid du Colombier 	}
87*7dd7cddfSDavid du Colombier 	gbranch(OGOTO);
88*7dd7cddfSDavid du Colombier 	p->as = ABEQ;
89*7dd7cddfSDavid du Colombier 	patch(p, r->label);
90*7dd7cddfSDavid du Colombier 	swit1(q, i, def, n, tn);
91*7dd7cddfSDavid du Colombier 
92*7dd7cddfSDavid du Colombier 	patch(sp, pc);
93*7dd7cddfSDavid du Colombier 	swit1(r+1, nc-i-1, def, n, tn);
94*7dd7cddfSDavid du Colombier }
95*7dd7cddfSDavid du Colombier 
96*7dd7cddfSDavid du Colombier void
97*7dd7cddfSDavid du Colombier cas(void)
98*7dd7cddfSDavid du Colombier {
99*7dd7cddfSDavid du Colombier 	Case *c;
100*7dd7cddfSDavid du Colombier 
101*7dd7cddfSDavid du Colombier 	c = alloc(sizeof(*c));
102*7dd7cddfSDavid du Colombier 	c->link = cases;
103*7dd7cddfSDavid du Colombier 	cases = c;
104*7dd7cddfSDavid du Colombier }
105*7dd7cddfSDavid du Colombier 
106*7dd7cddfSDavid du Colombier void
107*7dd7cddfSDavid du Colombier bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
108*7dd7cddfSDavid du Colombier {
109*7dd7cddfSDavid du Colombier 	int sh;
110*7dd7cddfSDavid du Colombier 	long v;
111*7dd7cddfSDavid du Colombier 	Node *l;
112*7dd7cddfSDavid du Colombier 
113*7dd7cddfSDavid du Colombier 	/*
114*7dd7cddfSDavid du Colombier 	 * n1 gets adjusted/masked value
115*7dd7cddfSDavid du Colombier 	 * n2 gets address of cell
116*7dd7cddfSDavid du Colombier 	 * n3 gets contents of cell
117*7dd7cddfSDavid du Colombier 	 */
118*7dd7cddfSDavid du Colombier 	l = b->left;
119*7dd7cddfSDavid du Colombier 	if(n2 != Z) {
120*7dd7cddfSDavid du Colombier 		regalloc(n1, l, nn);
121*7dd7cddfSDavid du Colombier 		reglcgen(n2, l, Z);
122*7dd7cddfSDavid du Colombier 		regalloc(n3, l, Z);
123*7dd7cddfSDavid du Colombier 		gopcode(OAS, n2, Z, n3);
124*7dd7cddfSDavid du Colombier 		gopcode(OAS, n3, Z, n1);
125*7dd7cddfSDavid du Colombier 	} else {
126*7dd7cddfSDavid du Colombier 		regalloc(n1, l, nn);
127*7dd7cddfSDavid du Colombier 		cgen(l, n1);
128*7dd7cddfSDavid du Colombier 	}
129*7dd7cddfSDavid du Colombier 	if(b->type->shift == 0 && typeu[b->type->etype]) {
130*7dd7cddfSDavid du Colombier 		v = ~0 + (1L << b->type->nbits);
131*7dd7cddfSDavid du Colombier 		gopcode(OAND, nodconst(v), Z, n1);
132*7dd7cddfSDavid du Colombier 	} else {
133*7dd7cddfSDavid du Colombier 		sh = 32 - b->type->shift - b->type->nbits;
134*7dd7cddfSDavid du Colombier 		if(sh > 0)
135*7dd7cddfSDavid du Colombier 			gopcode(OASHL, nodconst(sh), Z, n1);
136*7dd7cddfSDavid du Colombier 		sh += b->type->shift;
137*7dd7cddfSDavid du Colombier 		if(sh > 0)
138*7dd7cddfSDavid du Colombier 			if(typeu[b->type->etype])
139*7dd7cddfSDavid du Colombier 				gopcode(OLSHR, nodconst(sh), Z, n1);
140*7dd7cddfSDavid du Colombier 			else
141*7dd7cddfSDavid du Colombier 				gopcode(OASHR, nodconst(sh), Z, n1);
142*7dd7cddfSDavid du Colombier 	}
143*7dd7cddfSDavid du Colombier }
144*7dd7cddfSDavid du Colombier 
145*7dd7cddfSDavid du Colombier void
146*7dd7cddfSDavid du Colombier bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
147*7dd7cddfSDavid du Colombier {
148*7dd7cddfSDavid du Colombier 	long v;
149*7dd7cddfSDavid du Colombier 	Node nod, *l;
150*7dd7cddfSDavid du Colombier 	int sh;
151*7dd7cddfSDavid du Colombier 
152*7dd7cddfSDavid du Colombier 	/*
153*7dd7cddfSDavid du Colombier 	 * n1 has adjusted/masked value
154*7dd7cddfSDavid du Colombier 	 * n2 has address of cell
155*7dd7cddfSDavid du Colombier 	 * n3 has contents of cell
156*7dd7cddfSDavid du Colombier 	 */
157*7dd7cddfSDavid du Colombier 	l = b->left;
158*7dd7cddfSDavid du Colombier 	regalloc(&nod, l, Z);
159*7dd7cddfSDavid du Colombier 	v = ~0 + (1L << b->type->nbits);
160*7dd7cddfSDavid du Colombier 	gopcode(OAND, nodconst(v), Z, n1);
161*7dd7cddfSDavid du Colombier 	gopcode(OAS, n1, Z, &nod);
162*7dd7cddfSDavid du Colombier 	if(nn != Z)
163*7dd7cddfSDavid du Colombier 		gopcode(OAS, n1, Z, nn);
164*7dd7cddfSDavid du Colombier 	sh = b->type->shift;
165*7dd7cddfSDavid du Colombier 	if(sh > 0)
166*7dd7cddfSDavid du Colombier 		gopcode(OASHL, nodconst(sh), Z, &nod);
167*7dd7cddfSDavid du Colombier 	v <<= sh;
168*7dd7cddfSDavid du Colombier 	gopcode(OAND, nodconst(~v), Z, n3);
169*7dd7cddfSDavid du Colombier 	gopcode(OOR, n3, Z, &nod);
170*7dd7cddfSDavid du Colombier 	gopcode(OAS, &nod, Z, n2);
171*7dd7cddfSDavid du Colombier 
172*7dd7cddfSDavid du Colombier 	regfree(&nod);
173*7dd7cddfSDavid du Colombier 	regfree(n1);
174*7dd7cddfSDavid du Colombier 	regfree(n2);
175*7dd7cddfSDavid du Colombier 	regfree(n3);
176*7dd7cddfSDavid du Colombier }
177*7dd7cddfSDavid du Colombier 
178*7dd7cddfSDavid du Colombier long
179*7dd7cddfSDavid du Colombier outstring(char *s, long n)
180*7dd7cddfSDavid du Colombier {
181*7dd7cddfSDavid du Colombier 	long r;
182*7dd7cddfSDavid du Colombier 
183*7dd7cddfSDavid du Colombier 	r = nstring;
184*7dd7cddfSDavid du Colombier 	while(n) {
185*7dd7cddfSDavid du Colombier 		string[mnstring] = *s++;
186*7dd7cddfSDavid du Colombier 		mnstring++;
187*7dd7cddfSDavid du Colombier 		nstring++;
188*7dd7cddfSDavid du Colombier 		if(mnstring >= NSNAME) {
189*7dd7cddfSDavid du Colombier 			gpseudo(ADATA, symstring, nodconst(0L));
190*7dd7cddfSDavid du Colombier 			p->from.offset += nstring - NSNAME;
191*7dd7cddfSDavid du Colombier 			p->reg = NSNAME;
192*7dd7cddfSDavid du Colombier 			p->to.type = D_SCONST;
193*7dd7cddfSDavid du Colombier 			memmove(p->to.sval, string, NSNAME);
194*7dd7cddfSDavid du Colombier 			mnstring = 0;
195*7dd7cddfSDavid du Colombier 		}
196*7dd7cddfSDavid du Colombier 		n--;
197*7dd7cddfSDavid du Colombier 	}
198*7dd7cddfSDavid du Colombier 	return r;
199*7dd7cddfSDavid du Colombier }
200*7dd7cddfSDavid du Colombier 
201*7dd7cddfSDavid du Colombier long
202*7dd7cddfSDavid du Colombier outlstring(ushort *s, long n)
203*7dd7cddfSDavid du Colombier {
204*7dd7cddfSDavid du Colombier 	char buf[2];
205*7dd7cddfSDavid du Colombier 	int c;
206*7dd7cddfSDavid du Colombier 	long r;
207*7dd7cddfSDavid du Colombier 
208*7dd7cddfSDavid du Colombier 	while(nstring & 1)
209*7dd7cddfSDavid du Colombier 		outstring("", 1);
210*7dd7cddfSDavid du Colombier 	r = nstring;
211*7dd7cddfSDavid du Colombier 	while(n > 0) {
212*7dd7cddfSDavid du Colombier 		c = *s++;
213*7dd7cddfSDavid du Colombier 		if(align(0, types[TCHAR], Aarg1)) {
214*7dd7cddfSDavid du Colombier 			buf[0] = c>>8;
215*7dd7cddfSDavid du Colombier 			buf[1] = c;
216*7dd7cddfSDavid du Colombier 		} else {
217*7dd7cddfSDavid du Colombier 			buf[0] = c;
218*7dd7cddfSDavid du Colombier 			buf[1] = c>>8;
219*7dd7cddfSDavid du Colombier 		}
220*7dd7cddfSDavid du Colombier 		outstring(buf, 2);
221*7dd7cddfSDavid du Colombier 		n -= sizeof(ushort);
222*7dd7cddfSDavid du Colombier 	}
223*7dd7cddfSDavid du Colombier 	return r;
224*7dd7cddfSDavid du Colombier }
225*7dd7cddfSDavid du Colombier 
226*7dd7cddfSDavid du Colombier int
227*7dd7cddfSDavid du Colombier mulcon(Node *n, Node *nn)
228*7dd7cddfSDavid du Colombier {
229*7dd7cddfSDavid du Colombier 	Node *l, *r, nod1, nod2;
230*7dd7cddfSDavid du Colombier 	Multab *m;
231*7dd7cddfSDavid du Colombier 	long v;
232*7dd7cddfSDavid du Colombier 	int o;
233*7dd7cddfSDavid du Colombier 	char code[sizeof(m->code)+2], *p;
234*7dd7cddfSDavid du Colombier 
235*7dd7cddfSDavid du Colombier 	if(typefd[n->type->etype])
236*7dd7cddfSDavid du Colombier 		return 0;
237*7dd7cddfSDavid du Colombier 	l = n->left;
238*7dd7cddfSDavid du Colombier 	r = n->right;
239*7dd7cddfSDavid du Colombier 	if(l->op == OCONST) {
240*7dd7cddfSDavid du Colombier 		l = r;
241*7dd7cddfSDavid du Colombier 		r = n->left;
242*7dd7cddfSDavid du Colombier 	}
243*7dd7cddfSDavid du Colombier 	if(r->op != OCONST)
244*7dd7cddfSDavid du Colombier 		return 0;
245*7dd7cddfSDavid du Colombier 	v = convvtox(r->vconst, n->type->etype);
246*7dd7cddfSDavid du Colombier 	if(v != r->vconst) {
247*7dd7cddfSDavid du Colombier 		if(debug['M'])
248*7dd7cddfSDavid du Colombier 			print("%L multiply conv: %lld\n", n->lineno, r->vconst);
249*7dd7cddfSDavid du Colombier 		return 0;
250*7dd7cddfSDavid du Colombier 	}
251*7dd7cddfSDavid du Colombier 	m = mulcon0(n, v);
252*7dd7cddfSDavid du Colombier 	if(!m) {
253*7dd7cddfSDavid du Colombier 		if(debug['M'])
254*7dd7cddfSDavid du Colombier 			print("%L multiply table: %lld\n", n->lineno, r->vconst);
255*7dd7cddfSDavid du Colombier 		return 0;
256*7dd7cddfSDavid du Colombier 	}
257*7dd7cddfSDavid du Colombier 
258*7dd7cddfSDavid du Colombier 	memmove(code, m->code, sizeof(m->code));
259*7dd7cddfSDavid du Colombier 	code[sizeof(m->code)] = 0;
260*7dd7cddfSDavid du Colombier 
261*7dd7cddfSDavid du Colombier 	p = code;
262*7dd7cddfSDavid du Colombier 	if(p[1] == 'i')
263*7dd7cddfSDavid du Colombier 		p += 2;
264*7dd7cddfSDavid du Colombier 	regalloc(&nod1, n, nn);
265*7dd7cddfSDavid du Colombier 	cgen(l, &nod1);
266*7dd7cddfSDavid du Colombier 	if(v < 0)
267*7dd7cddfSDavid du Colombier 		gopcode(ONEG, &nod1, Z, &nod1);
268*7dd7cddfSDavid du Colombier 	regalloc(&nod2, n, Z);
269*7dd7cddfSDavid du Colombier 
270*7dd7cddfSDavid du Colombier loop:
271*7dd7cddfSDavid du Colombier 	switch(*p) {
272*7dd7cddfSDavid du Colombier 	case 0:
273*7dd7cddfSDavid du Colombier 		regfree(&nod2);
274*7dd7cddfSDavid du Colombier 		gopcode(OAS, &nod1, Z, nn);
275*7dd7cddfSDavid du Colombier 		regfree(&nod1);
276*7dd7cddfSDavid du Colombier 		return 1;
277*7dd7cddfSDavid du Colombier 	case '+':
278*7dd7cddfSDavid du Colombier 		o = OADD;
279*7dd7cddfSDavid du Colombier 		goto addsub;
280*7dd7cddfSDavid du Colombier 	case '-':
281*7dd7cddfSDavid du Colombier 		o = OSUB;
282*7dd7cddfSDavid du Colombier 	addsub:	/* number is r,n,l */
283*7dd7cddfSDavid du Colombier 		v = p[1] - '0';
284*7dd7cddfSDavid du Colombier 		r = &nod1;
285*7dd7cddfSDavid du Colombier 		if(v&4)
286*7dd7cddfSDavid du Colombier 			r = &nod2;
287*7dd7cddfSDavid du Colombier 		n = &nod1;
288*7dd7cddfSDavid du Colombier 		if(v&2)
289*7dd7cddfSDavid du Colombier 			n = &nod2;
290*7dd7cddfSDavid du Colombier 		l = &nod1;
291*7dd7cddfSDavid du Colombier 		if(v&1)
292*7dd7cddfSDavid du Colombier 			l = &nod2;
293*7dd7cddfSDavid du Colombier 		gopcode(o, l, n, r);
294*7dd7cddfSDavid du Colombier 		break;
295*7dd7cddfSDavid du Colombier 	default: /* op is shiftcount, number is r,l */
296*7dd7cddfSDavid du Colombier 		v = p[1] - '0';
297*7dd7cddfSDavid du Colombier 		r = &nod1;
298*7dd7cddfSDavid du Colombier 		if(v&2)
299*7dd7cddfSDavid du Colombier 			r = &nod2;
300*7dd7cddfSDavid du Colombier 		l = &nod1;
301*7dd7cddfSDavid du Colombier 		if(v&1)
302*7dd7cddfSDavid du Colombier 			l = &nod2;
303*7dd7cddfSDavid du Colombier 		v = *p - 'a';
304*7dd7cddfSDavid du Colombier 		if(v < 0 || v >= 32) {
305*7dd7cddfSDavid du Colombier 			diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
306*7dd7cddfSDavid du Colombier 			break;
307*7dd7cddfSDavid du Colombier 		}
308*7dd7cddfSDavid du Colombier 		gopcode(OASHL, nodconst(v), l, r);
309*7dd7cddfSDavid du Colombier 		break;
310*7dd7cddfSDavid du Colombier 	}
311*7dd7cddfSDavid du Colombier 	p += 2;
312*7dd7cddfSDavid du Colombier 	goto loop;
313*7dd7cddfSDavid du Colombier }
314*7dd7cddfSDavid du Colombier 
315*7dd7cddfSDavid du Colombier void
316*7dd7cddfSDavid du Colombier nullwarn(Node *l, Node *r)
317*7dd7cddfSDavid du Colombier {
318*7dd7cddfSDavid du Colombier 	warn(Z, "result of operation not used");
319*7dd7cddfSDavid du Colombier 	if(l != Z)
320*7dd7cddfSDavid du Colombier 		cgen(l, Z);
321*7dd7cddfSDavid du Colombier 	if(r != Z)
322*7dd7cddfSDavid du Colombier 		cgen(r, Z);
323*7dd7cddfSDavid du Colombier }
324*7dd7cddfSDavid du Colombier 
325*7dd7cddfSDavid du Colombier void
326*7dd7cddfSDavid du Colombier sextern(Sym *s, Node *a, long o, long w)
327*7dd7cddfSDavid du Colombier {
328*7dd7cddfSDavid du Colombier 	long e, lw;
329*7dd7cddfSDavid du Colombier 
330*7dd7cddfSDavid du Colombier 	for(e=0; e<w; e+=NSNAME) {
331*7dd7cddfSDavid du Colombier 		lw = NSNAME;
332*7dd7cddfSDavid du Colombier 		if(w-e < lw)
333*7dd7cddfSDavid du Colombier 			lw = w-e;
334*7dd7cddfSDavid du Colombier 		gpseudo(ADATA, s, nodconst(0));
335*7dd7cddfSDavid du Colombier 		p->from.offset += o+e;
336*7dd7cddfSDavid du Colombier 		p->reg = lw;
337*7dd7cddfSDavid du Colombier 		p->to.type = D_SCONST;
338*7dd7cddfSDavid du Colombier 		memmove(p->to.sval, a->cstring+e, lw);
339*7dd7cddfSDavid du Colombier 	}
340*7dd7cddfSDavid du Colombier }
341*7dd7cddfSDavid du Colombier 
342*7dd7cddfSDavid du Colombier void
343*7dd7cddfSDavid du Colombier gextern(Sym *s, Node *a, long o, long w)
344*7dd7cddfSDavid du Colombier {
345*7dd7cddfSDavid du Colombier 	if(a->op == OCONST && typev[a->type->etype]) {
346*7dd7cddfSDavid du Colombier 		gpseudo(ADATA, s, nod32const(a->vconst>>32));
347*7dd7cddfSDavid du Colombier 		p->from.offset += o;
348*7dd7cddfSDavid du Colombier 		p->reg = 4;
349*7dd7cddfSDavid du Colombier 		gpseudo(ADATA, s, nod32const(a->vconst));
350*7dd7cddfSDavid du Colombier 		p->from.offset += o + 4;
351*7dd7cddfSDavid du Colombier 		p->reg = 4;
352*7dd7cddfSDavid du Colombier 		return;
353*7dd7cddfSDavid du Colombier 	}
354*7dd7cddfSDavid du Colombier 	gpseudo(ADATA, s, a);
355*7dd7cddfSDavid du Colombier 	p->from.offset += o;
356*7dd7cddfSDavid du Colombier 	p->reg = w;
357*7dd7cddfSDavid du Colombier 	if(p->to.type == D_OREG)
358*7dd7cddfSDavid du Colombier 		p->to.type = D_CONST;
359*7dd7cddfSDavid du Colombier }
360*7dd7cddfSDavid du Colombier 
361*7dd7cddfSDavid du Colombier void	zname(Biobuf*, char*, int, int);
362*7dd7cddfSDavid du Colombier char*	zaddr(char*, Adr*, int);
363*7dd7cddfSDavid du Colombier void	zwrite(Biobuf*, Prog*, int, int);
364*7dd7cddfSDavid du Colombier void	outhist(Biobuf*);
365*7dd7cddfSDavid du Colombier 
366*7dd7cddfSDavid du Colombier void
367*7dd7cddfSDavid du Colombier outcode(void)
368*7dd7cddfSDavid du Colombier {
369*7dd7cddfSDavid du Colombier 	struct { Sym *sym; short type; } h[NSYM];
370*7dd7cddfSDavid du Colombier 	Prog *p;
371*7dd7cddfSDavid du Colombier 	Sym *s;
372*7dd7cddfSDavid du Colombier 	int sf, st, t, sym;
373*7dd7cddfSDavid du Colombier 
374*7dd7cddfSDavid du Colombier 	if(debug['S']) {
375*7dd7cddfSDavid du Colombier 		for(p = firstp; p != P; p = p->link)
376*7dd7cddfSDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
377*7dd7cddfSDavid du Colombier 				pc--;
378*7dd7cddfSDavid du Colombier 		for(p = firstp; p != P; p = p->link) {
379*7dd7cddfSDavid du Colombier 			print("%P\n", p);
380*7dd7cddfSDavid du Colombier 			if(p->as != ADATA && p->as != AGLOBL)
381*7dd7cddfSDavid du Colombier 				pc++;
382*7dd7cddfSDavid du Colombier 		}
383*7dd7cddfSDavid du Colombier 	}
384*7dd7cddfSDavid du Colombier 	outhist(&outbuf);
385*7dd7cddfSDavid du Colombier 	for(sym=0; sym<NSYM; sym++) {
386*7dd7cddfSDavid du Colombier 		h[sym].sym = S;
387*7dd7cddfSDavid du Colombier 		h[sym].type = 0;
388*7dd7cddfSDavid du Colombier 	}
389*7dd7cddfSDavid du Colombier 	sym = 1;
390*7dd7cddfSDavid du Colombier 	for(p = firstp; p != P; p = p->link) {
391*7dd7cddfSDavid du Colombier 	jackpot:
392*7dd7cddfSDavid du Colombier 		sf = 0;
393*7dd7cddfSDavid du Colombier 		s = p->from.sym;
394*7dd7cddfSDavid du Colombier 		while(s != S) {
395*7dd7cddfSDavid du Colombier 			sf = s->sym;
396*7dd7cddfSDavid du Colombier 			if(sf < 0 || sf >= NSYM)
397*7dd7cddfSDavid du Colombier 				sf = 0;
398*7dd7cddfSDavid du Colombier 			t = p->from.name;
399*7dd7cddfSDavid du Colombier 			if(h[sf].type == t)
400*7dd7cddfSDavid du Colombier 			if(h[sf].sym == s)
401*7dd7cddfSDavid du Colombier 				break;
402*7dd7cddfSDavid du Colombier 			zname(&outbuf, s->name, t, sym);
403*7dd7cddfSDavid du Colombier 			s->sym = sym;
404*7dd7cddfSDavid du Colombier 			h[sym].sym = s;
405*7dd7cddfSDavid du Colombier 			h[sym].type = t;
406*7dd7cddfSDavid du Colombier 			sf = sym;
407*7dd7cddfSDavid du Colombier 			sym++;
408*7dd7cddfSDavid du Colombier 			if(sym >= NSYM)
409*7dd7cddfSDavid du Colombier 				sym = 1;
410*7dd7cddfSDavid du Colombier 			break;
411*7dd7cddfSDavid du Colombier 		}
412*7dd7cddfSDavid du Colombier 		st = 0;
413*7dd7cddfSDavid du Colombier 		s = p->to.sym;
414*7dd7cddfSDavid du Colombier 		while(s != S) {
415*7dd7cddfSDavid du Colombier 			st = s->sym;
416*7dd7cddfSDavid du Colombier 			if(st < 0 || st >= NSYM)
417*7dd7cddfSDavid du Colombier 				st = 0;
418*7dd7cddfSDavid du Colombier 			t = p->to.name;
419*7dd7cddfSDavid du Colombier 			if(h[st].type == t)
420*7dd7cddfSDavid du Colombier 			if(h[st].sym == s)
421*7dd7cddfSDavid du Colombier 				break;
422*7dd7cddfSDavid du Colombier 			zname(&outbuf, s->name, t, sym);
423*7dd7cddfSDavid du Colombier 			s->sym = sym;
424*7dd7cddfSDavid du Colombier 			h[sym].sym = s;
425*7dd7cddfSDavid du Colombier 			h[sym].type = t;
426*7dd7cddfSDavid du Colombier 			st = sym;
427*7dd7cddfSDavid du Colombier 			sym++;
428*7dd7cddfSDavid du Colombier 			if(sym >= NSYM)
429*7dd7cddfSDavid du Colombier 				sym = 1;
430*7dd7cddfSDavid du Colombier 			if(st == sf)
431*7dd7cddfSDavid du Colombier 				goto jackpot;
432*7dd7cddfSDavid du Colombier 			break;
433*7dd7cddfSDavid du Colombier 		}
434*7dd7cddfSDavid du Colombier 		zwrite(&outbuf, p, sf, st);
435*7dd7cddfSDavid du Colombier 	}
436*7dd7cddfSDavid du Colombier 	firstp = P;
437*7dd7cddfSDavid du Colombier 	lastp = P;
438*7dd7cddfSDavid du Colombier }
439*7dd7cddfSDavid du Colombier 
440*7dd7cddfSDavid du Colombier void
441*7dd7cddfSDavid du Colombier zwrite(Biobuf *b, Prog *p, int sf, int st)
442*7dd7cddfSDavid du Colombier {
443*7dd7cddfSDavid du Colombier 	char bf[100], *bp;
444*7dd7cddfSDavid du Colombier 	long l;
445*7dd7cddfSDavid du Colombier 
446*7dd7cddfSDavid du Colombier 	bf[0] = p->as;
447*7dd7cddfSDavid du Colombier 	bf[1] = p->reg;
448*7dd7cddfSDavid du Colombier 	l = p->lineno;
449*7dd7cddfSDavid du Colombier 	bf[2] = l;
450*7dd7cddfSDavid du Colombier 	bf[3] = l>>8;
451*7dd7cddfSDavid du Colombier 	bf[4] = l>>16;
452*7dd7cddfSDavid du Colombier 	bf[5] = l>>24;
453*7dd7cddfSDavid du Colombier 	bp = zaddr(bf+6, &p->from, sf);
454*7dd7cddfSDavid du Colombier 	bp = zaddr(bp, &p->to, st);
455*7dd7cddfSDavid du Colombier 	Bwrite(b, bf, bp-bf);
456*7dd7cddfSDavid du Colombier }
457*7dd7cddfSDavid du Colombier 
458*7dd7cddfSDavid du Colombier void
459*7dd7cddfSDavid du Colombier outhist(Biobuf *b)
460*7dd7cddfSDavid du Colombier {
461*7dd7cddfSDavid du Colombier 	Hist *h;
462*7dd7cddfSDavid du Colombier 	char *p, *q, *op;
463*7dd7cddfSDavid du Colombier 	Prog pg;
464*7dd7cddfSDavid du Colombier 	int n;
465*7dd7cddfSDavid du Colombier 
466*7dd7cddfSDavid du Colombier 	pg = zprog;
467*7dd7cddfSDavid du Colombier 	pg.as = AHISTORY;
468*7dd7cddfSDavid du Colombier 	for(h = hist; h != H; h = h->link) {
469*7dd7cddfSDavid du Colombier 		p = h->name;
470*7dd7cddfSDavid du Colombier 		op = 0;
471*7dd7cddfSDavid du Colombier 		if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
472*7dd7cddfSDavid du Colombier 			op = p;
473*7dd7cddfSDavid du Colombier 			p = pathname;
474*7dd7cddfSDavid du Colombier 		}
475*7dd7cddfSDavid du Colombier 		while(p) {
476*7dd7cddfSDavid du Colombier 			q = utfrune(p, '/');
477*7dd7cddfSDavid du Colombier 			if(q) {
478*7dd7cddfSDavid du Colombier 				n = q-p;
479*7dd7cddfSDavid du Colombier 				if(n == 0)
480*7dd7cddfSDavid du Colombier 					n = 1;	/* leading "/" */
481*7dd7cddfSDavid du Colombier 				q++;
482*7dd7cddfSDavid du Colombier 			} else {
483*7dd7cddfSDavid du Colombier 				n = strlen(p);
484*7dd7cddfSDavid du Colombier 				q = 0;
485*7dd7cddfSDavid du Colombier 			}
486*7dd7cddfSDavid du Colombier 			if(n) {
487*7dd7cddfSDavid du Colombier 				Bputc(b, ANAME);
488*7dd7cddfSDavid du Colombier 				Bputc(b, D_FILE);
489*7dd7cddfSDavid du Colombier 				Bputc(b, 1);
490*7dd7cddfSDavid du Colombier 				Bputc(b, '<');
491*7dd7cddfSDavid du Colombier 				Bwrite(b, p, n);
492*7dd7cddfSDavid du Colombier 				Bputc(b, 0);
493*7dd7cddfSDavid du Colombier 			}
494*7dd7cddfSDavid du Colombier 			p = q;
495*7dd7cddfSDavid du Colombier 			if(p == 0 && op) {
496*7dd7cddfSDavid du Colombier 				p = op;
497*7dd7cddfSDavid du Colombier 				op = 0;
498*7dd7cddfSDavid du Colombier 			}
499*7dd7cddfSDavid du Colombier 		}
500*7dd7cddfSDavid du Colombier 		pg.lineno = h->line;
501*7dd7cddfSDavid du Colombier 		pg.to.type = zprog.to.type;
502*7dd7cddfSDavid du Colombier 		pg.to.offset = h->offset;
503*7dd7cddfSDavid du Colombier 		if(h->offset)
504*7dd7cddfSDavid du Colombier 			pg.to.type = D_CONST;
505*7dd7cddfSDavid du Colombier 
506*7dd7cddfSDavid du Colombier 		zwrite(b, &pg, 0, 0);
507*7dd7cddfSDavid du Colombier 	}
508*7dd7cddfSDavid du Colombier }
509*7dd7cddfSDavid du Colombier 
510*7dd7cddfSDavid du Colombier void
511*7dd7cddfSDavid du Colombier zname(Biobuf *b, char *n, int t, int s)
512*7dd7cddfSDavid du Colombier {
513*7dd7cddfSDavid du Colombier 	char bf[3];
514*7dd7cddfSDavid du Colombier 
515*7dd7cddfSDavid du Colombier 	bf[0] = ANAME;
516*7dd7cddfSDavid du Colombier 	bf[1] = t;	/* type */
517*7dd7cddfSDavid du Colombier 	bf[2] = s;	/* sym */
518*7dd7cddfSDavid du Colombier 	Bwrite(b, bf, 3);
519*7dd7cddfSDavid du Colombier 	Bwrite(b, n, strlen(n)+1);
520*7dd7cddfSDavid du Colombier }
521*7dd7cddfSDavid du Colombier 
522*7dd7cddfSDavid du Colombier char*
523*7dd7cddfSDavid du Colombier zaddr(char *bp, Adr *a, int s)
524*7dd7cddfSDavid du Colombier {
525*7dd7cddfSDavid du Colombier 	long l;
526*7dd7cddfSDavid du Colombier 	Ieee e;
527*7dd7cddfSDavid du Colombier 
528*7dd7cddfSDavid du Colombier 	bp[0] = a->type;
529*7dd7cddfSDavid du Colombier 	bp[1] = a->reg;
530*7dd7cddfSDavid du Colombier 	bp[2] = s;
531*7dd7cddfSDavid du Colombier 	bp[3] = a->name;
532*7dd7cddfSDavid du Colombier 	bp += 4;
533*7dd7cddfSDavid du Colombier 	switch(a->type) {
534*7dd7cddfSDavid du Colombier 	default:
535*7dd7cddfSDavid du Colombier 		diag(Z, "unknown type %d in zaddr", a->type);
536*7dd7cddfSDavid du Colombier 
537*7dd7cddfSDavid du Colombier 	case D_NONE:
538*7dd7cddfSDavid du Colombier 	case D_REG:
539*7dd7cddfSDavid du Colombier 	case D_FREG:
540*7dd7cddfSDavid du Colombier 	case D_CREG:
541*7dd7cddfSDavid du Colombier 		break;
542*7dd7cddfSDavid du Colombier 
543*7dd7cddfSDavid du Colombier 	case D_OREG:
544*7dd7cddfSDavid du Colombier 	case D_CONST:
545*7dd7cddfSDavid du Colombier 	case D_BRANCH:
546*7dd7cddfSDavid du Colombier 		l = a->offset;
547*7dd7cddfSDavid du Colombier 		bp[0] = l;
548*7dd7cddfSDavid du Colombier 		bp[1] = l>>8;
549*7dd7cddfSDavid du Colombier 		bp[2] = l>>16;
550*7dd7cddfSDavid du Colombier 		bp[3] = l>>24;
551*7dd7cddfSDavid du Colombier 		bp += 4;
552*7dd7cddfSDavid du Colombier 		break;
553*7dd7cddfSDavid du Colombier 
554*7dd7cddfSDavid du Colombier 	case D_SCONST:
555*7dd7cddfSDavid du Colombier 		memmove(bp, a->sval, NSNAME);
556*7dd7cddfSDavid du Colombier 		bp += NSNAME;
557*7dd7cddfSDavid du Colombier 		break;
558*7dd7cddfSDavid du Colombier 
559*7dd7cddfSDavid du Colombier 	case D_FCONST:
560*7dd7cddfSDavid du Colombier 		ieeedtod(&e, a->dval);
561*7dd7cddfSDavid du Colombier 		l = e.l;
562*7dd7cddfSDavid du Colombier 		bp[0] = l;
563*7dd7cddfSDavid du Colombier 		bp[1] = l>>8;
564*7dd7cddfSDavid du Colombier 		bp[2] = l>>16;
565*7dd7cddfSDavid du Colombier 		bp[3] = l>>24;
566*7dd7cddfSDavid du Colombier 		bp += 4;
567*7dd7cddfSDavid du Colombier 		l = e.h;
568*7dd7cddfSDavid du Colombier 		bp[0] = l;
569*7dd7cddfSDavid du Colombier 		bp[1] = l>>8;
570*7dd7cddfSDavid du Colombier 		bp[2] = l>>16;
571*7dd7cddfSDavid du Colombier 		bp[3] = l>>24;
572*7dd7cddfSDavid du Colombier 		bp += 4;
573*7dd7cddfSDavid du Colombier 		break;
574*7dd7cddfSDavid du Colombier 	}
575*7dd7cddfSDavid du Colombier 	return bp;
576*7dd7cddfSDavid du Colombier }
577*7dd7cddfSDavid du Colombier 
578*7dd7cddfSDavid du Colombier void
579*7dd7cddfSDavid du Colombier ieeedtod(Ieee *ieee, double native)
580*7dd7cddfSDavid du Colombier {
581*7dd7cddfSDavid du Colombier 	double fr, ho, f;
582*7dd7cddfSDavid du Colombier 	int exp;
583*7dd7cddfSDavid du Colombier 
584*7dd7cddfSDavid du Colombier 	if(native < 0) {
585*7dd7cddfSDavid du Colombier 		ieeedtod(ieee, -native);
586*7dd7cddfSDavid du Colombier 		ieee->h |= 0x80000000L;
587*7dd7cddfSDavid du Colombier 		return;
588*7dd7cddfSDavid du Colombier 	}
589*7dd7cddfSDavid du Colombier 	if(native == 0) {
590*7dd7cddfSDavid du Colombier 		ieee->l = 0;
591*7dd7cddfSDavid du Colombier 		ieee->h = 0;
592*7dd7cddfSDavid du Colombier 		return;
593*7dd7cddfSDavid du Colombier 	}
594*7dd7cddfSDavid du Colombier 	fr = frexp(native, &exp);
595*7dd7cddfSDavid du Colombier 	f = 2097152L;		/* shouldnt use fp constants here */
596*7dd7cddfSDavid du Colombier 	fr = modf(fr*f, &ho);
597*7dd7cddfSDavid du Colombier 	ieee->h = ho;
598*7dd7cddfSDavid du Colombier 	ieee->h &= 0xfffffL;
599*7dd7cddfSDavid du Colombier 	ieee->h |= (exp+1022L) << 20;
600*7dd7cddfSDavid du Colombier 	f = 65536L;
601*7dd7cddfSDavid du Colombier 	fr = modf(fr*f, &ho);
602*7dd7cddfSDavid du Colombier 	ieee->l = ho;
603*7dd7cddfSDavid du Colombier 	ieee->l <<= 16;
604*7dd7cddfSDavid du Colombier 	ieee->l |= (long)(fr*f);
605*7dd7cddfSDavid du Colombier }
606*7dd7cddfSDavid du Colombier 
607*7dd7cddfSDavid du Colombier long
608*7dd7cddfSDavid du Colombier align(long i, Type *t, int op)
609*7dd7cddfSDavid du Colombier {
610*7dd7cddfSDavid du Colombier 	long o;
611*7dd7cddfSDavid du Colombier 	Type *v;
612*7dd7cddfSDavid du Colombier 	int w;
613*7dd7cddfSDavid du Colombier 
614*7dd7cddfSDavid du Colombier 	o = i;
615*7dd7cddfSDavid du Colombier 	w = 1;
616*7dd7cddfSDavid du Colombier 	switch(op) {
617*7dd7cddfSDavid du Colombier 	default:
618*7dd7cddfSDavid du Colombier 		diag(Z, "unknown align opcode %d", op);
619*7dd7cddfSDavid du Colombier 		break;
620*7dd7cddfSDavid du Colombier 
621*7dd7cddfSDavid du Colombier 	case Asu2:	/* padding at end of a struct */
622*7dd7cddfSDavid du Colombier 		w = SZ_LONG;
623*7dd7cddfSDavid du Colombier 		break;
624*7dd7cddfSDavid du Colombier 
625*7dd7cddfSDavid du Colombier 	case Ael1:	/* initial allign of struct element */
626*7dd7cddfSDavid du Colombier 		for(v=t; v->etype==TARRAY; v=v->link)
627*7dd7cddfSDavid du Colombier 			;
628*7dd7cddfSDavid du Colombier 		w = ewidth[v->etype];
629*7dd7cddfSDavid du Colombier 		if(w <= 0 || w >= SZ_LONG)
630*7dd7cddfSDavid du Colombier 			w = SZ_LONG;
631*7dd7cddfSDavid du Colombier 		break;
632*7dd7cddfSDavid du Colombier 
633*7dd7cddfSDavid du Colombier 	case Ael2:	/* width of a struct element */
634*7dd7cddfSDavid du Colombier 		o += t->width;
635*7dd7cddfSDavid du Colombier 		break;
636*7dd7cddfSDavid du Colombier 
637*7dd7cddfSDavid du Colombier 	case Aarg0:	/* initial passbyptr argument in arg list */
638*7dd7cddfSDavid du Colombier 		if(typesuv[t->etype]) {
639*7dd7cddfSDavid du Colombier 			o = align(o, types[TIND], Aarg1);
640*7dd7cddfSDavid du Colombier 			o = align(o, types[TIND], Aarg2);
641*7dd7cddfSDavid du Colombier 		}
642*7dd7cddfSDavid du Colombier 		break;
643*7dd7cddfSDavid du Colombier 
644*7dd7cddfSDavid du Colombier 	case Aarg1:	/* initial allign of parameter */
645*7dd7cddfSDavid du Colombier 		w = ewidth[t->etype];
646*7dd7cddfSDavid du Colombier 		if(w <= 0 || w >= SZ_LONG) {
647*7dd7cddfSDavid du Colombier 			w = SZ_LONG;
648*7dd7cddfSDavid du Colombier 			break;
649*7dd7cddfSDavid du Colombier 		}
650*7dd7cddfSDavid du Colombier 		o += SZ_LONG - w;	/* big endian adjustment */
651*7dd7cddfSDavid du Colombier 		w = 1;
652*7dd7cddfSDavid du Colombier 		break;
653*7dd7cddfSDavid du Colombier 
654*7dd7cddfSDavid du Colombier 	case Aarg2:	/* width of a parameter */
655*7dd7cddfSDavid du Colombier 		o += t->width;
656*7dd7cddfSDavid du Colombier 		w = SZ_LONG;
657*7dd7cddfSDavid du Colombier 		break;
658*7dd7cddfSDavid du Colombier 
659*7dd7cddfSDavid du Colombier 	case Aaut3:	/* total allign of automatic */
660*7dd7cddfSDavid du Colombier 		o = align(o, t, Ael1);
661*7dd7cddfSDavid du Colombier 		o = align(o, t, Ael2);
662*7dd7cddfSDavid du Colombier 		break;
663*7dd7cddfSDavid du Colombier 	}
664*7dd7cddfSDavid du Colombier 	o = round(o, w);
665*7dd7cddfSDavid du Colombier 	if(debug['A'])
666*7dd7cddfSDavid du Colombier 		print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
667*7dd7cddfSDavid du Colombier 	return o;
668*7dd7cddfSDavid du Colombier }
669*7dd7cddfSDavid du Colombier 
670*7dd7cddfSDavid du Colombier long
671*7dd7cddfSDavid du Colombier maxround(long max, long v)
672*7dd7cddfSDavid du Colombier {
673*7dd7cddfSDavid du Colombier 	v += SZ_LONG-1;
674*7dd7cddfSDavid du Colombier 	if(v > max)
675*7dd7cddfSDavid du Colombier 		max = round(v, SZ_LONG);
676*7dd7cddfSDavid du Colombier 	return max;
677*7dd7cddfSDavid du Colombier }
678