8 E_MEMSP = 1<<3, /* uses offset and size */
9 E_MEMSB = 1<<4, /* uses offset and size */
10 ANYMEM = E_MEM|E_MEMSP|E_MEMSB,
14 typedef struct Sch Sch;
15 typedef struct Dep Dep;
34 void regsused(Sch*, Prog*);
35 int depend(Sch*, Sch*);
36 int conflict(Sch*, Sch*);
37 int offoverlap(Sch*, Sch*);
38 void dumpbits(Sch*, Dep*);
41 sched(Prog *p0, Prog *pe)
44 Sch sch[NSCHED], *s, *t, *u, *se, stmp;
47 * build side structure
50 for(p=p0;; p=p->link) {
51 memset(s, 0, sizeof(*s));
55 Bprint(&bso, "%P\tset", &s->p);
57 Bprint(&bso, "; used");
58 dumpbits(s, &s->used);
60 Bprint(&bso, "; compound");
62 Bprint(&bso, "; load");
63 if(s->p.mark & BRANCH)
64 Bprint(&bso, "; branch");
66 Bprint(&bso, "; fcmp");
75 for(s=se-1; s>=sch; s--) {
79 if(s->p.mark & BRANCH) {
80 /* t is the trial instruction to use */
81 for(t=s-1; t>=sch; t--) {
82 if(t->comp || (t->p.mark & FCMP))
91 Bprint(&bso, "?b%P\n", &s->p);
97 Bprint(&bso, "!b%P\n", &t->p);
98 Bprint(&bso, "%P\n", &s->p);
101 memmove(t, t+1, (uchar*)s - (uchar*)t);
108 * load delay. interlocked.
110 if(s->p.mark & LOAD) {
113 if(!conflict(s, (s+1)))
116 * s is load, s+1 is immediate use of result
117 * t is the trial instruction to insert between s and s+1
119 for(t=s-1; t>=sch; t--) {
120 if(t->p.mark & BRANCH)
123 if((s+1)->p.mark & BRANCH)
126 if(conflict(t, (s+1)))
128 for(u=t+1; u<=s; u++)
135 Bprint(&bso, "?l%P\n", &s->p);
139 Bprint(&bso, "!l%P\n", &t->p);
140 Bprint(&bso, "%P\n", &s->p);
143 memmove(t, t+1, (uchar*)s - (uchar*)t);
152 if(s->p.mark & FCMP) {
157 if(!((s+1)->p.mark & BRANCH))
159 /* t is the trial instruction to use */
160 for(t=s-1; t>=sch; t--) {
161 for(u=t+1; u<=s; u++)
168 Bprint(&bso, "?f%P\n", &s->p);
173 Bprint(&bso, "!f%P\n", &t->p);
174 Bprint(&bso, "%P\n", &s->p);
177 memmove(t, t+1, (uchar*)s - (uchar*)t);
187 for(s=sch, p=p0; s<se; s++, p=q) {
201 regsused(Sch *s, Prog *realp)
203 int c, ar, ad, ld, sz;
208 s->comp = compound(p);
211 s->set.ireg |= 1<<REGTMP;
212 s->used.ireg |= 1<<REGTMP;
214 ar = 0; /* dest is really reference */
215 ad = 0; /* source/dest is really address */
216 ld = 0; /* opcode is load instruction */
217 sz = 20; /* size of load/store for overlap computation */
220 * flags based on opcode
225 autosize = p->to.offset + 4;
299 case AFMOVX: /* gok */
333 * flags based on 'to' field
337 c = aclass(&p->to) + 1;
343 print("unknown class %d %D\n", c, &p->to);
366 s->used.ireg |= 1<<c;
370 s->soffset = regoff(&p->to);
385 s->used.ireg |= 1<<REGSP;
389 s->used.ireg |= 1<<REGSB;
393 s->used.ireg |= 1<<p->to.reg;
395 s->set.ireg |= 1<<p->to.reg;
398 /* do better -- determine double prec */
400 s->used.freg |= 1<<p->to.reg;
401 s->used.freg |= 1<<(p->to.reg|1);
403 s->set.freg |= 1<<p->to.reg;
404 s->set.freg |= 1<<(p->to.reg|1);
413 s->used.ireg |= 1<<REGSP;
417 s->soffset = regoff(&p->to);
420 s->used.cc |= E_MEMSP;
422 s->set.cc |= E_MEMSP;
430 s->used.ireg |= 1<<REGSB;
434 s->soffset = regoff(&p->to);
437 s->used.cc |= E_MEMSB;
439 s->set.cc |= E_MEMSB;
444 * flags based on 'from' field
448 c = aclass(&p->from) + 1;
454 print("unknown class %d %D\n", c, &p->from);
465 s->used.ireg |= 1<<c;
480 s->used.ireg |= 1<<c;
486 s->soffset = regoff(&p->from);
498 s->used.ireg |= 1<<REGSP;
502 s->used.ireg |= 1<<REGSB;
505 s->used.ireg |= 1<<p->from.reg;
508 /* do better -- determine double prec */
509 s->used.freg |= 1<<p->from.reg;
510 s->used.freg |= 1<<(p->from.reg|1);
518 s->used.ireg |= 1<<REGSP;
524 s->soffset = regoff(&p->from);
526 s->used.cc |= E_MEMSP;
534 s->used.ireg |= 1<<REGSB;
540 s->soffset = regoff(&p->from);
542 s->used.cc |= E_MEMSB;
548 if(p->from.type == D_FREG || p->to.type == D_FREG) {
549 s->used.freg |= 1<<c;
550 s->used.freg |= 1<<(c|1);
552 s->used.ireg |= 1<<c;
554 s->set.ireg &= ~(1<<0); /* R0 cant be set */
558 * test to see if 2 instrictions can be
559 * interchanged without changing semantics
562 depend(Sch *sa, Sch *sb)
566 if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
568 if(sb->set.ireg & sa->used.ireg)
571 if(sa->set.freg & (sb->set.freg|sb->used.freg))
573 if(sb->set.freg & sa->used.freg)
576 x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
577 (sb->set.cc & sa->used.cc);
580 * allow SB and SP to pass each other.
581 * allow SB to pass SB iff doffsets are ok
582 * anything else conflicts
584 if(x != E_MEMSP && x != E_MEMSB)
586 x = sa->set.cc | sb->set.cc |
587 sa->used.cc | sb->used.cc;
590 if(offoverlap(sa, sb))
598 offoverlap(Sch *sa, Sch *sb)
601 if(sa->soffset < sb->soffset) {
602 if(sa->soffset+sa->size > sb->soffset)
606 if(sb->soffset+sb->size > sa->soffset)
612 * test 2 adjacent instructions
613 * and find out if inserted instructions
614 * are desired to prevent stalls.
615 * first instruction is a load instruction.
618 conflict(Sch *sa, Sch *sb)
621 if(sa->set.ireg & sb->used.ireg)
623 if(sa->set.freg & sb->used.freg)
636 if(p->to.type == D_REG && p->to.reg == REGSB)
642 dumpbits(Sch *s, Dep *d)
648 Bprint(&bso, " R%d", i);
651 Bprint(&bso, " F%d", i);
653 switch(d->cc & (1<<i)) {
657 Bprint(&bso, " ICC");
660 Bprint(&bso, " FCC");
663 Bprint(&bso, " MEM%d", s->size);
666 Bprint(&bso, " SB%d", s->size);
669 Bprint(&bso, " SP%d", s->size);