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