174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth int xtramodes(Reg*, Adr*);
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth void
peep(void)674a4d8c2SCharles.Forsyth peep(void)
774a4d8c2SCharles.Forsyth {
874a4d8c2SCharles.Forsyth Reg *r, *r1, *r2;
974a4d8c2SCharles.Forsyth Prog *p, *p1;
1074a4d8c2SCharles.Forsyth int t;
1174a4d8c2SCharles.Forsyth /*
1274a4d8c2SCharles.Forsyth * complete R structure
1374a4d8c2SCharles.Forsyth */
1474a4d8c2SCharles.Forsyth t = 0;
1574a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r1) {
1674a4d8c2SCharles.Forsyth r1 = r->link;
1774a4d8c2SCharles.Forsyth if(r1 == R)
1874a4d8c2SCharles.Forsyth break;
1974a4d8c2SCharles.Forsyth p = r->prog->link;
2074a4d8c2SCharles.Forsyth while(p != r1->prog)
2174a4d8c2SCharles.Forsyth switch(p->as) {
2274a4d8c2SCharles.Forsyth default:
2374a4d8c2SCharles.Forsyth r2 = rega();
2474a4d8c2SCharles.Forsyth r->link = r2;
2574a4d8c2SCharles.Forsyth r2->link = r1;
2674a4d8c2SCharles.Forsyth
2774a4d8c2SCharles.Forsyth r2->prog = p;
2874a4d8c2SCharles.Forsyth r2->p1 = r;
2974a4d8c2SCharles.Forsyth r->s1 = r2;
3074a4d8c2SCharles.Forsyth r2->s1 = r1;
3174a4d8c2SCharles.Forsyth r1->p1 = r2;
3274a4d8c2SCharles.Forsyth
3374a4d8c2SCharles.Forsyth r = r2;
3474a4d8c2SCharles.Forsyth t++;
3574a4d8c2SCharles.Forsyth
3674a4d8c2SCharles.Forsyth case ADATA:
3774a4d8c2SCharles.Forsyth case AGLOBL:
3874a4d8c2SCharles.Forsyth case ANAME:
3974a4d8c2SCharles.Forsyth case ASIGNAME:
4074a4d8c2SCharles.Forsyth p = p->link;
4174a4d8c2SCharles.Forsyth }
4274a4d8c2SCharles.Forsyth }
4374a4d8c2SCharles.Forsyth
4474a4d8c2SCharles.Forsyth loop1:
4574a4d8c2SCharles.Forsyth t = 0;
4674a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
4774a4d8c2SCharles.Forsyth p = r->prog;
4874a4d8c2SCharles.Forsyth if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
4974a4d8c2SCharles.Forsyth /*
5074a4d8c2SCharles.Forsyth * elide shift into D_SHIFT operand of subsequent instruction
5174a4d8c2SCharles.Forsyth */
5274a4d8c2SCharles.Forsyth if(shiftprop(r)) {
5374a4d8c2SCharles.Forsyth excise(r);
5474a4d8c2SCharles.Forsyth t++;
5574a4d8c2SCharles.Forsyth }
5674a4d8c2SCharles.Forsyth }
5774a4d8c2SCharles.Forsyth if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
5874a4d8c2SCharles.Forsyth if(regtyp(&p->to)) {
5974a4d8c2SCharles.Forsyth if(p->from.type == D_CONST)
6074a4d8c2SCharles.Forsyth constprop(&p->from, &p->to, r->s1);
6174a4d8c2SCharles.Forsyth else if(regtyp(&p->from))
6274a4d8c2SCharles.Forsyth if(p->from.type == p->to.type) {
6374a4d8c2SCharles.Forsyth if(copyprop(r)) {
6474a4d8c2SCharles.Forsyth excise(r);
6574a4d8c2SCharles.Forsyth t++;
6674a4d8c2SCharles.Forsyth } else
6774a4d8c2SCharles.Forsyth if(subprop(r) && copyprop(r)) {
6874a4d8c2SCharles.Forsyth excise(r);
6974a4d8c2SCharles.Forsyth t++;
7074a4d8c2SCharles.Forsyth }
7174a4d8c2SCharles.Forsyth }
7274a4d8c2SCharles.Forsyth }
7374a4d8c2SCharles.Forsyth }
7474a4d8c2SCharles.Forsyth if(t)
7574a4d8c2SCharles.Forsyth goto loop1;
7674a4d8c2SCharles.Forsyth /*
7774a4d8c2SCharles.Forsyth * look for MOVB x,R; MOVB R,R
7874a4d8c2SCharles.Forsyth */
7974a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
8074a4d8c2SCharles.Forsyth p = r->prog;
8174a4d8c2SCharles.Forsyth switch(p->as) {
8274a4d8c2SCharles.Forsyth default:
8374a4d8c2SCharles.Forsyth continue;
8474a4d8c2SCharles.Forsyth case AEOR:
8574a4d8c2SCharles.Forsyth /*
8674a4d8c2SCharles.Forsyth * EOR -1,x,y => MVN x,y
8774a4d8c2SCharles.Forsyth */
8874a4d8c2SCharles.Forsyth if(p->from.type == D_CONST && p->from.offset == -1) {
8974a4d8c2SCharles.Forsyth p->as = AMVN;
9074a4d8c2SCharles.Forsyth p->from.type = D_REG;
9174a4d8c2SCharles.Forsyth if(p->reg != NREG)
9274a4d8c2SCharles.Forsyth p->from.reg = p->reg;
9374a4d8c2SCharles.Forsyth else
9474a4d8c2SCharles.Forsyth p->from.reg = p->to.reg;
9574a4d8c2SCharles.Forsyth p->reg = NREG;
9674a4d8c2SCharles.Forsyth }
9774a4d8c2SCharles.Forsyth continue;
9874a4d8c2SCharles.Forsyth case AMOVH:
9974a4d8c2SCharles.Forsyth case AMOVHU:
10074a4d8c2SCharles.Forsyth case AMOVB:
10174a4d8c2SCharles.Forsyth case AMOVBU:
10274a4d8c2SCharles.Forsyth if(p->to.type != D_REG)
10374a4d8c2SCharles.Forsyth continue;
10474a4d8c2SCharles.Forsyth break;
10574a4d8c2SCharles.Forsyth }
10674a4d8c2SCharles.Forsyth r1 = r->link;
10774a4d8c2SCharles.Forsyth if(r1 == R)
10874a4d8c2SCharles.Forsyth continue;
10974a4d8c2SCharles.Forsyth p1 = r1->prog;
11074a4d8c2SCharles.Forsyth if(p1->as != p->as)
11174a4d8c2SCharles.Forsyth continue;
11274a4d8c2SCharles.Forsyth if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
11374a4d8c2SCharles.Forsyth continue;
11474a4d8c2SCharles.Forsyth if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
11574a4d8c2SCharles.Forsyth continue;
11674a4d8c2SCharles.Forsyth excise(r1);
11774a4d8c2SCharles.Forsyth }
11874a4d8c2SCharles.Forsyth
11974a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
12074a4d8c2SCharles.Forsyth p = r->prog;
12174a4d8c2SCharles.Forsyth switch(p->as) {
12274a4d8c2SCharles.Forsyth case AMOVW:
12374a4d8c2SCharles.Forsyth case AMOVB:
12474a4d8c2SCharles.Forsyth case AMOVBU:
12574a4d8c2SCharles.Forsyth if(p->from.type == D_OREG && p->from.offset == 0)
12674a4d8c2SCharles.Forsyth xtramodes(r, &p->from);
12774a4d8c2SCharles.Forsyth else if(p->to.type == D_OREG && p->to.offset == 0)
12874a4d8c2SCharles.Forsyth xtramodes(r, &p->to);
12974a4d8c2SCharles.Forsyth else
13074a4d8c2SCharles.Forsyth continue;
13174a4d8c2SCharles.Forsyth break;
13274a4d8c2SCharles.Forsyth case ACMP:
13374a4d8c2SCharles.Forsyth /*
13474a4d8c2SCharles.Forsyth * elide CMP $0,x if calculation of x can set condition codes
13574a4d8c2SCharles.Forsyth */
13674a4d8c2SCharles.Forsyth if(p->from.type != D_CONST || p->from.offset != 0)
13774a4d8c2SCharles.Forsyth continue;
13874a4d8c2SCharles.Forsyth r2 = r->s1;
13974a4d8c2SCharles.Forsyth if(r2 == R)
14074a4d8c2SCharles.Forsyth continue;
14174a4d8c2SCharles.Forsyth t = r2->prog->as;
14274a4d8c2SCharles.Forsyth switch(t) {
14374a4d8c2SCharles.Forsyth default:
14474a4d8c2SCharles.Forsyth continue;
14574a4d8c2SCharles.Forsyth case ABEQ:
14674a4d8c2SCharles.Forsyth case ABNE:
14774a4d8c2SCharles.Forsyth case ABMI:
14874a4d8c2SCharles.Forsyth case ABPL:
14974a4d8c2SCharles.Forsyth break;
15074a4d8c2SCharles.Forsyth case ABGE:
15174a4d8c2SCharles.Forsyth t = ABPL;
15274a4d8c2SCharles.Forsyth break;
15374a4d8c2SCharles.Forsyth case ABLT:
15474a4d8c2SCharles.Forsyth t = ABMI;
15574a4d8c2SCharles.Forsyth break;
15674a4d8c2SCharles.Forsyth case ABHI:
15774a4d8c2SCharles.Forsyth t = ABNE;
15874a4d8c2SCharles.Forsyth break;
15974a4d8c2SCharles.Forsyth case ABLS:
16074a4d8c2SCharles.Forsyth t = ABEQ;
16174a4d8c2SCharles.Forsyth break;
16274a4d8c2SCharles.Forsyth }
16374a4d8c2SCharles.Forsyth r1 = r;
16474a4d8c2SCharles.Forsyth do
16574a4d8c2SCharles.Forsyth r1 = uniqp(r1);
16674a4d8c2SCharles.Forsyth while (r1 != R && r1->prog->as == ANOP);
16774a4d8c2SCharles.Forsyth if(r1 == R)
16874a4d8c2SCharles.Forsyth continue;
16974a4d8c2SCharles.Forsyth p1 = r1->prog;
17074a4d8c2SCharles.Forsyth if(p1->to.type != D_REG)
17174a4d8c2SCharles.Forsyth continue;
17274a4d8c2SCharles.Forsyth if(p1->to.reg != p->reg)
17374a4d8c2SCharles.Forsyth if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
17474a4d8c2SCharles.Forsyth continue;
17574a4d8c2SCharles.Forsyth switch(p1->as) {
17674a4d8c2SCharles.Forsyth default:
17774a4d8c2SCharles.Forsyth continue;
17874a4d8c2SCharles.Forsyth case AMOVW:
17974a4d8c2SCharles.Forsyth if(p1->from.type != D_REG)
18074a4d8c2SCharles.Forsyth continue;
18174a4d8c2SCharles.Forsyth case AAND:
18274a4d8c2SCharles.Forsyth case AEOR:
18374a4d8c2SCharles.Forsyth case AORR:
18474a4d8c2SCharles.Forsyth case ABIC:
18574a4d8c2SCharles.Forsyth case AMVN:
18674a4d8c2SCharles.Forsyth case ASUB:
18774a4d8c2SCharles.Forsyth case ARSB:
18874a4d8c2SCharles.Forsyth case AADD:
18974a4d8c2SCharles.Forsyth case AADC:
19074a4d8c2SCharles.Forsyth case ASBC:
19174a4d8c2SCharles.Forsyth case ARSC:
19274a4d8c2SCharles.Forsyth break;
19374a4d8c2SCharles.Forsyth }
19474a4d8c2SCharles.Forsyth p1->scond |= C_SBIT;
19574a4d8c2SCharles.Forsyth r2->prog->as = t;
19674a4d8c2SCharles.Forsyth excise(r);
19774a4d8c2SCharles.Forsyth continue;
19874a4d8c2SCharles.Forsyth }
19974a4d8c2SCharles.Forsyth }
20074a4d8c2SCharles.Forsyth
20174a4d8c2SCharles.Forsyth predicate();
20274a4d8c2SCharles.Forsyth }
20374a4d8c2SCharles.Forsyth
20474a4d8c2SCharles.Forsyth void
excise(Reg * r)20574a4d8c2SCharles.Forsyth excise(Reg *r)
20674a4d8c2SCharles.Forsyth {
20774a4d8c2SCharles.Forsyth Prog *p;
20874a4d8c2SCharles.Forsyth
20974a4d8c2SCharles.Forsyth p = r->prog;
21074a4d8c2SCharles.Forsyth p->as = ANOP;
21174a4d8c2SCharles.Forsyth p->scond = zprog.scond;
21274a4d8c2SCharles.Forsyth p->from = zprog.from;
21374a4d8c2SCharles.Forsyth p->to = zprog.to;
21474a4d8c2SCharles.Forsyth p->reg = zprog.reg; /**/
21574a4d8c2SCharles.Forsyth }
21674a4d8c2SCharles.Forsyth
21774a4d8c2SCharles.Forsyth Reg*
uniqp(Reg * r)21874a4d8c2SCharles.Forsyth uniqp(Reg *r)
21974a4d8c2SCharles.Forsyth {
22074a4d8c2SCharles.Forsyth Reg *r1;
22174a4d8c2SCharles.Forsyth
22274a4d8c2SCharles.Forsyth r1 = r->p1;
22374a4d8c2SCharles.Forsyth if(r1 == R) {
22474a4d8c2SCharles.Forsyth r1 = r->p2;
22574a4d8c2SCharles.Forsyth if(r1 == R || r1->p2link != R)
22674a4d8c2SCharles.Forsyth return R;
22774a4d8c2SCharles.Forsyth } else
22874a4d8c2SCharles.Forsyth if(r->p2 != R)
22974a4d8c2SCharles.Forsyth return R;
23074a4d8c2SCharles.Forsyth return r1;
23174a4d8c2SCharles.Forsyth }
23274a4d8c2SCharles.Forsyth
23374a4d8c2SCharles.Forsyth Reg*
uniqs(Reg * r)23474a4d8c2SCharles.Forsyth uniqs(Reg *r)
23574a4d8c2SCharles.Forsyth {
23674a4d8c2SCharles.Forsyth Reg *r1;
23774a4d8c2SCharles.Forsyth
23874a4d8c2SCharles.Forsyth r1 = r->s1;
23974a4d8c2SCharles.Forsyth if(r1 == R) {
24074a4d8c2SCharles.Forsyth r1 = r->s2;
24174a4d8c2SCharles.Forsyth if(r1 == R)
24274a4d8c2SCharles.Forsyth return R;
24374a4d8c2SCharles.Forsyth } else
24474a4d8c2SCharles.Forsyth if(r->s2 != R)
24574a4d8c2SCharles.Forsyth return R;
24674a4d8c2SCharles.Forsyth return r1;
24774a4d8c2SCharles.Forsyth }
24874a4d8c2SCharles.Forsyth
24974a4d8c2SCharles.Forsyth int
regtyp(Adr * a)25074a4d8c2SCharles.Forsyth regtyp(Adr *a)
25174a4d8c2SCharles.Forsyth {
25274a4d8c2SCharles.Forsyth
25374a4d8c2SCharles.Forsyth if(a->type == D_REG)
25474a4d8c2SCharles.Forsyth return 1;
25574a4d8c2SCharles.Forsyth if(a->type == D_FREG)
25674a4d8c2SCharles.Forsyth return 1;
25774a4d8c2SCharles.Forsyth return 0;
25874a4d8c2SCharles.Forsyth }
25974a4d8c2SCharles.Forsyth
26074a4d8c2SCharles.Forsyth /*
26174a4d8c2SCharles.Forsyth * the idea is to substitute
26274a4d8c2SCharles.Forsyth * one register for another
26374a4d8c2SCharles.Forsyth * from one MOV to another
26474a4d8c2SCharles.Forsyth * MOV a, R0
26574a4d8c2SCharles.Forsyth * ADD b, R0 / no use of R1
26674a4d8c2SCharles.Forsyth * MOV R0, R1
26774a4d8c2SCharles.Forsyth * would be converted to
26874a4d8c2SCharles.Forsyth * MOV a, R1
26974a4d8c2SCharles.Forsyth * ADD b, R1
27074a4d8c2SCharles.Forsyth * MOV R1, R0
27174a4d8c2SCharles.Forsyth * hopefully, then the former or latter MOV
27274a4d8c2SCharles.Forsyth * will be eliminated by copy propagation.
27374a4d8c2SCharles.Forsyth */
27474a4d8c2SCharles.Forsyth int
subprop(Reg * r0)27574a4d8c2SCharles.Forsyth subprop(Reg *r0)
27674a4d8c2SCharles.Forsyth {
27774a4d8c2SCharles.Forsyth Prog *p;
27874a4d8c2SCharles.Forsyth Adr *v1, *v2;
27974a4d8c2SCharles.Forsyth Reg *r;
28074a4d8c2SCharles.Forsyth int t;
28174a4d8c2SCharles.Forsyth
28274a4d8c2SCharles.Forsyth p = r0->prog;
28374a4d8c2SCharles.Forsyth v1 = &p->from;
28474a4d8c2SCharles.Forsyth if(!regtyp(v1))
28574a4d8c2SCharles.Forsyth return 0;
28674a4d8c2SCharles.Forsyth v2 = &p->to;
28774a4d8c2SCharles.Forsyth if(!regtyp(v2))
28874a4d8c2SCharles.Forsyth return 0;
28974a4d8c2SCharles.Forsyth for(r=uniqp(r0); r!=R; r=uniqp(r)) {
29074a4d8c2SCharles.Forsyth if(uniqs(r) == R)
29174a4d8c2SCharles.Forsyth break;
29274a4d8c2SCharles.Forsyth p = r->prog;
29374a4d8c2SCharles.Forsyth switch(p->as) {
29474a4d8c2SCharles.Forsyth case ABL:
29574a4d8c2SCharles.Forsyth return 0;
29674a4d8c2SCharles.Forsyth
29774a4d8c2SCharles.Forsyth case ACMP:
29874a4d8c2SCharles.Forsyth case ACMN:
29974a4d8c2SCharles.Forsyth case AADD:
30074a4d8c2SCharles.Forsyth case ASUB:
30174a4d8c2SCharles.Forsyth case ARSB:
30274a4d8c2SCharles.Forsyth case ASLL:
30374a4d8c2SCharles.Forsyth case ASRL:
30474a4d8c2SCharles.Forsyth case ASRA:
30574a4d8c2SCharles.Forsyth case AORR:
30674a4d8c2SCharles.Forsyth case AAND:
30774a4d8c2SCharles.Forsyth case AEOR:
30874a4d8c2SCharles.Forsyth case AMUL:
30974a4d8c2SCharles.Forsyth case ADIV:
31074a4d8c2SCharles.Forsyth case ADIVU:
31174a4d8c2SCharles.Forsyth
31274a4d8c2SCharles.Forsyth case ACMPF:
31374a4d8c2SCharles.Forsyth case ACMPD:
31474a4d8c2SCharles.Forsyth case AADDD:
31574a4d8c2SCharles.Forsyth case AADDF:
31674a4d8c2SCharles.Forsyth case ASUBD:
31774a4d8c2SCharles.Forsyth case ASUBF:
31874a4d8c2SCharles.Forsyth case AMULD:
31974a4d8c2SCharles.Forsyth case AMULF:
32074a4d8c2SCharles.Forsyth case ADIVD:
32174a4d8c2SCharles.Forsyth case ADIVF:
32274a4d8c2SCharles.Forsyth if(p->to.type == v1->type)
32374a4d8c2SCharles.Forsyth if(p->to.reg == v1->reg) {
32474a4d8c2SCharles.Forsyth if(p->reg == NREG)
32574a4d8c2SCharles.Forsyth p->reg = p->to.reg;
32674a4d8c2SCharles.Forsyth goto gotit;
32774a4d8c2SCharles.Forsyth }
32874a4d8c2SCharles.Forsyth break;
32974a4d8c2SCharles.Forsyth
33074a4d8c2SCharles.Forsyth case AMOVF:
33174a4d8c2SCharles.Forsyth case AMOVD:
33274a4d8c2SCharles.Forsyth case AMOVW:
33374a4d8c2SCharles.Forsyth if(p->to.type == v1->type)
33474a4d8c2SCharles.Forsyth if(p->to.reg == v1->reg)
33574a4d8c2SCharles.Forsyth goto gotit;
33674a4d8c2SCharles.Forsyth break;
33774a4d8c2SCharles.Forsyth
33874a4d8c2SCharles.Forsyth case AMOVM:
33974a4d8c2SCharles.Forsyth t = 1<<v2->reg;
34074a4d8c2SCharles.Forsyth if((p->from.type == D_CONST && (p->from.offset&t)) ||
34174a4d8c2SCharles.Forsyth (p->to.type == D_CONST && (p->to.offset&t)))
34274a4d8c2SCharles.Forsyth return 0;
34374a4d8c2SCharles.Forsyth break;
34474a4d8c2SCharles.Forsyth }
34574a4d8c2SCharles.Forsyth if(copyau(&p->from, v2) ||
34674a4d8c2SCharles.Forsyth copyau1(p, v2) ||
34774a4d8c2SCharles.Forsyth copyau(&p->to, v2))
34874a4d8c2SCharles.Forsyth break;
34974a4d8c2SCharles.Forsyth if(copysub(&p->from, v1, v2, 0) ||
35074a4d8c2SCharles.Forsyth copysub1(p, v1, v2, 0) ||
35174a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 0))
35274a4d8c2SCharles.Forsyth break;
35374a4d8c2SCharles.Forsyth }
35474a4d8c2SCharles.Forsyth return 0;
35574a4d8c2SCharles.Forsyth
35674a4d8c2SCharles.Forsyth gotit:
35774a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 1);
35874a4d8c2SCharles.Forsyth if(debug['P']) {
35974a4d8c2SCharles.Forsyth print("gotit: %D->%D\n%P", v1, v2, r->prog);
36074a4d8c2SCharles.Forsyth if(p->from.type == v2->type)
36174a4d8c2SCharles.Forsyth print(" excise");
36274a4d8c2SCharles.Forsyth print("\n");
36374a4d8c2SCharles.Forsyth }
36474a4d8c2SCharles.Forsyth for(r=uniqs(r); r!=r0; r=uniqs(r)) {
36574a4d8c2SCharles.Forsyth p = r->prog;
36674a4d8c2SCharles.Forsyth copysub(&p->from, v1, v2, 1);
36774a4d8c2SCharles.Forsyth copysub1(p, v1, v2, 1);
36874a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 1);
36974a4d8c2SCharles.Forsyth if(debug['P'])
37074a4d8c2SCharles.Forsyth print("%P\n", r->prog);
37174a4d8c2SCharles.Forsyth }
37274a4d8c2SCharles.Forsyth t = v1->reg;
37374a4d8c2SCharles.Forsyth v1->reg = v2->reg;
37474a4d8c2SCharles.Forsyth v2->reg = t;
37574a4d8c2SCharles.Forsyth if(debug['P'])
37674a4d8c2SCharles.Forsyth print("%P last\n", r->prog);
37774a4d8c2SCharles.Forsyth return 1;
37874a4d8c2SCharles.Forsyth }
37974a4d8c2SCharles.Forsyth
38074a4d8c2SCharles.Forsyth /*
38174a4d8c2SCharles.Forsyth * The idea is to remove redundant copies.
38274a4d8c2SCharles.Forsyth * v1->v2 F=0
38374a4d8c2SCharles.Forsyth * (use v2 s/v2/v1/)*
38474a4d8c2SCharles.Forsyth * set v1 F=1
38574a4d8c2SCharles.Forsyth * use v2 return fail
38674a4d8c2SCharles.Forsyth * -----------------
38774a4d8c2SCharles.Forsyth * v1->v2 F=0
38874a4d8c2SCharles.Forsyth * (use v2 s/v2/v1/)*
38974a4d8c2SCharles.Forsyth * set v1 F=1
39074a4d8c2SCharles.Forsyth * set v2 return success
39174a4d8c2SCharles.Forsyth */
39274a4d8c2SCharles.Forsyth int
copyprop(Reg * r0)39374a4d8c2SCharles.Forsyth copyprop(Reg *r0)
39474a4d8c2SCharles.Forsyth {
39574a4d8c2SCharles.Forsyth Prog *p;
39674a4d8c2SCharles.Forsyth Adr *v1, *v2;
39774a4d8c2SCharles.Forsyth Reg *r;
39874a4d8c2SCharles.Forsyth
39974a4d8c2SCharles.Forsyth p = r0->prog;
40074a4d8c2SCharles.Forsyth v1 = &p->from;
40174a4d8c2SCharles.Forsyth v2 = &p->to;
40274a4d8c2SCharles.Forsyth if(copyas(v1, v2))
40374a4d8c2SCharles.Forsyth return 1;
40474a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link)
40574a4d8c2SCharles.Forsyth r->active = 0;
40674a4d8c2SCharles.Forsyth return copy1(v1, v2, r0->s1, 0);
40774a4d8c2SCharles.Forsyth }
40874a4d8c2SCharles.Forsyth
40974a4d8c2SCharles.Forsyth int
copy1(Adr * v1,Adr * v2,Reg * r,int f)41074a4d8c2SCharles.Forsyth copy1(Adr *v1, Adr *v2, Reg *r, int f)
41174a4d8c2SCharles.Forsyth {
41274a4d8c2SCharles.Forsyth int t;
41374a4d8c2SCharles.Forsyth Prog *p;
41474a4d8c2SCharles.Forsyth
41574a4d8c2SCharles.Forsyth if(r->active) {
41674a4d8c2SCharles.Forsyth if(debug['P'])
41774a4d8c2SCharles.Forsyth print("act set; return 1\n");
41874a4d8c2SCharles.Forsyth return 1;
41974a4d8c2SCharles.Forsyth }
42074a4d8c2SCharles.Forsyth r->active = 1;
42174a4d8c2SCharles.Forsyth if(debug['P'])
42274a4d8c2SCharles.Forsyth print("copy %D->%D f=%d\n", v1, v2, f);
42374a4d8c2SCharles.Forsyth for(; r != R; r = r->s1) {
42474a4d8c2SCharles.Forsyth p = r->prog;
42574a4d8c2SCharles.Forsyth if(debug['P'])
42674a4d8c2SCharles.Forsyth print("%P", p);
42774a4d8c2SCharles.Forsyth if(!f && uniqp(r) == R) {
42874a4d8c2SCharles.Forsyth f = 1;
42974a4d8c2SCharles.Forsyth if(debug['P'])
43074a4d8c2SCharles.Forsyth print("; merge; f=%d", f);
43174a4d8c2SCharles.Forsyth }
43274a4d8c2SCharles.Forsyth t = copyu(p, v2, A);
43374a4d8c2SCharles.Forsyth switch(t) {
43474a4d8c2SCharles.Forsyth case 2: /* rar, cant split */
43574a4d8c2SCharles.Forsyth if(debug['P'])
43674a4d8c2SCharles.Forsyth print("; %Drar; return 0\n", v2);
43774a4d8c2SCharles.Forsyth return 0;
43874a4d8c2SCharles.Forsyth
43974a4d8c2SCharles.Forsyth case 3: /* set */
44074a4d8c2SCharles.Forsyth if(debug['P'])
44174a4d8c2SCharles.Forsyth print("; %Dset; return 1\n", v2);
44274a4d8c2SCharles.Forsyth return 1;
44374a4d8c2SCharles.Forsyth
44474a4d8c2SCharles.Forsyth case 1: /* used, substitute */
44574a4d8c2SCharles.Forsyth case 4: /* use and set */
44674a4d8c2SCharles.Forsyth if(f) {
44774a4d8c2SCharles.Forsyth if(!debug['P'])
44874a4d8c2SCharles.Forsyth return 0;
44974a4d8c2SCharles.Forsyth if(t == 4)
45074a4d8c2SCharles.Forsyth print("; %Dused+set and f=%d; return 0\n", v2, f);
45174a4d8c2SCharles.Forsyth else
45274a4d8c2SCharles.Forsyth print("; %Dused and f=%d; return 0\n", v2, f);
45374a4d8c2SCharles.Forsyth return 0;
45474a4d8c2SCharles.Forsyth }
45574a4d8c2SCharles.Forsyth if(copyu(p, v2, v1)) {
45674a4d8c2SCharles.Forsyth if(debug['P'])
45774a4d8c2SCharles.Forsyth print("; sub fail; return 0\n");
45874a4d8c2SCharles.Forsyth return 0;
45974a4d8c2SCharles.Forsyth }
46074a4d8c2SCharles.Forsyth if(debug['P'])
46174a4d8c2SCharles.Forsyth print("; sub%D/%D", v2, v1);
46274a4d8c2SCharles.Forsyth if(t == 4) {
46374a4d8c2SCharles.Forsyth if(debug['P'])
46474a4d8c2SCharles.Forsyth print("; %Dused+set; return 1\n", v2);
46574a4d8c2SCharles.Forsyth return 1;
46674a4d8c2SCharles.Forsyth }
46774a4d8c2SCharles.Forsyth break;
46874a4d8c2SCharles.Forsyth }
46974a4d8c2SCharles.Forsyth if(!f) {
47074a4d8c2SCharles.Forsyth t = copyu(p, v1, A);
47174a4d8c2SCharles.Forsyth if(!f && (t == 2 || t == 3 || t == 4)) {
47274a4d8c2SCharles.Forsyth f = 1;
47374a4d8c2SCharles.Forsyth if(debug['P'])
47474a4d8c2SCharles.Forsyth print("; %Dset and !f; f=%d", v1, f);
47574a4d8c2SCharles.Forsyth }
47674a4d8c2SCharles.Forsyth }
47774a4d8c2SCharles.Forsyth if(debug['P'])
47874a4d8c2SCharles.Forsyth print("\n");
47974a4d8c2SCharles.Forsyth if(r->s2)
48074a4d8c2SCharles.Forsyth if(!copy1(v1, v2, r->s2, f))
48174a4d8c2SCharles.Forsyth return 0;
48274a4d8c2SCharles.Forsyth }
48374a4d8c2SCharles.Forsyth return 1;
48474a4d8c2SCharles.Forsyth }
48574a4d8c2SCharles.Forsyth
48674a4d8c2SCharles.Forsyth /*
48774a4d8c2SCharles.Forsyth * The idea is to remove redundant constants.
48874a4d8c2SCharles.Forsyth * $c1->v1
48974a4d8c2SCharles.Forsyth * ($c1->v2 s/$c1/v1)*
49074a4d8c2SCharles.Forsyth * set v1 return
49174a4d8c2SCharles.Forsyth * The v1->v2 should be eliminated by copy propagation.
49274a4d8c2SCharles.Forsyth */
49374a4d8c2SCharles.Forsyth void
constprop(Adr * c1,Adr * v1,Reg * r)49474a4d8c2SCharles.Forsyth constprop(Adr *c1, Adr *v1, Reg *r)
49574a4d8c2SCharles.Forsyth {
49674a4d8c2SCharles.Forsyth Prog *p;
49774a4d8c2SCharles.Forsyth
49874a4d8c2SCharles.Forsyth if(debug['C'])
49974a4d8c2SCharles.Forsyth print("constprop %D->%D\n", c1, v1);
50074a4d8c2SCharles.Forsyth for(; r != R; r = r->s1) {
50174a4d8c2SCharles.Forsyth p = r->prog;
50274a4d8c2SCharles.Forsyth if(debug['C'])
50374a4d8c2SCharles.Forsyth print("%P", p);
50474a4d8c2SCharles.Forsyth if(uniqp(r) == R) {
50574a4d8c2SCharles.Forsyth if(debug['C'])
50674a4d8c2SCharles.Forsyth print("; merge; return\n");
50774a4d8c2SCharles.Forsyth return;
50874a4d8c2SCharles.Forsyth }
50974a4d8c2SCharles.Forsyth if(p->as == AMOVW && copyas(&p->from, c1)) {
51074a4d8c2SCharles.Forsyth if(debug['C'])
51174a4d8c2SCharles.Forsyth print("; sub%D/%D", &p->from, v1);
51274a4d8c2SCharles.Forsyth p->from = *v1;
51374a4d8c2SCharles.Forsyth } else if(copyu(p, v1, A) > 1) {
51474a4d8c2SCharles.Forsyth if(debug['C'])
51574a4d8c2SCharles.Forsyth print("; %Dset; return\n", v1);
51674a4d8c2SCharles.Forsyth return;
51774a4d8c2SCharles.Forsyth }
51874a4d8c2SCharles.Forsyth if(debug['C'])
51974a4d8c2SCharles.Forsyth print("\n");
52074a4d8c2SCharles.Forsyth if(r->s2)
52174a4d8c2SCharles.Forsyth constprop(c1, v1, r->s2);
52274a4d8c2SCharles.Forsyth }
52374a4d8c2SCharles.Forsyth }
52474a4d8c2SCharles.Forsyth
52574a4d8c2SCharles.Forsyth /*
52674a4d8c2SCharles.Forsyth * ASLL x,y,w
52774a4d8c2SCharles.Forsyth * .. (not use w, not set x y w)
52874a4d8c2SCharles.Forsyth * AXXX w,a,b (a != w)
52974a4d8c2SCharles.Forsyth * .. (not use w)
53074a4d8c2SCharles.Forsyth * (set w)
53174a4d8c2SCharles.Forsyth * ----------- changed to
53274a4d8c2SCharles.Forsyth * ..
53374a4d8c2SCharles.Forsyth * AXXX (x<<y),a,b
53474a4d8c2SCharles.Forsyth * ..
53574a4d8c2SCharles.Forsyth */
53674a4d8c2SCharles.Forsyth #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
53774a4d8c2SCharles.Forsyth int
shiftprop(Reg * r)53874a4d8c2SCharles.Forsyth shiftprop(Reg *r)
53974a4d8c2SCharles.Forsyth {
54074a4d8c2SCharles.Forsyth Reg *r1;
54174a4d8c2SCharles.Forsyth Prog *p, *p1, *p2;
54274a4d8c2SCharles.Forsyth int n, o;
54374a4d8c2SCharles.Forsyth Adr a;
54474a4d8c2SCharles.Forsyth
54574a4d8c2SCharles.Forsyth p = r->prog;
54674a4d8c2SCharles.Forsyth if(p->to.type != D_REG)
54774a4d8c2SCharles.Forsyth FAIL("BOTCH: result not reg");
54874a4d8c2SCharles.Forsyth n = p->to.reg;
54974a4d8c2SCharles.Forsyth a = zprog.from;
55074a4d8c2SCharles.Forsyth if(p->reg != NREG && p->reg != p->to.reg) {
55174a4d8c2SCharles.Forsyth a.type = D_REG;
55274a4d8c2SCharles.Forsyth a.reg = p->reg;
55374a4d8c2SCharles.Forsyth }
55474a4d8c2SCharles.Forsyth if(debug['H'])
55574a4d8c2SCharles.Forsyth print("shiftprop\n%P", p);
55674a4d8c2SCharles.Forsyth r1 = r;
55774a4d8c2SCharles.Forsyth for(;;) {
55874a4d8c2SCharles.Forsyth /* find first use of shift result; abort if shift operands or result are changed */
55974a4d8c2SCharles.Forsyth r1 = uniqs(r1);
56074a4d8c2SCharles.Forsyth if(r1 == R)
56174a4d8c2SCharles.Forsyth FAIL("branch");
56274a4d8c2SCharles.Forsyth if(uniqp(r1) == R)
56374a4d8c2SCharles.Forsyth FAIL("merge");
56474a4d8c2SCharles.Forsyth p1 = r1->prog;
56574a4d8c2SCharles.Forsyth if(debug['H'])
56674a4d8c2SCharles.Forsyth print("\n%P", p1);
56774a4d8c2SCharles.Forsyth switch(copyu(p1, &p->to, A)) {
56874a4d8c2SCharles.Forsyth case 0: /* not used or set */
56974a4d8c2SCharles.Forsyth if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
57074a4d8c2SCharles.Forsyth (a.type == D_REG && copyu(p1, &a, A) > 1))
57174a4d8c2SCharles.Forsyth FAIL("args modified");
57274a4d8c2SCharles.Forsyth continue;
57374a4d8c2SCharles.Forsyth case 3: /* set, not used */
57474a4d8c2SCharles.Forsyth FAIL("BOTCH: noref");
57574a4d8c2SCharles.Forsyth }
57674a4d8c2SCharles.Forsyth break;
57774a4d8c2SCharles.Forsyth }
57874a4d8c2SCharles.Forsyth /* check whether substitution can be done */
57974a4d8c2SCharles.Forsyth switch(p1->as) {
58074a4d8c2SCharles.Forsyth default:
58174a4d8c2SCharles.Forsyth FAIL("non-dpi");
58274a4d8c2SCharles.Forsyth case AAND:
58374a4d8c2SCharles.Forsyth case AEOR:
58474a4d8c2SCharles.Forsyth case AADD:
58574a4d8c2SCharles.Forsyth case AADC:
58674a4d8c2SCharles.Forsyth case AORR:
58774a4d8c2SCharles.Forsyth case ASUB:
58874a4d8c2SCharles.Forsyth case ARSB:
58974a4d8c2SCharles.Forsyth case ASBC:
59074a4d8c2SCharles.Forsyth case ARSC:
59174a4d8c2SCharles.Forsyth if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
59274a4d8c2SCharles.Forsyth if(p1->from.type != D_REG)
59374a4d8c2SCharles.Forsyth FAIL("can't swap");
59474a4d8c2SCharles.Forsyth p1->reg = p1->from.reg;
59574a4d8c2SCharles.Forsyth p1->from.reg = n;
59674a4d8c2SCharles.Forsyth switch(p1->as) {
59774a4d8c2SCharles.Forsyth case ASUB:
59874a4d8c2SCharles.Forsyth p1->as = ARSB;
59974a4d8c2SCharles.Forsyth break;
60074a4d8c2SCharles.Forsyth case ARSB:
60174a4d8c2SCharles.Forsyth p1->as = ASUB;
60274a4d8c2SCharles.Forsyth break;
60374a4d8c2SCharles.Forsyth case ASBC:
60474a4d8c2SCharles.Forsyth p1->as = ARSC;
60574a4d8c2SCharles.Forsyth break;
60674a4d8c2SCharles.Forsyth case ARSC:
60774a4d8c2SCharles.Forsyth p1->as = ASBC;
60874a4d8c2SCharles.Forsyth break;
60974a4d8c2SCharles.Forsyth }
61074a4d8c2SCharles.Forsyth if(debug['H'])
61174a4d8c2SCharles.Forsyth print("\t=>%P", p1);
61274a4d8c2SCharles.Forsyth }
61374a4d8c2SCharles.Forsyth case ABIC:
61474a4d8c2SCharles.Forsyth case ACMP:
61574a4d8c2SCharles.Forsyth case ACMN:
61674a4d8c2SCharles.Forsyth if(p1->reg == n)
61774a4d8c2SCharles.Forsyth FAIL("can't swap");
61874a4d8c2SCharles.Forsyth if(p1->reg == NREG && p1->to.reg == n)
61974a4d8c2SCharles.Forsyth FAIL("shift result used twice");
62074a4d8c2SCharles.Forsyth case AMVN:
62174a4d8c2SCharles.Forsyth if(p1->from.type == D_SHIFT)
62274a4d8c2SCharles.Forsyth FAIL("shift result used in shift");
62374a4d8c2SCharles.Forsyth if(p1->from.type != D_REG || p1->from.reg != n)
62474a4d8c2SCharles.Forsyth FAIL("BOTCH: where is it used?");
62574a4d8c2SCharles.Forsyth break;
62674a4d8c2SCharles.Forsyth }
62774a4d8c2SCharles.Forsyth /* check whether shift result is used subsequently */
62874a4d8c2SCharles.Forsyth p2 = p1;
62974a4d8c2SCharles.Forsyth if(p1->to.reg != n)
63074a4d8c2SCharles.Forsyth for (;;) {
63174a4d8c2SCharles.Forsyth r1 = uniqs(r1);
63274a4d8c2SCharles.Forsyth if(r1 == R)
63374a4d8c2SCharles.Forsyth FAIL("inconclusive");
63474a4d8c2SCharles.Forsyth p1 = r1->prog;
63574a4d8c2SCharles.Forsyth if(debug['H'])
63674a4d8c2SCharles.Forsyth print("\n%P", p1);
63774a4d8c2SCharles.Forsyth switch(copyu(p1, &p->to, A)) {
63874a4d8c2SCharles.Forsyth case 0: /* not used or set */
63974a4d8c2SCharles.Forsyth continue;
64074a4d8c2SCharles.Forsyth case 3: /* set, not used */
64174a4d8c2SCharles.Forsyth break;
64274a4d8c2SCharles.Forsyth default:/* used */
64374a4d8c2SCharles.Forsyth FAIL("reused");
64474a4d8c2SCharles.Forsyth }
64574a4d8c2SCharles.Forsyth break;
64674a4d8c2SCharles.Forsyth }
64774a4d8c2SCharles.Forsyth /* make the substitution */
64874a4d8c2SCharles.Forsyth p2->from.type = D_SHIFT;
64974a4d8c2SCharles.Forsyth p2->from.reg = NREG;
65074a4d8c2SCharles.Forsyth o = p->reg;
65174a4d8c2SCharles.Forsyth if(o == NREG)
65274a4d8c2SCharles.Forsyth o = p->to.reg;
65374a4d8c2SCharles.Forsyth switch(p->from.type){
65474a4d8c2SCharles.Forsyth case D_CONST:
65574a4d8c2SCharles.Forsyth o |= (p->from.offset&0x1f)<<7;
65674a4d8c2SCharles.Forsyth break;
65774a4d8c2SCharles.Forsyth case D_REG:
65874a4d8c2SCharles.Forsyth o |= (1<<4) | (p->from.reg<<8);
65974a4d8c2SCharles.Forsyth break;
66074a4d8c2SCharles.Forsyth }
66174a4d8c2SCharles.Forsyth switch(p->as){
66274a4d8c2SCharles.Forsyth case ASLL:
66374a4d8c2SCharles.Forsyth o |= 0<<5;
66474a4d8c2SCharles.Forsyth break;
66574a4d8c2SCharles.Forsyth case ASRL:
66674a4d8c2SCharles.Forsyth o |= 1<<5;
66774a4d8c2SCharles.Forsyth break;
66874a4d8c2SCharles.Forsyth case ASRA:
66974a4d8c2SCharles.Forsyth o |= 2<<5;
67074a4d8c2SCharles.Forsyth break;
67174a4d8c2SCharles.Forsyth }
67274a4d8c2SCharles.Forsyth p2->from.offset = o;
67374a4d8c2SCharles.Forsyth if(debug['H'])
67474a4d8c2SCharles.Forsyth print("\t=>%P\tSUCCEED\n", p2);
67574a4d8c2SCharles.Forsyth return 1;
67674a4d8c2SCharles.Forsyth }
67774a4d8c2SCharles.Forsyth
67874a4d8c2SCharles.Forsyth Reg*
findpre(Reg * r,Adr * v)67974a4d8c2SCharles.Forsyth findpre(Reg *r, Adr *v)
68074a4d8c2SCharles.Forsyth {
68174a4d8c2SCharles.Forsyth Reg *r1;
68274a4d8c2SCharles.Forsyth
68374a4d8c2SCharles.Forsyth for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
68474a4d8c2SCharles.Forsyth if(uniqs(r1) != r)
68574a4d8c2SCharles.Forsyth return R;
68674a4d8c2SCharles.Forsyth switch(copyu(r1->prog, v, A)) {
68774a4d8c2SCharles.Forsyth case 1: /* used */
68874a4d8c2SCharles.Forsyth case 2: /* read-alter-rewrite */
68974a4d8c2SCharles.Forsyth return R;
69074a4d8c2SCharles.Forsyth case 3: /* set */
69174a4d8c2SCharles.Forsyth case 4: /* set and used */
69274a4d8c2SCharles.Forsyth return r1;
69374a4d8c2SCharles.Forsyth }
69474a4d8c2SCharles.Forsyth }
69574a4d8c2SCharles.Forsyth return R;
69674a4d8c2SCharles.Forsyth }
69774a4d8c2SCharles.Forsyth
69874a4d8c2SCharles.Forsyth Reg*
findinc(Reg * r,Reg * r2,Adr * v)69974a4d8c2SCharles.Forsyth findinc(Reg *r, Reg *r2, Adr *v)
70074a4d8c2SCharles.Forsyth {
70174a4d8c2SCharles.Forsyth Reg *r1;
70274a4d8c2SCharles.Forsyth Prog *p;
70374a4d8c2SCharles.Forsyth
70474a4d8c2SCharles.Forsyth
70574a4d8c2SCharles.Forsyth for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
70674a4d8c2SCharles.Forsyth if(uniqp(r1) != r)
70774a4d8c2SCharles.Forsyth return R;
70874a4d8c2SCharles.Forsyth switch(copyu(r1->prog, v, A)) {
70974a4d8c2SCharles.Forsyth case 0: /* not touched */
71074a4d8c2SCharles.Forsyth continue;
71174a4d8c2SCharles.Forsyth case 4: /* set and used */
71274a4d8c2SCharles.Forsyth p = r1->prog;
71374a4d8c2SCharles.Forsyth if(p->as == AADD)
71474a4d8c2SCharles.Forsyth if(p->from.type == D_CONST)
71574a4d8c2SCharles.Forsyth if(p->from.offset > -4096 && p->from.offset < 4096)
71674a4d8c2SCharles.Forsyth return r1;
71774a4d8c2SCharles.Forsyth default:
71874a4d8c2SCharles.Forsyth return R;
71974a4d8c2SCharles.Forsyth }
72074a4d8c2SCharles.Forsyth }
72174a4d8c2SCharles.Forsyth return R;
72274a4d8c2SCharles.Forsyth }
72374a4d8c2SCharles.Forsyth
72474a4d8c2SCharles.Forsyth int
nochange(Reg * r,Reg * r2,Prog * p)72574a4d8c2SCharles.Forsyth nochange(Reg *r, Reg *r2, Prog *p)
72674a4d8c2SCharles.Forsyth {
72774a4d8c2SCharles.Forsyth Adr a[3];
72874a4d8c2SCharles.Forsyth int i, n;
72974a4d8c2SCharles.Forsyth
73074a4d8c2SCharles.Forsyth if(r == r2)
73174a4d8c2SCharles.Forsyth return 1;
73274a4d8c2SCharles.Forsyth n = 0;
73374a4d8c2SCharles.Forsyth if(p->reg != NREG && p->reg != p->to.reg) {
73474a4d8c2SCharles.Forsyth a[n].type = D_REG;
73574a4d8c2SCharles.Forsyth a[n++].reg = p->reg;
73674a4d8c2SCharles.Forsyth }
73774a4d8c2SCharles.Forsyth switch(p->from.type) {
73874a4d8c2SCharles.Forsyth case D_SHIFT:
73974a4d8c2SCharles.Forsyth a[n].type = D_REG;
74074a4d8c2SCharles.Forsyth a[n++].reg = p->from.offset&0xf;
74174a4d8c2SCharles.Forsyth case D_REG:
74274a4d8c2SCharles.Forsyth a[n].type = D_REG;
74374a4d8c2SCharles.Forsyth a[n++].reg = p->from.reg;
74474a4d8c2SCharles.Forsyth }
74574a4d8c2SCharles.Forsyth if(n == 0)
74674a4d8c2SCharles.Forsyth return 1;
74774a4d8c2SCharles.Forsyth for(; r!=R && r!=r2; r=uniqs(r)) {
74874a4d8c2SCharles.Forsyth p = r->prog;
74974a4d8c2SCharles.Forsyth for(i=0; i<n; i++)
75074a4d8c2SCharles.Forsyth if(copyu(p, &a[i], A) > 1)
75174a4d8c2SCharles.Forsyth return 0;
75274a4d8c2SCharles.Forsyth }
75374a4d8c2SCharles.Forsyth return 1;
75474a4d8c2SCharles.Forsyth }
75574a4d8c2SCharles.Forsyth
75674a4d8c2SCharles.Forsyth int
findu1(Reg * r,Adr * v)75774a4d8c2SCharles.Forsyth findu1(Reg *r, Adr *v)
75874a4d8c2SCharles.Forsyth {
75974a4d8c2SCharles.Forsyth for(; r != R; r = r->s1) {
76074a4d8c2SCharles.Forsyth if(r->active)
76174a4d8c2SCharles.Forsyth return 0;
76274a4d8c2SCharles.Forsyth r->active = 1;
76374a4d8c2SCharles.Forsyth switch(copyu(r->prog, v, A)) {
76474a4d8c2SCharles.Forsyth case 1: /* used */
76574a4d8c2SCharles.Forsyth case 2: /* read-alter-rewrite */
76674a4d8c2SCharles.Forsyth case 4: /* set and used */
76774a4d8c2SCharles.Forsyth return 1;
76874a4d8c2SCharles.Forsyth case 3: /* set */
76974a4d8c2SCharles.Forsyth return 0;
77074a4d8c2SCharles.Forsyth }
77174a4d8c2SCharles.Forsyth if(r->s2)
77274a4d8c2SCharles.Forsyth if (findu1(r->s2, v))
77374a4d8c2SCharles.Forsyth return 1;
77474a4d8c2SCharles.Forsyth }
77574a4d8c2SCharles.Forsyth return 0;
77674a4d8c2SCharles.Forsyth }
77774a4d8c2SCharles.Forsyth
77874a4d8c2SCharles.Forsyth int
finduse(Reg * r,Adr * v)77974a4d8c2SCharles.Forsyth finduse(Reg *r, Adr *v)
78074a4d8c2SCharles.Forsyth {
78174a4d8c2SCharles.Forsyth Reg *r1;
78274a4d8c2SCharles.Forsyth
78374a4d8c2SCharles.Forsyth for(r1=firstr; r1!=R; r1=r1->link)
78474a4d8c2SCharles.Forsyth r1->active = 0;
78574a4d8c2SCharles.Forsyth return findu1(r, v);
78674a4d8c2SCharles.Forsyth }
78774a4d8c2SCharles.Forsyth
78874a4d8c2SCharles.Forsyth int
xtramodes(Reg * r,Adr * a)78974a4d8c2SCharles.Forsyth xtramodes(Reg *r, Adr *a)
79074a4d8c2SCharles.Forsyth {
79174a4d8c2SCharles.Forsyth Reg *r1, *r2, *r3;
79274a4d8c2SCharles.Forsyth Prog *p, *p1;
79374a4d8c2SCharles.Forsyth Adr v;
79474a4d8c2SCharles.Forsyth
79574a4d8c2SCharles.Forsyth p = r->prog;
79674a4d8c2SCharles.Forsyth if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */
79774a4d8c2SCharles.Forsyth return 0;
79874a4d8c2SCharles.Forsyth v = *a;
79974a4d8c2SCharles.Forsyth v.type = D_REG;
80074a4d8c2SCharles.Forsyth r1 = findpre(r, &v);
80174a4d8c2SCharles.Forsyth if(r1 != R) {
80274a4d8c2SCharles.Forsyth p1 = r1->prog;
80374a4d8c2SCharles.Forsyth if(p1->to.type == D_REG && p1->to.reg == v.reg)
80474a4d8c2SCharles.Forsyth switch(p1->as) {
80574a4d8c2SCharles.Forsyth case AADD:
80674a4d8c2SCharles.Forsyth if(p1->from.type == D_REG ||
80774a4d8c2SCharles.Forsyth (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
80874a4d8c2SCharles.Forsyth (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
80974a4d8c2SCharles.Forsyth (p1->from.type == D_CONST &&
81074a4d8c2SCharles.Forsyth p1->from.offset > -4096 && p1->from.offset < 4096))
81174a4d8c2SCharles.Forsyth if(nochange(uniqs(r1), r, p1)) {
81274a4d8c2SCharles.Forsyth if(a != &p->from || v.reg != p->to.reg)
81374a4d8c2SCharles.Forsyth if (finduse(r->s1, &v)) {
81474a4d8c2SCharles.Forsyth if(p1->reg == NREG || p1->reg == v.reg)
81574a4d8c2SCharles.Forsyth /* pre-indexing */
81674a4d8c2SCharles.Forsyth p->scond |= C_WBIT;
81774a4d8c2SCharles.Forsyth else return 0;
81874a4d8c2SCharles.Forsyth }
81974a4d8c2SCharles.Forsyth switch (p1->from.type) {
82074a4d8c2SCharles.Forsyth case D_REG:
82174a4d8c2SCharles.Forsyth /* register offset */
82274a4d8c2SCharles.Forsyth a->type = D_SHIFT;
82374a4d8c2SCharles.Forsyth a->offset = p1->from.reg;
82474a4d8c2SCharles.Forsyth break;
82574a4d8c2SCharles.Forsyth case D_SHIFT:
82674a4d8c2SCharles.Forsyth /* scaled register offset */
82774a4d8c2SCharles.Forsyth a->type = D_SHIFT;
82874a4d8c2SCharles.Forsyth case D_CONST:
82974a4d8c2SCharles.Forsyth /* immediate offset */
83074a4d8c2SCharles.Forsyth a->offset = p1->from.offset;
83174a4d8c2SCharles.Forsyth break;
83274a4d8c2SCharles.Forsyth }
83374a4d8c2SCharles.Forsyth if(p1->reg != NREG)
83474a4d8c2SCharles.Forsyth a->reg = p1->reg;
83574a4d8c2SCharles.Forsyth excise(r1);
83674a4d8c2SCharles.Forsyth return 1;
83774a4d8c2SCharles.Forsyth }
83874a4d8c2SCharles.Forsyth break;
83974a4d8c2SCharles.Forsyth case AMOVW:
84074a4d8c2SCharles.Forsyth if(p1->from.type == D_REG)
84174a4d8c2SCharles.Forsyth if((r2 = findinc(r1, r, &p1->from)) != R) {
84274a4d8c2SCharles.Forsyth for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
84374a4d8c2SCharles.Forsyth ;
84474a4d8c2SCharles.Forsyth if(r3 == r) {
84574a4d8c2SCharles.Forsyth /* post-indexing */
84674a4d8c2SCharles.Forsyth p1 = r2->prog;
84774a4d8c2SCharles.Forsyth a->reg = p1->to.reg;
84874a4d8c2SCharles.Forsyth a->offset = p1->from.offset;
84974a4d8c2SCharles.Forsyth p->scond |= C_PBIT;
85074a4d8c2SCharles.Forsyth if(!finduse(r, &r1->prog->to))
85174a4d8c2SCharles.Forsyth excise(r1);
85274a4d8c2SCharles.Forsyth excise(r2);
85374a4d8c2SCharles.Forsyth return 1;
85474a4d8c2SCharles.Forsyth }
85574a4d8c2SCharles.Forsyth }
85674a4d8c2SCharles.Forsyth break;
85774a4d8c2SCharles.Forsyth }
85874a4d8c2SCharles.Forsyth }
85974a4d8c2SCharles.Forsyth if(a != &p->from || a->reg != p->to.reg)
86074a4d8c2SCharles.Forsyth if((r1 = findinc(r, R, &v)) != R) {
86174a4d8c2SCharles.Forsyth /* post-indexing */
86274a4d8c2SCharles.Forsyth p1 = r1->prog;
86374a4d8c2SCharles.Forsyth a->offset = p1->from.offset;
86474a4d8c2SCharles.Forsyth p->scond |= C_PBIT;
86574a4d8c2SCharles.Forsyth excise(r1);
86674a4d8c2SCharles.Forsyth return 1;
86774a4d8c2SCharles.Forsyth }
86874a4d8c2SCharles.Forsyth return 0;
86974a4d8c2SCharles.Forsyth }
87074a4d8c2SCharles.Forsyth
87174a4d8c2SCharles.Forsyth /*
87274a4d8c2SCharles.Forsyth * return
87374a4d8c2SCharles.Forsyth * 1 if v only used (and substitute),
87474a4d8c2SCharles.Forsyth * 2 if read-alter-rewrite
87574a4d8c2SCharles.Forsyth * 3 if set
87674a4d8c2SCharles.Forsyth * 4 if set and used
87774a4d8c2SCharles.Forsyth * 0 otherwise (not touched)
87874a4d8c2SCharles.Forsyth */
87974a4d8c2SCharles.Forsyth int
copyu(Prog * p,Adr * v,Adr * s)88074a4d8c2SCharles.Forsyth copyu(Prog *p, Adr *v, Adr *s)
88174a4d8c2SCharles.Forsyth {
88274a4d8c2SCharles.Forsyth
88374a4d8c2SCharles.Forsyth switch(p->as) {
88474a4d8c2SCharles.Forsyth
88574a4d8c2SCharles.Forsyth default:
88674a4d8c2SCharles.Forsyth if(debug['P'])
8876e425a9dSCharles.Forsyth print(" (?)");
88874a4d8c2SCharles.Forsyth return 2;
88974a4d8c2SCharles.Forsyth
89074a4d8c2SCharles.Forsyth case AMOVM:
89174a4d8c2SCharles.Forsyth if(v->type != D_REG)
89274a4d8c2SCharles.Forsyth return 0;
89374a4d8c2SCharles.Forsyth if(p->from.type == D_CONST) { /* read reglist, read/rar */
89474a4d8c2SCharles.Forsyth if(s != A) {
89574a4d8c2SCharles.Forsyth if(p->from.offset&(1<<v->reg))
89674a4d8c2SCharles.Forsyth return 1;
89774a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
89874a4d8c2SCharles.Forsyth return 1;
89974a4d8c2SCharles.Forsyth return 0;
90074a4d8c2SCharles.Forsyth }
90174a4d8c2SCharles.Forsyth if(copyau(&p->to, v)) {
90274a4d8c2SCharles.Forsyth if(p->scond&C_WBIT)
90374a4d8c2SCharles.Forsyth return 2;
90474a4d8c2SCharles.Forsyth return 1;
90574a4d8c2SCharles.Forsyth }
90674a4d8c2SCharles.Forsyth if(p->from.offset&(1<<v->reg))
90774a4d8c2SCharles.Forsyth return 1;
90874a4d8c2SCharles.Forsyth } else { /* read/rar, write reglist */
90974a4d8c2SCharles.Forsyth if(s != A) {
91074a4d8c2SCharles.Forsyth if(p->to.offset&(1<<v->reg))
91174a4d8c2SCharles.Forsyth return 1;
91274a4d8c2SCharles.Forsyth if(copysub(&p->from, v, s, 1))
91374a4d8c2SCharles.Forsyth return 1;
91474a4d8c2SCharles.Forsyth return 0;
91574a4d8c2SCharles.Forsyth }
91674a4d8c2SCharles.Forsyth if(copyau(&p->from, v)) {
91774a4d8c2SCharles.Forsyth if(p->scond&C_WBIT)
91874a4d8c2SCharles.Forsyth return 2;
91974a4d8c2SCharles.Forsyth if(p->to.offset&(1<<v->reg))
92074a4d8c2SCharles.Forsyth return 4;
92174a4d8c2SCharles.Forsyth return 1;
92274a4d8c2SCharles.Forsyth }
92374a4d8c2SCharles.Forsyth if(p->to.offset&(1<<v->reg))
92474a4d8c2SCharles.Forsyth return 3;
92574a4d8c2SCharles.Forsyth }
92674a4d8c2SCharles.Forsyth return 0;
92774a4d8c2SCharles.Forsyth
92874a4d8c2SCharles.Forsyth case ANOP: /* read, write */
92974a4d8c2SCharles.Forsyth case AMOVW:
93074a4d8c2SCharles.Forsyth case AMOVF:
93174a4d8c2SCharles.Forsyth case AMOVD:
93274a4d8c2SCharles.Forsyth case AMOVH:
93374a4d8c2SCharles.Forsyth case AMOVHU:
93474a4d8c2SCharles.Forsyth case AMOVB:
93574a4d8c2SCharles.Forsyth case AMOVBU:
93674a4d8c2SCharles.Forsyth case AMOVDW:
93774a4d8c2SCharles.Forsyth case AMOVWD:
93874a4d8c2SCharles.Forsyth case AMOVFD:
93974a4d8c2SCharles.Forsyth case AMOVDF:
94074a4d8c2SCharles.Forsyth if(p->scond&(C_WBIT|C_PBIT))
94174a4d8c2SCharles.Forsyth if(v->type == D_REG) {
94274a4d8c2SCharles.Forsyth if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
94374a4d8c2SCharles.Forsyth if(p->from.reg == v->reg)
94474a4d8c2SCharles.Forsyth return 2;
94574a4d8c2SCharles.Forsyth } else {
94674a4d8c2SCharles.Forsyth if(p->to.reg == v->reg)
94774a4d8c2SCharles.Forsyth return 2;
94874a4d8c2SCharles.Forsyth }
94974a4d8c2SCharles.Forsyth }
95074a4d8c2SCharles.Forsyth if(s != A) {
95174a4d8c2SCharles.Forsyth if(copysub(&p->from, v, s, 1))
95274a4d8c2SCharles.Forsyth return 1;
95374a4d8c2SCharles.Forsyth if(!copyas(&p->to, v))
95474a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
95574a4d8c2SCharles.Forsyth return 1;
95674a4d8c2SCharles.Forsyth return 0;
95774a4d8c2SCharles.Forsyth }
95874a4d8c2SCharles.Forsyth if(copyas(&p->to, v)) {
95974a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
96074a4d8c2SCharles.Forsyth return 4;
96174a4d8c2SCharles.Forsyth return 3;
96274a4d8c2SCharles.Forsyth }
96374a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
96474a4d8c2SCharles.Forsyth return 1;
96574a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
96674a4d8c2SCharles.Forsyth return 1;
96774a4d8c2SCharles.Forsyth return 0;
96874a4d8c2SCharles.Forsyth
96974a4d8c2SCharles.Forsyth
97074a4d8c2SCharles.Forsyth case AADD: /* read, read, write */
97174a4d8c2SCharles.Forsyth case ASUB:
97274a4d8c2SCharles.Forsyth case ARSB:
97374a4d8c2SCharles.Forsyth case ASLL:
97474a4d8c2SCharles.Forsyth case ASRL:
97574a4d8c2SCharles.Forsyth case ASRA:
97674a4d8c2SCharles.Forsyth case AORR:
97774a4d8c2SCharles.Forsyth case AAND:
97874a4d8c2SCharles.Forsyth case AEOR:
97974a4d8c2SCharles.Forsyth case AMUL:
98074a4d8c2SCharles.Forsyth case ADIV:
98174a4d8c2SCharles.Forsyth case ADIVU:
98274a4d8c2SCharles.Forsyth case AADDF:
98374a4d8c2SCharles.Forsyth case AADDD:
98474a4d8c2SCharles.Forsyth case ASUBF:
98574a4d8c2SCharles.Forsyth case ASUBD:
98674a4d8c2SCharles.Forsyth case AMULF:
98774a4d8c2SCharles.Forsyth case AMULD:
98874a4d8c2SCharles.Forsyth case ADIVF:
98974a4d8c2SCharles.Forsyth case ADIVD:
99074a4d8c2SCharles.Forsyth
99174a4d8c2SCharles.Forsyth case ACMPF:
99274a4d8c2SCharles.Forsyth case ACMPD:
99374a4d8c2SCharles.Forsyth case ACMP:
99474a4d8c2SCharles.Forsyth case ACMN:
99574a4d8c2SCharles.Forsyth case ACASE:
99674a4d8c2SCharles.Forsyth if(s != A) {
99774a4d8c2SCharles.Forsyth if(copysub(&p->from, v, s, 1))
99874a4d8c2SCharles.Forsyth return 1;
99974a4d8c2SCharles.Forsyth if(copysub1(p, v, s, 1))
100074a4d8c2SCharles.Forsyth return 1;
100174a4d8c2SCharles.Forsyth if(!copyas(&p->to, v))
100274a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
100374a4d8c2SCharles.Forsyth return 1;
100474a4d8c2SCharles.Forsyth return 0;
100574a4d8c2SCharles.Forsyth }
100674a4d8c2SCharles.Forsyth if(copyas(&p->to, v)) {
100774a4d8c2SCharles.Forsyth if(p->reg == NREG)
100874a4d8c2SCharles.Forsyth p->reg = p->to.reg;
100974a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
101074a4d8c2SCharles.Forsyth return 4;
101174a4d8c2SCharles.Forsyth if(copyau1(p, v))
101274a4d8c2SCharles.Forsyth return 4;
101374a4d8c2SCharles.Forsyth return 3;
101474a4d8c2SCharles.Forsyth }
101574a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
101674a4d8c2SCharles.Forsyth return 1;
101774a4d8c2SCharles.Forsyth if(copyau1(p, v))
101874a4d8c2SCharles.Forsyth return 1;
101974a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
102074a4d8c2SCharles.Forsyth return 1;
102174a4d8c2SCharles.Forsyth return 0;
102274a4d8c2SCharles.Forsyth
102374a4d8c2SCharles.Forsyth case ABEQ: /* read, read */
102474a4d8c2SCharles.Forsyth case ABNE:
102574a4d8c2SCharles.Forsyth case ABCS:
102674a4d8c2SCharles.Forsyth case ABHS:
102774a4d8c2SCharles.Forsyth case ABCC:
102874a4d8c2SCharles.Forsyth case ABLO:
102974a4d8c2SCharles.Forsyth case ABMI:
103074a4d8c2SCharles.Forsyth case ABPL:
103174a4d8c2SCharles.Forsyth case ABVS:
103274a4d8c2SCharles.Forsyth case ABVC:
103374a4d8c2SCharles.Forsyth case ABHI:
103474a4d8c2SCharles.Forsyth case ABLS:
103574a4d8c2SCharles.Forsyth case ABGE:
103674a4d8c2SCharles.Forsyth case ABLT:
103774a4d8c2SCharles.Forsyth case ABGT:
103874a4d8c2SCharles.Forsyth case ABLE:
103974a4d8c2SCharles.Forsyth if(s != A) {
104074a4d8c2SCharles.Forsyth if(copysub(&p->from, v, s, 1))
104174a4d8c2SCharles.Forsyth return 1;
104274a4d8c2SCharles.Forsyth return copysub1(p, v, s, 1);
104374a4d8c2SCharles.Forsyth }
104474a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
104574a4d8c2SCharles.Forsyth return 1;
104674a4d8c2SCharles.Forsyth if(copyau1(p, v))
104774a4d8c2SCharles.Forsyth return 1;
104874a4d8c2SCharles.Forsyth return 0;
104974a4d8c2SCharles.Forsyth
105074a4d8c2SCharles.Forsyth case AB: /* funny */
105174a4d8c2SCharles.Forsyth if(s != A) {
105274a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
105374a4d8c2SCharles.Forsyth return 1;
105474a4d8c2SCharles.Forsyth return 0;
105574a4d8c2SCharles.Forsyth }
105674a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
105774a4d8c2SCharles.Forsyth return 1;
105874a4d8c2SCharles.Forsyth return 0;
105974a4d8c2SCharles.Forsyth
106074a4d8c2SCharles.Forsyth case ARET: /* funny */
106174a4d8c2SCharles.Forsyth if(v->type == D_REG)
106274a4d8c2SCharles.Forsyth if(v->reg == REGRET)
106374a4d8c2SCharles.Forsyth return 2;
106474a4d8c2SCharles.Forsyth if(v->type == D_FREG)
106574a4d8c2SCharles.Forsyth if(v->reg == FREGRET)
106674a4d8c2SCharles.Forsyth return 2;
106774a4d8c2SCharles.Forsyth
106874a4d8c2SCharles.Forsyth case ABL: /* funny */
106974a4d8c2SCharles.Forsyth if(v->type == D_REG) {
107074a4d8c2SCharles.Forsyth if(v->reg <= REGEXT && v->reg > exregoffset)
107174a4d8c2SCharles.Forsyth return 2;
1072*45a20ab7Sforsyth if(v->reg == (uchar)REGARG)
107374a4d8c2SCharles.Forsyth return 2;
107474a4d8c2SCharles.Forsyth }
107574a4d8c2SCharles.Forsyth if(v->type == D_FREG)
107674a4d8c2SCharles.Forsyth if(v->reg <= FREGEXT && v->reg > exfregoffset)
107774a4d8c2SCharles.Forsyth return 2;
107874a4d8c2SCharles.Forsyth
107974a4d8c2SCharles.Forsyth if(s != A) {
108074a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
108174a4d8c2SCharles.Forsyth return 1;
108274a4d8c2SCharles.Forsyth return 0;
108374a4d8c2SCharles.Forsyth }
108474a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
108574a4d8c2SCharles.Forsyth return 4;
108674a4d8c2SCharles.Forsyth return 3;
108774a4d8c2SCharles.Forsyth
108874a4d8c2SCharles.Forsyth case ATEXT: /* funny */
108974a4d8c2SCharles.Forsyth if(v->type == D_REG)
1090*45a20ab7Sforsyth if(v->reg == (uchar)REGARG)
109174a4d8c2SCharles.Forsyth return 3;
109274a4d8c2SCharles.Forsyth return 0;
109374a4d8c2SCharles.Forsyth }
109474a4d8c2SCharles.Forsyth }
109574a4d8c2SCharles.Forsyth
109674a4d8c2SCharles.Forsyth int
a2type(Prog * p)109774a4d8c2SCharles.Forsyth a2type(Prog *p)
109874a4d8c2SCharles.Forsyth {
109974a4d8c2SCharles.Forsyth
110074a4d8c2SCharles.Forsyth switch(p->as) {
110174a4d8c2SCharles.Forsyth
110274a4d8c2SCharles.Forsyth case ACMP:
110374a4d8c2SCharles.Forsyth case ACMN:
110474a4d8c2SCharles.Forsyth
110574a4d8c2SCharles.Forsyth case AADD:
110674a4d8c2SCharles.Forsyth case ASUB:
110774a4d8c2SCharles.Forsyth case ARSB:
110874a4d8c2SCharles.Forsyth case ASLL:
110974a4d8c2SCharles.Forsyth case ASRL:
111074a4d8c2SCharles.Forsyth case ASRA:
111174a4d8c2SCharles.Forsyth case AORR:
111274a4d8c2SCharles.Forsyth case AAND:
111374a4d8c2SCharles.Forsyth case AEOR:
111474a4d8c2SCharles.Forsyth case AMUL:
111574a4d8c2SCharles.Forsyth case ADIV:
111674a4d8c2SCharles.Forsyth case ADIVU:
111774a4d8c2SCharles.Forsyth return D_REG;
111874a4d8c2SCharles.Forsyth
111974a4d8c2SCharles.Forsyth case ACMPF:
112074a4d8c2SCharles.Forsyth case ACMPD:
112174a4d8c2SCharles.Forsyth
112274a4d8c2SCharles.Forsyth case AADDF:
112374a4d8c2SCharles.Forsyth case AADDD:
112474a4d8c2SCharles.Forsyth case ASUBF:
112574a4d8c2SCharles.Forsyth case ASUBD:
112674a4d8c2SCharles.Forsyth case AMULF:
112774a4d8c2SCharles.Forsyth case AMULD:
112874a4d8c2SCharles.Forsyth case ADIVF:
112974a4d8c2SCharles.Forsyth case ADIVD:
113074a4d8c2SCharles.Forsyth return D_FREG;
113174a4d8c2SCharles.Forsyth }
113274a4d8c2SCharles.Forsyth return D_NONE;
113374a4d8c2SCharles.Forsyth }
113474a4d8c2SCharles.Forsyth
113574a4d8c2SCharles.Forsyth /*
113674a4d8c2SCharles.Forsyth * direct reference,
113774a4d8c2SCharles.Forsyth * could be set/use depending on
113874a4d8c2SCharles.Forsyth * semantics
113974a4d8c2SCharles.Forsyth */
114074a4d8c2SCharles.Forsyth int
copyas(Adr * a,Adr * v)114174a4d8c2SCharles.Forsyth copyas(Adr *a, Adr *v)
114274a4d8c2SCharles.Forsyth {
114374a4d8c2SCharles.Forsyth
114474a4d8c2SCharles.Forsyth if(regtyp(v)) {
114574a4d8c2SCharles.Forsyth if(a->type == v->type)
114674a4d8c2SCharles.Forsyth if(a->reg == v->reg)
114774a4d8c2SCharles.Forsyth return 1;
114874a4d8c2SCharles.Forsyth } else if(v->type == D_CONST) { /* for constprop */
114974a4d8c2SCharles.Forsyth if(a->type == v->type)
115074a4d8c2SCharles.Forsyth if(a->name == v->name)
115174a4d8c2SCharles.Forsyth if(a->sym == v->sym)
115274a4d8c2SCharles.Forsyth if(a->reg == v->reg)
115374a4d8c2SCharles.Forsyth if(a->offset == v->offset)
115474a4d8c2SCharles.Forsyth return 1;
115574a4d8c2SCharles.Forsyth }
115674a4d8c2SCharles.Forsyth return 0;
115774a4d8c2SCharles.Forsyth }
115874a4d8c2SCharles.Forsyth
115974a4d8c2SCharles.Forsyth /*
116074a4d8c2SCharles.Forsyth * either direct or indirect
116174a4d8c2SCharles.Forsyth */
116274a4d8c2SCharles.Forsyth int
copyau(Adr * a,Adr * v)116374a4d8c2SCharles.Forsyth copyau(Adr *a, Adr *v)
116474a4d8c2SCharles.Forsyth {
116574a4d8c2SCharles.Forsyth
116674a4d8c2SCharles.Forsyth if(copyas(a, v))
116774a4d8c2SCharles.Forsyth return 1;
116874a4d8c2SCharles.Forsyth if(v->type == D_REG) {
116974a4d8c2SCharles.Forsyth if(a->type == D_OREG) {
117074a4d8c2SCharles.Forsyth if(v->reg == a->reg)
117174a4d8c2SCharles.Forsyth return 1;
117274a4d8c2SCharles.Forsyth } else if(a->type == D_SHIFT) {
117374a4d8c2SCharles.Forsyth if((a->offset&0xf) == v->reg)
117474a4d8c2SCharles.Forsyth return 1;
117574a4d8c2SCharles.Forsyth if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
117674a4d8c2SCharles.Forsyth return 1;
117774a4d8c2SCharles.Forsyth }
117874a4d8c2SCharles.Forsyth }
117974a4d8c2SCharles.Forsyth return 0;
118074a4d8c2SCharles.Forsyth }
118174a4d8c2SCharles.Forsyth
118274a4d8c2SCharles.Forsyth int
copyau1(Prog * p,Adr * v)118374a4d8c2SCharles.Forsyth copyau1(Prog *p, Adr *v)
118474a4d8c2SCharles.Forsyth {
118574a4d8c2SCharles.Forsyth
118674a4d8c2SCharles.Forsyth if(regtyp(v)) {
118774a4d8c2SCharles.Forsyth if(a2type(p) == v->type)
118874a4d8c2SCharles.Forsyth if(p->reg == v->reg) {
118974a4d8c2SCharles.Forsyth if(a2type(p) != v->type)
119074a4d8c2SCharles.Forsyth print("botch a2type %P\n", p);
119174a4d8c2SCharles.Forsyth return 1;
119274a4d8c2SCharles.Forsyth }
119374a4d8c2SCharles.Forsyth }
119474a4d8c2SCharles.Forsyth return 0;
119574a4d8c2SCharles.Forsyth }
119674a4d8c2SCharles.Forsyth
119774a4d8c2SCharles.Forsyth /*
119874a4d8c2SCharles.Forsyth * substitute s for v in a
119974a4d8c2SCharles.Forsyth * return failure to substitute
120074a4d8c2SCharles.Forsyth */
120174a4d8c2SCharles.Forsyth int
copysub(Adr * a,Adr * v,Adr * s,int f)120274a4d8c2SCharles.Forsyth copysub(Adr *a, Adr *v, Adr *s, int f)
120374a4d8c2SCharles.Forsyth {
120474a4d8c2SCharles.Forsyth
120574a4d8c2SCharles.Forsyth if(f)
120674a4d8c2SCharles.Forsyth if(copyau(a, v)) {
120774a4d8c2SCharles.Forsyth if(a->type == D_SHIFT) {
120874a4d8c2SCharles.Forsyth if((a->offset&0xf) == v->reg)
120974a4d8c2SCharles.Forsyth a->offset = (a->offset&~0xf)|s->reg;
121074a4d8c2SCharles.Forsyth if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
121174a4d8c2SCharles.Forsyth a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
121274a4d8c2SCharles.Forsyth } else
121374a4d8c2SCharles.Forsyth a->reg = s->reg;
121474a4d8c2SCharles.Forsyth }
121574a4d8c2SCharles.Forsyth return 0;
121674a4d8c2SCharles.Forsyth }
121774a4d8c2SCharles.Forsyth
121874a4d8c2SCharles.Forsyth int
copysub1(Prog * p1,Adr * v,Adr * s,int f)121974a4d8c2SCharles.Forsyth copysub1(Prog *p1, Adr *v, Adr *s, int f)
122074a4d8c2SCharles.Forsyth {
122174a4d8c2SCharles.Forsyth
122274a4d8c2SCharles.Forsyth if(f)
122374a4d8c2SCharles.Forsyth if(copyau1(p1, v))
122474a4d8c2SCharles.Forsyth p1->reg = s->reg;
122574a4d8c2SCharles.Forsyth return 0;
122674a4d8c2SCharles.Forsyth }
122774a4d8c2SCharles.Forsyth
122874a4d8c2SCharles.Forsyth struct {
122974a4d8c2SCharles.Forsyth int opcode;
123074a4d8c2SCharles.Forsyth int notopcode;
123174a4d8c2SCharles.Forsyth int scond;
123274a4d8c2SCharles.Forsyth int notscond;
123374a4d8c2SCharles.Forsyth } predinfo[] = {
123474a4d8c2SCharles.Forsyth { ABEQ, ABNE, 0x0, 0x1, },
123574a4d8c2SCharles.Forsyth { ABNE, ABEQ, 0x1, 0x0, },
123674a4d8c2SCharles.Forsyth { ABCS, ABCC, 0x2, 0x3, },
123774a4d8c2SCharles.Forsyth { ABHS, ABLO, 0x2, 0x3, },
123874a4d8c2SCharles.Forsyth { ABCC, ABCS, 0x3, 0x2, },
123974a4d8c2SCharles.Forsyth { ABLO, ABHS, 0x3, 0x2, },
124074a4d8c2SCharles.Forsyth { ABMI, ABPL, 0x4, 0x5, },
124174a4d8c2SCharles.Forsyth { ABPL, ABMI, 0x5, 0x4, },
124274a4d8c2SCharles.Forsyth { ABVS, ABVC, 0x6, 0x7, },
124374a4d8c2SCharles.Forsyth { ABVC, ABVS, 0x7, 0x6, },
124474a4d8c2SCharles.Forsyth { ABHI, ABLS, 0x8, 0x9, },
124574a4d8c2SCharles.Forsyth { ABLS, ABHI, 0x9, 0x8, },
124674a4d8c2SCharles.Forsyth { ABGE, ABLT, 0xA, 0xB, },
124774a4d8c2SCharles.Forsyth { ABLT, ABGE, 0xB, 0xA, },
124874a4d8c2SCharles.Forsyth { ABGT, ABLE, 0xC, 0xD, },
124974a4d8c2SCharles.Forsyth { ABLE, ABGT, 0xD, 0xC, },
125074a4d8c2SCharles.Forsyth };
125174a4d8c2SCharles.Forsyth
125274a4d8c2SCharles.Forsyth typedef struct {
125374a4d8c2SCharles.Forsyth Reg *start;
125474a4d8c2SCharles.Forsyth Reg *last;
125574a4d8c2SCharles.Forsyth Reg *end;
125674a4d8c2SCharles.Forsyth int len;
125774a4d8c2SCharles.Forsyth } Joininfo;
125874a4d8c2SCharles.Forsyth
125974a4d8c2SCharles.Forsyth enum {
126074a4d8c2SCharles.Forsyth Join,
126174a4d8c2SCharles.Forsyth Split,
126274a4d8c2SCharles.Forsyth End,
126374a4d8c2SCharles.Forsyth Branch,
126474a4d8c2SCharles.Forsyth Setcond,
126574a4d8c2SCharles.Forsyth Toolong
126674a4d8c2SCharles.Forsyth };
126774a4d8c2SCharles.Forsyth
126874a4d8c2SCharles.Forsyth enum {
126974a4d8c2SCharles.Forsyth Falsecond,
127074a4d8c2SCharles.Forsyth Truecond,
127174a4d8c2SCharles.Forsyth Delbranch,
127274a4d8c2SCharles.Forsyth Keepbranch
127374a4d8c2SCharles.Forsyth };
127474a4d8c2SCharles.Forsyth
127574a4d8c2SCharles.Forsyth int
isbranch(Prog * p)127674a4d8c2SCharles.Forsyth isbranch(Prog *p)
127774a4d8c2SCharles.Forsyth {
127874a4d8c2SCharles.Forsyth return (ABEQ <= p->as) && (p->as <= ABLE);
127974a4d8c2SCharles.Forsyth }
128074a4d8c2SCharles.Forsyth
128174a4d8c2SCharles.Forsyth int
predicable(Prog * p)128274a4d8c2SCharles.Forsyth predicable(Prog *p)
128374a4d8c2SCharles.Forsyth {
128474a4d8c2SCharles.Forsyth if (isbranch(p)
128574a4d8c2SCharles.Forsyth || p->as == ANOP
128674a4d8c2SCharles.Forsyth || p->as == AXXX
128774a4d8c2SCharles.Forsyth || p->as == ADATA
128874a4d8c2SCharles.Forsyth || p->as == AGLOBL
128974a4d8c2SCharles.Forsyth || p->as == AGOK
129074a4d8c2SCharles.Forsyth || p->as == AHISTORY
129174a4d8c2SCharles.Forsyth || p->as == ANAME
129274a4d8c2SCharles.Forsyth || p->as == ASIGNAME
129374a4d8c2SCharles.Forsyth || p->as == ATEXT
129474a4d8c2SCharles.Forsyth || p->as == AWORD
129574a4d8c2SCharles.Forsyth || p->as == ADYNT
129674a4d8c2SCharles.Forsyth || p->as == AINIT
129774a4d8c2SCharles.Forsyth || p->as == ABCASE
129874a4d8c2SCharles.Forsyth || p->as == ACASE)
129974a4d8c2SCharles.Forsyth return 0;
130074a4d8c2SCharles.Forsyth return 1;
130174a4d8c2SCharles.Forsyth }
130274a4d8c2SCharles.Forsyth
130374a4d8c2SCharles.Forsyth /*
130474a4d8c2SCharles.Forsyth * Depends on an analysis of the encodings performed by 5l.
130574a4d8c2SCharles.Forsyth * These seem to be all of the opcodes that lead to the "S" bit
130674a4d8c2SCharles.Forsyth * being set in the instruction encodings.
130774a4d8c2SCharles.Forsyth *
130874a4d8c2SCharles.Forsyth * C_SBIT may also have been set explicitly in p->scond.
130974a4d8c2SCharles.Forsyth */
131074a4d8c2SCharles.Forsyth int
modifiescpsr(Prog * p)131174a4d8c2SCharles.Forsyth modifiescpsr(Prog *p)
131274a4d8c2SCharles.Forsyth {
131374a4d8c2SCharles.Forsyth return (p->scond&C_SBIT)
131474a4d8c2SCharles.Forsyth || p->as == ATST
131574a4d8c2SCharles.Forsyth || p->as == ATEQ
131674a4d8c2SCharles.Forsyth || p->as == ACMN
131774a4d8c2SCharles.Forsyth || p->as == ACMP
131874a4d8c2SCharles.Forsyth || p->as == AMULU
131974a4d8c2SCharles.Forsyth || p->as == ADIVU
132074a4d8c2SCharles.Forsyth || p->as == AMUL
132174a4d8c2SCharles.Forsyth || p->as == ADIV
132274a4d8c2SCharles.Forsyth || p->as == AMOD
132374a4d8c2SCharles.Forsyth || p->as == AMODU
132474a4d8c2SCharles.Forsyth || p->as == ABL;
132574a4d8c2SCharles.Forsyth }
132674a4d8c2SCharles.Forsyth
132774a4d8c2SCharles.Forsyth /*
132874a4d8c2SCharles.Forsyth * Find the maximal chain of instructions starting with r which could
132974a4d8c2SCharles.Forsyth * be executed conditionally
133074a4d8c2SCharles.Forsyth */
133174a4d8c2SCharles.Forsyth int
joinsplit(Reg * r,Joininfo * j)133274a4d8c2SCharles.Forsyth joinsplit(Reg *r, Joininfo *j)
133374a4d8c2SCharles.Forsyth {
133474a4d8c2SCharles.Forsyth j->start = r;
133574a4d8c2SCharles.Forsyth j->last = r;
133674a4d8c2SCharles.Forsyth j->len = 0;
133774a4d8c2SCharles.Forsyth do {
133874a4d8c2SCharles.Forsyth if (r->p2 && (r->p1 || r->p2->p2link)) {
133974a4d8c2SCharles.Forsyth j->end = r;
134074a4d8c2SCharles.Forsyth return Join;
134174a4d8c2SCharles.Forsyth }
134274a4d8c2SCharles.Forsyth if (r->s1 && r->s2) {
134374a4d8c2SCharles.Forsyth j->end = r;
134474a4d8c2SCharles.Forsyth return Split;
134574a4d8c2SCharles.Forsyth }
134674a4d8c2SCharles.Forsyth j->last = r;
134774a4d8c2SCharles.Forsyth if (r->prog->as != ANOP)
134874a4d8c2SCharles.Forsyth j->len++;
134974a4d8c2SCharles.Forsyth if (!r->s1 && !r->s2) {
135074a4d8c2SCharles.Forsyth j->end = r->link;
135174a4d8c2SCharles.Forsyth return End;
135274a4d8c2SCharles.Forsyth }
135374a4d8c2SCharles.Forsyth if (r->s2) {
135474a4d8c2SCharles.Forsyth j->end = r->s2;
135574a4d8c2SCharles.Forsyth return Branch;
135674a4d8c2SCharles.Forsyth }
135774a4d8c2SCharles.Forsyth if (modifiescpsr(r->prog)) {
135874a4d8c2SCharles.Forsyth j->end = r->s1;
135974a4d8c2SCharles.Forsyth return Setcond;
136074a4d8c2SCharles.Forsyth }
136174a4d8c2SCharles.Forsyth r = r->s1;
136274a4d8c2SCharles.Forsyth } while (j->len < 4);
136374a4d8c2SCharles.Forsyth j->end = r;
136474a4d8c2SCharles.Forsyth return Toolong;
136574a4d8c2SCharles.Forsyth }
136674a4d8c2SCharles.Forsyth
136774a4d8c2SCharles.Forsyth Reg *
successor(Reg * r)136874a4d8c2SCharles.Forsyth successor(Reg *r)
136974a4d8c2SCharles.Forsyth {
137074a4d8c2SCharles.Forsyth if (r->s1)
137174a4d8c2SCharles.Forsyth return r->s1;
137274a4d8c2SCharles.Forsyth else
137374a4d8c2SCharles.Forsyth return r->s2;
137474a4d8c2SCharles.Forsyth }
137574a4d8c2SCharles.Forsyth
137674a4d8c2SCharles.Forsyth void
applypred(Reg * rstart,Joininfo * j,int cond,int branch)137774a4d8c2SCharles.Forsyth applypred(Reg *rstart, Joininfo *j, int cond, int branch)
137874a4d8c2SCharles.Forsyth {
137974a4d8c2SCharles.Forsyth int pred;
138074a4d8c2SCharles.Forsyth Reg *r;
138174a4d8c2SCharles.Forsyth
138274a4d8c2SCharles.Forsyth if(j->len == 0)
138374a4d8c2SCharles.Forsyth return;
138474a4d8c2SCharles.Forsyth if (cond == Truecond)
138574a4d8c2SCharles.Forsyth pred = predinfo[rstart->prog->as - ABEQ].scond;
138674a4d8c2SCharles.Forsyth else
138774a4d8c2SCharles.Forsyth pred = predinfo[rstart->prog->as - ABEQ].notscond;
138874a4d8c2SCharles.Forsyth
138974a4d8c2SCharles.Forsyth for (r = j->start; ; r = successor(r)) {
139074a4d8c2SCharles.Forsyth if (r->prog->as == AB) {
139174a4d8c2SCharles.Forsyth if (r != j->last || branch == Delbranch)
139274a4d8c2SCharles.Forsyth excise(r);
139374a4d8c2SCharles.Forsyth else {
139474a4d8c2SCharles.Forsyth if (cond == Truecond)
139574a4d8c2SCharles.Forsyth r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
139674a4d8c2SCharles.Forsyth else
139774a4d8c2SCharles.Forsyth r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
139874a4d8c2SCharles.Forsyth }
139974a4d8c2SCharles.Forsyth }
140074a4d8c2SCharles.Forsyth else if (predicable(r->prog))
140174a4d8c2SCharles.Forsyth r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
140274a4d8c2SCharles.Forsyth if (r->s1 != r->link) {
140374a4d8c2SCharles.Forsyth r->s1 = r->link;
140474a4d8c2SCharles.Forsyth r->link->p1 = r;
140574a4d8c2SCharles.Forsyth }
140674a4d8c2SCharles.Forsyth if (r == j->last)
140774a4d8c2SCharles.Forsyth break;
140874a4d8c2SCharles.Forsyth }
140974a4d8c2SCharles.Forsyth }
141074a4d8c2SCharles.Forsyth
141174a4d8c2SCharles.Forsyth void
predicate(void)141274a4d8c2SCharles.Forsyth predicate(void)
141374a4d8c2SCharles.Forsyth {
141474a4d8c2SCharles.Forsyth Reg *r;
141574a4d8c2SCharles.Forsyth int t1, t2;
141674a4d8c2SCharles.Forsyth Joininfo j1, j2;
141774a4d8c2SCharles.Forsyth
141874a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
141974a4d8c2SCharles.Forsyth if (isbranch(r->prog)) {
142074a4d8c2SCharles.Forsyth t1 = joinsplit(r->s1, &j1);
142174a4d8c2SCharles.Forsyth t2 = joinsplit(r->s2, &j2);
142274a4d8c2SCharles.Forsyth if(j1.last->link != j2.start)
142374a4d8c2SCharles.Forsyth continue;
142474a4d8c2SCharles.Forsyth if(j1.end == j2.end)
142574a4d8c2SCharles.Forsyth if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
142674a4d8c2SCharles.Forsyth (t2 == Join && (t1 == Join || t1 == Setcond))) {
142774a4d8c2SCharles.Forsyth applypred(r, &j1, Falsecond, Delbranch);
142874a4d8c2SCharles.Forsyth applypred(r, &j2, Truecond, Delbranch);
142974a4d8c2SCharles.Forsyth excise(r);
143074a4d8c2SCharles.Forsyth continue;
143174a4d8c2SCharles.Forsyth }
143274a4d8c2SCharles.Forsyth if(t1 == End || t1 == Branch) {
143374a4d8c2SCharles.Forsyth applypred(r, &j1, Falsecond, Keepbranch);
143474a4d8c2SCharles.Forsyth excise(r);
143574a4d8c2SCharles.Forsyth continue;
143674a4d8c2SCharles.Forsyth }
143774a4d8c2SCharles.Forsyth }
143874a4d8c2SCharles.Forsyth }
143974a4d8c2SCharles.Forsyth }
1440