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