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