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