github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/6c/cgen.c (about)

     1  // Inferno utils/6c/cgen.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/cgen.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 "gc.h"
    32  
    33  /* ,x/^(print|prtree)\(/i/\/\/ */
    34  int castup(Type*, Type*);
    35  int vaddr(Node *n, int a);
    36  
    37  void
    38  cgen(Node *n, Node *nn)
    39  {
    40  	Node *l, *r, *t;
    41  	Prog *p1;
    42  	Node nod, nod1, nod2, nod3, nod4;
    43  	int o, hardleft;
    44  	int32 v, curs;
    45  	vlong c;
    46  
    47  	if(debug['g']) {
    48  		prtree(nn, "cgen lhs");
    49  		prtree(n, "cgen");
    50  	}
    51  	if(n == Z || n->type == T)
    52  		return;
    53  	if(typesu[n->type->etype]) {
    54  		sugen(n, nn, n->type->width);
    55  		return;
    56  	}
    57  	l = n->left;
    58  	r = n->right;
    59  	o = n->op;
    60  	
    61  	if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
    62  		gmove(n, nn);
    63  		return;
    64  	}
    65  
    66  	if(n->addable >= INDEXED) {
    67  		if(nn == Z) {
    68  			switch(o) {
    69  			default:
    70  				nullwarn(Z, Z);
    71  				break;
    72  			case OINDEX:
    73  				nullwarn(l, r);
    74  				break;
    75  			}
    76  			return;
    77  		}
    78  		gmove(n, nn);
    79  		return;
    80  	}
    81  	curs = cursafe;
    82  
    83  	if(l->complex >= FNX)
    84  	if(r != Z && r->complex >= FNX)
    85  	switch(o) {
    86  	default:
    87  		if(cond(o) && typesu[l->type->etype])
    88  			break;
    89  
    90  		regret(&nod, r);
    91  		cgen(r, &nod);
    92  
    93  		regsalloc(&nod1, r);
    94  		gmove(&nod, &nod1);
    95  
    96  		regfree(&nod);
    97  		nod = *n;
    98  		nod.right = &nod1;
    99  
   100  		cgen(&nod, nn);
   101  		return;
   102  
   103  	case OFUNC:
   104  	case OCOMMA:
   105  	case OANDAND:
   106  	case OOROR:
   107  	case OCOND:
   108  	case ODOT:
   109  		break;
   110  	}
   111  
   112  	hardleft = l->addable < INDEXED || l->complex >= FNX;
   113  	switch(o) {
   114  	default:
   115  		diag(n, "unknown op in cgen: %O", o);
   116  		break;
   117  
   118  	case ONEG:
   119  	case OCOM:
   120  		if(nn == Z) {
   121  			nullwarn(l, Z);
   122  			break;
   123  		}
   124  		regalloc(&nod, l, nn);
   125  		cgen(l, &nod);
   126  		gopcode(o, n->type, Z, &nod);
   127  		gmove(&nod, nn);
   128  		regfree(&nod);
   129  		break;
   130  
   131  	case OAS:
   132  		if(l->op == OBIT)
   133  			goto bitas;
   134  		if(!hardleft) {
   135  			if(nn != Z || r->addable < INDEXED || hardconst(r)) {
   136  				if(r->complex >= FNX && nn == Z)
   137  					regret(&nod, r);
   138  				else
   139  					regalloc(&nod, r, nn);
   140  				cgen(r, &nod);
   141  				gmove(&nod, l);
   142  				if(nn != Z)
   143  					gmove(&nod, nn);
   144  				regfree(&nod);
   145  			} else
   146  				gmove(r, l);
   147  			break;
   148  		}
   149  		if(l->complex >= r->complex) {
   150  			if(l->op == OINDEX && immconst(r)) {
   151  				gmove(r, l);
   152  				break;
   153  			}
   154  			reglcgen(&nod1, l, Z);
   155  			if(r->addable >= INDEXED && !hardconst(r)) {
   156  				gmove(r, &nod1);
   157  				if(nn != Z)
   158  					gmove(r, nn);
   159  				regfree(&nod1);
   160  				break;
   161  			}
   162  			regalloc(&nod, r, nn);
   163  			cgen(r, &nod);
   164  		} else {
   165  			regalloc(&nod, r, nn);
   166  			cgen(r, &nod);
   167  			reglcgen(&nod1, l, Z);
   168  		}
   169  		gmove(&nod, &nod1);
   170  		regfree(&nod);
   171  		regfree(&nod1);
   172  		break;
   173  
   174  	bitas:
   175  		n = l->left;
   176  		regalloc(&nod, r, nn);
   177  		if(l->complex >= r->complex) {
   178  			reglcgen(&nod1, n, Z);
   179  			cgen(r, &nod);
   180  		} else {
   181  			cgen(r, &nod);
   182  			reglcgen(&nod1, n, Z);
   183  		}
   184  		regalloc(&nod2, n, Z);
   185  		gmove(&nod1, &nod2);
   186  		bitstore(l, &nod, &nod1, &nod2, nn);
   187  		break;
   188  
   189  	case OBIT:
   190  		if(nn == Z) {
   191  			nullwarn(l, Z);
   192  			break;
   193  		}
   194  		bitload(n, &nod, Z, Z, nn);
   195  		gmove(&nod, nn);
   196  		regfree(&nod);
   197  		break;
   198  
   199  	case OLSHR:
   200  	case OASHL:
   201  	case OASHR:
   202  		if(nn == Z) {
   203  			nullwarn(l, r);
   204  			break;
   205  		}
   206  		if(r->op == OCONST) {
   207  			if(r->vconst == 0) {
   208  				cgen(l, nn);
   209  				break;
   210  			}
   211  			regalloc(&nod, l, nn);
   212  			cgen(l, &nod);
   213  			if(o == OASHL && r->vconst == 1)
   214  				gopcode(OADD, n->type, &nod, &nod);
   215  			else
   216  				gopcode(o, n->type, r, &nod);
   217  			gmove(&nod, nn);
   218  			regfree(&nod);
   219  			break;
   220  		}
   221  
   222  		/*
   223  		 * get nod to be D_CX
   224  		 */
   225  		if(nodreg(&nod, nn, D_CX)) {
   226  			regsalloc(&nod1, n);
   227  			gmove(&nod, &nod1);
   228  			cgen(n, &nod);		/* probably a bug */
   229  			gmove(&nod, nn);
   230  			gmove(&nod1, &nod);
   231  			break;
   232  		}
   233  		reg[D_CX]++;
   234  		if(nn->op == OREGISTER && nn->reg == D_CX)
   235  			regalloc(&nod1, l, Z);
   236  		else
   237  			regalloc(&nod1, l, nn);
   238  		if(r->complex >= l->complex) {
   239  			cgen(r, &nod);
   240  			cgen(l, &nod1);
   241  		} else {
   242  			cgen(l, &nod1);
   243  			cgen(r, &nod);
   244  		}
   245  		gopcode(o, n->type, &nod, &nod1);
   246  		gmove(&nod1, nn);
   247  		regfree(&nod);
   248  		regfree(&nod1);
   249  		break;
   250  
   251  	case OADD:
   252  	case OSUB:
   253  	case OOR:
   254  	case OXOR:
   255  	case OAND:
   256  		if(nn == Z) {
   257  			nullwarn(l, r);
   258  			break;
   259  		}
   260  		if(typefd[n->type->etype])
   261  			goto fop;
   262  		if(r->op == OCONST) {
   263  			if(r->vconst == 0 && o != OAND) {
   264  				cgen(l, nn);
   265  				break;
   266  			}
   267  		}
   268  		if(n->op == OOR && l->op == OASHL && r->op == OLSHR
   269  		&& l->right->op == OCONST && r->right->op == OCONST
   270  		&& l->left->op == ONAME && r->left->op == ONAME
   271  		&& l->left->sym == r->left->sym
   272  		&& l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
   273  			regalloc(&nod, l->left, nn);
   274  			cgen(l->left, &nod);
   275  			gopcode(OROTL, n->type, l->right, &nod);
   276  			gmove(&nod, nn);
   277  			regfree(&nod);
   278  			break;
   279  		}
   280  		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
   281  		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
   282  			c = l->right->vconst;
   283  			if(c > 0 && c <= 3) {
   284  				if(l->left->complex >= r->complex) {
   285  					regalloc(&nod, l->left, nn);
   286  					cgen(l->left, &nod);
   287  					if(r->addable < INDEXED) {
   288  						regalloc(&nod1, r, Z);
   289  						cgen(r, &nod1);
   290  						genmuladd(&nod, &nod, 1 << c, &nod1);
   291  						regfree(&nod1);
   292  					}
   293  					else
   294  						genmuladd(&nod, &nod, 1 << c, r);
   295  				}
   296  				else {
   297  					regalloc(&nod, r, nn);
   298  					cgen(r, &nod);
   299  					regalloc(&nod1, l->left, Z);
   300  					cgen(l->left, &nod1);
   301  					genmuladd(&nod, &nod1, 1 << c, &nod);
   302  					regfree(&nod1);
   303  				}
   304  				gmove(&nod, nn);
   305  				regfree(&nod);
   306  				break;
   307  			}
   308  		}
   309  		if(r->addable >= INDEXED && !hardconst(r)) {
   310  			regalloc(&nod, l, nn);
   311  			cgen(l, &nod);
   312  			gopcode(o, n->type, r, &nod);
   313  			gmove(&nod, nn);
   314  			regfree(&nod);
   315  			break;
   316  		}
   317  		if(l->complex >= r->complex) {
   318  			regalloc(&nod, l, nn);
   319  			cgen(l, &nod);
   320  			regalloc(&nod1, r, Z);
   321  			cgen(r, &nod1);
   322  			gopcode(o, n->type, &nod1, &nod);
   323  		} else {
   324  			regalloc(&nod1, r, nn);
   325  			cgen(r, &nod1);
   326  			regalloc(&nod, l, Z);
   327  			cgen(l, &nod);
   328  			gopcode(o, n->type, &nod1, &nod);
   329  		}
   330  		gmove(&nod, nn);
   331  		regfree(&nod);
   332  		regfree(&nod1);
   333  		break;
   334  
   335  	case OLMOD:
   336  	case OMOD:
   337  	case OLMUL:
   338  	case OLDIV:
   339  	case OMUL:
   340  	case ODIV:
   341  		if(nn == Z) {
   342  			nullwarn(l, r);
   343  			break;
   344  		}
   345  		if(typefd[n->type->etype])
   346  			goto fop;
   347  		if(r->op == OCONST && typechl[n->type->etype]) {	/* TO DO */
   348  			SET(v);
   349  			switch(o) {
   350  			case ODIV:
   351  			case OMOD:
   352  				c = r->vconst;
   353  				if(c < 0)
   354  					c = -c;
   355  				v = xlog2(c);
   356  				if(v < 0)
   357  					break;
   358  				/* fall thru */
   359  			case OMUL:
   360  			case OLMUL:
   361  				regalloc(&nod, l, nn);
   362  				cgen(l, &nod);
   363  				switch(o) {
   364  				case OMUL:
   365  				case OLMUL:
   366  					mulgen(n->type, r, &nod);
   367  					break;
   368  				case ODIV:
   369  					sdiv2(r->vconst, v, l, &nod);
   370  					break;
   371  				case OMOD:
   372  					smod2(r->vconst, v, l, &nod);
   373  					break;
   374  				}
   375  				gmove(&nod, nn);
   376  				regfree(&nod);
   377  				goto done;
   378  			case OLDIV:
   379  				c = r->vconst;
   380  				if((c & 0x80000000) == 0)
   381  					break;
   382  				regalloc(&nod1, l, Z);
   383  				cgen(l, &nod1);
   384  				regalloc(&nod, l, nn);
   385  				zeroregm(&nod);
   386  				gins(ACMPL, &nod1, nodconst(c));
   387  				gins(ASBBL, nodconst(-1), &nod);
   388  				regfree(&nod1);
   389  				gmove(&nod, nn);
   390  				regfree(&nod);
   391  				goto done;
   392  			}
   393  		}
   394  
   395  		if(o == OMUL) {
   396  			if(l->addable >= INDEXED) {
   397  				t = l;
   398  				l = r;
   399  				r = t;
   400  			}
   401  			/* should favour AX */
   402  			regalloc(&nod, l, nn);
   403  			cgen(l, &nod);
   404  			if(r->addable < INDEXED || hardconst(r)) {
   405  				regalloc(&nod1, r, Z);
   406  				cgen(r, &nod1);
   407  				gopcode(OMUL, n->type, &nod1, &nod);
   408  				regfree(&nod1);
   409  			}else
   410  				gopcode(OMUL, n->type, r, &nod);	/* addressible */
   411  			gmove(&nod, nn);
   412  			regfree(&nod);
   413  			break;
   414  		}
   415  
   416  		/*
   417  		 * get nod to be D_AX
   418  		 * get nod1 to be D_DX
   419  		 */
   420  		if(nodreg(&nod, nn, D_AX)) {
   421  			regsalloc(&nod2, n);
   422  			gmove(&nod, &nod2);
   423  			v = reg[D_AX];
   424  			reg[D_AX] = 0;
   425  
   426  			if(isreg(l, D_AX)) {
   427  				nod3 = *n;
   428  				nod3.left = &nod2;
   429  				cgen(&nod3, nn);
   430  			} else
   431  			if(isreg(r, D_AX)) {
   432  				nod3 = *n;
   433  				nod3.right = &nod2;
   434  				cgen(&nod3, nn);
   435  			} else
   436  				cgen(n, nn);
   437  
   438  			gmove(&nod2, &nod);
   439  			reg[D_AX] = v;
   440  			break;
   441  		}
   442  		if(nodreg(&nod1, nn, D_DX)) {
   443  			regsalloc(&nod2, n);
   444  			gmove(&nod1, &nod2);
   445  			v = reg[D_DX];
   446  			reg[D_DX] = 0;
   447  
   448  			if(isreg(l, D_DX)) {
   449  				nod3 = *n;
   450  				nod3.left = &nod2;
   451  				cgen(&nod3, nn);
   452  			} else
   453  			if(isreg(r, D_DX)) {
   454  				nod3 = *n;
   455  				nod3.right = &nod2;
   456  				cgen(&nod3, nn);
   457  			} else
   458  				cgen(n, nn);
   459  
   460  			gmove(&nod2, &nod1);
   461  			reg[D_DX] = v;
   462  			break;
   463  		}
   464  		reg[D_AX]++;
   465  
   466  		if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
   467  			reg[D_DX]++;
   468  			if(l->addable < INDEXED) {
   469  				regalloc(&nod2, l, Z);
   470  				cgen(l, &nod2);
   471  				l = &nod2;
   472  			}
   473  			if(o == ODIV)
   474  				sdivgen(l, r, &nod, &nod1);
   475  			else
   476  				udivgen(l, r, &nod, &nod1);
   477  			gmove(&nod1, nn);
   478  			if(l == &nod2)
   479  				regfree(l);
   480  			goto freeaxdx;
   481  		}
   482  
   483  		if(l->complex >= r->complex) {
   484  			cgen(l, &nod);
   485  			reg[D_DX]++;
   486  			if(o == ODIV || o == OMOD)
   487  				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
   488  			if(o == OLDIV || o == OLMOD)
   489  				zeroregm(&nod1);
   490  			if(r->addable < INDEXED || r->op == OCONST) {
   491  				regsalloc(&nod3, r);
   492  				cgen(r, &nod3);
   493  				gopcode(o, n->type, &nod3, Z);
   494  			} else
   495  				gopcode(o, n->type, r, Z);
   496  		} else {
   497  			regsalloc(&nod3, r);
   498  			cgen(r, &nod3);
   499  			cgen(l, &nod);
   500  			reg[D_DX]++;
   501  			if(o == ODIV || o == OMOD)
   502  				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
   503  			if(o == OLDIV || o == OLMOD)
   504  				zeroregm(&nod1);
   505  			gopcode(o, n->type, &nod3, Z);
   506  		}
   507  		if(o == OMOD || o == OLMOD)
   508  			gmove(&nod1, nn);
   509  		else
   510  			gmove(&nod, nn);
   511  	freeaxdx:
   512  		regfree(&nod);
   513  		regfree(&nod1);
   514  		break;
   515  
   516  	case OASLSHR:
   517  	case OASASHL:
   518  	case OASASHR:
   519  		if(r->op == OCONST)
   520  			goto asand;
   521  		if(l->op == OBIT)
   522  			goto asbitop;
   523  		if(typefd[n->type->etype])
   524  			goto asand;	/* can this happen? */
   525  
   526  		/*
   527  		 * get nod to be D_CX
   528  		 */
   529  		if(nodreg(&nod, nn, D_CX)) {
   530  			regsalloc(&nod1, n);
   531  			gmove(&nod, &nod1);
   532  			cgen(n, &nod);
   533  			if(nn != Z)
   534  				gmove(&nod, nn);
   535  			gmove(&nod1, &nod);
   536  			break;
   537  		}
   538  		reg[D_CX]++;
   539  
   540  		if(r->complex >= l->complex) {
   541  			cgen(r, &nod);
   542  			if(hardleft)
   543  				reglcgen(&nod1, l, Z);
   544  			else
   545  				nod1 = *l;
   546  		} else {
   547  			if(hardleft)
   548  				reglcgen(&nod1, l, Z);
   549  			else
   550  				nod1 = *l;
   551  			cgen(r, &nod);
   552  		}
   553  
   554  		gopcode(o, l->type, &nod, &nod1);
   555  		regfree(&nod);
   556  		if(nn != Z)
   557  			gmove(&nod1, nn);
   558  		if(hardleft)
   559  			regfree(&nod1);
   560  		break;
   561  
   562  	case OASAND:
   563  	case OASADD:
   564  	case OASSUB:
   565  	case OASXOR:
   566  	case OASOR:
   567  	asand:
   568  		if(l->op == OBIT)
   569  			goto asbitop;
   570  		if(typefd[l->type->etype] || typefd[r->type->etype])
   571  			goto asfop;
   572  		if(l->complex >= r->complex) {
   573  			if(hardleft)
   574  				reglcgen(&nod, l, Z);
   575  			else
   576  				nod = *l;
   577  			if(!immconst(r)) {
   578  				regalloc(&nod1, r, nn);
   579  				cgen(r, &nod1);
   580  				gopcode(o, l->type, &nod1, &nod);
   581  				regfree(&nod1);
   582  			} else
   583  				gopcode(o, l->type, r, &nod);
   584  		} else {
   585  			regalloc(&nod1, r, nn);
   586  			cgen(r, &nod1);
   587  			if(hardleft)
   588  				reglcgen(&nod, l, Z);
   589  			else
   590  				nod = *l;
   591  			gopcode(o, l->type, &nod1, &nod);
   592  			regfree(&nod1);
   593  		}
   594  		if(nn != Z)
   595  			gmove(&nod, nn);
   596  		if(hardleft)
   597  			regfree(&nod);
   598  		break;
   599  
   600  	asfop:
   601  		if(l->complex >= r->complex) {
   602  			if(hardleft)
   603  				reglcgen(&nod, l, Z);
   604  			else
   605  				nod = *l;
   606  			if(r->addable < INDEXED){
   607  				regalloc(&nod1, r, nn);
   608  				cgen(r, &nod1);
   609  			}else
   610  				nod1 = *r;
   611  			regalloc(&nod2, r, Z);
   612  			gmove(&nod, &nod2);
   613  			gopcode(o, r->type, &nod1, &nod2);
   614  			gmove(&nod2, &nod);
   615  			regfree(&nod2);
   616  			if(r->addable < INDEXED)
   617  				regfree(&nod1);
   618  		} else {
   619  			regalloc(&nod1, r, nn);
   620  			cgen(r, &nod1);
   621  			if(hardleft)
   622  				reglcgen(&nod, l, Z);
   623  			else
   624  				nod = *l;
   625  			if(o != OASMUL && o != OASADD) {
   626  				regalloc(&nod2, r, Z);
   627  				gmove(&nod, &nod2);
   628  				gopcode(o, r->type, &nod1, &nod2);
   629  				regfree(&nod1);
   630  				gmove(&nod2, &nod);
   631  				regfree(&nod2);
   632  			} else {
   633  				gopcode(o, r->type, &nod, &nod1);
   634  				gmove(&nod1, &nod);
   635  				regfree(&nod1);
   636  			}
   637  		}
   638  		if(nn != Z)
   639  			gmove(&nod, nn);
   640  		if(hardleft)
   641  			regfree(&nod);
   642  		break;
   643  
   644  	case OASLMUL:
   645  	case OASLDIV:
   646  	case OASLMOD:
   647  	case OASMUL:
   648  	case OASDIV:
   649  	case OASMOD:
   650  		if(l->op == OBIT)
   651  			goto asbitop;
   652  		if(typefd[n->type->etype] || typefd[r->type->etype])
   653  			goto asfop;
   654  		if(r->op == OCONST && typechl[n->type->etype]) {
   655  			SET(v);
   656  			switch(o) {
   657  			case OASDIV:
   658  			case OASMOD:
   659  				c = r->vconst;
   660  				if(c < 0)
   661  					c = -c;
   662  				v = xlog2(c);
   663  				if(v < 0)
   664  					break;
   665  				/* fall thru */
   666  			case OASMUL:
   667  			case OASLMUL:
   668  				if(hardleft)
   669  					reglcgen(&nod2, l, Z);
   670  				else
   671  					nod2 = *l;
   672  				regalloc(&nod, l, nn);
   673  				cgen(&nod2, &nod);
   674  				switch(o) {
   675  				case OASMUL:
   676  				case OASLMUL:
   677  					mulgen(n->type, r, &nod);
   678  					break;
   679  				case OASDIV:
   680  					sdiv2(r->vconst, v, l, &nod);
   681  					break;
   682  				case OASMOD:
   683  					smod2(r->vconst, v, l, &nod);
   684  					break;
   685  				}
   686  			havev:
   687  				gmove(&nod, &nod2);
   688  				if(nn != Z)
   689  					gmove(&nod, nn);
   690  				if(hardleft)
   691  					regfree(&nod2);
   692  				regfree(&nod);
   693  				goto done;
   694  			case OASLDIV:
   695  				c = r->vconst;
   696  				if((c & 0x80000000) == 0)
   697  					break;
   698  				if(hardleft)
   699  					reglcgen(&nod2, l, Z);
   700  				else
   701  					nod2 = *l;
   702  				regalloc(&nod1, l, nn);
   703  				cgen(&nod2, &nod1);
   704  				regalloc(&nod, l, nn);
   705  				zeroregm(&nod);
   706  				gins(ACMPL, &nod1, nodconst(c));
   707  				gins(ASBBL, nodconst(-1), &nod);
   708  				regfree(&nod1);
   709  				goto havev;
   710  			}
   711  		}
   712  
   713  		if(o == OASMUL) {
   714  			/* should favour AX */
   715  			regalloc(&nod, l, nn);
   716  			if(r->complex >= FNX) {
   717  				regalloc(&nod1, r, Z);
   718  				cgen(r, &nod1);
   719  				r = &nod1;
   720  			}
   721  			if(hardleft)
   722  				reglcgen(&nod2, l, Z);
   723  			else
   724  				nod2 = *l;
   725  			cgen(&nod2, &nod);
   726  			if(r->addable < INDEXED || hardconst(r)) {
   727  				if(r->complex < FNX) {
   728  					regalloc(&nod1, r, Z);
   729  					cgen(r, &nod1);
   730  				}
   731  				gopcode(OASMUL, n->type, &nod1, &nod);
   732  				regfree(&nod1);
   733  			}
   734  			else
   735  				gopcode(OASMUL, n->type, r, &nod);
   736  			if(r == &nod1)
   737  				regfree(r);
   738  			gmove(&nod, &nod2);
   739  			if(nn != Z)
   740  				gmove(&nod, nn);
   741  			regfree(&nod);
   742  			if(hardleft)
   743  				regfree(&nod2);
   744  			break;
   745  		}
   746  
   747  		/*
   748  		 * get nod to be D_AX
   749  		 * get nod1 to be D_DX
   750  		 */
   751  		if(nodreg(&nod, nn, D_AX)) {
   752  			regsalloc(&nod2, n);
   753  			gmove(&nod, &nod2);
   754  			v = reg[D_AX];
   755  			reg[D_AX] = 0;
   756  
   757  			if(isreg(l, D_AX)) {
   758  				nod3 = *n;
   759  				nod3.left = &nod2;
   760  				cgen(&nod3, nn);
   761  			} else
   762  			if(isreg(r, D_AX)) {
   763  				nod3 = *n;
   764  				nod3.right = &nod2;
   765  				cgen(&nod3, nn);
   766  			} else
   767  				cgen(n, nn);
   768  
   769  			gmove(&nod2, &nod);
   770  			reg[D_AX] = v;
   771  			break;
   772  		}
   773  		if(nodreg(&nod1, nn, D_DX)) {
   774  			regsalloc(&nod2, n);
   775  			gmove(&nod1, &nod2);
   776  			v = reg[D_DX];
   777  			reg[D_DX] = 0;
   778  
   779  			if(isreg(l, D_DX)) {
   780  				nod3 = *n;
   781  				nod3.left = &nod2;
   782  				cgen(&nod3, nn);
   783  			} else
   784  			if(isreg(r, D_DX)) {
   785  				nod3 = *n;
   786  				nod3.right = &nod2;
   787  				cgen(&nod3, nn);
   788  			} else
   789  				cgen(n, nn);
   790  
   791  			gmove(&nod2, &nod1);
   792  			reg[D_DX] = v;
   793  			break;
   794  		}
   795  		reg[D_AX]++;
   796  		reg[D_DX]++;
   797  
   798  		if(l->complex >= r->complex) {
   799  			if(hardleft)
   800  				reglcgen(&nod2, l, Z);
   801  			else
   802  				nod2 = *l;
   803  			cgen(&nod2, &nod);
   804  			if(r->op == OCONST && typechl[r->type->etype]) {
   805  				switch(o) {
   806  				case OASDIV:
   807  					sdivgen(&nod2, r, &nod, &nod1);
   808  					goto divdone;
   809  				case OASLDIV:
   810  					udivgen(&nod2, r, &nod, &nod1);
   811  				divdone:
   812  					gmove(&nod1, &nod2);
   813  					if(nn != Z)
   814  						gmove(&nod1, nn);
   815  					goto freelxaxdx;
   816  				}
   817  			}
   818  			if(o == OASDIV || o == OASMOD)
   819  				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
   820  			if(o == OASLDIV || o == OASLMOD)
   821  				zeroregm(&nod1);
   822  			if(r->addable < INDEXED || r->op == OCONST ||
   823  			   !typeil[r->type->etype]) {
   824  				regalloc(&nod3, r, Z);
   825  				cgen(r, &nod3);
   826  				gopcode(o, l->type, &nod3, Z);
   827  				regfree(&nod3);
   828  			} else
   829  				gopcode(o, n->type, r, Z);
   830  		} else {
   831  			regalloc(&nod3, r, Z);
   832  			cgen(r, &nod3);
   833  			if(hardleft)
   834  				reglcgen(&nod2, l, Z);
   835  			else
   836  				nod2 = *l;
   837  			cgen(&nod2, &nod);
   838  			if(o == OASDIV || o == OASMOD)
   839  				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
   840  			if(o == OASLDIV || o == OASLMOD)
   841  				zeroregm(&nod1);
   842  			gopcode(o, l->type, &nod3, Z);
   843  			regfree(&nod3);
   844  		}
   845  		if(o == OASMOD || o == OASLMOD) {
   846  			gmove(&nod1, &nod2);
   847  			if(nn != Z)
   848  				gmove(&nod1, nn);
   849  		} else {
   850  			gmove(&nod, &nod2);
   851  			if(nn != Z)
   852  				gmove(&nod, nn);
   853  		}
   854  	freelxaxdx:
   855  		if(hardleft)
   856  			regfree(&nod2);
   857  		regfree(&nod);
   858  		regfree(&nod1);
   859  		break;
   860  
   861  	fop:
   862  		if(l->complex >= r->complex) {
   863  			regalloc(&nod, l, nn);
   864  			cgen(l, &nod);
   865  			if(r->addable < INDEXED) {
   866  				regalloc(&nod1, r, Z);
   867  				cgen(r, &nod1);
   868  				gopcode(o, n->type, &nod1, &nod);
   869  				regfree(&nod1);
   870  			} else
   871  				gopcode(o, n->type, r, &nod);
   872  		} else {
   873  			/* TO DO: could do better with r->addable >= INDEXED */
   874  			regalloc(&nod1, r, Z);
   875  			cgen(r, &nod1);
   876  			regalloc(&nod, l, nn);
   877  			cgen(l, &nod);
   878  			gopcode(o, n->type, &nod1, &nod);
   879  			regfree(&nod1);
   880  		}
   881  		gmove(&nod, nn);
   882  		regfree(&nod);
   883  		break;
   884  
   885  	asbitop:
   886  		regalloc(&nod4, n, nn);
   887  		if(l->complex >= r->complex) {
   888  			bitload(l, &nod, &nod1, &nod2, &nod4);
   889  			regalloc(&nod3, r, Z);
   890  			cgen(r, &nod3);
   891  		} else {
   892  			regalloc(&nod3, r, Z);
   893  			cgen(r, &nod3);
   894  			bitload(l, &nod, &nod1, &nod2, &nod4);
   895  		}
   896  		gmove(&nod, &nod4);
   897  
   898  		{	/* TO DO: check floating point source */
   899  			Node onod;
   900  
   901  			/* incredible grot ... */
   902  			onod = nod3;
   903  			onod.op = o;
   904  			onod.complex = 2;
   905  			onod.addable = 0;
   906  			onod.type = tfield;
   907  			onod.left = &nod4;
   908  			onod.right = &nod3;
   909  			cgen(&onod, Z);
   910  		}
   911  		regfree(&nod3);
   912  		gmove(&nod4, &nod);
   913  		regfree(&nod4);
   914  		bitstore(l, &nod, &nod1, &nod2, nn);
   915  		break;
   916  
   917  	case OADDR:
   918  		if(nn == Z) {
   919  			nullwarn(l, Z);
   920  			break;
   921  		}
   922  		lcgen(l, nn);
   923  		break;
   924  
   925  	case OFUNC:
   926  		if(l->complex >= FNX) {
   927  			if(l->op != OIND)
   928  				diag(n, "bad function call");
   929  
   930  			regret(&nod, l->left);
   931  			cgen(l->left, &nod);
   932  			regsalloc(&nod1, l->left);
   933  			gmove(&nod, &nod1);
   934  			regfree(&nod);
   935  
   936  			nod = *n;
   937  			nod.left = &nod2;
   938  			nod2 = *l;
   939  			nod2.left = &nod1;
   940  			nod2.complex = 1;
   941  			cgen(&nod, nn);
   942  
   943  			return;
   944  		}
   945  		gargs(r, &nod, &nod1);
   946  		if(l->addable < INDEXED) {
   947  			reglcgen(&nod, l, nn);
   948  			nod.op = OREGISTER;
   949  			gopcode(OFUNC, n->type, Z, &nod);
   950  			regfree(&nod);
   951  		} else
   952  			gopcode(OFUNC, n->type, Z, l);
   953  		if(REGARG >= 0 && reg[REGARG])
   954  			reg[REGARG]--;
   955  		if(nn != Z) {
   956  			regret(&nod, n);
   957  			gmove(&nod, nn);
   958  			regfree(&nod);
   959  		}
   960  		break;
   961  
   962  	case OIND:
   963  		if(nn == Z) {
   964  			nullwarn(l, Z);
   965  			break;
   966  		}
   967  		regialloc(&nod, n, nn);
   968  		r = l;
   969  		while(r->op == OADD)
   970  			r = r->right;
   971  		if(sconst(r)) {
   972  			v = r->vconst;
   973  			r->vconst = 0;
   974  			cgen(l, &nod);
   975  			nod.xoffset += v;
   976  			r->vconst = v;
   977  		} else
   978  			cgen(l, &nod);
   979  		regind(&nod, n);
   980  		gmove(&nod, nn);
   981  		regfree(&nod);
   982  		break;
   983  
   984  	case OEQ:
   985  	case ONE:
   986  	case OLE:
   987  	case OLT:
   988  	case OGE:
   989  	case OGT:
   990  	case OLO:
   991  	case OLS:
   992  	case OHI:
   993  	case OHS:
   994  		if(nn == Z) {
   995  			nullwarn(l, r);
   996  			break;
   997  		}
   998  		boolgen(n, 1, nn);
   999  		break;
  1000  
  1001  	case OANDAND:
  1002  	case OOROR:
  1003  		boolgen(n, 1, nn);
  1004  		if(nn == Z)
  1005  			patch(p, pc);
  1006  		break;
  1007  
  1008  	case ONOT:
  1009  		if(nn == Z) {
  1010  			nullwarn(l, Z);
  1011  			break;
  1012  		}
  1013  		boolgen(n, 1, nn);
  1014  		break;
  1015  
  1016  	case OCOMMA:
  1017  		cgen(l, Z);
  1018  		cgen(r, nn);
  1019  		break;
  1020  
  1021  	case OCAST:
  1022  		if(nn == Z) {
  1023  			nullwarn(l, Z);
  1024  			break;
  1025  		}
  1026  		/*
  1027  		 * convert from types l->n->nn
  1028  		 */
  1029  		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
  1030  			/* both null, gen l->nn */
  1031  			cgen(l, nn);
  1032  			break;
  1033  		}
  1034  		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
  1035  			if(l->type->etype == TIND && typechlp[n->type->etype])
  1036  				warn(n, "conversion of pointer to shorter integer");
  1037  		}else if(0){
  1038  			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
  1039  				if(typefd[l->type->etype] != typefd[nn->type->etype])
  1040  					regalloc(&nod, l, nn);
  1041  				else
  1042  					regalloc(&nod, nn, nn);
  1043  				cgen(l, &nod);
  1044  				gmove(&nod, nn);
  1045  				regfree(&nod);
  1046  				break;
  1047  			}
  1048  		}
  1049  		regalloc(&nod, l, nn);
  1050  		cgen(l, &nod);
  1051  		regalloc(&nod1, n, &nod);
  1052  		gmove(&nod, &nod1);
  1053  		gmove(&nod1, nn);
  1054  		regfree(&nod1);
  1055  		regfree(&nod);
  1056  		break;
  1057  
  1058  	case ODOT:
  1059  		sugen(l, nodrat, l->type->width);
  1060  		if(nn == Z)
  1061  			break;
  1062  		warn(n, "non-interruptable temporary");
  1063  		nod = *nodrat;
  1064  		if(!r || r->op != OCONST) {
  1065  			diag(n, "DOT and no offset");
  1066  			break;
  1067  		}
  1068  		nod.xoffset += (int32)r->vconst;
  1069  		nod.type = n->type;
  1070  		cgen(&nod, nn);
  1071  		break;
  1072  
  1073  	case OCOND:
  1074  		bcgen(l, 1);
  1075  		p1 = p;
  1076  		cgen(r->left, nn);
  1077  		gbranch(OGOTO);
  1078  		patch(p1, pc);
  1079  		p1 = p;
  1080  		cgen(r->right, nn);
  1081  		patch(p1, pc);
  1082  		break;
  1083  
  1084  	case OPOSTINC:
  1085  	case OPOSTDEC:
  1086  		v = 1;
  1087  		if(l->type->etype == TIND)
  1088  			v = l->type->link->width;
  1089  		if(o == OPOSTDEC)
  1090  			v = -v;
  1091  		if(l->op == OBIT)
  1092  			goto bitinc;
  1093  		if(nn == Z)
  1094  			goto pre;
  1095  
  1096  		if(hardleft)
  1097  			reglcgen(&nod, l, Z);
  1098  		else
  1099  			nod = *l;
  1100  
  1101  		gmove(&nod, nn);
  1102  		if(typefd[n->type->etype]) {
  1103  			regalloc(&nod1, l, Z);
  1104  			gmove(&nod, &nod1);
  1105  			if(v < 0)
  1106  				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
  1107  			else
  1108  				gopcode(OADD, n->type, nodfconst(v), &nod1);
  1109  			gmove(&nod1, &nod);
  1110  			regfree(&nod1);
  1111  		} else
  1112  			gopcode(OADD, n->type, nodconst(v), &nod);
  1113  		if(hardleft)
  1114  			regfree(&nod);
  1115  		break;
  1116  
  1117  	case OPREINC:
  1118  	case OPREDEC:
  1119  		v = 1;
  1120  		if(l->type->etype == TIND)
  1121  			v = l->type->link->width;
  1122  		if(o == OPREDEC)
  1123  			v = -v;
  1124  		if(l->op == OBIT)
  1125  			goto bitinc;
  1126  
  1127  	pre:
  1128  		if(hardleft)
  1129  			reglcgen(&nod, l, Z);
  1130  		else
  1131  			nod = *l;
  1132  		if(typefd[n->type->etype]) {
  1133  			regalloc(&nod1, l, Z);
  1134  			gmove(&nod, &nod1);
  1135  			if(v < 0)
  1136  				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
  1137  			else
  1138  				gopcode(OADD, n->type, nodfconst(v), &nod1);
  1139  			gmove(&nod1, &nod);
  1140  			regfree(&nod1);
  1141  		} else
  1142  			gopcode(OADD, n->type, nodconst(v), &nod);
  1143  		if(nn != Z)
  1144  			gmove(&nod, nn);
  1145  		if(hardleft)
  1146  			regfree(&nod);
  1147  		break;
  1148  
  1149  	bitinc:
  1150  		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
  1151  			bitload(l, &nod, &nod1, &nod2, Z);
  1152  			gmove(&nod, nn);
  1153  			gopcode(OADD, tfield, nodconst(v), &nod);
  1154  			bitstore(l, &nod, &nod1, &nod2, Z);
  1155  			break;
  1156  		}
  1157  		bitload(l, &nod, &nod1, &nod2, nn);
  1158  		gopcode(OADD, tfield, nodconst(v), &nod);
  1159  		bitstore(l, &nod, &nod1, &nod2, nn);
  1160  		break;
  1161  	}
  1162  done:
  1163  	cursafe = curs;
  1164  }
  1165  
  1166  void
  1167  reglcgen(Node *t, Node *n, Node *nn)
  1168  {
  1169  	Node *r;
  1170  	int32 v;
  1171  
  1172  	regialloc(t, n, nn);
  1173  	if(n->op == OIND) {
  1174  		r = n->left;
  1175  		while(r->op == OADD)
  1176  			r = r->right;
  1177  		if(sconst(r)) {
  1178  			v = r->vconst;
  1179  			r->vconst = 0;
  1180  			lcgen(n, t);
  1181  			t->xoffset += v;
  1182  			r->vconst = v;
  1183  			regind(t, n);
  1184  			return;
  1185  		}
  1186  	}
  1187  	lcgen(n, t);
  1188  	regind(t, n);
  1189  }
  1190  
  1191  void
  1192  lcgen(Node *n, Node *nn)
  1193  {
  1194  	Prog *p1;
  1195  	Node nod;
  1196  
  1197  	if(debug['g']) {
  1198  		prtree(nn, "lcgen lhs");
  1199  		prtree(n, "lcgen");
  1200  	}
  1201  	if(n == Z || n->type == T)
  1202  		return;
  1203  	if(nn == Z) {
  1204  		nn = &nod;
  1205  		regalloc(&nod, n, Z);
  1206  	}
  1207  	switch(n->op) {
  1208  	default:
  1209  		if(n->addable < INDEXED) {
  1210  			diag(n, "unknown op in lcgen: %O", n->op);
  1211  			break;
  1212  		}
  1213  		gopcode(OADDR, n->type, n, nn);
  1214  		break;
  1215  
  1216  	case OCOMMA:
  1217  		cgen(n->left, n->left);
  1218  		lcgen(n->right, nn);
  1219  		break;
  1220  
  1221  	case OIND:
  1222  		cgen(n->left, nn);
  1223  		break;
  1224  
  1225  	case OCOND:
  1226  		bcgen(n->left, 1);
  1227  		p1 = p;
  1228  		lcgen(n->right->left, nn);
  1229  		gbranch(OGOTO);
  1230  		patch(p1, pc);
  1231  		p1 = p;
  1232  		lcgen(n->right->right, nn);
  1233  		patch(p1, pc);
  1234  		break;
  1235  	}
  1236  }
  1237  
  1238  void
  1239  bcgen(Node *n, int true)
  1240  {
  1241  
  1242  	if(n->type == T)
  1243  		gbranch(OGOTO);
  1244  	else
  1245  		boolgen(n, true, Z);
  1246  }
  1247  
  1248  void
  1249  boolgen(Node *n, int true, Node *nn)
  1250  {
  1251  	int o;
  1252  	Prog *p1, *p2, *p3;
  1253  	Node *l, *r, nod, nod1;
  1254  	int32 curs;
  1255  
  1256  	if(debug['g']) {
  1257  		print("boolgen %d\n", true);
  1258  		prtree(nn, "boolgen lhs");
  1259  		prtree(n, "boolgen");
  1260  	}
  1261  	curs = cursafe;
  1262  	l = n->left;
  1263  	r = n->right;
  1264  	switch(n->op) {
  1265  
  1266  	default:
  1267  		o = ONE;
  1268  		if(true)
  1269  			o = OEQ;
  1270  		/* bad, 13 is address of external that becomes constant */
  1271  		if(n->addable >= INDEXED && n->addable != 13) {
  1272  			if(typefd[n->type->etype]) {
  1273  				regalloc(&nod1, n, Z);
  1274  				gmove(nodfconst(0.0), &nod1);	/* TO DO: FREGZERO */
  1275  				gopcode(o, n->type, n, &nod1);
  1276  				regfree(&nod1);
  1277  			} else
  1278  				gopcode(o, n->type, n, nodconst(0));
  1279  			goto com;
  1280  		}
  1281  		regalloc(&nod, n, nn);
  1282  		cgen(n, &nod);
  1283  		if(typefd[n->type->etype]) {
  1284  			regalloc(&nod1, n, Z);
  1285  			gmove(nodfconst(0.0), &nod1);	/* TO DO: FREGZERO */
  1286  			gopcode(o, n->type, &nod, &nod1);
  1287  			regfree(&nod1);
  1288  		} else
  1289  			gopcode(o, n->type, &nod, nodconst(0));
  1290  		regfree(&nod);
  1291  		goto com;
  1292  
  1293  	case OCONST:
  1294  		o = vconst(n);
  1295  		if(!true)
  1296  			o = !o;
  1297  		gbranch(OGOTO);
  1298  		if(o) {
  1299  			p1 = p;
  1300  			gbranch(OGOTO);
  1301  			patch(p1, pc);
  1302  		}
  1303  		goto com;
  1304  
  1305  	case OCOMMA:
  1306  		cgen(l, Z);
  1307  		boolgen(r, true, nn);
  1308  		break;
  1309  
  1310  	case ONOT:
  1311  		boolgen(l, !true, nn);
  1312  		break;
  1313  
  1314  	case OCOND:
  1315  		bcgen(l, 1);
  1316  		p1 = p;
  1317  		bcgen(r->left, true);
  1318  		p2 = p;
  1319  		gbranch(OGOTO);
  1320  		patch(p1, pc);
  1321  		p1 = p;
  1322  		bcgen(r->right, !true);
  1323  		patch(p2, pc);
  1324  		p2 = p;
  1325  		gbranch(OGOTO);
  1326  		patch(p1, pc);
  1327  		patch(p2, pc);
  1328  		goto com;
  1329  
  1330  	case OANDAND:
  1331  		if(!true)
  1332  			goto caseor;
  1333  
  1334  	caseand:
  1335  		bcgen(l, true);
  1336  		p1 = p;
  1337  		bcgen(r, !true);
  1338  		p2 = p;
  1339  		patch(p1, pc);
  1340  		gbranch(OGOTO);
  1341  		patch(p2, pc);
  1342  		goto com;
  1343  
  1344  	case OOROR:
  1345  		if(!true)
  1346  			goto caseand;
  1347  
  1348  	caseor:
  1349  		bcgen(l, !true);
  1350  		p1 = p;
  1351  		bcgen(r, !true);
  1352  		p2 = p;
  1353  		gbranch(OGOTO);
  1354  		patch(p1, pc);
  1355  		patch(p2, pc);
  1356  		goto com;
  1357  
  1358  	case OEQ:
  1359  	case ONE:
  1360  	case OLE:
  1361  	case OLT:
  1362  	case OGE:
  1363  	case OGT:
  1364  	case OHI:
  1365  	case OHS:
  1366  	case OLO:
  1367  	case OLS:
  1368  		o = n->op;
  1369  		if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
  1370  			// Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
  1371  			// Jump around instead.
  1372  			boolgen(n, 0, Z);
  1373  			p1 = p;
  1374  			gbranch(OGOTO);
  1375  			patch(p1, pc);
  1376  			goto com;
  1377  		}
  1378  		if(true)
  1379  			o = comrel[relindex(o)];
  1380  		if(l->complex >= FNX && r->complex >= FNX) {
  1381  			regret(&nod, r);
  1382  			cgen(r, &nod);
  1383  			regsalloc(&nod1, r);
  1384  			gmove(&nod, &nod1);
  1385  			regfree(&nod);
  1386  			nod = *n;
  1387  			nod.right = &nod1;
  1388  			boolgen(&nod, true, nn);
  1389  			break;
  1390  		}
  1391  		if(immconst(l)) {
  1392  			// NOTE: Reversing the comparison here is wrong
  1393  			// for floating point ordering comparisons involving NaN,
  1394  			// but we don't have any of those yet so we don't
  1395  			// bother worrying about it.
  1396  			o = invrel[relindex(o)];
  1397  			/* bad, 13 is address of external that becomes constant */
  1398  			if(r->addable < INDEXED || r->addable == 13) {
  1399  				regalloc(&nod, r, nn);
  1400  				cgen(r, &nod);
  1401  				gopcode(o, l->type, &nod, l);
  1402  				regfree(&nod);
  1403  			} else
  1404  				gopcode(o, l->type, r, l);
  1405  			goto com;
  1406  		}
  1407  		if(typefd[l->type->etype])
  1408  			o = invrel[relindex(logrel[relindex(o)])];
  1409  		if(l->complex >= r->complex) {
  1410  			regalloc(&nod, l, nn);
  1411  			cgen(l, &nod);
  1412  			if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) {
  1413  				regalloc(&nod1, r, Z);
  1414  				cgen(r, &nod1);
  1415  				gopcode(o, l->type, &nod, &nod1);
  1416  				regfree(&nod1);
  1417  			} else {
  1418  				gopcode(o, l->type, &nod, r);
  1419  			}
  1420  			regfree(&nod);
  1421  			goto fixfloat;
  1422  		}
  1423  		regalloc(&nod, r, nn);
  1424  		cgen(r, &nod);
  1425  		if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) {
  1426  			regalloc(&nod1, l, Z);
  1427  			cgen(l, &nod1);
  1428  			if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT])
  1429  				gopcode(o, types[TINT], &nod1, &nod);
  1430  			else
  1431  				gopcode(o, l->type, &nod1, &nod);
  1432  			regfree(&nod1);
  1433  		} else
  1434  			gopcode(o, l->type, l, &nod);
  1435  		regfree(&nod);
  1436  	fixfloat:
  1437  		if(typefd[l->type->etype]) {
  1438  			switch(o) {
  1439  			case OEQ:
  1440  				// Already emitted AJEQ; want AJEQ and AJPC.
  1441  				p1 = p;
  1442  				gbranch(OGOTO);
  1443  				p2 = p;
  1444  				patch(p1, pc);
  1445  				gins(AJPC, Z, Z);
  1446  				patch(p2, pc);
  1447  				break;
  1448  
  1449  			case ONE:
  1450  				// Already emitted AJNE; want AJNE or AJPS.
  1451  				p1 = p;
  1452  				gins(AJPS, Z, Z);
  1453  				p2 = p;
  1454  				gbranch(OGOTO);
  1455  				p3 = p;
  1456  				patch(p1, pc);
  1457  				patch(p2, pc);
  1458  				gbranch(OGOTO);
  1459  				patch(p3, pc);
  1460  				break;
  1461  			}
  1462  		}
  1463  
  1464  	com:
  1465  		if(nn != Z) {
  1466  			p1 = p;
  1467  			gmove(nodconst(1L), nn);
  1468  			gbranch(OGOTO);
  1469  			p2 = p;
  1470  			patch(p1, pc);
  1471  			gmove(nodconst(0L), nn);
  1472  			patch(p2, pc);
  1473  		}
  1474  		break;
  1475  	}
  1476  	cursafe = curs;
  1477  }
  1478  
  1479  void
  1480  sugen(Node *n, Node *nn, int32 w)
  1481  {
  1482  	Prog *p1;
  1483  	Node nod0, nod1, nod2, nod3, nod4, *l, *r;
  1484  	Type *t;
  1485  	int c, mt, mo;
  1486  	vlong o0, o1;
  1487  
  1488  	if(n == Z || n->type == T)
  1489  		return;
  1490  	if(debug['g']) {
  1491  		prtree(nn, "sugen lhs");
  1492  		prtree(n, "sugen");
  1493  	}
  1494  	if(nn == nodrat)
  1495  		if(w > nrathole)
  1496  			nrathole = w;
  1497  	switch(n->op) {
  1498  	case OIND:
  1499  		if(nn == Z) {
  1500  			nullwarn(n->left, Z);
  1501  			break;
  1502  		}
  1503  
  1504  	default:
  1505  		goto copy;
  1506  
  1507  	case OCONST:
  1508  		goto copy;
  1509  
  1510  	case ODOT:
  1511  		l = n->left;
  1512  		sugen(l, nodrat, l->type->width);
  1513  		if(nn == Z)
  1514  			break;
  1515  		warn(n, "non-interruptable temporary");
  1516  		nod1 = *nodrat;
  1517  		r = n->right;
  1518  		if(!r || r->op != OCONST) {
  1519  			diag(n, "DOT and no offset");
  1520  			break;
  1521  		}
  1522  		nod1.xoffset += (int32)r->vconst;
  1523  		nod1.type = n->type;
  1524  		sugen(&nod1, nn, w);
  1525  		break;
  1526  
  1527  	case OSTRUCT:
  1528  		/*
  1529  		 * rewrite so lhs has no fn call
  1530  		 */
  1531  		if(nn != Z && side(nn)) {
  1532  			nod1 = *n;
  1533  			nod1.type = typ(TIND, n->type);
  1534  			regret(&nod2, &nod1);
  1535  			lcgen(nn, &nod2);
  1536  			regsalloc(&nod0, &nod1);
  1537  			cgen(&nod2, &nod0);
  1538  			regfree(&nod2);
  1539  
  1540  			nod1 = *n;
  1541  			nod1.op = OIND;
  1542  			nod1.left = &nod0;
  1543  			nod1.right = Z;
  1544  			nod1.complex = 1;
  1545  
  1546  			sugen(n, &nod1, w);
  1547  			return;
  1548  		}
  1549  
  1550  		r = n->left;
  1551  		for(t = n->type->link; t != T; t = t->down) {
  1552  			l = r;
  1553  			if(r->op == OLIST) {
  1554  				l = r->left;
  1555  				r = r->right;
  1556  			}
  1557  			if(nn == Z) {
  1558  				cgen(l, nn);
  1559  				continue;
  1560  			}
  1561  			/*
  1562  			 * hand craft *(&nn + o) = l
  1563  			 */
  1564  			nod0 = znode;
  1565  			nod0.op = OAS;
  1566  			nod0.type = t;
  1567  			nod0.left = &nod1;
  1568  			nod0.right = nil;
  1569  
  1570  			nod1 = znode;
  1571  			nod1.op = OIND;
  1572  			nod1.type = t;
  1573  			nod1.left = &nod2;
  1574  
  1575  			nod2 = znode;
  1576  			nod2.op = OADD;
  1577  			nod2.type = typ(TIND, t);
  1578  			nod2.left = &nod3;
  1579  			nod2.right = &nod4;
  1580  
  1581  			nod3 = znode;
  1582  			nod3.op = OADDR;
  1583  			nod3.type = nod2.type;
  1584  			nod3.left = nn;
  1585  
  1586  			nod4 = znode;
  1587  			nod4.op = OCONST;
  1588  			nod4.type = nod2.type;
  1589  			nod4.vconst = t->offset;
  1590  
  1591  			ccom(&nod0);
  1592  			acom(&nod0);
  1593  			xcom(&nod0);
  1594  			nod0.addable = 0;
  1595  			nod0.right = l;
  1596  
  1597  			// prtree(&nod0, "hand craft");
  1598  			cgen(&nod0, Z);
  1599  		}
  1600  		break;
  1601  
  1602  	case OAS:
  1603  		if(nn == Z) {
  1604  			if(n->addable < INDEXED)
  1605  				sugen(n->right, n->left, w);
  1606  			break;
  1607  		}
  1608  
  1609  		sugen(n->right, nodrat, w);
  1610  		warn(n, "non-interruptable temporary");
  1611  		sugen(nodrat, n->left, w);
  1612  		sugen(nodrat, nn, w);
  1613  		break;
  1614  
  1615  	case OFUNC:
  1616  		if(nn == Z) {
  1617  			sugen(n, nodrat, w);
  1618  			break;
  1619  		}
  1620  		if(nn->op != OIND) {
  1621  			nn = new1(OADDR, nn, Z);
  1622  			nn->type = types[TIND];
  1623  			nn->addable = 0;
  1624  		} else
  1625  			nn = nn->left;
  1626  		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  1627  		n->type = types[TVOID];
  1628  		n->left->type = types[TVOID];
  1629  		cgen(n, Z);
  1630  		break;
  1631  
  1632  	case OCOND:
  1633  		bcgen(n->left, 1);
  1634  		p1 = p;
  1635  		sugen(n->right->left, nn, w);
  1636  		gbranch(OGOTO);
  1637  		patch(p1, pc);
  1638  		p1 = p;
  1639  		sugen(n->right->right, nn, w);
  1640  		patch(p1, pc);
  1641  		break;
  1642  
  1643  	case OCOMMA:
  1644  		cgen(n->left, Z);
  1645  		sugen(n->right, nn, w);
  1646  		break;
  1647  	}
  1648  	return;
  1649  
  1650  copy:
  1651  	if(nn == Z) {
  1652  		switch(n->op) {
  1653  		case OASADD:
  1654  		case OASSUB:
  1655  		case OASAND:
  1656  		case OASOR:
  1657  		case OASXOR:
  1658  
  1659  		case OASMUL:
  1660  		case OASLMUL:
  1661  
  1662  
  1663  		case OASASHL:
  1664  		case OASASHR:
  1665  		case OASLSHR:
  1666  			break;
  1667  
  1668  		case OPOSTINC:
  1669  		case OPOSTDEC:
  1670  		case OPREINC:
  1671  		case OPREDEC:
  1672  			break;
  1673  
  1674  		default:
  1675  			return;
  1676  		}
  1677  	}
  1678  
  1679  	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
  1680  		t = nn->type;
  1681  		nn->type = types[TLONG];
  1682  		regialloc(&nod1, nn, Z);
  1683  		lcgen(nn, &nod1);
  1684  		regsalloc(&nod2, nn);
  1685  		nn->type = t;
  1686  
  1687  		gins(AMOVQ, &nod1, &nod2);
  1688  		regfree(&nod1);
  1689  
  1690  		nod2.type = typ(TIND, t);
  1691  
  1692  		nod1 = nod2;
  1693  		nod1.op = OIND;
  1694  		nod1.left = &nod2;
  1695  		nod1.right = Z;
  1696  		nod1.complex = 1;
  1697  		nod1.type = t;
  1698  
  1699  		sugen(n, &nod1, w);
  1700  		return;
  1701  	}
  1702  
  1703  	if(w <= 32) {
  1704  		c = cursafe;
  1705  		if(n->left != Z && n->left->complex >= FNX
  1706  		&& n->right != Z && n->right->complex >= FNX) {
  1707  			regsalloc(&nod1, n->right);
  1708  			cgen(n->right, &nod1);
  1709  			nod2 = *n;
  1710  			nod2.right = &nod1;
  1711  			cgen(&nod2, nn);
  1712  			cursafe = c;
  1713  			return;
  1714  		}
  1715  		if(w & 7) {
  1716  			mt = TLONG;
  1717  			mo = AMOVL;
  1718  		} else {
  1719  			mt = TVLONG;
  1720  			mo = AMOVQ;
  1721  		}
  1722  		if(n->complex > nn->complex) {
  1723  			t = n->type;
  1724  			n->type = types[mt];
  1725  			regalloc(&nod0, n, Z);
  1726  			if(!vaddr(n, 0)) {
  1727  				reglcgen(&nod1, n, Z);
  1728  				n->type = t;
  1729  				n = &nod1;
  1730  			}
  1731  			else
  1732  				n->type = t;
  1733  
  1734  			t = nn->type;
  1735  			nn->type = types[mt];
  1736  			if(!vaddr(nn, 0)) {
  1737  				reglcgen(&nod2, nn, Z);
  1738  				nn->type = t;
  1739  				nn = &nod2;
  1740  			}
  1741  			else
  1742  				nn->type = t;
  1743  		} else {
  1744  			t = nn->type;
  1745  			nn->type = types[mt];
  1746  			regalloc(&nod0, nn, Z);
  1747  			if(!vaddr(nn, 0)) {
  1748  				reglcgen(&nod2, nn, Z);
  1749  				nn->type = t;
  1750  				nn = &nod2;
  1751  			}
  1752  			else
  1753  				nn->type = t;
  1754  
  1755  			t = n->type;
  1756  			n->type = types[mt];
  1757  			if(!vaddr(n, 0)) {
  1758  				reglcgen(&nod1, n, Z);
  1759  				n->type = t;
  1760  				n = &nod1;
  1761  			}
  1762  			else
  1763  				n->type = t;
  1764  		}
  1765  		o0 = n->xoffset;
  1766  		o1 = nn->xoffset;
  1767  		w /= ewidth[mt];
  1768  		while(--w >= 0) {
  1769  			gins(mo, n, &nod0);
  1770  			gins(mo, &nod0, nn);
  1771  			n->xoffset += ewidth[mt];
  1772  			nn->xoffset += ewidth[mt];
  1773  		}
  1774  		n->xoffset = o0;
  1775  		nn->xoffset = o1;
  1776  		if(nn == &nod2)
  1777  			regfree(&nod2);
  1778  		if(n == &nod1)
  1779  			regfree(&nod1);
  1780  		regfree(&nod0);
  1781  		return;
  1782  	}
  1783  
  1784  	/* botch, need to save in .safe */
  1785  	c = 0;
  1786  	if(n->complex > nn->complex) {
  1787  		t = n->type;
  1788  		n->type = types[TLONG];
  1789  		nodreg(&nod1, n, D_SI);
  1790  		if(reg[D_SI]) {
  1791  			gins(APUSHQ, &nod1, Z);
  1792  			c |= 1;
  1793  			reg[D_SI]++;
  1794  		}
  1795  		lcgen(n, &nod1);
  1796  		n->type = t;
  1797  
  1798  		t = nn->type;
  1799  		nn->type = types[TLONG];
  1800  		nodreg(&nod2, nn, D_DI);
  1801  		if(reg[D_DI]) {
  1802  warn(Z, "DI botch");
  1803  			gins(APUSHQ, &nod2, Z);
  1804  			c |= 2;
  1805  			reg[D_DI]++;
  1806  		}
  1807  		lcgen(nn, &nod2);
  1808  		nn->type = t;
  1809  	} else {
  1810  		t = nn->type;
  1811  		nn->type = types[TLONG];
  1812  		nodreg(&nod2, nn, D_DI);
  1813  		if(reg[D_DI]) {
  1814  warn(Z, "DI botch");
  1815  			gins(APUSHQ, &nod2, Z);
  1816  			c |= 2;
  1817  			reg[D_DI]++;
  1818  		}
  1819  		lcgen(nn, &nod2);
  1820  		nn->type = t;
  1821  
  1822  		t = n->type;
  1823  		n->type = types[TLONG];
  1824  		nodreg(&nod1, n, D_SI);
  1825  		if(reg[D_SI]) {
  1826  			gins(APUSHQ, &nod1, Z);
  1827  			c |= 1;
  1828  			reg[D_SI]++;
  1829  		}
  1830  		lcgen(n, &nod1);
  1831  		n->type = t;
  1832  	}
  1833  	nodreg(&nod3, n, D_CX);
  1834  	if(reg[D_CX]) {
  1835  		gins(APUSHQ, &nod3, Z);
  1836  		c |= 4;
  1837  		reg[D_CX]++;
  1838  	}
  1839  	gins(AMOVL, nodconst(w/SZ_INT), &nod3);
  1840  	gins(ACLD, Z, Z);
  1841  	gins(AREP, Z, Z);
  1842  	gins(AMOVSL, Z, Z);
  1843  	if(c & 4) {
  1844  		gins(APOPQ, Z, &nod3);
  1845  		reg[D_CX]--;
  1846  	}
  1847  	if(c & 2) {
  1848  		gins(APOPQ, Z, &nod2);
  1849  		reg[nod2.reg]--;
  1850  	}
  1851  	if(c & 1) {
  1852  		gins(APOPQ, Z, &nod1);
  1853  		reg[nod1.reg]--;
  1854  	}
  1855  }
  1856  
  1857  /*
  1858   * TO DO
  1859   */
  1860  void
  1861  layout(Node *f, Node *t, int c, int cv, Node *cn)
  1862  {
  1863  	Node t1, t2;
  1864  
  1865  	while(c > 3) {
  1866  		layout(f, t, 2, 0, Z);
  1867  		c -= 2;
  1868  	}
  1869  
  1870  	regalloc(&t1, &lregnode, Z);
  1871  	regalloc(&t2, &lregnode, Z);
  1872  	if(c > 0) {
  1873  		gmove(f, &t1);
  1874  		f->xoffset += SZ_INT;
  1875  	}
  1876  	if(cn != Z)
  1877  		gmove(nodconst(cv), cn);
  1878  	if(c > 1) {
  1879  		gmove(f, &t2);
  1880  		f->xoffset += SZ_INT;
  1881  	}
  1882  	if(c > 0) {
  1883  		gmove(&t1, t);
  1884  		t->xoffset += SZ_INT;
  1885  	}
  1886  	if(c > 2) {
  1887  		gmove(f, &t1);
  1888  		f->xoffset += SZ_INT;
  1889  	}
  1890  	if(c > 1) {
  1891  		gmove(&t2, t);
  1892  		t->xoffset += SZ_INT;
  1893  	}
  1894  	if(c > 2) {
  1895  		gmove(&t1, t);
  1896  		t->xoffset += SZ_INT;
  1897  	}
  1898  	regfree(&t1);
  1899  	regfree(&t2);
  1900  }
  1901  
  1902  /*
  1903   * constant is not vlong or fits as 32-bit signed immediate
  1904   */
  1905  int
  1906  immconst(Node *n)
  1907  {
  1908  	int32 v;
  1909  
  1910  	if(n->op != OCONST || !typechlpv[n->type->etype])
  1911  		return 0;
  1912  	if(typechl[n->type->etype])
  1913  		return 1;
  1914  	v = n->vconst;
  1915  	return n->vconst == (vlong)v;
  1916  }
  1917  
  1918  /*
  1919   * if a constant and vlong, doesn't fit as 32-bit signed immediate
  1920   */
  1921  int
  1922  hardconst(Node *n)
  1923  {
  1924  	return n->op == OCONST && !immconst(n);
  1925  }
  1926  
  1927  /*
  1928   * casting up to t2 covers an intermediate cast to t1
  1929   */
  1930  int
  1931  castup(Type *t1, Type *t2)
  1932  {
  1933  	int ft;
  1934  
  1935  	if(!nilcast(t1, t2))
  1936  		return 0;
  1937  	/* known to be small to large */
  1938  	ft = t1->etype;
  1939  	switch(t2->etype){
  1940  	case TINT:
  1941  	case TLONG:
  1942  		return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
  1943  	case TUINT:
  1944  	case TULONG:
  1945  		return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
  1946  	case TVLONG:
  1947  		return ft == TLONG || ft == TINT || ft == TSHORT;
  1948  	case TUVLONG:
  1949  		return ft == TULONG || ft == TUINT || ft == TUSHORT;
  1950  	}
  1951  	return 0;
  1952  }
  1953  
  1954  void
  1955  zeroregm(Node *n)
  1956  {
  1957  	gins(AMOVL, nodconst(0), n);
  1958  }
  1959  
  1960  /* do we need to load the address of a vlong? */
  1961  int
  1962  vaddr(Node *n, int a)
  1963  {
  1964  	switch(n->op) {
  1965  	case ONAME:
  1966  		if(a)
  1967  			return 1;
  1968  		return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
  1969  
  1970  	case OCONST:
  1971  	case OREGISTER:
  1972  	case OINDREG:
  1973  		return 1;
  1974  	}
  1975  	return 0;
  1976  }
  1977  
  1978  int32
  1979  hi64v(Node *n)
  1980  {
  1981  	if(align(0, types[TCHAR], Aarg1, nil))	/* isbigendian */
  1982  		return (int32)(n->vconst) & ~0L;
  1983  	else
  1984  		return (int32)((uvlong)n->vconst>>32) & ~0L;
  1985  }
  1986  
  1987  int32
  1988  lo64v(Node *n)
  1989  {
  1990  	if(align(0, types[TCHAR], Aarg1, nil))	/* isbigendian */
  1991  		return (int32)((uvlong)n->vconst>>32) & ~0L;
  1992  	else
  1993  		return (int32)(n->vconst) & ~0L;
  1994  }
  1995  
  1996  Node *
  1997  hi64(Node *n)
  1998  {
  1999  	return nodconst(hi64v(n));
  2000  }
  2001  
  2002  Node *
  2003  lo64(Node *n)
  2004  {
  2005  	return nodconst(lo64v(n));
  2006  }
  2007  
  2008  int
  2009  cond(int op)
  2010  {
  2011  	switch(op) {
  2012  	case OANDAND:
  2013  	case OOROR:
  2014  	case ONOT:
  2015  		return 1;
  2016  
  2017  	case OEQ:
  2018  	case ONE:
  2019  	case OLE:
  2020  	case OLT:
  2021  	case OGE:
  2022  	case OGT:
  2023  	case OHI:
  2024  	case OHS:
  2025  	case OLO:
  2026  	case OLS:
  2027  		return 1;
  2028  	}
  2029  	return 0;
  2030  }