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