xref: /plan9/sys/src/cmd/vl/sched.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1219b2ee8SDavid du Colombier #include	"l.h"
2219b2ee8SDavid du Colombier 
3219b2ee8SDavid du Colombier enum
4219b2ee8SDavid du Colombier {
5219b2ee8SDavid du Colombier 	E_HILO	= 1<<0,
6219b2ee8SDavid du Colombier 	E_FCR	= 1<<1,
7219b2ee8SDavid du Colombier 	E_MCR	= 1<<2,
8219b2ee8SDavid du Colombier 	E_MEM	= 1<<3,
9219b2ee8SDavid du Colombier 	E_MEMSP	= 1<<4,	/* uses offset and size */
10219b2ee8SDavid du Colombier 	E_MEMSB	= 1<<5,	/* uses offset and size */
11219b2ee8SDavid du Colombier 	ANYMEM	= E_MEM|E_MEMSP|E_MEMSB,
12219b2ee8SDavid du Colombier 	DELAY	= BRANCH|LOAD|FCMP,
13219b2ee8SDavid du Colombier };
14219b2ee8SDavid du Colombier 
15219b2ee8SDavid du Colombier typedef	struct	Sch	Sch;
16219b2ee8SDavid du Colombier typedef	struct	Dep	Dep;
17219b2ee8SDavid du Colombier 
18219b2ee8SDavid du Colombier struct	Dep
19219b2ee8SDavid du Colombier {
20219b2ee8SDavid du Colombier 	ulong	ireg;
21219b2ee8SDavid du Colombier 	ulong	freg;
22219b2ee8SDavid du Colombier 	ulong	cc;
23219b2ee8SDavid du Colombier };
24219b2ee8SDavid du Colombier struct	Sch
25219b2ee8SDavid du Colombier {
26219b2ee8SDavid du Colombier 	Prog	p;
27219b2ee8SDavid du Colombier 	Dep	set;
28219b2ee8SDavid du Colombier 	Dep	used;
297dd7cddfSDavid du Colombier 	long	soffset;
30219b2ee8SDavid du Colombier 	char	size;
31219b2ee8SDavid du Colombier 	char	nop;
32219b2ee8SDavid du Colombier 	char	comp;
33219b2ee8SDavid du Colombier };
34219b2ee8SDavid du Colombier 
357dd7cddfSDavid du Colombier void	regsused(Sch*, Prog*);
36219b2ee8SDavid du Colombier int	depend(Sch*, Sch*);
37219b2ee8SDavid du Colombier int	conflict(Sch*, Sch*);
38219b2ee8SDavid du Colombier int	offoverlap(Sch*, Sch*);
39219b2ee8SDavid du Colombier void	dumpbits(Sch*, Dep*);
40219b2ee8SDavid du Colombier 
41219b2ee8SDavid du Colombier void
sched(Prog * p0,Prog * pe)42219b2ee8SDavid du Colombier sched(Prog *p0, Prog *pe)
43219b2ee8SDavid du Colombier {
44219b2ee8SDavid du Colombier 	Prog *p, *q;
45219b2ee8SDavid du Colombier 	Sch sch[NSCHED], *s, *t, *u, *se, stmp;
46219b2ee8SDavid du Colombier 
47219b2ee8SDavid du Colombier 	/*
48219b2ee8SDavid du Colombier 	 * build side structure
49219b2ee8SDavid du Colombier 	 */
50219b2ee8SDavid du Colombier 	s = sch;
51219b2ee8SDavid du Colombier 	for(p=p0;; p=p->link) {
52219b2ee8SDavid du Colombier 		memset(s, 0, sizeof(*s));
53219b2ee8SDavid du Colombier 		s->p = *p;
547dd7cddfSDavid du Colombier 		regsused(s, p);
55219b2ee8SDavid du Colombier 		if(debug['X']) {
56*9a747e4fSDavid du Colombier 			Bprint(&bso, "%P\t\tset", &s->p);
57219b2ee8SDavid du Colombier 			dumpbits(s, &s->set);
58219b2ee8SDavid du Colombier 			Bprint(&bso, "; used");
59219b2ee8SDavid du Colombier 			dumpbits(s, &s->used);
60219b2ee8SDavid du Colombier 			if(s->comp)
61219b2ee8SDavid du Colombier 				Bprint(&bso, "; compound");
62219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD)
63219b2ee8SDavid du Colombier 				Bprint(&bso, "; load");
64219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH)
65219b2ee8SDavid du Colombier 				Bprint(&bso, "; branch");
66219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP)
67219b2ee8SDavid du Colombier 				Bprint(&bso, "; fcmp");
68219b2ee8SDavid du Colombier 			Bprint(&bso, "\n");
69219b2ee8SDavid du Colombier 		}
70219b2ee8SDavid du Colombier 		if(p == pe)
71219b2ee8SDavid du Colombier 			break;
72219b2ee8SDavid du Colombier 		s++;
73219b2ee8SDavid du Colombier 	}
74219b2ee8SDavid du Colombier 	se = s;
75219b2ee8SDavid du Colombier 
76219b2ee8SDavid du Colombier 	/*
77219b2ee8SDavid du Colombier 	 * prepass to move things around
78219b2ee8SDavid du Colombier 	 * does nothing, but tries to make
79219b2ee8SDavid du Colombier 	 * the actual scheduler work better
80219b2ee8SDavid du Colombier 	 */
81219b2ee8SDavid du Colombier 	for(s=sch; s<=se; s++) {
82219b2ee8SDavid du Colombier 		if(!(s->p.mark & LOAD))
83219b2ee8SDavid du Colombier 			continue;
84219b2ee8SDavid du Colombier 		/* always good to put nonconflict loads together */
85219b2ee8SDavid du Colombier 		for(t=s+1; t<=se; t++) {
86219b2ee8SDavid du Colombier 			if(!(t->p.mark & LOAD))
87219b2ee8SDavid du Colombier 				continue;
88219b2ee8SDavid du Colombier 			if(t->p.mark & BRANCH)
89219b2ee8SDavid du Colombier 				break;
90219b2ee8SDavid du Colombier 			if(conflict(s, t))
91219b2ee8SDavid du Colombier 				break;
92219b2ee8SDavid du Colombier 			for(u=t-1; u>s; u--)
93219b2ee8SDavid du Colombier 				if(depend(u, t))
94219b2ee8SDavid du Colombier 					goto no11;
95219b2ee8SDavid du Colombier 			u = s+1;
96219b2ee8SDavid du Colombier 			stmp = *t;
97219b2ee8SDavid du Colombier 			memmove(s+2, u, (uchar*)t - (uchar*)u);
98219b2ee8SDavid du Colombier 			*u = stmp;
99219b2ee8SDavid du Colombier 			break;
100219b2ee8SDavid du Colombier 		}
101219b2ee8SDavid du Colombier 	no11:
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier 		/* put schedule fodder above load */
104219b2ee8SDavid du Colombier 		for(t=s+1; t<=se; t++) {
105219b2ee8SDavid du Colombier 			if(t->p.mark & BRANCH)
106219b2ee8SDavid du Colombier 				break;
107219b2ee8SDavid du Colombier 			if(s > sch && conflict(s-1, t))
108219b2ee8SDavid du Colombier 				continue;
109219b2ee8SDavid du Colombier 			for(u=t-1; u>=s; u--)
110219b2ee8SDavid du Colombier 				if(depend(t, u))
111219b2ee8SDavid du Colombier 					goto no1;
112219b2ee8SDavid du Colombier 			stmp = *t;
113219b2ee8SDavid du Colombier 			memmove(s+1, s, (uchar*)t - (uchar*)s);
114219b2ee8SDavid du Colombier 			*s = stmp;
115219b2ee8SDavid du Colombier 			if(!(s->p.mark & LOAD))
116219b2ee8SDavid du Colombier 				break;
117219b2ee8SDavid du Colombier 		no1:;
118219b2ee8SDavid du Colombier 		}
119219b2ee8SDavid du Colombier 	}
120219b2ee8SDavid du Colombier 
121219b2ee8SDavid du Colombier 	for(s=se; s>=sch; s--) {
122219b2ee8SDavid du Colombier 		if(!(s->p.mark & DELAY))
123219b2ee8SDavid du Colombier 			continue;
124219b2ee8SDavid du Colombier 		if(s < se)
125219b2ee8SDavid du Colombier 			if(!conflict(s, s+1))
126219b2ee8SDavid du Colombier 				goto out3;
127219b2ee8SDavid du Colombier 		/*
128219b2ee8SDavid du Colombier 		 * s is load, s+1 is immediate use of result or end of block
129219b2ee8SDavid du Colombier 		 * t is the trial instruction to insert between s and s+1
130219b2ee8SDavid du Colombier 		 */
131219b2ee8SDavid du Colombier 		if(!debug['Y'])
132219b2ee8SDavid du Colombier 		for(t=s-1; t>=sch; t--) {
133219b2ee8SDavid du Colombier 			if(t->comp)
134219b2ee8SDavid du Colombier 				if(s->p.mark & BRANCH)
135219b2ee8SDavid du Colombier 					goto no2;
136219b2ee8SDavid du Colombier 			if(t->p.mark & DELAY)
137219b2ee8SDavid du Colombier 				if(s >= se || conflict(t, s+1))
138219b2ee8SDavid du Colombier 					goto no2;
139219b2ee8SDavid du Colombier 			for(u=t+1; u<=s; u++)
140219b2ee8SDavid du Colombier 				if(depend(u, t))
141219b2ee8SDavid du Colombier 					goto no2;
142219b2ee8SDavid du Colombier 			goto out2;
143219b2ee8SDavid du Colombier 		no2:;
144219b2ee8SDavid du Colombier 		}
145219b2ee8SDavid du Colombier 		if(debug['X'])
146219b2ee8SDavid du Colombier 			Bprint(&bso, "?l%P\n", &s->p);
147219b2ee8SDavid du Colombier 		s->nop = 1;
148219b2ee8SDavid du Colombier 		if(debug['v']) {
149219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD) {
150219b2ee8SDavid du Colombier 				nop.load.count++;
151219b2ee8SDavid du Colombier 				nop.load.outof++;
152219b2ee8SDavid du Colombier 			}
153219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH) {
154219b2ee8SDavid du Colombier 				nop.branch.count++;
155219b2ee8SDavid du Colombier 				nop.branch.outof++;
156219b2ee8SDavid du Colombier 			}
157219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP) {
158219b2ee8SDavid du Colombier 				nop.fcmp.count++;
159219b2ee8SDavid du Colombier 				nop.fcmp.outof++;
160219b2ee8SDavid du Colombier 			}
161219b2ee8SDavid du Colombier 		}
162219b2ee8SDavid du Colombier 		continue;
163219b2ee8SDavid du Colombier 
164219b2ee8SDavid du Colombier 	out2:
165219b2ee8SDavid du Colombier 		if(debug['X']) {
166219b2ee8SDavid du Colombier 			Bprint(&bso, "!l%P\n", &t->p);
167219b2ee8SDavid du Colombier 			Bprint(&bso, "%P\n", &s->p);
168219b2ee8SDavid du Colombier 		}
169219b2ee8SDavid du Colombier 		stmp = *t;
170219b2ee8SDavid du Colombier 		memmove(t, t+1, (uchar*)s - (uchar*)t);
171219b2ee8SDavid du Colombier 		*s = stmp;
172219b2ee8SDavid du Colombier 		s--;
173219b2ee8SDavid du Colombier 
174219b2ee8SDavid du Colombier 	out3:
175219b2ee8SDavid du Colombier 		if(debug['v']) {
176219b2ee8SDavid du Colombier 			if(s->p.mark & LOAD)
177219b2ee8SDavid du Colombier 				nop.load.outof++;
178219b2ee8SDavid du Colombier 			if(s->p.mark & BRANCH)
179219b2ee8SDavid du Colombier 				nop.branch.outof++;
180219b2ee8SDavid du Colombier 			if(s->p.mark & FCMP)
181219b2ee8SDavid du Colombier 				nop.fcmp.outof++;
182219b2ee8SDavid du Colombier 		}
183219b2ee8SDavid du Colombier 	}
184219b2ee8SDavid du Colombier 
185219b2ee8SDavid du Colombier 	/* Avoid HI/LO use->set */
186219b2ee8SDavid du Colombier 	t = sch+1;
187219b2ee8SDavid du Colombier 	for(s=sch; s<se-1; s++, t++) {
188219b2ee8SDavid du Colombier 		if((s->used.cc & E_HILO) == 0)
189219b2ee8SDavid du Colombier 			continue;
190219b2ee8SDavid du Colombier 		if(t->set.cc & E_HILO)
191219b2ee8SDavid du Colombier 			s->nop = 2;
192219b2ee8SDavid du Colombier 	}
193219b2ee8SDavid du Colombier 
194219b2ee8SDavid du Colombier 	/*
195219b2ee8SDavid du Colombier 	 * put it all back
196219b2ee8SDavid du Colombier 	 */
197219b2ee8SDavid du Colombier 	for(s=sch, p=p0; s<=se; s++, p=q) {
198219b2ee8SDavid du Colombier 		q = p->link;
199219b2ee8SDavid du Colombier 		if(q != s->p.link) {
200219b2ee8SDavid du Colombier 			*p = s->p;
201219b2ee8SDavid du Colombier 			p->link = q;
202219b2ee8SDavid du Colombier 		}
203219b2ee8SDavid du Colombier 		while(s->nop--)
204219b2ee8SDavid du Colombier 			addnop(p);
205219b2ee8SDavid du Colombier 	}
206219b2ee8SDavid du Colombier 	if(debug['X']) {
207219b2ee8SDavid du Colombier 		Bprint(&bso, "\n");
208219b2ee8SDavid du Colombier 		Bflush(&bso);
209219b2ee8SDavid du Colombier 	}
210219b2ee8SDavid du Colombier }
211219b2ee8SDavid du Colombier 
212219b2ee8SDavid du Colombier void
regsused(Sch * s,Prog * realp)2137dd7cddfSDavid du Colombier regsused(Sch *s, Prog *realp)
214219b2ee8SDavid du Colombier {
215219b2ee8SDavid du Colombier 	int c, ar, ad, ld, sz;
216219b2ee8SDavid du Colombier 	ulong m;
217219b2ee8SDavid du Colombier 	Prog *p;
218219b2ee8SDavid du Colombier 
219219b2ee8SDavid du Colombier 	p = &s->p;
220219b2ee8SDavid du Colombier 	s->comp = compound(p);
221219b2ee8SDavid du Colombier 	s->nop = 0;
222219b2ee8SDavid du Colombier 	if(s->comp) {
223219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<REGTMP;
224219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGTMP;
225219b2ee8SDavid du Colombier 	}
226219b2ee8SDavid du Colombier 
227219b2ee8SDavid du Colombier 	ar = 0;		/* dest is really reference */
228219b2ee8SDavid du Colombier 	ad = 0;		/* source/dest is really address */
229219b2ee8SDavid du Colombier 	ld = 0;		/* opcode is load instruction */
230219b2ee8SDavid du Colombier 	sz = 20;	/* size of load/store for overlap computation */
231219b2ee8SDavid du Colombier 
232219b2ee8SDavid du Colombier /*
233219b2ee8SDavid du Colombier  * flags based on opcode
234219b2ee8SDavid du Colombier  */
235219b2ee8SDavid du Colombier 	switch(p->as) {
236219b2ee8SDavid du Colombier 	case ATEXT:
237219b2ee8SDavid du Colombier 		curtext = realp;
238219b2ee8SDavid du Colombier 		autosize = p->to.offset + 4;
239219b2ee8SDavid du Colombier 		ad = 1;
240219b2ee8SDavid du Colombier 		break;
241219b2ee8SDavid du Colombier 	case AJAL:
242219b2ee8SDavid du Colombier 		c = p->reg;
243219b2ee8SDavid du Colombier 		if(c == NREG)
244219b2ee8SDavid du Colombier 			c = REGLINK;
245219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<c;
246219b2ee8SDavid du Colombier 		ar = 1;
247219b2ee8SDavid du Colombier 		ad = 1;
248219b2ee8SDavid du Colombier 		break;
249219b2ee8SDavid du Colombier 	case ABGEZAL:
250219b2ee8SDavid du Colombier 	case ABLTZAL:
251219b2ee8SDavid du Colombier 		s->set.ireg |= 1<<REGLINK;
252219b2ee8SDavid du Colombier 	case ABEQ:
253219b2ee8SDavid du Colombier 	case ABGEZ:
254219b2ee8SDavid du Colombier 	case ABGTZ:
255219b2ee8SDavid du Colombier 	case ABLEZ:
256219b2ee8SDavid du Colombier 	case ABLTZ:
257219b2ee8SDavid du Colombier 	case ABNE:
258219b2ee8SDavid du Colombier 		ar = 1;
259219b2ee8SDavid du Colombier 		ad = 1;
260219b2ee8SDavid du Colombier 		break;
261219b2ee8SDavid du Colombier 	case ABFPT:
262219b2ee8SDavid du Colombier 	case ABFPF:
263219b2ee8SDavid du Colombier 		ad = 1;
264219b2ee8SDavid du Colombier 		s->used.cc |= E_FCR;
265219b2ee8SDavid du Colombier 		break;
266219b2ee8SDavid du Colombier 	case ACMPEQD:
267219b2ee8SDavid du Colombier 	case ACMPEQF:
268219b2ee8SDavid du Colombier 	case ACMPGED:
269219b2ee8SDavid du Colombier 	case ACMPGEF:
270219b2ee8SDavid du Colombier 	case ACMPGTD:
271219b2ee8SDavid du Colombier 	case ACMPGTF:
272219b2ee8SDavid du Colombier 		ar = 1;
273219b2ee8SDavid du Colombier 		s->set.cc |= E_FCR;
274219b2ee8SDavid du Colombier 		p->mark |= FCMP;
275219b2ee8SDavid du Colombier 		break;
276219b2ee8SDavid du Colombier 	case AJMP:
277219b2ee8SDavid du Colombier 		ar = 1;
278219b2ee8SDavid du Colombier 		ad = 1;
279219b2ee8SDavid du Colombier 		break;
280219b2ee8SDavid du Colombier 	case AMOVB:
281219b2ee8SDavid du Colombier 	case AMOVBU:
282219b2ee8SDavid du Colombier 		sz = 1;
283219b2ee8SDavid du Colombier 		ld = 1;
284219b2ee8SDavid du Colombier 		break;
285219b2ee8SDavid du Colombier 	case AMOVH:
286219b2ee8SDavid du Colombier 	case AMOVHU:
287219b2ee8SDavid du Colombier 		sz = 2;
288219b2ee8SDavid du Colombier 		ld = 1;
289219b2ee8SDavid du Colombier 		break;
290219b2ee8SDavid du Colombier 	case AMOVF:
291219b2ee8SDavid du Colombier 	case AMOVW:
292219b2ee8SDavid du Colombier 	case AMOVWL:
293219b2ee8SDavid du Colombier 	case AMOVWR:
294219b2ee8SDavid du Colombier 		sz = 4;
295219b2ee8SDavid du Colombier 		ld = 1;
296219b2ee8SDavid du Colombier 		break;
297219b2ee8SDavid du Colombier 	case AMOVD:
298219b2ee8SDavid du Colombier 	case AMOVV:
299219b2ee8SDavid du Colombier 	case AMOVVL:
300219b2ee8SDavid du Colombier 	case AMOVVR:
301219b2ee8SDavid du Colombier 		sz = 8;
302219b2ee8SDavid du Colombier 		ld = 1;
303219b2ee8SDavid du Colombier 		break;
304219b2ee8SDavid du Colombier 	case ADIV:
305219b2ee8SDavid du Colombier 	case ADIVU:
306219b2ee8SDavid du Colombier 	case AMUL:
307219b2ee8SDavid du Colombier 	case AMULU:
308219b2ee8SDavid du Colombier 	case AREM:
309219b2ee8SDavid du Colombier 	case AREMU:
310219b2ee8SDavid du Colombier 		s->set.cc = E_HILO;
311219b2ee8SDavid du Colombier 	case AADD:
312219b2ee8SDavid du Colombier 	case AADDU:
313219b2ee8SDavid du Colombier 	case AAND:
314219b2ee8SDavid du Colombier 	case ANOR:
315219b2ee8SDavid du Colombier 	case AOR:
316219b2ee8SDavid du Colombier 	case ASGT:
317219b2ee8SDavid du Colombier 	case ASGTU:
318219b2ee8SDavid du Colombier 	case ASLL:
319219b2ee8SDavid du Colombier 	case ASRA:
320219b2ee8SDavid du Colombier 	case ASRL:
321219b2ee8SDavid du Colombier 	case ASUB:
322219b2ee8SDavid du Colombier 	case ASUBU:
323219b2ee8SDavid du Colombier 	case AXOR:
324219b2ee8SDavid du Colombier 
325219b2ee8SDavid du Colombier 	case AADDD:
326219b2ee8SDavid du Colombier 	case AADDF:
327219b2ee8SDavid du Colombier 	case AADDW:
328219b2ee8SDavid du Colombier 	case ASUBD:
329219b2ee8SDavid du Colombier 	case ASUBF:
330219b2ee8SDavid du Colombier 	case ASUBW:
331219b2ee8SDavid du Colombier 	case AMULF:
332219b2ee8SDavid du Colombier 	case AMULD:
333219b2ee8SDavid du Colombier 	case AMULW:
334219b2ee8SDavid du Colombier 	case ADIVF:
335219b2ee8SDavid du Colombier 	case ADIVD:
336219b2ee8SDavid du Colombier 	case ADIVW:
337219b2ee8SDavid du Colombier 		if(p->reg == NREG) {
338219b2ee8SDavid du Colombier 			if(p->to.type == D_REG || p->to.type == D_FREG)
339219b2ee8SDavid du Colombier 				p->reg = p->to.reg;
340219b2ee8SDavid du Colombier 			if(p->reg == NREG)
341219b2ee8SDavid du Colombier 				print("botch %P\n", p);
342219b2ee8SDavid du Colombier 		}
343219b2ee8SDavid du Colombier 		break;
344219b2ee8SDavid du Colombier 	}
345219b2ee8SDavid du Colombier 
346219b2ee8SDavid du Colombier /*
347219b2ee8SDavid du Colombier  * flags based on 'to' field
348219b2ee8SDavid du Colombier  */
349219b2ee8SDavid du Colombier 	c = p->to.class;
350219b2ee8SDavid du Colombier 	if(c == 0) {
351219b2ee8SDavid du Colombier 		c = aclass(&p->to) + 1;
352219b2ee8SDavid du Colombier 		p->to.class = c;
353219b2ee8SDavid du Colombier 	}
354219b2ee8SDavid du Colombier 	c--;
355219b2ee8SDavid du Colombier 	switch(c) {
356219b2ee8SDavid du Colombier 	default:
357219b2ee8SDavid du Colombier 		print("unknown class %d %D\n", c, &p->to);
358219b2ee8SDavid du Colombier 
359219b2ee8SDavid du Colombier 	case C_ZCON:
360219b2ee8SDavid du Colombier 	case C_SCON:
361219b2ee8SDavid du Colombier 	case C_ADD0CON:
362219b2ee8SDavid du Colombier 	case C_AND0CON:
363219b2ee8SDavid du Colombier 	case C_ADDCON:
364219b2ee8SDavid du Colombier 	case C_ANDCON:
365219b2ee8SDavid du Colombier 	case C_UCON:
366219b2ee8SDavid du Colombier 	case C_LCON:
367219b2ee8SDavid du Colombier 	case C_NONE:
368219b2ee8SDavid du Colombier 	case C_SBRA:
369219b2ee8SDavid du Colombier 	case C_LBRA:
370219b2ee8SDavid du Colombier 		break;
371219b2ee8SDavid du Colombier 
372219b2ee8SDavid du Colombier 	case C_HI:
373219b2ee8SDavid du Colombier 	case C_LO:
374219b2ee8SDavid du Colombier 		s->set.cc |= E_HILO;
375219b2ee8SDavid du Colombier 		break;
376219b2ee8SDavid du Colombier 	case C_FCREG:
377219b2ee8SDavid du Colombier 		s->set.cc |= E_FCR;
378219b2ee8SDavid du Colombier 		break;
379219b2ee8SDavid du Colombier 	case C_MREG:
380219b2ee8SDavid du Colombier 		s->set.cc |= E_MCR;
381219b2ee8SDavid du Colombier 		break;
382219b2ee8SDavid du Colombier 	case C_ZOREG:
383219b2ee8SDavid du Colombier 	case C_SOREG:
384219b2ee8SDavid du Colombier 	case C_LOREG:
385219b2ee8SDavid du Colombier 		c = p->to.reg;
386219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<c;
387219b2ee8SDavid du Colombier 		if(ad)
388219b2ee8SDavid du Colombier 			break;
389219b2ee8SDavid du Colombier 		s->size = sz;
3907dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->to);
391219b2ee8SDavid du Colombier 
392219b2ee8SDavid du Colombier 		m = ANYMEM;
393219b2ee8SDavid du Colombier 		if(c == REGSB)
394219b2ee8SDavid du Colombier 			m = E_MEMSB;
395219b2ee8SDavid du Colombier 		if(c == REGSP)
396219b2ee8SDavid du Colombier 			m = E_MEMSP;
397219b2ee8SDavid du Colombier 
398219b2ee8SDavid du Colombier 		if(ar)
399219b2ee8SDavid du Colombier 			s->used.cc |= m;
400219b2ee8SDavid du Colombier 		else
401219b2ee8SDavid du Colombier 			s->set.cc |= m;
402219b2ee8SDavid du Colombier 		break;
403219b2ee8SDavid du Colombier 	case C_SACON:
404219b2ee8SDavid du Colombier 	case C_LACON:
405219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
406219b2ee8SDavid du Colombier 		break;
407219b2ee8SDavid du Colombier 	case C_SECON:
408219b2ee8SDavid du Colombier 	case C_LECON:
409219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
410219b2ee8SDavid du Colombier 		break;
411219b2ee8SDavid du Colombier 	case C_REG:
412219b2ee8SDavid du Colombier 		if(ar)
413219b2ee8SDavid du Colombier 			s->used.ireg |= 1<<p->to.reg;
414219b2ee8SDavid du Colombier 		else
415219b2ee8SDavid du Colombier 			s->set.ireg |= 1<<p->to.reg;
416219b2ee8SDavid du Colombier 		break;
417219b2ee8SDavid du Colombier 	case C_FREG:
418219b2ee8SDavid du Colombier 		/* do better -- determine double prec */
419219b2ee8SDavid du Colombier 		if(ar) {
420219b2ee8SDavid du Colombier 			s->used.freg |= 1<<p->to.reg;
421219b2ee8SDavid du Colombier 			s->used.freg |= 1<<(p->to.reg|1);
422219b2ee8SDavid du Colombier 		} else {
423219b2ee8SDavid du Colombier 			s->set.freg |= 1<<p->to.reg;
424219b2ee8SDavid du Colombier 			s->set.freg |= 1<<(p->to.reg|1);
425219b2ee8SDavid du Colombier 		}
426219b2ee8SDavid du Colombier 		if(ld && p->from.type == D_REG)
427219b2ee8SDavid du Colombier 			p->mark |= LOAD;
428219b2ee8SDavid du Colombier 		break;
429219b2ee8SDavid du Colombier 	case C_SAUTO:
430219b2ee8SDavid du Colombier 	case C_LAUTO:
431219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
432219b2ee8SDavid du Colombier 		if(ad)
433219b2ee8SDavid du Colombier 			break;
434219b2ee8SDavid du Colombier 		s->size = sz;
4357dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->to);
436219b2ee8SDavid du Colombier 
437219b2ee8SDavid du Colombier 		if(ar)
438219b2ee8SDavid du Colombier 			s->used.cc |= E_MEMSP;
439219b2ee8SDavid du Colombier 		else
440219b2ee8SDavid du Colombier 			s->set.cc |= E_MEMSP;
441219b2ee8SDavid du Colombier 		break;
442219b2ee8SDavid du Colombier 	case C_SEXT:
443219b2ee8SDavid du Colombier 	case C_LEXT:
444219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
445219b2ee8SDavid du Colombier 		if(ad)
446219b2ee8SDavid du Colombier 			break;
447219b2ee8SDavid du Colombier 		s->size = sz;
4487dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->to);
449219b2ee8SDavid du Colombier 
450219b2ee8SDavid du Colombier 		if(ar)
451219b2ee8SDavid du Colombier 			s->used.cc |= E_MEMSB;
452219b2ee8SDavid du Colombier 		else
453219b2ee8SDavid du Colombier 			s->set.cc |= E_MEMSB;
454219b2ee8SDavid du Colombier 		break;
455219b2ee8SDavid du Colombier 	}
456219b2ee8SDavid du Colombier 
457219b2ee8SDavid du Colombier /*
458219b2ee8SDavid du Colombier  * flags based on 'from' field
459219b2ee8SDavid du Colombier  */
460219b2ee8SDavid du Colombier 	c = p->from.class;
461219b2ee8SDavid du Colombier 	if(c == 0) {
462219b2ee8SDavid du Colombier 		c = aclass(&p->from) + 1;
463219b2ee8SDavid du Colombier 		p->from.class = c;
464219b2ee8SDavid du Colombier 	}
465219b2ee8SDavid du Colombier 	c--;
466219b2ee8SDavid du Colombier 	switch(c) {
467219b2ee8SDavid du Colombier 	default:
468219b2ee8SDavid du Colombier 		print("unknown class %d %D\n", c, &p->from);
469219b2ee8SDavid du Colombier 
470219b2ee8SDavid du Colombier 	case C_ZCON:
471219b2ee8SDavid du Colombier 	case C_SCON:
472219b2ee8SDavid du Colombier 	case C_ADD0CON:
473219b2ee8SDavid du Colombier 	case C_AND0CON:
474219b2ee8SDavid du Colombier 	case C_ADDCON:
475219b2ee8SDavid du Colombier 	case C_ANDCON:
476219b2ee8SDavid du Colombier 	case C_UCON:
477219b2ee8SDavid du Colombier 	case C_LCON:
478219b2ee8SDavid du Colombier 	case C_NONE:
479219b2ee8SDavid du Colombier 	case C_SBRA:
480219b2ee8SDavid du Colombier 	case C_LBRA:
481219b2ee8SDavid du Colombier 		break;
482219b2ee8SDavid du Colombier 	case C_HI:
483219b2ee8SDavid du Colombier 	case C_LO:
484219b2ee8SDavid du Colombier 		s->used.cc |= E_HILO;
485219b2ee8SDavid du Colombier 		break;
486219b2ee8SDavid du Colombier 	case C_FCREG:
487219b2ee8SDavid du Colombier 		s->used.cc |= E_FCR;
488219b2ee8SDavid du Colombier 		break;
489219b2ee8SDavid du Colombier 	case C_MREG:
490219b2ee8SDavid du Colombier 		s->used.cc |= E_MCR;
491219b2ee8SDavid du Colombier 		break;
492219b2ee8SDavid du Colombier 	case C_ZOREG:
493219b2ee8SDavid du Colombier 	case C_SOREG:
494219b2ee8SDavid du Colombier 	case C_LOREG:
495219b2ee8SDavid du Colombier 		c = p->from.reg;
496219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<c;
497219b2ee8SDavid du Colombier 		if(ld)
498219b2ee8SDavid du Colombier 			p->mark |= LOAD;
499219b2ee8SDavid du Colombier 		s->size = sz;
5007dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->from);
501219b2ee8SDavid du Colombier 
502219b2ee8SDavid du Colombier 		m = ANYMEM;
503219b2ee8SDavid du Colombier 		if(c == REGSB)
504219b2ee8SDavid du Colombier 			m = E_MEMSB;
505219b2ee8SDavid du Colombier 		if(c == REGSP)
506219b2ee8SDavid du Colombier 			m = E_MEMSP;
507219b2ee8SDavid du Colombier 
508219b2ee8SDavid du Colombier 		s->used.cc |= m;
509219b2ee8SDavid du Colombier 		break;
510219b2ee8SDavid du Colombier 	case C_SACON:
511219b2ee8SDavid du Colombier 	case C_LACON:
512219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
513219b2ee8SDavid du Colombier 		break;
514219b2ee8SDavid du Colombier 	case C_SECON:
515219b2ee8SDavid du Colombier 	case C_LECON:
516219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
517219b2ee8SDavid du Colombier 		break;
518219b2ee8SDavid du Colombier 	case C_REG:
519219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<p->from.reg;
520219b2ee8SDavid du Colombier 		break;
521219b2ee8SDavid du Colombier 	case C_FREG:
522219b2ee8SDavid du Colombier 		/* do better -- determine double prec */
523219b2ee8SDavid du Colombier 		s->used.freg |= 1<<p->from.reg;
524219b2ee8SDavid du Colombier 		s->used.freg |= 1<<(p->from.reg|1);
525219b2ee8SDavid du Colombier 		if(ld && p->to.type == D_REG)
526219b2ee8SDavid du Colombier 			p->mark |= LOAD;
527219b2ee8SDavid du Colombier 		break;
528219b2ee8SDavid du Colombier 	case C_SAUTO:
529219b2ee8SDavid du Colombier 	case C_LAUTO:
530219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSP;
531219b2ee8SDavid du Colombier 		if(ld)
532219b2ee8SDavid du Colombier 			p->mark |= LOAD;
533219b2ee8SDavid du Colombier 		if(ad)
534219b2ee8SDavid du Colombier 			break;
535219b2ee8SDavid du Colombier 		s->size = sz;
5367dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->from);
537219b2ee8SDavid du Colombier 
538219b2ee8SDavid du Colombier 		s->used.cc |= E_MEMSP;
539219b2ee8SDavid du Colombier 		break;
540219b2ee8SDavid du Colombier 	case C_SEXT:
541219b2ee8SDavid du Colombier 	case C_LEXT:
542219b2ee8SDavid du Colombier 		s->used.ireg |= 1<<REGSB;
543219b2ee8SDavid du Colombier 		if(ld)
544219b2ee8SDavid du Colombier 			p->mark |= LOAD;
545219b2ee8SDavid du Colombier 		if(ad)
546219b2ee8SDavid du Colombier 			break;
547219b2ee8SDavid du Colombier 		s->size = sz;
5487dd7cddfSDavid du Colombier 		s->soffset = regoff(&p->from);
549219b2ee8SDavid du Colombier 
550219b2ee8SDavid du Colombier 		s->used.cc |= E_MEMSB;
551219b2ee8SDavid du Colombier 		break;
552219b2ee8SDavid du Colombier 	}
553219b2ee8SDavid du Colombier 
554219b2ee8SDavid du Colombier 	c = p->reg;
555219b2ee8SDavid du Colombier 	if(c != NREG) {
556219b2ee8SDavid du Colombier 		if(p->from.type == D_FREG || p->to.type == D_FREG) {
557219b2ee8SDavid du Colombier 			s->used.freg |= 1<<c;
558219b2ee8SDavid du Colombier 			s->used.freg |= 1<<(c|1);
559219b2ee8SDavid du Colombier 		} else
560219b2ee8SDavid du Colombier 			s->used.ireg |= 1<<c;
561219b2ee8SDavid du Colombier 	}
562219b2ee8SDavid du Colombier 	s->set.ireg &= ~(1<<REGZERO);		/* R0 cant be set */
563219b2ee8SDavid du Colombier }
564219b2ee8SDavid du Colombier 
565219b2ee8SDavid du Colombier /*
566219b2ee8SDavid du Colombier  * test to see if 2 instrictions can be
567219b2ee8SDavid du Colombier  * interchanged without changing semantics
568219b2ee8SDavid du Colombier  */
569219b2ee8SDavid du Colombier int
depend(Sch * sa,Sch * sb)570219b2ee8SDavid du Colombier depend(Sch *sa, Sch *sb)
571219b2ee8SDavid du Colombier {
572219b2ee8SDavid du Colombier 	ulong x;
573219b2ee8SDavid du Colombier 
574219b2ee8SDavid du Colombier 	if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
575219b2ee8SDavid du Colombier 		return 1;
576219b2ee8SDavid du Colombier 	if(sb->set.ireg & sa->used.ireg)
577219b2ee8SDavid du Colombier 		return 1;
578219b2ee8SDavid du Colombier 
579219b2ee8SDavid du Colombier 	if(sa->set.freg & (sb->set.freg|sb->used.freg))
580219b2ee8SDavid du Colombier 		return 1;
581219b2ee8SDavid du Colombier 	if(sb->set.freg & sa->used.freg)
582219b2ee8SDavid du Colombier 		return 1;
583219b2ee8SDavid du Colombier 
584219b2ee8SDavid du Colombier 	/*
585219b2ee8SDavid du Colombier 	 * special case.
586219b2ee8SDavid du Colombier 	 * loads from same address cannot pass.
587219b2ee8SDavid du Colombier 	 * this is for hardware fifo's and the like
588219b2ee8SDavid du Colombier 	 */
589219b2ee8SDavid du Colombier 	if(sa->used.cc & sb->used.cc & E_MEM)
590219b2ee8SDavid du Colombier 		if(sa->p.reg == sb->p.reg)
591219b2ee8SDavid du Colombier 		if(regoff(&sa->p.from) == regoff(&sb->p.from))
592219b2ee8SDavid du Colombier 			return 1;
593219b2ee8SDavid du Colombier 
594219b2ee8SDavid du Colombier 	x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
595219b2ee8SDavid du Colombier 		(sb->set.cc & sa->used.cc);
596219b2ee8SDavid du Colombier 	if(x) {
597219b2ee8SDavid du Colombier 		/*
598219b2ee8SDavid du Colombier 		 * allow SB and SP to pass each other.
599219b2ee8SDavid du Colombier 		 * allow SB to pass SB iff doffsets are ok
600219b2ee8SDavid du Colombier 		 * anything else conflicts
601219b2ee8SDavid du Colombier 		 */
602219b2ee8SDavid du Colombier 		if(x != E_MEMSP && x != E_MEMSB)
603219b2ee8SDavid du Colombier 			return 1;
604219b2ee8SDavid du Colombier 		x = sa->set.cc | sb->set.cc |
605219b2ee8SDavid du Colombier 			sa->used.cc | sb->used.cc;
606219b2ee8SDavid du Colombier 		if(x & E_MEM)
607219b2ee8SDavid du Colombier 			return 1;
608219b2ee8SDavid du Colombier 		if(offoverlap(sa, sb))
609219b2ee8SDavid du Colombier 			return 1;
610219b2ee8SDavid du Colombier 	}
611219b2ee8SDavid du Colombier 
612219b2ee8SDavid du Colombier 	return 0;
613219b2ee8SDavid du Colombier }
614219b2ee8SDavid du Colombier 
615219b2ee8SDavid du Colombier int
offoverlap(Sch * sa,Sch * sb)616219b2ee8SDavid du Colombier offoverlap(Sch *sa, Sch *sb)
617219b2ee8SDavid du Colombier {
618219b2ee8SDavid du Colombier 
6197dd7cddfSDavid du Colombier 	if(sa->soffset < sb->soffset) {
6207dd7cddfSDavid du Colombier 		if(sa->soffset+sa->size > sb->soffset)
621219b2ee8SDavid du Colombier 			return 1;
622219b2ee8SDavid du Colombier 		return 0;
623219b2ee8SDavid du Colombier 	}
6247dd7cddfSDavid du Colombier 	if(sb->soffset+sb->size > sa->soffset)
625219b2ee8SDavid du Colombier 		return 1;
626219b2ee8SDavid du Colombier 	return 0;
627219b2ee8SDavid du Colombier }
628219b2ee8SDavid du Colombier 
629219b2ee8SDavid du Colombier /*
630219b2ee8SDavid du Colombier  * test 2 adjacent instructions
631219b2ee8SDavid du Colombier  * and find out if inserted instructions
632219b2ee8SDavid du Colombier  * are desired to prevent stalls.
633219b2ee8SDavid du Colombier  */
634219b2ee8SDavid du Colombier int
conflict(Sch * sa,Sch * sb)635219b2ee8SDavid du Colombier conflict(Sch *sa, Sch *sb)
636219b2ee8SDavid du Colombier {
637219b2ee8SDavid du Colombier 
638219b2ee8SDavid du Colombier 	if(sa->set.ireg & sb->used.ireg)
639219b2ee8SDavid du Colombier 		return 1;
640219b2ee8SDavid du Colombier 	if(sa->set.freg & sb->used.freg)
641219b2ee8SDavid du Colombier 		return 1;
642219b2ee8SDavid du Colombier 	if(sa->set.cc & sb->used.cc)
643219b2ee8SDavid du Colombier 		return 1;
644219b2ee8SDavid du Colombier 
645219b2ee8SDavid du Colombier 	return 0;
646219b2ee8SDavid du Colombier }
647219b2ee8SDavid du Colombier 
648219b2ee8SDavid du Colombier int
compound(Prog * p)649219b2ee8SDavid du Colombier compound(Prog *p)
650219b2ee8SDavid du Colombier {
651219b2ee8SDavid du Colombier 	Optab *o;
652219b2ee8SDavid du Colombier 
653219b2ee8SDavid du Colombier 	o = oplook(p);
654219b2ee8SDavid du Colombier 	if(o->size != 4)
655219b2ee8SDavid du Colombier 		return 1;
656219b2ee8SDavid du Colombier 	if(p->to.type == D_REG && p->to.reg == REGSB)
657219b2ee8SDavid du Colombier 		return 1;
658219b2ee8SDavid du Colombier 	return 0;
659219b2ee8SDavid du Colombier }
660219b2ee8SDavid du Colombier 
661219b2ee8SDavid du Colombier void
dumpbits(Sch * s,Dep * d)662219b2ee8SDavid du Colombier dumpbits(Sch *s, Dep *d)
663219b2ee8SDavid du Colombier {
664219b2ee8SDavid du Colombier 	int i;
665219b2ee8SDavid du Colombier 
666219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
667219b2ee8SDavid du Colombier 		if(d->ireg & (1<<i))
668219b2ee8SDavid du Colombier 			Bprint(&bso, " R%d", i);
669219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
670219b2ee8SDavid du Colombier 		if(d->freg & (1<<i))
671219b2ee8SDavid du Colombier 			Bprint(&bso, " F%d", i);
672219b2ee8SDavid du Colombier 	for(i=0; i<32; i++)
673219b2ee8SDavid du Colombier 		switch(d->cc & (1<<i)) {
674219b2ee8SDavid du Colombier 		default:
675219b2ee8SDavid du Colombier 			break;
676219b2ee8SDavid du Colombier 		case E_HILO:
677219b2ee8SDavid du Colombier 			Bprint(&bso, " HILO");
678219b2ee8SDavid du Colombier 			break;
679219b2ee8SDavid du Colombier 		case E_FCR:
680219b2ee8SDavid du Colombier 			Bprint(&bso, " FCR");
681219b2ee8SDavid du Colombier 			break;
682219b2ee8SDavid du Colombier 		case E_MCR:
683219b2ee8SDavid du Colombier 			Bprint(&bso, " MCR");
684219b2ee8SDavid du Colombier 			break;
685219b2ee8SDavid du Colombier 		case E_MEM:
686219b2ee8SDavid du Colombier 			Bprint(&bso, " MEM%d", s->size);
687219b2ee8SDavid du Colombier 			break;
688219b2ee8SDavid du Colombier 		case E_MEMSB:
689219b2ee8SDavid du Colombier 			Bprint(&bso, " SB%d", s->size);
690219b2ee8SDavid du Colombier 			break;
691219b2ee8SDavid du Colombier 		case E_MEMSP:
692219b2ee8SDavid du Colombier 			Bprint(&bso, " SP%d", s->size);
693219b2ee8SDavid du Colombier 			break;
694219b2ee8SDavid du Colombier 		}
695219b2ee8SDavid du Colombier }
696