github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/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)
   278  {
   279  	int r;
   280  
   281  	r = REGRET;
   282  	if(typefd[nn->type->etype])
   283  		r = FREGRET+NREG;
   284  	nodreg(n, nn, r);
   285  	reg[r]++;
   286  }
   287  
   288  int
   289  tmpreg(void)
   290  {
   291  	int i;
   292  
   293  	for(i=REGRET+1; i<NREG; i++)
   294  		if(reg[i] == 0)
   295  			return i;
   296  	diag(Z, "out of fixed registers");
   297  	return 0;
   298  }
   299  
   300  void
   301  regalloc(Node *n, Node *tn, Node *o)
   302  {
   303  	int i;
   304  
   305  	switch(tn->type->etype) {
   306  	case TCHAR:
   307  	case TUCHAR:
   308  	case TSHORT:
   309  	case TUSHORT:
   310  	case TINT:
   311  	case TUINT:
   312  	case TLONG:
   313  	case TULONG:
   314  	case TIND:
   315  		if(o != Z && o->op == OREGISTER) {
   316  			i = o->reg;
   317  			if(i >= 0 && i < NREG)
   318  				goto out;
   319  		}
   320  		for(i=REGRET+1; i<=REGEXT-2; i++)
   321  			if(reg[i] == 0)
   322  				goto out;
   323  		diag(tn, "out of fixed registers");
   324  		goto err;
   325  
   326  	case TFLOAT:
   327  	case TDOUBLE:
   328  	case TVLONG:
   329  		if(o != Z && o->op == OREGISTER) {
   330  			i = o->reg;
   331  			if(i >= NREG && i < NREG+NFREG)
   332  				goto out;
   333  		}
   334  		for(i=NREG; i<NREG+NFREG; i++)
   335  			if(reg[i] == 0)
   336  				goto out;
   337  		diag(tn, "out of float registers");
   338  		goto err;
   339  	}
   340  	diag(tn, "unknown type in regalloc: %T", tn->type);
   341  err:
   342  	nodreg(n, tn, 0);
   343  	return;
   344  out:
   345  	reg[i]++;
   346  	nodreg(n, tn, i);
   347  }
   348  
   349  void
   350  regialloc(Node *n, Node *tn, Node *o)
   351  {
   352  	Node nod;
   353  
   354  	nod = *tn;
   355  	nod.type = types[TIND];
   356  	regalloc(n, &nod, o);
   357  }
   358  
   359  void
   360  regfree(Node *n)
   361  {
   362  	int i;
   363  
   364  	i = 0;
   365  	if(n->op != OREGISTER && n->op != OINDREG)
   366  		goto err;
   367  	i = n->reg;
   368  	if(i < 0 || i >= nelem(reg))
   369  		goto err;
   370  	if(reg[i] <= 0)
   371  		goto err;
   372  	reg[i]--;
   373  	return;
   374  err:
   375  	diag(n, "error in regfree: %d", i);
   376  }
   377  
   378  void
   379  regsalloc(Node *n, Node *nn)
   380  {
   381  	cursafe = align(cursafe, nn->type, Aaut3, nil);
   382  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   383  	*n = *nodsafe;
   384  	n->xoffset = -(stkoff + cursafe);
   385  	n->type = nn->type;
   386  	n->etype = nn->type->etype;
   387  	n->lineno = nn->lineno;
   388  }
   389  
   390  void
   391  regaalloc1(Node *n, Node *nn)
   392  {
   393  	if(REGARG < 0) {
   394  		fatal(n, "regaalloc1 and REGARG<0");
   395  		return;
   396  	}
   397  	nodreg(n, nn, REGARG);
   398  	reg[REGARG]++;
   399  	curarg = align(curarg, nn->type, Aarg1, nil);
   400  	curarg = align(curarg, nn->type, Aarg2, nil);
   401  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   402  }
   403  
   404  void
   405  regaalloc(Node *n, Node *nn)
   406  {
   407  	curarg = align(curarg, nn->type, Aarg1, nil);
   408  	*n = *nn;
   409  	n->op = OINDREG;
   410  	n->reg = REGSP;
   411  	n->xoffset = curarg + SZ_LONG;
   412  	n->complex = 0;
   413  	n->addable = 20;
   414  	curarg = align(curarg, nn->type, Aarg2, nil);
   415  	maxargsafe = maxround(maxargsafe, cursafe+curarg);
   416  }
   417  
   418  void
   419  regind(Node *n, Node *nn)
   420  {
   421  
   422  	if(n->op != OREGISTER) {
   423  		diag(n, "regind not OREGISTER");
   424  		return;
   425  	}
   426  	n->op = OINDREG;
   427  	n->type = nn->type;
   428  }
   429  
   430  void
   431  raddr(Node *n, Prog *p)
   432  {
   433  	Addr a;
   434  
   435  	naddr(n, &a);
   436  	if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
   437  		a.type = D_REG;
   438  		a.reg = 0;
   439  	}
   440  	if(a.type != D_REG && a.type != D_FREG) {
   441  		if(n)
   442  			diag(n, "bad in raddr: %O", n->op);
   443  		else
   444  			diag(n, "bad in raddr: <null>");
   445  		p->reg = NREG;
   446  	} else
   447  		p->reg = a.reg;
   448  }
   449  
   450  void
   451  naddr(Node *n, Addr *a)
   452  {
   453  	int32 v;
   454  
   455  	a->type = D_NONE;
   456  	if(n == Z)
   457  		return;
   458  	switch(n->op) {
   459  	default:
   460  	bad:
   461  		diag(n, "bad in naddr: %O", n->op);
   462  		break;
   463  
   464  	case OREGISTER:
   465  		a->type = D_REG;
   466  		a->sym = nil;
   467  		a->reg = n->reg;
   468  		if(a->reg >= NREG) {
   469  			a->type = D_FREG;
   470  			a->reg -= NREG;
   471  		}
   472  		break;
   473  
   474  	case OIND:
   475  		naddr(n->left, a);
   476  		if(a->type == D_REG) {
   477  			a->type = D_OREG;
   478  			break;
   479  		}
   480  		if(a->type == D_CONST) {
   481  			a->type = D_OREG;
   482  			break;
   483  		}
   484  		goto bad;
   485  
   486  	case OINDREG:
   487  		a->type = D_OREG;
   488  		a->sym = nil;
   489  		a->offset = n->xoffset;
   490  		a->reg = n->reg;
   491  		break;
   492  
   493  	case ONAME:
   494  		a->etype = n->etype;
   495  		a->type = D_OREG;
   496  		a->name = D_STATIC;
   497  		a->sym = linksym(n->sym);
   498  		a->offset = n->xoffset;
   499  		if(n->class == CSTATIC)
   500  			break;
   501  		if(n->class == CEXTERN || n->class == CGLOBL) {
   502  			a->name = D_EXTERN;
   503  			break;
   504  		}
   505  		if(n->class == CAUTO) {
   506  			a->name = D_AUTO;
   507  			break;
   508  		}
   509  		if(n->class == CPARAM) {
   510  			a->name = D_PARAM;
   511  			break;
   512  		}
   513  		goto bad;
   514  
   515  	case OCONST:
   516  		a->sym = nil;
   517  		a->reg = NREG;
   518  		if(typefd[n->type->etype]) {
   519  			a->type = D_FCONST;
   520  			a->u.dval = n->fconst;
   521  		} else {
   522  			a->type = D_CONST;
   523  			a->offset = n->vconst;
   524  		}
   525  		break;
   526  
   527  	case OADDR:
   528  		naddr(n->left, a);
   529  		if(a->type == D_OREG) {
   530  			a->type = D_CONST;
   531  			break;
   532  		}
   533  		goto bad;
   534  
   535  	case OADD:
   536  		if(n->left->op == OCONST) {
   537  			naddr(n->left, a);
   538  			v = a->offset;
   539  			naddr(n->right, a);
   540  		} else {
   541  			naddr(n->right, a);
   542  			v = a->offset;
   543  			naddr(n->left, a);
   544  		}
   545  		a->offset += v;
   546  		break;
   547  
   548  	}
   549  }
   550  
   551  void
   552  fop(int as, int f1, int f2, Node *t)
   553  {
   554  	Node nod1, nod2, nod3;
   555  
   556  	nodreg(&nod1, t, NREG+f1);
   557  	nodreg(&nod2, t, NREG+f2);
   558  	regalloc(&nod3, t, t);
   559  	gopcode(as, &nod1, &nod2, &nod3);
   560  	gmove(&nod3, t);
   561  	regfree(&nod3);
   562  }
   563  
   564  void
   565  gmovm(Node *f, Node *t, int w)
   566  {
   567  	gins(AMOVM, f, t);
   568  	p->scond |= C_UBIT;
   569  	if(w)
   570  		p->scond |= C_WBIT;
   571  }
   572  
   573  void
   574  gmove(Node *f, Node *t)
   575  {
   576  	int ft, tt, a;
   577  	Node nod, nod1;
   578  	Prog *p1;
   579  
   580  	ft = f->type->etype;
   581  	tt = t->type->etype;
   582  
   583  	if(ft == TDOUBLE && f->op == OCONST) {
   584  	}
   585  	if(ft == TFLOAT && f->op == OCONST) {
   586  	}
   587  
   588  	/*
   589  	 * a load --
   590  	 * put it into a register then
   591  	 * worry what to do with it.
   592  	 */
   593  	if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
   594  		switch(ft) {
   595  		default:
   596  			a = AMOVW;
   597  			break;
   598  		case TFLOAT:
   599  			a = AMOVF;
   600  			break;
   601  		case TDOUBLE:
   602  			a = AMOVD;
   603  			break;
   604  		case TCHAR:
   605  			a = AMOVBS;
   606  			break;
   607  		case TUCHAR:
   608  			a = AMOVBU;
   609  			break;
   610  		case TSHORT:
   611  			a = AMOVHS;
   612  			break;
   613  		case TUSHORT:
   614  			a = AMOVHU;
   615  			break;
   616  		}
   617  		if(typechlp[ft] && typeilp[tt])
   618  			regalloc(&nod, t, t);
   619  		else
   620  			regalloc(&nod, f, t);
   621  		gins(a, f, &nod);
   622  		gmove(&nod, t);
   623  		regfree(&nod);
   624  		return;
   625  	}
   626  
   627  	/*
   628  	 * a store --
   629  	 * put it into a register then
   630  	 * store it.
   631  	 */
   632  	if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
   633  		switch(tt) {
   634  		default:
   635  			a = AMOVW;
   636  			break;
   637  		case TUCHAR:
   638  			a = AMOVBU;
   639  			break;
   640  		case TCHAR:
   641  			a = AMOVBS;
   642  			break;
   643  		case TUSHORT:
   644  			a = AMOVHU;
   645  			break;
   646  		case TSHORT:
   647  			a = AMOVHS;
   648  			break;
   649  		case TFLOAT:
   650  			a = AMOVF;
   651  			break;
   652  		case TVLONG:
   653  		case TDOUBLE:
   654  			a = AMOVD;
   655  			break;
   656  		}
   657  		if(ft == tt)
   658  			regalloc(&nod, t, f);
   659  		else
   660  			regalloc(&nod, t, Z);
   661  		gmove(f, &nod);
   662  		gins(a, &nod, t);
   663  		regfree(&nod);
   664  		return;
   665  	}
   666  
   667  	/*
   668  	 * type x type cross table
   669  	 */
   670  	a = AGOK;
   671  	switch(ft) {
   672  	case TDOUBLE:
   673  	case TVLONG:
   674  	case TFLOAT:
   675  		switch(tt) {
   676  		case TDOUBLE:
   677  		case TVLONG:
   678  			a = AMOVD;
   679  			if(ft == TFLOAT)
   680  				a = AMOVFD;
   681  			break;
   682  		case TFLOAT:
   683  			a = AMOVDF;
   684  			if(ft == TFLOAT)
   685  				a = AMOVF;
   686  			break;
   687  		case TINT:
   688  		case TUINT:
   689  		case TLONG:
   690  		case TULONG:
   691  		case TIND:
   692  			a = AMOVDW;
   693  			if(ft == TFLOAT)
   694  				a = AMOVFW;
   695  			break;
   696  		case TSHORT:
   697  		case TUSHORT:
   698  		case TCHAR:
   699  		case TUCHAR:
   700  			a = AMOVDW;
   701  			if(ft == TFLOAT)
   702  				a = AMOVFW;
   703  			break;
   704  		}
   705  		break;
   706  	case TUINT:
   707  	case TULONG:
   708  		if(tt == TFLOAT || tt == TDOUBLE) {
   709  			// ugly and probably longer than necessary,
   710  			// but vfp has a single instruction for this,
   711  			// so hopefully it won't last long.
   712  			//
   713  			//	tmp = f
   714  			//	tmp1 = tmp & 0x80000000
   715  			//	tmp ^= tmp1
   716  			//	t = float(int32(tmp))
   717  			//	if(tmp1)
   718  			//		t += 2147483648.
   719  			//
   720  			regalloc(&nod, f, Z);
   721  			regalloc(&nod1, f, Z);
   722  			gins(AMOVW, f, &nod);
   723  			gins(AMOVW, &nod, &nod1);
   724  			gins(AAND, nodconst(0x80000000), &nod1);
   725  			gins(AEOR, &nod1, &nod);
   726  			if(tt == TFLOAT)
   727  				gins(AMOVWF, &nod, t);
   728  			else
   729  				gins(AMOVWD, &nod, t);
   730  			gins(ACMP, nodconst(0), Z);
   731  			raddr(&nod1, p);
   732  			gins(ABEQ, Z, Z);
   733  			regfree(&nod);
   734  			regfree(&nod1);
   735  			p1 = p;
   736  			regalloc(&nod, t, Z);
   737  			gins(AMOVF, nodfconst(2147483648.), &nod);
   738  			gins(AADDF, &nod, t);
   739  			regfree(&nod);
   740  			patch(p1, pc);
   741  			return;
   742  		}
   743  		// fall through
   744  	
   745  	case TINT:
   746  	case TLONG:
   747  	case TIND:
   748  		switch(tt) {
   749  		case TDOUBLE:
   750  			gins(AMOVWD, f, t);
   751  			return;
   752  		case TFLOAT:
   753  			gins(AMOVWF, f, t);
   754  			return;
   755  		case TINT:
   756  		case TUINT:
   757  		case TLONG:
   758  		case TULONG:
   759  		case TIND:
   760  		case TSHORT:
   761  		case TUSHORT:
   762  		case TCHAR:
   763  		case TUCHAR:
   764  			a = AMOVW;
   765  			break;
   766  		}
   767  		break;
   768  	case TSHORT:
   769  		switch(tt) {
   770  		case TDOUBLE:
   771  			regalloc(&nod, f, Z);
   772  			gins(AMOVHS, f, &nod);
   773  			gins(AMOVWD, &nod, t);
   774  			regfree(&nod);
   775  			return;
   776  		case TFLOAT:
   777  			regalloc(&nod, f, Z);
   778  			gins(AMOVHS, f, &nod);
   779  			gins(AMOVWF, &nod, t);
   780  			regfree(&nod);
   781  			return;
   782  		case TUINT:
   783  		case TINT:
   784  		case TULONG:
   785  		case TLONG:
   786  		case TIND:
   787  			a = AMOVHS;
   788  			break;
   789  		case TSHORT:
   790  		case TUSHORT:
   791  		case TCHAR:
   792  		case TUCHAR:
   793  			a = AMOVW;
   794  			break;
   795  		}
   796  		break;
   797  	case TUSHORT:
   798  		switch(tt) {
   799  		case TDOUBLE:
   800  			regalloc(&nod, f, Z);
   801  			gins(AMOVHU, f, &nod);
   802  			gins(AMOVWD, &nod, t);
   803  			regfree(&nod);
   804  			return;
   805  		case TFLOAT:
   806  			regalloc(&nod, f, Z);
   807  			gins(AMOVHU, f, &nod);
   808  			gins(AMOVWF, &nod, t);
   809  			regfree(&nod);
   810  			return;
   811  		case TINT:
   812  		case TUINT:
   813  		case TLONG:
   814  		case TULONG:
   815  		case TIND:
   816  			a = AMOVHU;
   817  			break;
   818  		case TSHORT:
   819  		case TUSHORT:
   820  		case TCHAR:
   821  		case TUCHAR:
   822  			a = AMOVW;
   823  			break;
   824  		}
   825  		break;
   826  	case TCHAR:
   827  		switch(tt) {
   828  		case TDOUBLE:
   829  			regalloc(&nod, f, Z);
   830  			gins(AMOVBS, f, &nod);
   831  			gins(AMOVWD, &nod, t);
   832  			regfree(&nod);
   833  			return;
   834  		case TFLOAT:
   835  			regalloc(&nod, f, Z);
   836  			gins(AMOVBS, f, &nod);
   837  			gins(AMOVWF, &nod, t);
   838  			regfree(&nod);
   839  			return;
   840  		case TINT:
   841  		case TUINT:
   842  		case TLONG:
   843  		case TULONG:
   844  		case TIND:
   845  		case TSHORT:
   846  		case TUSHORT:
   847  			a = AMOVBS;
   848  			break;
   849  		case TCHAR:
   850  		case TUCHAR:
   851  			a = AMOVW;
   852  			break;
   853  		}
   854  		break;
   855  	case TUCHAR:
   856  		switch(tt) {
   857  		case TDOUBLE:
   858  			regalloc(&nod, f, Z);
   859  			gins(AMOVBU, f, &nod);
   860  			gins(AMOVWD, &nod, t);
   861  			regfree(&nod);
   862  			return;
   863  		case TFLOAT:
   864  			regalloc(&nod, f, Z);
   865  			gins(AMOVBU, f, &nod);
   866  			gins(AMOVWF, &nod, t);
   867  			regfree(&nod);
   868  			return;
   869  		case TINT:
   870  		case TUINT:
   871  		case TLONG:
   872  		case TULONG:
   873  		case TIND:
   874  		case TSHORT:
   875  		case TUSHORT:
   876  			a = AMOVBU;
   877  			break;
   878  		case TCHAR:
   879  		case TUCHAR:
   880  			a = AMOVW;
   881  			break;
   882  		}
   883  		break;
   884  	}
   885  	if(a == AGOK)
   886  		diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
   887  	if(a == AMOVW || a == AMOVF || a == AMOVD)
   888  	if(samaddr(f, t))
   889  		return;
   890  	gins(a, f, t);
   891  }
   892  
   893  void
   894  gmover(Node *f, Node *t)
   895  {
   896  	int ft, tt, a;
   897  
   898  	ft = f->type->etype;
   899  	tt = t->type->etype;
   900  	a = AGOK;
   901  	if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
   902  		switch(tt){
   903  		case TSHORT:
   904  			a = AMOVHS;
   905  			break;
   906  		case TUSHORT:
   907  			a = AMOVHU;
   908  			break;
   909  		case TCHAR:
   910  			a = AMOVBS;
   911  			break;
   912  		case TUCHAR:
   913  			a = AMOVBU;
   914  			break;
   915  		}
   916  	}
   917  	if(a == AGOK)
   918  		gmove(f, t);
   919  	else
   920  		gins(a, f, t);
   921  }
   922  
   923  void
   924  gins(int a, Node *f, Node *t)
   925  {
   926  
   927  	nextpc();
   928  	p->as = a;
   929  	if(f != Z)
   930  		naddr(f, &p->from);
   931  	if(t != Z)
   932  		naddr(t, &p->to);
   933  	if(debug['g'])
   934  		print("%P\n", p);
   935  }
   936  
   937  void
   938  gopcode(int o, Node *f1, Node *f2, Node *t)
   939  {
   940  	int a, et;
   941  	Addr ta;
   942  
   943  	et = TLONG;
   944  	if(f1 != Z && f1->type != T)
   945  		et = f1->type->etype;
   946  	a = AGOK;
   947  	switch(o) {
   948  	case OAS:
   949  		gmove(f1, t);
   950  		return;
   951  
   952  	case OASADD:
   953  	case OADD:
   954  		a = AADD;
   955  		if(et == TFLOAT)
   956  			a = AADDF;
   957  		else
   958  		if(et == TDOUBLE || et == TVLONG)
   959  			a = AADDD;
   960  		break;
   961  
   962  	case OASSUB:
   963  	case OSUB:
   964  		if(f2 && f2->op == OCONST) {
   965  			Node *t = f1;
   966  			f1 = f2;
   967  			f2 = t;
   968  			a = ARSB;
   969  		} else
   970  			a = ASUB;
   971  		if(et == TFLOAT)
   972  			a = ASUBF;
   973  		else
   974  		if(et == TDOUBLE || et == TVLONG)
   975  			a = ASUBD;
   976  		break;
   977  
   978  	case OASOR:
   979  	case OOR:
   980  		a = AORR;
   981  		break;
   982  
   983  	case OASAND:
   984  	case OAND:
   985  		a = AAND;
   986  		break;
   987  
   988  	case OASXOR:
   989  	case OXOR:
   990  		a = AEOR;
   991  		break;
   992  
   993  	case OASLSHR:
   994  	case OLSHR:
   995  		a = ASRL;
   996  		break;
   997  
   998  	case OASASHR:
   999  	case OASHR:
  1000  		a = ASRA;
  1001  		break;
  1002  
  1003  	case OASASHL:
  1004  	case OASHL:
  1005  		a = ASLL;
  1006  		break;
  1007  
  1008  	case OFUNC:
  1009  		a = ABL;
  1010  		break;
  1011  
  1012  	case OASMUL:
  1013  	case OMUL:
  1014  		a = AMUL;
  1015  		if(et == TFLOAT)
  1016  			a = AMULF;
  1017  		else
  1018  		if(et == TDOUBLE || et == TVLONG)
  1019  			a = AMULD;
  1020  		break;
  1021  
  1022  	case OASDIV:
  1023  	case ODIV:
  1024  		a = ADIV;
  1025  		if(et == TFLOAT)
  1026  			a = ADIVF;
  1027  		else
  1028  		if(et == TDOUBLE || et == TVLONG)
  1029  			a = ADIVD;
  1030  		break;
  1031  
  1032  	case OASMOD:
  1033  	case OMOD:
  1034  		a = AMOD;
  1035  		break;
  1036  
  1037  	case OASLMUL:
  1038  	case OLMUL:
  1039  		a = AMULU;
  1040  		break;
  1041  
  1042  	case OASLMOD:
  1043  	case OLMOD:
  1044  		a = AMODU;
  1045  		break;
  1046  
  1047  	case OASLDIV:
  1048  	case OLDIV:
  1049  		a = ADIVU;
  1050  		break;
  1051  
  1052  	case OCASE:
  1053  	case OEQ:
  1054  	case ONE:
  1055  	case OLT:
  1056  	case OLE:
  1057  	case OGE:
  1058  	case OGT:
  1059  	case OLO:
  1060  	case OLS:
  1061  	case OHS:
  1062  	case OHI:
  1063  		a = ACMP;
  1064  		if(et == TFLOAT)
  1065  			a = ACMPF;
  1066  		else
  1067  		if(et == TDOUBLE || et == TVLONG)
  1068  			a = ACMPD;
  1069  		nextpc();
  1070  		p->as = a;
  1071  		naddr(f1, &p->from);
  1072  		if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
  1073  			p->as = ACMN;
  1074  			p->from.offset = -p->from.offset;
  1075  		}
  1076  		raddr(f2, p);
  1077  		switch(o) {
  1078  		case OEQ:
  1079  			a = ABEQ;
  1080  			break;
  1081  		case ONE:
  1082  			a = ABNE;
  1083  			break;
  1084  		case OLT:
  1085  			a = ABLT;
  1086  			break;
  1087  		case OLE:
  1088  			a = ABLE;
  1089  			break;
  1090  		case OGE:
  1091  			a = ABGE;
  1092  			break;
  1093  		case OGT:
  1094  			a = ABGT;
  1095  			break;
  1096  		case OLO:
  1097  			a = ABLO;
  1098  			break;
  1099  		case OLS:
  1100  			a = ABLS;
  1101  			break;
  1102  		case OHS:
  1103  			a = ABHS;
  1104  			break;
  1105  		case OHI:
  1106  			a = ABHI;
  1107  			break;
  1108  		case OCASE:
  1109  			nextpc();
  1110  			p->as = ACASE;
  1111  			p->scond = 0x9;
  1112  			naddr(f2, &p->from);
  1113  			a = ABHI;
  1114  			break;
  1115  		}
  1116  		f1 = Z;
  1117  		f2 = Z;
  1118  		break;
  1119  	}
  1120  	if(a == AGOK)
  1121  		diag(Z, "bad in gopcode %O", o);
  1122  	nextpc();
  1123  	p->as = a;
  1124  	if(f1 != Z)
  1125  		naddr(f1, &p->from);
  1126  	if(f2 != Z) {
  1127  		naddr(f2, &ta);
  1128  		p->reg = ta.reg;
  1129  	}
  1130  	if(t != Z)
  1131  		naddr(t, &p->to);
  1132  	if(debug['g'])
  1133  		print("%P\n", p);
  1134  }
  1135  
  1136  int
  1137  samaddr(Node *f, Node *t)
  1138  {
  1139  
  1140  	if(f->op != t->op)
  1141  		return 0;
  1142  	switch(f->op) {
  1143  
  1144  	case OREGISTER:
  1145  		if(f->reg != t->reg)
  1146  			break;
  1147  		return 1;
  1148  	}
  1149  	return 0;
  1150  }
  1151  
  1152  void
  1153  gbranch(int o)
  1154  {
  1155  	int a;
  1156  
  1157  	a = AGOK;
  1158  	switch(o) {
  1159  	case ORETURN:
  1160  		a = ARET;
  1161  		break;
  1162  	case OGOTO:
  1163  		a = AB;
  1164  		break;
  1165  	}
  1166  	nextpc();
  1167  	if(a == AGOK) {
  1168  		diag(Z, "bad in gbranch %O",  o);
  1169  		nextpc();
  1170  	}
  1171  	p->as = a;
  1172  }
  1173  
  1174  void
  1175  patch(Prog *op, int32 pc)
  1176  {
  1177  
  1178  	op->to.offset = pc;
  1179  	op->to.type = D_BRANCH;
  1180  }
  1181  
  1182  void
  1183  gpseudo(int a, Sym *s, Node *n)
  1184  {
  1185  	nextpc();
  1186  	p->as = a;
  1187  	p->from.type = D_OREG;
  1188  	p->from.sym = linksym(s);
  1189  	p->from.name = D_EXTERN;
  1190  
  1191  	switch(a) {
  1192  	case ATEXT:
  1193  		p->reg = textflag;
  1194  		textflag = 0;
  1195  		break;
  1196  	case AGLOBL:
  1197  		p->reg = s->dataflag;
  1198  		break;
  1199  	}
  1200  
  1201  	if(s->class == CSTATIC)
  1202  		p->from.name = D_STATIC;
  1203  	naddr(n, &p->to);
  1204  	if(a == ADATA || a == AGLOBL)
  1205  		pc--;
  1206  }
  1207  
  1208  void
  1209  gpcdata(int index, int value)
  1210  {
  1211  	Node n1;
  1212  	
  1213  	n1 = *nodconst(index);
  1214  	gins(APCDATA, &n1, nodconst(value));
  1215  }
  1216  
  1217  void
  1218  gprefetch(Node *n)
  1219  {
  1220  	Node n1;
  1221  
  1222  	regalloc(&n1, n, Z);
  1223  	gmove(n, &n1);
  1224  	n1.op = OINDREG;
  1225  	gins(APLD, &n1, Z);
  1226  	regfree(&n1);
  1227  }
  1228  
  1229  int
  1230  sconst(Node *n)
  1231  {
  1232  	vlong vv;
  1233  
  1234  	if(n->op == OCONST) {
  1235  		if(!typefd[n->type->etype]) {
  1236  			vv = n->vconst;
  1237  			if(vv >= (vlong)(-32766) && vv < (vlong)32766)
  1238  				return 1;
  1239  			/*
  1240  			 * should be specialised for constant values which will
  1241  			 * fit in different instructionsl; for now, let 5l
  1242  			 * sort it out
  1243  			 */
  1244  			return 1;
  1245  		}
  1246  	}
  1247  	return 0;
  1248  }
  1249  
  1250  int
  1251  sval(int32 v)
  1252  {
  1253  	int i;
  1254  
  1255  	for(i=0; i<16; i++) {
  1256  		if((v & ~0xff) == 0)
  1257  			return 1;
  1258  		if((~v & ~0xff) == 0)
  1259  			return 1;
  1260  		v = (v<<2) | ((uint32)v>>30);
  1261  	}
  1262  	return 0;
  1263  }
  1264  
  1265  int32
  1266  exreg(Type *t)
  1267  {
  1268  	int32 o;
  1269  
  1270  	if(typechlp[t->etype]) {
  1271  		if(exregoffset <= REGEXT-4)
  1272  			return 0;
  1273  		o = exregoffset;
  1274  		exregoffset--;
  1275  		return o;
  1276  	}
  1277  	if(typefd[t->etype]) {
  1278  		if(exfregoffset <= NFREG-1)
  1279  			return 0;
  1280  		o = exfregoffset + NREG;
  1281  		exfregoffset--;
  1282  		return o;
  1283  	}
  1284  	return 0;
  1285  }
  1286  
  1287  schar	ewidth[NTYPE] =
  1288  {
  1289  	-1,		/* [TXXX] */
  1290  	SZ_CHAR,	/* [TCHAR] */
  1291  	SZ_CHAR,	/* [TUCHAR] */
  1292  	SZ_SHORT,	/* [TSHORT] */
  1293  	SZ_SHORT,	/* [TUSHORT] */
  1294  	SZ_INT,		/* [TINT] */
  1295  	SZ_INT,		/* [TUINT] */
  1296  	SZ_LONG,	/* [TLONG] */
  1297  	SZ_LONG,	/* [TULONG] */
  1298  	SZ_VLONG,	/* [TVLONG] */
  1299  	SZ_VLONG,	/* [TUVLONG] */
  1300  	SZ_FLOAT,	/* [TFLOAT] */
  1301  	SZ_DOUBLE,	/* [TDOUBLE] */
  1302  	SZ_IND,		/* [TIND] */
  1303  	0,		/* [TFUNC] */
  1304  	-1,		/* [TARRAY] */
  1305  	0,		/* [TVOID] */
  1306  	-1,		/* [TSTRUCT] */
  1307  	-1,		/* [TUNION] */
  1308  	SZ_INT,		/* [TENUM] */
  1309  };
  1310  
  1311  int32	ncast[NTYPE] =
  1312  {
  1313  	0,				/* [TXXX] */
  1314  	BCHAR|BUCHAR,			/* [TCHAR] */
  1315  	BCHAR|BUCHAR,			/* [TUCHAR] */
  1316  	BSHORT|BUSHORT,			/* [TSHORT] */
  1317  	BSHORT|BUSHORT,			/* [TUSHORT] */
  1318  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TINT] */
  1319  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TUINT] */
  1320  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TLONG] */
  1321  	BINT|BUINT|BLONG|BULONG|BIND,	/* [TULONG] */
  1322  	BVLONG|BUVLONG,			/* [TVLONG] */
  1323  	BVLONG|BUVLONG,			/* [TUVLONG] */
  1324  	BFLOAT,				/* [TFLOAT] */
  1325  	BDOUBLE,			/* [TDOUBLE] */
  1326  	BLONG|BULONG|BIND,		/* [TIND] */
  1327  	0,				/* [TFUNC] */
  1328  	0,				/* [TARRAY] */
  1329  	0,				/* [TVOID] */
  1330  	BSTRUCT,			/* [TSTRUCT] */
  1331  	BUNION,				/* [TUNION] */
  1332  	0,				/* [TENUM] */
  1333  };