github.com/reiver/go@v0.0.0-20150109200633-1d0c7792f172/src/cmd/9g/gsubr.c (about)

     1  // Derived from Inferno utils/6c/txt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  #include <u.h>
    32  #include <libc.h>
    33  #include "gg.h"
    34  #include "../../runtime/funcdata.h"
    35  
    36  // TODO(rsc): Can make this bigger if we move
    37  // the text segment up higher in 6l for all GOOS.
    38  // At the same time, can raise StackBig in ../../runtime/stack.h.
    39  vlong unmappedzero = 4096;
    40  
    41  void
    42  clearp(Prog *p)
    43  {
    44  	*p = zprog;
    45  	p->as = AEND;
    46  	p->pc = pcloc;
    47  	pcloc++;
    48  }
    49  
    50  static int ddumped;
    51  static Prog *dfirst;
    52  static Prog *dpc;
    53  
    54  /*
    55   * generate and return proc with p->as = as,
    56   * linked into program. pc is next instruction.
    57   */
    58  Prog*
    59  prog(int as)
    60  {
    61  	Prog *p;
    62  
    63  	if(as == ADATA || as == AGLOBL) {
    64  		if(ddumped)
    65  			fatal("already dumped data");
    66  		if(dpc == nil) {
    67  			dpc = mal(sizeof(*dpc));
    68  			dfirst = dpc;
    69  		}
    70  		p = dpc;
    71  		dpc = mal(sizeof(*dpc));
    72  		p->link = dpc;
    73  		p->reg = 0; // used for flags
    74  	} else {
    75  		p = pc;
    76  		pc = mal(sizeof(*pc));
    77  		clearp(pc);
    78  		p->link = pc;
    79  	}
    80  
    81  	if(lineno == 0) {
    82  		if(debug['K'])
    83  			warn("prog: line 0");
    84  	}
    85  
    86  	p->as = as;
    87  	p->lineno = lineno;
    88  	return p;
    89  }
    90  
    91  void
    92  dumpdata(void)
    93  {
    94  	ddumped = 1;
    95  	if(dfirst == nil)
    96  		return;
    97  	newplist();
    98  	*pc = *dfirst;
    99  	pc = dpc;
   100  	clearp(pc);
   101  }
   102  
   103  /*
   104   * generate a branch.
   105   * t is ignored.
   106   * likely values are for branch prediction:
   107   *	-1 unlikely
   108   *	0 no opinion
   109   *	+1 likely
   110   */
   111  Prog*
   112  gbranch(int as, Type *t, int likely)
   113  {
   114  	Prog *p;
   115  	
   116  	USED(t);
   117  
   118  	p = prog(as);
   119  	p->to.type = D_BRANCH;
   120  	p->to.u.branch = P;
   121  	// TODO(minux): Enable this code.
   122  	// Note: liblink used Bcc CR0, label form, so we need another way
   123  	// to set likely/unlikely flag. Also note the y bit is not exactly
   124  	// likely/unlikely bit.
   125  	if(0 && as != ABR && likely != 0) {
   126  		p->from.type = D_CONST;
   127  		p->from.offset = likely > 0;
   128  	}
   129  	return p;
   130  }
   131  
   132  /*
   133   * patch previous branch to jump to to.
   134   */
   135  void
   136  patch(Prog *p, Prog *to)
   137  {
   138  	if(p->to.type != D_BRANCH)
   139  		fatal("patch: not a branch");
   140  	p->to.u.branch = to;
   141  	p->to.offset = to->pc;
   142  }
   143  
   144  Prog*
   145  unpatch(Prog *p)
   146  {
   147  	Prog *q;
   148  
   149  	if(p->to.type != D_BRANCH)
   150  		fatal("unpatch: not a branch");
   151  	q = p->to.u.branch;
   152  	p->to.u.branch = P;
   153  	p->to.offset = 0;
   154  	return q;
   155  }
   156  
   157  /*
   158   * start a new Prog list.
   159   */
   160  Plist*
   161  newplist(void)
   162  {
   163  	Plist *pl;
   164  
   165  	pl = linknewplist(ctxt);
   166  
   167  	pc = mal(sizeof(*pc));
   168  	clearp(pc);
   169  	pl->firstpc = pc;
   170  
   171  	return pl;
   172  }
   173  
   174  void
   175  gused(Node *n)
   176  {
   177  	gins(ANOP, n, N);	// used
   178  }
   179  
   180  Prog*
   181  gjmp(Prog *to)
   182  {
   183  	Prog *p;
   184  
   185  	p = gbranch(ABR, T, 0);
   186  	if(to != P)
   187  		patch(p, to);
   188  	return p;
   189  }
   190  
   191  void
   192  ggloblnod(Node *nam)
   193  {
   194  	Prog *p;
   195  
   196  	p = gins(AGLOBL, nam, N);
   197  	p->lineno = nam->lineno;
   198  	p->from.sym->gotype = linksym(ngotype(nam));
   199  	p->to.sym = nil;
   200  	p->to.type = D_CONST;
   201  	p->to.offset = nam->type->width;
   202  	if(nam->readonly)
   203  		p->reg = RODATA;
   204  	if(nam->type != T && !haspointers(nam->type))
   205  		p->reg |= NOPTR;
   206  }
   207  
   208  void
   209  gtrack(Sym *s)
   210  {
   211  	Prog *p;
   212  	
   213  	p = gins(AUSEFIELD, N, N);
   214  	p->from.type = D_OREG;
   215  	p->from.name = D_EXTERN;
   216  	p->from.sym = linksym(s);
   217  }
   218  
   219  void
   220  ggloblsym(Sym *s, int32 width, int8 flags)
   221  {
   222  	Prog *p;
   223  
   224  	p = gins(AGLOBL, N, N);
   225  	p->from.type = D_OREG;
   226  	p->from.name = D_EXTERN;
   227  	p->from.sym = linksym(s);
   228  	p->to.type = D_CONST;
   229  	p->to.name = D_NONE;
   230  	p->to.offset = width;
   231  	p->reg = flags;
   232  }
   233  
   234  int
   235  isfat(Type *t)
   236  {
   237  	if(t != T)
   238  	switch(t->etype) {
   239  	case TSTRUCT:
   240  	case TARRAY:
   241  	case TSTRING:
   242  	case TINTER:	// maybe remove later
   243  		return 1;
   244  	}
   245  	return 0;
   246  }
   247  
   248  /*
   249   * naddr of func generates code for address of func.
   250   * if using opcode that can take address implicitly,
   251   * call afunclit to fix up the argument.
   252   */
   253  void
   254  afunclit(Addr *a, Node *n)
   255  {
   256  	if(a->type == D_CONST && a->name == D_EXTERN) {
   257  		a->type = D_OREG;
   258  		a->sym = linksym(n->sym);
   259  	}
   260  }
   261  
   262  static	int	resvd[] =
   263  {
   264  	REGZERO,
   265  	REGSP,	// reserved for SP
   266  	// We need to preserve the C ABI TLS pointer because sigtramp
   267  	// may happen during C code and needs to access the g.  C
   268  	// clobbers REGG, so if Go were to clobber REGTLS, sigtramp
   269  	// won't know which convention to use.  By preserving REGTLS,
   270  	// we can just retrieve g from TLS when we aren't sure.
   271  	REGTLS,
   272  	// TODO(austin): Consolidate REGTLS and REGG?
   273  	REGG,
   274  	REGTMP,	// REGTMP
   275  	FREGCVI+NREG,
   276  	FREGZERO+NREG,
   277  	FREGHALF+NREG,
   278  	FREGONE+NREG,
   279  	FREGTWO+NREG,
   280  };
   281  
   282  void
   283  ginit(void)
   284  {
   285  	int i;
   286  
   287  	for(i=0; i<nelem(reg); i++)
   288  		reg[i] = 1;
   289  	for(i=0; i<NREG; i++)
   290  		reg[i] = 0;
   291  	for(i=NREG; i<NREG+NREG; i++)
   292  		reg[i] = 0;
   293  
   294  	for(i=0; i<nelem(resvd); i++)
   295  		reg[resvd[i]]++;
   296  }
   297  
   298  static	uintptr	regpc[nelem(reg)];
   299  
   300  void
   301  gclean(void)
   302  {
   303  	int i;
   304  
   305  	for(i=0; i<nelem(resvd); i++)
   306  		reg[resvd[i]]--;
   307  
   308  	for(i=0; i<nelem(reg); i++)
   309  		if(reg[i])
   310  			yyerror("reg %R left allocated, %p\n", i, regpc[i]);
   311  }
   312  
   313  int32
   314  anyregalloc(void)
   315  {
   316  	int i, j;
   317  
   318  	for(i=0; i<nelem(reg); i++) {
   319  		if(reg[i] == 0)
   320  			goto ok;
   321  		for(j=0; j<nelem(resvd); j++)
   322  			if(resvd[j] == i)
   323  				goto ok;
   324  		return 1;
   325  	ok:;
   326  	}
   327  	return 0;
   328  }
   329  
   330  /*
   331   * allocate register of type t, leave in n.
   332   * if o != N, o is desired fixed register.
   333   * caller must regfree(n).
   334   */
   335  void
   336  regalloc(Node *n, Type *t, Node *o)
   337  {
   338  	int i, et;
   339  	int fixfree, fltfree;
   340  
   341  	if(t == T)
   342  		fatal("regalloc: t nil");
   343  	et = simtype[t->etype];
   344  
   345  	if(debug['r']) {
   346  		fixfree = 0;
   347  		fltfree = 0;
   348  		for(i = D_R0; i < D_F0+NREG; i++)
   349  			if(reg[i] == 0) {
   350  				if(i < D_F0)
   351  					fixfree++;
   352  				else
   353  					fltfree++;
   354  			}
   355  		print("regalloc fix %d flt %d free\n", fixfree, fltfree);
   356  	}
   357  
   358  	switch(et) {
   359  	case TINT8:
   360  	case TUINT8:
   361  	case TINT16:
   362  	case TUINT16:
   363  	case TINT32:
   364  	case TUINT32:
   365  	case TINT64:
   366  	case TUINT64:
   367  	case TPTR32:
   368  	case TPTR64:
   369  	case TBOOL:
   370  		if(o != N && o->op == OREGISTER) {
   371  			i = o->val.u.reg;
   372  			if(i >= D_R0+REGMIN && i <= D_R0+REGMAX)
   373  				goto out;
   374  		}
   375  		for(i=D_R0+REGMIN; i<=D_R0+REGMAX; i++)
   376  			if(reg[i] == 0) {
   377  				regpc[i] = (uintptr)getcallerpc(&n);
   378  				goto out;
   379  			}
   380  		flusherrors();
   381  		for(i=D_R0; i<D_R0+NREG; i++)
   382  			print("R%d %p\n", i, regpc[i]);
   383  		fatal("out of fixed registers");
   384  
   385  	case TFLOAT32:
   386  	case TFLOAT64:
   387  		if(o != N && o->op == OREGISTER) {
   388  			i = o->val.u.reg;
   389  			if(i >= D_F0+FREGMIN && i <= D_F0+FREGMAX)
   390  				goto out;
   391  		}
   392  		for(i=D_F0+FREGMIN; i<=D_F0+FREGMAX; i++)
   393  			if(reg[i] == 0) {
   394  				regpc[i] = (uintptr)getcallerpc(&n);
   395  				goto out;
   396  			}
   397  		flusherrors();
   398  		for(i=D_F0; i<D_F0+NREG; i++)
   399  			print("F%d %p\n", i, regpc[i]);
   400  		fatal("out of floating registers");
   401  
   402  	case TCOMPLEX64:
   403  	case TCOMPLEX128:
   404  		tempname(n, t);
   405  		return;
   406  	}
   407  	fatal("regalloc: unknown type %T", t);
   408  	return;
   409  
   410  out:
   411  	reg[i]++;
   412  	nodreg(n, t, i);
   413  }
   414  
   415  void
   416  regfree(Node *n)
   417  {
   418  	int i;
   419  
   420  	if(n->op == ONAME)
   421  		return;
   422  	if(n->op != OREGISTER && n->op != OINDREG)
   423  		fatal("regfree: not a register");
   424  	i = n->val.u.reg;
   425  	if(i == D_R0 + REGSP)
   426  		return;
   427  	if(i < 0 || i >= nelem(reg))
   428  		fatal("regfree: reg out of range");
   429  	if(reg[i] <= 0)
   430  		fatal("regfree: reg not allocated");
   431  	reg[i]--;
   432  	if(reg[i] == 0)
   433  		regpc[i] = 0;
   434  }
   435  
   436  /*
   437   * initialize n to be register r of type t.
   438   */
   439  void
   440  nodreg(Node *n, Type *t, int r)
   441  {
   442  	if(t == T)
   443  		fatal("nodreg: t nil");
   444  
   445  	memset(n, 0, sizeof(*n));
   446  	n->op = OREGISTER;
   447  	n->addable = 1;
   448  	ullmancalc(n);
   449  	n->val.u.reg = r;
   450  	n->type = t;
   451  }
   452  
   453  /*
   454   * initialize n to be indirect of register r; n is type t.
   455   */
   456  void
   457  nodindreg(Node *n, Type *t, int r)
   458  {
   459  	nodreg(n, t, r);
   460  	n->op = OINDREG;
   461  }
   462  
   463  Node*
   464  nodarg(Type *t, int fp)
   465  {
   466  	Node *n;
   467  	NodeList *l;
   468  	Type *first;
   469  	Iter savet;
   470  
   471  	// entire argument struct, not just one arg
   472  	if(t->etype == TSTRUCT && t->funarg) {
   473  		n = nod(ONAME, N, N);
   474  		n->sym = lookup(".args");
   475  		n->type = t;
   476  		first = structfirst(&savet, &t);
   477  		if(first == nil)
   478  			fatal("nodarg: bad struct");
   479  		if(first->width == BADWIDTH)
   480  			fatal("nodarg: offset not computed for %T", t);
   481  		n->xoffset = first->width;
   482  		n->addable = 1;
   483  		goto fp;
   484  	}
   485  
   486  	if(t->etype != TFIELD)
   487  		fatal("nodarg: not field %T", t);
   488  	
   489  	if(fp == 1) {
   490  		for(l=curfn->dcl; l; l=l->next) {
   491  			n = l->n;
   492  			if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym)
   493  				return n;
   494  		}
   495  	}
   496  
   497  	n = nod(ONAME, N, N);
   498  	n->type = t->type;
   499  	n->sym = t->sym;
   500  	
   501  	if(t->width == BADWIDTH)
   502  		fatal("nodarg: offset not computed for %T", t);
   503  	n->xoffset = t->width;
   504  	n->addable = 1;
   505  	n->orig = t->nname;
   506  
   507  fp:
   508  	// Rewrite argument named _ to __,
   509  	// or else the assignment to _ will be
   510  	// discarded during code generation.
   511  	if(isblank(n))
   512  		n->sym = lookup("__");
   513  
   514  	switch(fp) {
   515  	default:
   516  		fatal("nodarg %T %d", t, fp);
   517  
   518  	case 0:		// output arg for calling another function
   519  		n->op = OINDREG;
   520  		n->val.u.reg = D_R0+REGSP;
   521  		n->xoffset += 8;
   522  		break;
   523  
   524  	case 1:		// input arg to current function
   525  		n->class = PPARAM;
   526  		break;
   527  
   528  	case 2:		// offset output arg
   529  fatal("shouldn't be used");
   530  		n->op = OINDREG;
   531  		n->val.u.reg = D_R0 + REGSP;
   532  		n->xoffset += types[tptr]->width;
   533  		break;
   534  	}
   535  	n->typecheck = 1;
   536  	return n;
   537  }
   538  
   539  /*
   540   * generate
   541   *	as $c, n
   542   */
   543  void
   544  ginscon(int as, vlong c, Node *n2)
   545  {
   546  	Node n1, ntmp;
   547  
   548  	nodconst(&n1, types[TINT64], c);
   549  
   550  	if(as != AMOVD && (c < -BIG || c > BIG)) {
   551  		// cannot have more than 16-bit of immediate in ADD, etc.
   552  		// instead, MOV into register first.
   553  		regalloc(&ntmp, types[TINT64], N);
   554  		gins(AMOVD, &n1, &ntmp);
   555  		gins(as, &ntmp, n2);
   556  		regfree(&ntmp);
   557  		return;
   558  	}
   559  	gins(as, &n1, n2);
   560  }
   561  
   562  /*
   563   * generate
   564   *	as n, $c (CMP/CMPU)
   565   */
   566  void
   567  ginscon2(int as, Node *n2, vlong c)
   568  {
   569  	Node n1, ntmp;
   570  
   571  	nodconst(&n1, types[TINT64], c);
   572  
   573  	switch(as) {
   574  	default:
   575  		fatal("ginscon2");
   576  	case ACMP:
   577  		if(-BIG <= c && c <= BIG) {
   578  			gins(as, n2, &n1);
   579  			return;
   580  		}
   581  		break;
   582  	case ACMPU:
   583  		if(0 <= c && c <= 2*BIG) {
   584  			gins(as, n2, &n1);
   585  			return;
   586  		}
   587  		break;
   588  	}
   589  	// MOV n1 into register first
   590  	regalloc(&ntmp, types[TINT64], N);
   591  	gins(AMOVD, &n1, &ntmp);
   592  	gins(as, n2, &ntmp);
   593  	regfree(&ntmp);
   594  }
   595  
   596  #define	CASE(a,b)	(((a)<<16)|((b)<<0))
   597  /*c2go int CASE(int, int); */
   598  
   599  /*
   600   * Is this node a memory operand?
   601   */
   602  int
   603  ismem(Node *n)
   604  {
   605  	switch(n->op) {
   606  	case OITAB:
   607  	case OSPTR:
   608  	case OLEN:
   609  	case OCAP:
   610  	case OINDREG:
   611  	case ONAME:
   612  	case OPARAM:
   613  	case OCLOSUREVAR:
   614  	case OADDR:
   615  		return 1;
   616  	}
   617  	return 0;
   618  }
   619  
   620  /*
   621   * set up nodes representing 2^63
   622   */
   623  Node bigi;
   624  Node bigf;
   625  
   626  void
   627  bignodes(void)
   628  {
   629  	static int did;
   630  
   631  	if(did)
   632  		return;
   633  	did = 1;
   634  
   635  	nodconst(&bigi, types[TUINT64], 1);
   636  	mpshiftfix(bigi.val.u.xval, 63);
   637  
   638  	bigf = bigi;
   639  	bigf.type = types[TFLOAT64];
   640  	bigf.val.ctype = CTFLT;
   641  	bigf.val.u.fval = mal(sizeof *bigf.val.u.fval);
   642  	mpmovefixflt(bigf.val.u.fval, bigi.val.u.xval);
   643  }
   644  
   645  /*
   646   * generate move:
   647   *	t = f
   648   * hard part is conversions.
   649   */
   650  void
   651  gmove(Node *f, Node *t)
   652  {
   653  	int a, ft, tt;
   654  	Type *cvt;
   655  	Node r1, r2, r3, con;
   656  	Prog *p1, *p2;
   657  
   658  	if(debug['M'])
   659  		print("gmove %lN -> %lN\n", f, t);
   660  
   661  	ft = simsimtype(f->type);
   662  	tt = simsimtype(t->type);
   663  	cvt = t->type;
   664  
   665  	if(iscomplex[ft] || iscomplex[tt]) {
   666  		complexmove(f, t);
   667  		return;
   668  	}
   669  
   670  	// cannot have two memory operands
   671  	if(ismem(f) && ismem(t))
   672  		goto hard;
   673  
   674  	// convert constant to desired type
   675  	if(f->op == OLITERAL) {
   676  		switch(tt) {
   677  		default:
   678  			convconst(&con, t->type, &f->val);
   679  			break;
   680  
   681  		case TINT32:
   682  		case TINT16:
   683  		case TINT8:
   684  			convconst(&con, types[TINT64], &f->val);
   685  			regalloc(&r1, con.type, t);
   686  			gins(AMOVD, &con, &r1);
   687  			gmove(&r1, t);
   688  			regfree(&r1);
   689  			return;
   690  
   691  		case TUINT32:
   692  		case TUINT16:
   693  		case TUINT8:
   694  			convconst(&con, types[TUINT64], &f->val);
   695  			regalloc(&r1, con.type, t);
   696  			gins(AMOVD, &con, &r1);
   697  			gmove(&r1, t);
   698  			regfree(&r1);
   699  			return;
   700  		}
   701  
   702  		f = &con;
   703  		ft = tt;	// so big switch will choose a simple mov
   704  
   705  		// constants can't move directly to memory.
   706  		if(ismem(t)) {
   707  			goto hard;
   708  			// float constants come from memory.
   709  			//if(isfloat[tt])
   710  			//	goto hard;
   711  
   712  			// 64-bit immediates are also from memory.
   713  			//if(isint[tt])
   714  			//	goto hard;
   715  			//// 64-bit immediates are really 32-bit sign-extended
   716  			//// unless moving into a register.
   717  			//if(isint[tt]) {
   718  			//	if(mpcmpfixfix(con.val.u.xval, minintval[TINT32]) < 0)
   719  			//		goto hard;
   720  			//	if(mpcmpfixfix(con.val.u.xval, maxintval[TINT32]) > 0)
   721  			//		goto hard;
   722  			//}
   723  		}
   724  	}
   725  
   726  	// value -> value copy, only one memory operand.
   727  	// figure out the instruction to use.
   728  	// break out of switch for one-instruction gins.
   729  	// goto rdst for "destination must be register".
   730  	// goto hard for "convert to cvt type first".
   731  	// otherwise handle and return.
   732  
   733  	switch(CASE(ft, tt)) {
   734  	default:
   735  		fatal("gmove %lT -> %lT", f->type, t->type);
   736  
   737  	/*
   738  	 * integer copy and truncate
   739  	 */
   740  	case CASE(TINT8, TINT8):	// same size
   741  	case CASE(TUINT8, TINT8):
   742  	case CASE(TINT16, TINT8):	// truncate
   743  	case CASE(TUINT16, TINT8):
   744  	case CASE(TINT32, TINT8):
   745  	case CASE(TUINT32, TINT8):
   746  	case CASE(TINT64, TINT8):
   747  	case CASE(TUINT64, TINT8):
   748  		a = AMOVB;
   749  		break;
   750  
   751  	case CASE(TINT8, TUINT8):	// same size
   752  	case CASE(TUINT8, TUINT8):
   753  	case CASE(TINT16, TUINT8):	// truncate
   754  	case CASE(TUINT16, TUINT8):
   755  	case CASE(TINT32, TUINT8):
   756  	case CASE(TUINT32, TUINT8):
   757  	case CASE(TINT64, TUINT8):
   758  	case CASE(TUINT64, TUINT8):
   759  		a = AMOVBZ;
   760  		break;
   761  
   762  	case CASE(TINT16, TINT16):	// same size
   763  	case CASE(TUINT16, TINT16):
   764  	case CASE(TINT32, TINT16):	// truncate
   765  	case CASE(TUINT32, TINT16):
   766  	case CASE(TINT64, TINT16):
   767  	case CASE(TUINT64, TINT16):
   768  		a = AMOVH;
   769  		break;
   770  
   771  	case CASE(TINT16, TUINT16):	// same size
   772  	case CASE(TUINT16, TUINT16):
   773  	case CASE(TINT32, TUINT16):	// truncate
   774  	case CASE(TUINT32, TUINT16):
   775  	case CASE(TINT64, TUINT16):
   776  	case CASE(TUINT64, TUINT16):
   777  		a = AMOVHZ;
   778  		break;
   779  
   780  	case CASE(TINT32, TINT32):	// same size
   781  	case CASE(TUINT32, TINT32):
   782  	case CASE(TINT64, TINT32):	// truncate
   783  	case CASE(TUINT64, TINT32):
   784  		a = AMOVW;
   785  		break;
   786  
   787  	case CASE(TINT32, TUINT32):	// same size
   788  	case CASE(TUINT32, TUINT32):
   789  	case CASE(TINT64, TUINT32):
   790  	case CASE(TUINT64, TUINT32):
   791  		a = AMOVWZ;
   792  		break;
   793  
   794  	case CASE(TINT64, TINT64):	// same size
   795  	case CASE(TINT64, TUINT64):
   796  	case CASE(TUINT64, TINT64):
   797  	case CASE(TUINT64, TUINT64):
   798  		a = AMOVD;
   799  		break;
   800  
   801  	/*
   802  	 * integer up-conversions
   803  	 */
   804  	case CASE(TINT8, TINT16):	// sign extend int8
   805  	case CASE(TINT8, TUINT16):
   806  	case CASE(TINT8, TINT32):
   807  	case CASE(TINT8, TUINT32):
   808  	case CASE(TINT8, TINT64):
   809  	case CASE(TINT8, TUINT64):
   810  		a = AMOVB;
   811  		goto rdst;
   812  
   813  	case CASE(TUINT8, TINT16):	// zero extend uint8
   814  	case CASE(TUINT8, TUINT16):
   815  	case CASE(TUINT8, TINT32):
   816  	case CASE(TUINT8, TUINT32):
   817  	case CASE(TUINT8, TINT64):
   818  	case CASE(TUINT8, TUINT64):
   819  		a = AMOVBZ;
   820  		goto rdst;
   821  
   822  	case CASE(TINT16, TINT32):	// sign extend int16
   823  	case CASE(TINT16, TUINT32):
   824  	case CASE(TINT16, TINT64):
   825  	case CASE(TINT16, TUINT64):
   826  		a = AMOVH;
   827  		goto rdst;
   828  
   829  	case CASE(TUINT16, TINT32):	// zero extend uint16
   830  	case CASE(TUINT16, TUINT32):
   831  	case CASE(TUINT16, TINT64):
   832  	case CASE(TUINT16, TUINT64):
   833  		a = AMOVHZ;
   834  		goto rdst;
   835  
   836  	case CASE(TINT32, TINT64):	// sign extend int32
   837  	case CASE(TINT32, TUINT64):
   838  		a = AMOVW;
   839  		goto rdst;
   840  
   841  	case CASE(TUINT32, TINT64):	// zero extend uint32
   842  	case CASE(TUINT32, TUINT64):
   843  		a = AMOVWZ;
   844  		goto rdst;
   845  
   846  	/*
   847  	* float to integer
   848  	*/
   849  	case CASE(TFLOAT32, TINT32):
   850  	case CASE(TFLOAT64, TINT32):
   851  	case CASE(TFLOAT32, TINT64):
   852  	case CASE(TFLOAT64, TINT64):
   853  	case CASE(TFLOAT32, TINT16):
   854  	case CASE(TFLOAT32, TINT8):
   855  	case CASE(TFLOAT32, TUINT16):
   856  	case CASE(TFLOAT32, TUINT8):
   857  	case CASE(TFLOAT64, TINT16):
   858  	case CASE(TFLOAT64, TINT8):
   859  	case CASE(TFLOAT64, TUINT16):
   860  	case CASE(TFLOAT64, TUINT8):
   861  	case CASE(TFLOAT32, TUINT32):
   862  	case CASE(TFLOAT64, TUINT32):
   863  	case CASE(TFLOAT32, TUINT64):
   864  	case CASE(TFLOAT64, TUINT64):
   865  		//warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
   866  		//return;
   867  		// algorithm is:
   868  		//	if small enough, use native float64 -> int64 conversion.
   869  		//	otherwise, subtract 2^63, convert, and add it back.
   870  		bignodes();
   871  		regalloc(&r1, types[ft], f);
   872  		gmove(f, &r1);
   873  		if(tt == TUINT64) {
   874  			regalloc(&r2, types[TFLOAT64], N);
   875  			gmove(&bigf, &r2);
   876  			gins(AFCMPU, &r1, &r2);
   877  			p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1);
   878  			gins(AFSUB, &r2, &r1);
   879  			patch(p1, pc);
   880  			regfree(&r2);
   881  		}
   882  		regalloc(&r2, types[TFLOAT64], N);
   883  		regalloc(&r3, types[TINT64], t);
   884  		gins(AFCTIDZ, &r1, &r2);
   885  		p1 = gins(AFMOVD, &r2, N);
   886  		p1->to.type = D_OREG;
   887  		p1->to.reg = REGSP;
   888  		p1->to.offset = -8;
   889  		p1 = gins(AMOVD, N, &r3);
   890  		p1->from.type = D_OREG;
   891  		p1->from.reg = REGSP;
   892  		p1->from.offset = -8;
   893  		regfree(&r2);
   894  		regfree(&r1);
   895  		if(tt == TUINT64) {
   896  			p1 = gbranch(optoas(OLT, types[TFLOAT64]), T, +1); // use CR0 here again
   897  			nodreg(&r1, types[TINT64], D_R0+REGTMP);
   898  			gins(AMOVD, &bigi, &r1);
   899  			gins(AADD, &r1, &r3);
   900  			patch(p1, pc);
   901  		}
   902  		gmove(&r3, t);
   903  		regfree(&r3);
   904  		return;
   905  
   906  	/*
   907  	 * integer to float
   908  	 */
   909  	case CASE(TINT32, TFLOAT32):
   910  	case CASE(TINT32, TFLOAT64):
   911  	case CASE(TINT64, TFLOAT32):
   912  	case CASE(TINT64, TFLOAT64):
   913  	case CASE(TINT16, TFLOAT32):
   914  	case CASE(TINT16, TFLOAT64):
   915  	case CASE(TINT8, TFLOAT32):
   916  	case CASE(TINT8, TFLOAT64):
   917  	case CASE(TUINT16, TFLOAT32):
   918  	case CASE(TUINT16, TFLOAT64):
   919  	case CASE(TUINT8, TFLOAT32):
   920  	case CASE(TUINT8, TFLOAT64):
   921  	case CASE(TUINT32, TFLOAT32):
   922  	case CASE(TUINT32, TFLOAT64):
   923  	case CASE(TUINT64, TFLOAT32):
   924  	case CASE(TUINT64, TFLOAT64):
   925  		//warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
   926  		//return;
   927  		// algorithm is:
   928  		//	if small enough, use native int64 -> uint64 conversion.
   929  		//	otherwise, halve (rounding to odd?), convert, and double.
   930  		bignodes();
   931  		regalloc(&r1, types[TINT64], N);
   932  		gmove(f, &r1);
   933  		if(ft == TUINT64) {
   934  			nodreg(&r2, types[TUINT64], D_R0+REGTMP);
   935  			gmove(&bigi, &r2);
   936  			gins(ACMPU, &r1, &r2);
   937  			p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1);
   938  			p2 = gins(ASRD, N, &r1);
   939  			p2->from.type = D_CONST;
   940  			p2->from.offset = 1;
   941  			patch(p1, pc);
   942  		}
   943  		regalloc(&r2, types[TFLOAT64], t);
   944  		p1 = gins(AMOVD, &r1, N);
   945  		p1->to.type = D_OREG;
   946  		p1->to.reg = REGSP;
   947  		p1->to.offset = -8;
   948  		p1 = gins(AFMOVD, N, &r2);
   949  		p1->from.type = D_OREG;
   950  		p1->from.reg = REGSP;
   951  		p1->from.offset = -8;
   952  		gins(AFCFID, &r2, &r2);
   953  		regfree(&r1);
   954  		if(ft == TUINT64) {
   955  			p1 = gbranch(optoas(OLT, types[TUINT64]), T, +1); // use CR0 here again
   956  			nodreg(&r1, types[TFLOAT64], D_F0+FREGTWO);
   957  			gins(AFMUL, &r1, &r2);
   958  			patch(p1, pc);
   959  		}
   960  		gmove(&r2, t);
   961  		regfree(&r2);
   962  		return;
   963  
   964  	/*
   965  	 * float to float
   966  	 */
   967  	case CASE(TFLOAT32, TFLOAT32):
   968  		a = AFMOVS;
   969  		break;
   970  
   971  	case CASE(TFLOAT64, TFLOAT64):
   972  		a = AFMOVD;
   973  		break;
   974  
   975  	case CASE(TFLOAT32, TFLOAT64):
   976  		a = AFMOVS;
   977  		goto rdst;
   978  
   979  	case CASE(TFLOAT64, TFLOAT32):
   980  		a = AFRSP;
   981  		goto rdst;
   982  	}
   983  
   984  	gins(a, f, t);
   985  	return;
   986  
   987  rdst:
   988  	// requires register destination
   989  	regalloc(&r1, t->type, t);
   990  	gins(a, f, &r1);
   991  	gmove(&r1, t);
   992  	regfree(&r1);
   993  	return;
   994  
   995  hard:
   996  	// requires register intermediate
   997  	regalloc(&r1, cvt, t);
   998  	gmove(f, &r1);
   999  	gmove(&r1, t);
  1000  	regfree(&r1);
  1001  	return;
  1002  }
  1003  
  1004  /*
  1005   * generate one instruction:
  1006   *	as f, t
  1007   */
  1008  Prog*
  1009  gins(int as, Node *f, Node *t)
  1010  {
  1011  	int32 w;
  1012  	Prog *p;
  1013  	Addr af, at;
  1014  
  1015  	// TODO(austin): Add self-move test like in 6g (but be careful
  1016  	// of truncation moves)
  1017  
  1018  	memset(&af, 0, sizeof af);
  1019  	memset(&at, 0, sizeof at);
  1020  	if(f != N)
  1021  		naddr(f, &af, 1);
  1022  	if(t != N)
  1023  		naddr(t, &at, 1);
  1024  	p = prog(as);
  1025  	if(f != N)
  1026  		p->from = af;
  1027  	if(t != N)
  1028  		p->to = at;
  1029  	if(as == ATEXT)
  1030  		p->reg = 0;
  1031  	if(debug['g'])
  1032  		print("%P\n", p);
  1033  
  1034  	w = 0;
  1035  	switch(as) {
  1036  	case AMOVB:
  1037  	case AMOVBU:
  1038  	case AMOVBZ:
  1039  	case AMOVBZU:
  1040  		w = 1;
  1041  		break;
  1042  	case AMOVH:
  1043  	case AMOVHU:
  1044  	case AMOVHZ:
  1045  	case AMOVHZU:
  1046  		w = 2;
  1047  		break;
  1048  	case AMOVW:
  1049  	case AMOVWU:
  1050  	case AMOVWZ:
  1051  	case AMOVWZU:
  1052  		w = 4;
  1053  		break;
  1054  	case AMOVD:
  1055  	case AMOVDU:
  1056  		if(af.type == D_CONST)
  1057  			break;
  1058  		w = 8;
  1059  		break;
  1060  	}
  1061  	if(w != 0 && ((f != N && af.width < w) || (t != N && at.type != D_REG && at.width > w))) {
  1062  		dump("f", f);
  1063  		dump("t", t);
  1064  		fatal("bad width: %P (%d, %d)\n", p, af.width, at.width);
  1065  	}
  1066  
  1067  	return p;
  1068  }
  1069  
  1070  void
  1071  fixlargeoffset(Node *n)
  1072  {
  1073  	Node a;
  1074  
  1075  	if(n == N)
  1076  		return;
  1077  	if(n->op != OINDREG)
  1078  		return;
  1079  	if(n->val.u.reg == D_R0+REGSP) // stack offset cannot be large
  1080  		return;
  1081  	if(n->xoffset != (int32)n->xoffset) {
  1082  		// TODO(minux): offset too large, move into R31 and add to R31 instead.
  1083  		// this is used only in test/fixedbugs/issue6036.go.
  1084  		print("offset too large: %N\n", n);
  1085  		noimpl;
  1086  		a = *n;
  1087  		a.op = OREGISTER;
  1088  		a.type = types[tptr];
  1089  		a.xoffset = 0;
  1090  		cgen_checknil(&a);
  1091  		ginscon(optoas(OADD, types[tptr]), n->xoffset, &a);
  1092  		n->xoffset = 0;
  1093  	}
  1094  }
  1095  
  1096  /*
  1097   * generate code to compute n;
  1098   * make a refer to result.
  1099   */
  1100  void
  1101  naddr(Node *n, Addr *a, int canemitcode)
  1102  {
  1103  	Sym *s;
  1104  
  1105  	a->type = D_NONE;
  1106  	a->name = D_NONE;
  1107  	a->reg = NREG;
  1108  	a->gotype = nil;
  1109  	a->node = N;
  1110  	a->etype = 0;
  1111  	a->width = 0;
  1112  	if(n == N)
  1113  		return;
  1114  
  1115  	if(n->type != T && n->type->etype != TIDEAL) {
  1116  		dowidth(n->type);
  1117  		a->width = n->type->width;
  1118  	}
  1119  
  1120  	switch(n->op) {
  1121  	default:
  1122  		fatal("naddr: bad %O %D", n->op, a);
  1123  		break;
  1124  
  1125  	case ONAME:
  1126  		a->etype = 0;
  1127  		a->reg = NREG;
  1128  		if(n->type != T)
  1129  			a->etype = simtype[n->type->etype];
  1130  		a->offset = n->xoffset;
  1131  		s = n->sym;
  1132  		a->node = n->orig;
  1133  		//if(a->node >= (Node*)&n)
  1134  		//	fatal("stack node");
  1135  		if(s == S)
  1136  			s = lookup(".noname");
  1137  		if(n->method) {
  1138  			if(n->type != T)
  1139  			if(n->type->sym != S)
  1140  			if(n->type->sym->pkg != nil)
  1141  				s = pkglookup(s->name, n->type->sym->pkg);
  1142  		}
  1143  
  1144  		a->type = D_OREG;
  1145  		switch(n->class) {
  1146  		default:
  1147  			fatal("naddr: ONAME class %S %d\n", n->sym, n->class);
  1148  		case PEXTERN:
  1149  			a->name = D_EXTERN;
  1150  			break;
  1151  		case PAUTO:
  1152  			a->name = D_AUTO;
  1153  			break;
  1154  		case PPARAM:
  1155  		case PPARAMOUT:
  1156  			a->name = D_PARAM;
  1157  			break;
  1158  		case PFUNC:
  1159  			a->name = D_EXTERN;
  1160  			a->type = D_CONST;
  1161  			a->width = widthptr;
  1162  			s = funcsym(s);
  1163  			break;
  1164  		}
  1165  		a->sym = linksym(s);
  1166  		break;
  1167  
  1168  	case OLITERAL:
  1169  		switch(n->val.ctype) {
  1170  		default:
  1171  			fatal("naddr: const %lT", n->type);
  1172  			break;
  1173  		case CTFLT:
  1174  			a->type = D_FCONST;
  1175  			a->u.dval = mpgetflt(n->val.u.fval);
  1176  			break;
  1177  		case CTINT:
  1178  		case CTRUNE:
  1179  			a->sym = nil;
  1180  			a->type = D_CONST;
  1181  			a->offset = mpgetfix(n->val.u.xval);
  1182  			break;
  1183  		case CTSTR:
  1184  			datagostring(n->val.u.sval, a);
  1185  			break;
  1186  		case CTBOOL:
  1187  			a->sym = nil;
  1188  			a->type = D_CONST;
  1189  			a->offset = n->val.u.bval;
  1190  			break;
  1191  		case CTNIL:
  1192  			a->sym = nil;
  1193  			a->type = D_CONST;
  1194  			a->offset = 0;
  1195  			break;
  1196  		}
  1197  		break;
  1198  
  1199  	case OREGISTER:
  1200  		if(n->val.u.reg < D_F0) {
  1201  			a->type = D_REG;
  1202  			a->reg = n->val.u.reg;
  1203  		} else {
  1204  			a->type = D_FREG;
  1205  			a->reg = n->val.u.reg - D_F0;
  1206  		}
  1207  		a->sym = nil;
  1208  		break;
  1209  
  1210  	case OINDREG:
  1211  		a->type = D_OREG;
  1212  		a->reg = n->val.u.reg;
  1213  		a->sym = linksym(n->sym);
  1214  		a->offset = n->xoffset;
  1215  		if(a->offset != (int32)a->offset)
  1216  			yyerror("offset %lld too large for OINDREG", a->offset);
  1217  		break;
  1218  
  1219  	case OPARAM:
  1220  		// n->left is PHEAP ONAME for stack parameter.
  1221  		// compute address of actual parameter on stack.
  1222  		a->etype = simtype[n->left->type->etype];
  1223  		a->width = n->left->type->width;
  1224  		a->offset = n->xoffset;
  1225  		a->sym = linksym(n->left->sym);
  1226  		a->type = D_OREG;
  1227  		a->name = D_PARAM;
  1228  		a->node = n->left->orig;
  1229  		break;
  1230  
  1231  	case OCLOSUREVAR:
  1232  		if(!curfn->needctxt)
  1233  			fatal("closurevar without needctxt");
  1234  		a->type = D_OREG;
  1235  		a->reg = REGENV;
  1236  		a->offset = n->xoffset;
  1237  		a->sym = nil;
  1238  		break;
  1239  
  1240  	case OCFUNC:
  1241  		naddr(n->left, a, canemitcode);
  1242  		a->sym = linksym(n->left->sym);
  1243  		break;
  1244  
  1245  	case OITAB:
  1246  		// itable of interface value
  1247  		naddr(n->left, a, canemitcode);
  1248  		a->etype = simtype[tptr];
  1249  		if(a->type == D_CONST && a->offset == 0)
  1250  			break;	// itab(nil)
  1251  		a->width = widthptr;
  1252  		break;
  1253  
  1254  	case OSPTR:
  1255  		// pointer in a string or slice
  1256  		naddr(n->left, a, canemitcode);
  1257  		a->etype = simtype[tptr];
  1258  		if(a->type == D_CONST && a->offset == 0)
  1259  			break;	// ptr(nil)
  1260  		a->offset += Array_array;
  1261  		a->width = widthptr;
  1262  		break;
  1263  
  1264  	case OLEN:
  1265  		// len of string or slice
  1266  		naddr(n->left, a, canemitcode);
  1267  		a->etype = simtype[TINT];
  1268  		if(a->type == D_CONST && a->offset == 0)
  1269  			break;	// len(nil)
  1270  		a->offset += Array_nel;
  1271  		a->width = widthint;
  1272  		break;
  1273  
  1274  	case OCAP:
  1275  		// cap of string or slice
  1276  		naddr(n->left, a, canemitcode);
  1277  		a->etype = simtype[TINT];
  1278  		if(a->type == D_CONST && a->offset == 0)
  1279  			break;	// cap(nil)
  1280  		a->offset += Array_cap;
  1281  		a->width = widthint;
  1282  		break;
  1283  
  1284  	case OADDR:
  1285  		naddr(n->left, a, canemitcode);
  1286  		a->etype = tptr;
  1287  		switch(a->type) {
  1288  		case D_OREG:
  1289  			a->type = D_CONST;
  1290  			break;
  1291  
  1292  		case D_REG:
  1293  		case D_CONST:
  1294  			break;
  1295  
  1296  		default:
  1297  			fatal("naddr: OADDR %d\n", a->type);
  1298  		}
  1299  		break;
  1300  	}
  1301  }
  1302  
  1303  /*
  1304   * return Axxx for Oxxx on type t.
  1305   */
  1306  int
  1307  optoas(int op, Type *t)
  1308  {
  1309  	int a;
  1310  
  1311  	if(t == T)
  1312  		fatal("optoas: t is nil");
  1313  
  1314  	a = AGOK;
  1315  	switch(CASE(op, simtype[t->etype])) {
  1316  	default:
  1317  		fatal("optoas: no entry for op=%O type=%T", op, t);
  1318  		break;
  1319  
  1320  	case CASE(OEQ, TBOOL):
  1321  	case CASE(OEQ, TINT8):
  1322  	case CASE(OEQ, TUINT8):
  1323  	case CASE(OEQ, TINT16):
  1324  	case CASE(OEQ, TUINT16):
  1325  	case CASE(OEQ, TINT32):
  1326  	case CASE(OEQ, TUINT32):
  1327  	case CASE(OEQ, TINT64):
  1328  	case CASE(OEQ, TUINT64):
  1329  	case CASE(OEQ, TPTR32):
  1330  	case CASE(OEQ, TPTR64):
  1331  	case CASE(OEQ, TFLOAT32):
  1332  	case CASE(OEQ, TFLOAT64):
  1333  		a = ABEQ;
  1334  		break;
  1335  
  1336  	case CASE(ONE, TBOOL):
  1337  	case CASE(ONE, TINT8):
  1338  	case CASE(ONE, TUINT8):
  1339  	case CASE(ONE, TINT16):
  1340  	case CASE(ONE, TUINT16):
  1341  	case CASE(ONE, TINT32):
  1342  	case CASE(ONE, TUINT32):
  1343  	case CASE(ONE, TINT64):
  1344  	case CASE(ONE, TUINT64):
  1345  	case CASE(ONE, TPTR32):
  1346  	case CASE(ONE, TPTR64):
  1347  	case CASE(ONE, TFLOAT32):
  1348  	case CASE(ONE, TFLOAT64):
  1349  		a = ABNE;
  1350  		break;
  1351  
  1352  	case CASE(OLT, TINT8):	// ACMP
  1353  	case CASE(OLT, TINT16):
  1354  	case CASE(OLT, TINT32):
  1355  	case CASE(OLT, TINT64):
  1356  	case CASE(OLT, TUINT8):	// ACMPU
  1357  	case CASE(OLT, TUINT16):
  1358  	case CASE(OLT, TUINT32):
  1359  	case CASE(OLT, TUINT64):
  1360  	case CASE(OLT, TFLOAT32): // AFCMPU
  1361  	case CASE(OLT, TFLOAT64):
  1362  		a = ABLT;
  1363  		break;
  1364  
  1365  	case CASE(OLE, TINT8):	// ACMP
  1366  	case CASE(OLE, TINT16):
  1367  	case CASE(OLE, TINT32):
  1368  	case CASE(OLE, TINT64):
  1369  	case CASE(OLE, TUINT8):	// ACMPU
  1370  	case CASE(OLE, TUINT16):
  1371  	case CASE(OLE, TUINT32):
  1372  	case CASE(OLE, TUINT64):
  1373  	case CASE(OLE, TFLOAT32): // AFCMPU
  1374  	case CASE(OLE, TFLOAT64):
  1375  		a = ABLE;
  1376  		break;
  1377  
  1378  	case CASE(OGT, TINT8):
  1379  	case CASE(OGT, TINT16):
  1380  	case CASE(OGT, TINT32):
  1381  	case CASE(OGT, TINT64):
  1382  	case CASE(OGT, TUINT8):
  1383  	case CASE(OGT, TUINT16):
  1384  	case CASE(OGT, TUINT32):
  1385  	case CASE(OGT, TUINT64):
  1386  	case CASE(OGT, TFLOAT32):
  1387  	case CASE(OGT, TFLOAT64):
  1388  		a = ABGT;
  1389  		break;
  1390  
  1391  	case CASE(OGE, TINT8):
  1392  	case CASE(OGE, TINT16):
  1393  	case CASE(OGE, TINT32):
  1394  	case CASE(OGE, TINT64):
  1395  	case CASE(OGE, TUINT8):
  1396  	case CASE(OGE, TUINT16):
  1397  	case CASE(OGE, TUINT32):
  1398  	case CASE(OGE, TUINT64):
  1399  	case CASE(OGE, TFLOAT32):
  1400  	case CASE(OGE, TFLOAT64):
  1401  		a = ABGE;
  1402  		break;
  1403  
  1404  	case CASE(OCMP, TBOOL):
  1405  	case CASE(OCMP, TINT8):
  1406  	case CASE(OCMP, TINT16):
  1407  	case CASE(OCMP, TINT32):
  1408  	case CASE(OCMP, TPTR32):
  1409  	case CASE(OCMP, TINT64):
  1410  		a = ACMP;
  1411  		break;
  1412  
  1413  	case CASE(OCMP, TUINT8):
  1414  	case CASE(OCMP, TUINT16):
  1415  	case CASE(OCMP, TUINT32):
  1416  	case CASE(OCMP, TUINT64):
  1417  	case CASE(OCMP, TPTR64):
  1418  		a = ACMPU;
  1419  		break;
  1420  
  1421  	case CASE(OCMP, TFLOAT32):
  1422  	case CASE(OCMP, TFLOAT64):
  1423  		a = AFCMPU;
  1424  		break;
  1425  
  1426  	case CASE(OAS, TBOOL):
  1427  	case CASE(OAS, TINT8):
  1428  		a = AMOVB;
  1429  		break;
  1430  
  1431  	case CASE(OAS, TUINT8):
  1432  		a = AMOVBZ;
  1433  		break;
  1434  
  1435  	case CASE(OAS, TINT16):
  1436  		a = AMOVH;
  1437  		break;
  1438  
  1439  	case CASE(OAS, TUINT16):
  1440  		a = AMOVHZ;
  1441  		break;
  1442  
  1443  	case CASE(OAS, TINT32):
  1444  		a = AMOVW;
  1445  		break;
  1446  
  1447  	case CASE(OAS, TUINT32):
  1448  	case CASE(OAS, TPTR32):
  1449  		a = AMOVWZ;
  1450  		break;
  1451  
  1452  	case CASE(OAS, TINT64):
  1453  	case CASE(OAS, TUINT64):
  1454  	case CASE(OAS, TPTR64):
  1455  		a = AMOVD;
  1456  		break;
  1457  
  1458  	case CASE(OAS, TFLOAT32):
  1459  		a = AFMOVS;
  1460  		break;
  1461  
  1462  	case CASE(OAS, TFLOAT64):
  1463  		a = AFMOVD;
  1464  		break;
  1465  
  1466  	case CASE(OADD, TINT8):
  1467  	case CASE(OADD, TUINT8):
  1468  	case CASE(OADD, TINT16):
  1469  	case CASE(OADD, TUINT16):
  1470  	case CASE(OADD, TINT32):
  1471  	case CASE(OADD, TUINT32):
  1472  	case CASE(OADD, TPTR32):
  1473  	case CASE(OADD, TINT64):
  1474  	case CASE(OADD, TUINT64):
  1475  	case CASE(OADD, TPTR64):
  1476  		a = AADD;
  1477  		break;
  1478  
  1479  	case CASE(OADD, TFLOAT32):
  1480  		a = AFADDS;
  1481  		break;
  1482  
  1483  	case CASE(OADD, TFLOAT64):
  1484  		a = AFADD;
  1485  		break;
  1486  
  1487  	case CASE(OSUB, TINT8):
  1488  	case CASE(OSUB, TUINT8):
  1489  	case CASE(OSUB, TINT16):
  1490  	case CASE(OSUB, TUINT16):
  1491  	case CASE(OSUB, TINT32):
  1492  	case CASE(OSUB, TUINT32):
  1493  	case CASE(OSUB, TPTR32):
  1494  	case CASE(OSUB, TINT64):
  1495  	case CASE(OSUB, TUINT64):
  1496  	case CASE(OSUB, TPTR64):
  1497  		a = ASUB;
  1498  		break;
  1499  
  1500  	case CASE(OSUB, TFLOAT32):
  1501  		a = AFSUBS;
  1502  		break;
  1503  
  1504  	case CASE(OSUB, TFLOAT64):
  1505  		a = AFSUB;
  1506  		break;
  1507  
  1508  	case CASE(OMINUS, TINT8):
  1509  	case CASE(OMINUS, TUINT8):
  1510  	case CASE(OMINUS, TINT16):
  1511  	case CASE(OMINUS, TUINT16):
  1512  	case CASE(OMINUS, TINT32):
  1513  	case CASE(OMINUS, TUINT32):
  1514  	case CASE(OMINUS, TPTR32):
  1515  	case CASE(OMINUS, TINT64):
  1516  	case CASE(OMINUS, TUINT64):
  1517  	case CASE(OMINUS, TPTR64):
  1518  		a = ANEG;
  1519  		break;
  1520  
  1521  	case CASE(OAND, TINT8):
  1522  	case CASE(OAND, TUINT8):
  1523  	case CASE(OAND, TINT16):
  1524  	case CASE(OAND, TUINT16):
  1525  	case CASE(OAND, TINT32):
  1526  	case CASE(OAND, TUINT32):
  1527  	case CASE(OAND, TPTR32):
  1528  	case CASE(OAND, TINT64):
  1529  	case CASE(OAND, TUINT64):
  1530  	case CASE(OAND, TPTR64):
  1531  		a = AAND;
  1532  		break;
  1533  
  1534  	case CASE(OOR, TINT8):
  1535  	case CASE(OOR, TUINT8):
  1536  	case CASE(OOR, TINT16):
  1537  	case CASE(OOR, TUINT16):
  1538  	case CASE(OOR, TINT32):
  1539  	case CASE(OOR, TUINT32):
  1540  	case CASE(OOR, TPTR32):
  1541  	case CASE(OOR, TINT64):
  1542  	case CASE(OOR, TUINT64):
  1543  	case CASE(OOR, TPTR64):
  1544  		a = AOR;
  1545  		break;
  1546  
  1547  	case CASE(OXOR, TINT8):
  1548  	case CASE(OXOR, TUINT8):
  1549  	case CASE(OXOR, TINT16):
  1550  	case CASE(OXOR, TUINT16):
  1551  	case CASE(OXOR, TINT32):
  1552  	case CASE(OXOR, TUINT32):
  1553  	case CASE(OXOR, TPTR32):
  1554  	case CASE(OXOR, TINT64):
  1555  	case CASE(OXOR, TUINT64):
  1556  	case CASE(OXOR, TPTR64):
  1557  		a = AXOR;
  1558  		break;
  1559  
  1560  	// TODO(minux): handle rotates
  1561  	//case CASE(OLROT, TINT8):
  1562  	//case CASE(OLROT, TUINT8):
  1563  	//case CASE(OLROT, TINT16):
  1564  	//case CASE(OLROT, TUINT16):
  1565  	//case CASE(OLROT, TINT32):
  1566  	//case CASE(OLROT, TUINT32):
  1567  	//case CASE(OLROT, TPTR32):
  1568  	//case CASE(OLROT, TINT64):
  1569  	//case CASE(OLROT, TUINT64):
  1570  	//case CASE(OLROT, TPTR64):
  1571  	//	a = 0//???; RLDC?
  1572  	//	break;
  1573  
  1574  	case CASE(OLSH, TINT8):
  1575  	case CASE(OLSH, TUINT8):
  1576  	case CASE(OLSH, TINT16):
  1577  	case CASE(OLSH, TUINT16):
  1578  	case CASE(OLSH, TINT32):
  1579  	case CASE(OLSH, TUINT32):
  1580  	case CASE(OLSH, TPTR32):
  1581  	case CASE(OLSH, TINT64):
  1582  	case CASE(OLSH, TUINT64):
  1583  	case CASE(OLSH, TPTR64):
  1584  		a = ASLD;
  1585  		break;
  1586  
  1587  	case CASE(ORSH, TUINT8):
  1588  	case CASE(ORSH, TUINT16):
  1589  	case CASE(ORSH, TUINT32):
  1590  	case CASE(ORSH, TPTR32):
  1591  	case CASE(ORSH, TUINT64):
  1592  	case CASE(ORSH, TPTR64):
  1593  		a = ASRD;
  1594  		break;
  1595  
  1596  	case CASE(ORSH, TINT8):
  1597  	case CASE(ORSH, TINT16):
  1598  	case CASE(ORSH, TINT32):
  1599  	case CASE(ORSH, TINT64):
  1600  		a = ASRAD;
  1601  		break;
  1602  
  1603  	// TODO(minux): handle rotates
  1604  	//case CASE(ORROTC, TINT8):
  1605  	//case CASE(ORROTC, TUINT8):
  1606  	//case CASE(ORROTC, TINT16):
  1607  	//case CASE(ORROTC, TUINT16):
  1608  	//case CASE(ORROTC, TINT32):
  1609  	//case CASE(ORROTC, TUINT32):
  1610  	//case CASE(ORROTC, TINT64):
  1611  	//case CASE(ORROTC, TUINT64):
  1612  	//	a = 0//??? RLDC??
  1613  	//	break;
  1614  
  1615  	case CASE(OHMUL, TINT64):
  1616  		a = AMULHD;
  1617  		break;
  1618  	case CASE(OHMUL, TUINT64):
  1619  	case CASE(OHMUL, TPTR64):
  1620  		a = AMULHDU;
  1621  		break;
  1622  
  1623  	case CASE(OMUL, TINT8):
  1624  	case CASE(OMUL, TINT16):
  1625  	case CASE(OMUL, TINT32):
  1626  	case CASE(OMUL, TINT64):
  1627  		a = AMULLD;
  1628  		break;
  1629  
  1630  	case CASE(OMUL, TUINT8):
  1631  	case CASE(OMUL, TUINT16):
  1632  	case CASE(OMUL, TUINT32):
  1633  	case CASE(OMUL, TPTR32):
  1634  		// don't use word multiply, the high 32-bit are undefined.
  1635  		// fallthrough
  1636  	case CASE(OMUL, TUINT64):
  1637  	case CASE(OMUL, TPTR64):
  1638  		a = AMULLD; // for 64-bit multiplies, signedness doesn't matter.
  1639  		break;
  1640  
  1641  	case CASE(OMUL, TFLOAT32):
  1642  		a = AFMULS;
  1643  		break;
  1644  
  1645  	case CASE(OMUL, TFLOAT64):
  1646  		a = AFMUL;
  1647  		break;
  1648  
  1649  	case CASE(ODIV, TINT8):
  1650  	case CASE(ODIV, TINT16):
  1651  	case CASE(ODIV, TINT32):
  1652  	case CASE(ODIV, TINT64):
  1653  		a = ADIVD;
  1654  		break;
  1655  
  1656  	case CASE(ODIV, TUINT8):
  1657  	case CASE(ODIV, TUINT16):
  1658  	case CASE(ODIV, TUINT32):
  1659  	case CASE(ODIV, TPTR32):
  1660  	case CASE(ODIV, TUINT64):
  1661  	case CASE(ODIV, TPTR64):
  1662  		a = ADIVDU;
  1663  		break;
  1664  
  1665  	case CASE(ODIV, TFLOAT32):
  1666  		a = AFDIVS;
  1667  		break;
  1668  
  1669  	case CASE(ODIV, TFLOAT64):
  1670  		a = AFDIV;
  1671  		break;
  1672  
  1673  	}
  1674  	return a;
  1675  }
  1676  
  1677  enum
  1678  {
  1679  	ODynam		= 1<<0,
  1680  	OAddable	= 1<<1,
  1681  };
  1682  
  1683  int
  1684  xgen(Node *n, Node *a, int o)
  1685  {
  1686  	// TODO(minux)
  1687  	USED(n); USED(a); USED(o);
  1688  	return -1;
  1689  }
  1690  
  1691  void
  1692  sudoclean(void)
  1693  {
  1694  	return;
  1695  }
  1696  
  1697  /*
  1698   * generate code to compute address of n,
  1699   * a reference to a (perhaps nested) field inside
  1700   * an array or struct.
  1701   * return 0 on failure, 1 on success.
  1702   * on success, leaves usable address in a.
  1703   *
  1704   * caller is responsible for calling sudoclean
  1705   * after successful sudoaddable,
  1706   * to release the register used for a.
  1707   */
  1708  int
  1709  sudoaddable(int as, Node *n, Addr *a)
  1710  {
  1711  	// TODO(minux)
  1712  	USED(as); USED(n); USED(a);
  1713  	return 0;
  1714  }