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