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

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