github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/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, Type *t, int mode)
   355  {
   356  	int r;
   357  	
   358  	if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
   359  		r = REGRET;
   360  		if(typefd[nn->type->etype])
   361  			r = FREGRET;
   362  		nodreg(n, nn, r);
   363  		reg[r]++;
   364  		return;
   365  	}
   366  	
   367  	if(mode == 1) {
   368  		// fetch returned value after call.
   369  		// already called gargs, so curarg is set.
   370  		curarg = (curarg+7) & ~7;
   371  		regaalloc(n, nn);
   372  		return;
   373  	}
   374  
   375  	if(mode == 2) {
   376  		// store value to be returned.
   377  		// must compute arg offset.
   378  		if(t->etype != TFUNC)
   379  			fatal(Z, "bad regret func %T", t);
   380  		*n = *nn;
   381  		n->op = ONAME;
   382  		n->class = CPARAM;
   383  		n->sym = slookup(".ret");
   384  		n->complex = nodret->complex;
   385  		n->addable = 20;
   386  		n->xoffset = argsize(0);
   387  		return;
   388  	}
   389  	
   390  	fatal(Z, "bad regret");	
   391  }
   392  
   393  void
   394  regalloc(Node *n, Node *tn, Node *o)
   395  {
   396  	int i;
   397  
   398  	switch(tn->type->etype) {
   399  	case TCHAR:
   400  	case TUCHAR:
   401  	case TSHORT:
   402  	case TUSHORT:
   403  	case TINT:
   404  	case TUINT:
   405  	case TLONG:
   406  	case TULONG:
   407  	case TVLONG:
   408  	case TUVLONG:
   409  	case TIND:
   410  		if(o != Z && o->op == OREGISTER) {
   411  			i = o->reg;
   412  			if(i >= D_AX && i <= D_R15)
   413  				goto out;
   414  		}
   415  		for(i=D_AX; i<=D_R15; i++)
   416  			if(reg[i] == 0)
   417  				goto out;
   418  		diag(tn, "out of fixed registers");
   419  		goto err;
   420  
   421  	case TFLOAT:
   422  	case TDOUBLE:
   423  		if(o != Z && o->op == OREGISTER) {
   424  			i = o->reg;
   425  			if(i >= D_X0 && i <= D_X7)
   426  				goto out;
   427  		}
   428  		for(i=D_X0; i<=D_X7; i++)
   429  			if(reg[i] == 0)
   430  				goto out;
   431  		diag(tn, "out of float registers");
   432  		goto out;
   433  	}
   434  	diag(tn, "unknown type in regalloc: %T", tn->type);
   435  err:
   436  	i = 0;
   437  out:
   438  	if(i)
   439  		reg[i]++;
   440  	nodreg(n, tn, i);
   441  }
   442  
   443  void
   444  regialloc(Node *n, Node *tn, Node *o)
   445  {
   446  	Node nod;
   447  
   448  	nod = *tn;
   449  	nod.type = types[TIND];
   450  	regalloc(n, &nod, o);
   451  }
   452  
   453  void
   454  regfree(Node *n)
   455  {
   456  	int i;
   457  
   458  	i = 0;
   459  	if(n->op != OREGISTER && n->op != OINDREG)
   460  		goto err;
   461  	i = n->reg;
   462  	if(i < 0 || i >= nelem(reg))
   463  		goto err;
   464  	if(reg[i] <= 0)
   465  		goto err;
   466  	reg[i]--;
   467  	return;
   468  err:
   469  	diag(n, "error in regfree: %R", i);
   470  }
   471  
   472  void
   473  regsalloc(Node *n, Node *nn)
   474  {
   475  	cursafe = align(cursafe, nn->type, Aaut3, nil);
   476  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   477  	*n = *nodsafe;
   478  	n->xoffset = -(stkoff + cursafe);
   479  	n->type = nn->type;
   480  	n->etype = nn->type->etype;
   481  	n->lineno = nn->lineno;
   482  }
   483  
   484  void
   485  regaalloc1(Node *n, Node *nn)
   486  {
   487  	if(REGARG < 0) {
   488  		fatal(n, "regaalloc1 and REGARG<0");
   489  		return;
   490  	}
   491  	nodreg(n, nn, REGARG);
   492  	reg[(uchar)REGARG]++;
   493  	curarg = align(curarg, nn->type, Aarg1, nil);
   494  	curarg = align(curarg, nn->type, Aarg2, nil);
   495  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   496  }
   497  
   498  void
   499  regaalloc(Node *n, Node *nn)
   500  {
   501  	curarg = align(curarg, nn->type, Aarg1, nil);
   502  	*n = *nn;
   503  	n->op = OINDREG;
   504  	n->reg = REGSP;
   505  	n->xoffset = curarg;
   506  	n->complex = 0;
   507  	n->addable = 20;
   508  	curarg = align(curarg, nn->type, Aarg2, nil);
   509  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   510  }
   511  
   512  void
   513  regind(Node *n, Node *nn)
   514  {
   515  
   516  	if(n->op != OREGISTER) {
   517  		diag(n, "regind not OREGISTER");
   518  		return;
   519  	}
   520  	n->op = OINDREG;
   521  	n->type = nn->type;
   522  }
   523  
   524  void
   525  naddr(Node *n, Addr *a)
   526  {
   527  	int32 v;
   528  
   529  	a->type = D_NONE;
   530  	if(n == Z)
   531  		return;
   532  	switch(n->op) {
   533  	default:
   534  	bad:
   535  		diag(n, "bad in naddr: %O %D", n->op, a);
   536  		break;
   537  
   538  	case OREGISTER:
   539  		a->type = n->reg;
   540  		a->sym = nil;
   541  		break;
   542  
   543  	case OEXREG:
   544  		a->type = D_INDIR + D_TLS;
   545  		a->offset = n->reg - 1;
   546  		break;
   547  
   548  	case OIND:
   549  		naddr(n->left, a);
   550  		if(a->type >= D_AX && a->type <= D_R15)
   551  			a->type += D_INDIR;
   552  		else
   553  		if(a->type == D_CONST)
   554  			a->type = D_NONE+D_INDIR;
   555  		else
   556  		if(a->type == D_ADDR) {
   557  			a->type = a->index;
   558  			a->index = D_NONE;
   559  		} else
   560  			goto bad;
   561  		break;
   562  
   563  	case OINDEX:
   564  		a->type = idx.ptr;
   565  		if(n->left->op == OADDR || n->left->op == OCONST)
   566  			naddr(n->left, a);
   567  		if(a->type >= D_AX && a->type <= D_R15)
   568  			a->type += D_INDIR;
   569  		else
   570  		if(a->type == D_CONST)
   571  			a->type = D_NONE+D_INDIR;
   572  		else
   573  		if(a->type == D_ADDR) {
   574  			a->type = a->index;
   575  			a->index = D_NONE;
   576  		} else
   577  			goto bad;
   578  		a->index = idx.reg;
   579  		a->scale = n->scale;
   580  		a->offset += n->xoffset;
   581  		break;
   582  
   583  	case OINDREG:
   584  		a->type = n->reg+D_INDIR;
   585  		a->sym = nil;
   586  		a->offset = n->xoffset;
   587  		break;
   588  
   589  	case ONAME:
   590  		a->etype = n->etype;
   591  		a->type = D_STATIC;
   592  		a->sym = linksym(n->sym);
   593  		a->offset = n->xoffset;
   594  		if(n->class == CSTATIC)
   595  			break;
   596  		if(n->class == CEXTERN || n->class == CGLOBL) {
   597  			a->type = D_EXTERN;
   598  			break;
   599  		}
   600  		if(n->class == CAUTO) {
   601  			a->type = D_AUTO;
   602  			break;
   603  		}
   604  		if(n->class == CPARAM) {
   605  			a->type = D_PARAM;
   606  			break;
   607  		}
   608  		goto bad;
   609  
   610  	case OCONST:
   611  		if(typefd[n->type->etype]) {
   612  			a->type = D_FCONST;
   613  			a->u.dval = n->fconst;
   614  			break;
   615  		}
   616  		a->sym = nil;
   617  		a->type = D_CONST;
   618  		if(typev[n->type->etype] || (n->type->etype == TIND && ewidth[TIND] == 8))
   619  			a->offset = n->vconst;
   620  		else
   621  			a->offset = convvtox(n->vconst, typeu[n->type->etype]? TULONG: TLONG);
   622  		break;
   623  
   624  	case OADDR:
   625  		naddr(n->left, a);
   626  		if(a->type >= D_INDIR) {
   627  			a->type -= D_INDIR;
   628  			break;
   629  		}
   630  		if(a->type == D_EXTERN || a->type == D_STATIC ||
   631  		   a->type == D_AUTO || a->type == D_PARAM)
   632  			if(a->index == D_NONE) {
   633  				a->index = a->type;
   634  				a->type = D_ADDR;
   635  				break;
   636  			}
   637  		goto bad;
   638  
   639  	case OADD:
   640  		if(n->right->op == OCONST) {
   641  			v = n->right->vconst;
   642  			naddr(n->left, a);
   643  		} else
   644  		if(n->left->op == OCONST) {
   645  			v = n->left->vconst;
   646  			naddr(n->right, a);
   647  		} else
   648  			goto bad;
   649  		a->offset += v;
   650  		break;
   651  
   652  	}
   653  }
   654  
   655  void
   656  gcmp(int op, Node *n, vlong val)
   657  {
   658  	Node *cn, nod;
   659  
   660  	cn = nodgconst(val, n->type);
   661  	if(!immconst(cn)){
   662  		regalloc(&nod, n, Z);
   663  		gmove(cn, &nod);
   664  		gopcode(op, n->type, n, &nod);
   665  		regfree(&nod);
   666  	}else
   667  		gopcode(op, n->type, n, cn);
   668  }
   669  
   670  #define	CASE(a,b)	((a<<8)|(b<<0))
   671  
   672  void
   673  gmove(Node *f, Node *t)
   674  {
   675  	int ft, tt, t64, a;
   676  	Node nod, nod1, nod2, nod3;
   677  	Prog *p1, *p2;
   678  
   679  	ft = f->type->etype;
   680  	tt = t->type->etype;
   681  	if(ewidth[TIND] == 4) {
   682  		if(ft == TIND)
   683  			ft = TUINT;
   684  		if(tt == TIND)
   685  			tt = TUINT;
   686  	}
   687  	t64 = tt == TVLONG || tt == TUVLONG || tt == TIND;
   688  	if(debug['M'])
   689  		print("gop: %O %O[%s],%O[%s]\n", OAS,
   690  			f->op, tnames[ft], t->op, tnames[tt]);
   691  	if(typefd[ft] && f->op == OCONST) {
   692  		/* TO DO: pick up special constants, possibly preloaded */
   693  		if(f->fconst == 0.0){
   694  			regalloc(&nod, t, t);
   695  			gins(AXORPD, &nod, &nod);
   696  			gmove(&nod, t);
   697  			regfree(&nod);
   698  			return;
   699  		}
   700  	}
   701  /*
   702   * load
   703   */
   704  	if(ft == TVLONG || ft == TUVLONG)
   705  	if(f->op == OCONST)
   706  	if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
   707  	if(t->op != OREGISTER) {
   708  		regalloc(&nod, f, Z);
   709  		gmove(f, &nod);
   710  		gmove(&nod, t);
   711  		regfree(&nod);
   712  		return;
   713  	}
   714  
   715  	if(f->op == ONAME || f->op == OINDREG ||
   716  	   f->op == OIND || f->op == OINDEX)
   717  	switch(ft) {
   718  	case TCHAR:
   719  		a = AMOVBLSX;
   720  		if(t64)
   721  			a = AMOVBQSX;
   722  		goto ld;
   723  	case TUCHAR:
   724  		a = AMOVBLZX;
   725  		if(t64)
   726  			a = AMOVBQZX;
   727  		goto ld;
   728  	case TSHORT:
   729  		a = AMOVWLSX;
   730  		if(t64)
   731  			a = AMOVWQSX;
   732  		goto ld;
   733  	case TUSHORT:
   734  		a = AMOVWLZX;
   735  		if(t64)
   736  			a = AMOVWQZX;
   737  		goto ld;
   738  	case TINT:
   739  	case TLONG:
   740  		if(typefd[tt]) {
   741  			regalloc(&nod, t, t);
   742  			if(tt == TDOUBLE)
   743  				a = ACVTSL2SD;
   744  			else
   745  				a = ACVTSL2SS;
   746  			gins(a, f, &nod);
   747  			gmove(&nod, t);
   748  			regfree(&nod);
   749  			return;
   750  		}
   751  		a = AMOVL;
   752  		if(t64)
   753  			a = AMOVLQSX;
   754  		goto ld;
   755  	case TUINT:
   756  	case TULONG:
   757  		a = AMOVL;
   758  		if(t64)
   759  			a = AMOVLQZX;	/* could probably use plain MOVL */
   760  		goto ld;
   761  	case TVLONG:
   762  		if(typefd[tt]) {
   763  			regalloc(&nod, t, t);
   764  			if(tt == TDOUBLE)
   765  				a = ACVTSQ2SD;
   766  			else
   767  				a = ACVTSQ2SS;
   768  			gins(a, f, &nod);
   769  			gmove(&nod, t);
   770  			regfree(&nod);
   771  			return;
   772  		}
   773  	case TUVLONG:
   774  		a = AMOVQ;
   775  		goto ld;
   776  	case TIND:
   777  		a = AMOVQ;
   778  		if(ewidth[TIND] == 4)
   779  			a = AMOVL;
   780  
   781  	ld:
   782  		regalloc(&nod, f, t);
   783  		nod.type = t64? types[TVLONG]: types[TINT];
   784  		gins(a, f, &nod);
   785  		gmove(&nod, t);
   786  		regfree(&nod);
   787  		return;
   788  
   789  	case TFLOAT:
   790  		a = AMOVSS;
   791  		goto fld;
   792  	case TDOUBLE:
   793  		a = AMOVSD;
   794  	fld:
   795  		regalloc(&nod, f, t);
   796  		if(tt != TDOUBLE && tt != TFLOAT){	/* TO DO: why is this here */
   797  			prtree(f, "odd tree");
   798  			nod.type = t64? types[TVLONG]: types[TINT];
   799  		}
   800  		gins(a, f, &nod);
   801  		gmove(&nod, t);
   802  		regfree(&nod);
   803  		return;
   804  	}
   805  
   806  /*
   807   * store
   808   */
   809  	if(t->op == ONAME || t->op == OINDREG ||
   810  	   t->op == OIND || t->op == OINDEX)
   811  	switch(tt) {
   812  	case TCHAR:
   813  	case TUCHAR:
   814  		a = AMOVB;	goto st;
   815  	case TSHORT:
   816  	case TUSHORT:
   817  		a = AMOVW;	goto st;
   818  	case TINT:
   819  	case TUINT:
   820  	case TLONG:
   821  	case TULONG:
   822  		a = AMOVL;	goto st;
   823  	case TVLONG:
   824  	case TUVLONG:
   825  	case TIND:
   826  		a = AMOVQ;	goto st;
   827  
   828  	st:
   829  		if(f->op == OCONST) {
   830  			gins(a, f, t);
   831  			return;
   832  		}
   833  	fst:
   834  		regalloc(&nod, t, f);
   835  		gmove(f, &nod);
   836  		gins(a, &nod, t);
   837  		regfree(&nod);
   838  		return;
   839  
   840  	case TFLOAT:
   841  		a = AMOVSS;
   842  		goto fst;
   843  	case TDOUBLE:
   844  		a = AMOVSD;
   845  		goto fst;
   846  	}
   847  
   848  /*
   849   * convert
   850   */
   851  	switch(CASE(ft,tt)) {
   852  	default:
   853  /*
   854   * integer to integer
   855   ********
   856  		a = AGOK;	break;
   857  
   858  	case CASE(	TCHAR,	TCHAR):
   859  	case CASE(	TUCHAR,	TCHAR):
   860  	case CASE(	TSHORT,	TCHAR):
   861  	case CASE(	TUSHORT,TCHAR):
   862  	case CASE(	TINT,	TCHAR):
   863  	case CASE(	TUINT,	TCHAR):
   864  	case CASE(	TLONG,	TCHAR):
   865  	case CASE(	TULONG,	TCHAR):
   866  
   867  	case CASE(	TCHAR,	TUCHAR):
   868  	case CASE(	TUCHAR,	TUCHAR):
   869  	case CASE(	TSHORT,	TUCHAR):
   870  	case CASE(	TUSHORT,TUCHAR):
   871  	case CASE(	TINT,	TUCHAR):
   872  	case CASE(	TUINT,	TUCHAR):
   873  	case CASE(	TLONG,	TUCHAR):
   874  	case CASE(	TULONG,	TUCHAR):
   875  
   876  	case CASE(	TSHORT,	TSHORT):
   877  	case CASE(	TUSHORT,TSHORT):
   878  	case CASE(	TINT,	TSHORT):
   879  	case CASE(	TUINT,	TSHORT):
   880  	case CASE(	TLONG,	TSHORT):
   881  	case CASE(	TULONG,	TSHORT):
   882  
   883  	case CASE(	TSHORT,	TUSHORT):
   884  	case CASE(	TUSHORT,TUSHORT):
   885  	case CASE(	TINT,	TUSHORT):
   886  	case CASE(	TUINT,	TUSHORT):
   887  	case CASE(	TLONG,	TUSHORT):
   888  	case CASE(	TULONG,	TUSHORT):
   889  
   890  	case CASE(	TINT,	TINT):
   891  	case CASE(	TUINT,	TINT):
   892  	case CASE(	TLONG,	TINT):
   893  	case CASE(	TULONG,	TINT):
   894  
   895  	case CASE(	TINT,	TUINT):
   896  	case CASE(	TUINT,	TUINT):
   897  	case CASE(	TLONG,	TUINT):
   898  	case CASE(	TULONG,	TUINT):
   899   *****/
   900  		a = AMOVL;
   901  		break;
   902  
   903  	case CASE(	TINT,	TIND):
   904  	case CASE(	TINT,	TVLONG):
   905  	case CASE(	TINT,	TUVLONG):
   906  	case CASE(	TLONG,	TIND):
   907  	case CASE(	TLONG,	TVLONG):
   908  	case CASE(	TLONG,	TUVLONG):
   909  		a = AMOVLQSX;
   910  		if(f->op == OCONST) {
   911  			f->vconst &= (uvlong)0xffffffffU;
   912  			if(f->vconst & 0x80000000)
   913  				f->vconst |= (vlong)0xffffffff << 32;
   914  			a = AMOVQ;
   915  		}
   916  		break;
   917  
   918  	case CASE(	TUINT,	TIND):
   919  	case CASE(	TUINT,	TVLONG):
   920  	case CASE(	TUINT,	TUVLONG):
   921  	case CASE(	TULONG,	TVLONG):
   922  	case CASE(	TULONG,	TUVLONG):
   923  	case CASE(	TULONG,	TIND):
   924  		a = AMOVLQZX;
   925  		if(f->op == OCONST) {
   926  			f->vconst &= (uvlong)0xffffffffU;
   927  			a = AMOVQ;
   928  		}
   929  		break;
   930  	
   931  	case CASE(	TIND,	TCHAR):
   932  	case CASE(	TIND,	TUCHAR):
   933  	case CASE(	TIND,	TSHORT):
   934  	case CASE(	TIND,	TUSHORT):
   935  	case CASE(	TIND,	TINT):
   936  	case CASE(	TIND,	TUINT):
   937  	case CASE(	TIND,	TLONG):
   938  	case CASE(	TIND,	TULONG):
   939  	case CASE(	TVLONG,	TCHAR):
   940  	case CASE(	TVLONG,	TUCHAR):
   941  	case CASE(	TVLONG,	TSHORT):
   942  	case CASE(	TVLONG,	TUSHORT):
   943  	case CASE(	TVLONG,	TINT):
   944  	case CASE(	TVLONG,	TUINT):
   945  	case CASE(	TVLONG,	TLONG):
   946  	case CASE(	TVLONG,	TULONG):
   947  	case CASE(	TUVLONG,	TCHAR):
   948  	case CASE(	TUVLONG,	TUCHAR):
   949  	case CASE(	TUVLONG,	TSHORT):
   950  	case CASE(	TUVLONG,	TUSHORT):
   951  	case CASE(	TUVLONG,	TINT):
   952  	case CASE(	TUVLONG,	TUINT):
   953  	case CASE(	TUVLONG,	TLONG):
   954  	case CASE(	TUVLONG,	TULONG):
   955  		a = AMOVQL;
   956  		if(f->op == OCONST) {
   957  			f->vconst &= (int)0xffffffffU;
   958  			a = AMOVL;
   959  		}
   960  		break;	
   961  
   962  	case CASE(	TIND,	TIND):
   963  	case CASE(	TIND,	TVLONG):
   964  	case CASE(	TIND,	TUVLONG):
   965  	case CASE(	TVLONG,	TIND):
   966  	case CASE(	TVLONG,	TVLONG):
   967  	case CASE(	TVLONG,	TUVLONG):
   968  	case CASE(	TUVLONG,	TIND):
   969  	case CASE(	TUVLONG,	TVLONG):
   970  	case CASE(	TUVLONG,	TUVLONG):
   971  		a = AMOVQ;
   972  		break;
   973  
   974  	case CASE(	TSHORT,	TINT):
   975  	case CASE(	TSHORT,	TUINT):
   976  	case CASE(	TSHORT,	TLONG):
   977  	case CASE(	TSHORT,	TULONG):
   978  		a = AMOVWLSX;
   979  		if(f->op == OCONST) {
   980  			f->vconst &= 0xffff;
   981  			if(f->vconst & 0x8000)
   982  				f->vconst |= 0xffff0000;
   983  			a = AMOVL;
   984  		}
   985  		break;
   986  
   987  	case CASE(	TSHORT,	TVLONG):
   988  	case CASE(	TSHORT,	TUVLONG):
   989  	case CASE(	TSHORT,	TIND):
   990  		a = AMOVWQSX;
   991  		if(f->op == OCONST) {
   992  			f->vconst &= 0xffff;
   993  			if(f->vconst & 0x8000){
   994  				f->vconst |= 0xffff0000;
   995  				f->vconst |= (vlong)~0 << 32;
   996  			}
   997  			a = AMOVL;
   998  		}
   999  		break;
  1000  
  1001  	case CASE(	TUSHORT,TINT):
  1002  	case CASE(	TUSHORT,TUINT):
  1003  	case CASE(	TUSHORT,TLONG):
  1004  	case CASE(	TUSHORT,TULONG):
  1005  		a = AMOVWLZX;
  1006  		if(f->op == OCONST) {
  1007  			f->vconst &= 0xffff;
  1008  			a = AMOVL;
  1009  		}
  1010  		break;
  1011  
  1012  	case CASE(	TUSHORT,TVLONG):
  1013  	case CASE(	TUSHORT,TUVLONG):
  1014  	case CASE(	TUSHORT,TIND):
  1015  		a = AMOVWQZX;
  1016  		if(f->op == OCONST) {
  1017  			f->vconst &= 0xffff;
  1018  			a = AMOVL;	/* MOVL also zero-extends to 64 bits */
  1019  		}
  1020  		break;
  1021  
  1022  	case CASE(	TCHAR,	TSHORT):
  1023  	case CASE(	TCHAR,	TUSHORT):
  1024  	case CASE(	TCHAR,	TINT):
  1025  	case CASE(	TCHAR,	TUINT):
  1026  	case CASE(	TCHAR,	TLONG):
  1027  	case CASE(	TCHAR,	TULONG):
  1028  		a = AMOVBLSX;
  1029  		if(f->op == OCONST) {
  1030  			f->vconst &= 0xff;
  1031  			if(f->vconst & 0x80)
  1032  				f->vconst |= 0xffffff00;
  1033  			a = AMOVL;
  1034  		}
  1035  		break;
  1036  
  1037  	case CASE(	TCHAR,	TVLONG):
  1038  	case CASE(	TCHAR,	TUVLONG):
  1039  	case CASE(	TCHAR,	TIND):
  1040  		a = AMOVBQSX;
  1041  		if(f->op == OCONST) {
  1042  			f->vconst &= 0xff;
  1043  			if(f->vconst & 0x80){
  1044  				f->vconst |= 0xffffff00;
  1045  				f->vconst |= (vlong)~0 << 32;
  1046  			}
  1047  			a = AMOVQ;
  1048  		}
  1049  		break;
  1050  
  1051  	case CASE(	TUCHAR,	TSHORT):
  1052  	case CASE(	TUCHAR,	TUSHORT):
  1053  	case CASE(	TUCHAR,	TINT):
  1054  	case CASE(	TUCHAR,	TUINT):
  1055  	case CASE(	TUCHAR,	TLONG):
  1056  	case CASE(	TUCHAR,	TULONG):
  1057  		a = AMOVBLZX;
  1058  		if(f->op == OCONST) {
  1059  			f->vconst &= 0xff;
  1060  			a = AMOVL;
  1061  		}
  1062  		break;
  1063  
  1064  	case CASE(	TUCHAR,	TVLONG):
  1065  	case CASE(	TUCHAR,	TUVLONG):
  1066  	case CASE(	TUCHAR,	TIND):
  1067  		a = AMOVBQZX;
  1068  		if(f->op == OCONST) {
  1069  			f->vconst &= 0xff;
  1070  			a = AMOVL;	/* zero-extends to 64-bits */
  1071  		}
  1072  		break;
  1073  
  1074  /*
  1075   * float to fix
  1076   */
  1077  	case CASE(	TFLOAT,	TCHAR):
  1078  	case CASE(	TFLOAT,	TUCHAR):
  1079  	case CASE(	TFLOAT,	TSHORT):
  1080  	case CASE(	TFLOAT,	TUSHORT):
  1081  	case CASE(	TFLOAT,	TINT):
  1082  	case CASE(	TFLOAT,	TUINT):
  1083  	case CASE(	TFLOAT,	TLONG):
  1084  	case CASE(	TFLOAT,	TULONG):
  1085  	case CASE(	TFLOAT,	TVLONG):
  1086  	case CASE(	TFLOAT,	TUVLONG):
  1087  	case CASE(	TFLOAT,	TIND):
  1088  
  1089  	case CASE(	TDOUBLE,TCHAR):
  1090  	case CASE(	TDOUBLE,TUCHAR):
  1091  	case CASE(	TDOUBLE,TSHORT):
  1092  	case CASE(	TDOUBLE,TUSHORT):
  1093  	case CASE(	TDOUBLE,TINT):
  1094  	case CASE(	TDOUBLE,TUINT):
  1095  	case CASE(	TDOUBLE,TLONG):
  1096  	case CASE(	TDOUBLE,TULONG):
  1097  	case CASE(	TDOUBLE,TVLONG):
  1098  	case CASE(	TDOUBLE,TUVLONG):
  1099  	case CASE(	TDOUBLE,TIND):
  1100  		regalloc(&nod, t, Z);
  1101  		if(ewidth[tt] == SZ_VLONG || typeu[tt] && ewidth[tt] == SZ_INT){
  1102  			if(ft == TFLOAT)
  1103  				a = ACVTTSS2SQ;
  1104  			else
  1105  				a = ACVTTSD2SQ;
  1106  		}else{
  1107  			if(ft == TFLOAT)
  1108  				a = ACVTTSS2SL;
  1109  			else
  1110  				a = ACVTTSD2SL;
  1111  		}
  1112  		gins(a, f, &nod);
  1113  		gmove(&nod, t);
  1114  		regfree(&nod);
  1115  		return;
  1116  
  1117  /*
  1118   * uvlong to float
  1119   */
  1120  	case CASE(	TUVLONG,	TDOUBLE):
  1121  	case CASE(	TUVLONG,	TFLOAT):
  1122  		a = ACVTSQ2SS;
  1123  		if(tt == TDOUBLE)
  1124  			a = ACVTSQ2SD;
  1125  		regalloc(&nod, f, f);
  1126  		gmove(f, &nod);
  1127  		regalloc(&nod1, t, t);
  1128  		gins(ACMPQ, &nod, nodconst(0));
  1129  		gins(AJLT, Z, Z);
  1130  		p1 = p;
  1131  		gins(a, &nod, &nod1);
  1132  		gins(AJMP, Z, Z);
  1133  		p2 = p;
  1134  		patch(p1, pc);
  1135  		regalloc(&nod2, f, Z);
  1136  		regalloc(&nod3, f, Z);
  1137  		gmove(&nod, &nod2);
  1138  		gins(ASHRQ, nodconst(1), &nod2);
  1139  		gmove(&nod, &nod3);
  1140  		gins(AANDL, nodconst(1), &nod3);
  1141  		gins(AORQ, &nod3, &nod2);
  1142  		gins(a, &nod2, &nod1);
  1143  		gins(tt == TDOUBLE? AADDSD: AADDSS, &nod1, &nod1);
  1144  		regfree(&nod2);
  1145  		regfree(&nod3);
  1146  		patch(p2, pc);
  1147  		regfree(&nod);
  1148  		regfree(&nod1);
  1149  		return;
  1150  
  1151  	case CASE(	TULONG,	TDOUBLE):
  1152  	case CASE(	TUINT,	TDOUBLE):
  1153  	case CASE(	TULONG,	TFLOAT):
  1154  	case CASE(	TUINT,	TFLOAT):
  1155  		a = ACVTSQ2SS;
  1156  		if(tt == TDOUBLE)
  1157  			a = ACVTSQ2SD;
  1158  		regalloc(&nod, f, f);
  1159  		gins(AMOVLQZX, f, &nod);
  1160  		regalloc(&nod1, t, t);
  1161  		gins(a, &nod, &nod1);
  1162  		gmove(&nod1, t);
  1163  		regfree(&nod);
  1164  		regfree(&nod1);
  1165  		return;
  1166  
  1167  /*
  1168   * fix to float
  1169   */
  1170  	case CASE(	TCHAR,	TFLOAT):
  1171  	case CASE(	TUCHAR,	TFLOAT):
  1172  	case CASE(	TSHORT,	TFLOAT):
  1173  	case CASE(	TUSHORT,TFLOAT):
  1174  	case CASE(	TINT,	TFLOAT):
  1175  	case CASE(	TLONG,	TFLOAT):
  1176  	case	CASE(	TVLONG,	TFLOAT):
  1177  	case CASE(	TIND,	TFLOAT):
  1178  
  1179  	case CASE(	TCHAR,	TDOUBLE):
  1180  	case CASE(	TUCHAR,	TDOUBLE):
  1181  	case CASE(	TSHORT,	TDOUBLE):
  1182  	case CASE(	TUSHORT,TDOUBLE):
  1183  	case CASE(	TINT,	TDOUBLE):
  1184  	case CASE(	TLONG,	TDOUBLE):
  1185  	case CASE(	TVLONG,	TDOUBLE):
  1186  	case CASE(	TIND,	TDOUBLE):
  1187  		regalloc(&nod, t, t);
  1188  		if(ewidth[ft] == SZ_VLONG){
  1189  			if(tt == TFLOAT)
  1190  				a = ACVTSQ2SS;
  1191  			else
  1192  				a = ACVTSQ2SD;
  1193  		}else{
  1194  			if(tt == TFLOAT)
  1195  				a = ACVTSL2SS;
  1196  			else
  1197  				a = ACVTSL2SD;
  1198  		}
  1199  		gins(a, f, &nod);
  1200  		gmove(&nod, t);
  1201  		regfree(&nod);
  1202  		return;
  1203  
  1204  /*
  1205   * float to float
  1206   */
  1207  	case CASE(	TFLOAT,	TFLOAT):
  1208  		a = AMOVSS;
  1209  		break;
  1210  	case CASE(	TDOUBLE,TFLOAT):
  1211  		a = ACVTSD2SS;
  1212  		break;
  1213  	case CASE(	TFLOAT,	TDOUBLE):
  1214  		a = ACVTSS2SD;
  1215  		break;
  1216  	case CASE(	TDOUBLE,TDOUBLE):
  1217  		a = AMOVSD;
  1218  		break;
  1219  	}
  1220  	if(a == AMOVQ || a == AMOVSD || a == AMOVSS || a == AMOVL && ewidth[ft] == ewidth[tt])	/* TO DO: check AMOVL */
  1221  	if(samaddr(f, t))
  1222  		return;
  1223  	gins(a, f, t);
  1224  }
  1225  
  1226  void
  1227  doindex(Node *n)
  1228  {
  1229  	Node nod, nod1;
  1230  	int32 v;
  1231  
  1232  if(debug['Y'])
  1233  prtree(n, "index");
  1234  
  1235  if(n->left->complex >= FNX)
  1236  print("botch in doindex\n");
  1237  
  1238  	regalloc(&nod, &qregnode, Z);
  1239  	v = constnode.vconst;
  1240  	cgen(n->right, &nod);
  1241  	idx.ptr = D_NONE;
  1242  	if(n->left->op == OCONST)
  1243  		idx.ptr = D_CONST;
  1244  	else if(n->left->op == OREGISTER)
  1245  		idx.ptr = n->left->reg;
  1246  	else if(n->left->op != OADDR) {
  1247  		reg[D_BP]++;	// can't be used as a base
  1248  		regalloc(&nod1, &qregnode, Z);
  1249  		cgen(n->left, &nod1);
  1250  		idx.ptr = nod1.reg;
  1251  		regfree(&nod1);
  1252  		reg[D_BP]--;
  1253  	}
  1254  	idx.reg = nod.reg;
  1255  	regfree(&nod);
  1256  	constnode.vconst = v;
  1257  }
  1258  
  1259  void
  1260  gins(int a, Node *f, Node *t)
  1261  {
  1262  
  1263  	if(f != Z && f->op == OINDEX)
  1264  		doindex(f);
  1265  	if(t != Z && t->op == OINDEX)
  1266  		doindex(t);
  1267  	nextpc();
  1268  	p->as = a;
  1269  	if(f != Z)
  1270  		naddr(f, &p->from);
  1271  	if(t != Z)
  1272  		naddr(t, &p->to);
  1273  	if(debug['g'])
  1274  		print("%P\n", p);
  1275  }
  1276  
  1277  void
  1278  gopcode(int o, Type *ty, Node *f, Node *t)
  1279  {
  1280  	int a, et;
  1281  
  1282  	et = TLONG;
  1283  	if(ty != T)
  1284  		et = ty->etype;
  1285  	if(et == TIND && ewidth[TIND] == 4)
  1286  		et = TUINT;
  1287  	if(debug['M']) {
  1288  		if(f != Z && f->type != T)
  1289  			print("gop: %O %O[%s],", o, f->op, tnames[et]);
  1290  		else
  1291  			print("gop: %O Z,", o);
  1292  		if(t != Z && t->type != T)
  1293  			print("%O[%s]\n", t->op, tnames[t->type->etype]);
  1294  		else
  1295  			print("Z\n");
  1296  	}
  1297  	a = AGOK;
  1298  	switch(o) {
  1299  	case OCOM:
  1300  		a = ANOTL;
  1301  		if(et == TCHAR || et == TUCHAR)
  1302  			a = ANOTB;
  1303  		if(et == TSHORT || et == TUSHORT)
  1304  			a = ANOTW;
  1305  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1306  			a = ANOTQ;
  1307  		break;
  1308  
  1309  	case ONEG:
  1310  		a = ANEGL;
  1311  		if(et == TCHAR || et == TUCHAR)
  1312  			a = ANEGB;
  1313  		if(et == TSHORT || et == TUSHORT)
  1314  			a = ANEGW;
  1315  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1316  			a = ANEGQ;
  1317  		break;
  1318  
  1319  	case OADDR:
  1320  		a = ALEAQ;
  1321  		break;
  1322  
  1323  	case OASADD:
  1324  	case OADD:
  1325  		a = AADDL;
  1326  		if(et == TCHAR || et == TUCHAR)
  1327  			a = AADDB;
  1328  		if(et == TSHORT || et == TUSHORT)
  1329  			a = AADDW;
  1330  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1331  			a = AADDQ;
  1332  		if(et == TFLOAT)
  1333  			a = AADDSS;
  1334  		if(et == TDOUBLE)
  1335  			a = AADDSD;
  1336  		break;
  1337  
  1338  	case OASSUB:
  1339  	case OSUB:
  1340  		a = ASUBL;
  1341  		if(et == TCHAR || et == TUCHAR)
  1342  			a = ASUBB;
  1343  		if(et == TSHORT || et == TUSHORT)
  1344  			a = ASUBW;
  1345  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1346  			a = ASUBQ;
  1347  		if(et == TFLOAT)
  1348  			a = ASUBSS;
  1349  		if(et == TDOUBLE)
  1350  			a = ASUBSD;
  1351  		break;
  1352  
  1353  	case OASOR:
  1354  	case OOR:
  1355  		a = AORL;
  1356  		if(et == TCHAR || et == TUCHAR)
  1357  			a = AORB;
  1358  		if(et == TSHORT || et == TUSHORT)
  1359  			a = AORW;
  1360  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1361  			a = AORQ;
  1362  		break;
  1363  
  1364  	case OASAND:
  1365  	case OAND:
  1366  		a = AANDL;
  1367  		if(et == TCHAR || et == TUCHAR)
  1368  			a = AANDB;
  1369  		if(et == TSHORT || et == TUSHORT)
  1370  			a = AANDW;
  1371  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1372  			a = AANDQ;
  1373  		break;
  1374  
  1375  	case OASXOR:
  1376  	case OXOR:
  1377  		a = AXORL;
  1378  		if(et == TCHAR || et == TUCHAR)
  1379  			a = AXORB;
  1380  		if(et == TSHORT || et == TUSHORT)
  1381  			a = AXORW;
  1382  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1383  			a = AXORQ;
  1384  		break;
  1385  
  1386  	case OASLSHR:
  1387  	case OLSHR:
  1388  		a = ASHRL;
  1389  		if(et == TCHAR || et == TUCHAR)
  1390  			a = ASHRB;
  1391  		if(et == TSHORT || et == TUSHORT)
  1392  			a = ASHRW;
  1393  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1394  			a = ASHRQ;
  1395  		break;
  1396  
  1397  	case OASASHR:
  1398  	case OASHR:
  1399  		a = ASARL;
  1400  		if(et == TCHAR || et == TUCHAR)
  1401  			a = ASARB;
  1402  		if(et == TSHORT || et == TUSHORT)
  1403  			a = ASARW;
  1404  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1405  			a = ASARQ;
  1406  		break;
  1407  
  1408  	case OASASHL:
  1409  	case OASHL:
  1410  		a = ASALL;
  1411  		if(et == TCHAR || et == TUCHAR)
  1412  			a = ASALB;
  1413  		if(et == TSHORT || et == TUSHORT)
  1414  			a = ASALW;
  1415  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1416  			a = ASALQ;
  1417  		break;
  1418  
  1419  	case OROTL:
  1420  		a = AROLL;
  1421  		if(et == TCHAR || et == TUCHAR)
  1422  			a = AROLB;
  1423  		if(et == TSHORT || et == TUSHORT)
  1424  			a = AROLW;
  1425  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1426  			a = AROLQ;
  1427  		break;
  1428  
  1429  	case OFUNC:
  1430  		a = ACALL;
  1431  		break;
  1432  
  1433  	case OASMUL:
  1434  	case OMUL:
  1435  		if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
  1436  			t = Z;
  1437  		a = AIMULL;
  1438  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1439  			a = AIMULQ;
  1440  		if(et == TFLOAT)
  1441  			a = AMULSS;
  1442  		if(et == TDOUBLE)
  1443  			a = AMULSD;
  1444  		break;
  1445  
  1446  	case OASMOD:
  1447  	case OMOD:
  1448  	case OASDIV:
  1449  	case ODIV:
  1450  		a = AIDIVL;
  1451  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1452  			a = AIDIVQ;
  1453  		if(et == TFLOAT)
  1454  			a = ADIVSS;
  1455  		if(et == TDOUBLE)
  1456  			a = ADIVSD;
  1457  		break;
  1458  
  1459  	case OASLMUL:
  1460  	case OLMUL:
  1461  		a = AMULL;
  1462  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1463  			a = AMULQ;
  1464  		break;
  1465  
  1466  	case OASLMOD:
  1467  	case OLMOD:
  1468  	case OASLDIV:
  1469  	case OLDIV:
  1470  		a = ADIVL;
  1471  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1472  			a = ADIVQ;
  1473  		break;
  1474  
  1475  	case OEQ:
  1476  	case ONE:
  1477  	case OLT:
  1478  	case OLE:
  1479  	case OGE:
  1480  	case OGT:
  1481  	case OLO:
  1482  	case OLS:
  1483  	case OHS:
  1484  	case OHI:
  1485  		a = ACMPL;
  1486  		if(et == TCHAR || et == TUCHAR)
  1487  			a = ACMPB;
  1488  		if(et == TSHORT || et == TUSHORT)
  1489  			a = ACMPW;
  1490  		if(et == TVLONG || et == TUVLONG || et == TIND)
  1491  			a = ACMPQ;
  1492  		if(et == TFLOAT)
  1493  			a = AUCOMISS;
  1494  		if(et == TDOUBLE)
  1495  			a = AUCOMISD;
  1496  		gins(a, f, t);
  1497  		switch(o) {
  1498  		case OEQ:	a = AJEQ; break;
  1499  		case ONE:	a = AJNE; break;
  1500  		case OLT:	a = AJLT; break;
  1501  		case OLE:	a = AJLE; break;
  1502  		case OGE:	a = AJGE; break;
  1503  		case OGT:	a = AJGT; break;
  1504  		case OLO:	a = AJCS; break;
  1505  		case OLS:	a = AJLS; break;
  1506  		case OHS:	a = AJCC; break;
  1507  		case OHI:	a = AJHI; break;
  1508  		}
  1509  		gins(a, Z, Z);
  1510  		return;
  1511  	}
  1512  	if(a == AGOK)
  1513  		diag(Z, "bad in gopcode %O", o);
  1514  	gins(a, f, t);
  1515  }
  1516  
  1517  int
  1518  samaddr(Node *f, Node *t)
  1519  {
  1520  	return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
  1521  }
  1522  
  1523  void
  1524  gbranch(int o)
  1525  {
  1526  	int a;
  1527  
  1528  	a = AGOK;
  1529  	switch(o) {
  1530  	case ORETURN:
  1531  		a = ARET;
  1532  		break;
  1533  	case OGOTO:
  1534  		a = AJMP;
  1535  		break;
  1536  	}
  1537  	nextpc();
  1538  	if(a == AGOK) {
  1539  		diag(Z, "bad in gbranch %O",  o);
  1540  		nextpc();
  1541  	}
  1542  	p->as = a;
  1543  }
  1544  
  1545  void
  1546  patch(Prog *op, int32 pc)
  1547  {
  1548  	op->to.offset = pc;
  1549  	op->to.type = D_BRANCH;
  1550  	op->to.u.branch = nil;
  1551  	op->pcond = nil;
  1552  }
  1553  
  1554  void
  1555  gpseudo(int a, Sym *s, Node *n)
  1556  {
  1557  
  1558  	nextpc();
  1559  	p->as = a;
  1560  	p->from.type = D_EXTERN;
  1561  	p->from.sym = linksym(s);
  1562  
  1563  	switch(a) {
  1564  	case ATEXT:
  1565  		p->from.scale = textflag;
  1566  		textflag = 0;
  1567  		break;
  1568  	case AGLOBL:
  1569  		p->from.scale = s->dataflag;
  1570  		break;
  1571  	}
  1572  
  1573  	if(s->class == CSTATIC)
  1574  		p->from.type = D_STATIC;
  1575  	naddr(n, &p->to);
  1576  	if(a == ADATA || a == AGLOBL)
  1577  		pc--;
  1578  }
  1579  
  1580  void
  1581  gpcdata(int index, int value)
  1582  {
  1583  	Node n1;
  1584  	
  1585  	n1 = *nodconst(index);
  1586  	gins(APCDATA, &n1, nodconst(value));
  1587  }
  1588  
  1589  void
  1590  gprefetch(Node *n)
  1591  {
  1592  	Node n1;
  1593  	
  1594  	regalloc(&n1, n, Z);
  1595  	gmove(n, &n1);
  1596  	n1.op = OINDREG;
  1597  	gins(APREFETCHNTA, &n1, Z);
  1598  	regfree(&n1);
  1599  }
  1600  
  1601  int
  1602  sconst(Node *n)
  1603  {
  1604  	int32 v;
  1605  
  1606  	if(n->op == OCONST && !typefd[n->type->etype]) {
  1607  		v = n->vconst;
  1608  		if(v >= -32766L && v < 32766L)
  1609  			return 1;
  1610  	}
  1611  	return 0;
  1612  }
  1613  
  1614  int32
  1615  exreg(Type *t)
  1616  {
  1617  	int32 o;
  1618  
  1619  	if(typechlpv[t->etype]) {
  1620  		if(exregoffset >= 64)
  1621  			return 0;
  1622  		o = exregoffset;
  1623  		exregoffset += ewidth[TIND];
  1624  		return o+1;	// +1 to avoid 0 == failure; naddr's case OEXREG will subtract 1.
  1625  	}
  1626  	return 0;
  1627  }
  1628  
  1629  schar	ewidth[NTYPE] =
  1630  {
  1631  	-1,		/*[TXXX]*/
  1632  	SZ_CHAR,	/*[TCHAR]*/
  1633  	SZ_CHAR,	/*[TUCHAR]*/
  1634  	SZ_SHORT,	/*[TSHORT]*/
  1635  	SZ_SHORT,	/*[TUSHORT]*/
  1636  	SZ_INT,		/*[TINT]*/
  1637  	SZ_INT,		/*[TUINT]*/
  1638  	SZ_LONG,	/*[TLONG]*/
  1639  	SZ_LONG,	/*[TULONG]*/
  1640  	SZ_VLONG,	/*[TVLONG]*/
  1641  	SZ_VLONG,	/*[TUVLONG]*/
  1642  	SZ_FLOAT,	/*[TFLOAT]*/
  1643  	SZ_DOUBLE,	/*[TDOUBLE]*/
  1644  	SZ_IND,		/*[TIND]*/
  1645  	0,		/*[TFUNC]*/
  1646  	-1,		/*[TARRAY]*/
  1647  	0,		/*[TVOID]*/
  1648  	-1,		/*[TSTRUCT]*/
  1649  	-1,		/*[TUNION]*/
  1650  	SZ_INT,		/*[TENUM]*/
  1651  };
  1652  int32	ncast[NTYPE] =
  1653  {
  1654  	0,				/*[TXXX]*/
  1655  	BCHAR|BUCHAR,			/*[TCHAR]*/
  1656  	BCHAR|BUCHAR,			/*[TUCHAR]*/
  1657  	BSHORT|BUSHORT,			/*[TSHORT]*/
  1658  	BSHORT|BUSHORT,			/*[TUSHORT]*/
  1659  	BINT|BUINT|BLONG|BULONG,	/*[TINT]*/
  1660  	BINT|BUINT|BLONG|BULONG,	/*[TUINT]*/
  1661  	BINT|BUINT|BLONG|BULONG,	/*[TLONG]*/
  1662  	BINT|BUINT|BLONG|BULONG,	/*[TULONG]*/
  1663  	BVLONG|BUVLONG|BIND,			/*[TVLONG]*/
  1664  	BVLONG|BUVLONG|BIND,			/*[TUVLONG]*/
  1665  	BFLOAT,				/*[TFLOAT]*/
  1666  	BDOUBLE,			/*[TDOUBLE]*/
  1667  	BVLONG|BUVLONG|BIND,		/*[TIND]*/
  1668  	0,				/*[TFUNC]*/
  1669  	0,				/*[TARRAY]*/
  1670  	0,				/*[TVOID]*/
  1671  	BSTRUCT,			/*[TSTRUCT]*/
  1672  	BUNION,				/*[TUNION]*/
  1673  	0,				/*[TENUM]*/
  1674  };