]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/1c/peep.c
merge
[plan9front.git] / sys / src / cmd / 1c / peep.c
1 #include "gc.h"
2
3 void
4 peep(void)
5 {
6         Reg *r, *r1, *r2;
7         Prog *p, *p1;
8         int t, s;
9 /*
10  * complete R structure
11  */
12         t = 0;
13         for(r=firstr; r!=R; r=r1) {
14                 r1 = r->link;
15                 if(r1 == R)
16                         break;
17                 p = r->prog->link;
18                 while(p != r1->prog)
19                 switch(p->as) {
20                 default:
21                         r2 = rega();
22                         r->link = r2;
23                         r2->link = r1;
24
25                         r2->prog = p;
26                         r2->p1 = r;
27                         r->s1 = r2;
28                         r2->s1 = r1;
29                         r1->p1 = r2;
30
31                         r = r2;
32                         t++;
33
34                 case ADATA:
35                 case AGLOBL:
36                 case ANAME:
37                 case ASIGNAME:
38                         p = p->link;
39                 }
40         }
41
42 loop1:
43         /*
44          * propigate move's by renaming
45          */
46         t = 0;
47         for(r=firstr; r!=R; r=r->link) {
48                 p = r->prog;
49                 if(p->as == AMOVL || p->as == AFMOVEF || p->as == AFMOVED)
50                 if(regtyp(p->from.type))
51                 if(anyvar(&p->to)) {
52                         if(copyprop(r)) {
53                                 excise(r);
54                                 t++;
55                         } else
56                         if(subprop(r) && copyprop(r)) {
57                                 excise(r);
58                                 t++;
59                         }
60                 }
61         }
62         if(t)
63                 goto loop1;
64         for(r=firstr; r!=R; r=r->link) {
65                 p = r->prog;
66                 /*
67                  * convert (A) ... A++ into (A)++
68                  * and     A-- ... (A) into --(A)
69                  */
70                 t = aregind(&p->from);
71                 if(t == D_NONE)
72                         goto out1;
73                 s = asize(p->as);
74                 if(s == 0)
75                         goto out1;
76                 r1 = findop(r, t, AADDL, s);
77                 if(r1 != R) {
78                         if(usedin(t, &p->to))
79                                 goto out1;
80                         p->from.type += I_INDINC - I_INDIR;
81                         excise(r1);
82                         goto out1;
83                 }
84                 r1 = findop(r, t, ASUBL, s);
85                 if(r1 != R) {
86                         p->from.type += I_INDDEC - I_INDIR;
87                         excise(r1);
88                 }
89         out1:
90                 t = aregind(&p->to);
91                 if(t == D_NONE)
92                         goto out2;
93                 s = asize(p->as);
94                 if(s == 0)
95                         goto out2;
96                 r1 = findop(r, t, AADDL, s);
97                 if(r1 != R) {
98                         p->to.type += I_INDINC - I_INDIR;
99                         excise(r1);
100                         goto out2;
101                 }
102                 r1 = findop(r, t, ASUBL, s);
103                 if(r1 != R) {
104                         if(usedin(t, &p->from))
105                                 goto out2;
106                         p->to.type += I_INDDEC - I_INDIR;
107                         excise(r1);
108                 }
109         out2:
110                 /*
111                  * get rid of unneeded save/restore CCR
112                  */
113                 if(p->from.type == D_CCR) {
114                         r1 = findccr(r);
115                         if(r1 != R) {
116                                 excise(r);
117                                 excise(r1);
118                         }
119                 }
120                 switch(p->as) {
121                 case ATSTB:
122                 case ATSTW:
123                 case ATSTL:
124                         if(findtst(r, r->prog, 0))
125                                 excise(r);
126                 }
127                 /*
128                  * turn TSTB (A); BLT; ORB $128,(A) into TAS (A); BLT; NOP
129                  */
130                 if(p->as == ATSTB && (r1 = r->s1)) {
131                         if((r1->prog->as == ABLT && (r2 = r1->s1)) ||
132                            (r1->prog->as == ABGE && (r2 = r1->s2))) {
133                                 p1 = r2->prog;
134                                 if(p1->as == AORB)
135                                 if(p1->from.type == D_CONST)
136                                 if(p1->from.offset == 128)
137                                 if(r1 == uniqp(r2))
138                                 if(tasas(&p->to, &p1->to)) {
139                                         p->as = ATAS;
140                                         excise(r2);
141                                 }
142                         }
143                 }
144         }
145 }
146
147 void
148 excise(Reg *r)
149 {
150
151         p = r->prog;
152         p->as = ANOP;
153         p->from = zprog.from;
154         p->to = zprog.to;
155 }
156
157 Reg*
158 uniqp(Reg *r)
159 {
160         Reg *r1;
161
162         r1 = r->p1;
163         if(r1 == R) {
164                 r1 = r->p2;
165                 if(r1 == R || r1->p2link != R)
166                         return R;
167         } else
168                 if(r->p2 != R)
169                         return R;
170         return r1;
171 }
172
173 Reg*
174 uniqs(Reg *r)
175 {
176         Reg *r1;
177
178         r1 = r->s1;
179         if(r1 == R) {
180                 r1 = r->s2;
181                 if(r1 == R)
182                         return R;
183         } else
184                 if(r->s2 != R)
185                         return R;
186         return r1;
187 }
188
189 /*
190  * chase backward all cc setting.
191  * returns 1 if all set same.
192  */
193 int
194 findtst(Reg *r0, Prog *rp, int n)
195 {
196         Reg *r;
197         int c;
198
199 loop:
200         n++;
201         if(n >= 10)
202                 return 0;
203         for(r=r0->p2; r!=R; r=r->p2link) {
204                 c = setcc(r->prog, rp);
205                 if(c > 0)
206                         continue;
207                 if(c == 0)
208                         return 0;
209                 if(findtst(r, rp, n) == 0)
210                         return 0;
211         }
212         r = r0->p1;
213         if(r == R)
214                 return 1;
215         c = setcc(r->prog, rp);
216         if(c > 0)
217                 return 1;
218         if(c == 0)
219                 return 0;
220         r0 = r;
221         goto loop;
222 }
223
224 /*
225  * tests cc
226  * returns -1 if no change
227  * returns 1 if set the same
228  * returns 0 if set different
229  */
230 int
231 setcc(Prog *p, Prog *rp)
232 {
233         int s;
234
235         s = asize(rp->as);
236         switch(p->as) {
237         default:
238                 if(debug['P'])
239                         print("unknown setcc %A\n", p->as);
240                 break;
241
242         case ACMPB:
243         case ACMPW:
244         case ACMPL:
245         case ABSR:
246                 return 0;
247
248         case ABRA:
249         case ABGE:
250         case ABNE:
251         case ABLE:
252         case ABEQ:
253         case ABHI:
254         case ABLS:
255         case ABMI:
256         case ABPL:
257         case ABGT:
258         case ABLT:
259         case ABCC:
260         case ABCS:
261         case APEA:
262         case ALEA:
263         case ANOP:
264
265         case AFADDD:
266         case AFMULD:
267         case AFDIVD:
268         case AFSUBD:
269         case AFADDF:
270         case AFMULF:
271         case AFDIVF:
272         case AFSUBF:
273         case AADJSP:
274                 return -1;
275
276         case AADDW:
277         case AADDL:
278         case ASUBW:
279         case ASUBL:
280         case ACLRL:
281         case ACLRW:
282                 if(p->to.type >= D_A0 && p->to.type < D_A0+8)
283                         goto areg;
284
285         case AADDB:
286         case ASUBB:
287         case AANDB:
288         case AANDW:
289         case AANDL:
290         case AORB:
291         case AORW:
292         case AORL:
293         case AEORB:
294         case AEORW:
295         case AEORL:
296         case ALSLB:
297         case ALSLW:
298         case ALSLL:
299         case ALSRB:
300         case ALSRW:
301         case ALSRL:
302         case AASLB:
303         case AASLW:
304         case AASLL:
305         case AASRB:
306         case AASRW:
307         case AASRL:
308         case ATSTB:
309         case ATSTW:
310         case ATSTL:
311         case ANEGB:
312         case ANEGW:
313         case ANEGL:
314         case ACLRB:
315                 if(asize(p->as) != s)
316                         break;
317                 if(compat(&rp->to, &p->to))
318                         return 1;
319                 break;
320
321         case AMOVW:
322         case AMOVL:
323                 if(p->to.type >= D_A0 && p->to.type < D_A0+8)
324                         goto areg;
325         case AMOVB:
326                 if(asize(p->as) != s)
327                         break;
328                 if(compat(&rp->to, &p->to))
329                         return 1;
330                 if(compat(&rp->to, &p->from))
331                         return 1;
332         }
333         return 0;
334
335 areg:
336         if((rp->to.type&D_MASK) == p->to.type)
337                 return 0;
338         return -1;
339 }
340
341 int
342 compat(Adr *a, Adr *b)
343 {
344         int o;
345
346         o = a->type;
347         if((o >= D_R0 && o < D_R0+NREG) ||
348            (o >= D_A0 && o < D_A0+NREG))
349                 return o == b->type;
350         o &= D_MASK;
351         if(o >= D_A0 && o < D_A0+NREG) {
352                 if(o != (b->type&D_MASK))
353                         return 0;
354                 if(a->offset != b->offset)
355                         return 0;
356                 o = a->type & I_MASK;
357                 if(o == I_INDIR) {
358                         o = b->type & I_MASK;
359                         if(o == I_INDIR || o == I_INDDEC)
360                                 return 1;
361                         return 0;
362                 }
363                 if(o == I_INDINC) {
364                         o = b->type & I_MASK;
365                         if(o == I_INDIR) {
366                                 b->type += I_INDINC-I_INDIR;
367                                 return 1;
368                         }
369                         if(o == I_INDDEC) {
370                                 b->type += I_INDIR-I_INDDEC;
371                                 return 1;
372                         }
373                         return 0;
374                 }
375         }
376         return 0;
377 }
378
379 int
380 aregind(Adr *a)
381 {
382         int t;
383
384         t = a->type;
385         if(t >= (D_A0|I_INDIR) && t < ((D_A0+NREG)|I_INDIR))
386         while(a->offset == 0)
387                 return t & D_MASK;
388         return D_NONE;
389 }
390
391 int
392 asize(int a)
393 {
394
395         switch(a) {
396         case AFTSTD:
397         case AFMOVED:
398         case AFADDD:
399         case AFSUBD:
400         case AFMULD:
401         case AFDIVD:
402         case AFCMPD:
403         case AFNEGD:
404                 return 8;
405
406         case AFTSTF:
407         case AFMOVEF:
408         case AFADDF:
409         case AFSUBF:
410         case AFMULF:
411         case AFDIVF:
412         case AFCMPF:
413         case AFNEGF:
414
415         case ACLRL:
416         case ATSTL:
417         case AMOVL:
418         case AADDL:
419         case ASUBL:
420         case ACMPL:
421         case AANDL:
422         case AORL:
423         case AEORL:
424         case ALSLL:
425         case ALSRL:
426         case AASLL:
427         case AASRL:
428         case ANEGL:
429                 return 4;
430
431         case ACLRW:
432         case ATSTW:
433         case AMOVW:
434         case AADDW:
435         case ASUBW:
436         case ACMPW:
437         case AANDW:
438         case AORW:
439         case AEORW:
440         case ALSLW:
441         case ALSRW:
442         case AASLW:
443         case AASRW:
444         case ANEGW:
445                 return 2;
446
447         case ACLRB:
448         case ATSTB:
449         case AMOVB:
450         case AADDB:
451         case ASUBB:
452         case ACMPB:
453         case AANDB:
454         case AORB:
455         case AEORB:
456         case ALSLB:
457         case ALSRB:
458         case AASLB:
459         case AASRB:
460         case ANEGB:
461                 return 1;
462         }
463         if(debug['P'])
464                 print("unknown asize %A\n", p->as);
465         return 0;
466 }
467
468 int
469 usedin(int t, Adr *a)
470 {
471
472         if((a->type&D_MASK) == t)
473                 return 1;
474         return 0;
475 }
476
477 Reg*
478 findccr(Reg *r)
479 {
480         Prog *p;
481
482         for(;;) {
483                 r = uniqs(r);
484                 if(r == R)
485                         break;
486                 p = r->prog;
487                 if(p->to.type == D_CCR)
488                         return r;
489                 if(setccr(p))
490                         break;
491         }
492         return R;
493 }
494
495 int
496 setccr(Prog *p)
497 {
498
499         switch(p->as) {
500         case ANOP:
501                 return 0;
502
503         case AADDL:
504         case AMOVL:
505         case ACLRL:
506                 if(p->to.type >= D_A0 && p->to.type < D_A0+8)
507                         return 0;
508         }
509         return 1;
510 }
511
512 Reg*
513 findop(Reg *r, int t, int o, int s)
514 {
515         Prog *p;
516         Reg *r1;
517
518         for(;;) {
519                 if(o == AADDL) {
520                         r1 = uniqs(r);
521                         if(r1 == R)
522                                 break;
523                         if(uniqp(r1) != r)
524                                 break;
525                 } else {
526                         r1 = uniqp(r);
527                         if(r1 == R)
528                                 break;
529                         if(uniqs(r1) != r)
530                                 break;
531                 }
532                 r = r1;
533                 p = r->prog;
534                 if(usedin(t, &p->from))
535                         break;
536                 if(usedin(t, &p->to)) {
537                         if(p->as == o)
538                         if(p->to.type == t)
539                         if(p->from.type == D_CONST)
540                         if(p->from.offset == s)
541                                 return r;
542                         break;
543                 }
544         }
545         return R;
546 }
547
548 int
549 regtyp(int t)
550 {
551
552         if(t >= D_R0 && t < D_R0+8)
553                 return 1;
554         if(t >= D_A0 && t < D_A0+8)
555                 return 1;
556         if(t >= D_F0 && t < D_F0+8)
557                 return 1;
558         return 0;
559 }
560
561 int
562 anyvar(Adr *a)
563 {
564
565         if(regtyp(a->type))
566                 return 1;
567         return 0;
568 }
569
570 /*
571  * the idea is to substitute
572  * one register for another
573  * from one MOV to another
574  *      MOV     a, R0
575  *      ADD     b, R0   / no use of R1
576  *      MOV     R0, R1
577  * would be converted to
578  *      MOV     a, R1
579  *      ADD     b, R1
580  *      MOV     R1, R0
581  * hopefully, then the former or latter MOVL
582  * will be eliminated by copy propagation.
583  */
584 int
585 subprop(Reg *r0)
586 {
587         Prog *p;
588         Adr *v1, *v2;
589         Reg *r;
590         int t;
591
592         p = r0->prog;
593         v1 = &p->from;
594         if(!regtyp(v1->type))
595                 return 0;
596         v2 = &p->to;
597         if(!regtyp(v2->type))
598                 return 0;
599         for(r=uniqp(r0); r!=R; r=uniqp(r)) {
600                 if(uniqs(r) == R)
601                         break;
602                 p = r->prog;
603                 switch(p->as) {
604                 case ADIVUW:    /* these set Rn and Rn+1 */
605                 case ADIVUL:
606                 case ADIVSW:
607                 case ADIVSL:
608                 case ABSR:
609                         return 0;
610
611                 case AFMOVED:
612                 case AFMOVEF:
613                 case AMOVL:
614                         if(p->to.type == v1->type)
615                                 goto gotit;
616                 }
617                 if(copyau(&p->from, v2) || copyau(&p->to, v2))
618                         break;
619                 if(copysub(&p->from, v1, v2, p, 0) || copysub(&p->to, v1, v2, p, 0))
620                         break;
621         }
622         return 0;
623
624 gotit:
625         copysub(&p->to, v1, v2, p, 1);
626         if(debug['P']) {
627                 print("gotit: %D->%D\n%P", v1, v2, r->prog);
628                 if(p->from.type == v2->type)
629                         print(" excise");
630                 print("\n");
631         }
632         if(p->from.type == v2->type)
633                 excise(r);
634         for(r=uniqs(r); r!=r0; r=uniqs(r)) {
635                 p = r->prog;
636                 copysub(&p->from, v1, v2, p, 1);
637                 copysub(&p->to, v1, v2, p, 1);
638                 if(debug['P'])
639                         print("%P\n", r->prog);
640         }
641         t = v1->type;
642         v1->type = v2->type;
643         v2->type = t;
644         if(debug['P'])
645                 print("%P last\n", r->prog);
646         return 1;
647 }
648
649 /*
650  * The idea is to remove redundant copies.
651  *      v1->v2  F=0
652  *      (use v2 s/v2/v1/)*
653  *      set v1  F=1
654  *      use v2  return fail
655  *      -----------------
656  *      v1->v2  F=0
657  *      (use v2 s/v2/v1/)*
658  *      set v1  F=1
659  *      set v2  return success
660  */
661 int
662 copyprop(Reg *r0)
663 {
664         Prog *p;
665         Adr *v1, *v2;
666         Reg *r;
667
668         p = r0->prog;
669         v1 = &p->from;
670         v2 = &p->to;
671         if(copyas(v1, v2))
672                 return 1;
673         for(r=firstr; r!=R; r=r->link)
674                 r->active = 0;
675         return copy1(v1, v2, r0->s1, 0);
676 }
677
678 int
679 copy1(Adr *v1, Adr *v2, Reg *r, int f)
680 {
681         int t;
682
683         if(r->active) {
684                 if(debug['P'])
685                         print("copyret 1\n");
686                 return 1;
687         }
688         r->active = 1;
689         if(debug['P'])
690                 print("copy %D->%D\n", v1, v2);
691         for(; r != R; r = r->s1) {
692                 if(debug['P'])
693                         print("%P", r->prog);
694                 if(!f && uniqp(r) == R) {
695                         f = 1;
696                         if(debug['P'])
697                                 print("; merge; f=%d", f);
698                 }
699                 t = copyu(r->prog, v2, A);
700                 switch(t) {
701                 case 2: /* rar, cant split */
702                         if(debug['P'])
703                                 print("; rar return 0\n");
704                         return 0;
705                 case 3: /* set */
706                         if(debug['P'])
707                                 print("; set; return 1\n");
708                         return 1;
709                 case 1: /* used, substitute */
710                 case 4: /* use and set */
711                         if(f) {
712                                 if(debug['P'])
713                                         print("; used and f; return 0\n");
714                                 return 0;
715                         }
716                         if(copyu(r->prog, v2, v1)) {
717                                 if(debug['P'])
718                                         print("; sub fail; return 0\n");
719                                 return 0;
720                         }
721                         if(debug['P'])
722                                 print("; substitute");
723                         if(t == 4) {
724                                 if(debug['P'])
725                                         print("; used and set; return 1\n");
726                                 return 1;
727                         }
728                         break;
729                 }
730                 if(!f) {
731                         t = copyu(r->prog, v1, A);
732                         if(!f && (t == 2 || t == 3 || t == 4)) {
733                                 if(debug['P'])
734                                         print("; f set used");
735                                 f = 1;
736                         }
737                 }
738                 if(debug['P'])
739                         print("\n");
740                 if(r->s2)
741                         if(!copy1(v1, v2, r->s2, f))
742                                 return 0;
743         }
744         return 1;
745 }
746
747 /*
748  * return
749  * 1 if v only used (and substitute),
750  * 2 if read-alter-rewrite
751  * 3 if set
752  * 4 if set and used
753  * 0 otherwise (not touched)
754  */
755 int
756 copyu(Prog *p, Adr *v, Adr *s)
757 {
758         int t;
759
760         switch(p->as) {
761
762         default:
763                 if(debug['P'])
764                         print("unknown op %A\n", p->as);
765                 return 2;
766
767         case APEA:      /* rhs addr */
768                 if(copyas(&p->to, v))
769                         return 2;
770                 goto caseread;
771
772         case ALEA:      /* lhs addr, rhs store */
773                 if(copyas(&p->from, v))
774                         return 2;
775
776         case AMOVL:     /* rhs store */
777         case ACLRL:
778         case AFMOVEF:
779         case AFMOVED:
780         case AFMOVEB:
781         case AFMOVEW:
782         case AFMOVEL:
783         case ANOP:
784                 if(copyas(&p->to, v)) {
785                         if(s != A)
786                                 return copysub(&p->from, v, s, p, 1);
787                         if(copyau(&p->from, v))
788                                 return 4;
789                         return 3;
790                 }
791                 goto caseread;
792                         
793         case AADDL:     /* rhs rar */
794         case AADDW:
795         case AADDB:
796         case ASUBL:
797         case ASUBW:
798         case ASUBB:
799         case AANDL:
800         case AANDW:
801         case AANDB:
802         case AORL:
803         case AORW:
804         case AORB:
805         case AEORL:
806         case AEORW:
807         case AEORB:
808         case AASRL:
809         case AASRW:
810         case AASRB:
811         case AASLL:
812         case AASLW:
813         case AASLB:
814         case ALSRL:
815         case ALSRW:
816         case ALSRB:
817         case ANOTL:
818         case ANOTW:
819         case ANOTB:
820         case ANEGL:
821         case ANEGW:
822         case ANEGB:
823         case AEXTBL:
824         case AEXTWL:
825         case AEXTBW:
826
827         case AMULSL:
828         case AMULUL:
829
830         case AMOVW:     /* only sets part of register */
831         case AMOVB:
832         case ACLRW:
833         case ACLRB:
834
835         case AFADDD:
836         case AFMULD:
837         case AFDIVD:
838         case AFSUBD:
839         case AFNEGD:
840         case AFADDF:
841         case AFMULF:
842         case AFDIVF:
843         case AFSUBF:
844         case AFNEGF:
845                 if(copyas(&p->to, v))
846                         return 2;
847                 goto caseread;
848
849         case ADBF:      /* lhs rar */
850                 if(copyas(&p->from, v))
851                         return 2;
852                 goto caseread;
853
854         case ACMPL:     /* read only */
855         case ACMPW:
856         case ACMPB:
857         case AFCMPF:
858         case AFCMPD:
859         case ATSTL:
860         case ATSTW:
861         case ATSTB:
862         case AFTSTF:
863         case AFTSTD:
864         caseread:
865                 if(s != A) {
866                         if(copysub(&p->from, v, s, p, 1))
867                                 return 1;
868                         return copysub(&p->to, v, s, p, 1);
869                 }
870                 if(copyau(&p->from, v))
871                         return 1;
872                 if(copyau(&p->to, v))
873                         return 1;
874                 break;
875
876         case ABRA:      /* no reference */
877         case ABGE:
878         case ABNE:
879         case ABLE:
880         case ABEQ:
881         case ABHI:
882         case ABLS:
883         case ABMI:
884         case ABPL:
885         case ABGT:
886         case ABLT:
887         case ABCC:
888         case ABCS:
889
890         case AFBEQ:
891         case AFBNE:
892         case AFBGT:
893         case AFBGE:
894         case AFBLE:
895         case AFBLT:
896
897         case AADJSP:
898         case ACASEW:
899                 break;
900
901         case ADIVUW:    /* these set Rn and Rn+1 */
902         case ADIVUL:
903         case ADIVSW:
904         case ADIVSL:
905                 t = v->type;
906                 if(t == p->to.type || t == p->to.type+1)
907                         return 2;
908                 goto caseread;
909
910         case ARTS:      /* funny */
911                 t = v->type;
912                 if(t == D_R0 || t == D_F0)
913                         return 2;
914                 if(t >= D_R0 && t < D_R0+NREG)
915                 if(t-D_R0 > exregoffset)
916                         return 2;
917                 if(t >= D_A0 && t < D_A0+NREG)
918                 if(t-D_A0 > exaregoffset)
919                         return 2;
920                 if(t >= D_F0 && t < D_F0+NREG)
921                 if(t-D_F0 > exfregoffset)
922                         return 2;
923                 return 3;
924
925         case ABSR:      /* funny */
926                 t = v->type;
927                 if(t >= D_R0 && t < D_R0+NREG)
928                 if(t-D_R0 > exregoffset)
929                         return 2;
930                 if(t >= D_A0 && t < D_A0+NREG)
931                 if(t-D_A0 > exaregoffset)
932                         return 2;
933                 if(t >= D_F0 && t < D_F0+NREG)
934                 if(t-D_F0 > exfregoffset)
935                         return 2;
936                 if(copyau(&p->to, v))
937                         return 2;
938                 return 3;
939         }
940         return 0;
941 }
942
943 /*
944  * direct reference,
945  * could be set/use depending on
946  * semantics
947  */
948 int
949 copyas(Adr *a, Adr *v)
950 {
951
952         if(a->type != v->type)
953                 return 0;
954         if(regtyp(v->type))
955                 return 1;
956         if(v->type == D_AUTO || v->type == D_PARAM) {
957                 if(v->offset == a->offset)
958                         return 1;
959                 return 0;
960         }
961         return 0;
962 }
963
964 /*
965  * indirect
966  */
967 int
968 tasas(Adr *a, Adr *v)
969 {
970         int t;
971
972         t = a->type;
973         if(t < I_INDIR+D_A0 && t >= I_INDIR+D_A0+8)
974                 return 0;
975         if(v->type != t)
976                 return 0;
977         if(a->displace != v->displace)
978                 return 0;
979         return 1;
980 }
981
982 /*
983  * either direct or indirect
984  */
985 int
986 copyau(Adr *a, Adr *v)
987 {
988         int t;
989
990         if(copyas(a, v))
991                 return 1;
992         t = v->type;
993         if(regtyp(t)) {
994                 if((a->type & D_MASK) == t)
995                         return 1;
996         }
997         return 0;
998 }
999
1000 /*
1001  * substitute s for v in a
1002  * return failure to substitute
1003  */
1004 int
1005 copysub(Adr *a, Adr *v, Adr *s, Prog *p, int f)
1006 {
1007         int t;
1008
1009         if(copyas(a, v)) {
1010                 t = s->type;
1011                 if(t >= D_F0 && t < D_F0+8) {
1012                         if(f)
1013                                 a->type = t;
1014                         return 0;
1015                 }
1016                 if(t >= D_R0 && t < D_R0+8) {
1017                         if(f)
1018                                 a->type = t;
1019                         return 0;
1020                 }
1021                 if(!(t >= D_A0 && t < D_A0+8))
1022                         return 1;
1023                 switch(p->as) {
1024                 default:
1025                         return 1;
1026
1027                 case AMOVL:
1028                 case AMOVW:
1029                 case ACMPL:
1030                 case ACMPW:
1031                         break;
1032
1033                 case AADDL:
1034                 case AADDW:
1035                 case ASUBL:
1036                 case ASUBW:
1037                         if(a == &p->from && !regtyp(p->to.type))
1038                                 return 1;
1039                         break;
1040                 }
1041                 if(f)
1042                         a->type = t;
1043                 return 0;
1044         }
1045         t = v->type;
1046         if(regtyp(t)) {
1047                 if((a->type & D_MASK) == t) {
1048                         if((s->type ^ t) & ~(NREG-1))
1049                                 return 1;
1050                         if(f)
1051                                 a->type = (a->type & ~D_MASK) | s->type;
1052                         return 0;
1053                 }
1054                 return 0;
1055         }
1056         return 0;
1057 }