]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/2c/peep.c
devproc: can't wait for ourselfs to stop (thanks Shamar)
[plan9front.git] / sys / src / cmd / 2c / 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         if(a->index != D_NONE)
347                 return 0;
348         if(b->index != D_NONE)
349                 return 0;
350         o = a->type;
351         if((o >= D_R0 && o < D_R0+NREG) ||
352            (o >= D_A0 && o < D_A0+NREG))
353                 return o == b->type;
354         o &= D_MASK;
355         if(o >= D_A0 && o < D_A0+NREG) {
356                 if(o != (b->type&D_MASK))
357                         return 0;
358                 if(a->offset != b->offset)
359                         return 0;
360                 o = a->type & I_MASK;
361                 if(o == I_INDIR) {
362                         o = b->type & I_MASK;
363                         if(o == I_INDIR || o == I_INDDEC)
364                                 return 1;
365                         return 0;
366                 }
367                 if(o == I_INDINC) {
368                         o = b->type & I_MASK;
369                         if(o == I_INDIR) {
370                                 b->type += I_INDINC-I_INDIR;
371                                 return 1;
372                         }
373                         if(o == I_INDDEC) {
374                                 b->type += I_INDIR-I_INDDEC;
375                                 return 1;
376                         }
377                         return 0;
378                 }
379         }
380         return 0;
381 }
382
383 int
384 aregind(Adr *a)
385 {
386         int t;
387
388         t = a->type;
389         if(t >= (D_A0|I_INDIR) && t < ((D_A0+NREG)|I_INDIR))
390         while(a->offset == 0 && a->index == D_NONE)
391                 return t & D_MASK;
392         return D_NONE;
393 }
394
395 int
396 asize(int a)
397 {
398
399         switch(a) {
400         case AFTSTD:
401         case AFMOVED:
402         case AFADDD:
403         case AFSUBD:
404         case AFMULD:
405         case AFDIVD:
406         case AFCMPD:
407         case AFNEGD:
408                 return 8;
409
410         case AFTSTF:
411         case AFMOVEF:
412         case AFADDF:
413         case AFSUBF:
414         case AFMULF:
415         case AFDIVF:
416         case AFCMPF:
417         case AFNEGF:
418
419         case ACLRL:
420         case ATSTL:
421         case AMOVL:
422         case AADDL:
423         case ASUBL:
424         case ACMPL:
425         case AANDL:
426         case AORL:
427         case AEORL:
428         case ALSLL:
429         case ALSRL:
430         case AASLL:
431         case AASRL:
432         case ANEGL:
433                 return 4;
434
435         case ACLRW:
436         case ATSTW:
437         case AMOVW:
438         case AADDW:
439         case ASUBW:
440         case ACMPW:
441         case AANDW:
442         case AORW:
443         case AEORW:
444         case ALSLW:
445         case ALSRW:
446         case AASLW:
447         case AASRW:
448         case ANEGW:
449                 return 2;
450
451         case ACLRB:
452         case ATSTB:
453         case AMOVB:
454         case AADDB:
455         case ASUBB:
456         case ACMPB:
457         case AANDB:
458         case AORB:
459         case AEORB:
460         case ALSLB:
461         case ALSRB:
462         case AASLB:
463         case AASRB:
464         case ANEGB:
465                 return 1;
466         }
467         if(debug['P'])
468                 print("unknown asize %A\n", p->as);
469         return 0;
470 }
471
472 int
473 usedin(int t, Adr *a)
474 {
475
476         if((a->type&D_MASK) == t)
477                 return 1;
478         if((a->index&D_MASK) == t)
479                 return 1;
480         return 0;
481 }
482
483 Reg*
484 findccr(Reg *r)
485 {
486         Prog *p;
487
488         for(;;) {
489                 r = uniqs(r);
490                 if(r == R)
491                         break;
492                 p = r->prog;
493                 if(p->to.type == D_CCR)
494                         return r;
495                 if(setccr(p))
496                         break;
497         }
498         return R;
499 }
500
501 int
502 setccr(Prog *p)
503 {
504
505         switch(p->as) {
506         case ANOP:
507                 return 0;
508
509         case AADDL:
510         case AMOVL:
511         case ACLRL:
512                 if(p->to.type >= D_A0 && p->to.type < D_A0+8)
513                         return 0;
514         }
515         return 1;
516 }
517
518 Reg*
519 findop(Reg *r, int t, int o, int s)
520 {
521         Prog *p;
522         Reg *r1;
523
524         for(;;) {
525                 if(o == AADDL) {
526                         r1 = uniqs(r);
527                         if(r1 == R)
528                                 break;
529                         if(uniqp(r1) != r)
530                                 break;
531                 } else {
532                         r1 = uniqp(r);
533                         if(r1 == R)
534                                 break;
535                         if(uniqs(r1) != r)
536                                 break;
537                 }
538                 r = r1;
539                 p = r->prog;
540                 if(usedin(t, &p->from))
541                         break;
542                 if(usedin(t, &p->to)) {
543                         if(p->as == o)
544                         if(p->to.type == t)
545                         if(p->to.index == D_NONE)
546                         if(p->from.type == D_CONST)
547                         if(p->from.offset == s)
548                                 return r;
549                         break;
550                 }
551         }
552         return R;
553 }
554
555 int
556 regtyp(int t)
557 {
558
559         if(t >= D_R0 && t < D_R0+8)
560                 return 1;
561         if(t >= D_A0 && t < D_A0+8)
562                 return 1;
563         if(t >= D_F0 && t < D_F0+8)
564                 return 1;
565         return 0;
566 }
567
568 int
569 anyvar(Adr *a)
570 {
571
572         if(regtyp(a->type))
573                 return 1;
574         return 0;
575 }
576
577 /*
578  * the idea is to substitute
579  * one register for another
580  * from one MOV to another
581  *      MOV     a, R0
582  *      ADD     b, R0   / no use of R1
583  *      MOV     R0, R1
584  * would be converted to
585  *      MOV     a, R1
586  *      ADD     b, R1
587  *      MOV     R1, R0
588  * hopefully, then the former or latter MOVL
589  * will be eliminated by copy propagation.
590  */
591 int
592 subprop(Reg *r0)
593 {
594         Prog *p;
595         Adr *v1, *v2;
596         Reg *r;
597         int t;
598
599         p = r0->prog;
600         v1 = &p->from;
601         if(!regtyp(v1->type))
602                 return 0;
603         v2 = &p->to;
604         if(!regtyp(v2->type))
605                 return 0;
606         for(r=uniqp(r0); r!=R; r=uniqp(r)) {
607                 if(uniqs(r) == R)
608                         break;
609                 p = r->prog;
610                 switch(p->as) {
611                 case ADIVUW:    /* these set Rn and Rn+1 */
612                 case ADIVUL:
613                 case ADIVSW:
614                 case ADIVSL:
615                 case ABSR:
616                         return 0;
617
618                 case AFMOVED:
619                 case AFMOVEF:
620                 case AMOVL:
621                         if(p->to.type == v1->type)
622                                 goto gotit;
623                 }
624                 if(copyau(&p->from, v2) || copyau(&p->to, v2))
625                         break;
626                 if(copysub(&p->from, v1, v2, p, 0) || copysub(&p->to, v1, v2, p, 0))
627                         break;
628         }
629         return 0;
630
631 gotit:
632         copysub(&p->to, v1, v2, p, 1);
633         if(debug['P']) {
634                 print("gotit: %D->%D\n%P", v1, v2, r->prog);
635                 if(p->from.type == v2->type)
636                         print(" excise");
637                 print("\n");
638         }
639         if(p->from.type == v2->type)
640                 excise(r);
641         for(r=uniqs(r); r!=r0; r=uniqs(r)) {
642                 p = r->prog;
643                 copysub(&p->from, v1, v2, p, 1);
644                 copysub(&p->to, v1, v2, p, 1);
645                 if(debug['P'])
646                         print("%P\n", r->prog);
647         }
648         t = v1->type;
649         v1->type = v2->type;
650         v2->type = t;
651         if(debug['P'])
652                 print("%P last\n", r->prog);
653         return 1;
654 }
655
656 /*
657  * The idea is to remove redundant copies.
658  *      v1->v2  F=0
659  *      (use v2 s/v2/v1/)*
660  *      set v1  F=1
661  *      use v2  return fail
662  *      -----------------
663  *      v1->v2  F=0
664  *      (use v2 s/v2/v1/)*
665  *      set v1  F=1
666  *      set v2  return success
667  */
668 int
669 copyprop(Reg *r0)
670 {
671         Prog *p;
672         Adr *v1, *v2;
673         Reg *r;
674
675         p = r0->prog;
676         v1 = &p->from;
677         v2 = &p->to;
678         if(copyas(v1, v2))
679                 return 1;
680         for(r=firstr; r!=R; r=r->link)
681                 r->active = 0;
682         return copy1(v1, v2, r0->s1, 0);
683 }
684
685 int
686 copy1(Adr *v1, Adr *v2, Reg *r, int f)
687 {
688         int t;
689
690         if(r->active) {
691                 if(debug['P'])
692                         print("copyret 1\n");
693                 return 1;
694         }
695         r->active = 1;
696         if(debug['P'])
697                 print("copy %D->%D\n", v1, v2);
698         for(; r != R; r = r->s1) {
699                 if(debug['P'])
700                         print("%P", r->prog);
701                 if(!f && uniqp(r) == R) {
702                         f = 1;
703                         if(debug['P'])
704                                 print("; merge; f=%d", f);
705                 }
706                 t = copyu(r->prog, v2, A);
707                 switch(t) {
708                 case 2: /* rar, cant split */
709                         if(debug['P'])
710                                 print("; rar return 0\n");
711                         return 0;
712                 case 3: /* set */
713                         if(debug['P'])
714                                 print("; set; return 1\n");
715                         return 1;
716                 case 1: /* used, substitute */
717                 case 4: /* use and set */
718                         if(f) {
719                                 if(debug['P'])
720                                         print("; used and f; return 0\n");
721                                 return 0;
722                         }
723                         if(copyu(r->prog, v2, v1)) {
724                                 if(debug['P'])
725                                         print("; sub fail; return 0\n");
726                                 return 0;
727                         }
728                         if(debug['P'])
729                                 print("; substitute");
730                         if(t == 4) {
731                                 if(debug['P'])
732                                         print("; used and set; return 1\n");
733                                 return 1;
734                         }
735                         break;
736                 }
737                 if(!f) {
738                         t = copyu(r->prog, v1, A);
739                         if(!f && (t == 2 || t == 3 || t == 4)) {
740                                 if(debug['P'])
741                                         print("; f set used");
742                                 f = 1;
743                         }
744                 }
745                 if(debug['P'])
746                         print("\n");
747                 if(r->s2)
748                         if(!copy1(v1, v2, r->s2, f))
749                                 return 0;
750         }
751         return 1;
752 }
753
754 /*
755  * return
756  * 1 if v only used (and substitute),
757  * 2 if read-alter-rewrite
758  * 3 if set
759  * 4 if set and used
760  * 0 otherwise (not touched)
761  */
762 int
763 copyu(Prog *p, Adr *v, Adr *s)
764 {
765         int t;
766
767         switch(p->as) {
768
769         default:
770                 if(debug['P'])
771                         print("unknown op %A\n", p->as);
772                 return 2;
773
774         case APEA:      /* rhs addr */
775                 if(copyas(&p->to, v))
776                         return 2;
777                 goto caseread;
778
779         case ALEA:      /* lhs addr, rhs store */
780                 if(copyas(&p->from, v))
781                         return 2;
782
783         case AMOVL:     /* rhs store */
784         case ACLRL:
785         case AFMOVEF:
786         case AFMOVED:
787         case AFMOVEB:
788         case AFMOVEW:
789         case AFMOVEL:
790         case ANOP:
791                 if(copyas(&p->to, v)) {
792                         if(s != A)
793                                 return copysub(&p->from, v, s, p, 1);
794                         if(copyau(&p->from, v))
795                                 return 4;
796                         return 3;
797                 }
798                 goto caseread;
799                         
800         case AADDL:     /* rhs rar */
801         case AADDW:
802         case AADDB:
803         case ASUBL:
804         case ASUBW:
805         case ASUBB:
806         case AANDL:
807         case AANDW:
808         case AANDB:
809         case AORL:
810         case AORW:
811         case AORB:
812         case AEORL:
813         case AEORW:
814         case AEORB:
815         case AASRL:
816         case AASRW:
817         case AASRB:
818         case AASLL:
819         case AASLW:
820         case AASLB:
821         case ALSRL:
822         case ALSRW:
823         case ALSRB:
824         case ANOTL:
825         case ANOTW:
826         case ANOTB:
827         case ANEGL:
828         case ANEGW:
829         case ANEGB:
830         case AEXTBL:
831         case AEXTWL:
832         case AEXTBW:
833
834         case AMULSL:
835         case AMULUL:
836
837         case AMOVW:     /* only sets part of register */
838         case AMOVB:
839         case ACLRW:
840         case ACLRB:
841
842         case AFADDD:
843         case AFMULD:
844         case AFDIVD:
845         case AFSUBD:
846         case AFNEGD:
847         case AFADDF:
848         case AFMULF:
849         case AFDIVF:
850         case AFSUBF:
851         case AFNEGF:
852                 if(copyas(&p->to, v))
853                         return 2;
854                 goto caseread;
855
856         case ADBF:      /* lhs rar */
857                 if(copyas(&p->from, v))
858                         return 2;
859                 goto caseread;
860
861         case ACMPL:     /* read only */
862         case ACMPW:
863         case ACMPB:
864         case AFCMPF:
865         case AFCMPD:
866         case ATSTL:
867         case ATSTW:
868         case ATSTB:
869         case AFTSTF:
870         case AFTSTD:
871         caseread:
872                 if(s != A) {
873                         if(copysub(&p->from, v, s, p, 1))
874                                 return 1;
875                         return copysub(&p->to, v, s, p, 1);
876                 }
877                 if(copyau(&p->from, v))
878                         return 1;
879                 if(copyau(&p->to, v))
880                         return 1;
881                 break;
882
883         case ABRA:      /* no reference */
884         case ABGE:
885         case ABNE:
886         case ABLE:
887         case ABEQ:
888         case ABHI:
889         case ABLS:
890         case ABMI:
891         case ABPL:
892         case ABGT:
893         case ABLT:
894         case ABCC:
895         case ABCS:
896
897         case AFBEQ:
898         case AFBNE:
899         case AFBGT:
900         case AFBGE:
901         case AFBLE:
902         case AFBLT:
903
904         case AADJSP:
905         case ACASEW:
906                 break;
907
908         case ADIVUW:    /* these set Rn and Rn+1 */
909         case ADIVUL:
910         case ADIVSW:
911         case ADIVSL:
912                 t = v->type;
913                 if(t == p->to.type || t == p->to.type+1)
914                         return 2;
915                 goto caseread;
916
917         case ARTS:      /* funny */
918                 t = v->type;
919                 if(t == D_R0 || t == D_F0)
920                         return 2;
921                 if(t >= D_R0 && t < D_R0+NREG)
922                 if(t-D_R0 > exregoffset)
923                         return 2;
924                 if(t >= D_A0 && t < D_A0+NREG)
925                 if(t-D_A0 > exaregoffset)
926                         return 2;
927                 if(t >= D_F0 && t < D_F0+NREG)
928                 if(t-D_F0 > exfregoffset)
929                         return 2;
930                 return 3;
931
932         case ABSR:      /* funny */
933                 t = v->type;
934                 if(t >= D_R0 && t < D_R0+NREG)
935                 if(t-D_R0 > exregoffset)
936                         return 2;
937                 if(t >= D_A0 && t < D_A0+NREG)
938                 if(t-D_A0 > exaregoffset)
939                         return 2;
940                 if(t >= D_F0 && t < D_F0+NREG)
941                 if(t-D_F0 > exfregoffset)
942                         return 2;
943                 return 3;
944         }
945         return 0;
946 }
947
948 /*
949  * direct reference,
950  * could be set/use depending on
951  * semantics
952  */
953 int
954 copyas(Adr *a, Adr *v)
955 {
956
957         if(a->type != v->type)
958                 return 0;
959         if(regtyp(v->type))
960                 return 1;
961         if(v->type == D_AUTO || v->type == D_PARAM) {
962                 if(v->offset == a->offset)
963                         return 1;
964                 return 0;
965         }
966         return 0;
967 }
968
969 /*
970  * indirect
971  */
972 int
973 tasas(Adr *a, Adr *v)
974 {
975         int t;
976
977         if(a->index != D_NONE)
978                 return 0;
979         if(v->index != D_NONE)
980                 return 0;
981         t = a->type;
982         if(t < I_INDIR+D_A0 && t >= I_INDIR+D_A0+8)
983                 return 0;
984         if(v->type != t)
985                 return 0;
986         if(a->displace != v->displace)
987                 return 0;
988         return 1;
989 }
990
991 /*
992  * either direct or indirect
993  */
994 int
995 copyau(Adr *a, Adr *v)
996 {
997         int t;
998
999         if(copyas(a, v))
1000                 return 1;
1001         t = v->type;
1002         if(regtyp(t)) {
1003                 if((a->type & D_MASK) == t)
1004                         return 1;
1005                 if((a->index & D_MASK) == t)
1006                         return 1;
1007         }
1008         return 0;
1009 }
1010
1011 /*
1012  * substitute s for v in a
1013  * return failure to substitute
1014  */
1015 int
1016 copysub(Adr *a, Adr *v, Adr *s, Prog *p, int f)
1017 {
1018         int t;
1019
1020         if(copyas(a, v)) {
1021                 t = s->type;
1022                 if(t >= D_F0 && t < D_F0+8) {
1023                         if(f)
1024                                 a->type = t;
1025                         return 0;
1026                 }
1027                 if(t >= D_R0 && t < D_R0+8) {
1028                         if(f)
1029                                 a->type = t;
1030                         return 0;
1031                 }
1032                 if(!(t >= D_A0 && t < D_A0+8))
1033                         return 1;
1034                 switch(p->as) {
1035                 default:
1036                         return 1;
1037
1038                 case AMOVL:
1039                 case AMOVW:
1040                 case ACMPL:
1041                 case ACMPW:
1042                         break;
1043
1044                 case AADDL:
1045                 case AADDW:
1046                 case ASUBL:
1047                 case ASUBW:
1048                         if(a == &p->from && !regtyp(p->to.type))
1049                                 return 1;
1050                         break;
1051                 }
1052                 if(f)
1053                         a->type = t;
1054                 return 0;
1055         }
1056         t = v->type;
1057         if(regtyp(t)) {
1058                 if((a->type & D_MASK) == t) {
1059                         if((s->type ^ t) & ~(NREG-1))
1060                                 return 1;
1061                         if(f)
1062                                 a->type = (a->type & ~D_MASK) | s->type;
1063                         return 0;
1064                 }
1065                 if((a->index & D_MASK) == t) {
1066                         if(f)
1067                                 a->index = (a->index & ~D_MASK) | s->type;
1068                         return 0;
1069                 }
1070                 return 0;
1071         }
1072         return 0;
1073 }