github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/6c/txt.c (about)

     1  // Inferno utils/6c/txt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.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  int thechar = '6';
    34  char *thestring = "amd64";
    35  
    36  LinkArch	*thelinkarch = &linkamd64;
    37  
    38  void
    39  linkarchinit(void)
    40  {
    41  	if(strcmp(getgoarch(), "amd64p32") == 0)
    42  		thelinkarch = &linkamd64p32;
    43  }
    44  
    45  void
    46  ginit(void)
    47  {
    48  	int i;
    49  	Type *t;
    50  
    51  	dodefine("_64BITREG");
    52  	if(ewidth[TIND] == 8)
    53  		dodefine("_64BIT");
    54  	listinit();
    55  	nstring = 0;
    56  	mnstring = 0;
    57  	nrathole = 0;
    58  	pc = 0;
    59  	breakpc = -1;
    60  	continpc = -1;
    61  	cases = C;
    62  	lastp = P;
    63  	tfield = types[TINT];
    64  
    65  	typeword = typechlvp;
    66  	typecmplx = typesu;
    67  
    68  	/* TO DO */
    69  	memmove(typechlpv, typechlp, sizeof(typechlpv));
    70  	typechlpv[TVLONG] = 1;
    71  	typechlpv[TUVLONG] = 1;
    72  
    73  	zprog.link = P;
    74  	zprog.as = AGOK;
    75  	zprog.from.type = D_NONE;
    76  	zprog.from.index = D_NONE;
    77  	zprog.from.scale = 0;
    78  	zprog.to = zprog.from;
    79  
    80  	lregnode.op = OREGISTER;
    81  	lregnode.class = CEXREG;
    82  	lregnode.reg = REGTMP;
    83  	lregnode.complex = 0;
    84  	lregnode.addable = 11;
    85  	lregnode.type = types[TLONG];
    86  
    87  	qregnode = lregnode;
    88  	qregnode.type = types[TVLONG];
    89  
    90  	constnode.op = OCONST;
    91  	constnode.class = CXXX;
    92  	constnode.complex = 0;
    93  	constnode.addable = 20;
    94  	constnode.type = types[TLONG];
    95  
    96  	vconstnode = constnode;
    97  	vconstnode.type = types[TVLONG];
    98  
    99  	fconstnode.op = OCONST;
   100  	fconstnode.class = CXXX;
   101  	fconstnode.complex = 0;
   102  	fconstnode.addable = 20;
   103  	fconstnode.type = types[TDOUBLE];
   104  
   105  	nodsafe = new(ONAME, Z, Z);
   106  	nodsafe->sym = slookup(".safe");
   107  	nodsafe->type = types[TINT];
   108  	nodsafe->etype = types[TINT]->etype;
   109  	nodsafe->class = CAUTO;
   110  	complex(nodsafe);
   111  
   112  	t = typ(TARRAY, types[TCHAR]);
   113  	symrathole = slookup(".rathole");
   114  	symrathole->class = CGLOBL;
   115  	symrathole->type = t;
   116  
   117  	nodrat = new(ONAME, Z, Z);
   118  	nodrat->sym = symrathole;
   119  	nodrat->type = types[TIND];
   120  	nodrat->etype = TVOID;
   121  	nodrat->class = CGLOBL;
   122  	complex(nodrat);
   123  	nodrat->type = t;
   124  
   125  	nodret = new(ONAME, Z, Z);
   126  	nodret->sym = slookup(".ret");
   127  	nodret->type = types[TIND];
   128  	nodret->etype = TIND;
   129  	nodret->class = CPARAM;
   130  	nodret = new(OIND, nodret, Z);
   131  	complex(nodret);
   132  
   133  	if(0)
   134  		com64init();
   135  
   136  	for(i=0; i<nelem(reg); i++) {
   137  		reg[i] = 1;
   138  		if(i >= D_AX && i <= D_R15 && i != D_SP)
   139  			reg[i] = 0;
   140  		if(i >= D_X0 && i <= D_X7)
   141  			reg[i] = 0;
   142  	}
   143  	if(nacl) {
   144  		reg[D_BP] = 1;
   145  		reg[D_R15] = 1;
   146  	}
   147  }
   148  
   149  void
   150  gclean(void)
   151  {
   152  	int i;
   153  	Sym *s;
   154  
   155  	reg[D_SP]--;
   156  	if(nacl) {
   157  		reg[D_BP]--;
   158  		reg[D_R15]--;
   159  	}
   160  	for(i=D_AX; i<=D_R15; i++)
   161  		if(reg[i])
   162  			diag(Z, "reg %R left allocated", i);
   163  	for(i=D_X0; i<=D_X7; i++)
   164  		if(reg[i])
   165  			diag(Z, "reg %R left allocated", i);
   166  	while(mnstring)
   167  		outstring("", 1L);
   168  	symstring->type->width = nstring;
   169  	symrathole->type->width = nrathole;
   170  	for(i=0; i<NHASH; i++)
   171  	for(s = hash[i]; s != S; s = s->link) {
   172  		if(s->type == T)
   173  			continue;
   174  		if(s->type->width == 0)
   175  			continue;
   176  		if(s->class != CGLOBL && s->class != CSTATIC)
   177  			continue;
   178  		if(s->type == types[TENUM])
   179  			continue;
   180  		gpseudo(AGLOBL, s, nodconst(s->type->width));
   181  	}
   182  	nextpc();
   183  	p->as = AEND;
   184  	outcode();
   185  }
   186  
   187  void
   188  nextpc(void)
   189  {
   190  	Plist *pl;
   191  
   192  	p = alloc(sizeof(*p));
   193  	*p = zprog;
   194  	p->lineno = nearln;
   195  	p->pc = pc;
   196  	pc++;
   197  	if(lastp == nil) {
   198  		pl = linknewplist(ctxt);
   199  		pl->firstpc = p;
   200  	} else
   201  		lastp->link = p;
   202  	lastp = p;
   203  }
   204  
   205  void
   206  gargs(Node *n, Node *tn1, Node *tn2)
   207  {
   208  	int32 regs;
   209  	Node fnxargs[20], *fnxp;
   210  
   211  	regs = cursafe;
   212  
   213  	fnxp = fnxargs;
   214  	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
   215  
   216  	curarg = 0;
   217  	fnxp = fnxargs;
   218  	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
   219  
   220  	cursafe = regs;
   221  }
   222  
   223  int
   224  nareg(void)
   225  {
   226  	int i, n;
   227  
   228  	n = 0;
   229  	for(i=D_AX; i<=D_R15; i++)
   230  		if(reg[i] == 0)
   231  			n++;
   232  	return n;
   233  }
   234  
   235  void
   236  garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
   237  {
   238  	Node nod;
   239  
   240  	if(n == Z)
   241  		return;
   242  	if(n->op == OLIST) {
   243  		garg1(n->left, tn1, tn2, f, fnxp);
   244  		garg1(n->right, tn1, tn2, f, fnxp);
   245  		return;
   246  	}
   247  	if(f == 0) {
   248  		if(n->complex >= FNX) {
   249  			regsalloc(*fnxp, n);
   250  			nod = znode;
   251  			nod.op = OAS;
   252  			nod.left = *fnxp;
   253  			nod.right = n;
   254  			nod.type = n->type;
   255  			cgen(&nod, Z);
   256  			(*fnxp)++;
   257  		}
   258  		return;
   259  	}
   260  	if(typesu[n->type->etype]) {
   261  		regaalloc(tn2, n);
   262  		if(n->complex >= FNX) {
   263  			sugen(*fnxp, tn2, n->type->width);
   264  			(*fnxp)++;
   265  		} else
   266  			sugen(n, tn2, n->type->width);
   267  		return;
   268  	}
   269  	if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {
   270  		regaalloc1(tn1, n);
   271  		if(n->complex >= FNX) {
   272  			cgen(*fnxp, tn1);
   273  			(*fnxp)++;
   274  		} else
   275  			cgen(n, tn1);
   276  		return;
   277  	}
   278  	if(vconst(n) == 0) {
   279  		regaalloc(tn2, n);
   280  		gmove(n, tn2);
   281  		return;
   282  	}
   283  	regalloc(tn1, n, Z);
   284  	if(n->complex >= FNX) {
   285  		cgen(*fnxp, tn1);
   286  		(*fnxp)++;
   287  	} else
   288  		cgen(n, tn1);
   289  	regaalloc(tn2, n);
   290  	gmove(tn1, tn2);
   291  	regfree(tn1);
   292  }
   293  
   294  Node*
   295  nodgconst(vlong v, Type *t)
   296  {
   297  	if(!typev[t->etype])
   298  		return nodconst((int32)v);
   299  	vconstnode.vconst = v;
   300  	return &vconstnode;
   301  }
   302  
   303  Node*
   304  nodconst(int32 v)
   305  {
   306  	constnode.vconst = v;
   307  	return &constnode;
   308  }
   309  
   310  Node*
   311  nodfconst(double d)
   312  {
   313  	fconstnode.fconst = d;
   314  	return &fconstnode;
   315  }
   316  
   317  int
   318  isreg(Node *n, int r)
   319  {
   320  
   321  	if(n->op == OREGISTER)
   322  		if(n->reg == r)
   323  			return 1;
   324  	return 0;
   325  }
   326  
   327  int
   328  nodreg(Node *n, Node *nn, int r)
   329  {
   330  	int et;
   331  
   332  	*n = qregnode;
   333  	n->reg = r;
   334  	if(nn != Z){
   335  		et = nn->type->etype;
   336  		if(!typefd[et] && nn->type->width <= SZ_LONG && 0)
   337  			n->type = typeu[et]? types[TUINT]: types[TINT];
   338  		else
   339  			n->type = nn->type;
   340  //print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]);
   341  		n->lineno = nn->lineno;
   342  	}
   343  	if(reg[r] == 0)
   344  		return 0;
   345  	if(nn != Z) {
   346  		if(nn->op == OREGISTER)
   347  		if(nn->reg == r)
   348  			return 0;
   349  	}
   350  	return 1;
   351  }
   352  
   353  void
   354  regret(Node *n, Node *nn)
   355  {
   356  	int r;
   357  
   358  	r = REGRET;
   359  	if(typefd[nn->type->etype])
   360  		r = FREGRET;
   361  	nodreg(n, nn, r);
   362  	reg[r]++;
   363  }
   364  
   365  void
   366  regalloc(Node *n, Node *tn, Node *o)
   367  {
   368  	int i;
   369  
   370  	switch(tn->type->etype) {
   371  	case TCHAR:
   372  	case TUCHAR:
   373  	case TSHORT:
   374  	case TUSHORT:
   375  	case TINT:
   376  	case TUINT:
   377  	case TLONG:
   378  	case TULONG:
   379  	case TVLONG:
   380  	case TUVLONG:
   381  	case TIND:
   382  		if(o != Z && o->op == OREGISTER) {
   383  			i = o->reg;
   384  			if(i >= D_AX && i <= D_R15)
   385  				goto out;
   386  		}
   387  		for(i=D_AX; i<=D_R15; i++)
   388  			if(reg[i] == 0)
   389  				goto out;
   390  		diag(tn, "out of fixed registers");
   391  		goto err;
   392  
   393  	case TFLOAT:
   394  	case TDOUBLE:
   395  		if(o != Z && o->op == OREGISTER) {
   396  			i = o->reg;
   397  			if(i >= D_X0 && i <= D_X7)
   398  				goto out;
   399  		}
   400  		for(i=D_X0; i<=D_X7; i++)
   401  			if(reg[i] == 0)
   402  				goto out;
   403  		diag(tn, "out of float registers");
   404  		goto out;
   405  	}
   406  	diag(tn, "unknown type in regalloc: %T", tn->type);
   407  err:
   408  	i = 0;
   409  out:
   410  	if(i)
   411  		reg[i]++;
   412  	nodreg(n, tn, i);
   413  }
   414  
   415  void
   416  regialloc(Node *n, Node *tn, Node *o)
   417  {
   418  	Node nod;
   419  
   420  	nod = *tn;
   421  	nod.type = types[TIND];
   422  	regalloc(n, &nod, o);
   423  }
   424  
   425  void
   426  regfree(Node *n)
   427  {
   428  	int i;
   429  
   430  	i = 0;
   431  	if(n->op != OREGISTER && n->op != OINDREG)
   432  		goto err;
   433  	i = n->reg;
   434  	if(i < 0 || i >= nelem(reg))
   435  		goto err;
   436  	if(reg[i] <= 0)
   437  		goto err;
   438  	reg[i]--;
   439  	return;
   440  err:
   441  	diag(n, "error in regfree: %R", i);
   442  }
   443  
   444  void
   445  regsalloc(Node *n, Node *nn)
   446  {
   447  	cursafe = align(cursafe, nn->type, Aaut3, nil);
   448  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   449  	*n = *nodsafe;
   450  	n->xoffset = -(stkoff + cursafe);
   451  	n->type = nn->type;
   452  	n->etype = nn->type->etype;
   453  	n->lineno = nn->lineno;
   454  }
   455  
   456  void
   457  regaalloc1(Node *n, Node *nn)
   458  {
   459  	if(REGARG < 0) {
   460  		fatal(n, "regaalloc1 and REGARG<0");
   461  		return;
   462  	}
   463  	nodreg(n, nn, REGARG);
   464  	reg[(uchar)REGARG]++;
   465  	curarg = align(curarg, nn->type, Aarg1, nil);
   466  	curarg = align(curarg, nn->type, Aarg2, nil);
   467  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   468  }
   469  
   470  void
   471  regaalloc(Node *n, Node *nn)
   472  {
   473  	curarg = align(curarg, nn->type, Aarg1, nil);
   474  	*n = *nn;
   475  	n->op = OINDREG;
   476  	n->reg = REGSP;
   477  	n->xoffset = curarg;
   478  	n->complex = 0;
   479  	n->addable = 20;
   480  	curarg = align(curarg, nn->type, Aarg2, nil);
   481  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   482  }
   483  
   484  void
   485  regind(Node *n, Node *nn)
   486  {
   487  
   488  	if(n->op != OREGISTER) {
   489  		diag(n, "regind not OREGISTER");
   490  		return;
   491  	}
   492  	n->op = OINDREG;
   493  	n->type = nn->type;
   494  }
   495  
   496  void
   497  naddr(Node *n, Addr *a)
   498  {
   499  	int32 v;
   500  
   501  	a->type = D_NONE;
   502  	if(n == Z)
   503  		return;
   504  	switch(n->op) {
   505  	default:
   506  	bad:
   507  		diag(n, "bad in naddr: %O %D", n->op, a);
   508  		break;
   509  
   510  	case OREGISTER:
   511  		a->type = n->reg;
   512  		a->sym = nil;
   513  		break;
   514  
   515  	case OEXREG:
   516  		a->type = D_INDIR + D_TLS;
   517  		a->offset = n->reg - 1;
   518  		break;
   519  
   520  	case OIND:
   521  		naddr(n->left, a);
   522  		if(a->type >= D_AX && a->type <= D_R15)
   523  			a->type += D_INDIR;
   524  		else
   525  		if(a->type == D_CONST)
   526  			a->type = D_NONE+D_INDIR;
   527  		else
   528  		if(a->type == D_ADDR) {
   529  			a->type = a->index;
   530  			a->index = D_NONE;
   531  		} else
   532  			goto bad;
   533  		break;
   534  
   535  	case OINDEX:
   536  		a->type = idx.ptr;
   537  		if(n->left->op == OADDR || n->left->op == OCONST)
   538  			naddr(n->left, a);
   539  		if(a->type >= D_AX && a->type <= D_R15)
   540  			a->type += D_INDIR;
   541  		else
   542  		if(a->type == D_CONST)
   543  			a->type = D_NONE+D_INDIR;
   544  		else
   545  		if(a->type == D_ADDR) {
   546  			a->type = a->index;
   547  			a->index = D_NONE;
   548  		} else
   549  			goto bad;
   550  		a->index = idx.reg;
   551  		a->scale = n->scale;
   552  		a->offset += n->xoffset;
   553  		break;
   554  
   555  	case OINDREG:
   556  		a->type = n->reg+D_INDIR;
   557  		a->sym = nil;
   558  		a->offset = n->xoffset;
   559  		break;
   560  
   561  	case ONAME:
   562  		a->etype = n->etype;
   563  		a->type = D_STATIC;
   564  		a->sym = linksym(n->sym);
   565  		a->offset = n->xoffset;
   566  		if(n->class == CSTATIC)
   567  			break;
   568  		if(n->class == CEXTERN || n->class == CGLOBL) {
   569  			a->type = D_EXTERN;
   570  			break;
   571  		}
   572  		if(n->class == CAUTO) {
   573  			a->type = D_AUTO;
   574  			break;
   575  		}
   576  		if(n->class == CPARAM) {
   577  			a->type = D_PARAM;
   578  			break;
   579  		}
   580  		goto bad;
   581  
   582  	case OCONST:
   583  		if(typefd[n->type->etype]) {
   584  			a->type = D_FCONST;
   585  			a->u.dval = n->fconst;
   586  			break;
   587  		}
   588  		a->sym = nil;
   589  		a->type = D_CONST;
   590  		if(typev[n->type->etype] || (n->type->etype == TIND && ewidth[TIND] == 8))
   591  			a->offset = n->vconst;
   592  		else
   593  			a->offset = convvtox(n->vconst, typeu[n->type->etype]? TULONG: TLONG);
   594  		break;
   595  
   596  	case OADDR:
   597  		naddr(n->left, a);
   598  		if(a->type >= D_INDIR) {
   599  			a->type -= D_INDIR;
   600  			break;
   601  		}
   602  		if(a->type == D_EXTERN || a->type == D_STATIC ||
   603  		   a->type == D_AUTO || a->type == D_PARAM)
   604  			if(a->index == D_NONE) {
   605  				a->index = a->type;
   606  				a->type = D_ADDR;
   607  				break;
   608  			}
   609  		goto bad;
   610  
   611  	case OADD:
   612  		if(n->right->op == OCONST) {
   613  			v = n->right->vconst;
   614  			naddr(n->left, a);
   615  		} else
   616  		if(n->left->op == OCONST) {
   617  			v = n->left->vconst;
   618  			naddr(n->right, a);
   619  		} else
   620  			goto bad;
   621  		a->offset += v;
   622  		break;
   623  
   624  	}
   625  }
   626  
   627  void
   628  gcmp(int op, Node *n, vlong val)
   629  {
   630  	Node *cn, nod;
   631  
   632  	cn = nodgconst(val, n->type);
   633  	if(!immconst(cn)){
   634  		regalloc(&nod, n, Z);
   635  		gmove(cn, &nod);
   636  		gopcode(op, n->type, n, &nod);
   637  		regfree(&nod);
   638  	}else
   639  		gopcode(op, n->type, n, cn);
   640  }
   641  
   642  #define	CASE(a,b)	((a<<8)|(b<<0))
   643  
   644  void
   645  gmove(Node *f, Node *t)
   646  {
   647  	int ft, tt, t64, a;
   648  	Node nod, nod1, nod2, nod3;
   649  	Prog *p1, *p2;
   650  
   651  	ft = f->type->etype;
   652  	tt = t->type->etype;
   653  	if(ewidth[TIND] == 4) {
   654  		if(ft == TIND)
   655  			ft = TUINT;
   656  		if(tt == TIND)
   657  			tt = TUINT;
   658  	}
   659  	t64 = tt == TVLONG || tt == TUVLONG || tt == TIND;
   660  	if(debug['M'])
   661  		print("gop: %O %O[%s],%O[%s]\n", OAS,
   662  			f->op, tnames[ft], t->op, tnames[tt]);
   663  	if(typefd[ft] && f->op == OCONST) {
   664  		/* TO DO: pick up special constants, possibly preloaded */
   665  		if(f->fconst == 0.0){
   666  			regalloc(&nod, t, t);
   667  			gins(AXORPD, &nod, &nod);
   668  			gmove(&nod, t);
   669  			regfree(&nod);
   670  			return;
   671  		}
   672  	}
   673  /*
   674   * load
   675   */
   676  	if(ft == TVLONG || ft == TUVLONG)
   677  	if(f->op == OCONST)
   678  	if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
   679  	if(t->op != OREGISTER) {
   680  		regalloc(&nod, f, Z);
   681  		gmove(f, &nod);
   682  		gmove(&nod, t);
   683  		regfree(&nod);
   684  		return;
   685  	}
   686  
   687  	if(f->op == ONAME || f->op == OINDREG ||
   688  	   f->op == OIND || f->op == OINDEX)
   689  	switch(ft) {
   690  	case TCHAR:
   691  		a = AMOVBLSX;
   692  		if(t64)
   693  			a = AMOVBQSX;
   694  		goto ld;
   695  	case TUCHAR:
   696  		a = AMOVBLZX;
   697  		if(t64)
   698  			a = AMOVBQZX;
   699  		goto ld;
   700  	case TSHORT:
   701  		a = AMOVWLSX;
   702  		if(t64)
   703  			a = AMOVWQSX;
   704  		goto ld;
   705  	case TUSHORT:
   706  		a = AMOVWLZX;
   707  		if(t64)
   708  			a = AMOVWQZX;
   709  		goto ld;
   710  	case TINT:
   711  	case TLONG:
   712  		if(typefd[tt]) {
   713  			regalloc(&nod, t, t);
   714  			if(tt == TDOUBLE)
   715  				a = ACVTSL2SD;
   716  			else
   717  				a = ACVTSL2SS;
   718  			gins(a, f, &nod);
   719  			gmove(&nod, t);
   720  			regfree(&nod);
   721  			return;
   722  		}
   723  		a = AMOVL;
   724  		if(t64)
   725  			a = AMOVLQSX;
   726  		goto ld;
   727  	case TUINT:
   728  	case TULONG:
   729  		a = AMOVL;
   730  		if(t64)
   731  			a = AMOVLQZX;	/* could probably use plain MOVL */
   732  		goto ld;
   733  	case TVLONG:
   734  		if(typefd[tt]) {
   735  			regalloc(&nod, t, t);
   736  			if(tt == TDOUBLE)
   737  				a = ACVTSQ2SD;
   738  			else
   739  				a = ACVTSQ2SS;
   740  			gins(a, f, &nod);
   741  			gmove(&nod, t);
   742  			regfree(&nod);
   743  			return;
   744  		}
   745  	case TUVLONG:
   746  		a = AMOVQ;
   747  		goto ld;
   748  	case TIND:
   749  		a = AMOVQ;
   750  		if(ewidth[TIND] == 4)
   751  			a = AMOVL;
   752  
   753  	ld:
   754  		regalloc(&nod, f, t);
   755  		nod.type = t64? types[TVLONG]: types[TINT];
   756  		gins(a, f, &nod);
   757  		gmove(&nod, t);
   758  		regfree(&nod);
   759  		return;
   760  
   761  	case TFLOAT:
   762  		a = AMOVSS;
   763  		goto fld;
   764  	case TDOUBLE:
   765  		a = AMOVSD;
   766  	fld:
   767  		regalloc(&nod, f, t);
   768  		if(tt != TDOUBLE && tt != TFLOAT){	/* TO DO: why is this here */
   769  			prtree(f, "odd tree");
   770  			nod.type = t64? types[TVLONG]: types[TINT];
   771  		}
   772  		gins(a, f, &nod);
   773  		gmove(&nod, t);
   774  		regfree(&nod);
   775  		return;
   776  	}
   777  
   778  /*
   779   * store
   780   */
   781  	if(t->op == ONAME || t->op == OINDREG ||
   782  	   t->op == OIND || t->op == OINDEX)
   783  	switch(tt) {
   784  	case TCHAR:
   785  	case TUCHAR:
   786  		a = AMOVB;	goto st;
   787  	case TSHORT:
   788  	case TUSHORT:
   789  		a = AMOVW;	goto st;
   790  	case TINT:
   791  	case TUINT:
   792  	case TLONG:
   793  	case TULONG:
   794  		a = AMOVL;	goto st;
   795  	case TVLONG:
   796  	case TUVLONG:
   797  	case TIND:
   798  		a = AMOVQ;	goto st;
   799  
   800  	st:
   801  		if(f->op == OCONST) {
   802  			gins(a, f, t);
   803  			return;
   804  		}
   805  	fst:
   806  		regalloc(&nod, t, f);
   807  		gmove(f, &nod);
   808  		gins(a, &nod, t);
   809  		regfree(&nod);
   810  		return;
   811  
   812  	case TFLOAT:
   813  		a = AMOVSS;
   814  		goto fst;
   815  	case TDOUBLE:
   816  		a = AMOVSD;
   817  		goto fst;
   818  	}
   819  
   820  /*
   821   * convert
   822   */
   823  	switch(CASE(ft,tt)) {
   824  	default:
   825  /*
   826   * integer to integer
   827   ********
   828  		a = AGOK;	break;
   829  
   830  	case CASE(	TCHAR,	TCHAR):
   831  	case CASE(	TUCHAR,	TCHAR):
   832  	case CASE(	TSHORT,	TCHAR):
   833  	case CASE(	TUSHORT,TCHAR):
   834  	case CASE(	TINT,	TCHAR):
   835  	case CASE(	TUINT,	TCHAR):
   836  	case CASE(	TLONG,	TCHAR):
   837  	case CASE(	TULONG,	TCHAR):
   838  
   839  	case CASE(	TCHAR,	TUCHAR):
   840  	case CASE(	TUCHAR,	TUCHAR):
   841  	case CASE(	TSHORT,	TUCHAR):
   842  	case CASE(	TUSHORT,TUCHAR):
   843  	case CASE(	TINT,	TUCHAR):
   844  	case CASE(	TUINT,	TUCHAR):
   845  	case CASE(	TLONG,	TUCHAR):
   846  	case CASE(	TULONG,	TUCHAR):
   847  
   848  	case CASE(	TSHORT,	TSHORT):
   849  	case CASE(	TUSHORT,TSHORT):
   850  	case CASE(	TINT,	TSHORT):
   851  	case CASE(	TUINT,	TSHORT):
   852  	case CASE(	TLONG,	TSHORT):
   853  	case CASE(	TULONG,	TSHORT):
   854  
   855  	case CASE(	TSHORT,	TUSHORT):
   856  	case CASE(	TUSHORT,TUSHORT):
   857  	case CASE(	TINT,	TUSHORT):
   858  	case CASE(	TUINT,	TUSHORT):
   859  	case CASE(	TLONG,	TUSHORT):
   860  	case CASE(	TULONG,	TUSHORT):
   861  
   862  	case CASE(	TINT,	TINT):
   863  	case CASE(	TUINT,	TINT):
   864  	case CASE(	TLONG,	TINT):
   865  	case CASE(	TULONG,	TINT):
   866  
   867  	case CASE(	TINT,	TUINT):
   868  	case CASE(	TUINT,	TUINT):
   869  	case CASE(	TLONG,	TUINT):
   870  	case CASE(	TULONG,	TUINT):
   871   *****/
   872  		a = AMOVL;
   873  		break;
   874  
   875  	case CASE(	TINT,	TIND):
   876  	case CASE(	TINT,	TVLONG):
   877  	case CASE(	TINT,	TUVLONG):
   878  	case CASE(	TLONG,	TIND):
   879  	case CASE(	TLONG,	TVLONG):
   880  	case CASE(	TLONG,	TUVLONG):
   881  		a = AMOVLQSX;
   882  		if(f->op == OCONST) {
   883  			f->vconst &= (uvlong)0xffffffffU;
   884  			if(f->vconst & 0x80000000)
   885  				f->vconst |= (vlong)0xffffffff << 32;
   886  			a = AMOVQ;
   887  		}
   888  		break;
   889  
   890  	case CASE(	TUINT,	TIND):
   891  	case CASE(	TUINT,	TVLONG):
   892  	case CASE(	TUINT,	TUVLONG):
   893  	case CASE(	TULONG,	TVLONG):
   894  	case CASE(	TULONG,	TUVLONG):
   895  	case CASE(	TULONG,	TIND):
   896  		a = AMOVLQZX;
   897  		if(f->op == OCONST) {
   898  			f->vconst &= (uvlong)0xffffffffU;
   899  			a = AMOVQ;
   900  		}
   901  		break;
   902  	
   903  	case CASE(	TIND,	TCHAR):
   904  	case CASE(	TIND,	TUCHAR):
   905  	case CASE(	TIND,	TSHORT):
   906  	case CASE(	TIND,	TUSHORT):
   907  	case CASE(	TIND,	TINT):
   908  	case CASE(	TIND,	TUINT):
   909  	case CASE(	TIND,	TLONG):
   910  	case CASE(	TIND,	TULONG):
   911  	case CASE(	TVLONG,	TCHAR):
   912  	case CASE(	TVLONG,	TUCHAR):
   913  	case CASE(	TVLONG,	TSHORT):
   914  	case CASE(	TVLONG,	TUSHORT):
   915  	case CASE(	TVLONG,	TINT):
   916  	case CASE(	TVLONG,	TUINT):
   917  	case CASE(	TVLONG,	TLONG):
   918  	case CASE(	TVLONG,	TULONG):
   919  	case CASE(	TUVLONG,	TCHAR):
   920  	case CASE(	TUVLONG,	TUCHAR):
   921  	case CASE(	TUVLONG,	TSHORT):
   922  	case CASE(	TUVLONG,	TUSHORT):
   923  	case CASE(	TUVLONG,	TINT):
   924  	case CASE(	TUVLONG,	TUINT):
   925  	case CASE(	TUVLONG,	TLONG):
   926  	case CASE(	TUVLONG,	TULONG):
   927  		a = AMOVQL;
   928  		if(f->op == OCONST) {
   929  			f->vconst &= (int)0xffffffffU;
   930  			a = AMOVL;
   931  		}
   932  		break;	
   933  
   934  	case CASE(	TIND,	TIND):
   935  	case CASE(	TIND,	TVLONG):
   936  	case CASE(	TIND,	TUVLONG):
   937  	case CASE(	TVLONG,	TIND):
   938  	case CASE(	TVLONG,	TVLONG):
   939  	case CASE(	TVLONG,	TUVLONG):
   940  	case CASE(	TUVLONG,	TIND):
   941  	case CASE(	TUVLONG,	TVLONG):
   942  	case CASE(	TUVLONG,	TUVLONG):
   943  		a = AMOVQ;
   944  		break;
   945  
   946  	case CASE(	TSHORT,	TINT):
   947  	case CASE(	TSHORT,	TUINT):
   948  	case CASE(	TSHORT,	TLONG):
   949  	case CASE(	TSHORT,	TULONG):
   950  		a = AMOVWLSX;
   951  		if(f->op == OCONST) {
   952  			f->vconst &= 0xffff;
   953  			if(f->vconst & 0x8000)
   954  				f->vconst |= 0xffff0000;
   955  			a = AMOVL;
   956  		}
   957  		break;
   958  
   959  	case CASE(	TSHORT,	TVLONG):
   960  	case CASE(	TSHORT,	TUVLONG):
   961  	case CASE(	TSHORT,	TIND):
   962  		a = AMOVWQSX;
   963  		if(f->op == OCONST) {
   964  			f->vconst &= 0xffff;
   965  			if(f->vconst & 0x8000){
   966  				f->vconst |= 0xffff0000;
   967  				f->vconst |= (vlong)~0 << 32;
   968  			}
   969  			a = AMOVL;
   970  		}
   971  		break;
   972  
   973  	case CASE(	TUSHORT,TINT):
   974  	case CASE(	TUSHORT,TUINT):
   975  	case CASE(	TUSHORT,TLONG):
   976  	case CASE(	TUSHORT,TULONG):
   977  		a = AMOVWLZX;
   978  		if(f->op == OCONST) {
   979  			f->vconst &= 0xffff;
   980  			a = AMOVL;
   981  		}
   982  		break;
   983  
   984  	case CASE(	TUSHORT,TVLONG):
   985  	case CASE(	TUSHORT,TUVLONG):
   986  	case CASE(	TUSHORT,TIND):
   987  		a = AMOVWQZX;
   988  		if(f->op == OCONST) {
   989  			f->vconst &= 0xffff;
   990  			a = AMOVL;	/* MOVL also zero-extends to 64 bits */
   991  		}
   992  		break;
   993  
   994  	case CASE(	TCHAR,	TSHORT):
   995  	case CASE(	TCHAR,	TUSHORT):
   996  	case CASE(	TCHAR,	TINT):
   997  	case CASE(	TCHAR,	TUINT):
   998  	case CASE(	TCHAR,	TLONG):
   999  	case CASE(	TCHAR,	TULONG):
  1000  		a = AMOVBLSX;
  1001  		if(f->op == OCONST) {
  1002  			f->vconst &= 0xff;
  1003  			if(f->vconst & 0x80)
  1004  				f->vconst |= 0xffffff00;
  1005  			a = AMOVL;
  1006  		}
  1007  		break;
  1008  
  1009  	case CASE(	TCHAR,	TVLONG):
  1010  	case CASE(	TCHAR,	TUVLONG):
  1011  	case CASE(	TCHAR,	TIND):
  1012  		a = AMOVBQSX;
  1013  		if(f->op == OCONST) {
  1014  			f->vconst &= 0xff;
  1015  			if(f->vconst & 0x80){
  1016  				f->vconst |= 0xffffff00;
  1017  				f->vconst |= (vlong)~0 << 32;
  1018  			}
  1019  			a = AMOVQ;
  1020  		}
  1021  		break;
  1022  
  1023  	case CASE(	TUCHAR,	TSHORT):
  1024  	case CASE(	TUCHAR,	TUSHORT):
  1025  	case CASE(	TUCHAR,	TINT):
  1026  	case CASE(	TUCHAR,	TUINT):
  1027  	case CASE(	TUCHAR,	TLONG):
  1028  	case CASE(	TUCHAR,	TULONG):
  1029  		a = AMOVBLZX;
  1030  		if(f->op == OCONST) {
  1031  			f->vconst &= 0xff;
  1032  			a = AMOVL;
  1033  		}
  1034  		break;
  1035  
  1036  	case CASE(	TUCHAR,	TVLONG):
  1037  	case CASE(	TUCHAR,	TUVLONG):
  1038  	case CASE(	TUCHAR,	TIND):
  1039  		a = AMOVBQZX;
  1040  		if(f->op == OCONST) {
  1041  			f->vconst &= 0xff;
  1042  			a = AMOVL;	/* zero-extends to 64-bits */
  1043  		}
  1044  		break;
  1045  
  1046  /*
  1047   * float to fix
  1048   */
  1049  	case CASE(	TFLOAT,	TCHAR):
  1050  	case CASE(	TFLOAT,	TUCHAR):
  1051  	case CASE(	TFLOAT,	TSHORT):
  1052  	case CASE(	TFLOAT,	TUSHORT):
  1053  	case CASE(	TFLOAT,	TINT):
  1054  	case CASE(	TFLOAT,	TUINT):
  1055  	case CASE(	TFLOAT,	TLONG):
  1056  	case CASE(	TFLOAT,	TULONG):
  1057  	case CASE(	TFLOAT,	TVLONG):
  1058  	case CASE(	TFLOAT,	TUVLONG):
  1059  	case CASE(	TFLOAT,	TIND):
  1060  
  1061  	case CASE(	TDOUBLE,TCHAR):
  1062  	case CASE(	TDOUBLE,TUCHAR):
  1063  	case CASE(	TDOUBLE,TSHORT):
  1064  	case CASE(	TDOUBLE,TUSHORT):
  1065  	case CASE(	TDOUBLE,TINT):
  1066  	case CASE(	TDOUBLE,TUINT):
  1067  	case CASE(	TDOUBLE,TLONG):
  1068  	case CASE(	TDOUBLE,TULONG):
  1069  	case CASE(	TDOUBLE,TVLONG):
  1070  	case CASE(	TDOUBLE,TUVLONG):
  1071  	case CASE(	TDOUBLE,TIND):
  1072  		regalloc(&nod, t, Z);
  1073  		if(ewidth[tt] == SZ_VLONG || typeu[tt] && ewidth[tt] == SZ_INT){
  1074  			if(ft == TFLOAT)
  1075  				a = ACVTTSS2SQ;
  1076  			else
  1077  				a = ACVTTSD2SQ;
  1078  		}else{
  1079  			if(ft == TFLOAT)
  1080  				a = ACVTTSS2SL;
  1081  			else
  1082  				a = ACVTTSD2SL;
  1083  		}
  1084  		gins(a, f, &nod);
  1085  		gmove(&nod, t);
  1086  		regfree(&nod);
  1087  		return;
  1088  
  1089  /*
  1090   * uvlong to float
  1091   */
  1092  	case CASE(	TUVLONG,	TDOUBLE):
  1093  	case CASE(	TUVLONG,	TFLOAT):
  1094  		a = ACVTSQ2SS;
  1095  		if(tt == TDOUBLE)
  1096  			a = ACVTSQ2SD;
  1097  		regalloc(&nod, f, f);
  1098  		gmove(f, &nod);
  1099  		regalloc(&nod1, t, t);
  1100  		gins(ACMPQ, &nod, nodconst(0));
  1101  		gins(AJLT, Z, Z);
  1102  		p1 = p;
  1103  		gins(a, &nod, &nod1);
  1104  		gins(AJMP, Z, Z);
  1105  		p2 = p;
  1106  		patch(p1, pc);
  1107  		regalloc(&nod2, f, Z);
  1108  		regalloc(&nod3, f, Z);
  1109  		gmove(&nod, &nod2);
  1110  		gins(ASHRQ, nodconst(1), &nod2);
  1111  		gmove(&nod, &nod3);
  1112  		gins(AANDL, nodconst(1), &nod3);
  1113  		gins(AORQ, &nod3, &nod2);
  1114  		gins(a, &nod2, &nod1);
  1115  		gins(tt == TDOUBLE? AADDSD: AADDSS, &nod1, &nod1);
  1116  		regfree(&nod2);
  1117  		regfree(&nod3);
  1118  		patch(p2, pc);
  1119  		regfree(&nod);
  1120  		regfree(&nod1);
  1121  		return;
  1122  
  1123  	case CASE(	TULONG,	TDOUBLE):
  1124  	case CASE(	TUINT,	TDOUBLE):
  1125  	case CASE(	TULONG,	TFLOAT):
  1126  	case CASE(	TUINT,	TFLOAT):
  1127  		a = ACVTSQ2SS;
  1128  		if(tt == TDOUBLE)
  1129  			a = ACVTSQ2SD;
  1130  		regalloc(&nod, f, f);
  1131  		gins(AMOVLQZX, f, &nod);
  1132  		regalloc(&nod1, t, t);
  1133  		gins(a, &nod, &nod1);
  1134  		gmove(&nod1, t);
  1135  		regfree(&nod);
  1136  		regfree(&nod1);
  1137  		return;
  1138  
  1139  /*
  1140   * fix to float
  1141   */
  1142  	case CASE(	TCHAR,	TFLOAT):
  1143  	case CASE(	TUCHAR,	TFLOAT):
  1144  	case CASE(	TSHORT,	TFLOAT):
  1145  	case CASE(	TUSHORT,TFLOAT):
  1146  	case CASE(	TINT,	TFLOAT):
  1147  	case CASE(	TLONG,	TFLOAT):
  1148  	case	CASE(	TVLONG,	TFLOAT):
  1149  	case CASE(	TIND,	TFLOAT):
  1150  
  1151  	case CASE(	TCHAR,	TDOUBLE):
  1152  	case CASE(	TUCHAR,	TDOUBLE):
  1153  	case CASE(	TSHORT,	TDOUBLE):
  1154  	case CASE(	TUSHORT,TDOUBLE):
  1155  	case CASE(	TINT,	TDOUBLE):
  1156  	case CASE(	TLONG,	TDOUBLE):
  1157  	case CASE(	TVLONG,	TDOUBLE):
  1158  	case CASE(	TIND,	TDOUBLE):
  1159  		regalloc(&nod, t, t);
  1160  		if(ewidth[ft] == SZ_VLONG){
  1161  			if(tt == TFLOAT)
  1162  				a = ACVTSQ2SS;
  1163  			else
  1164  				a = ACVTSQ2SD;
  1165  		}else{
  1166  			if(tt == TFLOAT)
  1167  				a = ACVTSL2SS;
  1168  			else
  1169  				a = ACVTSL2SD;
  1170  		}
  1171  		gins(a, f, &nod);
  1172  		gmove(&nod, t);
  1173  		regfree(&nod);
  1174  		return;
  1175  
  1176  /*
  1177   * float to float
  1178   */
  1179  	case CASE(	TFLOAT,	TFLOAT):
  1180  		a = AMOVSS;
  1181  		break;
  1182  	case CASE(	TDOUBLE,TFLOAT):
  1183  		a = ACVTSD2SS;
  1184  		break;
  1185  	case CASE(	TFLOAT,	TDOUBLE):
  1186  		a = ACVTSS2SD;
  1187  		break;
  1188  	case CASE(	TDOUBLE,TDOUBLE):
  1189  		a = AMOVSD;
  1190  		break;
  1191  	}
  1192  	if(a == AMOVQ || a == AMOVSD || a == AMOVSS || a == AMOVL && ewidth[ft] == ewidth[tt])	/* TO DO: check AMOVL */
  1193  	if(samaddr(f, t))
  1194  		return;
  1195  	gins(a, f, t);
  1196  }
  1197  
  1198  void
  1199  doindex(Node *n)
  1200  {
  1201  	Node nod, nod1;
  1202  	int32 v;
  1203  
  1204  if(debug['Y'])
  1205  prtree(n, "index");
  1206  
  1207  if(n->left->complex >= FNX)
  1208  print("botch in doindex\n");
  1209  
  1210  	regalloc(&nod, &qregnode, Z);
  1211  	v = constnode.vconst;
  1212  	cgen(n->right, &nod);
  1213  	idx.ptr = D_NONE;
  1214  	if(n->left->op == OCONST)
  1215  		idx.ptr = D_CONST;
  1216  	else if(n->left->op == OREGISTER)
  1217  		idx.ptr = n->left->reg;
  1218  	else if(n->left->op != OADDR) {
  1219  		reg[D_BP]++;	// can't be used as a base
  1220  		regalloc(&nod1, &qregnode, Z);
  1221  		cgen(n->left, &nod1);
  1222  		idx.ptr = nod1.reg;
  1223  		regfree(&nod1);
  1224  		reg[D_BP]--;
  1225  	}
  1226  	idx.reg = nod.reg;
  1227  	regfree(&nod);
  1228  	constnode.vconst = v;
  1229  }
  1230  
  1231  void
  1232  gins(int a, Node *f, Node *t)
  1233  {
  1234  
  1235  	if(f != Z && f->op == OINDEX)
  1236  		doindex(f);
  1237  	if(t != Z && t->op == OINDEX)
  1238  		doindex(t);
  1239  	nextpc();
  1240  	p->as = a;
  1241  	if(f != Z)
  1242  		naddr(f, &p->from);
  1243  	if(t != Z)
  1244  		naddr(t, &p->to);
  1245  	if(debug['g'])
  1246  		print("%P\n", p);
  1247  }
  1248  
  1249  void
  1250  gopcode(int o, Type *ty, Node *f, Node *t)
  1251  {
  1252  	int a, et;
  1253  
  1254  	et = TLONG;
  1255  	if(ty != T)
  1256  		et = ty->etype;
  1257  	if(et == TIND && ewidth[TIND] == 4)
  1258  		et = TUINT;
  1259  	if(debug['M']) {
  1260  		if(f != Z && f->type != T)
  1261  			print("gop: %O %O[%s],", o, f->op, tnames[et]);
  1262  		else
  1263  			print("gop: %O Z,", o);
  1264  		if(t != Z && t->type != T)
  1265  			print("%O[%s]\n", t->op, tnames[t->type->etype]);
  1266  		else
  1267  			print("Z\n");
  1268  	}
  1269  	a = AGOK;
  1270  	switch(o) {
  1271  	case OCOM:
  1272  		a = ANOTL;
  1273  		if(et == TCHAR || et == TUCHAR)
  1274  			a = ANOTB;
  1275  		if(et == TSHORT || et == TUSHORT)
  1276  			a = ANOTW;
  1277  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1278  			a = ANOTQ;
  1279  		break;
  1280  
  1281  	case ONEG:
  1282  		a = ANEGL;
  1283  		if(et == TCHAR || et == TUCHAR)
  1284  			a = ANEGB;
  1285  		if(et == TSHORT || et == TUSHORT)
  1286  			a = ANEGW;
  1287  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1288  			a = ANEGQ;
  1289  		break;
  1290  
  1291  	case OADDR:
  1292  		a = ALEAQ;
  1293  		break;
  1294  
  1295  	case OASADD:
  1296  	case OADD:
  1297  		a = AADDL;
  1298  		if(et == TCHAR || et == TUCHAR)
  1299  			a = AADDB;
  1300  		if(et == TSHORT || et == TUSHORT)
  1301  			a = AADDW;
  1302  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1303  			a = AADDQ;
  1304  		if(et == TFLOAT)
  1305  			a = AADDSS;
  1306  		if(et == TDOUBLE)
  1307  			a = AADDSD;
  1308  		break;
  1309  
  1310  	case OASSUB:
  1311  	case OSUB:
  1312  		a = ASUBL;
  1313  		if(et == TCHAR || et == TUCHAR)
  1314  			a = ASUBB;
  1315  		if(et == TSHORT || et == TUSHORT)
  1316  			a = ASUBW;
  1317  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1318  			a = ASUBQ;
  1319  		if(et == TFLOAT)
  1320  			a = ASUBSS;
  1321  		if(et == TDOUBLE)
  1322  			a = ASUBSD;
  1323  		break;
  1324  
  1325  	case OASOR:
  1326  	case OOR:
  1327  		a = AORL;
  1328  		if(et == TCHAR || et == TUCHAR)
  1329  			a = AORB;
  1330  		if(et == TSHORT || et == TUSHORT)
  1331  			a = AORW;
  1332  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1333  			a = AORQ;
  1334  		break;
  1335  
  1336  	case OASAND:
  1337  	case OAND:
  1338  		a = AANDL;
  1339  		if(et == TCHAR || et == TUCHAR)
  1340  			a = AANDB;
  1341  		if(et == TSHORT || et == TUSHORT)
  1342  			a = AANDW;
  1343  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1344  			a = AANDQ;
  1345  		break;
  1346  
  1347  	case OASXOR:
  1348  	case OXOR:
  1349  		a = AXORL;
  1350  		if(et == TCHAR || et == TUCHAR)
  1351  			a = AXORB;
  1352  		if(et == TSHORT || et == TUSHORT)
  1353  			a = AXORW;
  1354  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1355  			a = AXORQ;
  1356  		break;
  1357  
  1358  	case OASLSHR:
  1359  	case OLSHR:
  1360  		a = ASHRL;
  1361  		if(et == TCHAR || et == TUCHAR)
  1362  			a = ASHRB;
  1363  		if(et == TSHORT || et == TUSHORT)
  1364  			a = ASHRW;
  1365  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1366  			a = ASHRQ;
  1367  		break;
  1368  
  1369  	case OASASHR:
  1370  	case OASHR:
  1371  		a = ASARL;
  1372  		if(et == TCHAR || et == TUCHAR)
  1373  			a = ASARB;
  1374  		if(et == TSHORT || et == TUSHORT)
  1375  			a = ASARW;
  1376  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1377  			a = ASARQ;
  1378  		break;
  1379  
  1380  	case OASASHL:
  1381  	case OASHL:
  1382  		a = ASALL;
  1383  		if(et == TCHAR || et == TUCHAR)
  1384  			a = ASALB;
  1385  		if(et == TSHORT || et == TUSHORT)
  1386  			a = ASALW;
  1387  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1388  			a = ASALQ;
  1389  		break;
  1390  
  1391  	case OROTL:
  1392  		a = AROLL;
  1393  		if(et == TCHAR || et == TUCHAR)
  1394  			a = AROLB;
  1395  		if(et == TSHORT || et == TUSHORT)
  1396  			a = AROLW;
  1397  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1398  			a = AROLQ;
  1399  		break;
  1400  
  1401  	case OFUNC:
  1402  		a = ACALL;
  1403  		break;
  1404  
  1405  	case OASMUL:
  1406  	case OMUL:
  1407  		if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
  1408  			t = Z;
  1409  		a = AIMULL;
  1410  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1411  			a = AIMULQ;
  1412  		if(et == TFLOAT)
  1413  			a = AMULSS;
  1414  		if(et == TDOUBLE)
  1415  			a = AMULSD;
  1416  		break;
  1417  
  1418  	case OASMOD:
  1419  	case OMOD:
  1420  	case OASDIV:
  1421  	case ODIV:
  1422  		a = AIDIVL;
  1423  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1424  			a = AIDIVQ;
  1425  		if(et == TFLOAT)
  1426  			a = ADIVSS;
  1427  		if(et == TDOUBLE)
  1428  			a = ADIVSD;
  1429  		break;
  1430  
  1431  	case OASLMUL:
  1432  	case OLMUL:
  1433  		a = AMULL;
  1434  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1435  			a = AMULQ;
  1436  		break;
  1437  
  1438  	case OASLMOD:
  1439  	case OLMOD:
  1440  	case OASLDIV:
  1441  	case OLDIV:
  1442  		a = ADIVL;
  1443  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1444  			a = ADIVQ;
  1445  		break;
  1446  
  1447  	case OEQ:
  1448  	case ONE:
  1449  	case OLT:
  1450  	case OLE:
  1451  	case OGE:
  1452  	case OGT:
  1453  	case OLO:
  1454  	case OLS:
  1455  	case OHS:
  1456  	case OHI:
  1457  		a = ACMPL;
  1458  		if(et == TCHAR || et == TUCHAR)
  1459  			a = ACMPB;
  1460  		if(et == TSHORT || et == TUSHORT)
  1461  			a = ACMPW;
  1462  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1463  			a = ACMPQ;
  1464  		if(et == TFLOAT)
  1465  			a = AUCOMISS;
  1466  		if(et == TDOUBLE)
  1467  			a = AUCOMISD;
  1468  		gins(a, f, t);
  1469  		switch(o) {
  1470  		case OEQ:	a = AJEQ; break;
  1471  		case ONE:	a = AJNE; break;
  1472  		case OLT:	a = AJLT; break;
  1473  		case OLE:	a = AJLE; break;
  1474  		case OGE:	a = AJGE; break;
  1475  		case OGT:	a = AJGT; break;
  1476  		case OLO:	a = AJCS; break;
  1477  		case OLS:	a = AJLS; break;
  1478  		case OHS:	a = AJCC; break;
  1479  		case OHI:	a = AJHI; break;
  1480  		}
  1481  		gins(a, Z, Z);
  1482  		return;
  1483  	}
  1484  	if(a == AGOK)
  1485  		diag(Z, "bad in gopcode %O", o);
  1486  	gins(a, f, t);
  1487  }
  1488  
  1489  int
  1490  samaddr(Node *f, Node *t)
  1491  {
  1492  	return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
  1493  }
  1494  
  1495  void
  1496  gbranch(int o)
  1497  {
  1498  	int a;
  1499  
  1500  	a = AGOK;
  1501  	switch(o) {
  1502  	case ORETURN:
  1503  		a = ARET;
  1504  		break;
  1505  	case OGOTO:
  1506  		a = AJMP;
  1507  		break;
  1508  	}
  1509  	nextpc();
  1510  	if(a == AGOK) {
  1511  		diag(Z, "bad in gbranch %O",  o);
  1512  		nextpc();
  1513  	}
  1514  	p->as = a;
  1515  }
  1516  
  1517  void
  1518  patch(Prog *op, int32 pc)
  1519  {
  1520  	op->to.offset = pc;
  1521  	op->to.type = D_BRANCH;
  1522  	op->to.u.branch = nil;
  1523  	op->pcond = nil;
  1524  }
  1525  
  1526  void
  1527  gpseudo(int a, Sym *s, Node *n)
  1528  {
  1529  
  1530  	nextpc();
  1531  	p->as = a;
  1532  	p->from.type = D_EXTERN;
  1533  	p->from.sym = linksym(s);
  1534  
  1535  	switch(a) {
  1536  	case ATEXT:
  1537  		p->from.scale = textflag;
  1538  		textflag = 0;
  1539  		break;
  1540  	case AGLOBL:
  1541  		p->from.scale = s->dataflag;
  1542  		break;
  1543  	}
  1544  
  1545  	if(s->class == CSTATIC)
  1546  		p->from.type = D_STATIC;
  1547  	naddr(n, &p->to);
  1548  	if(a == ADATA || a == AGLOBL)
  1549  		pc--;
  1550  }
  1551  
  1552  void
  1553  gpcdata(int index, int value)
  1554  {
  1555  	Node n1;
  1556  	
  1557  	n1 = *nodconst(index);
  1558  	gins(APCDATA, &n1, nodconst(value));
  1559  }
  1560  
  1561  void
  1562  gprefetch(Node *n)
  1563  {
  1564  	Node n1;
  1565  	
  1566  	regalloc(&n1, n, Z);
  1567  	gmove(n, &n1);
  1568  	n1.op = OINDREG;
  1569  	gins(APREFETCHNTA, &n1, Z);
  1570  	regfree(&n1);
  1571  }
  1572  
  1573  int
  1574  sconst(Node *n)
  1575  {
  1576  	int32 v;
  1577  
  1578  	if(n->op == OCONST && !typefd[n->type->etype]) {
  1579  		v = n->vconst;
  1580  		if(v >= -32766L && v < 32766L)
  1581  			return 1;
  1582  	}
  1583  	return 0;
  1584  }
  1585  
  1586  int32
  1587  exreg(Type *t)
  1588  {
  1589  	int32 o;
  1590  
  1591  	if(typechlpv[t->etype]) {
  1592  		if(exregoffset >= 64)
  1593  			return 0;
  1594  		o = exregoffset;
  1595  		exregoffset += ewidth[TIND];
  1596  		return o+1;	// +1 to avoid 0 == failure; naddr's case OEXREG will subtract 1.
  1597  	}
  1598  	return 0;
  1599  }
  1600  
  1601  schar	ewidth[NTYPE] =
  1602  {
  1603  	-1,		/*[TXXX]*/
  1604  	SZ_CHAR,	/*[TCHAR]*/
  1605  	SZ_CHAR,	/*[TUCHAR]*/
  1606  	SZ_SHORT,	/*[TSHORT]*/
  1607  	SZ_SHORT,	/*[TUSHORT]*/
  1608  	SZ_INT,		/*[TINT]*/
  1609  	SZ_INT,		/*[TUINT]*/
  1610  	SZ_LONG,	/*[TLONG]*/
  1611  	SZ_LONG,	/*[TULONG]*/
  1612  	SZ_VLONG,	/*[TVLONG]*/
  1613  	SZ_VLONG,	/*[TUVLONG]*/
  1614  	SZ_FLOAT,	/*[TFLOAT]*/
  1615  	SZ_DOUBLE,	/*[TDOUBLE]*/
  1616  	SZ_IND,		/*[TIND]*/
  1617  	0,		/*[TFUNC]*/
  1618  	-1,		/*[TARRAY]*/
  1619  	0,		/*[TVOID]*/
  1620  	-1,		/*[TSTRUCT]*/
  1621  	-1,		/*[TUNION]*/
  1622  	SZ_INT,		/*[TENUM]*/
  1623  };
  1624  int32	ncast[NTYPE] =
  1625  {
  1626  	0,				/*[TXXX]*/
  1627  	BCHAR|BUCHAR,			/*[TCHAR]*/
  1628  	BCHAR|BUCHAR,			/*[TUCHAR]*/
  1629  	BSHORT|BUSHORT,			/*[TSHORT]*/
  1630  	BSHORT|BUSHORT,			/*[TUSHORT]*/
  1631  	BINT|BUINT|BLONG|BULONG,	/*[TINT]*/
  1632  	BINT|BUINT|BLONG|BULONG,	/*[TUINT]*/
  1633  	BINT|BUINT|BLONG|BULONG,	/*[TLONG]*/
  1634  	BINT|BUINT|BLONG|BULONG,	/*[TULONG]*/
  1635  	BVLONG|BUVLONG|BIND,			/*[TVLONG]*/
  1636  	BVLONG|BUVLONG|BIND,			/*[TUVLONG]*/
  1637  	BFLOAT,				/*[TFLOAT]*/
  1638  	BDOUBLE,			/*[TDOUBLE]*/
  1639  	BVLONG|BUVLONG|BIND,		/*[TIND]*/
  1640  	0,				/*[TFUNC]*/
  1641  	0,				/*[TARRAY]*/
  1642  	0,				/*[TVOID]*/
  1643  	BSTRUCT,			/*[TSTRUCT]*/
  1644  	BUNION,				/*[TUNION]*/
  1645  	0,				/*[TENUM]*/
  1646  };