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

     1  // Inferno utils/5c/txt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5c/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  
    32  #include "gc.h"
    33  
    34  
    35  int thechar = '5';
    36  char *thestring = "arm";
    37  
    38  LinkArch	*thelinkarch = &linkarm;
    39  
    40  void
    41  linkarchinit(void)
    42  {
    43  }
    44  
    45  void
    46  ginit(void)
    47  {
    48  	Type *t;
    49  
    50  	exregoffset = REGEXT;
    51  	exfregoffset = FREGEXT;
    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.reg = NREG;
    66  	zprog.from.type = D_NONE;
    67  	zprog.from.name = D_NONE;
    68  	zprog.from.reg = NREG;
    69  	zprog.to = zprog.from;
    70  	zprog.scond = 0xE;
    71  
    72  	regnode.op = OREGISTER;
    73  	regnode.class = CEXREG;
    74  	regnode.reg = REGTMP;
    75  	regnode.complex = 0;
    76  	regnode.addable = 11;
    77  	regnode.type = types[TLONG];
    78  
    79  	constnode.op = OCONST;
    80  	constnode.class = CXXX;
    81  	constnode.complex = 0;
    82  	constnode.addable = 20;
    83  	constnode.type = types[TLONG];
    84  
    85  	fconstnode.op = OCONST;
    86  	fconstnode.class = CXXX;
    87  	fconstnode.complex = 0;
    88  	fconstnode.addable = 20;
    89  	fconstnode.type = types[TDOUBLE];
    90  
    91  	nodsafe = new(ONAME, Z, Z);
    92  	nodsafe->sym = slookup(".safe");
    93  	nodsafe->type = types[TINT];
    94  	nodsafe->etype = types[TINT]->etype;
    95  	nodsafe->class = CAUTO;
    96  	complex(nodsafe);
    97  
    98  	t = typ(TARRAY, types[TCHAR]);
    99  	symrathole = slookup(".rathole");
   100  	symrathole->class = CGLOBL;
   101  	symrathole->type = t;
   102  
   103  	nodrat = new(ONAME, Z, Z);
   104  	nodrat->sym = symrathole;
   105  	nodrat->type = types[TIND];
   106  	nodrat->etype = TVOID;
   107  	nodrat->class = CGLOBL;
   108  	complex(nodrat);
   109  	nodrat->type = t;
   110  
   111  	nodret = new(ONAME, Z, Z);
   112  	nodret->sym = slookup(".ret");
   113  	nodret->type = types[TIND];
   114  	nodret->etype = TIND;
   115  	nodret->class = CPARAM;
   116  	nodret = new(OIND, nodret, Z);
   117  	complex(nodret);
   118  
   119  	com64init();
   120  
   121  	memset(reg, 0, sizeof(reg));
   122  }
   123  
   124  void
   125  gclean(void)
   126  {
   127  	int i;
   128  	Sym *s;
   129  
   130  	for(i=0; i<NREG; i++)
   131  		if(reg[i])
   132  			diag(Z, "reg %d left allocated", i);
   133  	for(i=NREG; i<NREG+NFREG; i++)
   134  		if(reg[i])
   135  			diag(Z, "freg %d left allocated", i-NREG);
   136  	while(mnstring)
   137  		outstring("", 1L);
   138  	symstring->type->width = nstring;
   139  	symrathole->type->width = nrathole;
   140  	for(i=0; i<NHASH; i++)
   141  	for(s = hash[i]; s != S; s = s->link) {
   142  		if(s->type == T)
   143  			continue;
   144  		if(s->type->width == 0)
   145  			continue;
   146  		if(s->class != CGLOBL && s->class != CSTATIC)
   147  			continue;
   148  		if(s->type == types[TENUM])
   149  			continue;
   150  		gpseudo(AGLOBL, s, nodconst(s->type->width));
   151  	}
   152  	nextpc();
   153  	p->as = AEND;
   154  	outcode();
   155  }
   156  
   157  void
   158  nextpc(void)
   159  {
   160  	Plist *pl;
   161  
   162  	p = alloc(sizeof(*p));
   163  	*p = zprog;
   164  	p->lineno = nearln;
   165  	pc++;
   166  	if(lastp == nil) {
   167  		pl = linknewplist(ctxt);
   168  		pl->firstpc = p;
   169  	} else
   170  		lastp->link = p;
   171  	lastp = p;
   172  }
   173  
   174  void
   175  gargs(Node *n, Node *tn1, Node *tn2)
   176  {
   177  	int32 regs;
   178  	Node fnxargs[20], *fnxp;
   179  
   180  	regs = cursafe;
   181  
   182  	fnxp = fnxargs;
   183  	garg1(n, tn1, tn2, 0, &fnxp);	/* compile fns to temps */
   184  
   185  	curarg = 0;
   186  	fnxp = fnxargs;
   187  	garg1(n, tn1, tn2, 1, &fnxp);	/* compile normal args and temps */
   188  
   189  	cursafe = regs;
   190  }
   191  
   192  void
   193  garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
   194  {
   195  	Node nod;
   196  
   197  	if(n == Z)
   198  		return;
   199  	if(n->op == OLIST) {
   200  		garg1(n->left, tn1, tn2, f, fnxp);
   201  		garg1(n->right, tn1, tn2, f, fnxp);
   202  		return;
   203  	}
   204  	if(f == 0) {
   205  		if(n->complex >= FNX) {
   206  			regsalloc(*fnxp, n);
   207  			nod = znode;
   208  			nod.op = OAS;
   209  			nod.left = *fnxp;
   210  			nod.right = n;
   211  			nod.type = n->type;
   212  			cgen(&nod, Z);
   213  			(*fnxp)++;
   214  		}
   215  		return;
   216  	}
   217  	if(typesuv[n->type->etype]) {
   218  		regaalloc(tn2, n);
   219  		if(n->complex >= FNX) {
   220  			sugen(*fnxp, tn2, n->type->width);
   221  			(*fnxp)++;
   222  		} else
   223  			sugen(n, tn2, n->type->width);
   224  		return;
   225  	}
   226  	if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) {
   227  		regaalloc1(tn1, n);
   228  		if(n->complex >= FNX) {
   229  			cgen(*fnxp, tn1);
   230  			(*fnxp)++;
   231  		} else
   232  			cgen(n, tn1);
   233  		return;
   234  	}
   235  	regalloc(tn1, n, Z);
   236  	if(n->complex >= FNX) {
   237  		cgen(*fnxp, tn1);
   238  		(*fnxp)++;
   239  	} else
   240  		cgen(n, tn1);
   241  	regaalloc(tn2, n);
   242  	gopcode(OAS, tn1, Z, tn2);
   243  	regfree(tn1);
   244  }
   245  
   246  Node*
   247  nodconst(int32 v)
   248  {
   249  	constnode.vconst = v;
   250  	return &constnode;
   251  }
   252  
   253  Node*
   254  nod32const(vlong v)
   255  {
   256  	constnode.vconst = v & MASK(32);
   257  	return &constnode;
   258  }
   259  
   260  Node*
   261  nodfconst(double d)
   262  {
   263  	fconstnode.fconst = d;
   264  	return &fconstnode;
   265  }
   266  
   267  void
   268  nodreg(Node *n, Node *nn, int reg)
   269  {
   270  	*n = regnode;
   271  	n->reg = reg;
   272  	n->type = nn->type;
   273  	n->lineno = nn->lineno;
   274  }
   275  
   276  void
   277  regret(Node *n, Node *nn, Type *t, int mode)
   278  {
   279  	int r;
   280  
   281  	if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
   282  		r = REGRET;
   283  		if(typefd[nn->type->etype])
   284  			r = FREGRET+NREG;
   285  		nodreg(n, nn, r);
   286  		reg[r]++;
   287  		return;
   288  	}
   289  	
   290  	if(mode == 1) {
   291  		// fetch returned value after call.
   292  		// already called gargs, so curarg is set.
   293  		curarg = (curarg+3) & ~3;
   294  		regaalloc(n, nn);
   295  		return;
   296  	}
   297  	
   298  	if(mode == 2) {
   299  		// store value to be returned.
   300  		// must compute arg offset.
   301  		if(t->etype != TFUNC)
   302  			fatal(Z, "bad regret func %T", t);
   303  		*n = *nn;
   304  		n->op = ONAME;
   305  		n->class = CPARAM;
   306  		n->sym = slookup(".ret");
   307  		n->complex = nodret->complex;
   308  		n->xoffset = argsize(0);
   309  		n->addable = 20;
   310  		return;
   311  	}
   312  	
   313  	fatal(Z, "bad regret");
   314  }
   315  
   316  int
   317  tmpreg(void)
   318  {
   319  	int i;
   320  
   321  	for(i=REGRET+1; i<NREG; i++)
   322  		if(reg[i] == 0)
   323  			return i;
   324  	diag(Z, "out of fixed registers");
   325  	return 0;
   326  }
   327  
   328  void
   329  regalloc(Node *n, Node *tn, Node *o)
   330  {
   331  	int i;
   332  
   333  	switch(tn->type->etype) {
   334  	case TCHAR:
   335  	case TUCHAR:
   336  	case TSHORT:
   337  	case TUSHORT:
   338  	case TINT:
   339  	case TUINT:
   340  	case TLONG:
   341  	case TULONG:
   342  	case TIND:
   343  		if(o != Z && o->op == OREGISTER) {
   344  			i = o->reg;
   345  			if(i >= 0 && i < NREG)
   346  				goto out;
   347  		}
   348  		for(i=REGRET+1; i<=REGEXT-2; i++)
   349  			if(reg[i] == 0)
   350  				goto out;
   351  		diag(tn, "out of fixed registers");
   352  		goto err;
   353  
   354  	case TFLOAT:
   355  	case TDOUBLE:
   356  	case TVLONG:
   357  		if(o != Z && o->op == OREGISTER) {
   358  			i = o->reg;
   359  			if(i >= NREG && i < NREG+NFREG)
   360  				goto out;
   361  		}
   362  		for(i=NREG; i<NREG+NFREG; i++)
   363  			if(reg[i] == 0)
   364  				goto out;
   365  		diag(tn, "out of float registers");
   366  		goto err;
   367  	}
   368  	diag(tn, "unknown type in regalloc: %T", tn->type);
   369  err:
   370  	nodreg(n, tn, 0);
   371  	return;
   372  out:
   373  	reg[i]++;
   374  	nodreg(n, tn, i);
   375  }
   376  
   377  void
   378  regialloc(Node *n, Node *tn, Node *o)
   379  {
   380  	Node nod;
   381  
   382  	nod = *tn;
   383  	nod.type = types[TIND];
   384  	regalloc(n, &nod, o);
   385  }
   386  
   387  void
   388  regfree(Node *n)
   389  {
   390  	int i;
   391  
   392  	i = 0;
   393  	if(n->op != OREGISTER && n->op != OINDREG)
   394  		goto err;
   395  	i = n->reg;
   396  	if(i < 0 || i >= nelem(reg))
   397  		goto err;
   398  	if(reg[i] <= 0)
   399  		goto err;
   400  	reg[i]--;
   401  	return;
   402  err:
   403  	diag(n, "error in regfree: %d", i);
   404  }
   405  
   406  void
   407  regsalloc(Node *n, Node *nn)
   408  {
   409  	cursafe = align(cursafe, nn->type, Aaut3, nil);
   410  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   411  	*n = *nodsafe;
   412  	n->xoffset = -(stkoff + cursafe);
   413  	n->type = nn->type;
   414  	n->etype = nn->type->etype;
   415  	n->lineno = nn->lineno;
   416  }
   417  
   418  void
   419  regaalloc1(Node *n, Node *nn)
   420  {
   421  	if(REGARG < 0) {
   422  		fatal(n, "regaalloc1 and REGARG<0");
   423  		return;
   424  	}
   425  	nodreg(n, nn, REGARG);
   426  	reg[REGARG]++;
   427  	curarg = align(curarg, nn->type, Aarg1, nil);
   428  	curarg = align(curarg, nn->type, Aarg2, nil);
   429  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   430  }
   431  
   432  void
   433  regaalloc(Node *n, Node *nn)
   434  {
   435  	curarg = align(curarg, nn->type, Aarg1, nil);
   436  	*n = *nn;
   437  	n->op = OINDREG;
   438  	n->reg = REGSP;
   439  	n->xoffset = curarg + SZ_LONG;
   440  	n->complex = 0;
   441  	n->addable = 20;
   442  	curarg = align(curarg, nn->type, Aarg2, nil);
   443  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   444  }
   445  
   446  void
   447  regind(Node *n, Node *nn)
   448  {
   449  
   450  	if(n->op != OREGISTER) {
   451  		diag(n, "regind not OREGISTER");
   452  		return;
   453  	}
   454  	n->op = OINDREG;
   455  	n->type = nn->type;
   456  }
   457  
   458  void
   459  raddr(Node *n, Prog *p)
   460  {
   461  	Addr a;
   462  
   463  	naddr(n, &a);
   464  	if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
   465  		a.type = D_REG;
   466  		a.reg = 0;
   467  	}
   468  	if(a.type != D_REG && a.type != D_FREG) {
   469  		if(n)
   470  			diag(n, "bad in raddr: %O", n->op);
   471  		else
   472  			diag(n, "bad in raddr: <null>");
   473  		p->reg = NREG;
   474  	} else
   475  		p->reg = a.reg;
   476  }
   477  
   478  void
   479  naddr(Node *n, Addr *a)
   480  {
   481  	int32 v;
   482  
   483  	a->type = D_NONE;
   484  	if(n == Z)
   485  		return;
   486  	switch(n->op) {
   487  	default:
   488  	bad:
   489  		diag(n, "bad in naddr: %O", n->op);
   490  		break;
   491  
   492  	case OREGISTER:
   493  		a->type = D_REG;
   494  		a->sym = nil;
   495  		a->reg = n->reg;
   496  		if(a->reg >= NREG) {
   497  			a->type = D_FREG;
   498  			a->reg -= NREG;
   499  		}
   500  		break;
   501  
   502  	case OIND:
   503  		naddr(n->left, a);
   504  		if(a->type == D_REG) {
   505  			a->type = D_OREG;
   506  			break;
   507  		}
   508  		if(a->type == D_CONST) {
   509  			a->type = D_OREG;
   510  			break;
   511  		}
   512  		goto bad;
   513  
   514  	case OINDREG:
   515  		a->type = D_OREG;
   516  		a->sym = nil;
   517  		a->offset = n->xoffset;
   518  		a->reg = n->reg;
   519  		break;
   520  
   521  	case ONAME:
   522  		a->etype = n->etype;
   523  		a->type = D_OREG;
   524  		a->name = D_STATIC;
   525  		a->sym = linksym(n->sym);
   526  		a->offset = n->xoffset;
   527  		if(n->class == CSTATIC)
   528  			break;
   529  		if(n->class == CEXTERN || n->class == CGLOBL) {
   530  			a->name = D_EXTERN;
   531  			break;
   532  		}
   533  		if(n->class == CAUTO) {
   534  			a->name = D_AUTO;
   535  			break;
   536  		}
   537  		if(n->class == CPARAM) {
   538  			a->name = D_PARAM;
   539  			break;
   540  		}
   541  		goto bad;
   542  
   543  	case OCONST:
   544  		a->sym = nil;
   545  		a->reg = NREG;
   546  		if(typefd[n->type->etype]) {
   547  			a->type = D_FCONST;
   548  			a->u.dval = n->fconst;
   549  		} else {
   550  			a->type = D_CONST;
   551  			a->offset = n->vconst;
   552  		}
   553  		break;
   554  
   555  	case OADDR:
   556  		naddr(n->left, a);
   557  		if(a->type == D_OREG) {
   558  			a->type = D_CONST;
   559  			break;
   560  		}
   561  		goto bad;
   562  
   563  	case OADD:
   564  		if(n->left->op == OCONST) {
   565  			naddr(n->left, a);
   566  			v = a->offset;
   567  			naddr(n->right, a);
   568  		} else {
   569  			naddr(n->right, a);
   570  			v = a->offset;
   571  			naddr(n->left, a);
   572  		}
   573  		a->offset += v;
   574  		break;
   575  
   576  	}
   577  }
   578  
   579  void
   580  fop(int as, int f1, int f2, Node *t)
   581  {
   582  	Node nod1, nod2, nod3;
   583  
   584  	nodreg(&nod1, t, NREG+f1);
   585  	nodreg(&nod2, t, NREG+f2);
   586  	regalloc(&nod3, t, t);
   587  	gopcode(as, &nod1, &nod2, &nod3);
   588  	gmove(&nod3, t);
   589  	regfree(&nod3);
   590  }
   591  
   592  void
   593  gmovm(Node *f, Node *t, int w)
   594  {
   595  	gins(AMOVM, f, t);
   596  	p->scond |= C_UBIT;
   597  	if(w)
   598  		p->scond |= C_WBIT;
   599  }
   600  
   601  void
   602  gmove(Node *f, Node *t)
   603  {
   604  	int ft, tt, a;
   605  	Node nod, nod1;
   606  	Prog *p1;
   607  
   608  	ft = f->type->etype;
   609  	tt = t->type->etype;
   610  
   611  	if(ft == TDOUBLE && f->op == OCONST) {
   612  	}
   613  	if(ft == TFLOAT && f->op == OCONST) {
   614  	}
   615  
   616  	/*
   617  	 * a load --
   618  	 * put it into a register then
   619  	 * worry what to do with it.
   620  	 */
   621  	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
   622  		switch(ft) {
   623  		default:
   624  			a = AMOVW;
   625  			break;
   626  		case TFLOAT:
   627  			a = AMOVF;
   628  			break;
   629  		case TDOUBLE:
   630  			a = AMOVD;
   631  			break;
   632  		case TCHAR:
   633  			a = AMOVBS;
   634  			break;
   635  		case TUCHAR:
   636  			a = AMOVBU;
   637  			break;
   638  		case TSHORT:
   639  			a = AMOVHS;
   640  			break;
   641  		case TUSHORT:
   642  			a = AMOVHU;
   643  			break;
   644  		}
   645  		if(typechlp[ft] && typeilp[tt])
   646  			regalloc(&nod, t, t);
   647  		else
   648  			regalloc(&nod, f, t);
   649  		gins(a, f, &nod);
   650  		gmove(&nod, t);
   651  		regfree(&nod);
   652  		return;
   653  	}
   654  
   655  	/*
   656  	 * a store --
   657  	 * put it into a register then
   658  	 * store it.
   659  	 */
   660  	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
   661  		switch(tt) {
   662  		default:
   663  			a = AMOVW;
   664  			break;
   665  		case TUCHAR:
   666  			a = AMOVBU;
   667  			break;
   668  		case TCHAR:
   669  			a = AMOVBS;
   670  			break;
   671  		case TUSHORT:
   672  			a = AMOVHU;
   673  			break;
   674  		case TSHORT:
   675  			a = AMOVHS;
   676  			break;
   677  		case TFLOAT:
   678  			a = AMOVF;
   679  			break;
   680  		case TVLONG:
   681  		case TDOUBLE:
   682  			a = AMOVD;
   683  			break;
   684  		}
   685  		if(ft == tt)
   686  			regalloc(&nod, t, f);
   687  		else
   688  			regalloc(&nod, t, Z);
   689  		gmove(f, &nod);
   690  		gins(a, &nod, t);
   691  		regfree(&nod);
   692  		return;
   693  	}
   694  
   695  	/*
   696  	 * type x type cross table
   697  	 */
   698  	a = AGOK;
   699  	switch(ft) {
   700  	case TDOUBLE:
   701  	case TVLONG:
   702  	case TFLOAT:
   703  		switch(tt) {
   704  		case TDOUBLE:
   705  		case TVLONG:
   706  			a = AMOVD;
   707  			if(ft == TFLOAT)
   708  				a = AMOVFD;
   709  			break;
   710  		case TFLOAT:
   711  			a = AMOVDF;
   712  			if(ft == TFLOAT)
   713  				a = AMOVF;
   714  			break;
   715  		case TINT:
   716  		case TUINT:
   717  		case TLONG:
   718  		case TULONG:
   719  		case TIND:
   720  			a = AMOVDW;
   721  			if(ft == TFLOAT)
   722  				a = AMOVFW;
   723  			break;
   724  		case TSHORT:
   725  		case TUSHORT:
   726  		case TCHAR:
   727  		case TUCHAR:
   728  			a = AMOVDW;
   729  			if(ft == TFLOAT)
   730  				a = AMOVFW;
   731  			break;
   732  		}
   733  		break;
   734  	case TUINT:
   735  	case TULONG:
   736  		if(tt == TFLOAT || tt == TDOUBLE) {
   737  			// ugly and probably longer than necessary,
   738  			// but vfp has a single instruction for this,
   739  			// so hopefully it won't last long.
   740  			//
   741  			//	tmp = f
   742  			//	tmp1 = tmp & 0x80000000
   743  			//	tmp ^= tmp1
   744  			//	t = float(int32(tmp))
   745  			//	if(tmp1)
   746  			//		t += 2147483648.
   747  			//
   748  			regalloc(&nod, f, Z);
   749  			regalloc(&nod1, f, Z);
   750  			gins(AMOVW, f, &nod);
   751  			gins(AMOVW, &nod, &nod1);
   752  			gins(AAND, nodconst(0x80000000), &nod1);
   753  			gins(AEOR, &nod1, &nod);
   754  			if(tt == TFLOAT)
   755  				gins(AMOVWF, &nod, t);
   756  			else
   757  				gins(AMOVWD, &nod, t);
   758  			gins(ACMP, nodconst(0), Z);
   759  			raddr(&nod1, p);
   760  			gins(ABEQ, Z, Z);
   761  			regfree(&nod);
   762  			regfree(&nod1);
   763  			p1 = p;
   764  			regalloc(&nod, t, Z);
   765  			gins(AMOVF, nodfconst(2147483648.), &nod);
   766  			gins(AADDF, &nod, t);
   767  			regfree(&nod);
   768  			patch(p1, pc);
   769  			return;
   770  		}
   771  		// fall through
   772  	
   773  	case TINT:
   774  	case TLONG:
   775  	case TIND:
   776  		switch(tt) {
   777  		case TDOUBLE:
   778  			gins(AMOVWD, f, t);
   779  			return;
   780  		case TFLOAT:
   781  			gins(AMOVWF, f, t);
   782  			return;
   783  		case TINT:
   784  		case TUINT:
   785  		case TLONG:
   786  		case TULONG:
   787  		case TIND:
   788  		case TSHORT:
   789  		case TUSHORT:
   790  		case TCHAR:
   791  		case TUCHAR:
   792  			a = AMOVW;
   793  			break;
   794  		}
   795  		break;
   796  	case TSHORT:
   797  		switch(tt) {
   798  		case TDOUBLE:
   799  			regalloc(&nod, f, Z);
   800  			gins(AMOVHS, f, &nod);
   801  			gins(AMOVWD, &nod, t);
   802  			regfree(&nod);
   803  			return;
   804  		case TFLOAT:
   805  			regalloc(&nod, f, Z);
   806  			gins(AMOVHS, f, &nod);
   807  			gins(AMOVWF, &nod, t);
   808  			regfree(&nod);
   809  			return;
   810  		case TUINT:
   811  		case TINT:
   812  		case TULONG:
   813  		case TLONG:
   814  		case TIND:
   815  			a = AMOVHS;
   816  			break;
   817  		case TSHORT:
   818  		case TUSHORT:
   819  		case TCHAR:
   820  		case TUCHAR:
   821  			a = AMOVW;
   822  			break;
   823  		}
   824  		break;
   825  	case TUSHORT:
   826  		switch(tt) {
   827  		case TDOUBLE:
   828  			regalloc(&nod, f, Z);
   829  			gins(AMOVHU, f, &nod);
   830  			gins(AMOVWD, &nod, t);
   831  			regfree(&nod);
   832  			return;
   833  		case TFLOAT:
   834  			regalloc(&nod, f, Z);
   835  			gins(AMOVHU, f, &nod);
   836  			gins(AMOVWF, &nod, t);
   837  			regfree(&nod);
   838  			return;
   839  		case TINT:
   840  		case TUINT:
   841  		case TLONG:
   842  		case TULONG:
   843  		case TIND:
   844  			a = AMOVHU;
   845  			break;
   846  		case TSHORT:
   847  		case TUSHORT:
   848  		case TCHAR:
   849  		case TUCHAR:
   850  			a = AMOVW;
   851  			break;
   852  		}
   853  		break;
   854  	case TCHAR:
   855  		switch(tt) {
   856  		case TDOUBLE:
   857  			regalloc(&nod, f, Z);
   858  			gins(AMOVBS, f, &nod);
   859  			gins(AMOVWD, &nod, t);
   860  			regfree(&nod);
   861  			return;
   862  		case TFLOAT:
   863  			regalloc(&nod, f, Z);
   864  			gins(AMOVBS, f, &nod);
   865  			gins(AMOVWF, &nod, t);
   866  			regfree(&nod);
   867  			return;
   868  		case TINT:
   869  		case TUINT:
   870  		case TLONG:
   871  		case TULONG:
   872  		case TIND:
   873  		case TSHORT:
   874  		case TUSHORT:
   875  			a = AMOVBS;
   876  			break;
   877  		case TCHAR:
   878  		case TUCHAR:
   879  			a = AMOVW;
   880  			break;
   881  		}
   882  		break;
   883  	case TUCHAR:
   884  		switch(tt) {
   885  		case TDOUBLE:
   886  			regalloc(&nod, f, Z);
   887  			gins(AMOVBU, f, &nod);
   888  			gins(AMOVWD, &nod, t);
   889  			regfree(&nod);
   890  			return;
   891  		case TFLOAT:
   892  			regalloc(&nod, f, Z);
   893  			gins(AMOVBU, f, &nod);
   894  			gins(AMOVWF, &nod, t);
   895  			regfree(&nod);
   896  			return;
   897  		case TINT:
   898  		case TUINT:
   899  		case TLONG:
   900  		case TULONG:
   901  		case TIND:
   902  		case TSHORT:
   903  		case TUSHORT:
   904  			a = AMOVBU;
   905  			break;
   906  		case TCHAR:
   907  		case TUCHAR:
   908  			a = AMOVW;
   909  			break;
   910  		}
   911  		break;
   912  	}
   913  	if(a == AGOK)
   914  		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
   915  	if(a == AMOVW || a == AMOVF || a == AMOVD)
   916  	if(samaddr(f, t))
   917  		return;
   918  	gins(a, f, t);
   919  }
   920  
   921  void
   922  gmover(Node *f, Node *t)
   923  {
   924  	int ft, tt, a;
   925  
   926  	ft = f->type->etype;
   927  	tt = t->type->etype;
   928  	a = AGOK;
   929  	if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
   930  		switch(tt){
   931  		case TSHORT:
   932  			a = AMOVHS;
   933  			break;
   934  		case TUSHORT:
   935  			a = AMOVHU;
   936  			break;
   937  		case TCHAR:
   938  			a = AMOVBS;
   939  			break;
   940  		case TUCHAR:
   941  			a = AMOVBU;
   942  			break;
   943  		}
   944  	}
   945  	if(a == AGOK)
   946  		gmove(f, t);
   947  	else
   948  		gins(a, f, t);
   949  }
   950  
   951  void
   952  gins(int a, Node *f, Node *t)
   953  {
   954  
   955  	nextpc();
   956  	p->as = a;
   957  	if(f != Z)
   958  		naddr(f, &p->from);
   959  	if(t != Z)
   960  		naddr(t, &p->to);
   961  	if(debug['g'])
   962  		print("%P\n", p);
   963  }
   964  
   965  void
   966  gopcode(int o, Node *f1, Node *f2, Node *t)
   967  {
   968  	int a, et;
   969  	Addr ta;
   970  
   971  	et = TLONG;
   972  	if(f1 != Z && f1->type != T)
   973  		et = f1->type->etype;
   974  	a = AGOK;
   975  	switch(o) {
   976  	case OAS:
   977  		gmove(f1, t);
   978  		return;
   979  
   980  	case OASADD:
   981  	case OADD:
   982  		a = AADD;
   983  		if(et == TFLOAT)
   984  			a = AADDF;
   985  		else
   986  		if(et == TDOUBLE || et == TVLONG)
   987  			a = AADDD;
   988  		break;
   989  
   990  	case OASSUB:
   991  	case OSUB:
   992  		if(f2 && f2->op == OCONST) {
   993  			Node *t = f1;
   994  			f1 = f2;
   995  			f2 = t;
   996  			a = ARSB;
   997  		} else
   998  			a = ASUB;
   999  		if(et == TFLOAT)
  1000  			a = ASUBF;
  1001  		else
  1002  		if(et == TDOUBLE || et == TVLONG)
  1003  			a = ASUBD;
  1004  		break;
  1005  
  1006  	case OASOR:
  1007  	case OOR:
  1008  		a = AORR;
  1009  		break;
  1010  
  1011  	case OASAND:
  1012  	case OAND:
  1013  		a = AAND;
  1014  		break;
  1015  
  1016  	case OASXOR:
  1017  	case OXOR:
  1018  		a = AEOR;
  1019  		break;
  1020  
  1021  	case OASLSHR:
  1022  	case OLSHR:
  1023  		a = ASRL;
  1024  		break;
  1025  
  1026  	case OASASHR:
  1027  	case OASHR:
  1028  		a = ASRA;
  1029  		break;
  1030  
  1031  	case OASASHL:
  1032  	case OASHL:
  1033  		a = ASLL;
  1034  		break;
  1035  
  1036  	case OFUNC:
  1037  		a = ABL;
  1038  		break;
  1039  
  1040  	case OASMUL:
  1041  	case OMUL:
  1042  		a = AMUL;
  1043  		if(et == TFLOAT)
  1044  			a = AMULF;
  1045  		else
  1046  		if(et == TDOUBLE || et == TVLONG)
  1047  			a = AMULD;
  1048  		break;
  1049  
  1050  	case OASDIV:
  1051  	case ODIV:
  1052  		a = ADIV;
  1053  		if(et == TFLOAT)
  1054  			a = ADIVF;
  1055  		else
  1056  		if(et == TDOUBLE || et == TVLONG)
  1057  			a = ADIVD;
  1058  		break;
  1059  
  1060  	case OASMOD:
  1061  	case OMOD:
  1062  		a = AMOD;
  1063  		break;
  1064  
  1065  	case OASLMUL:
  1066  	case OLMUL:
  1067  		a = AMULU;
  1068  		break;
  1069  
  1070  	case OASLMOD:
  1071  	case OLMOD:
  1072  		a = AMODU;
  1073  		break;
  1074  
  1075  	case OASLDIV:
  1076  	case OLDIV:
  1077  		a = ADIVU;
  1078  		break;
  1079  
  1080  	case OCASE:
  1081  	case OEQ:
  1082  	case ONE:
  1083  	case OLT:
  1084  	case OLE:
  1085  	case OGE:
  1086  	case OGT:
  1087  	case OLO:
  1088  	case OLS:
  1089  	case OHS:
  1090  	case OHI:
  1091  		a = ACMP;
  1092  		if(et == TFLOAT)
  1093  			a = ACMPF;
  1094  		else
  1095  		if(et == TDOUBLE || et == TVLONG)
  1096  			a = ACMPD;
  1097  		nextpc();
  1098  		p->as = a;
  1099  		naddr(f1, &p->from);
  1100  		if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
  1101  			p->as = ACMN;
  1102  			p->from.offset = -p->from.offset;
  1103  		}
  1104  		raddr(f2, p);
  1105  		switch(o) {
  1106  		case OEQ:
  1107  			a = ABEQ;
  1108  			break;
  1109  		case ONE:
  1110  			a = ABNE;
  1111  			break;
  1112  		case OLT:
  1113  			a = ABLT;
  1114  			break;
  1115  		case OLE:
  1116  			a = ABLE;
  1117  			break;
  1118  		case OGE:
  1119  			a = ABGE;
  1120  			break;
  1121  		case OGT:
  1122  			a = ABGT;
  1123  			break;
  1124  		case OLO:
  1125  			a = ABLO;
  1126  			break;
  1127  		case OLS:
  1128  			a = ABLS;
  1129  			break;
  1130  		case OHS:
  1131  			a = ABHS;
  1132  			break;
  1133  		case OHI:
  1134  			a = ABHI;
  1135  			break;
  1136  		case OCASE:
  1137  			nextpc();
  1138  			p->as = ACASE;
  1139  			p->scond = 0x9;
  1140  			naddr(f2, &p->from);
  1141  			a = ABHI;
  1142  			break;
  1143  		}
  1144  		f1 = Z;
  1145  		f2 = Z;
  1146  		break;
  1147  	}
  1148  	if(a == AGOK)
  1149  		diag(Z, "bad in gopcode %O", o);
  1150  	nextpc();
  1151  	p->as = a;
  1152  	if(f1 != Z)
  1153  		naddr(f1, &p->from);
  1154  	if(f2 != Z) {
  1155  		naddr(f2, &ta);
  1156  		p->reg = ta.reg;
  1157  	}
  1158  	if(t != Z)
  1159  		naddr(t, &p->to);
  1160  	if(debug['g'])
  1161  		print("%P\n", p);
  1162  }
  1163  
  1164  int
  1165  samaddr(Node *f, Node *t)
  1166  {
  1167  
  1168  	if(f->op != t->op)
  1169  		return 0;
  1170  	switch(f->op) {
  1171  
  1172  	case OREGISTER:
  1173  		if(f->reg != t->reg)
  1174  			break;
  1175  		return 1;
  1176  	}
  1177  	return 0;
  1178  }
  1179  
  1180  void
  1181  gbranch(int o)
  1182  {
  1183  	int a;
  1184  
  1185  	a = AGOK;
  1186  	switch(o) {
  1187  	case ORETURN:
  1188  		a = ARET;
  1189  		break;
  1190  	case OGOTO:
  1191  		a = AB;
  1192  		break;
  1193  	}
  1194  	nextpc();
  1195  	if(a == AGOK) {
  1196  		diag(Z, "bad in gbranch %O",  o);
  1197  		nextpc();
  1198  	}
  1199  	p->as = a;
  1200  }
  1201  
  1202  void
  1203  patch(Prog *op, int32 pc)
  1204  {
  1205  
  1206  	op->to.offset = pc;
  1207  	op->to.type = D_BRANCH;
  1208  }
  1209  
  1210  void
  1211  gpseudo(int a, Sym *s, Node *n)
  1212  {
  1213  	nextpc();
  1214  	p->as = a;
  1215  	p->from.type = D_OREG;
  1216  	p->from.sym = linksym(s);
  1217  	p->from.name = D_EXTERN;
  1218  
  1219  	switch(a) {
  1220  	case ATEXT:
  1221  		p->reg = textflag;
  1222  		textflag = 0;
  1223  		break;
  1224  	case AGLOBL:
  1225  		p->reg = s->dataflag;
  1226  		break;
  1227  	}
  1228  
  1229  	if(s->class == CSTATIC)
  1230  		p->from.name = D_STATIC;
  1231  	naddr(n, &p->to);
  1232  	if(a == ADATA || a == AGLOBL)
  1233  		pc--;
  1234  }
  1235  
  1236  void
  1237  gpcdata(int index, int value)
  1238  {
  1239  	Node n1;
  1240  	
  1241  	n1 = *nodconst(index);
  1242  	gins(APCDATA, &n1, nodconst(value));
  1243  }
  1244  
  1245  void
  1246  gprefetch(Node *n)
  1247  {
  1248  	Node n1;
  1249  
  1250  	regalloc(&n1, n, Z);
  1251  	gmove(n, &n1);
  1252  	n1.op = OINDREG;
  1253  	gins(APLD, &n1, Z);
  1254  	regfree(&n1);
  1255  }
  1256  
  1257  int
  1258  sconst(Node *n)
  1259  {
  1260  	vlong vv;
  1261  
  1262  	if(n->op == OCONST) {
  1263  		if(!typefd[n->type->etype]) {
  1264  			vv = n->vconst;
  1265  			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
  1266  				return 1;
  1267  			/*
  1268  			 * should be specialised for constant values which will
  1269  			 * fit in different instructionsl; for now, let 5l
  1270  			 * sort it out
  1271  			 */
  1272  			return 1;
  1273  		}
  1274  	}
  1275  	return 0;
  1276  }
  1277  
  1278  int
  1279  sval(int32 v)
  1280  {
  1281  	int i;
  1282  
  1283  	for(i=0; i<16; i++) {
  1284  		if((v & ~0xff) == 0)
  1285  			return 1;
  1286  		if((~v & ~0xff) == 0)
  1287  			return 1;
  1288  		v = (v<<2) | ((uint32)v>>30);
  1289  	}
  1290  	return 0;
  1291  }
  1292  
  1293  int32
  1294  exreg(Type *t)
  1295  {
  1296  	int32 o;
  1297  
  1298  	if(typechlp[t->etype]) {
  1299  		if(exregoffset <= REGEXT-4)
  1300  			return 0;
  1301  		o = exregoffset;
  1302  		exregoffset--;
  1303  		return o;
  1304  	}
  1305  	if(typefd[t->etype]) {
  1306  		if(exfregoffset <= NFREG-1)
  1307  			return 0;
  1308  		o = exfregoffset + NREG;
  1309  		exfregoffset--;
  1310  		return o;
  1311  	}
  1312  	return 0;
  1313  }
  1314  
  1315  schar	ewidth[NTYPE] =
  1316  {
  1317  	-1,		/* [TXXX] */
  1318  	SZ_CHAR,	/* [TCHAR] */
  1319  	SZ_CHAR,	/* [TUCHAR] */
  1320  	SZ_SHORT,	/* [TSHORT] */
  1321  	SZ_SHORT,	/* [TUSHORT] */
  1322  	SZ_INT,		/* [TINT] */
  1323  	SZ_INT,		/* [TUINT] */
  1324  	SZ_LONG,	/* [TLONG] */
  1325  	SZ_LONG,	/* [TULONG] */
  1326  	SZ_VLONG,	/* [TVLONG] */
  1327  	SZ_VLONG,	/* [TUVLONG] */
  1328  	SZ_FLOAT,	/* [TFLOAT] */
  1329  	SZ_DOUBLE,	/* [TDOUBLE] */
  1330  	SZ_IND,		/* [TIND] */
  1331  	0,		/* [TFUNC] */
  1332  	-1,		/* [TARRAY] */
  1333  	0,		/* [TVOID] */
  1334  	-1,		/* [TSTRUCT] */
  1335  	-1,		/* [TUNION] */
  1336  	SZ_INT,		/* [TENUM] */
  1337  };
  1338  
  1339  int32	ncast[NTYPE] =
  1340  {
  1341  	0,				/* [TXXX] */
  1342  	BCHAR|BUCHAR,			/* [TCHAR] */
  1343  	BCHAR|BUCHAR,			/* [TUCHAR] */
  1344  	BSHORT|BUSHORT,			/* [TSHORT] */
  1345  	BSHORT|BUSHORT,			/* [TUSHORT] */
  1346  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
  1347  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
  1348  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
  1349  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
  1350  	BVLONG|BUVLONG,			/* [TVLONG] */
  1351  	BVLONG|BUVLONG,			/* [TUVLONG] */
  1352  	BFLOAT,				/* [TFLOAT] */
  1353  	BDOUBLE,			/* [TDOUBLE] */
  1354  	BLONG|BULONG|BIND,		/* [TIND] */
  1355  	0,				/* [TFUNC] */
  1356  	0,				/* [TARRAY] */
  1357  	0,				/* [TVOID] */
  1358  	BSTRUCT,			/* [TSTRUCT] */
  1359  	BUNION,				/* [TUNION] */
  1360  	0,				/* [TENUM] */
  1361  };