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