github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/8c/txt.c (about)

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