8 E_MEMSP = 1<<3, /* uses offset and size */
9 E_MEMSB = 1<<4, /* uses offset and size */
18 ANYMEM = E_MEM|E_MEMSP|E_MEMSB,
22 typedef struct Sch Sch;
23 typedef struct Dep Dep;
42 void regused(Sch*, Prog*);
43 int depend(Sch*, Sch*);
44 int conflict(Sch*, Sch*);
45 int offoverlap(Sch*, Sch*);
46 void dumpbits(Sch*, Dep*);
49 sched(Prog *p0, Prog *pe)
52 Sch sch[NSCHED], *s, *t, *u, *se, stmp;
57 * build side structure
60 for(p=p0;; p=p->link) {
61 memset(s, 0, sizeof(*s));
65 Bprint(&bso, "%P\tset", &s->p);
67 Bprint(&bso, "; used");
68 dumpbits(s, &s->used);
70 Bprint(&bso, "; compound");
72 Bprint(&bso, "; load");
73 if(s->p.mark & BRANCH)
74 Bprint(&bso, "; branch");
76 Bprint(&bso, "; fcmp");
85 for(s=se-1; s>=sch; s--) {
88 * load delay. interlocked.
90 if(s->p.mark & LOAD) {
93 if(!conflict(s, (s+1)))
96 * s is load, s+1 is immediate use of result
97 * t is the trial instruction to insert between s and s+1
99 for(t=s-1; t>=sch; t--) {
100 if(t->p.mark & BRANCH)
103 if((s+1)->p.mark & BRANCH)
106 if(conflict(t, (s+1)))
108 for(u=t+1; u<=s; u++)
115 Bprint(&bso, "?l%P\n", &s->p);
119 Bprint(&bso, "!l%P\n", &t->p);
120 Bprint(&bso, "%P\n", &s->p);
123 memmove(t, t+1, (uchar*)s - (uchar*)t);
132 if(s->p.mark & FCMP) {
135 if(!((s+1)->p.mark & BRANCH))
137 /* t is the trial instruction to use */
138 for(t=s-1; t>=sch; t--) {
139 for(u=t+1; u<=s; u++)
146 Bprint(&bso, "?f%P\n", &s->p);
150 Bprint(&bso, "!f%P\n", &t->p);
151 Bprint(&bso, "%P\n", &s->p);
154 memmove(t, t+1, (uchar*)s - (uchar*)t);
164 for(s=sch, p=p0; s<se; s++, p=q) {
176 regused(Sch *s, Prog *realp)
178 int c, ar, ad, ld, sz, nr, upd;
183 s->comp = compound(p);
185 s->set.ireg |= 1<<REGTMP;
186 s->used.ireg |= 1<<REGTMP;
188 ar = 0; /* dest is really reference */
189 ad = 0; /* source/dest is really address */
190 ld = 0; /* opcode is load instruction */
191 sz = 32*4; /* size of load/store for overlap computation */
192 nr = 0; /* source/dest is not really reg */
193 upd = 0; /* move with update; changes reg */
196 * flags based on opcode
201 autosize = p->to.offset + 4;
218 s->set.cr |= (0xF<<((p->reg&7)*4));
227 s->set.cr |= (0xF<<((p->reg&7)*4));
238 s->used.cr |= 1<<p->from.reg;
239 s->set.cr |= 1<<p->to.reg;
242 case ABCL: /* tricky */
243 s->used.cc |= E_FCC|E_ICC;
248 case ABC: /* tricky */
249 s->used.cc |= E_FCC|E_ICC;
267 /* could do better */
415 * flags based on 'to' field
419 c = aclass(&p->to) + 1;
425 print("unknown class %d %D\n", c, &p->to);
442 s->set.cr |= (0xF << ((p->from.reg&7)*4));
465 s->used.ireg |= 1<<c;
471 s->soffset = regoff(&p->to);
486 s->used.ireg |= 1<<REGSP;
492 s->used.ireg |= 1<<REGSB;
500 s->used.ireg |= 1<<p->to.reg;
502 s->set.ireg |= 1<<p->to.reg;
506 s->used.freg |= 1<<p->to.reg;
508 s->set.freg |= 1<<p->to.reg;
512 s->used.ireg |= 1<<REGSP;
518 s->soffset = regoff(&p->to);
521 s->used.cc |= E_MEMSP;
523 s->set.cc |= E_MEMSP;
527 s->used.ireg |= 1<<REGSB;
533 s->soffset = regoff(&p->to);
536 s->used.cc |= E_MEMSB;
538 s->set.cc |= E_MEMSB;
543 * flags based on 'from' field
547 c = aclass(&p->from) + 1;
553 print("unknown class %d %D\n", c, &p->from);
566 s->used.ireg |= 1<<c;
573 s->used.cr |= (0xF << ((p->from.reg&7)*4));
596 s->used.ireg |= 1<<c;
602 s->soffset = regoff(&p->from);
614 s->used.ireg |= 1<<REGSP;
618 s->used.ireg |= 1<<REGSB;
623 s->used.ireg |= 1<<p->from.reg;
626 s->used.freg |= 1<<p->from.reg;
630 s->used.ireg |= 1<<REGSP;
636 s->soffset = regoff(&p->from);
638 s->used.cc |= E_MEMSP;
642 s->used.ireg |= 1<<REGSB;
648 s->soffset = regoff(&p->from);
650 s->used.cc |= E_MEMSB;
656 if(p->from.type == D_FREG || p->to.type == D_FREG)
657 s->used.freg |= 1<<c;
659 s->used.ireg |= 1<<c;
664 * test to see if 2 instrictions can be
665 * interchanged without changing semantics
668 depend(Sch *sa, Sch *sb)
672 if(sa->set.ireg & (sb->set.ireg|sb->used.ireg))
674 if(sb->set.ireg & sa->used.ireg)
677 if(sa->set.freg & (sb->set.freg|sb->used.freg))
679 if(sb->set.freg & sa->used.freg)
682 if(sa->set.cr & (sb->set.cr|sb->used.cr))
684 if(sb->set.cr & sa->used.cr)
688 x = (sa->set.cc & (sb->set.cc|sb->used.cc)) |
689 (sb->set.cc & sa->used.cc);
692 * allow SB and SP to pass each other.
693 * allow SB to pass SB iff doffsets are ok
694 * anything else conflicts
696 if(x != E_MEMSP && x != E_MEMSB)
698 x = sa->set.cc | sb->set.cc |
699 sa->used.cc | sb->used.cc;
702 if(offoverlap(sa, sb))
710 offoverlap(Sch *sa, Sch *sb)
713 if(sa->soffset < sb->soffset) {
714 if(sa->soffset+sa->size > sb->soffset)
718 if(sb->soffset+sb->size > sa->soffset)
724 * test 2 adjacent instructions
725 * and find out if inserted instructions
726 * are desired to prevent stalls.
727 * first instruction is a load instruction.
730 conflict(Sch *sa, Sch *sb)
733 if(sa->set.ireg & sb->used.ireg)
735 if(sa->set.freg & sb->used.freg)
737 if(sa->set.cr & sb->used.cr)
750 if(p->to.type == D_REG && p->to.reg == REGSB)
756 dumpbits(Sch *s, Dep *d)
762 Bprint(&bso, " R%d", i);
765 Bprint(&bso, " F%d", i);
768 Bprint(&bso, " C%d", i);
770 switch(d->cc & (1<<i)) {
774 Bprint(&bso, " ICC");
777 Bprint(&bso, " FCC");
786 Bprint(&bso, " CTR");
789 Bprint(&bso, " XER");
792 Bprint(&bso, " MEM%d", s->size);
795 Bprint(&bso, " SB%d", s->size);
798 Bprint(&bso, " SP%d", s->size);