github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/6c/peep.c (about)

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