174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth void addsplits(void);
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth Reg*
rega(void)674a4d8c2SCharles.Forsyth rega(void)
774a4d8c2SCharles.Forsyth {
874a4d8c2SCharles.Forsyth Reg *r;
974a4d8c2SCharles.Forsyth
1074a4d8c2SCharles.Forsyth r = freer;
1174a4d8c2SCharles.Forsyth if(r == R) {
1274a4d8c2SCharles.Forsyth r = alloc(sizeof(*r));
1374a4d8c2SCharles.Forsyth } else
1474a4d8c2SCharles.Forsyth freer = r->link;
1574a4d8c2SCharles.Forsyth
1674a4d8c2SCharles.Forsyth *r = zreg;
1774a4d8c2SCharles.Forsyth return r;
1874a4d8c2SCharles.Forsyth }
1974a4d8c2SCharles.Forsyth
2074a4d8c2SCharles.Forsyth int
rcmp(void * a1,void * a2)21*45a20ab7Sforsyth rcmp(void *a1, void *a2)
2274a4d8c2SCharles.Forsyth {
2374a4d8c2SCharles.Forsyth Rgn *p1, *p2;
2474a4d8c2SCharles.Forsyth int c1, c2;
2574a4d8c2SCharles.Forsyth
2674a4d8c2SCharles.Forsyth p1 = (Rgn*)a1;
2774a4d8c2SCharles.Forsyth p2 = (Rgn*)a2;
2874a4d8c2SCharles.Forsyth c1 = p2->cost;
2974a4d8c2SCharles.Forsyth c2 = p1->cost;
3074a4d8c2SCharles.Forsyth if(c1 -= c2)
3174a4d8c2SCharles.Forsyth return c1;
3274a4d8c2SCharles.Forsyth return p2->varno - p1->varno;
3374a4d8c2SCharles.Forsyth }
3474a4d8c2SCharles.Forsyth
3574a4d8c2SCharles.Forsyth void
regopt(Prog * p)3674a4d8c2SCharles.Forsyth regopt(Prog *p)
3774a4d8c2SCharles.Forsyth {
3874a4d8c2SCharles.Forsyth Reg *r, *r1, *r2;
3974a4d8c2SCharles.Forsyth Prog *p1;
4074a4d8c2SCharles.Forsyth int i, z;
4174a4d8c2SCharles.Forsyth long initpc, val, npc;
4274a4d8c2SCharles.Forsyth ulong vreg;
4374a4d8c2SCharles.Forsyth Bits bit;
4474a4d8c2SCharles.Forsyth struct
4574a4d8c2SCharles.Forsyth {
4674a4d8c2SCharles.Forsyth long m;
4774a4d8c2SCharles.Forsyth long c;
4874a4d8c2SCharles.Forsyth Reg* p;
4974a4d8c2SCharles.Forsyth } log5[6], *lp;
5074a4d8c2SCharles.Forsyth
5174a4d8c2SCharles.Forsyth firstr = R;
5274a4d8c2SCharles.Forsyth lastr = R;
5374a4d8c2SCharles.Forsyth nvar = 0;
5474a4d8c2SCharles.Forsyth regbits = 0;
5574a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
5674a4d8c2SCharles.Forsyth externs.b[z] = 0;
5774a4d8c2SCharles.Forsyth params.b[z] = 0;
5874a4d8c2SCharles.Forsyth consts.b[z] = 0;
5974a4d8c2SCharles.Forsyth addrs.b[z] = 0;
6074a4d8c2SCharles.Forsyth }
6174a4d8c2SCharles.Forsyth
6274a4d8c2SCharles.Forsyth /*
6374a4d8c2SCharles.Forsyth * pass 1
6474a4d8c2SCharles.Forsyth * build aux data structure
6574a4d8c2SCharles.Forsyth * allocate pcs
6674a4d8c2SCharles.Forsyth * find use and set of variables
6774a4d8c2SCharles.Forsyth */
6874a4d8c2SCharles.Forsyth val = 5L * 5L * 5L * 5L * 5L;
6974a4d8c2SCharles.Forsyth lp = log5;
7074a4d8c2SCharles.Forsyth for(i=0; i<5; i++) {
7174a4d8c2SCharles.Forsyth lp->m = val;
7274a4d8c2SCharles.Forsyth lp->c = 0;
7374a4d8c2SCharles.Forsyth lp->p = R;
7474a4d8c2SCharles.Forsyth val /= 5L;
7574a4d8c2SCharles.Forsyth lp++;
7674a4d8c2SCharles.Forsyth }
7774a4d8c2SCharles.Forsyth val = 0;
7874a4d8c2SCharles.Forsyth for(; p != P; p = p->link) {
7974a4d8c2SCharles.Forsyth switch(p->as) {
8074a4d8c2SCharles.Forsyth case ADATA:
8174a4d8c2SCharles.Forsyth case AGLOBL:
8274a4d8c2SCharles.Forsyth case ANAME:
8374a4d8c2SCharles.Forsyth case ASIGNAME:
8474a4d8c2SCharles.Forsyth continue;
8574a4d8c2SCharles.Forsyth }
8674a4d8c2SCharles.Forsyth r = rega();
8774a4d8c2SCharles.Forsyth if(firstr == R) {
8874a4d8c2SCharles.Forsyth firstr = r;
8974a4d8c2SCharles.Forsyth lastr = r;
9074a4d8c2SCharles.Forsyth } else {
9174a4d8c2SCharles.Forsyth lastr->link = r;
9274a4d8c2SCharles.Forsyth r->p1 = lastr;
9374a4d8c2SCharles.Forsyth lastr->s1 = r;
9474a4d8c2SCharles.Forsyth lastr = r;
9574a4d8c2SCharles.Forsyth }
9674a4d8c2SCharles.Forsyth r->prog = p;
9774a4d8c2SCharles.Forsyth r->pc = val;
9874a4d8c2SCharles.Forsyth val++;
9974a4d8c2SCharles.Forsyth
10074a4d8c2SCharles.Forsyth lp = log5;
10174a4d8c2SCharles.Forsyth for(i=0; i<5; i++) {
10274a4d8c2SCharles.Forsyth lp->c--;
10374a4d8c2SCharles.Forsyth if(lp->c <= 0) {
10474a4d8c2SCharles.Forsyth lp->c = lp->m;
10574a4d8c2SCharles.Forsyth if(lp->p != R)
10674a4d8c2SCharles.Forsyth lp->p->log5 = r;
10774a4d8c2SCharles.Forsyth lp->p = r;
10874a4d8c2SCharles.Forsyth (lp+1)->c = 0;
10974a4d8c2SCharles.Forsyth break;
11074a4d8c2SCharles.Forsyth }
11174a4d8c2SCharles.Forsyth lp++;
11274a4d8c2SCharles.Forsyth }
11374a4d8c2SCharles.Forsyth
11474a4d8c2SCharles.Forsyth r1 = r->p1;
11574a4d8c2SCharles.Forsyth if(r1 != R)
11674a4d8c2SCharles.Forsyth switch(r1->prog->as) {
11774a4d8c2SCharles.Forsyth case ARET:
11874a4d8c2SCharles.Forsyth case AJMP:
11974a4d8c2SCharles.Forsyth case ARFE:
12074a4d8c2SCharles.Forsyth r->p1 = R;
12174a4d8c2SCharles.Forsyth r1->s1 = R;
12274a4d8c2SCharles.Forsyth }
12374a4d8c2SCharles.Forsyth
12474a4d8c2SCharles.Forsyth /*
12574a4d8c2SCharles.Forsyth * left side always read
12674a4d8c2SCharles.Forsyth */
12774a4d8c2SCharles.Forsyth bit = mkvar(&p->from, p->as==AMOVW);
12874a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
12974a4d8c2SCharles.Forsyth r->use1.b[z] |= bit.b[z];
13074a4d8c2SCharles.Forsyth
13174a4d8c2SCharles.Forsyth /*
13274a4d8c2SCharles.Forsyth * right side depends on opcode
13374a4d8c2SCharles.Forsyth */
13474a4d8c2SCharles.Forsyth bit = mkvar(&p->to, 0);
13574a4d8c2SCharles.Forsyth if(bany(&bit))
13674a4d8c2SCharles.Forsyth switch(p->as) {
13774a4d8c2SCharles.Forsyth default:
13874a4d8c2SCharles.Forsyth diag(Z, "reg: unknown asop: %A", p->as);
13974a4d8c2SCharles.Forsyth break;
14074a4d8c2SCharles.Forsyth
14174a4d8c2SCharles.Forsyth /*
14274a4d8c2SCharles.Forsyth * right side write
14374a4d8c2SCharles.Forsyth */
14474a4d8c2SCharles.Forsyth case ANOP:
14574a4d8c2SCharles.Forsyth case AMOVB:
14674a4d8c2SCharles.Forsyth case AMOVBU:
14774a4d8c2SCharles.Forsyth case AMOVH:
14874a4d8c2SCharles.Forsyth case AMOVHU:
14974a4d8c2SCharles.Forsyth case AMOVW:
15074a4d8c2SCharles.Forsyth case AMOVV:
15174a4d8c2SCharles.Forsyth case AMOVF:
15274a4d8c2SCharles.Forsyth case AMOVD:
15374a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
15474a4d8c2SCharles.Forsyth r->set.b[z] |= bit.b[z];
15574a4d8c2SCharles.Forsyth break;
15674a4d8c2SCharles.Forsyth
15774a4d8c2SCharles.Forsyth /*
15874a4d8c2SCharles.Forsyth * funny
15974a4d8c2SCharles.Forsyth */
16074a4d8c2SCharles.Forsyth case AJAL:
16174a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
16274a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
16374a4d8c2SCharles.Forsyth break;
16474a4d8c2SCharles.Forsyth }
16574a4d8c2SCharles.Forsyth }
16674a4d8c2SCharles.Forsyth if(firstr == R)
16774a4d8c2SCharles.Forsyth return;
16874a4d8c2SCharles.Forsyth initpc = pc - val;
16974a4d8c2SCharles.Forsyth npc = val;
17074a4d8c2SCharles.Forsyth
17174a4d8c2SCharles.Forsyth /*
17274a4d8c2SCharles.Forsyth * pass 2
17374a4d8c2SCharles.Forsyth * turn branch references to pointers
17474a4d8c2SCharles.Forsyth * build back pointers
17574a4d8c2SCharles.Forsyth */
17674a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
17774a4d8c2SCharles.Forsyth p = r->prog;
17874a4d8c2SCharles.Forsyth if(p->to.type == D_BRANCH) {
17974a4d8c2SCharles.Forsyth val = p->to.offset - initpc;
18074a4d8c2SCharles.Forsyth r1 = firstr;
18174a4d8c2SCharles.Forsyth while(r1 != R) {
18274a4d8c2SCharles.Forsyth r2 = r1->log5;
18374a4d8c2SCharles.Forsyth if(r2 != R && val >= r2->pc) {
18474a4d8c2SCharles.Forsyth r1 = r2;
18574a4d8c2SCharles.Forsyth continue;
18674a4d8c2SCharles.Forsyth }
18774a4d8c2SCharles.Forsyth if(r1->pc == val)
18874a4d8c2SCharles.Forsyth break;
18974a4d8c2SCharles.Forsyth r1 = r1->link;
19074a4d8c2SCharles.Forsyth }
19174a4d8c2SCharles.Forsyth if(r1 == R) {
19274a4d8c2SCharles.Forsyth nearln = p->lineno;
19374a4d8c2SCharles.Forsyth diag(Z, "ref not found\n%P", p);
19474a4d8c2SCharles.Forsyth continue;
19574a4d8c2SCharles.Forsyth }
19674a4d8c2SCharles.Forsyth if(r1 == r) {
19774a4d8c2SCharles.Forsyth nearln = p->lineno;
19874a4d8c2SCharles.Forsyth diag(Z, "ref to self\n%P", p);
19974a4d8c2SCharles.Forsyth continue;
20074a4d8c2SCharles.Forsyth }
20174a4d8c2SCharles.Forsyth r->s2 = r1;
20274a4d8c2SCharles.Forsyth r->p2link = r1->p2;
20374a4d8c2SCharles.Forsyth r1->p2 = r;
20474a4d8c2SCharles.Forsyth }
20574a4d8c2SCharles.Forsyth }
20674a4d8c2SCharles.Forsyth if(debug['R']) {
20774a4d8c2SCharles.Forsyth p = firstr->prog;
20874a4d8c2SCharles.Forsyth print("\n%L %D\n", p->lineno, &p->from);
20974a4d8c2SCharles.Forsyth }
21074a4d8c2SCharles.Forsyth
21174a4d8c2SCharles.Forsyth /*
21274a4d8c2SCharles.Forsyth * pass 2.5
21374a4d8c2SCharles.Forsyth * find looping structure
21474a4d8c2SCharles.Forsyth */
21574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
21674a4d8c2SCharles.Forsyth r->active = 0;
21774a4d8c2SCharles.Forsyth change = 0;
21874a4d8c2SCharles.Forsyth loopit(firstr, npc);
21974a4d8c2SCharles.Forsyth
22074a4d8c2SCharles.Forsyth /*
22174a4d8c2SCharles.Forsyth * pass 3
22274a4d8c2SCharles.Forsyth * iterate propagating usage
22374a4d8c2SCharles.Forsyth * back until flow graph is complete
22474a4d8c2SCharles.Forsyth */
22574a4d8c2SCharles.Forsyth loop1:
22674a4d8c2SCharles.Forsyth change = 0;
22774a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
22874a4d8c2SCharles.Forsyth r->active = 0;
22974a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
23074a4d8c2SCharles.Forsyth if(r->prog->as == ARET)
23174a4d8c2SCharles.Forsyth prop(r, zbits, zbits);
23274a4d8c2SCharles.Forsyth loop11:
23374a4d8c2SCharles.Forsyth /* pick up unreachable code */
23474a4d8c2SCharles.Forsyth i = 0;
23574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r1) {
23674a4d8c2SCharles.Forsyth r1 = r->link;
23774a4d8c2SCharles.Forsyth if(r1 && r1->active && !r->active) {
23874a4d8c2SCharles.Forsyth prop(r, zbits, zbits);
23974a4d8c2SCharles.Forsyth i = 1;
24074a4d8c2SCharles.Forsyth }
24174a4d8c2SCharles.Forsyth }
24274a4d8c2SCharles.Forsyth if(i)
24374a4d8c2SCharles.Forsyth goto loop11;
24474a4d8c2SCharles.Forsyth if(change)
24574a4d8c2SCharles.Forsyth goto loop1;
24674a4d8c2SCharles.Forsyth
24774a4d8c2SCharles.Forsyth
24874a4d8c2SCharles.Forsyth /*
24974a4d8c2SCharles.Forsyth * pass 4
25074a4d8c2SCharles.Forsyth * iterate propagating register/variable synchrony
25174a4d8c2SCharles.Forsyth * forward until graph is complete
25274a4d8c2SCharles.Forsyth */
25374a4d8c2SCharles.Forsyth loop2:
25474a4d8c2SCharles.Forsyth change = 0;
25574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
25674a4d8c2SCharles.Forsyth r->active = 0;
25774a4d8c2SCharles.Forsyth synch(firstr, zbits);
25874a4d8c2SCharles.Forsyth if(change)
25974a4d8c2SCharles.Forsyth goto loop2;
26074a4d8c2SCharles.Forsyth
26174a4d8c2SCharles.Forsyth addsplits();
26274a4d8c2SCharles.Forsyth
26374a4d8c2SCharles.Forsyth if(debug['R'] && debug['v']) {
26474a4d8c2SCharles.Forsyth print("\nprop structure:\n");
26574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
26674a4d8c2SCharles.Forsyth print("%ld:%P", r->loop, r->prog);
26774a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
26874a4d8c2SCharles.Forsyth bit.b[z] = r->set.b[z] |
26974a4d8c2SCharles.Forsyth r->refahead.b[z] | r->calahead.b[z] |
27074a4d8c2SCharles.Forsyth r->refbehind.b[z] | r->calbehind.b[z] |
27174a4d8c2SCharles.Forsyth r->use1.b[z] | r->use2.b[z];
27274a4d8c2SCharles.Forsyth if(bany(&bit)) {
27374a4d8c2SCharles.Forsyth print("\t");
27474a4d8c2SCharles.Forsyth if(bany(&r->use1))
27574a4d8c2SCharles.Forsyth print(" u1=%B", r->use1);
27674a4d8c2SCharles.Forsyth if(bany(&r->use2))
27774a4d8c2SCharles.Forsyth print(" u2=%B", r->use2);
27874a4d8c2SCharles.Forsyth if(bany(&r->set))
27974a4d8c2SCharles.Forsyth print(" st=%B", r->set);
28074a4d8c2SCharles.Forsyth if(bany(&r->refahead))
28174a4d8c2SCharles.Forsyth print(" ra=%B", r->refahead);
28274a4d8c2SCharles.Forsyth if(bany(&r->calahead))
28374a4d8c2SCharles.Forsyth print(" ca=%B", r->calahead);
28474a4d8c2SCharles.Forsyth if(bany(&r->refbehind))
28574a4d8c2SCharles.Forsyth print(" rb=%B", r->refbehind);
28674a4d8c2SCharles.Forsyth if(bany(&r->calbehind))
28774a4d8c2SCharles.Forsyth print(" cb=%B", r->calbehind);
28874a4d8c2SCharles.Forsyth }
28974a4d8c2SCharles.Forsyth print("\n");
29074a4d8c2SCharles.Forsyth }
29174a4d8c2SCharles.Forsyth }
29274a4d8c2SCharles.Forsyth
29374a4d8c2SCharles.Forsyth /*
29474a4d8c2SCharles.Forsyth * pass 5
29574a4d8c2SCharles.Forsyth * isolate regions
29674a4d8c2SCharles.Forsyth * calculate costs (paint1)
29774a4d8c2SCharles.Forsyth */
29874a4d8c2SCharles.Forsyth r = firstr;
29974a4d8c2SCharles.Forsyth if(r) {
30074a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
30174a4d8c2SCharles.Forsyth bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
30274a4d8c2SCharles.Forsyth ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
30374a4d8c2SCharles.Forsyth if(bany(&bit)) {
30474a4d8c2SCharles.Forsyth nearln = r->prog->lineno;
30574a4d8c2SCharles.Forsyth warn(Z, "used and not set: %B", bit);
30674a4d8c2SCharles.Forsyth if(debug['R'] && !debug['w'])
30774a4d8c2SCharles.Forsyth print("used and not set: %B\n", bit);
30874a4d8c2SCharles.Forsyth }
30974a4d8c2SCharles.Forsyth }
31074a4d8c2SCharles.Forsyth
31174a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link)
31274a4d8c2SCharles.Forsyth r->act = zbits;
31374a4d8c2SCharles.Forsyth rgp = region;
31474a4d8c2SCharles.Forsyth nregion = 0;
31574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
31674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
31774a4d8c2SCharles.Forsyth bit.b[z] = r->set.b[z] &
31874a4d8c2SCharles.Forsyth ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
31974a4d8c2SCharles.Forsyth if(bany(&bit)) {
32074a4d8c2SCharles.Forsyth nearln = r->prog->lineno;
32174a4d8c2SCharles.Forsyth warn(Z, "set and not used: %B", bit);
32274a4d8c2SCharles.Forsyth if(debug['R'])
32374a4d8c2SCharles.Forsyth print("set and not used: %B\n", bit);
32474a4d8c2SCharles.Forsyth excise(r);
32574a4d8c2SCharles.Forsyth }
32674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
32774a4d8c2SCharles.Forsyth bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
32874a4d8c2SCharles.Forsyth while(bany(&bit)) {
32974a4d8c2SCharles.Forsyth i = bnum(bit);
33074a4d8c2SCharles.Forsyth rgp->enter = r;
33174a4d8c2SCharles.Forsyth rgp->varno = i;
33274a4d8c2SCharles.Forsyth change = 0;
33374a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
33474a4d8c2SCharles.Forsyth print("\n");
33574a4d8c2SCharles.Forsyth paint1(r, i);
33674a4d8c2SCharles.Forsyth bit.b[i/32] &= ~(1L<<(i%32));
33774a4d8c2SCharles.Forsyth if(change <= 0) {
33874a4d8c2SCharles.Forsyth if(debug['R'])
33974a4d8c2SCharles.Forsyth print("%L $%d: %B\n",
34074a4d8c2SCharles.Forsyth r->prog->lineno, change, blsh(i));
34174a4d8c2SCharles.Forsyth continue;
34274a4d8c2SCharles.Forsyth }
34374a4d8c2SCharles.Forsyth rgp->cost = change;
34474a4d8c2SCharles.Forsyth nregion++;
34574a4d8c2SCharles.Forsyth if(nregion >= NRGN) {
34674a4d8c2SCharles.Forsyth warn(Z, "too many regions");
34774a4d8c2SCharles.Forsyth goto brk;
34874a4d8c2SCharles.Forsyth }
34974a4d8c2SCharles.Forsyth rgp++;
35074a4d8c2SCharles.Forsyth }
35174a4d8c2SCharles.Forsyth }
35274a4d8c2SCharles.Forsyth brk:
35374a4d8c2SCharles.Forsyth qsort(region, nregion, sizeof(region[0]), rcmp);
35474a4d8c2SCharles.Forsyth
35574a4d8c2SCharles.Forsyth /*
35674a4d8c2SCharles.Forsyth * pass 6
35774a4d8c2SCharles.Forsyth * determine used registers (paint2)
35874a4d8c2SCharles.Forsyth * replace code (paint3)
35974a4d8c2SCharles.Forsyth */
36074a4d8c2SCharles.Forsyth rgp = region;
36174a4d8c2SCharles.Forsyth for(i=0; i<nregion; i++) {
36274a4d8c2SCharles.Forsyth bit = blsh(rgp->varno);
36374a4d8c2SCharles.Forsyth vreg = paint2(rgp->enter, rgp->varno);
36474a4d8c2SCharles.Forsyth vreg = allreg(vreg, rgp);
36574a4d8c2SCharles.Forsyth if(debug['R']) {
36674a4d8c2SCharles.Forsyth if(rgp->regno >= NREG)
36774a4d8c2SCharles.Forsyth print("%L $%d F%d: %B\n",
36874a4d8c2SCharles.Forsyth rgp->enter->prog->lineno,
36974a4d8c2SCharles.Forsyth rgp->cost,
37074a4d8c2SCharles.Forsyth rgp->regno-NREG,
37174a4d8c2SCharles.Forsyth bit);
37274a4d8c2SCharles.Forsyth else
37374a4d8c2SCharles.Forsyth print("%L $%d R%d: %B\n",
37474a4d8c2SCharles.Forsyth rgp->enter->prog->lineno,
37574a4d8c2SCharles.Forsyth rgp->cost,
37674a4d8c2SCharles.Forsyth rgp->regno,
37774a4d8c2SCharles.Forsyth bit);
37874a4d8c2SCharles.Forsyth }
37974a4d8c2SCharles.Forsyth if(rgp->regno != 0)
38074a4d8c2SCharles.Forsyth paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
38174a4d8c2SCharles.Forsyth rgp++;
38274a4d8c2SCharles.Forsyth }
38374a4d8c2SCharles.Forsyth /*
38474a4d8c2SCharles.Forsyth * pass 7
38574a4d8c2SCharles.Forsyth * peep-hole on basic block
38674a4d8c2SCharles.Forsyth */
38774a4d8c2SCharles.Forsyth if(!debug['R'] || debug['P'])
38874a4d8c2SCharles.Forsyth peep();
38974a4d8c2SCharles.Forsyth
39074a4d8c2SCharles.Forsyth /*
39174a4d8c2SCharles.Forsyth * pass 8
39274a4d8c2SCharles.Forsyth * recalculate pc
39374a4d8c2SCharles.Forsyth */
39474a4d8c2SCharles.Forsyth val = initpc;
39574a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r1) {
39674a4d8c2SCharles.Forsyth r->pc = val;
39774a4d8c2SCharles.Forsyth p = r->prog;
39874a4d8c2SCharles.Forsyth p1 = P;
39974a4d8c2SCharles.Forsyth r1 = r->link;
40074a4d8c2SCharles.Forsyth if(r1 != R)
40174a4d8c2SCharles.Forsyth p1 = r1->prog;
40274a4d8c2SCharles.Forsyth for(; p != p1; p = p->link) {
40374a4d8c2SCharles.Forsyth switch(p->as) {
40474a4d8c2SCharles.Forsyth default:
40574a4d8c2SCharles.Forsyth val++;
40674a4d8c2SCharles.Forsyth break;
40774a4d8c2SCharles.Forsyth
40874a4d8c2SCharles.Forsyth case ANOP:
40974a4d8c2SCharles.Forsyth case ADATA:
41074a4d8c2SCharles.Forsyth case AGLOBL:
41174a4d8c2SCharles.Forsyth case ANAME:
41274a4d8c2SCharles.Forsyth case ASIGNAME:
41374a4d8c2SCharles.Forsyth break;
41474a4d8c2SCharles.Forsyth }
41574a4d8c2SCharles.Forsyth }
41674a4d8c2SCharles.Forsyth }
41774a4d8c2SCharles.Forsyth pc = val;
41874a4d8c2SCharles.Forsyth
41974a4d8c2SCharles.Forsyth /*
42074a4d8c2SCharles.Forsyth * fix up branches
42174a4d8c2SCharles.Forsyth */
42274a4d8c2SCharles.Forsyth if(debug['R'])
42374a4d8c2SCharles.Forsyth if(bany(&addrs))
42474a4d8c2SCharles.Forsyth print("addrs: %B\n", addrs);
42574a4d8c2SCharles.Forsyth
42674a4d8c2SCharles.Forsyth r1 = 0; /* set */
42774a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
42874a4d8c2SCharles.Forsyth p = r->prog;
42974a4d8c2SCharles.Forsyth if(p->to.type == D_BRANCH)
43074a4d8c2SCharles.Forsyth p->to.offset = r->s2->pc;
43174a4d8c2SCharles.Forsyth r1 = r;
43274a4d8c2SCharles.Forsyth }
43374a4d8c2SCharles.Forsyth
43474a4d8c2SCharles.Forsyth /*
43574a4d8c2SCharles.Forsyth * last pass
43674a4d8c2SCharles.Forsyth * eliminate nops
43774a4d8c2SCharles.Forsyth * free aux structures
43874a4d8c2SCharles.Forsyth */
43974a4d8c2SCharles.Forsyth for(p = firstr->prog; p != P; p = p->link){
44074a4d8c2SCharles.Forsyth while(p->link && p->link->as == ANOP)
44174a4d8c2SCharles.Forsyth p->link = p->link->link;
44274a4d8c2SCharles.Forsyth }
44374a4d8c2SCharles.Forsyth if(r1 != R) {
44474a4d8c2SCharles.Forsyth r1->link = freer;
44574a4d8c2SCharles.Forsyth freer = firstr;
44674a4d8c2SCharles.Forsyth }
44774a4d8c2SCharles.Forsyth }
44874a4d8c2SCharles.Forsyth
44974a4d8c2SCharles.Forsyth void
addsplits(void)45074a4d8c2SCharles.Forsyth addsplits(void)
45174a4d8c2SCharles.Forsyth {
45274a4d8c2SCharles.Forsyth Reg *r, *r1;
45374a4d8c2SCharles.Forsyth int z, i;
45474a4d8c2SCharles.Forsyth Bits bit;
45574a4d8c2SCharles.Forsyth
45674a4d8c2SCharles.Forsyth for(r = firstr; r != R; r = r->link) {
45774a4d8c2SCharles.Forsyth if(r->loop > 1)
45874a4d8c2SCharles.Forsyth continue;
45974a4d8c2SCharles.Forsyth if(r->prog->as == AJAL)
46074a4d8c2SCharles.Forsyth continue;
46174a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
46274a4d8c2SCharles.Forsyth if(r1->loop <= 1)
46374a4d8c2SCharles.Forsyth continue;
46474a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
46574a4d8c2SCharles.Forsyth bit.b[z] = r1->calbehind.b[z] &
46674a4d8c2SCharles.Forsyth (r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
46774a4d8c2SCharles.Forsyth ~(r->calahead.b[z] & addrs.b[z]);
46874a4d8c2SCharles.Forsyth while(bany(&bit)) {
46974a4d8c2SCharles.Forsyth i = bnum(bit);
47074a4d8c2SCharles.Forsyth bit.b[i/32] &= ~(1L << (i%32));
47174a4d8c2SCharles.Forsyth }
47274a4d8c2SCharles.Forsyth }
47374a4d8c2SCharles.Forsyth }
47474a4d8c2SCharles.Forsyth }
47574a4d8c2SCharles.Forsyth
47674a4d8c2SCharles.Forsyth /*
47774a4d8c2SCharles.Forsyth * add mov b,rn
47874a4d8c2SCharles.Forsyth * just after r
47974a4d8c2SCharles.Forsyth */
48074a4d8c2SCharles.Forsyth void
addmove(Reg * r,int bn,int rn,int f)48174a4d8c2SCharles.Forsyth addmove(Reg *r, int bn, int rn, int f)
48274a4d8c2SCharles.Forsyth {
48374a4d8c2SCharles.Forsyth Prog *p, *p1;
48474a4d8c2SCharles.Forsyth Adr *a;
48574a4d8c2SCharles.Forsyth Var *v;
48674a4d8c2SCharles.Forsyth
48774a4d8c2SCharles.Forsyth p1 = alloc(sizeof(*p1));
48874a4d8c2SCharles.Forsyth *p1 = zprog;
48974a4d8c2SCharles.Forsyth p = r->prog;
49074a4d8c2SCharles.Forsyth
49174a4d8c2SCharles.Forsyth p1->link = p->link;
49274a4d8c2SCharles.Forsyth p->link = p1;
49374a4d8c2SCharles.Forsyth p1->lineno = p->lineno;
49474a4d8c2SCharles.Forsyth
49574a4d8c2SCharles.Forsyth v = var + bn;
49674a4d8c2SCharles.Forsyth
49774a4d8c2SCharles.Forsyth a = &p1->to;
49874a4d8c2SCharles.Forsyth a->sym = v->sym;
49974a4d8c2SCharles.Forsyth a->name = v->name;
50074a4d8c2SCharles.Forsyth a->offset = v->offset;
50174a4d8c2SCharles.Forsyth a->etype = v->etype;
50274a4d8c2SCharles.Forsyth a->type = D_OREG;
50374a4d8c2SCharles.Forsyth if(a->etype == TARRAY || a->sym == S)
50474a4d8c2SCharles.Forsyth a->type = D_CONST;
50574a4d8c2SCharles.Forsyth
50674a4d8c2SCharles.Forsyth p1->as = AMOVW;
50774a4d8c2SCharles.Forsyth if(v->etype == TCHAR || v->etype == TUCHAR)
50874a4d8c2SCharles.Forsyth p1->as = AMOVB;
50974a4d8c2SCharles.Forsyth if(v->etype == TSHORT || v->etype == TUSHORT)
51074a4d8c2SCharles.Forsyth p1->as = AMOVH;
51174a4d8c2SCharles.Forsyth if(v->etype == TVLONG || v->etype == TUVLONG)
51274a4d8c2SCharles.Forsyth p1->as = AMOVV;
51374a4d8c2SCharles.Forsyth if(v->etype == TFLOAT)
51474a4d8c2SCharles.Forsyth p1->as = AMOVF;
51574a4d8c2SCharles.Forsyth if(v->etype == TDOUBLE)
51674a4d8c2SCharles.Forsyth p1->as = AMOVD;
51774a4d8c2SCharles.Forsyth
51874a4d8c2SCharles.Forsyth p1->from.type = D_REG;
51974a4d8c2SCharles.Forsyth p1->from.reg = rn;
52074a4d8c2SCharles.Forsyth if(rn >= NREG) {
52174a4d8c2SCharles.Forsyth p1->from.type = D_FREG;
52274a4d8c2SCharles.Forsyth p1->from.reg = rn-NREG;
52374a4d8c2SCharles.Forsyth }
52474a4d8c2SCharles.Forsyth if(!f) {
52574a4d8c2SCharles.Forsyth p1->from = *a;
52674a4d8c2SCharles.Forsyth *a = zprog.from;
52774a4d8c2SCharles.Forsyth a->type = D_REG;
52874a4d8c2SCharles.Forsyth a->reg = rn;
52974a4d8c2SCharles.Forsyth if(rn >= NREG) {
53074a4d8c2SCharles.Forsyth a->type = D_FREG;
53174a4d8c2SCharles.Forsyth a->reg = rn-NREG;
53274a4d8c2SCharles.Forsyth }
53374a4d8c2SCharles.Forsyth if(v->etype == TUCHAR)
53474a4d8c2SCharles.Forsyth p1->as = AMOVBU;
53574a4d8c2SCharles.Forsyth if(v->etype == TUSHORT)
53674a4d8c2SCharles.Forsyth p1->as = AMOVHU;
53774a4d8c2SCharles.Forsyth }
53874a4d8c2SCharles.Forsyth if(debug['R'])
53974a4d8c2SCharles.Forsyth print("%P\t.a%P\n", p, p1);
54074a4d8c2SCharles.Forsyth }
54174a4d8c2SCharles.Forsyth
54274a4d8c2SCharles.Forsyth Bits
mkvar(Adr * a,int docon)54374a4d8c2SCharles.Forsyth mkvar(Adr *a, int docon)
54474a4d8c2SCharles.Forsyth {
54574a4d8c2SCharles.Forsyth Var *v;
54674a4d8c2SCharles.Forsyth int i, t, n, et, z;
54774a4d8c2SCharles.Forsyth long o;
54874a4d8c2SCharles.Forsyth Bits bit;
54974a4d8c2SCharles.Forsyth Sym *s;
55074a4d8c2SCharles.Forsyth
55174a4d8c2SCharles.Forsyth t = a->type;
55274a4d8c2SCharles.Forsyth if(t == D_REG && a->reg != NREG)
55374a4d8c2SCharles.Forsyth regbits |= RtoB(a->reg);
55474a4d8c2SCharles.Forsyth if(t == D_FREG && a->reg != NREG)
55574a4d8c2SCharles.Forsyth regbits |= FtoB(a->reg);
55674a4d8c2SCharles.Forsyth s = a->sym;
55774a4d8c2SCharles.Forsyth o = a->offset;
55874a4d8c2SCharles.Forsyth et = a->etype;
55974a4d8c2SCharles.Forsyth if(s == S) {
56074a4d8c2SCharles.Forsyth if(t != D_CONST || !docon || a->reg != NREG)
56174a4d8c2SCharles.Forsyth goto none;
56274a4d8c2SCharles.Forsyth et = TLONG;
56374a4d8c2SCharles.Forsyth }
56474a4d8c2SCharles.Forsyth if(t == D_CONST) {
56574a4d8c2SCharles.Forsyth if(s == S && sval(o))
56674a4d8c2SCharles.Forsyth goto none;
56774a4d8c2SCharles.Forsyth }
56874a4d8c2SCharles.Forsyth
56974a4d8c2SCharles.Forsyth n = a->name;
57074a4d8c2SCharles.Forsyth v = var;
57174a4d8c2SCharles.Forsyth for(i=0; i<nvar; i++) {
57274a4d8c2SCharles.Forsyth if(s == v->sym)
57374a4d8c2SCharles.Forsyth if(n == v->name)
57474a4d8c2SCharles.Forsyth if(o == v->offset)
57574a4d8c2SCharles.Forsyth goto out;
57674a4d8c2SCharles.Forsyth v++;
57774a4d8c2SCharles.Forsyth }
57874a4d8c2SCharles.Forsyth if(s)
57974a4d8c2SCharles.Forsyth if(s->name[0] == '.')
58074a4d8c2SCharles.Forsyth goto none;
58174a4d8c2SCharles.Forsyth if(nvar >= NVAR) {
58274a4d8c2SCharles.Forsyth if(debug['w'] > 1 && s)
58374a4d8c2SCharles.Forsyth warn(Z, "variable not optimized: %s", s->name);
58474a4d8c2SCharles.Forsyth goto none;
58574a4d8c2SCharles.Forsyth }
58674a4d8c2SCharles.Forsyth i = nvar;
58774a4d8c2SCharles.Forsyth nvar++;
58874a4d8c2SCharles.Forsyth v = &var[i];
58974a4d8c2SCharles.Forsyth v->sym = s;
59074a4d8c2SCharles.Forsyth v->offset = o;
59174a4d8c2SCharles.Forsyth v->etype = et;
59274a4d8c2SCharles.Forsyth v->name = n;
59374a4d8c2SCharles.Forsyth if(debug['R'])
59474a4d8c2SCharles.Forsyth print("bit=%2d et=%2d %D\n", i, et, a);
59574a4d8c2SCharles.Forsyth out:
59674a4d8c2SCharles.Forsyth bit = blsh(i);
59774a4d8c2SCharles.Forsyth if(n == D_EXTERN || n == D_STATIC)
59874a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
59974a4d8c2SCharles.Forsyth externs.b[z] |= bit.b[z];
60074a4d8c2SCharles.Forsyth if(n == D_PARAM)
60174a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
60274a4d8c2SCharles.Forsyth params.b[z] |= bit.b[z];
60374a4d8c2SCharles.Forsyth if(v->etype != et || !(typechlpfd[et]/* || typev[et]*/)) /* funny punning */
60474a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
60574a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
60674a4d8c2SCharles.Forsyth if(t == D_CONST) {
60774a4d8c2SCharles.Forsyth if(s == S) {
60874a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
60974a4d8c2SCharles.Forsyth consts.b[z] |= bit.b[z];
61074a4d8c2SCharles.Forsyth return bit;
61174a4d8c2SCharles.Forsyth }
61274a4d8c2SCharles.Forsyth if(et != TARRAY)
61374a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
61474a4d8c2SCharles.Forsyth addrs.b[z] |= bit.b[z];
61574a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
61674a4d8c2SCharles.Forsyth params.b[z] |= bit.b[z];
61774a4d8c2SCharles.Forsyth return bit;
61874a4d8c2SCharles.Forsyth }
61974a4d8c2SCharles.Forsyth if(t == D_OREG)
62074a4d8c2SCharles.Forsyth return bit;
62174a4d8c2SCharles.Forsyth
62274a4d8c2SCharles.Forsyth none:
62374a4d8c2SCharles.Forsyth return zbits;
62474a4d8c2SCharles.Forsyth }
62574a4d8c2SCharles.Forsyth
62674a4d8c2SCharles.Forsyth void
prop(Reg * r,Bits ref,Bits cal)62774a4d8c2SCharles.Forsyth prop(Reg *r, Bits ref, Bits cal)
62874a4d8c2SCharles.Forsyth {
62974a4d8c2SCharles.Forsyth Reg *r1, *r2;
63074a4d8c2SCharles.Forsyth int z;
63174a4d8c2SCharles.Forsyth
63274a4d8c2SCharles.Forsyth for(r1 = r; r1 != R; r1 = r1->p1) {
63374a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
63474a4d8c2SCharles.Forsyth ref.b[z] |= r1->refahead.b[z];
63574a4d8c2SCharles.Forsyth if(ref.b[z] != r1->refahead.b[z]) {
63674a4d8c2SCharles.Forsyth r1->refahead.b[z] = ref.b[z];
63774a4d8c2SCharles.Forsyth change++;
63874a4d8c2SCharles.Forsyth }
63974a4d8c2SCharles.Forsyth cal.b[z] |= r1->calahead.b[z];
64074a4d8c2SCharles.Forsyth if(cal.b[z] != r1->calahead.b[z]) {
64174a4d8c2SCharles.Forsyth r1->calahead.b[z] = cal.b[z];
64274a4d8c2SCharles.Forsyth change++;
64374a4d8c2SCharles.Forsyth }
64474a4d8c2SCharles.Forsyth }
64574a4d8c2SCharles.Forsyth switch(r1->prog->as) {
64674a4d8c2SCharles.Forsyth case AJAL:
64774a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
64874a4d8c2SCharles.Forsyth cal.b[z] |= ref.b[z] | externs.b[z];
64974a4d8c2SCharles.Forsyth ref.b[z] = 0;
65074a4d8c2SCharles.Forsyth }
65174a4d8c2SCharles.Forsyth break;
65274a4d8c2SCharles.Forsyth
65374a4d8c2SCharles.Forsyth case ATEXT:
65474a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
65574a4d8c2SCharles.Forsyth cal.b[z] = 0;
65674a4d8c2SCharles.Forsyth ref.b[z] = 0;
65774a4d8c2SCharles.Forsyth }
65874a4d8c2SCharles.Forsyth break;
65974a4d8c2SCharles.Forsyth
66074a4d8c2SCharles.Forsyth case ARET:
66174a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
66274a4d8c2SCharles.Forsyth cal.b[z] = externs.b[z];
66374a4d8c2SCharles.Forsyth ref.b[z] = 0;
66474a4d8c2SCharles.Forsyth }
66574a4d8c2SCharles.Forsyth }
66674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
66774a4d8c2SCharles.Forsyth ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
66874a4d8c2SCharles.Forsyth r1->use1.b[z] | r1->use2.b[z];
66974a4d8c2SCharles.Forsyth cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
67074a4d8c2SCharles.Forsyth r1->refbehind.b[z] = ref.b[z];
67174a4d8c2SCharles.Forsyth r1->calbehind.b[z] = cal.b[z];
67274a4d8c2SCharles.Forsyth }
67374a4d8c2SCharles.Forsyth if(r1->active)
67474a4d8c2SCharles.Forsyth break;
67574a4d8c2SCharles.Forsyth r1->active = 1;
67674a4d8c2SCharles.Forsyth }
67774a4d8c2SCharles.Forsyth for(; r != r1; r = r->p1)
67874a4d8c2SCharles.Forsyth for(r2 = r->p2; r2 != R; r2 = r2->p2link)
67974a4d8c2SCharles.Forsyth prop(r2, r->refbehind, r->calbehind);
68074a4d8c2SCharles.Forsyth }
68174a4d8c2SCharles.Forsyth
68274a4d8c2SCharles.Forsyth /*
68374a4d8c2SCharles.Forsyth * find looping structure
68474a4d8c2SCharles.Forsyth *
68574a4d8c2SCharles.Forsyth * 1) find reverse postordering
68674a4d8c2SCharles.Forsyth * 2) find approximate dominators,
68774a4d8c2SCharles.Forsyth * the actual dominators if the flow graph is reducible
68874a4d8c2SCharles.Forsyth * otherwise, dominators plus some other non-dominators.
68974a4d8c2SCharles.Forsyth * See Matthew S. Hecht and Jeffrey D. Ullman,
69074a4d8c2SCharles.Forsyth * "Analysis of a Simple Algorithm for Global Data Flow Problems",
69174a4d8c2SCharles.Forsyth * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
69274a4d8c2SCharles.Forsyth * Oct. 1-3, 1973, pp. 207-217.
69374a4d8c2SCharles.Forsyth * 3) find all nodes with a predecessor dominated by the current node.
69474a4d8c2SCharles.Forsyth * such a node is a loop head.
69574a4d8c2SCharles.Forsyth * recursively, all preds with a greater rpo number are in the loop
69674a4d8c2SCharles.Forsyth */
69774a4d8c2SCharles.Forsyth long
postorder(Reg * r,Reg ** rpo2r,long n)69874a4d8c2SCharles.Forsyth postorder(Reg *r, Reg **rpo2r, long n)
69974a4d8c2SCharles.Forsyth {
70074a4d8c2SCharles.Forsyth Reg *r1;
70174a4d8c2SCharles.Forsyth
70274a4d8c2SCharles.Forsyth r->rpo = 1;
70374a4d8c2SCharles.Forsyth r1 = r->s1;
70474a4d8c2SCharles.Forsyth if(r1 && !r1->rpo)
70574a4d8c2SCharles.Forsyth n = postorder(r1, rpo2r, n);
70674a4d8c2SCharles.Forsyth r1 = r->s2;
70774a4d8c2SCharles.Forsyth if(r1 && !r1->rpo)
70874a4d8c2SCharles.Forsyth n = postorder(r1, rpo2r, n);
70974a4d8c2SCharles.Forsyth rpo2r[n] = r;
71074a4d8c2SCharles.Forsyth n++;
71174a4d8c2SCharles.Forsyth return n;
71274a4d8c2SCharles.Forsyth }
71374a4d8c2SCharles.Forsyth
71474a4d8c2SCharles.Forsyth long
rpolca(long * idom,long rpo1,long rpo2)71574a4d8c2SCharles.Forsyth rpolca(long *idom, long rpo1, long rpo2)
71674a4d8c2SCharles.Forsyth {
71774a4d8c2SCharles.Forsyth long t;
71874a4d8c2SCharles.Forsyth
71974a4d8c2SCharles.Forsyth if(rpo1 == -1)
72074a4d8c2SCharles.Forsyth return rpo2;
72174a4d8c2SCharles.Forsyth while(rpo1 != rpo2){
72274a4d8c2SCharles.Forsyth if(rpo1 > rpo2){
72374a4d8c2SCharles.Forsyth t = rpo2;
72474a4d8c2SCharles.Forsyth rpo2 = rpo1;
72574a4d8c2SCharles.Forsyth rpo1 = t;
72674a4d8c2SCharles.Forsyth }
72774a4d8c2SCharles.Forsyth while(rpo1 < rpo2){
72874a4d8c2SCharles.Forsyth t = idom[rpo2];
72974a4d8c2SCharles.Forsyth if(t >= rpo2)
73074a4d8c2SCharles.Forsyth fatal(Z, "bad idom");
73174a4d8c2SCharles.Forsyth rpo2 = t;
73274a4d8c2SCharles.Forsyth }
73374a4d8c2SCharles.Forsyth }
73474a4d8c2SCharles.Forsyth return rpo1;
73574a4d8c2SCharles.Forsyth }
73674a4d8c2SCharles.Forsyth
73774a4d8c2SCharles.Forsyth int
doms(long * idom,long r,long s)73874a4d8c2SCharles.Forsyth doms(long *idom, long r, long s)
73974a4d8c2SCharles.Forsyth {
74074a4d8c2SCharles.Forsyth while(s > r)
74174a4d8c2SCharles.Forsyth s = idom[s];
74274a4d8c2SCharles.Forsyth return s == r;
74374a4d8c2SCharles.Forsyth }
74474a4d8c2SCharles.Forsyth
74574a4d8c2SCharles.Forsyth int
loophead(long * idom,Reg * r)74674a4d8c2SCharles.Forsyth loophead(long *idom, Reg *r)
74774a4d8c2SCharles.Forsyth {
74874a4d8c2SCharles.Forsyth long src;
74974a4d8c2SCharles.Forsyth
75074a4d8c2SCharles.Forsyth src = r->rpo;
75174a4d8c2SCharles.Forsyth if(r->p1 != R && doms(idom, src, r->p1->rpo))
75274a4d8c2SCharles.Forsyth return 1;
75374a4d8c2SCharles.Forsyth for(r = r->p2; r != R; r = r->p2link)
75474a4d8c2SCharles.Forsyth if(doms(idom, src, r->rpo))
75574a4d8c2SCharles.Forsyth return 1;
75674a4d8c2SCharles.Forsyth return 0;
75774a4d8c2SCharles.Forsyth }
75874a4d8c2SCharles.Forsyth
75974a4d8c2SCharles.Forsyth void
loopmark(Reg ** rpo2r,long head,Reg * r)76074a4d8c2SCharles.Forsyth loopmark(Reg **rpo2r, long head, Reg *r)
76174a4d8c2SCharles.Forsyth {
76274a4d8c2SCharles.Forsyth if(r->rpo < head || r->active == head)
76374a4d8c2SCharles.Forsyth return;
76474a4d8c2SCharles.Forsyth r->active = head;
76574a4d8c2SCharles.Forsyth r->loop += LOOP;
76674a4d8c2SCharles.Forsyth if(r->p1 != R)
76774a4d8c2SCharles.Forsyth loopmark(rpo2r, head, r->p1);
76874a4d8c2SCharles.Forsyth for(r = r->p2; r != R; r = r->p2link)
76974a4d8c2SCharles.Forsyth loopmark(rpo2r, head, r);
77074a4d8c2SCharles.Forsyth }
77174a4d8c2SCharles.Forsyth
77274a4d8c2SCharles.Forsyth void
loopit(Reg * r,long nr)77374a4d8c2SCharles.Forsyth loopit(Reg *r, long nr)
77474a4d8c2SCharles.Forsyth {
77574a4d8c2SCharles.Forsyth Reg *r1;
77674a4d8c2SCharles.Forsyth long i, d, me;
77774a4d8c2SCharles.Forsyth
77874a4d8c2SCharles.Forsyth if(nr > maxnr) {
77974a4d8c2SCharles.Forsyth rpo2r = alloc(nr * sizeof(Reg*));
78074a4d8c2SCharles.Forsyth idom = alloc(nr * sizeof(long));
78174a4d8c2SCharles.Forsyth maxnr = nr;
78274a4d8c2SCharles.Forsyth }
78374a4d8c2SCharles.Forsyth
78474a4d8c2SCharles.Forsyth d = postorder(r, rpo2r, 0);
78574a4d8c2SCharles.Forsyth if(d > nr)
78674a4d8c2SCharles.Forsyth fatal(Z, "too many reg nodes");
78774a4d8c2SCharles.Forsyth nr = d;
78874a4d8c2SCharles.Forsyth for(i = 0; i < nr / 2; i++){
78974a4d8c2SCharles.Forsyth r1 = rpo2r[i];
79074a4d8c2SCharles.Forsyth rpo2r[i] = rpo2r[nr - 1 - i];
79174a4d8c2SCharles.Forsyth rpo2r[nr - 1 - i] = r1;
79274a4d8c2SCharles.Forsyth }
79374a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++)
79474a4d8c2SCharles.Forsyth rpo2r[i]->rpo = i;
79574a4d8c2SCharles.Forsyth
79674a4d8c2SCharles.Forsyth idom[0] = 0;
79774a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++){
79874a4d8c2SCharles.Forsyth r1 = rpo2r[i];
79974a4d8c2SCharles.Forsyth me = r1->rpo;
80074a4d8c2SCharles.Forsyth d = -1;
80174a4d8c2SCharles.Forsyth if(r1->p1 != R && r1->p1->rpo < me)
80274a4d8c2SCharles.Forsyth d = r1->p1->rpo;
80374a4d8c2SCharles.Forsyth for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
80474a4d8c2SCharles.Forsyth if(r1->rpo < me)
80574a4d8c2SCharles.Forsyth d = rpolca(idom, d, r1->rpo);
80674a4d8c2SCharles.Forsyth idom[i] = d;
80774a4d8c2SCharles.Forsyth }
80874a4d8c2SCharles.Forsyth
80974a4d8c2SCharles.Forsyth for(i = 0; i < nr; i++){
81074a4d8c2SCharles.Forsyth r1 = rpo2r[i];
81174a4d8c2SCharles.Forsyth r1->loop++;
81274a4d8c2SCharles.Forsyth if(r1->p2 != R && loophead(idom, r1))
81374a4d8c2SCharles.Forsyth loopmark(rpo2r, i, r1);
81474a4d8c2SCharles.Forsyth }
81574a4d8c2SCharles.Forsyth }
81674a4d8c2SCharles.Forsyth
81774a4d8c2SCharles.Forsyth void
synch(Reg * r,Bits dif)81874a4d8c2SCharles.Forsyth synch(Reg *r, Bits dif)
81974a4d8c2SCharles.Forsyth {
82074a4d8c2SCharles.Forsyth Reg *r1;
82174a4d8c2SCharles.Forsyth int z;
82274a4d8c2SCharles.Forsyth
82374a4d8c2SCharles.Forsyth for(r1 = r; r1 != R; r1 = r1->s1) {
82474a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++) {
82574a4d8c2SCharles.Forsyth dif.b[z] = (dif.b[z] &
82674a4d8c2SCharles.Forsyth ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
82774a4d8c2SCharles.Forsyth r1->set.b[z] | r1->regdiff.b[z];
82874a4d8c2SCharles.Forsyth if(dif.b[z] != r1->regdiff.b[z]) {
82974a4d8c2SCharles.Forsyth r1->regdiff.b[z] = dif.b[z];
83074a4d8c2SCharles.Forsyth change++;
83174a4d8c2SCharles.Forsyth }
83274a4d8c2SCharles.Forsyth }
83374a4d8c2SCharles.Forsyth if(r1->active)
83474a4d8c2SCharles.Forsyth break;
83574a4d8c2SCharles.Forsyth r1->active = 1;
83674a4d8c2SCharles.Forsyth for(z=0; z<BITS; z++)
83774a4d8c2SCharles.Forsyth dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
83874a4d8c2SCharles.Forsyth if(r1->s2 != R)
83974a4d8c2SCharles.Forsyth synch(r1->s2, dif);
84074a4d8c2SCharles.Forsyth }
84174a4d8c2SCharles.Forsyth }
84274a4d8c2SCharles.Forsyth
84374a4d8c2SCharles.Forsyth ulong
allreg(ulong b,Rgn * r)84474a4d8c2SCharles.Forsyth allreg(ulong b, Rgn *r)
84574a4d8c2SCharles.Forsyth {
84674a4d8c2SCharles.Forsyth Var *v;
84774a4d8c2SCharles.Forsyth int i;
84874a4d8c2SCharles.Forsyth
84974a4d8c2SCharles.Forsyth v = var + r->varno;
85074a4d8c2SCharles.Forsyth r->regno = 0;
85174a4d8c2SCharles.Forsyth switch(v->etype) {
85274a4d8c2SCharles.Forsyth
85374a4d8c2SCharles.Forsyth default:
85474a4d8c2SCharles.Forsyth diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
85574a4d8c2SCharles.Forsyth break;
85674a4d8c2SCharles.Forsyth
85774a4d8c2SCharles.Forsyth case TCHAR:
85874a4d8c2SCharles.Forsyth case TUCHAR:
85974a4d8c2SCharles.Forsyth case TSHORT:
86074a4d8c2SCharles.Forsyth case TUSHORT:
86174a4d8c2SCharles.Forsyth case TINT:
86274a4d8c2SCharles.Forsyth case TUINT:
86374a4d8c2SCharles.Forsyth case TLONG:
86474a4d8c2SCharles.Forsyth case TULONG:
86574a4d8c2SCharles.Forsyth case TVLONG:
86674a4d8c2SCharles.Forsyth case TUVLONG:
86774a4d8c2SCharles.Forsyth case TIND:
86874a4d8c2SCharles.Forsyth case TARRAY:
86974a4d8c2SCharles.Forsyth i = BtoR(~b);
87074a4d8c2SCharles.Forsyth if(i && r->cost >= 0) {
87174a4d8c2SCharles.Forsyth r->regno = i;
87274a4d8c2SCharles.Forsyth return RtoB(i);
87374a4d8c2SCharles.Forsyth }
87474a4d8c2SCharles.Forsyth break;
87574a4d8c2SCharles.Forsyth
87674a4d8c2SCharles.Forsyth case TDOUBLE:
87774a4d8c2SCharles.Forsyth case TFLOAT:
87874a4d8c2SCharles.Forsyth i = BtoF(~b);
87974a4d8c2SCharles.Forsyth if(i && r->cost >= 0) {
88074a4d8c2SCharles.Forsyth r->regno = i+NREG;
88174a4d8c2SCharles.Forsyth return FtoB(i);
88274a4d8c2SCharles.Forsyth }
88374a4d8c2SCharles.Forsyth break;
88474a4d8c2SCharles.Forsyth }
88574a4d8c2SCharles.Forsyth return 0;
88674a4d8c2SCharles.Forsyth }
88774a4d8c2SCharles.Forsyth
88874a4d8c2SCharles.Forsyth void
paint1(Reg * r,int bn)88974a4d8c2SCharles.Forsyth paint1(Reg *r, int bn)
89074a4d8c2SCharles.Forsyth {
89174a4d8c2SCharles.Forsyth Reg *r1;
89274a4d8c2SCharles.Forsyth Prog *p;
89374a4d8c2SCharles.Forsyth int z;
89474a4d8c2SCharles.Forsyth ulong bb;
89574a4d8c2SCharles.Forsyth
89674a4d8c2SCharles.Forsyth z = bn/32;
89774a4d8c2SCharles.Forsyth bb = 1L<<(bn%32);
89874a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
89974a4d8c2SCharles.Forsyth return;
90074a4d8c2SCharles.Forsyth for(;;) {
90174a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
90274a4d8c2SCharles.Forsyth break;
90374a4d8c2SCharles.Forsyth r1 = r->p1;
90474a4d8c2SCharles.Forsyth if(r1 == R)
90574a4d8c2SCharles.Forsyth break;
90674a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
90774a4d8c2SCharles.Forsyth break;
90874a4d8c2SCharles.Forsyth if(r1->act.b[z] & bb)
90974a4d8c2SCharles.Forsyth break;
91074a4d8c2SCharles.Forsyth r = r1;
91174a4d8c2SCharles.Forsyth }
91274a4d8c2SCharles.Forsyth
91374a4d8c2SCharles.Forsyth if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
91474a4d8c2SCharles.Forsyth change -= CLOAD * r->loop;
91574a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
91674a4d8c2SCharles.Forsyth print("%ld%P\tld %B $%d\n", r->loop,
91774a4d8c2SCharles.Forsyth r->prog, blsh(bn), change);
91874a4d8c2SCharles.Forsyth }
91974a4d8c2SCharles.Forsyth for(;;) {
92074a4d8c2SCharles.Forsyth r->act.b[z] |= bb;
92174a4d8c2SCharles.Forsyth p = r->prog;
92274a4d8c2SCharles.Forsyth
92374a4d8c2SCharles.Forsyth if(r->use1.b[z] & bb) {
92474a4d8c2SCharles.Forsyth change += CREF * r->loop;
92574a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
92674a4d8c2SCharles.Forsyth print("%ld%P\tu1 %B $%d\n", r->loop,
92774a4d8c2SCharles.Forsyth p, blsh(bn), change);
92874a4d8c2SCharles.Forsyth }
92974a4d8c2SCharles.Forsyth
93074a4d8c2SCharles.Forsyth if((r->use2.b[z]|r->set.b[z]) & bb) {
93174a4d8c2SCharles.Forsyth change += CREF * r->loop;
93274a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
93374a4d8c2SCharles.Forsyth print("%ld%P\tu2 %B $%d\n", r->loop,
93474a4d8c2SCharles.Forsyth p, blsh(bn), change);
93574a4d8c2SCharles.Forsyth }
93674a4d8c2SCharles.Forsyth
93774a4d8c2SCharles.Forsyth if(STORE(r) & r->regdiff.b[z] & bb) {
93874a4d8c2SCharles.Forsyth change -= CLOAD * r->loop;
93974a4d8c2SCharles.Forsyth if(debug['R'] && debug['v'])
94074a4d8c2SCharles.Forsyth print("%ld%P\tst %B $%d\n", r->loop,
94174a4d8c2SCharles.Forsyth p, blsh(bn), change);
94274a4d8c2SCharles.Forsyth }
94374a4d8c2SCharles.Forsyth
94474a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
94574a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
94674a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
94774a4d8c2SCharles.Forsyth paint1(r1, bn);
94874a4d8c2SCharles.Forsyth
94974a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
95074a4d8c2SCharles.Forsyth break;
95174a4d8c2SCharles.Forsyth r1 = r->s2;
95274a4d8c2SCharles.Forsyth if(r1 != R)
95374a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
95474a4d8c2SCharles.Forsyth paint1(r1, bn);
95574a4d8c2SCharles.Forsyth r = r->s1;
95674a4d8c2SCharles.Forsyth if(r == R)
95774a4d8c2SCharles.Forsyth break;
95874a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
95974a4d8c2SCharles.Forsyth break;
96074a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
96174a4d8c2SCharles.Forsyth break;
96274a4d8c2SCharles.Forsyth }
96374a4d8c2SCharles.Forsyth }
96474a4d8c2SCharles.Forsyth
96574a4d8c2SCharles.Forsyth ulong
paint2(Reg * r,int bn)96674a4d8c2SCharles.Forsyth paint2(Reg *r, int bn)
96774a4d8c2SCharles.Forsyth {
96874a4d8c2SCharles.Forsyth Reg *r1;
96974a4d8c2SCharles.Forsyth int z;
97074a4d8c2SCharles.Forsyth ulong bb, vreg;
97174a4d8c2SCharles.Forsyth
97274a4d8c2SCharles.Forsyth z = bn/32;
97374a4d8c2SCharles.Forsyth bb = 1L << (bn%32);
97474a4d8c2SCharles.Forsyth vreg = regbits;
97574a4d8c2SCharles.Forsyth if(!(r->act.b[z] & bb))
97674a4d8c2SCharles.Forsyth return vreg;
97774a4d8c2SCharles.Forsyth for(;;) {
97874a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
97974a4d8c2SCharles.Forsyth break;
98074a4d8c2SCharles.Forsyth r1 = r->p1;
98174a4d8c2SCharles.Forsyth if(r1 == R)
98274a4d8c2SCharles.Forsyth break;
98374a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
98474a4d8c2SCharles.Forsyth break;
98574a4d8c2SCharles.Forsyth if(!(r1->act.b[z] & bb))
98674a4d8c2SCharles.Forsyth break;
98774a4d8c2SCharles.Forsyth r = r1;
98874a4d8c2SCharles.Forsyth }
98974a4d8c2SCharles.Forsyth for(;;) {
99074a4d8c2SCharles.Forsyth r->act.b[z] &= ~bb;
99174a4d8c2SCharles.Forsyth
99274a4d8c2SCharles.Forsyth vreg |= r->regu;
99374a4d8c2SCharles.Forsyth
99474a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
99574a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
99674a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
99774a4d8c2SCharles.Forsyth vreg |= paint2(r1, bn);
99874a4d8c2SCharles.Forsyth
99974a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
100074a4d8c2SCharles.Forsyth break;
100174a4d8c2SCharles.Forsyth r1 = r->s2;
100274a4d8c2SCharles.Forsyth if(r1 != R)
100374a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
100474a4d8c2SCharles.Forsyth vreg |= paint2(r1, bn);
100574a4d8c2SCharles.Forsyth r = r->s1;
100674a4d8c2SCharles.Forsyth if(r == R)
100774a4d8c2SCharles.Forsyth break;
100874a4d8c2SCharles.Forsyth if(!(r->act.b[z] & bb))
100974a4d8c2SCharles.Forsyth break;
101074a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
101174a4d8c2SCharles.Forsyth break;
101274a4d8c2SCharles.Forsyth }
101374a4d8c2SCharles.Forsyth return vreg;
101474a4d8c2SCharles.Forsyth }
101574a4d8c2SCharles.Forsyth
101674a4d8c2SCharles.Forsyth void
paint3(Reg * r,int bn,long rb,int rn)101774a4d8c2SCharles.Forsyth paint3(Reg *r, int bn, long rb, int rn)
101874a4d8c2SCharles.Forsyth {
101974a4d8c2SCharles.Forsyth Reg *r1;
102074a4d8c2SCharles.Forsyth Prog *p;
102174a4d8c2SCharles.Forsyth int z;
102274a4d8c2SCharles.Forsyth ulong bb;
102374a4d8c2SCharles.Forsyth
102474a4d8c2SCharles.Forsyth z = bn/32;
102574a4d8c2SCharles.Forsyth bb = 1L << (bn%32);
102674a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
102774a4d8c2SCharles.Forsyth return;
102874a4d8c2SCharles.Forsyth for(;;) {
102974a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
103074a4d8c2SCharles.Forsyth break;
103174a4d8c2SCharles.Forsyth r1 = r->p1;
103274a4d8c2SCharles.Forsyth if(r1 == R)
103374a4d8c2SCharles.Forsyth break;
103474a4d8c2SCharles.Forsyth if(!(r1->refahead.b[z] & bb))
103574a4d8c2SCharles.Forsyth break;
103674a4d8c2SCharles.Forsyth if(r1->act.b[z] & bb)
103774a4d8c2SCharles.Forsyth break;
103874a4d8c2SCharles.Forsyth r = r1;
103974a4d8c2SCharles.Forsyth }
104074a4d8c2SCharles.Forsyth
104174a4d8c2SCharles.Forsyth if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
104274a4d8c2SCharles.Forsyth addmove(r, bn, rn, 0);
104374a4d8c2SCharles.Forsyth for(;;) {
104474a4d8c2SCharles.Forsyth r->act.b[z] |= bb;
104574a4d8c2SCharles.Forsyth p = r->prog;
104674a4d8c2SCharles.Forsyth
104774a4d8c2SCharles.Forsyth if(r->use1.b[z] & bb) {
104874a4d8c2SCharles.Forsyth if(debug['R'])
104974a4d8c2SCharles.Forsyth print("%P", p);
105074a4d8c2SCharles.Forsyth addreg(&p->from, rn);
105174a4d8c2SCharles.Forsyth if(debug['R'])
105274a4d8c2SCharles.Forsyth print("\t.c%P\n", p);
105374a4d8c2SCharles.Forsyth }
105474a4d8c2SCharles.Forsyth if((r->use2.b[z]|r->set.b[z]) & bb) {
105574a4d8c2SCharles.Forsyth if(debug['R'])
105674a4d8c2SCharles.Forsyth print("%P", p);
105774a4d8c2SCharles.Forsyth addreg(&p->to, rn);
105874a4d8c2SCharles.Forsyth if(debug['R'])
105974a4d8c2SCharles.Forsyth print("\t.c%P\n", p);
106074a4d8c2SCharles.Forsyth }
106174a4d8c2SCharles.Forsyth
106274a4d8c2SCharles.Forsyth if(STORE(r) & r->regdiff.b[z] & bb)
106374a4d8c2SCharles.Forsyth addmove(r, bn, rn, 1);
106474a4d8c2SCharles.Forsyth r->regu |= rb;
106574a4d8c2SCharles.Forsyth
106674a4d8c2SCharles.Forsyth if(r->refbehind.b[z] & bb)
106774a4d8c2SCharles.Forsyth for(r1 = r->p2; r1 != R; r1 = r1->p2link)
106874a4d8c2SCharles.Forsyth if(r1->refahead.b[z] & bb)
106974a4d8c2SCharles.Forsyth paint3(r1, bn, rb, rn);
107074a4d8c2SCharles.Forsyth
107174a4d8c2SCharles.Forsyth if(!(r->refahead.b[z] & bb))
107274a4d8c2SCharles.Forsyth break;
107374a4d8c2SCharles.Forsyth r1 = r->s2;
107474a4d8c2SCharles.Forsyth if(r1 != R)
107574a4d8c2SCharles.Forsyth if(r1->refbehind.b[z] & bb)
107674a4d8c2SCharles.Forsyth paint3(r1, bn, rb, rn);
107774a4d8c2SCharles.Forsyth r = r->s1;
107874a4d8c2SCharles.Forsyth if(r == R)
107974a4d8c2SCharles.Forsyth break;
108074a4d8c2SCharles.Forsyth if(r->act.b[z] & bb)
108174a4d8c2SCharles.Forsyth break;
108274a4d8c2SCharles.Forsyth if(!(r->refbehind.b[z] & bb))
108374a4d8c2SCharles.Forsyth break;
108474a4d8c2SCharles.Forsyth }
108574a4d8c2SCharles.Forsyth }
108674a4d8c2SCharles.Forsyth
108774a4d8c2SCharles.Forsyth void
addreg(Adr * a,int rn)108874a4d8c2SCharles.Forsyth addreg(Adr *a, int rn)
108974a4d8c2SCharles.Forsyth {
109074a4d8c2SCharles.Forsyth
109174a4d8c2SCharles.Forsyth a->sym = 0;
109274a4d8c2SCharles.Forsyth a->name = D_NONE;
109374a4d8c2SCharles.Forsyth a->type = D_REG;
109474a4d8c2SCharles.Forsyth a->reg = rn;
109574a4d8c2SCharles.Forsyth if(rn >= NREG) {
109674a4d8c2SCharles.Forsyth a->type = D_FREG;
109774a4d8c2SCharles.Forsyth a->reg = rn-NREG;
109874a4d8c2SCharles.Forsyth }
109974a4d8c2SCharles.Forsyth }
110074a4d8c2SCharles.Forsyth
110174a4d8c2SCharles.Forsyth /*
110274a4d8c2SCharles.Forsyth * bit reg
110374a4d8c2SCharles.Forsyth * 0 R3
110474a4d8c2SCharles.Forsyth * 1 R4
110574a4d8c2SCharles.Forsyth * ... ...
110674a4d8c2SCharles.Forsyth * 19 R22
110774a4d8c2SCharles.Forsyth * 20 R23
110874a4d8c2SCharles.Forsyth */
110974a4d8c2SCharles.Forsyth long
RtoB(int r)111074a4d8c2SCharles.Forsyth RtoB(int r)
111174a4d8c2SCharles.Forsyth {
111274a4d8c2SCharles.Forsyth
111374a4d8c2SCharles.Forsyth if(r < 3 || r > 23)
111474a4d8c2SCharles.Forsyth return 0;
111574a4d8c2SCharles.Forsyth return 1L << (r-3);
111674a4d8c2SCharles.Forsyth }
111774a4d8c2SCharles.Forsyth
11186e425a9dSCharles.Forsyth int
BtoR(long b)111974a4d8c2SCharles.Forsyth BtoR(long b)
112074a4d8c2SCharles.Forsyth {
112174a4d8c2SCharles.Forsyth
112274a4d8c2SCharles.Forsyth b &= 0x001fffffL;
112374a4d8c2SCharles.Forsyth if(b == 0)
112474a4d8c2SCharles.Forsyth return 0;
112574a4d8c2SCharles.Forsyth return bitno(b) + 3;
112674a4d8c2SCharles.Forsyth }
112774a4d8c2SCharles.Forsyth
112874a4d8c2SCharles.Forsyth /*
112974a4d8c2SCharles.Forsyth * bit reg
113074a4d8c2SCharles.Forsyth * 22 F4
113174a4d8c2SCharles.Forsyth * 23 F6
113274a4d8c2SCharles.Forsyth * ... ...
113374a4d8c2SCharles.Forsyth * 31 F22
113474a4d8c2SCharles.Forsyth */
113574a4d8c2SCharles.Forsyth long
FtoB(int f)113674a4d8c2SCharles.Forsyth FtoB(int f)
113774a4d8c2SCharles.Forsyth {
113874a4d8c2SCharles.Forsyth
113974a4d8c2SCharles.Forsyth if(f < 4 || f > 22 || (f&1))
114074a4d8c2SCharles.Forsyth return 0;
114174a4d8c2SCharles.Forsyth return 1L << (f/2 + 20);
114274a4d8c2SCharles.Forsyth }
114374a4d8c2SCharles.Forsyth
114474a4d8c2SCharles.Forsyth int
BtoF(long b)114574a4d8c2SCharles.Forsyth BtoF(long b)
114674a4d8c2SCharles.Forsyth {
114774a4d8c2SCharles.Forsyth
114874a4d8c2SCharles.Forsyth b &= 0xffc00000L;
114974a4d8c2SCharles.Forsyth if(b == 0)
115074a4d8c2SCharles.Forsyth return 0;
115174a4d8c2SCharles.Forsyth return bitno(b)*2 - 40;
115274a4d8c2SCharles.Forsyth }
1153