xref: /plan9-contrib/sys/src/cmd/vl/sched.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier #include	"l.h"
2*219b2ee8SDavid du Colombier 
3*219b2ee8SDavid du Colombier enum
4*219b2ee8SDavid du Colombier {
5*219b2ee8SDavid du Colombier 	E_HILO	= 1<<0,
6*219b2ee8SDavid du Colombier 	E_FCR	= 1<<1,
7*219b2ee8SDavid du Colombier 	E_MCR	= 1<<2,
8*219b2ee8SDavid du Colombier 	E_MEM	= 1<<3,
9*219b2ee8SDavid du Colombier 	E_MEMSP	= 1<<4,	/* uses offset and size */
10*219b2ee8SDavid du Colombier 	E_MEMSB	= 1<<5,	/* uses offset and size */
11*219b2ee8SDavid du Colombier 	ANYMEM	= E_MEM|E_MEMSP|E_MEMSB,
12*219b2ee8SDavid du Colombier 	DELAY	= BRANCH|LOAD|FCMP,
13*219b2ee8SDavid du Colombier };
14*219b2ee8SDavid du Colombier 
15*219b2ee8SDavid du Colombier typedef	struct	Sch	Sch;
16*219b2ee8SDavid du Colombier typedef	struct	Dep	Dep;
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier struct	Dep
19*219b2ee8SDavid du Colombier {
20*219b2ee8SDavid du Colombier 	ulong	ireg;
21*219b2ee8SDavid du Colombier 	ulong	freg;
22*219b2ee8SDavid du Colombier 	ulong	cc;
23*219b2ee8SDavid du Colombier };
24*219b2ee8SDavid du Colombier struct	Sch
25*219b2ee8SDavid du Colombier {
26*219b2ee8SDavid du Colombier 	Prog	p;
27*219b2ee8SDavid du Colombier 	Dep	set;
28*219b2ee8SDavid du Colombier 	Dep	used;
29*219b2ee8SDavid du Colombier 	long	offset;
30*219b2ee8SDavid du Colombier 	char	size;
31*219b2ee8SDavid du Colombier 	char	nop;
32*219b2ee8SDavid du Colombier 	char	comp;
33*219b2ee8SDavid du Colombier };
34*219b2ee8SDavid du Colombier 
35*219b2ee8SDavid du Colombier void	regused(Sch*, Prog*);
36*219b2ee8SDavid du Colombier int	depend(Sch*, Sch*);
37*219b2ee8SDavid du Colombier int	conflict(Sch*, Sch*);
38*219b2ee8SDavid du Colombier int	offoverlap(Sch*, Sch*);
39*219b2ee8SDavid du Colombier void	dumpbits(Sch*, Dep*);
40*219b2ee8SDavid du Colombier 
41*219b2ee8SDavid du Colombier void
42*219b2ee8SDavid du Colombier sched(Prog *p0, Prog *pe)
43*219b2ee8SDavid du Colombier {
44*219b2ee8SDavid du Colombier 	Prog *p, *q;
45*219b2ee8SDavid du Colombier 	Sch sch[NSCHED], *s, *t, *u, *se, stmp;
46*219b2ee8SDavid du Colombier 
47*219b2ee8SDavid du Colombier 	/*
48*219b2ee8SDavid du Colombier 	 * build side structure
49*219b2ee8SDavid du Colombier 	 */
50*219b2ee8SDavid du Colombier 	s = sch;
51*219b2ee8SDavid du Colombier 	for(p=p0;; p=p->link) {
52*219b2ee8SDavid du Colombier 		memset(s, 0, sizeof(*s));
53*219b2ee8SDavid du Colombier 		s->p = *p;
54*219b2ee8SDavid du Colombier 		regused(s, p);
55*219b2ee8SDavid du Colombier 		if(debug['X']) {
56*219b2ee8SDavid du Colombier 			Bprint(&bso, "%P%|set", &s->p, 40);
57*219b2ee8SDavid du Colombier 			dumpbits(s, &s->set);
58*219b2ee8SDavid du Colombier 			Bprint(&bso, "; used");
59*219b2ee8SDavid du Colombier 			dumpbits(s, &s->used);
60*219b2ee8SDavid du Colombier 			if(s->comp)
61*219b2ee8SDavid du Colombier 				Bprint(&bso, "; compound");
62*219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD)
63*219b2ee8SDavid du Colombier 				Bprint(&bso, "; load");
64*219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH)
65*219b2ee8SDavid du Colombier 				Bprint(&bso, "; branch");
66*219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP)
67*219b2ee8SDavid du Colombier 				Bprint(&bso, "; fcmp");
68*219b2ee8SDavid du Colombier 			Bprint(&bso, "\n");
69*219b2ee8SDavid du Colombier 		}
70*219b2ee8SDavid du Colombier 		if(p == pe)
71*219b2ee8SDavid du Colombier 			break;
72*219b2ee8SDavid du Colombier 		s++;
73*219b2ee8SDavid du Colombier 	}
74*219b2ee8SDavid du Colombier 	se = s;
75*219b2ee8SDavid du Colombier 
76*219b2ee8SDavid du Colombier 	/*
77*219b2ee8SDavid du Colombier 	 * prepass to move things around
78*219b2ee8SDavid du Colombier 	 * does nothing, but tries to make
79*219b2ee8SDavid du Colombier 	 * the actual scheduler work better
80*219b2ee8SDavid du Colombier 	 */
81*219b2ee8SDavid du Colombier 	for(s=sch; s<=se; s++) {
82*219b2ee8SDavid du Colombier 		if(!(s->p.mark & LOAD))
83*219b2ee8SDavid du Colombier 			continue;
84*219b2ee8SDavid du Colombier 		/* always good to put nonconflict loads together */
85*219b2ee8SDavid du Colombier 		for(t=s+1; t<=se; t++) {
86*219b2ee8SDavid du Colombier 			if(!(t->p.mark & LOAD))
87*219b2ee8SDavid du Colombier 				continue;
88*219b2ee8SDavid du Colombier 			if(t->p.mark & BRANCH)
89*219b2ee8SDavid du Colombier 				break;
90*219b2ee8SDavid du Colombier 			if(conflict(s, t))
91*219b2ee8SDavid du Colombier 				break;
92*219b2ee8SDavid du Colombier 			for(u=t-1; u>s; u--)
93*219b2ee8SDavid du Colombier 				if(depend(u, t))
94*219b2ee8SDavid du Colombier 					goto no11;
95*219b2ee8SDavid du Colombier 			u = s+1;
96*219b2ee8SDavid du Colombier 			stmp = *t;
97*219b2ee8SDavid du Colombier 			memmove(s+2, u, (uchar*)t - (uchar*)u);
98*219b2ee8SDavid du Colombier 			*u = stmp;
99*219b2ee8SDavid du Colombier 			break;
100*219b2ee8SDavid du Colombier 		}
101*219b2ee8SDavid du Colombier 	no11:
102*219b2ee8SDavid du Colombier 
103*219b2ee8SDavid du Colombier 		/* put schedule fodder above load */
104*219b2ee8SDavid du Colombier 		for(t=s+1; t<=se; t++) {
105*219b2ee8SDavid du Colombier 			if(t->p.mark & BRANCH)
106*219b2ee8SDavid du Colombier 				break;
107*219b2ee8SDavid du Colombier 			if(s > sch && conflict(s-1, t))
108*219b2ee8SDavid du Colombier 				continue;
109*219b2ee8SDavid du Colombier 			for(u=t-1; u>=s; u--)
110*219b2ee8SDavid du Colombier 				if(depend(t, u))
111*219b2ee8SDavid du Colombier 					goto no1;
112*219b2ee8SDavid du Colombier 			stmp = *t;
113*219b2ee8SDavid du Colombier 			memmove(s+1, s, (uchar*)t - (uchar*)s);
114*219b2ee8SDavid du Colombier 			*s = stmp;
115*219b2ee8SDavid du Colombier 			if(!(s->p.mark & LOAD))
116*219b2ee8SDavid du Colombier 				break;
117*219b2ee8SDavid du Colombier 		no1:;
118*219b2ee8SDavid du Colombier 		}
119*219b2ee8SDavid du Colombier 	no12:;
120*219b2ee8SDavid du Colombier 	}
121*219b2ee8SDavid du Colombier 
122*219b2ee8SDavid du Colombier 	for(s=se; s>=sch; s--) {
123*219b2ee8SDavid du Colombier 		if(!(s->p.mark & DELAY))
124*219b2ee8SDavid du Colombier 			continue;
125*219b2ee8SDavid du Colombier 		if(s < se)
126*219b2ee8SDavid du Colombier 			if(!conflict(s, s+1))
127*219b2ee8SDavid du Colombier 				goto out3;
128*219b2ee8SDavid du Colombier 		/*
129*219b2ee8SDavid du Colombier 		 * s is load, s+1 is immediate use of result or end of block
130*219b2ee8SDavid du Colombier 		 * t is the trial instruction to insert between s and s+1
131*219b2ee8SDavid du Colombier 		 */
132*219b2ee8SDavid du Colombier 		if(!debug['Y'])
133*219b2ee8SDavid du Colombier 		for(t=s-1; t>=sch; t--) {
134*219b2ee8SDavid du Colombier 			if(t->comp)
135*219b2ee8SDavid du Colombier 				if(s->p.mark & BRANCH)
136*219b2ee8SDavid du Colombier 					goto no2;
137*219b2ee8SDavid du Colombier 			if(t->p.mark & DELAY)
138*219b2ee8SDavid du Colombier 				if(s >= se || conflict(t, s+1))
139*219b2ee8SDavid du Colombier 					goto no2;
140*219b2ee8SDavid du Colombier 			for(u=t+1; u<=s; u++)
141*219b2ee8SDavid du Colombier 				if(depend(u, t))
142*219b2ee8SDavid du Colombier 					goto no2;
143*219b2ee8SDavid du Colombier 			goto out2;
144*219b2ee8SDavid du Colombier 		no2:;
145*219b2ee8SDavid du Colombier 		}
146*219b2ee8SDavid du Colombier 		if(debug['X'])
147*219b2ee8SDavid du Colombier 			Bprint(&bso, "?l%P\n", &s->p);
148*219b2ee8SDavid du Colombier 		s->nop = 1;
149*219b2ee8SDavid du Colombier 		if(debug['v']) {
150*219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD) {
151*219b2ee8SDavid du Colombier 				nop.load.count++;
152*219b2ee8SDavid du Colombier 				nop.load.outof++;
153*219b2ee8SDavid du Colombier 			}
154*219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH) {
155*219b2ee8SDavid du Colombier 				nop.branch.count++;
156*219b2ee8SDavid du Colombier 				nop.branch.outof++;
157*219b2ee8SDavid du Colombier 			}
158*219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP) {
159*219b2ee8SDavid du Colombier 				nop.fcmp.count++;
160*219b2ee8SDavid du Colombier 				nop.fcmp.outof++;
161*219b2ee8SDavid du Colombier 			}
162*219b2ee8SDavid du Colombier 		}
163*219b2ee8SDavid du Colombier 		continue;
164*219b2ee8SDavid du Colombier 
165*219b2ee8SDavid du Colombier 	out2:
166*219b2ee8SDavid du Colombier 		if(debug['X']) {
167*219b2ee8SDavid du Colombier 			Bprint(&bso, "!l%P\n", &t->p);
168*219b2ee8SDavid du Colombier 			Bprint(&bso, "%P\n", &s->p);
169*219b2ee8SDavid du Colombier 		}
170*219b2ee8SDavid du Colombier 		stmp = *t;
171*219b2ee8SDavid du Colombier 		memmove(t, t+1, (uchar*)s - (uchar*)t);
172*219b2ee8SDavid du Colombier 		*s = stmp;
173*219b2ee8SDavid du Colombier 		s--;
174*219b2ee8SDavid du Colombier 
175*219b2ee8SDavid du Colombier 	out3:
176*219b2ee8SDavid du Colombier 		if(debug['v']) {
177*219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD)
178*219b2ee8SDavid du Colombier 				nop.load.outof++;
179*219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH)
180*219b2ee8SDavid du Colombier 				nop.branch.outof++;
181*219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP)
182*219b2ee8SDavid du Colombier 				nop.fcmp.outof++;
183*219b2ee8SDavid du Colombier 		}
184*219b2ee8SDavid du Colombier 	}
185*219b2ee8SDavid du Colombier 
186*219b2ee8SDavid du Colombier 	/* Avoid HI/LO use->set */
187*219b2ee8SDavid du Colombier 	t = sch+1;
188*219b2ee8SDavid du Colombier 	for(s=sch; s<se-1; s++, t++) {
189*219b2ee8SDavid du Colombier 		if((s->used.cc & E_HILO) == 0)
190*219b2ee8SDavid du Colombier 			continue;
191*219b2ee8SDavid du Colombier 		if(t->set.cc & E_HILO)
192*219b2ee8SDavid du Colombier 			s->nop = 2;
193*219b2ee8SDavid du Colombier 	}
194*219b2ee8SDavid du Colombier 
195*219b2ee8SDavid du Colombier 	/*
196*219b2ee8SDavid du Colombier 	 * put it all back
197*219b2ee8SDavid du Colombier 	 */
198*219b2ee8SDavid du Colombier 	for(s=sch, p=p0; s<=se; s++, p=q) {
199*219b2ee8SDavid du Colombier 		q = p->link;
200*219b2ee8SDavid du Colombier 		if(q != s->p.link) {
201*219b2ee8SDavid du Colombier 			*p = s->p;
202*219b2ee8SDavid du Colombier 			p->link = q;
203*219b2ee8SDavid du Colombier 		}
204*219b2ee8SDavid du Colombier 		while(s->nop--)
205*219b2ee8SDavid du Colombier 			addnop(p);
206*219b2ee8SDavid du Colombier 	}
207*219b2ee8SDavid du Colombier 	if(debug['X']) {
208*219b2ee8SDavid du Colombier 		Bprint(&bso, "\n");
209*219b2ee8SDavid du Colombier 		Bflush(&bso);
210*219b2ee8SDavid du Colombier 	}
211*219b2ee8SDavid du Colombier }
212*219b2ee8SDavid du Colombier 
213*219b2ee8SDavid du Colombier void
214*219b2ee8SDavid du Colombier regused(Sch *s, Prog *realp)
215*219b2ee8SDavid du Colombier {
216*219b2ee8SDavid du Colombier 	int c, ar, ad, ld, sz;
217*219b2ee8SDavid du Colombier 	ulong m;
218*219b2ee8SDavid du Colombier 	Prog *p;
219*219b2ee8SDavid du Colombier 
220*219b2ee8SDavid du Colombier 	p = &s->p;
221*219b2ee8SDavid du Colombier 	s->comp = compound(p);
222*219b2ee8SDavid du Colombier 	s->nop = 0;
223*219b2ee8SDavid du Colombier 	if(s->comp) {
224*219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<REGTMP;
225*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGTMP;
226*219b2ee8SDavid du Colombier 	}
227*219b2ee8SDavid du Colombier 
228*219b2ee8SDavid du Colombier 	ar = 0;		/* dest is really reference */
229*219b2ee8SDavid du Colombier 	ad = 0;		/* source/dest is really address */
230*219b2ee8SDavid du Colombier 	ld = 0;		/* opcode is load instruction */
231*219b2ee8SDavid du Colombier 	sz = 20;	/* size of load/store for overlap computation */
232*219b2ee8SDavid du Colombier 
233*219b2ee8SDavid du Colombier /*
234*219b2ee8SDavid du Colombier  * flags based on opcode
235*219b2ee8SDavid du Colombier  */
236*219b2ee8SDavid du Colombier 	switch(p->as) {
237*219b2ee8SDavid du Colombier 	case ATEXT:
238*219b2ee8SDavid du Colombier 		curtext = realp;
239*219b2ee8SDavid du Colombier 		autosize = p->to.offset + 4;
240*219b2ee8SDavid du Colombier 		ad = 1;
241*219b2ee8SDavid du Colombier 		break;
242*219b2ee8SDavid du Colombier 	case AJAL:
243*219b2ee8SDavid du Colombier 		c = p->reg;
244*219b2ee8SDavid du Colombier 		if(c == NREG)
245*219b2ee8SDavid du Colombier 			c = REGLINK;
246*219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<c;
247*219b2ee8SDavid du Colombier 		ar = 1;
248*219b2ee8SDavid du Colombier 		ad = 1;
249*219b2ee8SDavid du Colombier 		break;
250*219b2ee8SDavid du Colombier 	case ABGEZAL:
251*219b2ee8SDavid du Colombier 	case ABLTZAL:
252*219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<REGLINK;
253*219b2ee8SDavid du Colombier 	case ABEQ:
254*219b2ee8SDavid du Colombier 	case ABGEZ:
255*219b2ee8SDavid du Colombier 	case ABGTZ:
256*219b2ee8SDavid du Colombier 	case ABLEZ:
257*219b2ee8SDavid du Colombier 	case ABLTZ:
258*219b2ee8SDavid du Colombier 	case ABNE:
259*219b2ee8SDavid du Colombier 		ar = 1;
260*219b2ee8SDavid du Colombier 		ad = 1;
261*219b2ee8SDavid du Colombier 		break;
262*219b2ee8SDavid du Colombier 	case ABFPT:
263*219b2ee8SDavid du Colombier 	case ABFPF:
264*219b2ee8SDavid du Colombier 		ad = 1;
265*219b2ee8SDavid du Colombier 		s->used.cc |= E_FCR;
266*219b2ee8SDavid du Colombier 		break;
267*219b2ee8SDavid du Colombier 	case ACMPEQD:
268*219b2ee8SDavid du Colombier 	case ACMPEQF:
269*219b2ee8SDavid du Colombier 	case ACMPGED:
270*219b2ee8SDavid du Colombier 	case ACMPGEF:
271*219b2ee8SDavid du Colombier 	case ACMPGTD:
272*219b2ee8SDavid du Colombier 	case ACMPGTF:
273*219b2ee8SDavid du Colombier 		ar = 1;
274*219b2ee8SDavid du Colombier 		s->set.cc |= E_FCR;
275*219b2ee8SDavid du Colombier 		p->mark |= FCMP;
276*219b2ee8SDavid du Colombier 		break;
277*219b2ee8SDavid du Colombier 	case AJMP:
278*219b2ee8SDavid du Colombier 		ar = 1;
279*219b2ee8SDavid du Colombier 		ad = 1;
280*219b2ee8SDavid du Colombier 		break;
281*219b2ee8SDavid du Colombier 	case AMOVB:
282*219b2ee8SDavid du Colombier 	case AMOVBU:
283*219b2ee8SDavid du Colombier 		sz = 1;
284*219b2ee8SDavid du Colombier 		ld = 1;
285*219b2ee8SDavid du Colombier 		break;
286*219b2ee8SDavid du Colombier 	case AMOVH:
287*219b2ee8SDavid du Colombier 	case AMOVHU:
288*219b2ee8SDavid du Colombier 		sz = 2;
289*219b2ee8SDavid du Colombier 		ld = 1;
290*219b2ee8SDavid du Colombier 		break;
291*219b2ee8SDavid du Colombier 	case AMOVF:
292*219b2ee8SDavid du Colombier 	case AMOVW:
293*219b2ee8SDavid du Colombier 	case AMOVWL:
294*219b2ee8SDavid du Colombier 	case AMOVWR:
295*219b2ee8SDavid du Colombier 		sz = 4;
296*219b2ee8SDavid du Colombier 		ld = 1;
297*219b2ee8SDavid du Colombier 		break;
298*219b2ee8SDavid du Colombier 	case AMOVD:
299*219b2ee8SDavid du Colombier 	case AMOVV:
300*219b2ee8SDavid du Colombier 	case AMOVVL:
301*219b2ee8SDavid du Colombier 	case AMOVVR:
302*219b2ee8SDavid du Colombier 		sz = 8;
303*219b2ee8SDavid du Colombier 		ld = 1;
304*219b2ee8SDavid du Colombier 		break;
305*219b2ee8SDavid du Colombier 	case ADIV:
306*219b2ee8SDavid du Colombier 	case ADIVU:
307*219b2ee8SDavid du Colombier 	case AMUL:
308*219b2ee8SDavid du Colombier 	case AMULU:
309*219b2ee8SDavid du Colombier 	case AREM:
310*219b2ee8SDavid du Colombier 	case AREMU:
311*219b2ee8SDavid du Colombier 		s->set.cc = E_HILO;
312*219b2ee8SDavid du Colombier 	case AADD:
313*219b2ee8SDavid du Colombier 	case AADDU:
314*219b2ee8SDavid du Colombier 	case AAND:
315*219b2ee8SDavid du Colombier 	case ANOR:
316*219b2ee8SDavid du Colombier 	case AOR:
317*219b2ee8SDavid du Colombier 	case ASGT:
318*219b2ee8SDavid du Colombier 	case ASGTU:
319*219b2ee8SDavid du Colombier 	case ASLL:
320*219b2ee8SDavid du Colombier 	case ASRA:
321*219b2ee8SDavid du Colombier 	case ASRL:
322*219b2ee8SDavid du Colombier 	case ASUB:
323*219b2ee8SDavid du Colombier 	case ASUBU:
324*219b2ee8SDavid du Colombier 	case AXOR:
325*219b2ee8SDavid du Colombier 
326*219b2ee8SDavid du Colombier 	case AADDD:
327*219b2ee8SDavid du Colombier 	case AADDF:
328*219b2ee8SDavid du Colombier 	case AADDW:
329*219b2ee8SDavid du Colombier 	case ASUBD:
330*219b2ee8SDavid du Colombier 	case ASUBF:
331*219b2ee8SDavid du Colombier 	case ASUBW:
332*219b2ee8SDavid du Colombier 	case AMULF:
333*219b2ee8SDavid du Colombier 	case AMULD:
334*219b2ee8SDavid du Colombier 	case AMULW:
335*219b2ee8SDavid du Colombier 	case ADIVF:
336*219b2ee8SDavid du Colombier 	case ADIVD:
337*219b2ee8SDavid du Colombier 	case ADIVW:
338*219b2ee8SDavid du Colombier 		if(p->reg == NREG) {
339*219b2ee8SDavid du Colombier 			if(p->to.type == D_REG || p->to.type == D_FREG)
340*219b2ee8SDavid du Colombier 				p->reg = p->to.reg;
341*219b2ee8SDavid du Colombier 			if(p->reg == NREG)
342*219b2ee8SDavid du Colombier 				print("botch %P\n", p);
343*219b2ee8SDavid du Colombier 		}
344*219b2ee8SDavid du Colombier 		break;
345*219b2ee8SDavid du Colombier 	}
346*219b2ee8SDavid du Colombier 
347*219b2ee8SDavid du Colombier /*
348*219b2ee8SDavid du Colombier  * flags based on 'to' field
349*219b2ee8SDavid du Colombier  */
350*219b2ee8SDavid du Colombier 	c = p->to.class;
351*219b2ee8SDavid du Colombier 	if(c == 0) {
352*219b2ee8SDavid du Colombier 		c = aclass(&p->to) + 1;
353*219b2ee8SDavid du Colombier 		p->to.class = c;
354*219b2ee8SDavid du Colombier 	}
355*219b2ee8SDavid du Colombier 	c--;
356*219b2ee8SDavid du Colombier 	switch(c) {
357*219b2ee8SDavid du Colombier 	default:
358*219b2ee8SDavid du Colombier 		print("unknown class %d %D\n", c, &p->to);
359*219b2ee8SDavid du Colombier 
360*219b2ee8SDavid du Colombier 	case C_ZCON:
361*219b2ee8SDavid du Colombier 	case C_SCON:
362*219b2ee8SDavid du Colombier 	case C_ADD0CON:
363*219b2ee8SDavid du Colombier 	case C_AND0CON:
364*219b2ee8SDavid du Colombier 	case C_ADDCON:
365*219b2ee8SDavid du Colombier 	case C_ANDCON:
366*219b2ee8SDavid du Colombier 	case C_UCON:
367*219b2ee8SDavid du Colombier 	case C_LCON:
368*219b2ee8SDavid du Colombier 	case C_NONE:
369*219b2ee8SDavid du Colombier 	case C_SBRA:
370*219b2ee8SDavid du Colombier 	case C_LBRA:
371*219b2ee8SDavid du Colombier 		break;
372*219b2ee8SDavid du Colombier 
373*219b2ee8SDavid du Colombier 	case C_HI:
374*219b2ee8SDavid du Colombier 	case C_LO:
375*219b2ee8SDavid du Colombier 		s->set.cc |= E_HILO;
376*219b2ee8SDavid du Colombier 		break;
377*219b2ee8SDavid du Colombier 	case C_FCREG:
378*219b2ee8SDavid du Colombier 		s->set.cc |= E_FCR;
379*219b2ee8SDavid du Colombier 		break;
380*219b2ee8SDavid du Colombier 	case C_MREG:
381*219b2ee8SDavid du Colombier 		s->set.cc |= E_MCR;
382*219b2ee8SDavid du Colombier 		break;
383*219b2ee8SDavid du Colombier 	case C_ZOREG:
384*219b2ee8SDavid du Colombier 	case C_SOREG:
385*219b2ee8SDavid du Colombier 	case C_LOREG:
386*219b2ee8SDavid du Colombier 		c = p->to.reg;
387*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<c;
388*219b2ee8SDavid du Colombier 		if(ad)
389*219b2ee8SDavid du Colombier 			break;
390*219b2ee8SDavid du Colombier 		s->size = sz;
391*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->to);
392*219b2ee8SDavid du Colombier 
393*219b2ee8SDavid du Colombier 		m = ANYMEM;
394*219b2ee8SDavid du Colombier 		if(c == REGSB)
395*219b2ee8SDavid du Colombier 			m = E_MEMSB;
396*219b2ee8SDavid du Colombier 		if(c == REGSP)
397*219b2ee8SDavid du Colombier 			m = E_MEMSP;
398*219b2ee8SDavid du Colombier 
399*219b2ee8SDavid du Colombier 		if(ar)
400*219b2ee8SDavid du Colombier 			s->used.cc |= m;
401*219b2ee8SDavid du Colombier 		else
402*219b2ee8SDavid du Colombier 			s->set.cc |= m;
403*219b2ee8SDavid du Colombier 		break;
404*219b2ee8SDavid du Colombier 	case C_SACON:
405*219b2ee8SDavid du Colombier 	case C_LACON:
406*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
407*219b2ee8SDavid du Colombier 		break;
408*219b2ee8SDavid du Colombier 	case C_SECON:
409*219b2ee8SDavid du Colombier 	case C_LECON:
410*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
411*219b2ee8SDavid du Colombier 		break;
412*219b2ee8SDavid du Colombier 	case C_REG:
413*219b2ee8SDavid du Colombier 		if(ar)
414*219b2ee8SDavid du Colombier 			s->used.ireg |= 1<<p->to.reg;
415*219b2ee8SDavid du Colombier 		else
416*219b2ee8SDavid du Colombier 			s->set.ireg |= 1<<p->to.reg;
417*219b2ee8SDavid du Colombier 		break;
418*219b2ee8SDavid du Colombier 	case C_FREG:
419*219b2ee8SDavid du Colombier 		/* do better -- determine double prec */
420*219b2ee8SDavid du Colombier 		if(ar) {
421*219b2ee8SDavid du Colombier 			s->used.freg |= 1<<p->to.reg;
422*219b2ee8SDavid du Colombier 			s->used.freg |= 1<<(p->to.reg|1);
423*219b2ee8SDavid du Colombier 		} else {
424*219b2ee8SDavid du Colombier 			s->set.freg |= 1<<p->to.reg;
425*219b2ee8SDavid du Colombier 			s->set.freg |= 1<<(p->to.reg|1);
426*219b2ee8SDavid du Colombier 		}
427*219b2ee8SDavid du Colombier 		if(ld && p->from.type == D_REG)
428*219b2ee8SDavid du Colombier 			p->mark |= LOAD;
429*219b2ee8SDavid du Colombier 		break;
430*219b2ee8SDavid du Colombier 	case C_SAUTO:
431*219b2ee8SDavid du Colombier 	case C_LAUTO:
432*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
433*219b2ee8SDavid du Colombier 		if(ad)
434*219b2ee8SDavid du Colombier 			break;
435*219b2ee8SDavid du Colombier 		s->size = sz;
436*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->to);
437*219b2ee8SDavid du Colombier 
438*219b2ee8SDavid du Colombier 		if(ar)
439*219b2ee8SDavid du Colombier 			s->used.cc |= E_MEMSP;
440*219b2ee8SDavid du Colombier 		else
441*219b2ee8SDavid du Colombier 			s->set.cc |= E_MEMSP;
442*219b2ee8SDavid du Colombier 		break;
443*219b2ee8SDavid du Colombier 	case C_SEXT:
444*219b2ee8SDavid du Colombier 	case C_LEXT:
445*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
446*219b2ee8SDavid du Colombier 		if(ad)
447*219b2ee8SDavid du Colombier 			break;
448*219b2ee8SDavid du Colombier 		s->size = sz;
449*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->to);
450*219b2ee8SDavid du Colombier 
451*219b2ee8SDavid du Colombier 		if(ar)
452*219b2ee8SDavid du Colombier 			s->used.cc |= E_MEMSB;
453*219b2ee8SDavid du Colombier 		else
454*219b2ee8SDavid du Colombier 			s->set.cc |= E_MEMSB;
455*219b2ee8SDavid du Colombier 		break;
456*219b2ee8SDavid du Colombier 	}
457*219b2ee8SDavid du Colombier 
458*219b2ee8SDavid du Colombier /*
459*219b2ee8SDavid du Colombier  * flags based on 'from' field
460*219b2ee8SDavid du Colombier  */
461*219b2ee8SDavid du Colombier 	c = p->from.class;
462*219b2ee8SDavid du Colombier 	if(c == 0) {
463*219b2ee8SDavid du Colombier 		c = aclass(&p->from) + 1;
464*219b2ee8SDavid du Colombier 		p->from.class = c;
465*219b2ee8SDavid du Colombier 	}
466*219b2ee8SDavid du Colombier 	c--;
467*219b2ee8SDavid du Colombier 	switch(c) {
468*219b2ee8SDavid du Colombier 	default:
469*219b2ee8SDavid du Colombier 		print("unknown class %d %D\n", c, &p->from);
470*219b2ee8SDavid du Colombier 
471*219b2ee8SDavid du Colombier 	case C_ZCON:
472*219b2ee8SDavid du Colombier 	case C_SCON:
473*219b2ee8SDavid du Colombier 	case C_ADD0CON:
474*219b2ee8SDavid du Colombier 	case C_AND0CON:
475*219b2ee8SDavid du Colombier 	case C_ADDCON:
476*219b2ee8SDavid du Colombier 	case C_ANDCON:
477*219b2ee8SDavid du Colombier 	case C_UCON:
478*219b2ee8SDavid du Colombier 	case C_LCON:
479*219b2ee8SDavid du Colombier 	case C_NONE:
480*219b2ee8SDavid du Colombier 	case C_SBRA:
481*219b2ee8SDavid du Colombier 	case C_LBRA:
482*219b2ee8SDavid du Colombier 		break;
483*219b2ee8SDavid du Colombier 	case C_HI:
484*219b2ee8SDavid du Colombier 	case C_LO:
485*219b2ee8SDavid du Colombier 		s->used.cc |= E_HILO;
486*219b2ee8SDavid du Colombier 		break;
487*219b2ee8SDavid du Colombier 	case C_FCREG:
488*219b2ee8SDavid du Colombier 		s->used.cc |= E_FCR;
489*219b2ee8SDavid du Colombier 		break;
490*219b2ee8SDavid du Colombier 	case C_MREG:
491*219b2ee8SDavid du Colombier 		s->used.cc |= E_MCR;
492*219b2ee8SDavid du Colombier 		break;
493*219b2ee8SDavid du Colombier 	case C_ZOREG:
494*219b2ee8SDavid du Colombier 	case C_SOREG:
495*219b2ee8SDavid du Colombier 	case C_LOREG:
496*219b2ee8SDavid du Colombier 		c = p->from.reg;
497*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<c;
498*219b2ee8SDavid du Colombier 		if(ld)
499*219b2ee8SDavid du Colombier 			p->mark |= LOAD;
500*219b2ee8SDavid du Colombier 		s->size = sz;
501*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->from);
502*219b2ee8SDavid du Colombier 
503*219b2ee8SDavid du Colombier 		m = ANYMEM;
504*219b2ee8SDavid du Colombier 		if(c == REGSB)
505*219b2ee8SDavid du Colombier 			m = E_MEMSB;
506*219b2ee8SDavid du Colombier 		if(c == REGSP)
507*219b2ee8SDavid du Colombier 			m = E_MEMSP;
508*219b2ee8SDavid du Colombier 
509*219b2ee8SDavid du Colombier 		s->used.cc |= m;
510*219b2ee8SDavid du Colombier 		break;
511*219b2ee8SDavid du Colombier 	case C_SACON:
512*219b2ee8SDavid du Colombier 	case C_LACON:
513*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
514*219b2ee8SDavid du Colombier 		break;
515*219b2ee8SDavid du Colombier 	case C_SECON:
516*219b2ee8SDavid du Colombier 	case C_LECON:
517*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
518*219b2ee8SDavid du Colombier 		break;
519*219b2ee8SDavid du Colombier 	case C_REG:
520*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<p->from.reg;
521*219b2ee8SDavid du Colombier 		break;
522*219b2ee8SDavid du Colombier 	case C_FREG:
523*219b2ee8SDavid du Colombier 		/* do better -- determine double prec */
524*219b2ee8SDavid du Colombier 		s->used.freg |= 1<<p->from.reg;
525*219b2ee8SDavid du Colombier 		s->used.freg |= 1<<(p->from.reg|1);
526*219b2ee8SDavid du Colombier 		if(ld && p->to.type == D_REG)
527*219b2ee8SDavid du Colombier 			p->mark |= LOAD;
528*219b2ee8SDavid du Colombier 		break;
529*219b2ee8SDavid du Colombier 	case C_SAUTO:
530*219b2ee8SDavid du Colombier 	case C_LAUTO:
531*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
532*219b2ee8SDavid du Colombier 		if(ld)
533*219b2ee8SDavid du Colombier 			p->mark |= LOAD;
534*219b2ee8SDavid du Colombier 		if(ad)
535*219b2ee8SDavid du Colombier 			break;
536*219b2ee8SDavid du Colombier 		s->size = sz;
537*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->from);
538*219b2ee8SDavid du Colombier 
539*219b2ee8SDavid du Colombier 		s->used.cc |= E_MEMSP;
540*219b2ee8SDavid du Colombier 		break;
541*219b2ee8SDavid du Colombier 	case C_SEXT:
542*219b2ee8SDavid du Colombier 	case C_LEXT:
543*219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
544*219b2ee8SDavid du Colombier 		if(ld)
545*219b2ee8SDavid du Colombier 			p->mark |= LOAD;
546*219b2ee8SDavid du Colombier 		if(ad)
547*219b2ee8SDavid du Colombier 			break;
548*219b2ee8SDavid du Colombier 		s->size = sz;
549*219b2ee8SDavid du Colombier 		s->offset = regoff(&p->from);
550*219b2ee8SDavid du Colombier 
551*219b2ee8SDavid du Colombier 		s->used.cc |= E_MEMSB;
552*219b2ee8SDavid du Colombier 		break;
553*219b2ee8SDavid du Colombier 	}
554*219b2ee8SDavid du Colombier 
555*219b2ee8SDavid du Colombier 	c = p->reg;
556*219b2ee8SDavid du Colombier 	if(c != NREG) {
557*219b2ee8SDavid du Colombier 		if(p->from.type == D_FREG || p->to.type == D_FREG) {
558*219b2ee8SDavid du Colombier 			s->used.freg |= 1<<c;
559*219b2ee8SDavid du Colombier 			s->used.freg |= 1<<(c|1);
560*219b2ee8SDavid du Colombier 		} else
561*219b2ee8SDavid du Colombier 			s->used.ireg |= 1<<c;
562*219b2ee8SDavid du Colombier 	}
563*219b2ee8SDavid du Colombier 	s->set.ireg &= ~(1<<REGZERO);		/* R0 cant be set */
564*219b2ee8SDavid du Colombier }
565*219b2ee8SDavid du Colombier 
566*219b2ee8SDavid du Colombier /*
567*219b2ee8SDavid du Colombier  * test to see if 2 instrictions can be
568*219b2ee8SDavid du Colombier  * interchanged without changing semantics
569*219b2ee8SDavid du Colombier  */
570*219b2ee8SDavid du Colombier int
571*219b2ee8SDavid du Colombier depend(Sch *sa, Sch *sb)
572*219b2ee8SDavid du Colombier {
573*219b2ee8SDavid du Colombier 	ulong x;
574*219b2ee8SDavid du Colombier 
575*219b2ee8SDavid du Colombier 	if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
576*219b2ee8SDavid du Colombier 		return 1;
577*219b2ee8SDavid du Colombier 	if(sb->set.ireg & sa->used.ireg)
578*219b2ee8SDavid du Colombier 		return 1;
579*219b2ee8SDavid du Colombier 
580*219b2ee8SDavid du Colombier 	if(sa->set.freg & (sb->set.freg|sb->used.freg))
581*219b2ee8SDavid du Colombier 		return 1;
582*219b2ee8SDavid du Colombier 	if(sb->set.freg & sa->used.freg)
583*219b2ee8SDavid du Colombier 		return 1;
584*219b2ee8SDavid du Colombier 
585*219b2ee8SDavid du Colombier 	/*
586*219b2ee8SDavid du Colombier 	 * special case.
587*219b2ee8SDavid du Colombier 	 * loads from same address cannot pass.
588*219b2ee8SDavid du Colombier 	 * this is for hardware fifo's and the like
589*219b2ee8SDavid du Colombier 	 */
590*219b2ee8SDavid du Colombier 	if(sa->used.cc & sb->used.cc & E_MEM)
591*219b2ee8SDavid du Colombier 		if(sa->p.reg == sb->p.reg)
592*219b2ee8SDavid du Colombier 		if(regoff(&sa->p.from) == regoff(&sb->p.from))
593*219b2ee8SDavid du Colombier 			return 1;
594*219b2ee8SDavid du Colombier 
595*219b2ee8SDavid du Colombier 	x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
596*219b2ee8SDavid du Colombier 		(sb->set.cc & sa->used.cc);
597*219b2ee8SDavid du Colombier 	if(x) {
598*219b2ee8SDavid du Colombier 		/*
599*219b2ee8SDavid du Colombier 		 * allow SB and SP to pass each other.
600*219b2ee8SDavid du Colombier 		 * allow SB to pass SB iff doffsets are ok
601*219b2ee8SDavid du Colombier 		 * anything else conflicts
602*219b2ee8SDavid du Colombier 		 */
603*219b2ee8SDavid du Colombier 		if(x != E_MEMSP && x != E_MEMSB)
604*219b2ee8SDavid du Colombier 			return 1;
605*219b2ee8SDavid du Colombier 		x = sa->set.cc | sb->set.cc |
606*219b2ee8SDavid du Colombier 			sa->used.cc | sb->used.cc;
607*219b2ee8SDavid du Colombier 		if(x & E_MEM)
608*219b2ee8SDavid du Colombier 			return 1;
609*219b2ee8SDavid du Colombier 		if(offoverlap(sa, sb))
610*219b2ee8SDavid du Colombier 			return 1;
611*219b2ee8SDavid du Colombier 	}
612*219b2ee8SDavid du Colombier 
613*219b2ee8SDavid du Colombier 	return 0;
614*219b2ee8SDavid du Colombier }
615*219b2ee8SDavid du Colombier 
616*219b2ee8SDavid du Colombier int
617*219b2ee8SDavid du Colombier offoverlap(Sch *sa, Sch *sb)
618*219b2ee8SDavid du Colombier {
619*219b2ee8SDavid du Colombier 
620*219b2ee8SDavid du Colombier 	if(sa->offset < sb->offset) {
621*219b2ee8SDavid du Colombier 		if(sa->offset+sa->size > sb->offset)
622*219b2ee8SDavid du Colombier 			return 1;
623*219b2ee8SDavid du Colombier 		return 0;
624*219b2ee8SDavid du Colombier 	}
625*219b2ee8SDavid du Colombier 	if(sb->offset+sb->size > sa->offset)
626*219b2ee8SDavid du Colombier 		return 1;
627*219b2ee8SDavid du Colombier 	return 0;
628*219b2ee8SDavid du Colombier }
629*219b2ee8SDavid du Colombier 
630*219b2ee8SDavid du Colombier /*
631*219b2ee8SDavid du Colombier  * test 2 adjacent instructions
632*219b2ee8SDavid du Colombier  * and find out if inserted instructions
633*219b2ee8SDavid du Colombier  * are desired to prevent stalls.
634*219b2ee8SDavid du Colombier  */
635*219b2ee8SDavid du Colombier int
636*219b2ee8SDavid du Colombier conflict(Sch *sa, Sch *sb)
637*219b2ee8SDavid du Colombier {
638*219b2ee8SDavid du Colombier 
639*219b2ee8SDavid du Colombier 	if(sa->set.ireg & sb->used.ireg)
640*219b2ee8SDavid du Colombier 		return 1;
641*219b2ee8SDavid du Colombier 	if(sa->set.freg & sb->used.freg)
642*219b2ee8SDavid du Colombier 		return 1;
643*219b2ee8SDavid du Colombier 	if(sa->set.cc & sb->used.cc)
644*219b2ee8SDavid du Colombier 		return 1;
645*219b2ee8SDavid du Colombier 
646*219b2ee8SDavid du Colombier 	return 0;
647*219b2ee8SDavid du Colombier }
648*219b2ee8SDavid du Colombier 
649*219b2ee8SDavid du Colombier int
650*219b2ee8SDavid du Colombier compound(Prog *p)
651*219b2ee8SDavid du Colombier {
652*219b2ee8SDavid du Colombier 	Optab *o;
653*219b2ee8SDavid du Colombier 
654*219b2ee8SDavid du Colombier 	o = oplook(p);
655*219b2ee8SDavid du Colombier 	if(o->size != 4)
656*219b2ee8SDavid du Colombier 		return 1;
657*219b2ee8SDavid du Colombier 	if(p->to.type == D_REG && p->to.reg == REGSB)
658*219b2ee8SDavid du Colombier 		return 1;
659*219b2ee8SDavid du Colombier 	return 0;
660*219b2ee8SDavid du Colombier }
661*219b2ee8SDavid du Colombier 
662*219b2ee8SDavid du Colombier void
663*219b2ee8SDavid du Colombier dumpbits(Sch *s, Dep *d)
664*219b2ee8SDavid du Colombier {
665*219b2ee8SDavid du Colombier 	int i;
666*219b2ee8SDavid du Colombier 
667*219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
668*219b2ee8SDavid du Colombier 		if(d->ireg & (1<<i))
669*219b2ee8SDavid du Colombier 			Bprint(&bso, " R%d", i);
670*219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
671*219b2ee8SDavid du Colombier 		if(d->freg & (1<<i))
672*219b2ee8SDavid du Colombier 			Bprint(&bso, " F%d", i);
673*219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
674*219b2ee8SDavid du Colombier 		switch(d->cc & (1<<i)) {
675*219b2ee8SDavid du Colombier 		default:
676*219b2ee8SDavid du Colombier 			break;
677*219b2ee8SDavid du Colombier 		case E_HILO:
678*219b2ee8SDavid du Colombier 			Bprint(&bso, " HILO");
679*219b2ee8SDavid du Colombier 			break;
680*219b2ee8SDavid du Colombier 		case E_FCR:
681*219b2ee8SDavid du Colombier 			Bprint(&bso, " FCR");
682*219b2ee8SDavid du Colombier 			break;
683*219b2ee8SDavid du Colombier 		case E_MCR:
684*219b2ee8SDavid du Colombier 			Bprint(&bso, " MCR");
685*219b2ee8SDavid du Colombier 			break;
686*219b2ee8SDavid du Colombier 		case E_MEM:
687*219b2ee8SDavid du Colombier 			Bprint(&bso, " MEM%d", s->size);
688*219b2ee8SDavid du Colombier 			break;
689*219b2ee8SDavid du Colombier 		case E_MEMSB:
690*219b2ee8SDavid du Colombier 			Bprint(&bso, " SB%d", s->size);
691*219b2ee8SDavid du Colombier 			break;
692*219b2ee8SDavid du Colombier 		case E_MEMSP:
693*219b2ee8SDavid du Colombier 			Bprint(&bso, " SP%d", s->size);
694*219b2ee8SDavid du Colombier 			break;
695*219b2ee8SDavid du Colombier 		}
696*219b2ee8SDavid du Colombier }
697