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