174a4d8c2SCharles.Forsyth #include "gc.h"
274a4d8c2SCharles.Forsyth
374a4d8c2SCharles.Forsyth static int
needc(Prog * p)474a4d8c2SCharles.Forsyth needc(Prog *p)
574a4d8c2SCharles.Forsyth {
674a4d8c2SCharles.Forsyth while(p != P) {
774a4d8c2SCharles.Forsyth switch(p->as) {
874a4d8c2SCharles.Forsyth case AADCL:
974a4d8c2SCharles.Forsyth case ASBBL:
1074a4d8c2SCharles.Forsyth case ARCRL:
1174a4d8c2SCharles.Forsyth return 1;
1274a4d8c2SCharles.Forsyth case AADDL:
1374a4d8c2SCharles.Forsyth case ASUBL:
1474a4d8c2SCharles.Forsyth case AJMP:
1574a4d8c2SCharles.Forsyth case ARET:
1674a4d8c2SCharles.Forsyth case ACALL:
1774a4d8c2SCharles.Forsyth return 0;
1874a4d8c2SCharles.Forsyth default:
1974a4d8c2SCharles.Forsyth if(p->to.type == D_BRANCH)
2074a4d8c2SCharles.Forsyth return 0;
2174a4d8c2SCharles.Forsyth }
2274a4d8c2SCharles.Forsyth p = p->link;
2374a4d8c2SCharles.Forsyth }
2474a4d8c2SCharles.Forsyth return 0;
2574a4d8c2SCharles.Forsyth }
2674a4d8c2SCharles.Forsyth
2774a4d8c2SCharles.Forsyth void
peep(void)2874a4d8c2SCharles.Forsyth peep(void)
2974a4d8c2SCharles.Forsyth {
3074a4d8c2SCharles.Forsyth Reg *r, *r1, *r2;
3174a4d8c2SCharles.Forsyth Prog *p, *p1;
3274a4d8c2SCharles.Forsyth int t;
3374a4d8c2SCharles.Forsyth
3474a4d8c2SCharles.Forsyth /*
3574a4d8c2SCharles.Forsyth * complete R structure
3674a4d8c2SCharles.Forsyth */
3774a4d8c2SCharles.Forsyth t = 0;
3874a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r1) {
3974a4d8c2SCharles.Forsyth r1 = r->link;
4074a4d8c2SCharles.Forsyth if(r1 == R)
4174a4d8c2SCharles.Forsyth break;
4274a4d8c2SCharles.Forsyth p = r->prog->link;
4374a4d8c2SCharles.Forsyth while(p != r1->prog)
4474a4d8c2SCharles.Forsyth switch(p->as) {
4574a4d8c2SCharles.Forsyth default:
4674a4d8c2SCharles.Forsyth r2 = rega();
4774a4d8c2SCharles.Forsyth r->link = r2;
4874a4d8c2SCharles.Forsyth r2->link = r1;
4974a4d8c2SCharles.Forsyth
5074a4d8c2SCharles.Forsyth r2->prog = p;
5174a4d8c2SCharles.Forsyth r2->p1 = r;
5274a4d8c2SCharles.Forsyth r->s1 = r2;
5374a4d8c2SCharles.Forsyth r2->s1 = r1;
5474a4d8c2SCharles.Forsyth r1->p1 = r2;
5574a4d8c2SCharles.Forsyth
5674a4d8c2SCharles.Forsyth r = r2;
5774a4d8c2SCharles.Forsyth t++;
5874a4d8c2SCharles.Forsyth
5974a4d8c2SCharles.Forsyth case ADATA:
6074a4d8c2SCharles.Forsyth case AGLOBL:
6174a4d8c2SCharles.Forsyth case ANAME:
6274a4d8c2SCharles.Forsyth case ASIGNAME:
6374a4d8c2SCharles.Forsyth p = p->link;
6474a4d8c2SCharles.Forsyth }
6574a4d8c2SCharles.Forsyth }
6674a4d8c2SCharles.Forsyth
6774a4d8c2SCharles.Forsyth pc = 0; /* speculating it won't kill */
6874a4d8c2SCharles.Forsyth
6974a4d8c2SCharles.Forsyth loop1:
7074a4d8c2SCharles.Forsyth
7174a4d8c2SCharles.Forsyth t = 0;
7274a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link) {
7374a4d8c2SCharles.Forsyth p = r->prog;
7474a4d8c2SCharles.Forsyth switch(p->as) {
7574a4d8c2SCharles.Forsyth case AMOVL:
7674a4d8c2SCharles.Forsyth if(regtyp(&p->to))
7774a4d8c2SCharles.Forsyth if(regtyp(&p->from)) {
7874a4d8c2SCharles.Forsyth if(copyprop(r)) {
7974a4d8c2SCharles.Forsyth excise(r);
8074a4d8c2SCharles.Forsyth t++;
8174a4d8c2SCharles.Forsyth }
8274a4d8c2SCharles.Forsyth if(subprop(r) && copyprop(r)) {
8374a4d8c2SCharles.Forsyth excise(r);
8474a4d8c2SCharles.Forsyth t++;
8574a4d8c2SCharles.Forsyth }
8674a4d8c2SCharles.Forsyth }
8774a4d8c2SCharles.Forsyth break;
8874a4d8c2SCharles.Forsyth
8974a4d8c2SCharles.Forsyth case AMOVBLSX:
9074a4d8c2SCharles.Forsyth case AMOVBLZX:
9174a4d8c2SCharles.Forsyth case AMOVWLSX:
9274a4d8c2SCharles.Forsyth case AMOVWLZX:
9374a4d8c2SCharles.Forsyth if(regtyp(&p->to)) {
9474a4d8c2SCharles.Forsyth r1 = uniqs(r);
9574a4d8c2SCharles.Forsyth if(r1 != R) {
9674a4d8c2SCharles.Forsyth p1 = r1->prog;
9774a4d8c2SCharles.Forsyth if(p->as == p1->as && p->to.type == p1->from.type)
9874a4d8c2SCharles.Forsyth p1->as = AMOVL;
9974a4d8c2SCharles.Forsyth }
10074a4d8c2SCharles.Forsyth }
10174a4d8c2SCharles.Forsyth break;
10274a4d8c2SCharles.Forsyth case AADDL:
10374a4d8c2SCharles.Forsyth case AADDW:
10474a4d8c2SCharles.Forsyth if(p->from.type != D_CONST || needc(p->link))
10574a4d8c2SCharles.Forsyth break;
10674a4d8c2SCharles.Forsyth if(p->from.offset == -1){
10774a4d8c2SCharles.Forsyth if(p->as == AADDL)
10874a4d8c2SCharles.Forsyth p->as = ADECL;
10974a4d8c2SCharles.Forsyth else
11074a4d8c2SCharles.Forsyth p->as = ADECW;
11174a4d8c2SCharles.Forsyth p->from = zprog.from;
11274a4d8c2SCharles.Forsyth }
11374a4d8c2SCharles.Forsyth else if(p->from.offset == 1){
11474a4d8c2SCharles.Forsyth if(p->as == AADDL)
11574a4d8c2SCharles.Forsyth p->as = AINCL;
11674a4d8c2SCharles.Forsyth else
11774a4d8c2SCharles.Forsyth p->as = AINCW;
11874a4d8c2SCharles.Forsyth p->from = zprog.from;
11974a4d8c2SCharles.Forsyth }
12074a4d8c2SCharles.Forsyth break;
12174a4d8c2SCharles.Forsyth case ASUBL:
12274a4d8c2SCharles.Forsyth case ASUBW:
12374a4d8c2SCharles.Forsyth if(p->from.type != D_CONST || needc(p->link))
12474a4d8c2SCharles.Forsyth break;
12574a4d8c2SCharles.Forsyth if(p->from.offset == -1) {
12674a4d8c2SCharles.Forsyth if(p->as == ASUBL)
12774a4d8c2SCharles.Forsyth p->as = AINCL;
12874a4d8c2SCharles.Forsyth else
12974a4d8c2SCharles.Forsyth p->as = AINCW;
13074a4d8c2SCharles.Forsyth p->from = zprog.from;
13174a4d8c2SCharles.Forsyth }
13274a4d8c2SCharles.Forsyth else if(p->from.offset == 1){
13374a4d8c2SCharles.Forsyth if(p->as == ASUBL)
13474a4d8c2SCharles.Forsyth p->as = ADECL;
13574a4d8c2SCharles.Forsyth else
13674a4d8c2SCharles.Forsyth p->as = ADECW;
13774a4d8c2SCharles.Forsyth p->from = zprog.from;
13874a4d8c2SCharles.Forsyth }
13974a4d8c2SCharles.Forsyth break;
14074a4d8c2SCharles.Forsyth }
14174a4d8c2SCharles.Forsyth }
14274a4d8c2SCharles.Forsyth if(t)
14374a4d8c2SCharles.Forsyth goto loop1;
14474a4d8c2SCharles.Forsyth }
14574a4d8c2SCharles.Forsyth
14674a4d8c2SCharles.Forsyth void
excise(Reg * r)14774a4d8c2SCharles.Forsyth excise(Reg *r)
14874a4d8c2SCharles.Forsyth {
14974a4d8c2SCharles.Forsyth Prog *p;
15074a4d8c2SCharles.Forsyth
15174a4d8c2SCharles.Forsyth p = r->prog;
15274a4d8c2SCharles.Forsyth p->as = ANOP;
15374a4d8c2SCharles.Forsyth p->from = zprog.from;
15474a4d8c2SCharles.Forsyth p->to = zprog.to;
15574a4d8c2SCharles.Forsyth }
15674a4d8c2SCharles.Forsyth
15774a4d8c2SCharles.Forsyth Reg*
uniqp(Reg * r)15874a4d8c2SCharles.Forsyth uniqp(Reg *r)
15974a4d8c2SCharles.Forsyth {
16074a4d8c2SCharles.Forsyth Reg *r1;
16174a4d8c2SCharles.Forsyth
16274a4d8c2SCharles.Forsyth r1 = r->p1;
16374a4d8c2SCharles.Forsyth if(r1 == R) {
16474a4d8c2SCharles.Forsyth r1 = r->p2;
16574a4d8c2SCharles.Forsyth if(r1 == R || r1->p2link != R)
16674a4d8c2SCharles.Forsyth return R;
16774a4d8c2SCharles.Forsyth } else
16874a4d8c2SCharles.Forsyth if(r->p2 != R)
16974a4d8c2SCharles.Forsyth return R;
17074a4d8c2SCharles.Forsyth return r1;
17174a4d8c2SCharles.Forsyth }
17274a4d8c2SCharles.Forsyth
17374a4d8c2SCharles.Forsyth Reg*
uniqs(Reg * r)17474a4d8c2SCharles.Forsyth uniqs(Reg *r)
17574a4d8c2SCharles.Forsyth {
17674a4d8c2SCharles.Forsyth Reg *r1;
17774a4d8c2SCharles.Forsyth
17874a4d8c2SCharles.Forsyth r1 = r->s1;
17974a4d8c2SCharles.Forsyth if(r1 == R) {
18074a4d8c2SCharles.Forsyth r1 = r->s2;
18174a4d8c2SCharles.Forsyth if(r1 == R)
18274a4d8c2SCharles.Forsyth return R;
18374a4d8c2SCharles.Forsyth } else
18474a4d8c2SCharles.Forsyth if(r->s2 != R)
18574a4d8c2SCharles.Forsyth return R;
18674a4d8c2SCharles.Forsyth return r1;
18774a4d8c2SCharles.Forsyth }
18874a4d8c2SCharles.Forsyth
18974a4d8c2SCharles.Forsyth int
regtyp(Adr * a)19074a4d8c2SCharles.Forsyth regtyp(Adr *a)
19174a4d8c2SCharles.Forsyth {
19274a4d8c2SCharles.Forsyth int t;
19374a4d8c2SCharles.Forsyth
19474a4d8c2SCharles.Forsyth t = a->type;
19574a4d8c2SCharles.Forsyth if(t >= D_AX && t <= D_DI)
19674a4d8c2SCharles.Forsyth return 1;
19774a4d8c2SCharles.Forsyth return 0;
19874a4d8c2SCharles.Forsyth }
19974a4d8c2SCharles.Forsyth
20074a4d8c2SCharles.Forsyth /*
20174a4d8c2SCharles.Forsyth * the idea is to substitute
20274a4d8c2SCharles.Forsyth * one register for another
20374a4d8c2SCharles.Forsyth * from one MOV to another
20474a4d8c2SCharles.Forsyth * MOV a, R0
20574a4d8c2SCharles.Forsyth * ADD b, R0 / no use of R1
20674a4d8c2SCharles.Forsyth * MOV R0, R1
20774a4d8c2SCharles.Forsyth * would be converted to
20874a4d8c2SCharles.Forsyth * MOV a, R1
20974a4d8c2SCharles.Forsyth * ADD b, R1
21074a4d8c2SCharles.Forsyth * MOV R1, R0
21174a4d8c2SCharles.Forsyth * hopefully, then the former or latter MOV
21274a4d8c2SCharles.Forsyth * will be eliminated by copy propagation.
21374a4d8c2SCharles.Forsyth */
21474a4d8c2SCharles.Forsyth int
subprop(Reg * r0)21574a4d8c2SCharles.Forsyth subprop(Reg *r0)
21674a4d8c2SCharles.Forsyth {
21774a4d8c2SCharles.Forsyth Prog *p;
21874a4d8c2SCharles.Forsyth Adr *v1, *v2;
21974a4d8c2SCharles.Forsyth Reg *r;
22074a4d8c2SCharles.Forsyth int t;
22174a4d8c2SCharles.Forsyth
22274a4d8c2SCharles.Forsyth p = r0->prog;
22374a4d8c2SCharles.Forsyth v1 = &p->from;
22474a4d8c2SCharles.Forsyth if(!regtyp(v1))
22574a4d8c2SCharles.Forsyth return 0;
22674a4d8c2SCharles.Forsyth v2 = &p->to;
22774a4d8c2SCharles.Forsyth if(!regtyp(v2))
22874a4d8c2SCharles.Forsyth return 0;
22974a4d8c2SCharles.Forsyth for(r=uniqp(r0); r!=R; r=uniqp(r)) {
23074a4d8c2SCharles.Forsyth if(uniqs(r) == R)
23174a4d8c2SCharles.Forsyth break;
23274a4d8c2SCharles.Forsyth p = r->prog;
23374a4d8c2SCharles.Forsyth switch(p->as) {
23474a4d8c2SCharles.Forsyth case ACALL:
23574a4d8c2SCharles.Forsyth return 0;
23674a4d8c2SCharles.Forsyth
23774a4d8c2SCharles.Forsyth case AIMULL:
23874a4d8c2SCharles.Forsyth case AIMULW:
23974a4d8c2SCharles.Forsyth if(p->to.type != D_NONE)
24074a4d8c2SCharles.Forsyth break;
24174a4d8c2SCharles.Forsyth
24274a4d8c2SCharles.Forsyth case ADIVB:
24374a4d8c2SCharles.Forsyth case ADIVL:
24474a4d8c2SCharles.Forsyth case ADIVW:
24574a4d8c2SCharles.Forsyth case AIDIVB:
24674a4d8c2SCharles.Forsyth case AIDIVL:
24774a4d8c2SCharles.Forsyth case AIDIVW:
24874a4d8c2SCharles.Forsyth case AIMULB:
24974a4d8c2SCharles.Forsyth case AMULB:
25074a4d8c2SCharles.Forsyth case AMULL:
25174a4d8c2SCharles.Forsyth case AMULW:
25274a4d8c2SCharles.Forsyth
25374a4d8c2SCharles.Forsyth case AROLB:
25474a4d8c2SCharles.Forsyth case AROLL:
25574a4d8c2SCharles.Forsyth case AROLW:
25674a4d8c2SCharles.Forsyth case ARORB:
25774a4d8c2SCharles.Forsyth case ARORL:
25874a4d8c2SCharles.Forsyth case ARORW:
25974a4d8c2SCharles.Forsyth case ASALB:
26074a4d8c2SCharles.Forsyth case ASALL:
26174a4d8c2SCharles.Forsyth case ASALW:
26274a4d8c2SCharles.Forsyth case ASARB:
26374a4d8c2SCharles.Forsyth case ASARL:
26474a4d8c2SCharles.Forsyth case ASARW:
26574a4d8c2SCharles.Forsyth case ASHLB:
26674a4d8c2SCharles.Forsyth case ASHLL:
26774a4d8c2SCharles.Forsyth case ASHLW:
26874a4d8c2SCharles.Forsyth case ASHRB:
26974a4d8c2SCharles.Forsyth case ASHRL:
27074a4d8c2SCharles.Forsyth case ASHRW:
27174a4d8c2SCharles.Forsyth
27274a4d8c2SCharles.Forsyth case AREP:
27374a4d8c2SCharles.Forsyth case AREPN:
27474a4d8c2SCharles.Forsyth
27574a4d8c2SCharles.Forsyth case ACWD:
27674a4d8c2SCharles.Forsyth case ACDQ:
27774a4d8c2SCharles.Forsyth
278*45a20ab7Sforsyth case ASTOSB:
279*45a20ab7Sforsyth case ASTOSL:
280*45a20ab7Sforsyth case AMOVSB:
28174a4d8c2SCharles.Forsyth case AMOVSL:
28274a4d8c2SCharles.Forsyth case AFSTSW:
28374a4d8c2SCharles.Forsyth return 0;
28474a4d8c2SCharles.Forsyth
28574a4d8c2SCharles.Forsyth case AMOVL:
28674a4d8c2SCharles.Forsyth if(p->to.type == v1->type)
28774a4d8c2SCharles.Forsyth goto gotit;
28874a4d8c2SCharles.Forsyth break;
28974a4d8c2SCharles.Forsyth }
29074a4d8c2SCharles.Forsyth if(copyau(&p->from, v2) ||
29174a4d8c2SCharles.Forsyth copyau(&p->to, v2))
29274a4d8c2SCharles.Forsyth break;
29374a4d8c2SCharles.Forsyth if(copysub(&p->from, v1, v2, 0) ||
29474a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 0))
29574a4d8c2SCharles.Forsyth break;
29674a4d8c2SCharles.Forsyth }
29774a4d8c2SCharles.Forsyth return 0;
29874a4d8c2SCharles.Forsyth
29974a4d8c2SCharles.Forsyth gotit:
30074a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 1);
30174a4d8c2SCharles.Forsyth if(debug['P']) {
30274a4d8c2SCharles.Forsyth print("gotit: %D->%D\n%P", v1, v2, r->prog);
30374a4d8c2SCharles.Forsyth if(p->from.type == v2->type)
30474a4d8c2SCharles.Forsyth print(" excise");
30574a4d8c2SCharles.Forsyth print("\n");
30674a4d8c2SCharles.Forsyth }
30774a4d8c2SCharles.Forsyth for(r=uniqs(r); r!=r0; r=uniqs(r)) {
30874a4d8c2SCharles.Forsyth p = r->prog;
30974a4d8c2SCharles.Forsyth copysub(&p->from, v1, v2, 1);
31074a4d8c2SCharles.Forsyth copysub(&p->to, v1, v2, 1);
31174a4d8c2SCharles.Forsyth if(debug['P'])
31274a4d8c2SCharles.Forsyth print("%P\n", r->prog);
31374a4d8c2SCharles.Forsyth }
31474a4d8c2SCharles.Forsyth t = v1->type;
31574a4d8c2SCharles.Forsyth v1->type = v2->type;
31674a4d8c2SCharles.Forsyth v2->type = t;
31774a4d8c2SCharles.Forsyth if(debug['P'])
31874a4d8c2SCharles.Forsyth print("%P last\n", r->prog);
31974a4d8c2SCharles.Forsyth return 1;
32074a4d8c2SCharles.Forsyth }
32174a4d8c2SCharles.Forsyth
32274a4d8c2SCharles.Forsyth /*
32374a4d8c2SCharles.Forsyth * The idea is to remove redundant copies.
32474a4d8c2SCharles.Forsyth * v1->v2 F=0
32574a4d8c2SCharles.Forsyth * (use v2 s/v2/v1/)*
32674a4d8c2SCharles.Forsyth * set v1 F=1
32774a4d8c2SCharles.Forsyth * use v2 return fail
32874a4d8c2SCharles.Forsyth * -----------------
32974a4d8c2SCharles.Forsyth * v1->v2 F=0
33074a4d8c2SCharles.Forsyth * (use v2 s/v2/v1/)*
33174a4d8c2SCharles.Forsyth * set v1 F=1
33274a4d8c2SCharles.Forsyth * set v2 return success
33374a4d8c2SCharles.Forsyth */
33474a4d8c2SCharles.Forsyth int
copyprop(Reg * r0)33574a4d8c2SCharles.Forsyth copyprop(Reg *r0)
33674a4d8c2SCharles.Forsyth {
33774a4d8c2SCharles.Forsyth Prog *p;
33874a4d8c2SCharles.Forsyth Adr *v1, *v2;
33974a4d8c2SCharles.Forsyth Reg *r;
34074a4d8c2SCharles.Forsyth
34174a4d8c2SCharles.Forsyth p = r0->prog;
34274a4d8c2SCharles.Forsyth v1 = &p->from;
34374a4d8c2SCharles.Forsyth v2 = &p->to;
34474a4d8c2SCharles.Forsyth if(copyas(v1, v2))
34574a4d8c2SCharles.Forsyth return 1;
34674a4d8c2SCharles.Forsyth for(r=firstr; r!=R; r=r->link)
34774a4d8c2SCharles.Forsyth r->active = 0;
34874a4d8c2SCharles.Forsyth return copy1(v1, v2, r0->s1, 0);
34974a4d8c2SCharles.Forsyth }
35074a4d8c2SCharles.Forsyth
35174a4d8c2SCharles.Forsyth int
copy1(Adr * v1,Adr * v2,Reg * r,int f)35274a4d8c2SCharles.Forsyth copy1(Adr *v1, Adr *v2, Reg *r, int f)
35374a4d8c2SCharles.Forsyth {
35474a4d8c2SCharles.Forsyth int t;
35574a4d8c2SCharles.Forsyth Prog *p;
35674a4d8c2SCharles.Forsyth
35774a4d8c2SCharles.Forsyth if(r->active) {
35874a4d8c2SCharles.Forsyth if(debug['P'])
35974a4d8c2SCharles.Forsyth print("act set; return 1\n");
36074a4d8c2SCharles.Forsyth return 1;
36174a4d8c2SCharles.Forsyth }
36274a4d8c2SCharles.Forsyth r->active = 1;
36374a4d8c2SCharles.Forsyth if(debug['P'])
36474a4d8c2SCharles.Forsyth print("copy %D->%D f=%d\n", v1, v2, f);
36574a4d8c2SCharles.Forsyth for(; r != R; r = r->s1) {
36674a4d8c2SCharles.Forsyth p = r->prog;
36774a4d8c2SCharles.Forsyth if(debug['P'])
36874a4d8c2SCharles.Forsyth print("%P", p);
36974a4d8c2SCharles.Forsyth if(!f && uniqp(r) == R) {
37074a4d8c2SCharles.Forsyth f = 1;
37174a4d8c2SCharles.Forsyth if(debug['P'])
37274a4d8c2SCharles.Forsyth print("; merge; f=%d", f);
37374a4d8c2SCharles.Forsyth }
37474a4d8c2SCharles.Forsyth t = copyu(p, v2, A);
37574a4d8c2SCharles.Forsyth switch(t) {
37674a4d8c2SCharles.Forsyth case 2: /* rar, cant split */
37774a4d8c2SCharles.Forsyth if(debug['P'])
37874a4d8c2SCharles.Forsyth print("; %D rar; return 0\n", v2);
37974a4d8c2SCharles.Forsyth return 0;
38074a4d8c2SCharles.Forsyth
38174a4d8c2SCharles.Forsyth case 3: /* set */
38274a4d8c2SCharles.Forsyth if(debug['P'])
38374a4d8c2SCharles.Forsyth print("; %D set; return 1\n", v2);
38474a4d8c2SCharles.Forsyth return 1;
38574a4d8c2SCharles.Forsyth
38674a4d8c2SCharles.Forsyth case 1: /* used, substitute */
38774a4d8c2SCharles.Forsyth case 4: /* use and set */
38874a4d8c2SCharles.Forsyth if(f) {
38974a4d8c2SCharles.Forsyth if(!debug['P'])
39074a4d8c2SCharles.Forsyth return 0;
39174a4d8c2SCharles.Forsyth if(t == 4)
39274a4d8c2SCharles.Forsyth print("; %D used+set and f=%d; return 0\n", v2, f);
39374a4d8c2SCharles.Forsyth else
39474a4d8c2SCharles.Forsyth print("; %D used and f=%d; return 0\n", v2, f);
39574a4d8c2SCharles.Forsyth return 0;
39674a4d8c2SCharles.Forsyth }
39774a4d8c2SCharles.Forsyth if(copyu(p, v2, v1)) {
39874a4d8c2SCharles.Forsyth if(debug['P'])
39974a4d8c2SCharles.Forsyth print("; sub fail; return 0\n");
40074a4d8c2SCharles.Forsyth return 0;
40174a4d8c2SCharles.Forsyth }
40274a4d8c2SCharles.Forsyth if(debug['P'])
40374a4d8c2SCharles.Forsyth print("; sub %D/%D", v2, v1);
40474a4d8c2SCharles.Forsyth if(t == 4) {
40574a4d8c2SCharles.Forsyth if(debug['P'])
40674a4d8c2SCharles.Forsyth print("; %D used+set; return 1\n", v2);
40774a4d8c2SCharles.Forsyth return 1;
40874a4d8c2SCharles.Forsyth }
40974a4d8c2SCharles.Forsyth break;
41074a4d8c2SCharles.Forsyth }
41174a4d8c2SCharles.Forsyth if(!f) {
41274a4d8c2SCharles.Forsyth t = copyu(p, v1, A);
41374a4d8c2SCharles.Forsyth if(!f && (t == 2 || t == 3 || t == 4)) {
41474a4d8c2SCharles.Forsyth f = 1;
41574a4d8c2SCharles.Forsyth if(debug['P'])
41674a4d8c2SCharles.Forsyth print("; %D set and !f; f=%d", v1, f);
41774a4d8c2SCharles.Forsyth }
41874a4d8c2SCharles.Forsyth }
41974a4d8c2SCharles.Forsyth if(debug['P'])
42074a4d8c2SCharles.Forsyth print("\n");
42174a4d8c2SCharles.Forsyth if(r->s2)
42274a4d8c2SCharles.Forsyth if(!copy1(v1, v2, r->s2, f))
42374a4d8c2SCharles.Forsyth return 0;
42474a4d8c2SCharles.Forsyth }
42574a4d8c2SCharles.Forsyth return 1;
42674a4d8c2SCharles.Forsyth }
42774a4d8c2SCharles.Forsyth
42874a4d8c2SCharles.Forsyth /*
42974a4d8c2SCharles.Forsyth * return
43074a4d8c2SCharles.Forsyth * 1 if v only used (and substitute),
43174a4d8c2SCharles.Forsyth * 2 if read-alter-rewrite
43274a4d8c2SCharles.Forsyth * 3 if set
43374a4d8c2SCharles.Forsyth * 4 if set and used
43474a4d8c2SCharles.Forsyth * 0 otherwise (not touched)
43574a4d8c2SCharles.Forsyth */
43674a4d8c2SCharles.Forsyth int
copyu(Prog * p,Adr * v,Adr * s)43774a4d8c2SCharles.Forsyth copyu(Prog *p, Adr *v, Adr *s)
43874a4d8c2SCharles.Forsyth {
43974a4d8c2SCharles.Forsyth
44074a4d8c2SCharles.Forsyth switch(p->as) {
44174a4d8c2SCharles.Forsyth
44274a4d8c2SCharles.Forsyth default:
44374a4d8c2SCharles.Forsyth if(debug['P'])
44474a4d8c2SCharles.Forsyth print("unknown op %A\n", p->as);
44574a4d8c2SCharles.Forsyth return 2;
44674a4d8c2SCharles.Forsyth
44774a4d8c2SCharles.Forsyth case ANEGB:
44874a4d8c2SCharles.Forsyth case ANEGW:
44974a4d8c2SCharles.Forsyth case ANEGL:
45074a4d8c2SCharles.Forsyth case ANOTB:
45174a4d8c2SCharles.Forsyth case ANOTW:
45274a4d8c2SCharles.Forsyth case ANOTL:
45374a4d8c2SCharles.Forsyth if(copyas(&p->to, v))
45474a4d8c2SCharles.Forsyth return 2;
45574a4d8c2SCharles.Forsyth break;
45674a4d8c2SCharles.Forsyth
45774a4d8c2SCharles.Forsyth case ALEAL: /* lhs addr, rhs store */
45874a4d8c2SCharles.Forsyth if(copyas(&p->from, v))
45974a4d8c2SCharles.Forsyth return 2;
46074a4d8c2SCharles.Forsyth
46174a4d8c2SCharles.Forsyth
46274a4d8c2SCharles.Forsyth case ANOP: /* rhs store */
46374a4d8c2SCharles.Forsyth case AMOVL:
46474a4d8c2SCharles.Forsyth case AMOVBLSX:
46574a4d8c2SCharles.Forsyth case AMOVBLZX:
46674a4d8c2SCharles.Forsyth case AMOVWLSX:
46774a4d8c2SCharles.Forsyth case AMOVWLZX:
46874a4d8c2SCharles.Forsyth if(copyas(&p->to, v)) {
46974a4d8c2SCharles.Forsyth if(s != A)
47074a4d8c2SCharles.Forsyth return copysub(&p->from, v, s, 1);
47174a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
47274a4d8c2SCharles.Forsyth return 4;
47374a4d8c2SCharles.Forsyth return 3;
47474a4d8c2SCharles.Forsyth }
47574a4d8c2SCharles.Forsyth goto caseread;
47674a4d8c2SCharles.Forsyth
47774a4d8c2SCharles.Forsyth case AROLB:
47874a4d8c2SCharles.Forsyth case AROLL:
47974a4d8c2SCharles.Forsyth case AROLW:
48074a4d8c2SCharles.Forsyth case ARORB:
48174a4d8c2SCharles.Forsyth case ARORL:
48274a4d8c2SCharles.Forsyth case ARORW:
48374a4d8c2SCharles.Forsyth case ASALB:
48474a4d8c2SCharles.Forsyth case ASALL:
48574a4d8c2SCharles.Forsyth case ASALW:
48674a4d8c2SCharles.Forsyth case ASARB:
48774a4d8c2SCharles.Forsyth case ASARL:
48874a4d8c2SCharles.Forsyth case ASARW:
48974a4d8c2SCharles.Forsyth case ASHLB:
49074a4d8c2SCharles.Forsyth case ASHLL:
49174a4d8c2SCharles.Forsyth case ASHLW:
49274a4d8c2SCharles.Forsyth case ASHRB:
49374a4d8c2SCharles.Forsyth case ASHRL:
49474a4d8c2SCharles.Forsyth case ASHRW:
49574a4d8c2SCharles.Forsyth if(copyas(&p->to, v))
49674a4d8c2SCharles.Forsyth return 2;
49774a4d8c2SCharles.Forsyth if(copyas(&p->from, v))
49874a4d8c2SCharles.Forsyth if(p->from.type == D_CX)
49974a4d8c2SCharles.Forsyth return 2;
50074a4d8c2SCharles.Forsyth goto caseread;
50174a4d8c2SCharles.Forsyth
50274a4d8c2SCharles.Forsyth case AADDB: /* rhs rar */
50374a4d8c2SCharles.Forsyth case AADDL:
50474a4d8c2SCharles.Forsyth case AADDW:
50574a4d8c2SCharles.Forsyth case AANDB:
50674a4d8c2SCharles.Forsyth case AANDL:
50774a4d8c2SCharles.Forsyth case AANDW:
50874a4d8c2SCharles.Forsyth case ADECL:
50974a4d8c2SCharles.Forsyth case ADECW:
51074a4d8c2SCharles.Forsyth case AINCL:
51174a4d8c2SCharles.Forsyth case AINCW:
51274a4d8c2SCharles.Forsyth case ASUBB:
51374a4d8c2SCharles.Forsyth case ASUBL:
51474a4d8c2SCharles.Forsyth case ASUBW:
51574a4d8c2SCharles.Forsyth case AORB:
51674a4d8c2SCharles.Forsyth case AORL:
51774a4d8c2SCharles.Forsyth case AORW:
51874a4d8c2SCharles.Forsyth case AXORB:
51974a4d8c2SCharles.Forsyth case AXORL:
52074a4d8c2SCharles.Forsyth case AXORW:
52174a4d8c2SCharles.Forsyth case AMOVB:
52274a4d8c2SCharles.Forsyth case AMOVW:
52374a4d8c2SCharles.Forsyth
52474a4d8c2SCharles.Forsyth case AFMOVB:
52574a4d8c2SCharles.Forsyth case AFMOVBP:
52674a4d8c2SCharles.Forsyth case AFMOVD:
52774a4d8c2SCharles.Forsyth case AFMOVDP:
52874a4d8c2SCharles.Forsyth case AFMOVF:
52974a4d8c2SCharles.Forsyth case AFMOVFP:
53074a4d8c2SCharles.Forsyth case AFMOVL:
53174a4d8c2SCharles.Forsyth case AFMOVLP:
53274a4d8c2SCharles.Forsyth case AFMOVV:
53374a4d8c2SCharles.Forsyth case AFMOVVP:
53474a4d8c2SCharles.Forsyth case AFMOVW:
53574a4d8c2SCharles.Forsyth case AFMOVWP:
53674a4d8c2SCharles.Forsyth case AFMOVX:
53774a4d8c2SCharles.Forsyth case AFMOVXP:
53874a4d8c2SCharles.Forsyth case AFADDDP:
53974a4d8c2SCharles.Forsyth case AFADDW:
54074a4d8c2SCharles.Forsyth case AFADDL:
54174a4d8c2SCharles.Forsyth case AFADDF:
54274a4d8c2SCharles.Forsyth case AFADDD:
54374a4d8c2SCharles.Forsyth case AFMULDP:
54474a4d8c2SCharles.Forsyth case AFMULW:
54574a4d8c2SCharles.Forsyth case AFMULL:
54674a4d8c2SCharles.Forsyth case AFMULF:
54774a4d8c2SCharles.Forsyth case AFMULD:
54874a4d8c2SCharles.Forsyth case AFSUBDP:
54974a4d8c2SCharles.Forsyth case AFSUBW:
55074a4d8c2SCharles.Forsyth case AFSUBL:
55174a4d8c2SCharles.Forsyth case AFSUBF:
55274a4d8c2SCharles.Forsyth case AFSUBD:
55374a4d8c2SCharles.Forsyth case AFSUBRDP:
55474a4d8c2SCharles.Forsyth case AFSUBRW:
55574a4d8c2SCharles.Forsyth case AFSUBRL:
55674a4d8c2SCharles.Forsyth case AFSUBRF:
55774a4d8c2SCharles.Forsyth case AFSUBRD:
55874a4d8c2SCharles.Forsyth case AFDIVDP:
55974a4d8c2SCharles.Forsyth case AFDIVW:
56074a4d8c2SCharles.Forsyth case AFDIVL:
56174a4d8c2SCharles.Forsyth case AFDIVF:
56274a4d8c2SCharles.Forsyth case AFDIVD:
56374a4d8c2SCharles.Forsyth case AFDIVRDP:
56474a4d8c2SCharles.Forsyth case AFDIVRW:
56574a4d8c2SCharles.Forsyth case AFDIVRL:
56674a4d8c2SCharles.Forsyth case AFDIVRF:
56774a4d8c2SCharles.Forsyth case AFDIVRD:
56874a4d8c2SCharles.Forsyth if(copyas(&p->to, v))
56974a4d8c2SCharles.Forsyth return 2;
57074a4d8c2SCharles.Forsyth goto caseread;
57174a4d8c2SCharles.Forsyth
57274a4d8c2SCharles.Forsyth case ACMPL: /* read only */
57374a4d8c2SCharles.Forsyth case ACMPW:
57474a4d8c2SCharles.Forsyth case ACMPB:
57574a4d8c2SCharles.Forsyth
57674a4d8c2SCharles.Forsyth case AFCOMB:
57774a4d8c2SCharles.Forsyth case AFCOMBP:
57874a4d8c2SCharles.Forsyth case AFCOMD:
57974a4d8c2SCharles.Forsyth case AFCOMDP:
58074a4d8c2SCharles.Forsyth case AFCOMDPP:
58174a4d8c2SCharles.Forsyth case AFCOMF:
58274a4d8c2SCharles.Forsyth case AFCOMFP:
58374a4d8c2SCharles.Forsyth case AFCOML:
58474a4d8c2SCharles.Forsyth case AFCOMLP:
58574a4d8c2SCharles.Forsyth case AFCOMW:
58674a4d8c2SCharles.Forsyth case AFCOMWP:
58774a4d8c2SCharles.Forsyth case AFUCOM:
58874a4d8c2SCharles.Forsyth case AFUCOMP:
58974a4d8c2SCharles.Forsyth case AFUCOMPP:
59074a4d8c2SCharles.Forsyth caseread:
59174a4d8c2SCharles.Forsyth if(s != A) {
59274a4d8c2SCharles.Forsyth if(copysub(&p->from, v, s, 1))
59374a4d8c2SCharles.Forsyth return 1;
59474a4d8c2SCharles.Forsyth return copysub(&p->to, v, s, 1);
59574a4d8c2SCharles.Forsyth }
59674a4d8c2SCharles.Forsyth if(copyau(&p->from, v))
59774a4d8c2SCharles.Forsyth return 1;
59874a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
59974a4d8c2SCharles.Forsyth return 1;
60074a4d8c2SCharles.Forsyth break;
60174a4d8c2SCharles.Forsyth
60274a4d8c2SCharles.Forsyth case AJGE: /* no reference */
60374a4d8c2SCharles.Forsyth case AJNE:
60474a4d8c2SCharles.Forsyth case AJLE:
60574a4d8c2SCharles.Forsyth case AJEQ:
60674a4d8c2SCharles.Forsyth case AJHI:
60774a4d8c2SCharles.Forsyth case AJLS:
60874a4d8c2SCharles.Forsyth case AJMI:
60974a4d8c2SCharles.Forsyth case AJPL:
61074a4d8c2SCharles.Forsyth case AJGT:
61174a4d8c2SCharles.Forsyth case AJLT:
61274a4d8c2SCharles.Forsyth case AJCC:
61374a4d8c2SCharles.Forsyth case AJCS:
61474a4d8c2SCharles.Forsyth
61574a4d8c2SCharles.Forsyth case AADJSP:
61674a4d8c2SCharles.Forsyth case AFLDZ:
61774a4d8c2SCharles.Forsyth case AWAIT:
61874a4d8c2SCharles.Forsyth break;
61974a4d8c2SCharles.Forsyth
62074a4d8c2SCharles.Forsyth case AIMULL:
62174a4d8c2SCharles.Forsyth case AIMULW:
62274a4d8c2SCharles.Forsyth if(p->to.type != D_NONE) {
62374a4d8c2SCharles.Forsyth if(copyas(&p->to, v))
62474a4d8c2SCharles.Forsyth return 2;
62574a4d8c2SCharles.Forsyth goto caseread;
62674a4d8c2SCharles.Forsyth }
62774a4d8c2SCharles.Forsyth
62874a4d8c2SCharles.Forsyth case ADIVB:
62974a4d8c2SCharles.Forsyth case ADIVL:
63074a4d8c2SCharles.Forsyth case ADIVW:
63174a4d8c2SCharles.Forsyth case AIDIVB:
63274a4d8c2SCharles.Forsyth case AIDIVL:
63374a4d8c2SCharles.Forsyth case AIDIVW:
63474a4d8c2SCharles.Forsyth case AIMULB:
63574a4d8c2SCharles.Forsyth case AMULB:
63674a4d8c2SCharles.Forsyth case AMULL:
63774a4d8c2SCharles.Forsyth case AMULW:
63874a4d8c2SCharles.Forsyth
63974a4d8c2SCharles.Forsyth case ACWD:
64074a4d8c2SCharles.Forsyth case ACDQ:
64174a4d8c2SCharles.Forsyth if(v->type == D_AX || v->type == D_DX)
64274a4d8c2SCharles.Forsyth return 2;
64374a4d8c2SCharles.Forsyth goto caseread;
64474a4d8c2SCharles.Forsyth
64574a4d8c2SCharles.Forsyth case AREP:
64674a4d8c2SCharles.Forsyth case AREPN:
6474d1cf526Sforsyth if(v->type == D_CX)
6484d1cf526Sforsyth return 2;
6494d1cf526Sforsyth goto caseread;
6504d1cf526Sforsyth
651*45a20ab7Sforsyth case AMOVSB:
6524d1cf526Sforsyth case AMOVSL:
6534d1cf526Sforsyth if(v->type == D_DI || v->type == D_SI)
65474a4d8c2SCharles.Forsyth return 2;
65574a4d8c2SCharles.Forsyth goto caseread;
65674a4d8c2SCharles.Forsyth
657*45a20ab7Sforsyth case ASTOSB:
658*45a20ab7Sforsyth case ASTOSL:
659*45a20ab7Sforsyth if(v->type == D_AX || v->type == D_DI)
660*45a20ab7Sforsyth return 2;
661*45a20ab7Sforsyth goto caseread;
662*45a20ab7Sforsyth
66374a4d8c2SCharles.Forsyth case AFSTSW:
66474a4d8c2SCharles.Forsyth if(v->type == D_AX)
66574a4d8c2SCharles.Forsyth return 2;
66674a4d8c2SCharles.Forsyth goto caseread;
66774a4d8c2SCharles.Forsyth
66874a4d8c2SCharles.Forsyth case AJMP: /* funny */
66974a4d8c2SCharles.Forsyth if(s != A) {
67074a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
67174a4d8c2SCharles.Forsyth return 1;
67274a4d8c2SCharles.Forsyth return 0;
67374a4d8c2SCharles.Forsyth }
67474a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
67574a4d8c2SCharles.Forsyth return 1;
67674a4d8c2SCharles.Forsyth return 0;
67774a4d8c2SCharles.Forsyth
67874a4d8c2SCharles.Forsyth case ARET: /* funny */
67974a4d8c2SCharles.Forsyth if(v->type == REGRET)
68074a4d8c2SCharles.Forsyth return 2;
68174a4d8c2SCharles.Forsyth if(s != A)
68274a4d8c2SCharles.Forsyth return 1;
68374a4d8c2SCharles.Forsyth return 3;
68474a4d8c2SCharles.Forsyth
68574a4d8c2SCharles.Forsyth case ACALL: /* funny */
686c0927006Sforsyth if(REGARG>=0 && v->type == REGARG)
68774a4d8c2SCharles.Forsyth return 2;
68874a4d8c2SCharles.Forsyth
68974a4d8c2SCharles.Forsyth if(s != A) {
69074a4d8c2SCharles.Forsyth if(copysub(&p->to, v, s, 1))
69174a4d8c2SCharles.Forsyth return 1;
69274a4d8c2SCharles.Forsyth return 0;
69374a4d8c2SCharles.Forsyth }
69474a4d8c2SCharles.Forsyth if(copyau(&p->to, v))
69574a4d8c2SCharles.Forsyth return 4;
69674a4d8c2SCharles.Forsyth return 3;
69774a4d8c2SCharles.Forsyth }
69874a4d8c2SCharles.Forsyth return 0;
69974a4d8c2SCharles.Forsyth }
70074a4d8c2SCharles.Forsyth
70174a4d8c2SCharles.Forsyth /*
70274a4d8c2SCharles.Forsyth * direct reference,
70374a4d8c2SCharles.Forsyth * could be set/use depending on
70474a4d8c2SCharles.Forsyth * semantics
70574a4d8c2SCharles.Forsyth */
70674a4d8c2SCharles.Forsyth int
copyas(Adr * a,Adr * v)70774a4d8c2SCharles.Forsyth copyas(Adr *a, Adr *v)
70874a4d8c2SCharles.Forsyth {
70974a4d8c2SCharles.Forsyth if(a->type != v->type)
71074a4d8c2SCharles.Forsyth return 0;
71174a4d8c2SCharles.Forsyth if(regtyp(v))
71274a4d8c2SCharles.Forsyth return 1;
71374a4d8c2SCharles.Forsyth if(v->type == D_AUTO || v->type == D_PARAM)
71474a4d8c2SCharles.Forsyth if(v->offset == a->offset)
71574a4d8c2SCharles.Forsyth return 1;
71674a4d8c2SCharles.Forsyth return 0;
71774a4d8c2SCharles.Forsyth }
71874a4d8c2SCharles.Forsyth
71974a4d8c2SCharles.Forsyth /*
72074a4d8c2SCharles.Forsyth * either direct or indirect
72174a4d8c2SCharles.Forsyth */
72274a4d8c2SCharles.Forsyth int
copyau(Adr * a,Adr * v)72374a4d8c2SCharles.Forsyth copyau(Adr *a, Adr *v)
72474a4d8c2SCharles.Forsyth {
72574a4d8c2SCharles.Forsyth
72674a4d8c2SCharles.Forsyth if(copyas(a, v))
72774a4d8c2SCharles.Forsyth return 1;
72874a4d8c2SCharles.Forsyth if(regtyp(v)) {
72974a4d8c2SCharles.Forsyth if(a->type-D_INDIR == v->type)
73074a4d8c2SCharles.Forsyth return 1;
73174a4d8c2SCharles.Forsyth if(a->index == v->type)
73274a4d8c2SCharles.Forsyth return 1;
73374a4d8c2SCharles.Forsyth }
73474a4d8c2SCharles.Forsyth return 0;
73574a4d8c2SCharles.Forsyth }
73674a4d8c2SCharles.Forsyth
73774a4d8c2SCharles.Forsyth /*
73874a4d8c2SCharles.Forsyth * substitute s for v in a
73974a4d8c2SCharles.Forsyth * return failure to substitute
74074a4d8c2SCharles.Forsyth */
74174a4d8c2SCharles.Forsyth int
copysub(Adr * a,Adr * v,Adr * s,int f)74274a4d8c2SCharles.Forsyth copysub(Adr *a, Adr *v, Adr *s, int f)
74374a4d8c2SCharles.Forsyth {
74474a4d8c2SCharles.Forsyth int t;
74574a4d8c2SCharles.Forsyth
74674a4d8c2SCharles.Forsyth if(copyas(a, v)) {
74774a4d8c2SCharles.Forsyth t = s->type;
74874a4d8c2SCharles.Forsyth if(t >= D_AX && t <= D_DI) {
74974a4d8c2SCharles.Forsyth if(f)
75074a4d8c2SCharles.Forsyth a->type = t;
75174a4d8c2SCharles.Forsyth }
75274a4d8c2SCharles.Forsyth return 0;
75374a4d8c2SCharles.Forsyth }
75474a4d8c2SCharles.Forsyth if(regtyp(v)) {
75574a4d8c2SCharles.Forsyth t = v->type;
75674a4d8c2SCharles.Forsyth if(a->type == t+D_INDIR) {
75774a4d8c2SCharles.Forsyth if(s->type == D_BP && a->index != D_NONE)
75874a4d8c2SCharles.Forsyth return 1; /* can't use BP-base with index */
75974a4d8c2SCharles.Forsyth if(f)
76074a4d8c2SCharles.Forsyth a->type = s->type+D_INDIR;
76174a4d8c2SCharles.Forsyth // return 0;
76274a4d8c2SCharles.Forsyth }
76374a4d8c2SCharles.Forsyth if(a->index == t) {
76474a4d8c2SCharles.Forsyth if(f)
76574a4d8c2SCharles.Forsyth a->index = s->type;
76674a4d8c2SCharles.Forsyth return 0;
76774a4d8c2SCharles.Forsyth }
76874a4d8c2SCharles.Forsyth return 0;
76974a4d8c2SCharles.Forsyth }
77074a4d8c2SCharles.Forsyth return 0;
77174a4d8c2SCharles.Forsyth }
772