github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/6c/cgen.c (about)

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