17dd7cddfSDavid du Colombier #include "gc.h"
27dd7cddfSDavid du Colombier
359cc4ca5SDavid du Colombier int xtramodes(Reg*, Adr*);
459cc4ca5SDavid du Colombier
57dd7cddfSDavid du Colombier void
peep(void)67dd7cddfSDavid du Colombier peep(void)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier Reg *r, *r1, *r2;
97dd7cddfSDavid du Colombier Prog *p, *p1;
107dd7cddfSDavid du Colombier int t;
117dd7cddfSDavid du Colombier /*
127dd7cddfSDavid du Colombier * complete R structure
137dd7cddfSDavid du Colombier */
147dd7cddfSDavid du Colombier t = 0;
157dd7cddfSDavid du Colombier for(r=firstr; r!=R; r=r1) {
167dd7cddfSDavid du Colombier r1 = r->link;
177dd7cddfSDavid du Colombier if(r1 == R)
187dd7cddfSDavid du Colombier break;
197dd7cddfSDavid du Colombier p = r->prog->link;
207dd7cddfSDavid du Colombier while(p != r1->prog)
217dd7cddfSDavid du Colombier switch(p->as) {
227dd7cddfSDavid du Colombier default:
237dd7cddfSDavid du Colombier r2 = rega();
247dd7cddfSDavid du Colombier r->link = r2;
257dd7cddfSDavid du Colombier r2->link = r1;
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier r2->prog = p;
287dd7cddfSDavid du Colombier r2->p1 = r;
297dd7cddfSDavid du Colombier r->s1 = r2;
307dd7cddfSDavid du Colombier r2->s1 = r1;
317dd7cddfSDavid du Colombier r1->p1 = r2;
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier r = r2;
347dd7cddfSDavid du Colombier t++;
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier case ADATA:
377dd7cddfSDavid du Colombier case AGLOBL:
387dd7cddfSDavid du Colombier case ANAME:
39375daca8SDavid du Colombier case ASIGNAME:
407dd7cddfSDavid du Colombier p = p->link;
417dd7cddfSDavid du Colombier }
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier
447dd7cddfSDavid du Colombier loop1:
457dd7cddfSDavid du Colombier t = 0;
467dd7cddfSDavid du Colombier for(r=firstr; r!=R; r=r->link) {
477dd7cddfSDavid du Colombier p = r->prog;
4859cc4ca5SDavid du Colombier if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
4959cc4ca5SDavid du Colombier /*
5059cc4ca5SDavid du Colombier * elide shift into D_SHIFT operand of subsequent instruction
5159cc4ca5SDavid du Colombier */
5259cc4ca5SDavid du Colombier if(shiftprop(r)) {
5359cc4ca5SDavid du Colombier excise(r);
5459cc4ca5SDavid du Colombier t++;
5559cc4ca5SDavid du Colombier }
5659cc4ca5SDavid du Colombier }
577dd7cddfSDavid du Colombier if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
587dd7cddfSDavid du Colombier if(regtyp(&p->to)) {
5959cc4ca5SDavid du Colombier if(p->from.type == D_CONST)
6059cc4ca5SDavid du Colombier constprop(&p->from, &p->to, r->s1);
6159cc4ca5SDavid du Colombier else if(regtyp(&p->from))
627dd7cddfSDavid du Colombier if(p->from.type == p->to.type) {
637dd7cddfSDavid du Colombier if(copyprop(r)) {
647dd7cddfSDavid du Colombier excise(r);
657dd7cddfSDavid du Colombier t++;
667dd7cddfSDavid du Colombier } else
677dd7cddfSDavid du Colombier if(subprop(r) && copyprop(r)) {
687dd7cddfSDavid du Colombier excise(r);
697dd7cddfSDavid du Colombier t++;
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier }
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier }
747dd7cddfSDavid du Colombier if(t)
757dd7cddfSDavid du Colombier goto loop1;
767dd7cddfSDavid du Colombier /*
777dd7cddfSDavid du Colombier * look for MOVB x,R; MOVB R,R
787dd7cddfSDavid du Colombier */
797dd7cddfSDavid du Colombier for(r=firstr; r!=R; r=r->link) {
807dd7cddfSDavid du Colombier p = r->prog;
817dd7cddfSDavid du Colombier switch(p->as) {
827dd7cddfSDavid du Colombier default:
837dd7cddfSDavid du Colombier continue;
8459cc4ca5SDavid du Colombier case AEOR:
8559cc4ca5SDavid du Colombier /*
8659cc4ca5SDavid du Colombier * EOR -1,x,y => MVN x,y
8759cc4ca5SDavid du Colombier */
8859cc4ca5SDavid du Colombier if(p->from.type == D_CONST && p->from.offset == -1) {
8959cc4ca5SDavid du Colombier p->as = AMVN;
9059cc4ca5SDavid du Colombier p->from.type = D_REG;
9159cc4ca5SDavid du Colombier if(p->reg != NREG)
9259cc4ca5SDavid du Colombier p->from.reg = p->reg;
9359cc4ca5SDavid du Colombier else
9459cc4ca5SDavid du Colombier p->from.reg = p->to.reg;
9559cc4ca5SDavid du Colombier p->reg = NREG;
9659cc4ca5SDavid du Colombier }
9759cc4ca5SDavid du Colombier continue;
987dd7cddfSDavid du Colombier case AMOVH:
997dd7cddfSDavid du Colombier case AMOVHU:
1007dd7cddfSDavid du Colombier case AMOVB:
1017dd7cddfSDavid du Colombier case AMOVBU:
1027dd7cddfSDavid du Colombier if(p->to.type != D_REG)
1037dd7cddfSDavid du Colombier continue;
1047dd7cddfSDavid du Colombier break;
1057dd7cddfSDavid du Colombier }
1067dd7cddfSDavid du Colombier r1 = r->link;
1077dd7cddfSDavid du Colombier if(r1 == R)
1087dd7cddfSDavid du Colombier continue;
1097dd7cddfSDavid du Colombier p1 = r1->prog;
1107dd7cddfSDavid du Colombier if(p1->as != p->as)
1117dd7cddfSDavid du Colombier continue;
1127dd7cddfSDavid du Colombier if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
1137dd7cddfSDavid du Colombier continue;
1147dd7cddfSDavid du Colombier if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
1157dd7cddfSDavid du Colombier continue;
1167dd7cddfSDavid du Colombier excise(r1);
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier
11959cc4ca5SDavid du Colombier for(r=firstr; r!=R; r=r->link) {
12059cc4ca5SDavid du Colombier p = r->prog;
12159cc4ca5SDavid du Colombier switch(p->as) {
12259cc4ca5SDavid du Colombier case AMOVW:
12359cc4ca5SDavid du Colombier case AMOVB:
12459cc4ca5SDavid du Colombier case AMOVBU:
12559cc4ca5SDavid du Colombier if(p->from.type == D_OREG && p->from.offset == 0)
12659cc4ca5SDavid du Colombier xtramodes(r, &p->from);
12759cc4ca5SDavid du Colombier else if(p->to.type == D_OREG && p->to.offset == 0)
12859cc4ca5SDavid du Colombier xtramodes(r, &p->to);
12959cc4ca5SDavid du Colombier else
13059cc4ca5SDavid du Colombier continue;
13159cc4ca5SDavid du Colombier break;
13259cc4ca5SDavid du Colombier case ACMP:
13359cc4ca5SDavid du Colombier /*
13459cc4ca5SDavid du Colombier * elide CMP $0,x if calculation of x can set condition codes
13559cc4ca5SDavid du Colombier */
13659cc4ca5SDavid du Colombier if(p->from.type != D_CONST || p->from.offset != 0)
13759cc4ca5SDavid du Colombier continue;
13859cc4ca5SDavid du Colombier r2 = r->s1;
13959cc4ca5SDavid du Colombier if(r2 == R)
14059cc4ca5SDavid du Colombier continue;
14159cc4ca5SDavid du Colombier t = r2->prog->as;
14259cc4ca5SDavid du Colombier switch(t) {
14359cc4ca5SDavid du Colombier default:
14459cc4ca5SDavid du Colombier continue;
14559cc4ca5SDavid du Colombier case ABEQ:
14659cc4ca5SDavid du Colombier case ABNE:
14759cc4ca5SDavid du Colombier case ABMI:
14859cc4ca5SDavid du Colombier case ABPL:
14959cc4ca5SDavid du Colombier break;
15059cc4ca5SDavid du Colombier case ABGE:
15159cc4ca5SDavid du Colombier t = ABPL;
15259cc4ca5SDavid du Colombier break;
15359cc4ca5SDavid du Colombier case ABLT:
15459cc4ca5SDavid du Colombier t = ABMI;
15559cc4ca5SDavid du Colombier break;
15659cc4ca5SDavid du Colombier case ABHI:
15759cc4ca5SDavid du Colombier t = ABNE;
15859cc4ca5SDavid du Colombier break;
15959cc4ca5SDavid du Colombier case ABLS:
16059cc4ca5SDavid du Colombier t = ABEQ;
16159cc4ca5SDavid du Colombier break;
16259cc4ca5SDavid du Colombier }
16359cc4ca5SDavid du Colombier r1 = r;
16459cc4ca5SDavid du Colombier do
16559cc4ca5SDavid du Colombier r1 = uniqp(r1);
16659cc4ca5SDavid du Colombier while (r1 != R && r1->prog->as == ANOP);
16759cc4ca5SDavid du Colombier if(r1 == R)
16859cc4ca5SDavid du Colombier continue;
16959cc4ca5SDavid du Colombier p1 = r1->prog;
17059cc4ca5SDavid du Colombier if(p1->to.type != D_REG)
17159cc4ca5SDavid du Colombier continue;
17259cc4ca5SDavid du Colombier if(p1->to.reg != p->reg)
17359cc4ca5SDavid du Colombier if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
17459cc4ca5SDavid du Colombier continue;
17559cc4ca5SDavid du Colombier switch(p1->as) {
17659cc4ca5SDavid du Colombier default:
17759cc4ca5SDavid du Colombier continue;
17859cc4ca5SDavid du Colombier case AMOVW:
17959cc4ca5SDavid du Colombier if(p1->from.type != D_REG)
18059cc4ca5SDavid du Colombier continue;
18159cc4ca5SDavid du Colombier case AAND:
18259cc4ca5SDavid du Colombier case AEOR:
18359cc4ca5SDavid du Colombier case AORR:
18459cc4ca5SDavid du Colombier case ABIC:
18559cc4ca5SDavid du Colombier case AMVN:
18659cc4ca5SDavid du Colombier case ASUB:
18759cc4ca5SDavid du Colombier case ARSB:
18859cc4ca5SDavid du Colombier case AADD:
18959cc4ca5SDavid du Colombier case AADC:
19059cc4ca5SDavid du Colombier case ASBC:
19159cc4ca5SDavid du Colombier case ARSC:
19259cc4ca5SDavid du Colombier break;
19359cc4ca5SDavid du Colombier }
19459cc4ca5SDavid du Colombier p1->scond |= C_SBIT;
19559cc4ca5SDavid du Colombier r2->prog->as = t;
19659cc4ca5SDavid du Colombier excise(r);
19759cc4ca5SDavid du Colombier continue;
19859cc4ca5SDavid du Colombier }
19959cc4ca5SDavid du Colombier }
20059cc4ca5SDavid du Colombier
2017dd7cddfSDavid du Colombier predicate();
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier void
excise(Reg * r)2057dd7cddfSDavid du Colombier excise(Reg *r)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier Prog *p;
2087dd7cddfSDavid du Colombier
2097dd7cddfSDavid du Colombier p = r->prog;
2107dd7cddfSDavid du Colombier p->as = ANOP;
21159cc4ca5SDavid du Colombier p->scond = zprog.scond;
2127dd7cddfSDavid du Colombier p->from = zprog.from;
2137dd7cddfSDavid du Colombier p->to = zprog.to;
2147dd7cddfSDavid du Colombier p->reg = zprog.reg; /**/
2157dd7cddfSDavid du Colombier }
2167dd7cddfSDavid du Colombier
2177dd7cddfSDavid du Colombier Reg*
uniqp(Reg * r)2187dd7cddfSDavid du Colombier uniqp(Reg *r)
2197dd7cddfSDavid du Colombier {
2207dd7cddfSDavid du Colombier Reg *r1;
2217dd7cddfSDavid du Colombier
2227dd7cddfSDavid du Colombier r1 = r->p1;
2237dd7cddfSDavid du Colombier if(r1 == R) {
2247dd7cddfSDavid du Colombier r1 = r->p2;
2257dd7cddfSDavid du Colombier if(r1 == R || r1->p2link != R)
2267dd7cddfSDavid du Colombier return R;
2277dd7cddfSDavid du Colombier } else
2287dd7cddfSDavid du Colombier if(r->p2 != R)
2297dd7cddfSDavid du Colombier return R;
2307dd7cddfSDavid du Colombier return r1;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier Reg*
uniqs(Reg * r)2347dd7cddfSDavid du Colombier uniqs(Reg *r)
2357dd7cddfSDavid du Colombier {
2367dd7cddfSDavid du Colombier Reg *r1;
2377dd7cddfSDavid du Colombier
2387dd7cddfSDavid du Colombier r1 = r->s1;
2397dd7cddfSDavid du Colombier if(r1 == R) {
2407dd7cddfSDavid du Colombier r1 = r->s2;
2417dd7cddfSDavid du Colombier if(r1 == R)
2427dd7cddfSDavid du Colombier return R;
2437dd7cddfSDavid du Colombier } else
2447dd7cddfSDavid du Colombier if(r->s2 != R)
2457dd7cddfSDavid du Colombier return R;
2467dd7cddfSDavid du Colombier return r1;
2477dd7cddfSDavid du Colombier }
2487dd7cddfSDavid du Colombier
2497dd7cddfSDavid du Colombier int
regtyp(Adr * a)2507dd7cddfSDavid du Colombier regtyp(Adr *a)
2517dd7cddfSDavid du Colombier {
2527dd7cddfSDavid du Colombier
2537dd7cddfSDavid du Colombier if(a->type == D_REG)
2547dd7cddfSDavid du Colombier return 1;
2557dd7cddfSDavid du Colombier if(a->type == D_FREG)
2567dd7cddfSDavid du Colombier return 1;
2577dd7cddfSDavid du Colombier return 0;
2587dd7cddfSDavid du Colombier }
2597dd7cddfSDavid du Colombier
2607dd7cddfSDavid du Colombier /*
2617dd7cddfSDavid du Colombier * the idea is to substitute
2627dd7cddfSDavid du Colombier * one register for another
2637dd7cddfSDavid du Colombier * from one MOV to another
2647dd7cddfSDavid du Colombier * MOV a, R0
2657dd7cddfSDavid du Colombier * ADD b, R0 / no use of R1
2667dd7cddfSDavid du Colombier * MOV R0, R1
2677dd7cddfSDavid du Colombier * would be converted to
2687dd7cddfSDavid du Colombier * MOV a, R1
2697dd7cddfSDavid du Colombier * ADD b, R1
2707dd7cddfSDavid du Colombier * MOV R1, R0
2717dd7cddfSDavid du Colombier * hopefully, then the former or latter MOV
2727dd7cddfSDavid du Colombier * will be eliminated by copy propagation.
2737dd7cddfSDavid du Colombier */
2747dd7cddfSDavid du Colombier int
subprop(Reg * r0)2757dd7cddfSDavid du Colombier subprop(Reg *r0)
2767dd7cddfSDavid du Colombier {
2777dd7cddfSDavid du Colombier Prog *p;
2787dd7cddfSDavid du Colombier Adr *v1, *v2;
2797dd7cddfSDavid du Colombier Reg *r;
2807dd7cddfSDavid du Colombier int t;
2817dd7cddfSDavid du Colombier
2827dd7cddfSDavid du Colombier p = r0->prog;
2837dd7cddfSDavid du Colombier v1 = &p->from;
2847dd7cddfSDavid du Colombier if(!regtyp(v1))
2857dd7cddfSDavid du Colombier return 0;
2867dd7cddfSDavid du Colombier v2 = &p->to;
2877dd7cddfSDavid du Colombier if(!regtyp(v2))
2887dd7cddfSDavid du Colombier return 0;
2897dd7cddfSDavid du Colombier for(r=uniqp(r0); r!=R; r=uniqp(r)) {
2907dd7cddfSDavid du Colombier if(uniqs(r) == R)
2917dd7cddfSDavid du Colombier break;
2927dd7cddfSDavid du Colombier p = r->prog;
2937dd7cddfSDavid du Colombier switch(p->as) {
2947dd7cddfSDavid du Colombier case ABL:
2957dd7cddfSDavid du Colombier return 0;
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier case ACMP:
29859cc4ca5SDavid du Colombier case ACMN:
2997dd7cddfSDavid du Colombier case AADD:
3007dd7cddfSDavid du Colombier case ASUB:
3017dd7cddfSDavid du Colombier case ARSB:
3027dd7cddfSDavid du Colombier case ASLL:
3037dd7cddfSDavid du Colombier case ASRL:
3047dd7cddfSDavid du Colombier case ASRA:
3057dd7cddfSDavid du Colombier case AORR:
3067dd7cddfSDavid du Colombier case AAND:
3077dd7cddfSDavid du Colombier case AEOR:
3087dd7cddfSDavid du Colombier case AMUL:
309*40d01547SDavid du Colombier case AMULU:
3107dd7cddfSDavid du Colombier case ADIV:
3117dd7cddfSDavid du Colombier case ADIVU:
3127dd7cddfSDavid du Colombier
3137dd7cddfSDavid du Colombier case ACMPF:
3147dd7cddfSDavid du Colombier case ACMPD:
3157dd7cddfSDavid du Colombier case AADDD:
3167dd7cddfSDavid du Colombier case AADDF:
3177dd7cddfSDavid du Colombier case ASUBD:
3187dd7cddfSDavid du Colombier case ASUBF:
3197dd7cddfSDavid du Colombier case AMULD:
3207dd7cddfSDavid du Colombier case AMULF:
3217dd7cddfSDavid du Colombier case ADIVD:
3227dd7cddfSDavid du Colombier case ADIVF:
3237dd7cddfSDavid du Colombier if(p->to.type == v1->type)
3247dd7cddfSDavid du Colombier if(p->to.reg == v1->reg) {
3257dd7cddfSDavid du Colombier if(p->reg == NREG)
3267dd7cddfSDavid du Colombier p->reg = p->to.reg;
3277dd7cddfSDavid du Colombier goto gotit;
3287dd7cddfSDavid du Colombier }
3297dd7cddfSDavid du Colombier break;
3307dd7cddfSDavid du Colombier
3317dd7cddfSDavid du Colombier case AMOVF:
3327dd7cddfSDavid du Colombier case AMOVD:
3337dd7cddfSDavid du Colombier case AMOVW:
3347dd7cddfSDavid du Colombier if(p->to.type == v1->type)
3357dd7cddfSDavid du Colombier if(p->to.reg == v1->reg)
3367dd7cddfSDavid du Colombier goto gotit;
3377dd7cddfSDavid du Colombier break;
33859cc4ca5SDavid du Colombier
33959cc4ca5SDavid du Colombier case AMOVM:
34059cc4ca5SDavid du Colombier t = 1<<v2->reg;
34159cc4ca5SDavid du Colombier if((p->from.type == D_CONST && (p->from.offset&t)) ||
34259cc4ca5SDavid du Colombier (p->to.type == D_CONST && (p->to.offset&t)))
34359cc4ca5SDavid du Colombier return 0;
34459cc4ca5SDavid du Colombier break;
3457dd7cddfSDavid du Colombier }
3467dd7cddfSDavid du Colombier if(copyau(&p->from, v2) ||
3477dd7cddfSDavid du Colombier copyau1(p, v2) ||
3487dd7cddfSDavid du Colombier copyau(&p->to, v2))
3497dd7cddfSDavid du Colombier break;
3507dd7cddfSDavid du Colombier if(copysub(&p->from, v1, v2, 0) ||
3517dd7cddfSDavid du Colombier copysub1(p, v1, v2, 0) ||
3527dd7cddfSDavid du Colombier copysub(&p->to, v1, v2, 0))
3537dd7cddfSDavid du Colombier break;
3547dd7cddfSDavid du Colombier }
3557dd7cddfSDavid du Colombier return 0;
3567dd7cddfSDavid du Colombier
3577dd7cddfSDavid du Colombier gotit:
3587dd7cddfSDavid du Colombier copysub(&p->to, v1, v2, 1);
3597dd7cddfSDavid du Colombier if(debug['P']) {
3607dd7cddfSDavid du Colombier print("gotit: %D->%D\n%P", v1, v2, r->prog);
3617dd7cddfSDavid du Colombier if(p->from.type == v2->type)
3627dd7cddfSDavid du Colombier print(" excise");
3637dd7cddfSDavid du Colombier print("\n");
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier for(r=uniqs(r); r!=r0; r=uniqs(r)) {
3667dd7cddfSDavid du Colombier p = r->prog;
3677dd7cddfSDavid du Colombier copysub(&p->from, v1, v2, 1);
3687dd7cddfSDavid du Colombier copysub1(p, v1, v2, 1);
3697dd7cddfSDavid du Colombier copysub(&p->to, v1, v2, 1);
3707dd7cddfSDavid du Colombier if(debug['P'])
3717dd7cddfSDavid du Colombier print("%P\n", r->prog);
3727dd7cddfSDavid du Colombier }
3737dd7cddfSDavid du Colombier t = v1->reg;
3747dd7cddfSDavid du Colombier v1->reg = v2->reg;
3757dd7cddfSDavid du Colombier v2->reg = t;
3767dd7cddfSDavid du Colombier if(debug['P'])
3777dd7cddfSDavid du Colombier print("%P last\n", r->prog);
3787dd7cddfSDavid du Colombier return 1;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier
3817dd7cddfSDavid du Colombier /*
3827dd7cddfSDavid du Colombier * The idea is to remove redundant copies.
3837dd7cddfSDavid du Colombier * v1->v2 F=0
3847dd7cddfSDavid du Colombier * (use v2 s/v2/v1/)*
3857dd7cddfSDavid du Colombier * set v1 F=1
3867dd7cddfSDavid du Colombier * use v2 return fail
3877dd7cddfSDavid du Colombier * -----------------
3887dd7cddfSDavid du Colombier * v1->v2 F=0
3897dd7cddfSDavid du Colombier * (use v2 s/v2/v1/)*
3907dd7cddfSDavid du Colombier * set v1 F=1
3917dd7cddfSDavid du Colombier * set v2 return success
3927dd7cddfSDavid du Colombier */
3937dd7cddfSDavid du Colombier int
copyprop(Reg * r0)3947dd7cddfSDavid du Colombier copyprop(Reg *r0)
3957dd7cddfSDavid du Colombier {
3967dd7cddfSDavid du Colombier Prog *p;
3977dd7cddfSDavid du Colombier Adr *v1, *v2;
3987dd7cddfSDavid du Colombier Reg *r;
3997dd7cddfSDavid du Colombier
4007dd7cddfSDavid du Colombier p = r0->prog;
4017dd7cddfSDavid du Colombier v1 = &p->from;
4027dd7cddfSDavid du Colombier v2 = &p->to;
4037dd7cddfSDavid du Colombier if(copyas(v1, v2))
4047dd7cddfSDavid du Colombier return 1;
4057dd7cddfSDavid du Colombier for(r=firstr; r!=R; r=r->link)
4067dd7cddfSDavid du Colombier r->active = 0;
4077dd7cddfSDavid du Colombier return copy1(v1, v2, r0->s1, 0);
4087dd7cddfSDavid du Colombier }
4097dd7cddfSDavid du Colombier
4107dd7cddfSDavid du Colombier int
copy1(Adr * v1,Adr * v2,Reg * r,int f)4117dd7cddfSDavid du Colombier copy1(Adr *v1, Adr *v2, Reg *r, int f)
4127dd7cddfSDavid du Colombier {
4137dd7cddfSDavid du Colombier int t;
4147dd7cddfSDavid du Colombier Prog *p;
4157dd7cddfSDavid du Colombier
4167dd7cddfSDavid du Colombier if(r->active) {
4177dd7cddfSDavid du Colombier if(debug['P'])
4187dd7cddfSDavid du Colombier print("act set; return 1\n");
4197dd7cddfSDavid du Colombier return 1;
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier r->active = 1;
4227dd7cddfSDavid du Colombier if(debug['P'])
4237dd7cddfSDavid du Colombier print("copy %D->%D f=%d\n", v1, v2, f);
4247dd7cddfSDavid du Colombier for(; r != R; r = r->s1) {
4257dd7cddfSDavid du Colombier p = r->prog;
4267dd7cddfSDavid du Colombier if(debug['P'])
4277dd7cddfSDavid du Colombier print("%P", p);
4287dd7cddfSDavid du Colombier if(!f && uniqp(r) == R) {
4297dd7cddfSDavid du Colombier f = 1;
4307dd7cddfSDavid du Colombier if(debug['P'])
4317dd7cddfSDavid du Colombier print("; merge; f=%d", f);
4327dd7cddfSDavid du Colombier }
4337dd7cddfSDavid du Colombier t = copyu(p, v2, A);
4347dd7cddfSDavid du Colombier switch(t) {
4357dd7cddfSDavid du Colombier case 2: /* rar, cant split */
4367dd7cddfSDavid du Colombier if(debug['P'])
4377dd7cddfSDavid du Colombier print("; %Drar; return 0\n", v2);
4387dd7cddfSDavid du Colombier return 0;
4397dd7cddfSDavid du Colombier
4407dd7cddfSDavid du Colombier case 3: /* set */
4417dd7cddfSDavid du Colombier if(debug['P'])
4427dd7cddfSDavid du Colombier print("; %Dset; return 1\n", v2);
4437dd7cddfSDavid du Colombier return 1;
4447dd7cddfSDavid du Colombier
4457dd7cddfSDavid du Colombier case 1: /* used, substitute */
4467dd7cddfSDavid du Colombier case 4: /* use and set */
4477dd7cddfSDavid du Colombier if(f) {
4487dd7cddfSDavid du Colombier if(!debug['P'])
4497dd7cddfSDavid du Colombier return 0;
4507dd7cddfSDavid du Colombier if(t == 4)
4517dd7cddfSDavid du Colombier print("; %Dused+set and f=%d; return 0\n", v2, f);
4527dd7cddfSDavid du Colombier else
4537dd7cddfSDavid du Colombier print("; %Dused and f=%d; return 0\n", v2, f);
4547dd7cddfSDavid du Colombier return 0;
4557dd7cddfSDavid du Colombier }
4567dd7cddfSDavid du Colombier if(copyu(p, v2, v1)) {
4577dd7cddfSDavid du Colombier if(debug['P'])
4587dd7cddfSDavid du Colombier print("; sub fail; return 0\n");
4597dd7cddfSDavid du Colombier return 0;
4607dd7cddfSDavid du Colombier }
4617dd7cddfSDavid du Colombier if(debug['P'])
4627dd7cddfSDavid du Colombier print("; sub%D/%D", v2, v1);
4637dd7cddfSDavid du Colombier if(t == 4) {
4647dd7cddfSDavid du Colombier if(debug['P'])
4657dd7cddfSDavid du Colombier print("; %Dused+set; return 1\n", v2);
4667dd7cddfSDavid du Colombier return 1;
4677dd7cddfSDavid du Colombier }
4687dd7cddfSDavid du Colombier break;
4697dd7cddfSDavid du Colombier }
4707dd7cddfSDavid du Colombier if(!f) {
4717dd7cddfSDavid du Colombier t = copyu(p, v1, A);
4727dd7cddfSDavid du Colombier if(!f && (t == 2 || t == 3 || t == 4)) {
4737dd7cddfSDavid du Colombier f = 1;
4747dd7cddfSDavid du Colombier if(debug['P'])
4757dd7cddfSDavid du Colombier print("; %Dset and !f; f=%d", v1, f);
4767dd7cddfSDavid du Colombier }
4777dd7cddfSDavid du Colombier }
4787dd7cddfSDavid du Colombier if(debug['P'])
4797dd7cddfSDavid du Colombier print("\n");
4807dd7cddfSDavid du Colombier if(r->s2)
4817dd7cddfSDavid du Colombier if(!copy1(v1, v2, r->s2, f))
4827dd7cddfSDavid du Colombier return 0;
4837dd7cddfSDavid du Colombier }
4847dd7cddfSDavid du Colombier return 1;
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier
4877dd7cddfSDavid du Colombier /*
48859cc4ca5SDavid du Colombier * The idea is to remove redundant constants.
48959cc4ca5SDavid du Colombier * $c1->v1
49059cc4ca5SDavid du Colombier * ($c1->v2 s/$c1/v1)*
49159cc4ca5SDavid du Colombier * set v1 return
49259cc4ca5SDavid du Colombier * The v1->v2 should be eliminated by copy propagation.
49359cc4ca5SDavid du Colombier */
49459cc4ca5SDavid du Colombier void
constprop(Adr * c1,Adr * v1,Reg * r)49559cc4ca5SDavid du Colombier constprop(Adr *c1, Adr *v1, Reg *r)
49659cc4ca5SDavid du Colombier {
49759cc4ca5SDavid du Colombier Prog *p;
49859cc4ca5SDavid du Colombier
49959cc4ca5SDavid du Colombier if(debug['C'])
50059cc4ca5SDavid du Colombier print("constprop %D->%D\n", c1, v1);
50159cc4ca5SDavid du Colombier for(; r != R; r = r->s1) {
50259cc4ca5SDavid du Colombier p = r->prog;
50359cc4ca5SDavid du Colombier if(debug['C'])
50459cc4ca5SDavid du Colombier print("%P", p);
50559cc4ca5SDavid du Colombier if(uniqp(r) == R) {
50659cc4ca5SDavid du Colombier if(debug['C'])
50759cc4ca5SDavid du Colombier print("; merge; return\n");
50859cc4ca5SDavid du Colombier return;
50959cc4ca5SDavid du Colombier }
51059cc4ca5SDavid du Colombier if(p->as == AMOVW && copyas(&p->from, c1)) {
51159cc4ca5SDavid du Colombier if(debug['C'])
51259cc4ca5SDavid du Colombier print("; sub%D/%D", &p->from, v1);
51359cc4ca5SDavid du Colombier p->from = *v1;
51459cc4ca5SDavid du Colombier } else if(copyu(p, v1, A) > 1) {
51559cc4ca5SDavid du Colombier if(debug['C'])
51659cc4ca5SDavid du Colombier print("; %Dset; return\n", v1);
51759cc4ca5SDavid du Colombier return;
51859cc4ca5SDavid du Colombier }
51959cc4ca5SDavid du Colombier if(debug['C'])
52059cc4ca5SDavid du Colombier print("\n");
52159cc4ca5SDavid du Colombier if(r->s2)
52259cc4ca5SDavid du Colombier constprop(c1, v1, r->s2);
52359cc4ca5SDavid du Colombier }
52459cc4ca5SDavid du Colombier }
52559cc4ca5SDavid du Colombier
52659cc4ca5SDavid du Colombier /*
52759cc4ca5SDavid du Colombier * ASLL x,y,w
52859cc4ca5SDavid du Colombier * .. (not use w, not set x y w)
52959cc4ca5SDavid du Colombier * AXXX w,a,b (a != w)
53059cc4ca5SDavid du Colombier * .. (not use w)
53159cc4ca5SDavid du Colombier * (set w)
53259cc4ca5SDavid du Colombier * ----------- changed to
53359cc4ca5SDavid du Colombier * ..
53459cc4ca5SDavid du Colombier * AXXX (x<<y),a,b
53559cc4ca5SDavid du Colombier * ..
53659cc4ca5SDavid du Colombier */
53759cc4ca5SDavid du Colombier #define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
53859cc4ca5SDavid du Colombier int
shiftprop(Reg * r)53959cc4ca5SDavid du Colombier shiftprop(Reg *r)
54059cc4ca5SDavid du Colombier {
54159cc4ca5SDavid du Colombier Reg *r1;
54259cc4ca5SDavid du Colombier Prog *p, *p1, *p2;
54359cc4ca5SDavid du Colombier int n, o;
54459cc4ca5SDavid du Colombier Adr a;
54559cc4ca5SDavid du Colombier
54659cc4ca5SDavid du Colombier p = r->prog;
54759cc4ca5SDavid du Colombier if(p->to.type != D_REG)
54859cc4ca5SDavid du Colombier FAIL("BOTCH: result not reg");
54959cc4ca5SDavid du Colombier n = p->to.reg;
55059cc4ca5SDavid du Colombier a = zprog.from;
55159cc4ca5SDavid du Colombier if(p->reg != NREG && p->reg != p->to.reg) {
55259cc4ca5SDavid du Colombier a.type = D_REG;
55359cc4ca5SDavid du Colombier a.reg = p->reg;
55459cc4ca5SDavid du Colombier }
55559cc4ca5SDavid du Colombier if(debug['H'])
55659cc4ca5SDavid du Colombier print("shiftprop\n%P", p);
55759cc4ca5SDavid du Colombier r1 = r;
55859cc4ca5SDavid du Colombier for(;;) {
55959cc4ca5SDavid du Colombier /* find first use of shift result; abort if shift operands or result are changed */
56059cc4ca5SDavid du Colombier r1 = uniqs(r1);
56159cc4ca5SDavid du Colombier if(r1 == R)
56259cc4ca5SDavid du Colombier FAIL("branch");
56359cc4ca5SDavid du Colombier if(uniqp(r1) == R)
56459cc4ca5SDavid du Colombier FAIL("merge");
56559cc4ca5SDavid du Colombier p1 = r1->prog;
56659cc4ca5SDavid du Colombier if(debug['H'])
56759cc4ca5SDavid du Colombier print("\n%P", p1);
56859cc4ca5SDavid du Colombier switch(copyu(p1, &p->to, A)) {
56959cc4ca5SDavid du Colombier case 0: /* not used or set */
57059cc4ca5SDavid du Colombier if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
57159cc4ca5SDavid du Colombier (a.type == D_REG && copyu(p1, &a, A) > 1))
57259cc4ca5SDavid du Colombier FAIL("args modified");
57359cc4ca5SDavid du Colombier continue;
57459cc4ca5SDavid du Colombier case 3: /* set, not used */
57559cc4ca5SDavid du Colombier FAIL("BOTCH: noref");
57659cc4ca5SDavid du Colombier }
57759cc4ca5SDavid du Colombier break;
57859cc4ca5SDavid du Colombier }
57959cc4ca5SDavid du Colombier /* check whether substitution can be done */
58059cc4ca5SDavid du Colombier switch(p1->as) {
58159cc4ca5SDavid du Colombier default:
58259cc4ca5SDavid du Colombier FAIL("non-dpi");
58359cc4ca5SDavid du Colombier case AAND:
58459cc4ca5SDavid du Colombier case AEOR:
58559cc4ca5SDavid du Colombier case AADD:
58659cc4ca5SDavid du Colombier case AADC:
58759cc4ca5SDavid du Colombier case AORR:
58859cc4ca5SDavid du Colombier case ASUB:
58959cc4ca5SDavid du Colombier case ARSB:
59059cc4ca5SDavid du Colombier case ASBC:
59159cc4ca5SDavid du Colombier case ARSC:
59259cc4ca5SDavid du Colombier if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
59359cc4ca5SDavid du Colombier if(p1->from.type != D_REG)
59459cc4ca5SDavid du Colombier FAIL("can't swap");
59559cc4ca5SDavid du Colombier p1->reg = p1->from.reg;
59659cc4ca5SDavid du Colombier p1->from.reg = n;
59759cc4ca5SDavid du Colombier switch(p1->as) {
59859cc4ca5SDavid du Colombier case ASUB:
59959cc4ca5SDavid du Colombier p1->as = ARSB;
60059cc4ca5SDavid du Colombier break;
60159cc4ca5SDavid du Colombier case ARSB:
60259cc4ca5SDavid du Colombier p1->as = ASUB;
60359cc4ca5SDavid du Colombier break;
60459cc4ca5SDavid du Colombier case ASBC:
60559cc4ca5SDavid du Colombier p1->as = ARSC;
60659cc4ca5SDavid du Colombier break;
60759cc4ca5SDavid du Colombier case ARSC:
60859cc4ca5SDavid du Colombier p1->as = ASBC;
60959cc4ca5SDavid du Colombier break;
61059cc4ca5SDavid du Colombier }
61159cc4ca5SDavid du Colombier if(debug['H'])
61259cc4ca5SDavid du Colombier print("\t=>%P", p1);
61359cc4ca5SDavid du Colombier }
61459cc4ca5SDavid du Colombier case ABIC:
61559cc4ca5SDavid du Colombier case ACMP:
61659cc4ca5SDavid du Colombier case ACMN:
61759cc4ca5SDavid du Colombier if(p1->reg == n)
61859cc4ca5SDavid du Colombier FAIL("can't swap");
61959cc4ca5SDavid du Colombier if(p1->reg == NREG && p1->to.reg == n)
62059cc4ca5SDavid du Colombier FAIL("shift result used twice");
62159cc4ca5SDavid du Colombier case AMVN:
62259cc4ca5SDavid du Colombier if(p1->from.type == D_SHIFT)
62359cc4ca5SDavid du Colombier FAIL("shift result used in shift");
62459cc4ca5SDavid du Colombier if(p1->from.type != D_REG || p1->from.reg != n)
62559cc4ca5SDavid du Colombier FAIL("BOTCH: where is it used?");
62659cc4ca5SDavid du Colombier break;
62759cc4ca5SDavid du Colombier }
62859cc4ca5SDavid du Colombier /* check whether shift result is used subsequently */
62959cc4ca5SDavid du Colombier p2 = p1;
63059cc4ca5SDavid du Colombier if(p1->to.reg != n)
63159cc4ca5SDavid du Colombier for (;;) {
63259cc4ca5SDavid du Colombier r1 = uniqs(r1);
63359cc4ca5SDavid du Colombier if(r1 == R)
63459cc4ca5SDavid du Colombier FAIL("inconclusive");
63559cc4ca5SDavid du Colombier p1 = r1->prog;
63659cc4ca5SDavid du Colombier if(debug['H'])
63759cc4ca5SDavid du Colombier print("\n%P", p1);
63859cc4ca5SDavid du Colombier switch(copyu(p1, &p->to, A)) {
63959cc4ca5SDavid du Colombier case 0: /* not used or set */
64059cc4ca5SDavid du Colombier continue;
64159cc4ca5SDavid du Colombier case 3: /* set, not used */
64259cc4ca5SDavid du Colombier break;
64359cc4ca5SDavid du Colombier default:/* used */
64459cc4ca5SDavid du Colombier FAIL("reused");
64559cc4ca5SDavid du Colombier }
64659cc4ca5SDavid du Colombier break;
64759cc4ca5SDavid du Colombier }
64859cc4ca5SDavid du Colombier /* make the substitution */
64959cc4ca5SDavid du Colombier p2->from.type = D_SHIFT;
65059cc4ca5SDavid du Colombier p2->from.reg = NREG;
65159cc4ca5SDavid du Colombier o = p->reg;
65259cc4ca5SDavid du Colombier if(o == NREG)
65359cc4ca5SDavid du Colombier o = p->to.reg;
65459cc4ca5SDavid du Colombier switch(p->from.type){
65559cc4ca5SDavid du Colombier case D_CONST:
65659cc4ca5SDavid du Colombier o |= (p->from.offset&0x1f)<<7;
65759cc4ca5SDavid du Colombier break;
65859cc4ca5SDavid du Colombier case D_REG:
65959cc4ca5SDavid du Colombier o |= (1<<4) | (p->from.reg<<8);
66059cc4ca5SDavid du Colombier break;
66159cc4ca5SDavid du Colombier }
66259cc4ca5SDavid du Colombier switch(p->as){
66359cc4ca5SDavid du Colombier case ASLL:
66459cc4ca5SDavid du Colombier o |= 0<<5;
66559cc4ca5SDavid du Colombier break;
66659cc4ca5SDavid du Colombier case ASRL:
66759cc4ca5SDavid du Colombier o |= 1<<5;
66859cc4ca5SDavid du Colombier break;
66959cc4ca5SDavid du Colombier case ASRA:
67059cc4ca5SDavid du Colombier o |= 2<<5;
67159cc4ca5SDavid du Colombier break;
67259cc4ca5SDavid du Colombier }
67359cc4ca5SDavid du Colombier p2->from.offset = o;
67459cc4ca5SDavid du Colombier if(debug['H'])
67559cc4ca5SDavid du Colombier print("\t=>%P\tSUCCEED\n", p2);
67659cc4ca5SDavid du Colombier return 1;
67759cc4ca5SDavid du Colombier }
67859cc4ca5SDavid du Colombier
67959cc4ca5SDavid du Colombier Reg*
findpre(Reg * r,Adr * v)68059cc4ca5SDavid du Colombier findpre(Reg *r, Adr *v)
68159cc4ca5SDavid du Colombier {
68259cc4ca5SDavid du Colombier Reg *r1;
68359cc4ca5SDavid du Colombier
68459cc4ca5SDavid du Colombier for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
68559cc4ca5SDavid du Colombier if(uniqs(r1) != r)
68659cc4ca5SDavid du Colombier return R;
68759cc4ca5SDavid du Colombier switch(copyu(r1->prog, v, A)) {
68859cc4ca5SDavid du Colombier case 1: /* used */
68959cc4ca5SDavid du Colombier case 2: /* read-alter-rewrite */
69059cc4ca5SDavid du Colombier return R;
69159cc4ca5SDavid du Colombier case 3: /* set */
69259cc4ca5SDavid du Colombier case 4: /* set and used */
69359cc4ca5SDavid du Colombier return r1;
69459cc4ca5SDavid du Colombier }
69559cc4ca5SDavid du Colombier }
69659cc4ca5SDavid du Colombier return R;
69759cc4ca5SDavid du Colombier }
69859cc4ca5SDavid du Colombier
69959cc4ca5SDavid du Colombier Reg*
findinc(Reg * r,Reg * r2,Adr * v)70059cc4ca5SDavid du Colombier findinc(Reg *r, Reg *r2, Adr *v)
70159cc4ca5SDavid du Colombier {
70259cc4ca5SDavid du Colombier Reg *r1;
70359cc4ca5SDavid du Colombier Prog *p;
70459cc4ca5SDavid du Colombier
70559cc4ca5SDavid du Colombier
70659cc4ca5SDavid du Colombier for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
70759cc4ca5SDavid du Colombier if(uniqp(r1) != r)
70859cc4ca5SDavid du Colombier return R;
70959cc4ca5SDavid du Colombier switch(copyu(r1->prog, v, A)) {
71059cc4ca5SDavid du Colombier case 0: /* not touched */
71159cc4ca5SDavid du Colombier continue;
71259cc4ca5SDavid du Colombier case 4: /* set and used */
71359cc4ca5SDavid du Colombier p = r1->prog;
71459cc4ca5SDavid du Colombier if(p->as == AADD)
71559cc4ca5SDavid du Colombier if(p->from.type == D_CONST)
71659cc4ca5SDavid du Colombier if(p->from.offset > -4096 && p->from.offset < 4096)
71759cc4ca5SDavid du Colombier return r1;
71859cc4ca5SDavid du Colombier default:
71959cc4ca5SDavid du Colombier return R;
72059cc4ca5SDavid du Colombier }
72159cc4ca5SDavid du Colombier }
72259cc4ca5SDavid du Colombier return R;
72359cc4ca5SDavid du Colombier }
72459cc4ca5SDavid du Colombier
72559cc4ca5SDavid du Colombier int
nochange(Reg * r,Reg * r2,Prog * p)72659cc4ca5SDavid du Colombier nochange(Reg *r, Reg *r2, Prog *p)
72759cc4ca5SDavid du Colombier {
72859cc4ca5SDavid du Colombier Adr a[3];
72959cc4ca5SDavid du Colombier int i, n;
73059cc4ca5SDavid du Colombier
73159cc4ca5SDavid du Colombier if(r == r2)
73259cc4ca5SDavid du Colombier return 1;
73359cc4ca5SDavid du Colombier n = 0;
73459cc4ca5SDavid du Colombier if(p->reg != NREG && p->reg != p->to.reg) {
73559cc4ca5SDavid du Colombier a[n].type = D_REG;
73659cc4ca5SDavid du Colombier a[n++].reg = p->reg;
73759cc4ca5SDavid du Colombier }
73859cc4ca5SDavid du Colombier switch(p->from.type) {
73959cc4ca5SDavid du Colombier case D_SHIFT:
74059cc4ca5SDavid du Colombier a[n].type = D_REG;
74159cc4ca5SDavid du Colombier a[n++].reg = p->from.offset&0xf;
74259cc4ca5SDavid du Colombier case D_REG:
74359cc4ca5SDavid du Colombier a[n].type = D_REG;
74459cc4ca5SDavid du Colombier a[n++].reg = p->from.reg;
74559cc4ca5SDavid du Colombier }
74659cc4ca5SDavid du Colombier if(n == 0)
74759cc4ca5SDavid du Colombier return 1;
74859cc4ca5SDavid du Colombier for(; r!=R && r!=r2; r=uniqs(r)) {
74959cc4ca5SDavid du Colombier p = r->prog;
75059cc4ca5SDavid du Colombier for(i=0; i<n; i++)
75159cc4ca5SDavid du Colombier if(copyu(p, &a[i], A) > 1)
75259cc4ca5SDavid du Colombier return 0;
75359cc4ca5SDavid du Colombier }
75459cc4ca5SDavid du Colombier return 1;
75559cc4ca5SDavid du Colombier }
75659cc4ca5SDavid du Colombier
75759cc4ca5SDavid du Colombier int
findu1(Reg * r,Adr * v)75859cc4ca5SDavid du Colombier findu1(Reg *r, Adr *v)
75959cc4ca5SDavid du Colombier {
76059cc4ca5SDavid du Colombier for(; r != R; r = r->s1) {
76159cc4ca5SDavid du Colombier if(r->active)
76259cc4ca5SDavid du Colombier return 0;
76359cc4ca5SDavid du Colombier r->active = 1;
76459cc4ca5SDavid du Colombier switch(copyu(r->prog, v, A)) {
76559cc4ca5SDavid du Colombier case 1: /* used */
76659cc4ca5SDavid du Colombier case 2: /* read-alter-rewrite */
76759cc4ca5SDavid du Colombier case 4: /* set and used */
76859cc4ca5SDavid du Colombier return 1;
76959cc4ca5SDavid du Colombier case 3: /* set */
77059cc4ca5SDavid du Colombier return 0;
77159cc4ca5SDavid du Colombier }
77259cc4ca5SDavid du Colombier if(r->s2)
77359cc4ca5SDavid du Colombier if (findu1(r->s2, v))
77459cc4ca5SDavid du Colombier return 1;
77559cc4ca5SDavid du Colombier }
77659cc4ca5SDavid du Colombier return 0;
77759cc4ca5SDavid du Colombier }
77859cc4ca5SDavid du Colombier
77959cc4ca5SDavid du Colombier int
finduse(Reg * r,Adr * v)78059cc4ca5SDavid du Colombier finduse(Reg *r, Adr *v)
78159cc4ca5SDavid du Colombier {
78259cc4ca5SDavid du Colombier Reg *r1;
78359cc4ca5SDavid du Colombier
78459cc4ca5SDavid du Colombier for(r1=firstr; r1!=R; r1=r1->link)
78559cc4ca5SDavid du Colombier r1->active = 0;
78659cc4ca5SDavid du Colombier return findu1(r, v);
78759cc4ca5SDavid du Colombier }
78859cc4ca5SDavid du Colombier
78959cc4ca5SDavid du Colombier int
xtramodes(Reg * r,Adr * a)79059cc4ca5SDavid du Colombier xtramodes(Reg *r, Adr *a)
79159cc4ca5SDavid du Colombier {
79259cc4ca5SDavid du Colombier Reg *r1, *r2, *r3;
79359cc4ca5SDavid du Colombier Prog *p, *p1;
79459cc4ca5SDavid du Colombier Adr v;
79559cc4ca5SDavid du Colombier
79659cc4ca5SDavid du Colombier p = r->prog;
797375daca8SDavid du Colombier if(debug['h'] && p->as == AMOVB && p->from.type == D_OREG) /* byte load */
798375daca8SDavid du Colombier return 0;
79959cc4ca5SDavid du Colombier v = *a;
80059cc4ca5SDavid du Colombier v.type = D_REG;
80159cc4ca5SDavid du Colombier r1 = findpre(r, &v);
80259cc4ca5SDavid du Colombier if(r1 != R) {
80359cc4ca5SDavid du Colombier p1 = r1->prog;
80459cc4ca5SDavid du Colombier if(p1->to.type == D_REG && p1->to.reg == v.reg)
80559cc4ca5SDavid du Colombier switch(p1->as) {
80659cc4ca5SDavid du Colombier case AADD:
80759cc4ca5SDavid du Colombier if(p1->from.type == D_REG ||
80859cc4ca5SDavid du Colombier (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
80959cc4ca5SDavid du Colombier (p->as != AMOVB || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
81059cc4ca5SDavid du Colombier (p1->from.type == D_CONST &&
81159cc4ca5SDavid du Colombier p1->from.offset > -4096 && p1->from.offset < 4096))
81259cc4ca5SDavid du Colombier if(nochange(uniqs(r1), r, p1)) {
81359cc4ca5SDavid du Colombier if(a != &p->from || v.reg != p->to.reg)
81459cc4ca5SDavid du Colombier if (finduse(r->s1, &v)) {
81559cc4ca5SDavid du Colombier if(p1->reg == NREG || p1->reg == v.reg)
81659cc4ca5SDavid du Colombier /* pre-indexing */
81759cc4ca5SDavid du Colombier p->scond |= C_WBIT;
81859cc4ca5SDavid du Colombier else return 0;
81959cc4ca5SDavid du Colombier }
82059cc4ca5SDavid du Colombier switch (p1->from.type) {
82159cc4ca5SDavid du Colombier case D_REG:
82259cc4ca5SDavid du Colombier /* register offset */
82359cc4ca5SDavid du Colombier a->type = D_SHIFT;
82459cc4ca5SDavid du Colombier a->offset = p1->from.reg;
82559cc4ca5SDavid du Colombier break;
82659cc4ca5SDavid du Colombier case D_SHIFT:
82759cc4ca5SDavid du Colombier /* scaled register offset */
82859cc4ca5SDavid du Colombier a->type = D_SHIFT;
82959cc4ca5SDavid du Colombier case D_CONST:
83059cc4ca5SDavid du Colombier /* immediate offset */
83159cc4ca5SDavid du Colombier a->offset = p1->from.offset;
83259cc4ca5SDavid du Colombier break;
83359cc4ca5SDavid du Colombier }
83459cc4ca5SDavid du Colombier if(p1->reg != NREG)
83559cc4ca5SDavid du Colombier a->reg = p1->reg;
83659cc4ca5SDavid du Colombier excise(r1);
83759cc4ca5SDavid du Colombier return 1;
83859cc4ca5SDavid du Colombier }
83959cc4ca5SDavid du Colombier break;
84059cc4ca5SDavid du Colombier case AMOVW:
84159cc4ca5SDavid du Colombier if(p1->from.type == D_REG)
84259cc4ca5SDavid du Colombier if((r2 = findinc(r1, r, &p1->from)) != R) {
84359cc4ca5SDavid du Colombier for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
84459cc4ca5SDavid du Colombier ;
84559cc4ca5SDavid du Colombier if(r3 == r) {
84659cc4ca5SDavid du Colombier /* post-indexing */
84759cc4ca5SDavid du Colombier p1 = r2->prog;
84859cc4ca5SDavid du Colombier a->reg = p1->to.reg;
84959cc4ca5SDavid du Colombier a->offset = p1->from.offset;
85059cc4ca5SDavid du Colombier p->scond |= C_PBIT;
85159cc4ca5SDavid du Colombier if(!finduse(r, &r1->prog->to))
85259cc4ca5SDavid du Colombier excise(r1);
85359cc4ca5SDavid du Colombier excise(r2);
85459cc4ca5SDavid du Colombier return 1;
85559cc4ca5SDavid du Colombier }
85659cc4ca5SDavid du Colombier }
85759cc4ca5SDavid du Colombier break;
85859cc4ca5SDavid du Colombier }
85959cc4ca5SDavid du Colombier }
86059cc4ca5SDavid du Colombier if(a != &p->from || a->reg != p->to.reg)
86159cc4ca5SDavid du Colombier if((r1 = findinc(r, R, &v)) != R) {
86259cc4ca5SDavid du Colombier /* post-indexing */
86359cc4ca5SDavid du Colombier p1 = r1->prog;
86459cc4ca5SDavid du Colombier a->offset = p1->from.offset;
86559cc4ca5SDavid du Colombier p->scond |= C_PBIT;
86659cc4ca5SDavid du Colombier excise(r1);
86759cc4ca5SDavid du Colombier return 1;
86859cc4ca5SDavid du Colombier }
86959cc4ca5SDavid du Colombier return 0;
87059cc4ca5SDavid du Colombier }
87159cc4ca5SDavid du Colombier
87259cc4ca5SDavid du Colombier /*
8737dd7cddfSDavid du Colombier * return
8747dd7cddfSDavid du Colombier * 1 if v only used (and substitute),
8757dd7cddfSDavid du Colombier * 2 if read-alter-rewrite
8767dd7cddfSDavid du Colombier * 3 if set
8777dd7cddfSDavid du Colombier * 4 if set and used
8787dd7cddfSDavid du Colombier * 0 otherwise (not touched)
8797dd7cddfSDavid du Colombier */
8807dd7cddfSDavid du Colombier int
copyu(Prog * p,Adr * v,Adr * s)8817dd7cddfSDavid du Colombier copyu(Prog *p, Adr *v, Adr *s)
8827dd7cddfSDavid du Colombier {
8837dd7cddfSDavid du Colombier
8847dd7cddfSDavid du Colombier switch(p->as) {
8857dd7cddfSDavid du Colombier
8867dd7cddfSDavid du Colombier default:
8877dd7cddfSDavid du Colombier if(debug['P'])
8887dd7cddfSDavid du Colombier print(" (???)");
8897dd7cddfSDavid du Colombier return 2;
8907dd7cddfSDavid du Colombier
89159cc4ca5SDavid du Colombier case AMOVM:
89259cc4ca5SDavid du Colombier if(v->type != D_REG)
89359cc4ca5SDavid du Colombier return 0;
89459cc4ca5SDavid du Colombier if(p->from.type == D_CONST) { /* read reglist, read/rar */
89559cc4ca5SDavid du Colombier if(s != A) {
89659cc4ca5SDavid du Colombier if(p->from.offset&(1<<v->reg))
89759cc4ca5SDavid du Colombier return 1;
89859cc4ca5SDavid du Colombier if(copysub(&p->to, v, s, 1))
89959cc4ca5SDavid du Colombier return 1;
90059cc4ca5SDavid du Colombier return 0;
90159cc4ca5SDavid du Colombier }
90259cc4ca5SDavid du Colombier if(copyau(&p->to, v)) {
90359cc4ca5SDavid du Colombier if(p->scond&C_WBIT)
90459cc4ca5SDavid du Colombier return 2;
90559cc4ca5SDavid du Colombier return 1;
90659cc4ca5SDavid du Colombier }
90759cc4ca5SDavid du Colombier if(p->from.offset&(1<<v->reg))
90859cc4ca5SDavid du Colombier return 1;
90959cc4ca5SDavid du Colombier } else { /* read/rar, write reglist */
91059cc4ca5SDavid du Colombier if(s != A) {
91159cc4ca5SDavid du Colombier if(p->to.offset&(1<<v->reg))
91259cc4ca5SDavid du Colombier return 1;
91359cc4ca5SDavid du Colombier if(copysub(&p->from, v, s, 1))
91459cc4ca5SDavid du Colombier return 1;
91559cc4ca5SDavid du Colombier return 0;
91659cc4ca5SDavid du Colombier }
91759cc4ca5SDavid du Colombier if(copyau(&p->from, v)) {
91859cc4ca5SDavid du Colombier if(p->scond&C_WBIT)
91959cc4ca5SDavid du Colombier return 2;
92059cc4ca5SDavid du Colombier if(p->to.offset&(1<<v->reg))
92159cc4ca5SDavid du Colombier return 4;
92259cc4ca5SDavid du Colombier return 1;
92359cc4ca5SDavid du Colombier }
92459cc4ca5SDavid du Colombier if(p->to.offset&(1<<v->reg))
92559cc4ca5SDavid du Colombier return 3;
92659cc4ca5SDavid du Colombier }
92759cc4ca5SDavid du Colombier return 0;
9287dd7cddfSDavid du Colombier
9297dd7cddfSDavid du Colombier case ANOP: /* read, write */
9307dd7cddfSDavid du Colombier case AMOVW:
9317dd7cddfSDavid du Colombier case AMOVF:
9327dd7cddfSDavid du Colombier case AMOVD:
9337dd7cddfSDavid du Colombier case AMOVH:
9347dd7cddfSDavid du Colombier case AMOVHU:
9357dd7cddfSDavid du Colombier case AMOVB:
9367dd7cddfSDavid du Colombier case AMOVBU:
9377dd7cddfSDavid du Colombier case AMOVDW:
9387dd7cddfSDavid du Colombier case AMOVWD:
9397dd7cddfSDavid du Colombier case AMOVFD:
9407dd7cddfSDavid du Colombier case AMOVDF:
94159cc4ca5SDavid du Colombier if(p->scond&(C_WBIT|C_PBIT))
94259cc4ca5SDavid du Colombier if(v->type == D_REG) {
94359cc4ca5SDavid du Colombier if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
94459cc4ca5SDavid du Colombier if(p->from.reg == v->reg)
94559cc4ca5SDavid du Colombier return 2;
94659cc4ca5SDavid du Colombier } else {
94759cc4ca5SDavid du Colombier if(p->to.reg == v->reg)
94859cc4ca5SDavid du Colombier return 2;
94959cc4ca5SDavid du Colombier }
95059cc4ca5SDavid du Colombier }
9517dd7cddfSDavid du Colombier if(s != A) {
9527dd7cddfSDavid du Colombier if(copysub(&p->from, v, s, 1))
9537dd7cddfSDavid du Colombier return 1;
9547dd7cddfSDavid du Colombier if(!copyas(&p->to, v))
9557dd7cddfSDavid du Colombier if(copysub(&p->to, v, s, 1))
9567dd7cddfSDavid du Colombier return 1;
9577dd7cddfSDavid du Colombier return 0;
9587dd7cddfSDavid du Colombier }
9597dd7cddfSDavid du Colombier if(copyas(&p->to, v)) {
9607dd7cddfSDavid du Colombier if(copyau(&p->from, v))
9617dd7cddfSDavid du Colombier return 4;
9627dd7cddfSDavid du Colombier return 3;
9637dd7cddfSDavid du Colombier }
9647dd7cddfSDavid du Colombier if(copyau(&p->from, v))
9657dd7cddfSDavid du Colombier return 1;
9667dd7cddfSDavid du Colombier if(copyau(&p->to, v))
9677dd7cddfSDavid du Colombier return 1;
9687dd7cddfSDavid du Colombier return 0;
9697dd7cddfSDavid du Colombier
9707dd7cddfSDavid du Colombier
9717dd7cddfSDavid du Colombier case AADD: /* read, read, write */
9727dd7cddfSDavid du Colombier case ASUB:
9737dd7cddfSDavid du Colombier case ARSB:
9747dd7cddfSDavid du Colombier case ASLL:
9757dd7cddfSDavid du Colombier case ASRL:
9767dd7cddfSDavid du Colombier case ASRA:
9777dd7cddfSDavid du Colombier case AORR:
9787dd7cddfSDavid du Colombier case AAND:
9797dd7cddfSDavid du Colombier case AEOR:
9807dd7cddfSDavid du Colombier case AMUL:
981*40d01547SDavid du Colombier case AMULU:
9827dd7cddfSDavid du Colombier case ADIV:
9837dd7cddfSDavid du Colombier case ADIVU:
9847dd7cddfSDavid du Colombier case AADDF:
9857dd7cddfSDavid du Colombier case AADDD:
9867dd7cddfSDavid du Colombier case ASUBF:
9877dd7cddfSDavid du Colombier case ASUBD:
9887dd7cddfSDavid du Colombier case AMULF:
9897dd7cddfSDavid du Colombier case AMULD:
9907dd7cddfSDavid du Colombier case ADIVF:
9917dd7cddfSDavid du Colombier case ADIVD:
9927dd7cddfSDavid du Colombier
9937dd7cddfSDavid du Colombier case ACMPF:
9947dd7cddfSDavid du Colombier case ACMPD:
9957dd7cddfSDavid du Colombier case ACMP:
99659cc4ca5SDavid du Colombier case ACMN:
99759cc4ca5SDavid du Colombier case ACASE:
9987dd7cddfSDavid du Colombier if(s != A) {
9997dd7cddfSDavid du Colombier if(copysub(&p->from, v, s, 1))
10007dd7cddfSDavid du Colombier return 1;
10017dd7cddfSDavid du Colombier if(copysub1(p, v, s, 1))
10027dd7cddfSDavid du Colombier return 1;
10037dd7cddfSDavid du Colombier if(!copyas(&p->to, v))
10047dd7cddfSDavid du Colombier if(copysub(&p->to, v, s, 1))
10057dd7cddfSDavid du Colombier return 1;
10067dd7cddfSDavid du Colombier return 0;
10077dd7cddfSDavid du Colombier }
10087dd7cddfSDavid du Colombier if(copyas(&p->to, v)) {
10097dd7cddfSDavid du Colombier if(p->reg == NREG)
10107dd7cddfSDavid du Colombier p->reg = p->to.reg;
10117dd7cddfSDavid du Colombier if(copyau(&p->from, v))
10127dd7cddfSDavid du Colombier return 4;
10137dd7cddfSDavid du Colombier if(copyau1(p, v))
10147dd7cddfSDavid du Colombier return 4;
10157dd7cddfSDavid du Colombier return 3;
10167dd7cddfSDavid du Colombier }
10177dd7cddfSDavid du Colombier if(copyau(&p->from, v))
10187dd7cddfSDavid du Colombier return 1;
10197dd7cddfSDavid du Colombier if(copyau1(p, v))
10207dd7cddfSDavid du Colombier return 1;
10217dd7cddfSDavid du Colombier if(copyau(&p->to, v))
10227dd7cddfSDavid du Colombier return 1;
10237dd7cddfSDavid du Colombier return 0;
10247dd7cddfSDavid du Colombier
10257dd7cddfSDavid du Colombier case ABEQ: /* read, read */
10267dd7cddfSDavid du Colombier case ABNE:
10277dd7cddfSDavid du Colombier case ABCS:
10287dd7cddfSDavid du Colombier case ABHS:
10297dd7cddfSDavid du Colombier case ABCC:
10307dd7cddfSDavid du Colombier case ABLO:
10317dd7cddfSDavid du Colombier case ABMI:
10327dd7cddfSDavid du Colombier case ABPL:
10337dd7cddfSDavid du Colombier case ABVS:
10347dd7cddfSDavid du Colombier case ABVC:
10357dd7cddfSDavid du Colombier case ABHI:
10367dd7cddfSDavid du Colombier case ABLS:
10377dd7cddfSDavid du Colombier case ABGE:
10387dd7cddfSDavid du Colombier case ABLT:
10397dd7cddfSDavid du Colombier case ABGT:
10407dd7cddfSDavid du Colombier case ABLE:
10417dd7cddfSDavid du Colombier if(s != A) {
10427dd7cddfSDavid du Colombier if(copysub(&p->from, v, s, 1))
10437dd7cddfSDavid du Colombier return 1;
10447dd7cddfSDavid du Colombier return copysub1(p, v, s, 1);
10457dd7cddfSDavid du Colombier }
10467dd7cddfSDavid du Colombier if(copyau(&p->from, v))
10477dd7cddfSDavid du Colombier return 1;
10487dd7cddfSDavid du Colombier if(copyau1(p, v))
10497dd7cddfSDavid du Colombier return 1;
10507dd7cddfSDavid du Colombier return 0;
10517dd7cddfSDavid du Colombier
10527dd7cddfSDavid du Colombier case AB: /* funny */
10537dd7cddfSDavid du Colombier if(s != A) {
10547dd7cddfSDavid du Colombier if(copysub(&p->to, v, s, 1))
10557dd7cddfSDavid du Colombier return 1;
10567dd7cddfSDavid du Colombier return 0;
10577dd7cddfSDavid du Colombier }
10587dd7cddfSDavid du Colombier if(copyau(&p->to, v))
10597dd7cddfSDavid du Colombier return 1;
10607dd7cddfSDavid du Colombier return 0;
10617dd7cddfSDavid du Colombier
10627dd7cddfSDavid du Colombier case ARET: /* funny */
10637dd7cddfSDavid du Colombier if(v->type == D_REG)
10647dd7cddfSDavid du Colombier if(v->reg == REGRET)
10657dd7cddfSDavid du Colombier return 2;
10667dd7cddfSDavid du Colombier if(v->type == D_FREG)
10677dd7cddfSDavid du Colombier if(v->reg == FREGRET)
10687dd7cddfSDavid du Colombier return 2;
10697dd7cddfSDavid du Colombier
10707dd7cddfSDavid du Colombier case ABL: /* funny */
10717dd7cddfSDavid du Colombier if(v->type == D_REG) {
10727dd7cddfSDavid du Colombier if(v->reg <= REGEXT && v->reg > exregoffset)
10737dd7cddfSDavid du Colombier return 2;
107427acba7cSDavid du Colombier if(v->reg == (uchar)REGARG)
10757dd7cddfSDavid du Colombier return 2;
10767dd7cddfSDavid du Colombier }
10777dd7cddfSDavid du Colombier if(v->type == D_FREG)
10787dd7cddfSDavid du Colombier if(v->reg <= FREGEXT && v->reg > exfregoffset)
10797dd7cddfSDavid du Colombier return 2;
10807dd7cddfSDavid du Colombier
10817dd7cddfSDavid du Colombier if(s != A) {
10827dd7cddfSDavid du Colombier if(copysub(&p->to, v, s, 1))
10837dd7cddfSDavid du Colombier return 1;
10847dd7cddfSDavid du Colombier return 0;
10857dd7cddfSDavid du Colombier }
10867dd7cddfSDavid du Colombier if(copyau(&p->to, v))
10877dd7cddfSDavid du Colombier return 4;
10887dd7cddfSDavid du Colombier return 3;
10897dd7cddfSDavid du Colombier
10907dd7cddfSDavid du Colombier case ATEXT: /* funny */
10917dd7cddfSDavid du Colombier if(v->type == D_REG)
109227acba7cSDavid du Colombier if(v->reg == (uchar)REGARG)
10937dd7cddfSDavid du Colombier return 3;
10947dd7cddfSDavid du Colombier return 0;
10957dd7cddfSDavid du Colombier }
10967dd7cddfSDavid du Colombier }
10977dd7cddfSDavid du Colombier
10987dd7cddfSDavid du Colombier int
a2type(Prog * p)10997dd7cddfSDavid du Colombier a2type(Prog *p)
11007dd7cddfSDavid du Colombier {
11017dd7cddfSDavid du Colombier
11027dd7cddfSDavid du Colombier switch(p->as) {
11037dd7cddfSDavid du Colombier
11047dd7cddfSDavid du Colombier case ACMP:
110559cc4ca5SDavid du Colombier case ACMN:
11067dd7cddfSDavid du Colombier
11077dd7cddfSDavid du Colombier case AADD:
11087dd7cddfSDavid du Colombier case ASUB:
11097dd7cddfSDavid du Colombier case ARSB:
11107dd7cddfSDavid du Colombier case ASLL:
11117dd7cddfSDavid du Colombier case ASRL:
11127dd7cddfSDavid du Colombier case ASRA:
11137dd7cddfSDavid du Colombier case AORR:
11147dd7cddfSDavid du Colombier case AAND:
11157dd7cddfSDavid du Colombier case AEOR:
11167dd7cddfSDavid du Colombier case AMUL:
1117*40d01547SDavid du Colombier case AMULU:
11187dd7cddfSDavid du Colombier case ADIV:
11197dd7cddfSDavid du Colombier case ADIVU:
11207dd7cddfSDavid du Colombier return D_REG;
11217dd7cddfSDavid du Colombier
11227dd7cddfSDavid du Colombier case ACMPF:
11237dd7cddfSDavid du Colombier case ACMPD:
11247dd7cddfSDavid du Colombier
11257dd7cddfSDavid du Colombier case AADDF:
11267dd7cddfSDavid du Colombier case AADDD:
11277dd7cddfSDavid du Colombier case ASUBF:
11287dd7cddfSDavid du Colombier case ASUBD:
11297dd7cddfSDavid du Colombier case AMULF:
11307dd7cddfSDavid du Colombier case AMULD:
11317dd7cddfSDavid du Colombier case ADIVF:
11327dd7cddfSDavid du Colombier case ADIVD:
11337dd7cddfSDavid du Colombier return D_FREG;
11347dd7cddfSDavid du Colombier }
11357dd7cddfSDavid du Colombier return D_NONE;
11367dd7cddfSDavid du Colombier }
11377dd7cddfSDavid du Colombier
11387dd7cddfSDavid du Colombier /*
11397dd7cddfSDavid du Colombier * direct reference,
11407dd7cddfSDavid du Colombier * could be set/use depending on
11417dd7cddfSDavid du Colombier * semantics
11427dd7cddfSDavid du Colombier */
11437dd7cddfSDavid du Colombier int
copyas(Adr * a,Adr * v)11447dd7cddfSDavid du Colombier copyas(Adr *a, Adr *v)
11457dd7cddfSDavid du Colombier {
11467dd7cddfSDavid du Colombier
114759cc4ca5SDavid du Colombier if(regtyp(v)) {
11487dd7cddfSDavid du Colombier if(a->type == v->type)
11497dd7cddfSDavid du Colombier if(a->reg == v->reg)
11507dd7cddfSDavid du Colombier return 1;
115159cc4ca5SDavid du Colombier } else if(v->type == D_CONST) { /* for constprop */
115259cc4ca5SDavid du Colombier if(a->type == v->type)
115359cc4ca5SDavid du Colombier if(a->name == v->name)
115459cc4ca5SDavid du Colombier if(a->sym == v->sym)
115559cc4ca5SDavid du Colombier if(a->reg == v->reg)
115659cc4ca5SDavid du Colombier if(a->offset == v->offset)
115759cc4ca5SDavid du Colombier return 1;
115859cc4ca5SDavid du Colombier }
11597dd7cddfSDavid du Colombier return 0;
11607dd7cddfSDavid du Colombier }
11617dd7cddfSDavid du Colombier
11627dd7cddfSDavid du Colombier /*
11637dd7cddfSDavid du Colombier * either direct or indirect
11647dd7cddfSDavid du Colombier */
11657dd7cddfSDavid du Colombier int
copyau(Adr * a,Adr * v)11667dd7cddfSDavid du Colombier copyau(Adr *a, Adr *v)
11677dd7cddfSDavid du Colombier {
11687dd7cddfSDavid du Colombier
11697dd7cddfSDavid du Colombier if(copyas(a, v))
11707dd7cddfSDavid du Colombier return 1;
117159cc4ca5SDavid du Colombier if(v->type == D_REG) {
117259cc4ca5SDavid du Colombier if(a->type == D_OREG) {
11737dd7cddfSDavid du Colombier if(v->reg == a->reg)
11747dd7cddfSDavid du Colombier return 1;
117559cc4ca5SDavid du Colombier } else if(a->type == D_SHIFT) {
117659cc4ca5SDavid du Colombier if((a->offset&0xf) == v->reg)
117759cc4ca5SDavid du Colombier return 1;
117859cc4ca5SDavid du Colombier if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
117959cc4ca5SDavid du Colombier return 1;
118059cc4ca5SDavid du Colombier }
118159cc4ca5SDavid du Colombier }
11827dd7cddfSDavid du Colombier return 0;
11837dd7cddfSDavid du Colombier }
11847dd7cddfSDavid du Colombier
11857dd7cddfSDavid du Colombier int
copyau1(Prog * p,Adr * v)11867dd7cddfSDavid du Colombier copyau1(Prog *p, Adr *v)
11877dd7cddfSDavid du Colombier {
11887dd7cddfSDavid du Colombier
11897dd7cddfSDavid du Colombier if(regtyp(v)) {
11907dd7cddfSDavid du Colombier if(a2type(p) == v->type)
11917dd7cddfSDavid du Colombier if(p->reg == v->reg) {
11927dd7cddfSDavid du Colombier if(a2type(p) != v->type)
11937dd7cddfSDavid du Colombier print("botch a2type %P\n", p);
11947dd7cddfSDavid du Colombier return 1;
11957dd7cddfSDavid du Colombier }
11967dd7cddfSDavid du Colombier }
11977dd7cddfSDavid du Colombier return 0;
11987dd7cddfSDavid du Colombier }
11997dd7cddfSDavid du Colombier
12007dd7cddfSDavid du Colombier /*
12017dd7cddfSDavid du Colombier * substitute s for v in a
12027dd7cddfSDavid du Colombier * return failure to substitute
12037dd7cddfSDavid du Colombier */
12047dd7cddfSDavid du Colombier int
copysub(Adr * a,Adr * v,Adr * s,int f)12057dd7cddfSDavid du Colombier copysub(Adr *a, Adr *v, Adr *s, int f)
12067dd7cddfSDavid du Colombier {
12077dd7cddfSDavid du Colombier
12087dd7cddfSDavid du Colombier if(f)
120959cc4ca5SDavid du Colombier if(copyau(a, v)) {
121059cc4ca5SDavid du Colombier if(a->type == D_SHIFT) {
121159cc4ca5SDavid du Colombier if((a->offset&0xf) == v->reg)
121259cc4ca5SDavid du Colombier a->offset = (a->offset&~0xf)|s->reg;
121359cc4ca5SDavid du Colombier if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
121459cc4ca5SDavid du Colombier a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
121559cc4ca5SDavid du Colombier } else
12167dd7cddfSDavid du Colombier a->reg = s->reg;
121759cc4ca5SDavid du Colombier }
12187dd7cddfSDavid du Colombier return 0;
12197dd7cddfSDavid du Colombier }
12207dd7cddfSDavid du Colombier
12217dd7cddfSDavid du Colombier int
copysub1(Prog * p1,Adr * v,Adr * s,int f)12227dd7cddfSDavid du Colombier copysub1(Prog *p1, Adr *v, Adr *s, int f)
12237dd7cddfSDavid du Colombier {
12247dd7cddfSDavid du Colombier
12257dd7cddfSDavid du Colombier if(f)
12267dd7cddfSDavid du Colombier if(copyau1(p1, v))
12277dd7cddfSDavid du Colombier p1->reg = s->reg;
12287dd7cddfSDavid du Colombier return 0;
12297dd7cddfSDavid du Colombier }
12307dd7cddfSDavid du Colombier
12317dd7cddfSDavid du Colombier struct {
12327dd7cddfSDavid du Colombier int opcode;
123359cc4ca5SDavid du Colombier int notopcode;
12347dd7cddfSDavid du Colombier int scond;
12357dd7cddfSDavid du Colombier int notscond;
12367dd7cddfSDavid du Colombier } predinfo[] = {
123759cc4ca5SDavid du Colombier { ABEQ, ABNE, 0x0, 0x1, },
123859cc4ca5SDavid du Colombier { ABNE, ABEQ, 0x1, 0x0, },
123959cc4ca5SDavid du Colombier { ABCS, ABCC, 0x2, 0x3, },
124059cc4ca5SDavid du Colombier { ABHS, ABLO, 0x2, 0x3, },
124159cc4ca5SDavid du Colombier { ABCC, ABCS, 0x3, 0x2, },
124259cc4ca5SDavid du Colombier { ABLO, ABHS, 0x3, 0x2, },
124359cc4ca5SDavid du Colombier { ABMI, ABPL, 0x4, 0x5, },
124459cc4ca5SDavid du Colombier { ABPL, ABMI, 0x5, 0x4, },
124559cc4ca5SDavid du Colombier { ABVS, ABVC, 0x6, 0x7, },
124659cc4ca5SDavid du Colombier { ABVC, ABVS, 0x7, 0x6, },
124759cc4ca5SDavid du Colombier { ABHI, ABLS, 0x8, 0x9, },
124859cc4ca5SDavid du Colombier { ABLS, ABHI, 0x9, 0x8, },
124959cc4ca5SDavid du Colombier { ABGE, ABLT, 0xA, 0xB, },
125059cc4ca5SDavid du Colombier { ABLT, ABGE, 0xB, 0xA, },
125159cc4ca5SDavid du Colombier { ABGT, ABLE, 0xC, 0xD, },
125259cc4ca5SDavid du Colombier { ABLE, ABGT, 0xD, 0xC, },
12537dd7cddfSDavid du Colombier };
12547dd7cddfSDavid du Colombier
125559cc4ca5SDavid du Colombier typedef struct {
125659cc4ca5SDavid du Colombier Reg *start;
125759cc4ca5SDavid du Colombier Reg *last;
125859cc4ca5SDavid du Colombier Reg *end;
125959cc4ca5SDavid du Colombier int len;
126059cc4ca5SDavid du Colombier } Joininfo;
12617dd7cddfSDavid du Colombier
126259cc4ca5SDavid du Colombier enum {
126359cc4ca5SDavid du Colombier Join,
126459cc4ca5SDavid du Colombier Split,
126559cc4ca5SDavid du Colombier End,
126659cc4ca5SDavid du Colombier Branch,
126759cc4ca5SDavid du Colombier Setcond,
126859cc4ca5SDavid du Colombier Toolong
126959cc4ca5SDavid du Colombier };
127059cc4ca5SDavid du Colombier
127159cc4ca5SDavid du Colombier enum {
127259cc4ca5SDavid du Colombier Falsecond,
127359cc4ca5SDavid du Colombier Truecond,
127459cc4ca5SDavid du Colombier Delbranch,
127559cc4ca5SDavid du Colombier Keepbranch
127659cc4ca5SDavid du Colombier };
12777dd7cddfSDavid du Colombier
12787dd7cddfSDavid du Colombier int
isbranch(Prog * p)12797dd7cddfSDavid du Colombier isbranch(Prog *p)
12807dd7cddfSDavid du Colombier {
12817dd7cddfSDavid du Colombier return (ABEQ <= p->as) && (p->as <= ABLE);
12827dd7cddfSDavid du Colombier }
12837dd7cddfSDavid du Colombier
12847dd7cddfSDavid du Colombier int
predicable(Prog * p)12857dd7cddfSDavid du Colombier predicable(Prog *p)
12867dd7cddfSDavid du Colombier {
12877dd7cddfSDavid du Colombier if (isbranch(p)
128859cc4ca5SDavid du Colombier || p->as == ANOP
12897dd7cddfSDavid du Colombier || p->as == AXXX
12907dd7cddfSDavid du Colombier || p->as == ADATA
12917dd7cddfSDavid du Colombier || p->as == AGLOBL
12927dd7cddfSDavid du Colombier || p->as == AGOK
12937dd7cddfSDavid du Colombier || p->as == AHISTORY
12947dd7cddfSDavid du Colombier || p->as == ANAME
1295375daca8SDavid du Colombier || p->as == ASIGNAME
12967dd7cddfSDavid du Colombier || p->as == ATEXT
12977dd7cddfSDavid du Colombier || p->as == AWORD
12987dd7cddfSDavid du Colombier || p->as == ADYNT
12997dd7cddfSDavid du Colombier || p->as == AINIT
13007dd7cddfSDavid du Colombier || p->as == ABCASE
13017dd7cddfSDavid du Colombier || p->as == ACASE)
13027dd7cddfSDavid du Colombier return 0;
13037dd7cddfSDavid du Colombier return 1;
13047dd7cddfSDavid du Colombier }
13057dd7cddfSDavid du Colombier
13067dd7cddfSDavid du Colombier /*
13077dd7cddfSDavid du Colombier * Depends on an analysis of the encodings performed by 5l.
13087dd7cddfSDavid du Colombier * These seem to be all of the opcodes that lead to the "S" bit
13097dd7cddfSDavid du Colombier * being set in the instruction encodings.
13107dd7cddfSDavid du Colombier *
131159cc4ca5SDavid du Colombier * C_SBIT may also have been set explicitly in p->scond.
13127dd7cddfSDavid du Colombier */
13137dd7cddfSDavid du Colombier int
modifiescpsr(Prog * p)13147dd7cddfSDavid du Colombier modifiescpsr(Prog *p)
13157dd7cddfSDavid du Colombier {
131659cc4ca5SDavid du Colombier return (p->scond&C_SBIT)
131759cc4ca5SDavid du Colombier || p->as == ATST
13187dd7cddfSDavid du Colombier || p->as == ATEQ
13197dd7cddfSDavid du Colombier || p->as == ACMN
13207dd7cddfSDavid du Colombier || p->as == ACMP
13217dd7cddfSDavid du Colombier || p->as == AMULU
13227dd7cddfSDavid du Colombier || p->as == ADIVU
13237dd7cddfSDavid du Colombier || p->as == AMUL
13247dd7cddfSDavid du Colombier || p->as == ADIV
13257dd7cddfSDavid du Colombier || p->as == AMOD
13267dd7cddfSDavid du Colombier || p->as == AMODU
13277dd7cddfSDavid du Colombier || p->as == ABL;
13287dd7cddfSDavid du Colombier }
13297dd7cddfSDavid du Colombier
133059cc4ca5SDavid du Colombier /*
133159cc4ca5SDavid du Colombier * Find the maximal chain of instructions starting with r which could
133259cc4ca5SDavid du Colombier * be executed conditionally
133359cc4ca5SDavid du Colombier */
133459cc4ca5SDavid du Colombier int
joinsplit(Reg * r,Joininfo * j)133559cc4ca5SDavid du Colombier joinsplit(Reg *r, Joininfo *j)
13367dd7cddfSDavid du Colombier {
133759cc4ca5SDavid du Colombier j->start = r;
133859cc4ca5SDavid du Colombier j->last = r;
133959cc4ca5SDavid du Colombier j->len = 0;
134059cc4ca5SDavid du Colombier do {
134159cc4ca5SDavid du Colombier if (r->p2 && (r->p1 || r->p2->p2link)) {
134259cc4ca5SDavid du Colombier j->end = r;
134359cc4ca5SDavid du Colombier return Join;
13447dd7cddfSDavid du Colombier }
134559cc4ca5SDavid du Colombier if (r->s1 && r->s2) {
134659cc4ca5SDavid du Colombier j->end = r;
134759cc4ca5SDavid du Colombier return Split;
134859cc4ca5SDavid du Colombier }
134959cc4ca5SDavid du Colombier j->last = r;
135059cc4ca5SDavid du Colombier if (r->prog->as != ANOP)
135159cc4ca5SDavid du Colombier j->len++;
135259cc4ca5SDavid du Colombier if (!r->s1 && !r->s2) {
135359cc4ca5SDavid du Colombier j->end = r->link;
135459cc4ca5SDavid du Colombier return End;
135559cc4ca5SDavid du Colombier }
135659cc4ca5SDavid du Colombier if (r->s2) {
135759cc4ca5SDavid du Colombier j->end = r->s2;
135859cc4ca5SDavid du Colombier return Branch;
135959cc4ca5SDavid du Colombier }
136059cc4ca5SDavid du Colombier if (modifiescpsr(r->prog)) {
136159cc4ca5SDavid du Colombier j->end = r->s1;
136259cc4ca5SDavid du Colombier return Setcond;
136359cc4ca5SDavid du Colombier }
136459cc4ca5SDavid du Colombier r = r->s1;
136559cc4ca5SDavid du Colombier } while (j->len < 4);
136659cc4ca5SDavid du Colombier j->end = r;
136759cc4ca5SDavid du Colombier return Toolong;
13687dd7cddfSDavid du Colombier }
13697dd7cddfSDavid du Colombier
13707dd7cddfSDavid du Colombier Reg *
successor(Reg * r)13717dd7cddfSDavid du Colombier successor(Reg *r)
13727dd7cddfSDavid du Colombier {
13737dd7cddfSDavid du Colombier if (r->s1)
13747dd7cddfSDavid du Colombier return r->s1;
13757dd7cddfSDavid du Colombier else
13767dd7cddfSDavid du Colombier return r->s2;
13777dd7cddfSDavid du Colombier }
13787dd7cddfSDavid du Colombier
137959cc4ca5SDavid du Colombier void
applypred(Reg * rstart,Joininfo * j,int cond,int branch)138059cc4ca5SDavid du Colombier applypred(Reg *rstart, Joininfo *j, int cond, int branch)
13817dd7cddfSDavid du Colombier {
138259cc4ca5SDavid du Colombier int pred;
13837dd7cddfSDavid du Colombier Reg *r;
13847dd7cddfSDavid du Colombier
138559cc4ca5SDavid du Colombier if(j->len == 0)
138659cc4ca5SDavid du Colombier return;
138759cc4ca5SDavid du Colombier if (cond == Truecond)
138859cc4ca5SDavid du Colombier pred = predinfo[rstart->prog->as - ABEQ].scond;
138959cc4ca5SDavid du Colombier else
139059cc4ca5SDavid du Colombier pred = predinfo[rstart->prog->as - ABEQ].notscond;
139159cc4ca5SDavid du Colombier
139259cc4ca5SDavid du Colombier for (r = j->start; ; r = successor(r)) {
139359cc4ca5SDavid du Colombier if (r->prog->as == AB) {
139459cc4ca5SDavid du Colombier if (r != j->last || branch == Delbranch)
139559cc4ca5SDavid du Colombier excise(r);
139659cc4ca5SDavid du Colombier else {
139759cc4ca5SDavid du Colombier if (cond == Truecond)
139859cc4ca5SDavid du Colombier r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
139959cc4ca5SDavid du Colombier else
140059cc4ca5SDavid du Colombier r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
14017dd7cddfSDavid du Colombier }
14027dd7cddfSDavid du Colombier }
140359cc4ca5SDavid du Colombier else if (predicable(r->prog))
140459cc4ca5SDavid du Colombier r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
140559cc4ca5SDavid du Colombier if (r->s1 != r->link) {
140659cc4ca5SDavid du Colombier r->s1 = r->link;
140759cc4ca5SDavid du Colombier r->link->p1 = r;
140859cc4ca5SDavid du Colombier }
140959cc4ca5SDavid du Colombier if (r == j->last)
141059cc4ca5SDavid du Colombier break;
141159cc4ca5SDavid du Colombier }
14127dd7cddfSDavid du Colombier }
14137dd7cddfSDavid du Colombier
14147dd7cddfSDavid du Colombier void
predicate(void)141559cc4ca5SDavid du Colombier predicate(void)
14167dd7cddfSDavid du Colombier {
14177dd7cddfSDavid du Colombier Reg *r;
141859cc4ca5SDavid du Colombier int t1, t2;
141959cc4ca5SDavid du Colombier Joininfo j1, j2;
14207dd7cddfSDavid du Colombier
142159cc4ca5SDavid du Colombier for(r=firstr; r!=R; r=r->link) {
142259cc4ca5SDavid du Colombier if (isbranch(r->prog)) {
142359cc4ca5SDavid du Colombier t1 = joinsplit(r->s1, &j1);
142459cc4ca5SDavid du Colombier t2 = joinsplit(r->s2, &j2);
142559cc4ca5SDavid du Colombier if(j1.last->link != j2.start)
142659cc4ca5SDavid du Colombier continue;
142759cc4ca5SDavid du Colombier if(j1.end == j2.end)
142859cc4ca5SDavid du Colombier if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
142959cc4ca5SDavid du Colombier (t2 == Join && (t1 == Join || t1 == Setcond))) {
143059cc4ca5SDavid du Colombier applypred(r, &j1, Falsecond, Delbranch);
143159cc4ca5SDavid du Colombier applypred(r, &j2, Truecond, Delbranch);
14327dd7cddfSDavid du Colombier excise(r);
143359cc4ca5SDavid du Colombier continue;
143459cc4ca5SDavid du Colombier }
143559cc4ca5SDavid du Colombier if(t1 == End || t1 == Branch) {
143659cc4ca5SDavid du Colombier applypred(r, &j1, Falsecond, Keepbranch);
143759cc4ca5SDavid du Colombier excise(r);
143859cc4ca5SDavid du Colombier continue;
143959cc4ca5SDavid du Colombier }
144059cc4ca5SDavid du Colombier }
144159cc4ca5SDavid du Colombier }
14427dd7cddfSDavid du Colombier }
1443