github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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 "../../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] && (n->op != OFUNC || nn != Z)) {
    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, 0, 0);
    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, 0, 0);
   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, 0, 0);
   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  		if(l->addable < INDEXED) {
   942  			reglcgen(&nod, l, nn);
   943  			nod.op = OREGISTER;
   944  			gopcode(OFUNC, n->type, Z, &nod);
   945  			regfree(&nod);
   946  		} else
   947  			gopcode(OFUNC, n->type, Z, l);
   948  		if(REGARG >= 0 && reg[REGARG])
   949  			reg[REGARG]--;
   950  		regret(&nod, n, l->type, 1); // update maxarg if nothing else
   951  		if(nn != Z)
   952  			gmove(&nod, nn);
   953  		if(nod.op == OREGISTER)
   954  			regfree(&nod);
   955  		if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype])
   956  			gins(AFMOVDP, &fregnode0, &fregnode0);
   957  		break;
   958  
   959  	case OIND:
   960  		if(nn == Z) {
   961  			nullwarn(l, Z);
   962  			break;
   963  		}
   964  		regialloc(&nod, n, nn);
   965  		r = l;
   966  		while(r->op == OADD)
   967  			r = r->right;
   968  		if(sconst(r)) {
   969  			v = r->vconst;
   970  			r->vconst = 0;
   971  			cgen(l, &nod);
   972  			nod.xoffset += v;
   973  			r->vconst = v;
   974  		} else
   975  			cgen(l, &nod);
   976  		regind(&nod, n);
   977  		gmove(&nod, nn);
   978  		regfree(&nod);
   979  		break;
   980  
   981  	case OEQ:
   982  	case ONE:
   983  	case OLE:
   984  	case OLT:
   985  	case OGE:
   986  	case OGT:
   987  	case OLO:
   988  	case OLS:
   989  	case OHI:
   990  	case OHS:
   991  		if(nn == Z) {
   992  			nullwarn(l, r);
   993  			break;
   994  		}
   995  		boolgen(n, 1, nn);
   996  		break;
   997  
   998  	case OANDAND:
   999  	case OOROR:
  1000  		boolgen(n, 1, nn);
  1001  		if(nn == Z)
  1002  			patch(p, pc);
  1003  		break;
  1004  
  1005  	case ONOT:
  1006  		if(nn == Z) {
  1007  			nullwarn(l, Z);
  1008  			break;
  1009  		}
  1010  		boolgen(n, 1, nn);
  1011  		break;
  1012  
  1013  	case OCOMMA:
  1014  		cgen(l, Z);
  1015  		cgen(r, nn);
  1016  		break;
  1017  
  1018  	case OCAST:
  1019  		if(nn == Z) {
  1020  			nullwarn(l, Z);
  1021  			break;
  1022  		}
  1023  		/*
  1024  		 * convert from types l->n->nn
  1025  		 */
  1026  		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
  1027  			/* both null, gen l->nn */
  1028  			cgen(l, nn);
  1029  			break;
  1030  		}
  1031  		if(typev[l->type->etype]) {
  1032  			cgen64(n, nn);
  1033  			break;
  1034  		}
  1035  		regalloc(&nod, l, nn);
  1036  		cgen(l, &nod);
  1037  		regalloc(&nod1, n, &nod);
  1038  		gmove(&nod, &nod1);
  1039  		gmove(&nod1, nn);
  1040  		regfree(&nod1);
  1041  		regfree(&nod);
  1042  		break;
  1043  
  1044  	case ODOT:
  1045  		sugen(l, nodrat, l->type->width);
  1046  		if(nn == Z)
  1047  			break;
  1048  		warn(n, "non-interruptable temporary");
  1049  		nod = *nodrat;
  1050  		if(!r || r->op != OCONST) {
  1051  			diag(n, "DOT and no offset");
  1052  			break;
  1053  		}
  1054  		nod.xoffset += (int32)r->vconst;
  1055  		nod.type = n->type;
  1056  		cgen(&nod, nn);
  1057  		break;
  1058  
  1059  	case OCOND:
  1060  		bcgen(l, 1);
  1061  		p1 = p;
  1062  		cgen(r->left, nn);
  1063  		gbranch(OGOTO);
  1064  		patch(p1, pc);
  1065  		p1 = p;
  1066  		cgen(r->right, nn);
  1067  		patch(p1, pc);
  1068  		break;
  1069  
  1070  	case OPOSTINC:
  1071  	case OPOSTDEC:
  1072  		v = 1;
  1073  		if(l->type->etype == TIND)
  1074  			v = l->type->link->width;
  1075  		if(o == OPOSTDEC)
  1076  			v = -v;
  1077  		if(l->op == OBIT)
  1078  			goto bitinc;
  1079  		if(nn == Z)
  1080  			goto pre;
  1081  
  1082  		if(hardleft)
  1083  			reglcgen(&nod, l, Z);
  1084  		else
  1085  			nod = *l;
  1086  
  1087  		if(typefd[n->type->etype])
  1088  			goto fltinc;
  1089  		gmove(&nod, nn);
  1090  		gopcode(OADD, n->type, nodconst(v), &nod);
  1091  		if(hardleft)
  1092  			regfree(&nod);
  1093  		break;
  1094  
  1095  	case OPREINC:
  1096  	case OPREDEC:
  1097  		v = 1;
  1098  		if(l->type->etype == TIND)
  1099  			v = l->type->link->width;
  1100  		if(o == OPREDEC)
  1101  			v = -v;
  1102  		if(l->op == OBIT)
  1103  			goto bitinc;
  1104  
  1105  	pre:
  1106  		if(hardleft)
  1107  			reglcgen(&nod, l, Z);
  1108  		else
  1109  			nod = *l;
  1110  		if(typefd[n->type->etype])
  1111  			goto fltinc;
  1112  		gopcode(OADD, n->type, nodconst(v), &nod);
  1113  		if(nn != Z)
  1114  			gmove(&nod, nn);
  1115  		if(hardleft)
  1116  			regfree(&nod);
  1117  		break;
  1118  
  1119  	fltinc:
  1120  		gmove(&nod, &fregnode0);
  1121  		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
  1122  			gins(AFMOVD, &fregnode0, &fregnode0);
  1123  		gins(AFLD1, Z, Z);
  1124  		if(v < 0)
  1125  			fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
  1126  		else
  1127  			fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
  1128  		if(nn != Z && (o == OPREINC || o == OPREDEC))
  1129  			gins(AFMOVD, &fregnode0, &fregnode0);
  1130  		gmove(&fregnode0, &nod);
  1131  		if(hardleft)
  1132  			regfree(&nod);
  1133  		break;
  1134  
  1135  	bitinc:
  1136  		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
  1137  			bitload(l, &nod, &nod1, &nod2, Z);
  1138  			gmove(&nod, nn);
  1139  			gopcode(OADD, tfield, nodconst(v), &nod);
  1140  			bitstore(l, &nod, &nod1, &nod2, Z);
  1141  			break;
  1142  		}
  1143  		bitload(l, &nod, &nod1, &nod2, nn);
  1144  		gopcode(OADD, tfield, nodconst(v), &nod);
  1145  		bitstore(l, &nod, &nod1, &nod2, nn);
  1146  		break;
  1147  	}
  1148  done:
  1149  	cursafe = curs;
  1150  }
  1151  
  1152  void
  1153  reglcgen(Node *t, Node *n, Node *nn)
  1154  {
  1155  	Node *r;
  1156  	int32 v;
  1157  
  1158  	regialloc(t, n, nn);
  1159  	if(n->op == OIND) {
  1160  		r = n->left;
  1161  		while(r->op == OADD)
  1162  			r = r->right;
  1163  		if(sconst(r)) {
  1164  			v = r->vconst;
  1165  			r->vconst = 0;
  1166  			lcgen(n, t);
  1167  			t->xoffset += v;
  1168  			r->vconst = v;
  1169  			regind(t, n);
  1170  			return;
  1171  		}
  1172  	}
  1173  	lcgen(n, t);
  1174  	regind(t, n);
  1175  }
  1176  
  1177  void
  1178  lcgen(Node *n, Node *nn)
  1179  {
  1180  	Prog *p1;
  1181  	Node nod;
  1182  
  1183  	if(debug['g']) {
  1184  		prtree(nn, "lcgen lhs");
  1185  		prtree(n, "lcgen");
  1186  	}
  1187  	if(n == Z || n->type == T)
  1188  		return;
  1189  	if(nn == Z) {
  1190  		nn = &nod;
  1191  		regalloc(&nod, n, Z);
  1192  	}
  1193  	switch(n->op) {
  1194  	default:
  1195  		if(n->addable < INDEXED) {
  1196  			diag(n, "unknown op in lcgen: %O", n->op);
  1197  			break;
  1198  		}
  1199  		gopcode(OADDR, n->type, n, nn);
  1200  		break;
  1201  
  1202  	case OCOMMA:
  1203  		cgen(n->left, n->left);
  1204  		lcgen(n->right, nn);
  1205  		break;
  1206  
  1207  	case OIND:
  1208  		cgen(n->left, nn);
  1209  		break;
  1210  
  1211  	case OCOND:
  1212  		bcgen(n->left, 1);
  1213  		p1 = p;
  1214  		lcgen(n->right->left, nn);
  1215  		gbranch(OGOTO);
  1216  		patch(p1, pc);
  1217  		p1 = p;
  1218  		lcgen(n->right->right, nn);
  1219  		patch(p1, pc);
  1220  		break;
  1221  	}
  1222  }
  1223  
  1224  void
  1225  bcgen(Node *n, int true)
  1226  {
  1227  
  1228  	if(n->type == T)
  1229  		gbranch(OGOTO);
  1230  	else
  1231  		boolgen(n, true, Z);
  1232  }
  1233  
  1234  void
  1235  boolgen(Node *n, int true, Node *nn)
  1236  {
  1237  	int o;
  1238  	Prog *p1, *p2, *p3;
  1239  	Node *l, *r, nod, nod1;
  1240  	int32 curs;
  1241  
  1242  	if(debug['g']) {
  1243  		prtree(nn, "boolgen lhs");
  1244  		prtree(n, "boolgen");
  1245  	}
  1246  	curs = cursafe;
  1247  	l = n->left;
  1248  	r = n->right;
  1249  	switch(n->op) {
  1250  
  1251  	default:
  1252  		if(typev[n->type->etype]) {
  1253  			testv(n, true);
  1254  			goto com;
  1255  		}
  1256  		o = ONE;
  1257  		if(true)
  1258  			o = OEQ;
  1259  		if(typefd[n->type->etype]) {
  1260  			if(n->addable < INDEXED) {
  1261  				cgen(n, &fregnode0);
  1262  				gins(AFLDZ, Z, Z);
  1263  				fgopcode(o, &fregnode0, &fregnode1, 1, 1);
  1264  			} else {
  1265  				gins(AFLDZ, Z, Z);
  1266  				fgopcode(o, n, &fregnode0, 0, 1);
  1267  			}
  1268  			goto com;
  1269  		}
  1270  		/* bad, 13 is address of external that becomes constant */
  1271  		if(n->addable >= INDEXED && n->addable != 13) {
  1272  			gopcode(o, n->type, n, nodconst(0));
  1273  			goto com;
  1274  		}
  1275  		regalloc(&nod, n, nn);
  1276  		cgen(n, &nod);
  1277  		gopcode(o, n->type, &nod, nodconst(0));
  1278  		regfree(&nod);
  1279  		goto com;
  1280  
  1281  	case OCONST:
  1282  		o = vconst(n);
  1283  		if(!true)
  1284  			o = !o;
  1285  		gbranch(OGOTO);
  1286  		if(o) {
  1287  			p1 = p;
  1288  			gbranch(OGOTO);
  1289  			patch(p1, pc);
  1290  		}
  1291  		goto com;
  1292  
  1293  	case OCOMMA:
  1294  		cgen(l, Z);
  1295  		boolgen(r, true, nn);
  1296  		break;
  1297  
  1298  	case ONOT:
  1299  		boolgen(l, !true, nn);
  1300  		break;
  1301  
  1302  	case OCOND:
  1303  		bcgen(l, 1);
  1304  		p1 = p;
  1305  		bcgen(r->left, true);
  1306  		p2 = p;
  1307  		gbranch(OGOTO);
  1308  		patch(p1, pc);
  1309  		p1 = p;
  1310  		bcgen(r->right, !true);
  1311  		patch(p2, pc);
  1312  		p2 = p;
  1313  		gbranch(OGOTO);
  1314  		patch(p1, pc);
  1315  		patch(p2, pc);
  1316  		goto com;
  1317  
  1318  	case OANDAND:
  1319  		if(!true)
  1320  			goto caseor;
  1321  
  1322  	caseand:
  1323  		bcgen(l, true);
  1324  		p1 = p;
  1325  		bcgen(r, !true);
  1326  		p2 = p;
  1327  		patch(p1, pc);
  1328  		gbranch(OGOTO);
  1329  		patch(p2, pc);
  1330  		goto com;
  1331  
  1332  	case OOROR:
  1333  		if(!true)
  1334  			goto caseand;
  1335  
  1336  	caseor:
  1337  		bcgen(l, !true);
  1338  		p1 = p;
  1339  		bcgen(r, !true);
  1340  		p2 = p;
  1341  		gbranch(OGOTO);
  1342  		patch(p1, pc);
  1343  		patch(p2, pc);
  1344  		goto com;
  1345  
  1346  	case OEQ:
  1347  	case ONE:
  1348  	case OLE:
  1349  	case OLT:
  1350  	case OGE:
  1351  	case OGT:
  1352  	case OHI:
  1353  	case OHS:
  1354  	case OLO:
  1355  	case OLS:
  1356  		o = n->op;
  1357  		if(typev[l->type->etype]) {
  1358  			if(!true)
  1359  				n->op = comrel[relindex(o)];
  1360  			cgen64(n, Z);
  1361  			goto com;
  1362  		}
  1363  		if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
  1364  			// Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
  1365  			// Jump around instead.
  1366  			boolgen(n, 0, Z);
  1367  			p1 = p;
  1368  			gbranch(OGOTO);
  1369  			patch(p1, pc);
  1370  			goto com;
  1371  		}
  1372  		if(true)
  1373  			o = comrel[relindex(o)];
  1374  		if(l->complex >= FNX && r->complex >= FNX) {
  1375  			regret(&nod, r, 0, 0);
  1376  			cgen(r, &nod);
  1377  			regsalloc(&nod1, r);
  1378  			gmove(&nod, &nod1);
  1379  			regfree(&nod);
  1380  			nod = *n;
  1381  			nod.right = &nod1;
  1382  			boolgen(&nod, true, nn);
  1383  			break;
  1384  		}
  1385  		if(typefd[l->type->etype]) {
  1386  			if(l->complex >= r->complex) {
  1387  				cgen(l, &fregnode0);
  1388  				if(r->addable < INDEXED) {
  1389  					cgen(r, &fregnode0);
  1390  					o = invrel[relindex(o)];
  1391  					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
  1392  				} else
  1393  					fgopcode(o, r, &fregnode0, 0, 1);
  1394  			} else {
  1395  				o = invrel[relindex(o)];
  1396  				cgen(r, &fregnode0);
  1397  				if(l->addable < INDEXED) {
  1398  					cgen(l, &fregnode0);
  1399  					o = invrel[relindex(o)];
  1400  					fgopcode(o, &fregnode0, &fregnode1, 1, 1);
  1401  				} else
  1402  					fgopcode(o, l, &fregnode0, 0, 1);
  1403  			}
  1404  			switch(o) {
  1405  			case OEQ:
  1406  				// Already emitted AJEQ; want AJEQ and AJPC.
  1407  				p1 = p;
  1408  				gbranch(OGOTO);
  1409  				p2 = p;
  1410  				patch(p1, pc);
  1411  				gins(AJPC, Z, Z);
  1412  				patch(p2, pc);
  1413  				break;
  1414  
  1415  			case ONE:
  1416  				// Already emitted AJNE; want AJNE or AJPS.
  1417  				p1 = p;
  1418  				gins(AJPS, Z, Z);
  1419  				p2 = p;
  1420  				gbranch(OGOTO);
  1421  				p3 = p;
  1422  				patch(p1, pc);
  1423  				patch(p2, pc);
  1424  				gbranch(OGOTO);
  1425  				patch(p3, pc);
  1426  				break;
  1427  			}
  1428  			goto com;
  1429  		}
  1430  		if(l->op == OCONST) {
  1431  			o = invrel[relindex(o)];
  1432  			/* bad, 13 is address of external that becomes constant */
  1433  			if(r->addable < INDEXED || r->addable == 13) {
  1434  				regalloc(&nod, r, nn);
  1435  				cgen(r, &nod);
  1436  				gopcode(o, l->type, &nod, l);
  1437  				regfree(&nod);
  1438  			} else
  1439  				gopcode(o, l->type, r, l);
  1440  			goto com;
  1441  		}
  1442  		if(l->complex >= r->complex) {
  1443  			regalloc(&nod, l, nn);
  1444  			cgen(l, &nod);
  1445  			if(r->addable < INDEXED) {
  1446  				regalloc(&nod1, r, Z);
  1447  				cgen(r, &nod1);
  1448  				gopcode(o, l->type, &nod, &nod1);
  1449  				regfree(&nod1);
  1450  			} else
  1451  				gopcode(o, l->type, &nod, r);
  1452  			regfree(&nod);
  1453  			goto com;
  1454  		}
  1455  		regalloc(&nod, r, nn);
  1456  		cgen(r, &nod);
  1457  		if(l->addable < INDEXED || l->addable == 13) {
  1458  			regalloc(&nod1, l, Z);
  1459  			cgen(l, &nod1);
  1460  			if(typechlp[l->type->etype])
  1461  				gopcode(o, types[TINT], &nod1, &nod);
  1462  			else
  1463  				gopcode(o, l->type, &nod1, &nod);
  1464  			regfree(&nod1);
  1465  		} else
  1466  			gopcode(o, l->type, l, &nod);
  1467  		regfree(&nod);
  1468  
  1469  	com:
  1470  		if(nn != Z) {
  1471  			p1 = p;
  1472  			gmove(nodconst(1L), nn);
  1473  			gbranch(OGOTO);
  1474  			p2 = p;
  1475  			patch(p1, pc);
  1476  			gmove(nodconst(0L), nn);
  1477  			patch(p2, pc);
  1478  		}
  1479  		break;
  1480  	}
  1481  	cursafe = curs;
  1482  }
  1483  
  1484  void
  1485  sugen(Node *n, Node *nn, int32 w)
  1486  {
  1487  	Prog *p1;
  1488  	Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
  1489  	Type *t;
  1490  	int c, v, x;
  1491  
  1492  	if(n == Z || n->type == T)
  1493  		return;
  1494  	if(debug['g']) {
  1495  		prtree(nn, "sugen lhs");
  1496  		prtree(n, "sugen");
  1497  	}
  1498  	if(nn == nodrat)
  1499  		if(w > nrathole)
  1500  			nrathole = w;
  1501  	switch(n->op) {
  1502  	case OIND:
  1503  		if(nn == Z) {
  1504  			nullwarn(n->left, Z);
  1505  			break;
  1506  		}
  1507  
  1508  	default:
  1509  		goto copy;
  1510  
  1511  	case OCONST:
  1512  		if(n->type && typev[n->type->etype]) {
  1513  			if(nn == Z) {
  1514  				nullwarn(n->left, Z);
  1515  				break;
  1516  			}
  1517  
  1518  			if(nn->op == OREGPAIR) {
  1519  				loadpair(n, nn);
  1520  				break;
  1521  			}
  1522  			else if(!vaddr(nn, 0)) {
  1523  				t = nn->type;
  1524  				nn->type = types[TLONG];
  1525  				reglcgen(&nod1, nn, Z);
  1526  				nn->type = t;
  1527  
  1528  				gmove(lo64(n), &nod1);
  1529  				nod1.xoffset += SZ_LONG;
  1530  				gmove(hi64(n), &nod1);
  1531  				regfree(&nod1);
  1532  			}
  1533  			else {
  1534  				gins(AMOVL, lo64(n), nn);
  1535  				nn->xoffset += SZ_LONG;
  1536  				gins(AMOVL, hi64(n), nn);
  1537  				nn->xoffset -= SZ_LONG;
  1538  				break;
  1539  			}
  1540  			break;
  1541  		}
  1542  		goto copy;
  1543  
  1544  	case ODOT:
  1545  		l = n->left;
  1546  		sugen(l, nodrat, l->type->width);
  1547  		if(nn == Z)
  1548  			break;
  1549  		warn(n, "non-interruptable temporary");
  1550  		nod1 = *nodrat;
  1551  		r = n->right;
  1552  		if(!r || r->op != OCONST) {
  1553  			diag(n, "DOT and no offset");
  1554  			break;
  1555  		}
  1556  		nod1.xoffset += (int32)r->vconst;
  1557  		nod1.type = n->type;
  1558  		sugen(&nod1, nn, w);
  1559  		break;
  1560  
  1561  	case OSTRUCT:
  1562  		/*
  1563  		 * rewrite so lhs has no fn call
  1564  		 */
  1565  		if(nn != Z && side(nn)) {
  1566  			nod1 = *n;
  1567  			nod1.type = typ(TIND, n->type);
  1568  			regret(&nod2, &nod1, 0, 0);
  1569  			lcgen(nn, &nod2);
  1570  			regsalloc(&nod0, &nod1);
  1571  			cgen(&nod2, &nod0);
  1572  			regfree(&nod2);
  1573  
  1574  			nod1 = *n;
  1575  			nod1.op = OIND;
  1576  			nod1.left = &nod0;
  1577  			nod1.right = Z;
  1578  			nod1.complex = 1;
  1579  
  1580  			sugen(n, &nod1, w);
  1581  			return;
  1582  		}
  1583  
  1584  		r = n->left;
  1585  		for(t = n->type->link; t != T; t = t->down) {
  1586  			l = r;
  1587  			if(r->op == OLIST) {
  1588  				l = r->left;
  1589  				r = r->right;
  1590  			}
  1591  			if(nn == Z) {
  1592  				cgen(l, nn);
  1593  				continue;
  1594  			}
  1595  			/*
  1596  			 * hand craft *(&nn + o) = l
  1597  			 */
  1598  			nod0 = znode;
  1599  			nod0.op = OAS;
  1600  			nod0.type = t;
  1601  			nod0.left = &nod1;
  1602  			nod0.right = nil;
  1603  
  1604  			nod1 = znode;
  1605  			nod1.op = OIND;
  1606  			nod1.type = t;
  1607  			nod1.left = &nod2;
  1608  
  1609  			nod2 = znode;
  1610  			nod2.op = OADD;
  1611  			nod2.type = typ(TIND, t);
  1612  			nod2.left = &nod3;
  1613  			nod2.right = &nod4;
  1614  
  1615  			nod3 = znode;
  1616  			nod3.op = OADDR;
  1617  			nod3.type = nod2.type;
  1618  			nod3.left = nn;
  1619  
  1620  			nod4 = znode;
  1621  			nod4.op = OCONST;
  1622  			nod4.type = nod2.type;
  1623  			nod4.vconst = t->offset;
  1624  
  1625  			ccom(&nod0);
  1626  			acom(&nod0);
  1627  			xcom(&nod0);
  1628  			nod0.addable = 0;
  1629  			nod0.right = l;
  1630  
  1631  			// prtree(&nod0, "hand craft");
  1632  			cgen(&nod0, Z);
  1633  		}
  1634  		break;
  1635  
  1636  	case OAS:
  1637  		if(nn == Z) {
  1638  			if(n->addable < INDEXED)
  1639  				sugen(n->right, n->left, w);
  1640  			break;
  1641  		}
  1642  
  1643  		sugen(n->right, nodrat, w);
  1644  		warn(n, "non-interruptable temporary");
  1645  		sugen(nodrat, n->left, w);
  1646  		sugen(nodrat, nn, w);
  1647  		break;
  1648  
  1649  	case OFUNC:
  1650  		if(!hasdotdotdot(n->left->type)) {
  1651  			cgen(n, Z);
  1652  			if(nn != Z) {
  1653  				curarg -= n->type->width;
  1654  				regret(&nod1, n, n->left->type, 1);
  1655  				if(nn->complex >= FNX) {
  1656  					regsalloc(&nod2, n);
  1657  					cgen(&nod1, &nod2);
  1658  					nod1 = nod2;
  1659  				}
  1660  				cgen(&nod1, nn);
  1661  			}
  1662  			break;
  1663  		}
  1664  		if(nn == Z) {
  1665  			sugen(n, nodrat, w);
  1666  			break;
  1667  		}
  1668  		h = nn;
  1669  		if(nn->op == OREGPAIR) {
  1670  			regsalloc(&nod1, nn);
  1671  			nn = &nod1;
  1672  		}
  1673  		if(nn->op != OIND) {
  1674  			nn = new1(OADDR, nn, Z);
  1675  			nn->type = types[TIND];
  1676  			nn->addable = 0;
  1677  		} else
  1678  			nn = nn->left;
  1679  		n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  1680  		n->type = types[TVOID];
  1681  		n->left->type = types[TVOID];
  1682  		cgen(n, Z);
  1683  		if(h->op == OREGPAIR)
  1684  			loadpair(nn->left, h);
  1685  		break;
  1686  
  1687  	case OCOND:
  1688  		bcgen(n->left, 1);
  1689  		p1 = p;
  1690  		sugen(n->right->left, nn, w);
  1691  		gbranch(OGOTO);
  1692  		patch(p1, pc);
  1693  		p1 = p;
  1694  		sugen(n->right->right, nn, w);
  1695  		patch(p1, pc);
  1696  		break;
  1697  
  1698  	case OCOMMA:
  1699  		cgen(n->left, Z);
  1700  		sugen(n->right, nn, w);
  1701  		break;
  1702  	}
  1703  	return;
  1704  
  1705  copy:
  1706  	if(nn == Z) {
  1707  		switch(n->op) {
  1708  		case OASADD:
  1709  		case OASSUB:
  1710  		case OASAND:
  1711  		case OASOR:
  1712  		case OASXOR:
  1713  
  1714  		case OASMUL:
  1715  		case OASLMUL:
  1716  
  1717  
  1718  		case OASASHL:
  1719  		case OASASHR:
  1720  		case OASLSHR:
  1721  			break;
  1722  
  1723  		case OPOSTINC:
  1724  		case OPOSTDEC:
  1725  		case OPREINC:
  1726  		case OPREDEC:
  1727  			break;
  1728  
  1729  		default:
  1730  			return;
  1731  		}
  1732  	}
  1733  
  1734  	v = w == 8;
  1735  	if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
  1736  		t = nn->type;
  1737  		nn->type = types[TLONG];
  1738  		regialloc(&nod1, nn, Z);
  1739  		lcgen(nn, &nod1);
  1740  		regsalloc(&nod2, nn);
  1741  		nn->type = t;
  1742  
  1743  		gins(AMOVL, &nod1, &nod2);
  1744  		regfree(&nod1);
  1745  
  1746  		nod2.type = typ(TIND, t);
  1747  
  1748  		nod1 = nod2;
  1749  		nod1.op = OIND;
  1750  		nod1.left = &nod2;
  1751  		nod1.right = Z;
  1752  		nod1.complex = 1;
  1753  		nod1.type = t;
  1754  
  1755  		sugen(n, &nod1, w);
  1756  		return;
  1757  	}
  1758  
  1759  	x = 0;
  1760  	if(v) {
  1761  		if(nn != nil && nn->complex >= FNX) {
  1762  			t = nn->type;
  1763  			nn->type = types[TLONG];
  1764  			regialloc(&nod2, nn, Z);
  1765  			lcgen(nn, &nod2);
  1766  			nn->type = t;
  1767  			
  1768  			nod2.type = typ(TIND, t);
  1769  	
  1770  			nod1 = nod2;
  1771  			nod1.op = OIND;
  1772  			nod1.left = &nod2;
  1773  			nod1.right = Z;
  1774  			nod1.complex = 1;
  1775  			nod1.type = t;
  1776  	
  1777  			sugen(n, &nod1, w);
  1778  			regfree(&nod2);
  1779  			return;
  1780  		}
  1781  			
  1782  		c = cursafe;
  1783  		if(n->left != Z && n->left->complex >= FNX
  1784  		&& n->right != Z && n->right->complex >= FNX) {
  1785  //			warn(n, "toughie");
  1786  			regsalloc(&nod1, n->right);
  1787  			cgen(n->right, &nod1);
  1788  			nod2 = *n;
  1789  			nod2.right = &nod1;
  1790  			cgen(&nod2, nn);
  1791  			cursafe = c;
  1792  			return;
  1793  		}
  1794  		if(cgen64(n, nn)) {
  1795  			cursafe = c;
  1796  			return;
  1797  		}
  1798  		if(n->op == OCOM) {
  1799  			n = n->left;
  1800  			x = 1;
  1801  		}
  1802  	}
  1803  
  1804  	/* botch, need to save in .safe */
  1805  	c = 0;
  1806  	if(n->complex > nn->complex) {
  1807  		t = n->type;
  1808  		n->type = types[TLONG];
  1809  		if(v) {
  1810  			regalloc(&nod0, n, Z);
  1811  			if(!vaddr(n, 0)) {
  1812  				reglcgen(&nod1, n, Z);
  1813  				n->type = t;
  1814  				n = &nod1;
  1815  			}
  1816  			else
  1817  				n->type = t;
  1818  		}
  1819  		else {
  1820  			nodreg(&nod1, n, D_SI);
  1821  			if(reg[D_SI]) {
  1822  				gins(APUSHL, &nod1, Z);
  1823  				c |= 1;
  1824  				reg[D_SI]++;
  1825  			}
  1826  			lcgen(n, &nod1);
  1827  			n->type = t;
  1828  		}
  1829  
  1830  		t = nn->type;
  1831  		nn->type = types[TLONG];
  1832  		if(v) {
  1833  			if(!vaddr(nn, 0)) {
  1834  				reglcgen(&nod2, nn, Z);
  1835  				nn->type = t;
  1836  				nn = &nod2;
  1837  			}
  1838  			else
  1839  				nn->type = t;
  1840  		}
  1841  		else {
  1842  			nodreg(&nod2, nn, D_DI);
  1843  			if(reg[D_DI]) {
  1844  				gins(APUSHL, &nod2, Z);
  1845  				c |= 2;
  1846  				reg[D_DI]++;
  1847  			}
  1848  			lcgen(nn, &nod2);
  1849  			nn->type = t;
  1850  		}
  1851  	} else {
  1852  		t = nn->type;
  1853  		nn->type = types[TLONG];
  1854  		if(v) {
  1855  			regalloc(&nod0, nn, Z);
  1856  			if(!vaddr(nn, 0)) {
  1857  				reglcgen(&nod2, nn, Z);
  1858  				nn->type = t;
  1859  				nn = &nod2;
  1860  			}
  1861  			else
  1862  				nn->type = t;
  1863  		}
  1864  		else {
  1865  			nodreg(&nod2, nn, D_DI);
  1866  			if(reg[D_DI]) {
  1867  				gins(APUSHL, &nod2, Z);
  1868  				c |= 2;
  1869  				reg[D_DI]++;
  1870  			}
  1871  			lcgen(nn, &nod2);
  1872  			nn->type = t;
  1873  		}
  1874  
  1875  		t = n->type;
  1876  		n->type = types[TLONG];
  1877  		if(v) {
  1878  			if(!vaddr(n, 0)) {
  1879  				reglcgen(&nod1, n, Z);
  1880  				n->type = t;
  1881  				n = &nod1;
  1882  			}
  1883  			else
  1884  				n->type = t;
  1885  		}
  1886  		else {
  1887  			nodreg(&nod1, n, D_SI);
  1888  			if(reg[D_SI]) {
  1889  				gins(APUSHL, &nod1, Z);
  1890  				c |= 1;
  1891  				reg[D_SI]++;
  1892  			}
  1893  			lcgen(n, &nod1);
  1894  			n->type = t;
  1895  		}
  1896  	}
  1897  	if(v) {
  1898  		gins(AMOVL, n, &nod0);
  1899  		if(x)
  1900  			gins(ANOTL, Z, &nod0);
  1901  		gins(AMOVL, &nod0, nn);
  1902  		n->xoffset += SZ_LONG;
  1903  		nn->xoffset += SZ_LONG;
  1904  		gins(AMOVL, n, &nod0);
  1905  		if(x)
  1906  			gins(ANOTL, Z, &nod0);
  1907  		gins(AMOVL, &nod0, nn);
  1908  		n->xoffset -= SZ_LONG;
  1909  		nn->xoffset -= SZ_LONG;
  1910  		if(nn == &nod2)
  1911  			regfree(&nod2);
  1912  		if(n == &nod1)
  1913  			regfree(&nod1);
  1914  		regfree(&nod0);
  1915  		return;
  1916  	}
  1917  	nodreg(&nod3, n, D_CX);
  1918  	if(reg[D_CX]) {
  1919  		gins(APUSHL, &nod3, Z);
  1920  		c |= 4;
  1921  		reg[D_CX]++;
  1922  	}
  1923  	gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
  1924  	gins(ACLD, Z, Z);
  1925  	gins(AREP, Z, Z);
  1926  	gins(AMOVSL, Z, Z);
  1927  	if(c & 4) {
  1928  		gins(APOPL, Z, &nod3);
  1929  		reg[D_CX]--;
  1930  	}
  1931  	if(c & 2) {
  1932  		gins(APOPL, Z, &nod2);
  1933  		reg[nod2.reg]--;
  1934  	}
  1935  	if(c & 1) {
  1936  		gins(APOPL, Z, &nod1);
  1937  		reg[nod1.reg]--;
  1938  	}
  1939  }