]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/6c/peep.c
awk: make empty FS unicodely-correct.
[plan9front.git] / sys / src / cmd / 6c / peep.c
1 #include "gc.h"
2
3 static int
4 needc(Prog *p)
5 {
6         while(p != P) {
7                 switch(p->as) {
8                 case AADCL:
9                 case AADCQ:
10                 case ASBBL:
11                 case ASBBQ:
12                 case ARCRL:
13                 case ARCRQ:
14                         return 1;
15                 case AADDL:
16                 case AADDQ:
17                 case ASUBL:
18                 case ASUBQ:
19                 case AJMP:
20                 case ARET:
21                 case ACALL:
22                         return 0;
23                 default:
24                         if(p->to.type == D_BRANCH)
25                                 return 0;
26                 }
27                 p = p->link;
28         }
29         return 0;
30 }
31
32 static Reg*
33 rnops(Reg *r)
34 {
35         Prog *p;
36         Reg *r1;
37
38         if(r != R)
39         for(;;){
40                 p = r->prog;
41                 if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
42                         break;
43                 r1 = uniqs(r);
44                 if(r1 == R)
45                         break;
46                 r = r1;
47         }
48         return r;
49 }
50
51 void
52 peep(void)
53 {
54         Reg *r, *r1, *r2;
55         Prog *p, *p1;
56         int t;
57
58         /*
59          * complete R structure
60          */
61         t = 0;
62         for(r=firstr; r!=R; r=r1) {
63                 r1 = r->link;
64                 if(r1 == R)
65                         break;
66                 p = r->prog->link;
67                 while(p != r1->prog)
68                 switch(p->as) {
69                 default:
70                         r2 = rega();
71                         r->link = r2;
72                         r2->link = r1;
73
74                         r2->prog = p;
75                         r2->p1 = r;
76                         r->s1 = r2;
77                         r2->s1 = r1;
78                         r1->p1 = r2;
79
80                         r = r2;
81                         t++;
82
83                 case ADATA:
84                 case AGLOBL:
85                 case ANAME:
86                 case ASIGNAME:
87                         p = p->link;
88                 }
89         }
90
91         pc = 0; /* speculating it won't kill */
92
93 loop1:
94
95         t = 0;
96         for(r=firstr; r!=R; r=r->link) {
97                 p = r->prog;
98                 switch(p->as) {
99                 case AMOVL:
100                 case AMOVQ:
101                 case AMOVSS:
102                 case AMOVSD:
103                         if(!regtyp(&p->to))
104                                 break;
105                         if(regtyp(&p->from)) {
106                                 if(copyprop(r)) {
107                                         excise(r);
108                                         t++;
109                                         break;
110                                 }
111                                 if(subprop(r) && copyprop(r)) {
112                                         excise(r);
113                                         t++;
114                                         break;
115                                 }
116                         }
117                         if(p->as != AMOVL)
118                                 break;
119                         r1 = rnops(uniqs(r));
120                         if(r1 != R){
121                                 p1 = r1->prog;
122                                 if(p1->as == AMOVLQZX && p1->from.type == p->to.type && p1->to.type == p->to.type){
123                                         excise(r1);
124                                         t++;
125                                 }
126                         }
127                         break;
128
129                 case AMOVBLZX:
130                 case AMOVWLZX:
131                 case AMOVBLSX:
132                 case AMOVWLSX:
133                         if(regtyp(&p->to)) {
134                                 r1 = rnops(uniqs(r));
135                                 if(r1 != R) {
136                                         p1 = r1->prog;
137                                         if(p->to.type != p1->from.type)
138                                                 break;
139                                         if((p->as == AMOVBLZX && p1->as == AMOVBQZX)
140                                         || (p->as == AMOVWLZX && p1->as == AMOVWQZX)
141                                         || (p->as == AMOVBLSX && p1->as == AMOVBQSX && p1->to.type == p->to.type)
142                                         || (p->as == AMOVWLSX && p1->as == AMOVWQSX && p1->to.type == p->to.type)) {
143                                                 p->as = p1->as;
144                                                 p1->as = AMOVQ;
145                                                 t++;
146                                         } else
147                                         if(p->as == p1->as) {
148                                                 p1->as = AMOVL;
149                                                 t++;
150                                         }
151                                 }
152                         }
153                         break;
154
155                 case AMOVBQSX:
156                 case AMOVBQZX:
157                 case AMOVWQSX:
158                 case AMOVWQZX:
159                 case AMOVLQSX:
160                 case AMOVLQZX:
161                         if(regtyp(&p->to)) {
162                                 r1 = rnops(uniqs(r));
163                                 if(r1 != R) {
164                                         p1 = r1->prog;
165                                         if(p->as == p1->as && p->to.type == p1->from.type){
166                                                 p1->as = AMOVQ;
167                                                 t++;
168                                         }
169                                 }
170                         }
171                         break;
172
173                 case ALEAQ:
174                         if(regtyp(&p->to)) {
175                                 r1 = rnops(uniqs(r));
176                                 if(r1 != R){
177                                         p1 = r1->prog;
178                                         if((p1->as == AMOVL || p1->as == AMOVQ)
179                                         && p1->to.type == p->to.type
180                                         && p1->from.type-D_INDIR == p->to.type
181                                         && p1->from.index == D_NONE
182                                         && p1->from.offset == 0){
183                                                 p->as = p1->as;
184                                                 excise(r1);
185                                                 t++;
186                                         }
187                                 }
188                         }
189                         break;
190
191                 case AADDL:
192                 case AADDQ:
193                 case AADDW:
194                         if(p->from.type != D_CONST || needc(p->link))
195                                 break;
196                         if(p->from.offset == -1){
197                                 if(p->as == AADDQ)
198                                         p->as = ADECQ;
199                                 else if(p->as == AADDL)
200                                         p->as = ADECL;
201                                 else
202                                         p->as = ADECW;
203                                 p->from = zprog.from;
204                         }
205                         else if(p->from.offset == 1){
206                                 if(p->as == AADDQ)
207                                         p->as = AINCQ;
208                                 else if(p->as == AADDL)
209                                         p->as = AINCL;
210                                 else
211                                         p->as = AINCW;
212                                 p->from = zprog.from;
213                         }
214                         break;
215
216                 case ASUBL:
217                 case ASUBQ:
218                 case ASUBW:
219                         if(p->from.type != D_CONST || needc(p->link))
220                                 break;
221                         if(p->from.offset == -1) {
222                                 if(p->as == ASUBQ)
223                                         p->as = AINCQ;
224                                 else if(p->as == ASUBL)
225                                         p->as = AINCL;
226                                 else
227                                         p->as = AINCW;
228                                 p->from = zprog.from;
229                         }
230                         else if(p->from.offset == 1){
231                                 if(p->as == ASUBQ)
232                                         p->as = ADECQ;
233                                 else if(p->as == ASUBL)
234                                         p->as = ADECL;
235                                 else
236                                         p->as = ADECW;
237                                 p->from = zprog.from;
238                         }
239                         break;
240
241                 case ACMPL:
242                 case ACMPQ:
243                         if(p->to.type != D_CONST || p->to.offset != 0 || regtyp(&p->from) == 0)
244                                 break;
245                         if(p->link == P || (p->link->as != AJEQ && p->link->as != AJNE))
246                                 break;
247                         r1 = uniqp(r);
248                         while(r1 != R && r1->prog->as == ANOP)
249                                 r1 = uniqp(r1);
250                         if(r1 == R || r1->prog->to.type != p->from.type)
251                                 break;
252                         p1 = r1->prog;
253                         switch(p1->as){
254                         case ASHLQ:
255                         case ASHRQ:
256                         case ASALQ:
257                         case ASARQ:
258                                 /* shift doesnt affect ZF when shift count is zero */
259                                 if(p1->from.type != D_CONST || p1->from.offset == 0)
260                                         break;
261                         case AANDQ:
262                         case AORQ:
263                         case AXORQ:
264                         case ANEGQ:
265                         case AADDQ:
266                         case AADCQ:
267                         case ASUBQ:
268                         case ASBBQ:
269                         case AINCQ:
270                         case ADECQ:
271                                 if(p->as != ACMPQ)
272                                         break;
273                         case AANDL:
274                         case AORL:
275                         case AXORL:
276                         case ANEGL:
277                         case AADDL:
278                         case AADCL:
279                         case ASUBL:
280                         case ASBBL:
281                         case AINCL:
282                         case ADECL:
283                                 excise(r);
284                                 break;
285                         case ASHLL:
286                         case ASHRL:
287                         case ASALL:
288                         case ASARL:
289                                 /* shift doesnt affect ZF when shift count is zero */
290                                 if(p1->from.type != D_CONST || p1->from.offset == 0)
291                                         break;
292                                 excise(r);
293                         }
294                         break;
295                 }
296         }
297         if(t)
298                 goto loop1;
299 }
300
301 void
302 excise(Reg *r)
303 {
304         Prog *p;
305
306         p = r->prog;
307         p->as = ANOP;
308         p->from = zprog.from;
309         p->to = zprog.to;
310 }
311
312 Reg*
313 uniqp(Reg *r)
314 {
315         Reg *r1;
316
317         r1 = r->p1;
318         if(r1 == R) {
319                 r1 = r->p2;
320                 if(r1 == R || r1->p2link != R)
321                         return R;
322         } else
323                 if(r->p2 != R)
324                         return R;
325         return r1;
326 }
327
328 Reg*
329 uniqs(Reg *r)
330 {
331         Reg *r1;
332
333         r1 = r->s1;
334         if(r1 == R) {
335                 r1 = r->s2;
336                 if(r1 == R)
337                         return R;
338         } else
339                 if(r->s2 != R)
340                         return R;
341         return r1;
342 }
343
344 int
345 regtyp(Adr *a)
346 {
347         int t;
348
349         t = a->type;
350         if(t >= D_AX && t <= D_R15)
351                 return 1;
352         if(t >= D_X0 && t <= D_X0+15)
353                 return 1;
354         return 0;
355 }
356
357 /*
358  * the idea is to substitute
359  * one register for another
360  * from one MOV to another
361  *      MOV     a, R0
362  *      ADD     b, R0   / no use of R1
363  *      MOV     R0, R1
364  * would be converted to
365  *      MOV     a, R1
366  *      ADD     b, R1
367  *      MOV     R1, R0
368  * hopefully, then the former or latter MOV
369  * will be eliminated by copy propagation.
370  */
371 int
372 subprop(Reg *r0)
373 {
374         Prog *p;
375         Adr *v1, *v2;
376         Reg *r;
377         int t;
378
379         p = r0->prog;
380         v1 = &p->from;
381         if(!regtyp(v1))
382                 return 0;
383         v2 = &p->to;
384         if(!regtyp(v2))
385                 return 0;
386         for(r=uniqp(r0); r!=R; r=uniqp(r)) {
387                 if(uniqs(r) == R)
388                         break;
389                 p = r->prog;
390                 switch(p->as) {
391                 case AIMULL:
392                 case AIMULQ:
393                 case AIMULW:
394                         if(p->to.type != D_NONE)
395                                 break;
396                 case ADIVB:
397                 case ADIVL:
398                 case ADIVQ:
399                 case ADIVW:
400                 case AIDIVB:
401                 case AIDIVL:
402                 case AIDIVQ:
403                 case AIDIVW:
404                 case AIMULB:
405                 case AMULB:
406                 case AMULL:
407                 case AMULQ:
408                 case AMULW:
409
410                 case ACWD:
411                 case ACDQ:
412                 case ACQO:
413
414                 case AREP:
415                 case AREPN:
416                 case ALOOP:
417                 case ALOOPEQ:
418                 case ALOOPNE:
419
420                 case ACALL:
421                         return 0;
422
423                 case AROLB:
424                 case AROLL:
425                 case AROLQ:
426                 case AROLW:
427                 case ARORB:
428                 case ARORL:
429                 case ARORQ:
430                 case ARORW:
431                 case ASALB:
432                 case ASALL:
433                 case ASALQ:
434                 case ASALW:
435                 case ASARB:
436                 case ASARL:
437                 case ASARQ:
438                 case ASARW:
439                 case ASHLB:
440                 case ASHLL:
441                 case ASHLQ:
442                 case ASHLW:
443                 case ASHRB:
444                 case ASHRL:
445                 case ASHRQ:
446                 case ASHRW:
447                         if(p->from.type == D_CX && v1->type == D_CX)
448                                 return 0;
449                         break;
450
451                 case AORL:
452                 case AORQ:
453                 case AANDL:
454                 case AANDQ:
455                 case AXORL:
456                 case AXORQ:
457                 case AADDL:
458                 case AADDQ:
459                 case AADCL:
460                 case AADCQ:
461
462                 case AADDSS:
463                 case AADDSD:
464                 case AMULSS:
465                 case AMULSD:
466                         /*
467                          * can swap when:
468                          *  ADD R2, R1
469                          *  MOV R1, R2
470                          * convert to:
471                          *  ADD R1, R2
472                          *  MOV R2, R1  / no use for R1
473                          */
474                         if(p->to.type == v1->type && p->from.type == v2->type){
475                                 copysub(&p->from, v2, v1, 1);
476                                 goto gotit;
477                         }
478                         break;
479
480                 case AMOVL:
481                 case ALEAL:
482                 case AMOVSL:
483                 case AMOVBLZX:
484                 case AMOVBLSX:
485                 case AMOVWLZX:
486                 case AMOVWLSX:
487                 case AMOVQL:
488
489                 case AMOVQ:
490                 case ALEAQ:
491                 case AMOVSQ:
492                 case AMOVBQZX:
493                 case AMOVBQSX:
494                 case AMOVWQZX:
495                 case AMOVWQSX:
496                 case AMOVLQZX:
497                 case AMOVLQSX:
498
499                 case AMOVSS:
500                 case AMOVSD:
501                         if(p->to.type == v1->type)
502                                 goto gotit;
503                         break;
504                 }
505                 if(copyau(&p->from, v2) ||
506                    copyau(&p->to, v2))
507                         break;
508                 if(copysub(&p->from, v1, v2, 0) ||
509                    copysub(&p->to, v1, v2, 0))
510                         break;
511         }
512         return 0;
513
514 gotit:
515         copysub(&p->to, v1, v2, 1);
516         if(debug['P']) {
517                 print("gotit: %D->%D\n%P", v1, v2, r->prog);
518                 if(p->from.type == v2->type)
519                         print(" excise");
520                 print("\n");
521         }
522         for(r=uniqs(r); r!=r0; r=uniqs(r)) {
523                 p = r->prog;
524                 copysub(&p->from, v1, v2, 1);
525                 copysub(&p->to, v1, v2, 1);
526                 if(debug['P'])
527                         print("%P\n", r->prog);
528         }
529         t = v1->type;
530         v1->type = v2->type;
531         v2->type = t;
532         if(debug['P'])
533                 print("%P last\n", r->prog);
534         return 1;
535 }
536
537 /*
538  * The idea is to remove redundant copies.
539  *      v1->v2  F=0
540  *      (use v2 s/v2/v1/)*
541  *      set v1  F=1
542  *      use v2  return fail
543  *      -----------------
544  *      v1->v2  F=0
545  *      (use v2 s/v2/v1/)*
546  *      set v1  F=1
547  *      set v2  return success
548  */
549 int
550 copyprop(Reg *r0)
551 {
552         Prog *p;
553         Adr *v1, *v2;
554         Reg *r;
555
556         p = r0->prog;
557         v1 = &p->from;
558         v2 = &p->to;
559         if(copyas(v1, v2))
560                 return 1;
561         for(r=firstr; r!=R; r=r->link)
562                 r->active = 0;
563         return copy1(v1, v2, r0->s1, 0);
564 }
565
566 int
567 copy1(Adr *v1, Adr *v2, Reg *r, int f)
568 {
569         int t;
570         Prog *p;
571
572         if(r->active) {
573                 if(debug['P'])
574                         print("act set; return 1\n");
575                 return 1;
576         }
577         r->active = 1;
578         if(debug['P'])
579                 print("copy %D->%D f=%d\n", v1, v2, f);
580         for(; r != R; r = r->s1) {
581                 p = r->prog;
582                 if(debug['P'])
583                         print("%P", p);
584                 if(!f && uniqp(r) == R) {
585                         f = 1;
586                         if(debug['P'])
587                                 print("; merge; f=%d", f);
588                 }
589                 t = copyu(p, v2, A);
590                 switch(t) {
591                 case 2: /* rar, cant split */
592                         if(debug['P'])
593                                 print("; %D rar; return 0\n", v2);
594                         return 0;
595
596                 case 3: /* set */
597                         if(debug['P'])
598                                 print("; %D set; return 1\n", v2);
599                         return 1;
600
601                 case 1: /* used, substitute */
602                 case 4: /* use and set */
603                         if(f) {
604                                 if(!debug['P'])
605                                         return 0;
606                                 if(t == 4)
607                                         print("; %D used+set and f=%d; return 0\n", v2, f);
608                                 else
609                                         print("; %D used and f=%d; return 0\n", v2, f);
610                                 return 0;
611                         }
612                         if(copyu(p, v2, v1)) {
613                                 if(debug['P'])
614                                         print("; sub fail; return 0\n");
615                                 return 0;
616                         }
617                         if(debug['P'])
618                                 print("; sub %D/%D", v2, v1);
619                         if(t == 4) {
620                                 if(debug['P'])
621                                         print("; %D used+set; return 1\n", v2);
622                                 return 1;
623                         }
624                         break;
625                 }
626                 if(!f) {
627                         t = copyu(p, v1, A);
628                         if(!f && (t == 2 || t == 3 || t == 4)) {
629                                 f = 1;
630                                 if(debug['P'])
631                                         print("; %D set and !f; f=%d", v1, f);
632                         }
633                 }
634                 if(debug['P'])
635                         print("\n");
636                 if(r->s2)
637                         if(!copy1(v1, v2, r->s2, f))
638                                 return 0;
639         }
640         return 1;
641 }
642
643 /*
644  * return
645  * 1 if v only used (and substitute),
646  * 2 if read-alter-rewrite
647  * 3 if set
648  * 4 if set and used
649  * 0 otherwise (not touched)
650  */
651 int
652 copyu(Prog *p, Adr *v, Adr *s)
653 {
654
655         switch(p->as) {
656
657         default:
658                 if(debug['P'])
659                         print("unknown op %A\n", p->as);
660                 /* SBBL; ADCL; FLD1; SAHF */
661                 return 2;
662
663
664         case ANEGB:
665         case ANEGW:
666         case ANEGL:
667         case ANEGQ:
668         case ANOTB:
669         case ANOTW:
670         case ANOTL:
671         case ANOTQ:
672                 if(copyas(&p->to, v))
673                         return 2;
674                 break;
675
676         case ALEAL:     /* lhs addr, rhs store */
677         case ALEAQ:
678                 if(copyas(&p->from, v))
679                         return 2;
680
681
682         case ANOP:      /* rhs store */
683         case AMOVL:
684         case AMOVQ:
685         case AMOVBLSX:
686         case AMOVBLZX:
687         case AMOVBQSX:
688         case AMOVBQZX:
689         case AMOVLQSX:
690         case AMOVLQZX:
691         case AMOVWLSX:
692         case AMOVWLZX:
693         case AMOVWQSX:
694         case AMOVWQZX:
695         case AMOVQL:
696
697         case AMOVSS:
698         case AMOVSD:
699         case ACVTSD2SL:
700         case ACVTSD2SQ:
701         case ACVTSD2SS:
702         case ACVTSL2SD:
703         case ACVTSL2SS:
704         case ACVTSQ2SD:
705         case ACVTSQ2SS:
706         case ACVTSS2SD:
707         case ACVTSS2SL:
708         case ACVTSS2SQ:
709         case ACVTTSD2SL:
710         case ACVTTSD2SQ:
711         case ACVTTSS2SL:
712         case ACVTTSS2SQ:
713                 if(copyas(&p->to, v)) {
714                         if(s != A)
715                                 return copysub(&p->from, v, s, 1);
716                         if(copyau(&p->from, v))
717                                 return 4;
718                         return 3;
719                 }
720                 goto caseread;
721
722         case AROLB:
723         case AROLL:
724         case AROLQ:
725         case AROLW:
726         case ARORB:
727         case ARORL:
728         case ARORQ:
729         case ARORW:
730         case ASALB:
731         case ASALL:
732         case ASALQ:
733         case ASALW:
734         case ASARB:
735         case ASARL:
736         case ASARQ:
737         case ASARW:
738         case ASHLB:
739         case ASHLL:
740         case ASHLQ:
741         case ASHLW:
742         case ASHRB:
743         case ASHRL:
744         case ASHRQ:
745         case ASHRW:
746                 if(copyas(&p->to, v))
747                         return 2;
748                 if(copyas(&p->from, v))
749                         if(p->from.type == D_CX)
750                                 return 2;
751                 goto caseread;
752
753         case AADDB:     /* rhs rar */
754         case AADDL:
755         case AADDQ:
756         case AADDW:
757         case AANDB:
758         case AANDL:
759         case AANDQ:
760         case AANDW:
761         case ADECL:
762         case ADECQ:
763         case ADECW:
764         case AINCL:
765         case AINCQ:
766         case AINCW:
767         case ASUBB:
768         case ASUBL:
769         case ASUBQ:
770         case ASUBW:
771         case AORB:
772         case AORL:
773         case AORQ:
774         case AORW:
775         case AXORB:
776         case AXORL:
777         case AXORQ:
778         case AXORW:
779         case AMOVB:
780         case AMOVW:
781
782         case AADDSD:
783         case AADDSS:
784         case ACMPSD:
785         case ACMPSS:
786         case ADIVSD:
787         case ADIVSS:
788         case AMAXSD:
789         case AMAXSS:
790         case AMINSD:
791         case AMINSS:
792         case AMULSD:
793         case AMULSS:
794         case ARCPSS:
795         case ARSQRTSS:
796         case ASQRTSD:
797         case ASQRTSS:
798         case ASUBSD:
799         case ASUBSS:
800         case AXORPD:
801                 if(copyas(&p->to, v))
802                         return 2;
803                 goto caseread;
804
805         case ACMPL:     /* read only */
806         case ACMPW:
807         case ACMPB:
808         case ACMPQ:
809
810         case ACOMISD:
811         case ACOMISS:
812         case AUCOMISD:
813         case AUCOMISS:
814         caseread:
815                 if(s != A) {
816                         if(copysub(&p->from, v, s, 1))
817                                 return 1;
818                         return copysub(&p->to, v, s, 1);
819                 }
820                 if(copyau(&p->from, v))
821                         return 1;
822                 if(copyau(&p->to, v))
823                         return 1;
824                 break;
825
826         case AJGE:      /* no reference */
827         case AJNE:
828         case AJLE:
829         case AJEQ:
830         case AJHI:
831         case AJLS:
832         case AJMI:
833         case AJPL:
834         case AJGT:
835         case AJLT:
836         case AJCC:
837         case AJCS:
838
839         case AADJSP:
840         case AWAIT:
841         case ACLD:
842                 break;
843
844         case AIMULL:
845         case AIMULQ:
846         case AIMULW:
847                 if(p->to.type != D_NONE) {
848                         if(copyas(&p->to, v))
849                                 return 2;
850                         goto caseread;
851                 }
852
853         case ADIVB:
854         case ADIVL:
855         case ADIVQ:
856         case ADIVW:
857         case AIDIVB:
858         case AIDIVL:
859         case AIDIVQ:
860         case AIDIVW:
861         case AIMULB:
862         case AMULB:
863         case AMULL:
864         case AMULQ:
865         case AMULW:
866
867         case ACWD:
868         case ACDQ:
869         case ACQO:
870                 if(v->type == D_AX || v->type == D_DX)
871                         return 2;
872                 goto caseread;
873
874         case AMOVSL:
875         case AMOVSQ:
876         case AREP:
877         case AREPN:
878                 if(v->type == D_CX || v->type == D_DI || v->type == D_SI)
879                         return 2;
880                 goto caseread;
881
882         case AJMP:      /* funny */
883                 if(s != A) {
884                         if(copysub(&p->to, v, s, 1))
885                                 return 1;
886                         return 0;
887                 }
888                 if(copyau(&p->to, v))
889                         return 1;
890                 return 0;
891
892         case ARET:      /* funny */
893                 if(v->type == REGRET || v->type == FREGRET)
894                         return 2;
895                 if(s != A)
896                         return 1;
897                 return 3;
898
899         case ACALL:     /* funny */
900                 if(REGEXT && v->type <= REGEXT && v->type > exregoffset)
901                         return 2;
902                 if(REGARG && v->type == REGARG)
903                         return 2;
904
905                 if(s != A) {
906                         if(copysub(&p->to, v, s, 1))
907                                 return 1;
908                         return 0;
909                 }
910                 if(copyau(&p->to, v))
911                         return 4;
912                 return 3;
913
914         case ATEXT:     /* funny */
915                 if(REGARG && v->type == REGARG)
916                         return 3;
917                 return 0;
918         }
919         return 0;
920 }
921
922 /*
923  * direct reference,
924  * could be set/use depending on
925  * semantics
926  */
927 int
928 copyas(Adr *a, Adr *v)
929 {
930         if(a->type != v->type)
931                 return 0;
932         if(regtyp(v))
933                 return 1;
934         if(v->type == D_AUTO || v->type == D_PARAM)
935                 if(v->offset == a->offset)
936                         return 1;
937         return 0;
938 }
939
940 /*
941  * either direct or indirect
942  */
943 int
944 copyau(Adr *a, Adr *v)
945 {
946
947         if(copyas(a, v))
948                 return 1;
949         if(regtyp(v)) {
950                 if(a->type-D_INDIR == v->type)
951                         return 1;
952                 if(a->index == v->type)
953                         return 1;
954         }
955         return 0;
956 }
957
958 /*
959  * substitute s for v in a
960  * return failure to substitute
961  */
962 int
963 copysub(Adr *a, Adr *v, Adr *s, int f)
964 {
965         int t;
966
967         if(copyas(a, v)) {
968                 t = s->type;
969                 if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
970                         if(f)
971                                 a->type = t;
972                 }
973                 return 0;
974         }
975         if(regtyp(v)) {
976                 t = v->type;
977                 if(a->type == t+D_INDIR) {
978                         if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
979                                 return 1;       /* can't use BP-base with index */
980                         if(f)
981                                 a->type = s->type+D_INDIR;
982 //                      return 0;
983                 }
984                 if(a->index == t) {
985                         if(f)
986                                 a->index = s->type;
987                         return 0;
988                 }
989                 return 0;
990         }
991         return 0;
992 }