github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/cmd/5g/cgen64.c (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include <u.h>
     6  #include <libc.h>
     7  #include "gg.h"
     8  
     9  /*
    10   * attempt to generate 64-bit
    11   *	res = n
    12   * return 1 on success, 0 if op not handled.
    13   */
    14  void
    15  cgen64(Node *n, Node *res)
    16  {
    17  	Node t1, t2, *l, *r;
    18  	Node lo1, lo2, hi1, hi2;
    19  	Node al, ah, bl, bh, cl, ch, s, n1, creg;
    20  	Prog *p1, *p2, *p3, *p4, *p5, *p6;
    21  
    22  	uint64 v;
    23  
    24  	if(res->op != OINDREG && res->op != ONAME) {
    25  		dump("n", n);
    26  		dump("res", res);
    27  		fatal("cgen64 %O of %O", n->op, res->op);
    28  	}
    29  
    30  	l = n->left;
    31  	if(!l->addable) {
    32  		tempname(&t1, l->type);
    33  		cgen(l, &t1);
    34  		l = &t1;
    35  	}
    36  
    37  	split64(l, &lo1, &hi1);
    38  	switch(n->op) {
    39  	default:
    40  		fatal("cgen64 %O", n->op);
    41  
    42  	case OMINUS:
    43  		split64(res, &lo2, &hi2);
    44  
    45  		regalloc(&t1, lo1.type, N);
    46  		regalloc(&al, lo1.type, N);
    47  		regalloc(&ah, hi1.type, N);
    48  
    49  		gins(AMOVW, &lo1, &al);
    50  		gins(AMOVW, &hi1, &ah);
    51  
    52  		gmove(ncon(0), &t1);
    53  		p1 = gins(ASUB, &al, &t1);
    54  		p1->scond |= C_SBIT;
    55  		gins(AMOVW, &t1, &lo2);
    56  
    57  		gmove(ncon(0), &t1);
    58  		gins(ASBC, &ah, &t1);
    59  		gins(AMOVW, &t1, &hi2);
    60  
    61  		regfree(&t1);
    62  		regfree(&al);
    63  		regfree(&ah);
    64  		splitclean();
    65  		splitclean();
    66  		return;
    67  
    68  	case OCOM:
    69  		regalloc(&t1, lo1.type, N);
    70  		gmove(ncon(-1), &t1);
    71  
    72  		split64(res, &lo2, &hi2);
    73  		regalloc(&n1, lo1.type, N);
    74  
    75  		gins(AMOVW, &lo1, &n1);
    76  		gins(AEOR, &t1, &n1);
    77  		gins(AMOVW, &n1, &lo2);
    78  
    79  		gins(AMOVW, &hi1, &n1);
    80  		gins(AEOR, &t1, &n1);
    81  		gins(AMOVW, &n1, &hi2);
    82  
    83  		regfree(&t1);
    84  		regfree(&n1);
    85  		splitclean();
    86  		splitclean();
    87  		return;
    88  
    89  	case OADD:
    90  	case OSUB:
    91  	case OMUL:
    92  	case OLSH:
    93  	case ORSH:
    94  	case OAND:
    95  	case OOR:
    96  	case OXOR:
    97  	case OLROT:
    98  		// binary operators.
    99  		// common setup below.
   100  		break;
   101  	}
   102  
   103  	// setup for binary operators
   104  	r = n->right;
   105  	if(r != N && !r->addable) {
   106  		tempname(&t2, r->type);
   107  		cgen(r, &t2);
   108  		r = &t2;
   109  	}
   110  	if(is64(r->type))
   111  		split64(r, &lo2, &hi2);
   112  
   113  	regalloc(&al, lo1.type, N);
   114  	regalloc(&ah, hi1.type, N);
   115  
   116  	// Do op.  Leave result in ah:al.
   117  	switch(n->op) {
   118  	default:
   119  		fatal("cgen64: not implemented: %N\n", n);
   120  
   121  	case OADD:
   122  		// TODO: Constants
   123  		regalloc(&bl, types[TPTR32], N);
   124  		regalloc(&bh, types[TPTR32], N);
   125  		gins(AMOVW, &hi1, &ah);
   126  		gins(AMOVW, &lo1, &al);
   127  		gins(AMOVW, &hi2, &bh);
   128  		gins(AMOVW, &lo2, &bl);
   129  		p1 = gins(AADD, &bl, &al);
   130  		p1->scond |= C_SBIT;
   131  		gins(AADC, &bh, &ah);
   132  		regfree(&bl);
   133  		regfree(&bh);
   134  		break;
   135  
   136  	case OSUB:
   137  		// TODO: Constants.
   138  		regalloc(&bl, types[TPTR32], N);
   139  		regalloc(&bh, types[TPTR32], N);
   140  		gins(AMOVW, &lo1, &al);
   141  		gins(AMOVW, &hi1, &ah);
   142  		gins(AMOVW, &lo2, &bl);
   143  		gins(AMOVW, &hi2, &bh);
   144  		p1 = gins(ASUB, &bl, &al);
   145  		p1->scond |= C_SBIT;
   146  		gins(ASBC, &bh, &ah);
   147  		regfree(&bl);
   148  		regfree(&bh);
   149  		break;
   150  
   151  	case OMUL:
   152  		// TODO(kaib): this can be done with 4 regs and does not need 6
   153  		regalloc(&bl, types[TPTR32], N);
   154  		regalloc(&bh, types[TPTR32], N);
   155  		regalloc(&cl, types[TPTR32], N);
   156  		regalloc(&ch, types[TPTR32], N);
   157  
   158  		// load args into bh:bl and bh:bl.
   159  		gins(AMOVW, &hi1, &bh);
   160  		gins(AMOVW, &lo1, &bl);
   161  		gins(AMOVW, &hi2, &ch);
   162  		gins(AMOVW, &lo2, &cl);
   163  
   164  		// bl * cl -> ah al
   165  		p1 = gins(AMULLU, N, N);
   166  		p1->from.type = D_REG;
   167  		p1->from.reg = bl.val.u.reg;
   168  		p1->reg = cl.val.u.reg;
   169  		p1->to.type = D_REGREG;
   170  		p1->to.reg = ah.val.u.reg;
   171  		p1->to.offset = al.val.u.reg;
   172  //print("%P\n", p1);
   173  
   174  		// bl * ch + ah -> ah
   175  		p1 = gins(AMULA, N, N);
   176  		p1->from.type = D_REG;
   177  		p1->from.reg = bl.val.u.reg;
   178  		p1->reg = ch.val.u.reg;
   179  		p1->to.type = D_REGREG2;
   180  		p1->to.reg = ah.val.u.reg;
   181  		p1->to.offset = ah.val.u.reg;
   182  //print("%P\n", p1);
   183  
   184  		// bh * cl + ah -> ah
   185  		p1 = gins(AMULA, N, N);
   186  		p1->from.type = D_REG;
   187  		p1->from.reg = bh.val.u.reg;
   188  		p1->reg = cl.val.u.reg;
   189  		p1->to.type = D_REGREG2;
   190  		p1->to.reg = ah.val.u.reg;
   191  		p1->to.offset = ah.val.u.reg;
   192  //print("%P\n", p1);
   193  
   194  		regfree(&bh);
   195  		regfree(&bl);
   196  		regfree(&ch);
   197  		regfree(&cl);
   198  
   199  		break;
   200  
   201  	case OLROT:
   202  		// We only rotate by a constant c in [0,64).
   203  		// if c >= 32:
   204  		//	lo, hi = hi, lo
   205  		//	c -= 32
   206  		// if c == 0:
   207  		//	no-op
   208  		// else:
   209  		//	t = hi
   210  		//	shld hi:lo, c
   211  		//	shld lo:t, c
   212  		v = mpgetfix(r->val.u.xval);
   213  		regalloc(&bl, lo1.type, N);
   214  		regalloc(&bh, hi1.type, N);
   215  		if(v >= 32) {
   216  			// reverse during load to do the first 32 bits of rotate
   217  			v -= 32;
   218  			gins(AMOVW, &hi1, &bl);
   219  			gins(AMOVW, &lo1, &bh);
   220  		} else {
   221  			gins(AMOVW, &hi1, &bh);
   222  			gins(AMOVW, &lo1, &bl);
   223  		}
   224  		if(v == 0) {
   225  			gins(AMOVW, &bh, &ah);
   226  			gins(AMOVW, &bl, &al);
   227  		} else {
   228  			// rotate by 1 <= v <= 31
   229  			//	MOVW	bl<<v, al
   230  			//	MOVW	bh<<v, ah
   231  			//	OR		bl>>(32-v), ah
   232  			//	OR		bh>>(32-v), al
   233  			gshift(AMOVW, &bl, SHIFT_LL, v, &al);
   234  			gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
   235  			gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
   236  			gshift(AORR, &bh, SHIFT_LR, 32-v, &al);
   237  		}
   238  		regfree(&bl);
   239  		regfree(&bh);
   240  		break;
   241  
   242  	case OLSH:
   243  		regalloc(&bl, lo1.type, N);
   244  		regalloc(&bh, hi1.type, N);
   245  		gins(AMOVW, &hi1, &bh);
   246  		gins(AMOVW, &lo1, &bl);
   247  
   248  		if(r->op == OLITERAL) {
   249  			v = mpgetfix(r->val.u.xval);
   250  			if(v >= 64) {
   251  				// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
   252  				// here and below (verify it optimizes to EOR)
   253  				gins(AEOR, &al, &al);
   254  				gins(AEOR, &ah, &ah);
   255  			} else
   256  			if(v > 32) {
   257  				gins(AEOR, &al, &al);
   258  				//	MOVW	bl<<(v-32), ah
   259  				gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
   260  			} else
   261  			if(v == 32) {
   262  				gins(AEOR, &al, &al);
   263  				gins(AMOVW, &bl, &ah);
   264  			} else
   265  			if(v > 0) {
   266  				//	MOVW	bl<<v, al
   267  				gshift(AMOVW, &bl, SHIFT_LL, v, &al);
   268  
   269  				//	MOVW	bh<<v, ah
   270  				gshift(AMOVW, &bh, SHIFT_LL, v, &ah);
   271  
   272  				//	OR		bl>>(32-v), ah
   273  				gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
   274  			} else {
   275  				gins(AMOVW, &bl, &al);
   276  				gins(AMOVW, &bh, &ah);
   277  			}
   278  			goto olsh_break;
   279  		}
   280  
   281  		regalloc(&s, types[TUINT32], N);
   282  		regalloc(&creg, types[TUINT32], N);
   283  		if (is64(r->type)) {
   284  			// shift is >= 1<<32
   285  			split64(r, &cl, &ch);
   286  			gmove(&ch, &s);
   287  			gins(ATST, &s, N);
   288  			p6 = gbranch(ABNE, T, 0);
   289  			gmove(&cl, &s);
   290  			splitclean();
   291  		} else {
   292  			gmove(r, &s);
   293  			p6 = P;
   294  		}
   295  		gins(ATST, &s, N);
   296  
   297  		// shift == 0
   298  		p1 = gins(AMOVW, &bl, &al);
   299  		p1->scond = C_SCOND_EQ;
   300  		p1 = gins(AMOVW, &bh, &ah);
   301  		p1->scond = C_SCOND_EQ;
   302  		p2 = gbranch(ABEQ, T, 0);
   303  
   304  		// shift is < 32
   305  		nodconst(&n1, types[TUINT32], 32);
   306  		gmove(&n1, &creg);
   307  		gcmp(ACMP, &s, &creg);
   308  
   309  		//	MOVW.LO		bl<<s, al
   310  		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
   311  		p1->scond = C_SCOND_LO;
   312  
   313  		//	MOVW.LO		bh<<s, ah
   314  		p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
   315  		p1->scond = C_SCOND_LO;
   316  
   317  		//	SUB.LO		s, creg
   318  		p1 = gins(ASUB, &s, &creg);
   319  		p1->scond = C_SCOND_LO;
   320  
   321  		//	OR.LO		bl>>creg, ah
   322  		p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
   323  		p1->scond = C_SCOND_LO;
   324  
   325  		//	BLO	end
   326  		p3 = gbranch(ABLO, T, 0);
   327  
   328  		// shift == 32
   329  		p1 = gins(AEOR, &al, &al);
   330  		p1->scond = C_SCOND_EQ;
   331  		p1 = gins(AMOVW, &bl, &ah);
   332  		p1->scond = C_SCOND_EQ;
   333  		p4 = gbranch(ABEQ, T, 0);
   334  
   335  		// shift is < 64
   336  		nodconst(&n1, types[TUINT32], 64);
   337  		gmove(&n1, &creg);
   338  		gcmp(ACMP, &s, &creg);
   339  
   340  		//	EOR.LO	al, al
   341  		p1 = gins(AEOR, &al, &al);
   342  		p1->scond = C_SCOND_LO;
   343  
   344  		//	MOVW.LO		creg>>1, creg
   345  		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
   346  		p1->scond = C_SCOND_LO;
   347  
   348  		//	SUB.LO		creg, s
   349  		p1 = gins(ASUB, &creg, &s);
   350  		p1->scond = C_SCOND_LO;
   351  
   352  		//	MOVW	bl<<s, ah
   353  		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
   354  		p1->scond = C_SCOND_LO;
   355  
   356  		p5 = gbranch(ABLO, T, 0);
   357  
   358  		// shift >= 64
   359  		if (p6 != P) patch(p6, pc);
   360  		gins(AEOR, &al, &al);
   361  		gins(AEOR, &ah, &ah);
   362  
   363  		patch(p2, pc);
   364  		patch(p3, pc);
   365  		patch(p4, pc);
   366  		patch(p5, pc);
   367  		regfree(&s);
   368  		regfree(&creg);
   369  
   370  olsh_break:
   371  		regfree(&bl);
   372  		regfree(&bh);
   373  		break;
   374  
   375  
   376  	case ORSH:
   377  		regalloc(&bl, lo1.type, N);
   378  		regalloc(&bh, hi1.type, N);
   379  		gins(AMOVW, &hi1, &bh);
   380  		gins(AMOVW, &lo1, &bl);
   381  
   382  		if(r->op == OLITERAL) {
   383  			v = mpgetfix(r->val.u.xval);
   384  			if(v >= 64) {
   385  				if(bh.type->etype == TINT32) {
   386  					//	MOVW	bh->31, al
   387  					gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
   388  
   389  					//	MOVW	bh->31, ah
   390  					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
   391  				} else {
   392  					gins(AEOR, &al, &al);
   393  					gins(AEOR, &ah, &ah);
   394  				}
   395  			} else
   396  			if(v > 32) {
   397  				if(bh.type->etype == TINT32) {
   398  					//	MOVW	bh->(v-32), al
   399  					gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);
   400  
   401  					//	MOVW	bh->31, ah
   402  					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
   403  				} else {
   404  					//	MOVW	bh>>(v-32), al
   405  					gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
   406  					gins(AEOR, &ah, &ah);
   407  				}
   408  			} else
   409  			if(v == 32) {
   410  				gins(AMOVW, &bh, &al);
   411  				if(bh.type->etype == TINT32) {
   412  					//	MOVW	bh->31, ah
   413  					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
   414  				} else {
   415  					gins(AEOR, &ah, &ah);
   416  				}
   417  			} else
   418  			if( v > 0) {
   419  				//	MOVW	bl>>v, al
   420  				gshift(AMOVW, &bl, SHIFT_LR, v, &al);
   421  	
   422  				//	OR		bh<<(32-v), al
   423  				gshift(AORR, &bh, SHIFT_LL, 32-v, &al);
   424  
   425  				if(bh.type->etype == TINT32) {
   426  					//	MOVW	bh->v, ah
   427  					gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
   428  				} else {
   429  					//	MOVW	bh>>v, ah
   430  					gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
   431  				}
   432  			} else {
   433  				gins(AMOVW, &bl, &al);
   434  				gins(AMOVW, &bh, &ah);
   435  			}
   436  			goto orsh_break;
   437  		}
   438  
   439  		regalloc(&s, types[TUINT32], N);
   440  		regalloc(&creg, types[TUINT32], N);
   441  		if(is64(r->type)) {
   442  			// shift is >= 1<<32
   443  			split64(r, &cl, &ch);
   444  			gmove(&ch, &s);
   445  			gins(ATST, &s, N);
   446  			if(bh.type->etype == TINT32)
   447  				p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
   448  			else
   449  				p1 = gins(AEOR, &ah, &ah);
   450  			p1->scond = C_SCOND_NE;
   451  			p6 = gbranch(ABNE, T, 0);
   452  			gmove(&cl, &s);
   453  			splitclean();
   454  		} else {
   455  			gmove(r, &s);
   456  			p6 = P;
   457  		}
   458  		gins(ATST, &s, N);
   459  
   460  		// shift == 0
   461  		p1 = gins(AMOVW, &bl, &al);
   462  		p1->scond = C_SCOND_EQ;
   463  		p1 = gins(AMOVW, &bh, &ah);
   464  		p1->scond = C_SCOND_EQ;
   465  		p2 = gbranch(ABEQ, T, 0);
   466  
   467  		// check if shift is < 32
   468  		nodconst(&n1, types[TUINT32], 32);
   469  		gmove(&n1, &creg);
   470  		gcmp(ACMP, &s, &creg);
   471  
   472  		//	MOVW.LO		bl>>s, al
   473  		p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
   474  		p1->scond = C_SCOND_LO;
   475  
   476  		//	SUB.LO		s,creg
   477  		p1 = gins(ASUB, &s, &creg);
   478  		p1->scond = C_SCOND_LO;
   479  
   480  		//	OR.LO		bh<<(32-s), al
   481  		p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
   482  		p1->scond = C_SCOND_LO;
   483  
   484  		if(bh.type->etype == TINT32) {
   485  			//	MOVW	bh->s, ah
   486  			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
   487  		} else {
   488  			//	MOVW	bh>>s, ah
   489  			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
   490  		}
   491  		p1->scond = C_SCOND_LO;
   492  
   493  		//	BLO	end
   494  		p3 = gbranch(ABLO, T, 0);
   495  
   496  		// shift == 32
   497  		p1 = gins(AMOVW, &bh, &al);
   498  		p1->scond = C_SCOND_EQ;
   499  		if(bh.type->etype == TINT32)
   500  			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
   501  		else
   502  			gins(AEOR, &ah, &ah);
   503  		p4 = gbranch(ABEQ, T, 0);
   504  
   505  		// check if shift is < 64
   506  		nodconst(&n1, types[TUINT32], 64);
   507  		gmove(&n1, &creg);
   508  		gcmp(ACMP, &s, &creg);
   509  
   510  		//	MOVW.LO		creg>>1, creg
   511  		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
   512  		p1->scond = C_SCOND_LO;
   513  
   514  		//	SUB.LO		creg, s
   515  		p1 = gins(ASUB, &creg, &s);
   516  		p1->scond = C_SCOND_LO;
   517  
   518  		if(bh.type->etype == TINT32) {
   519  			//	MOVW	bh->(s-32), al
   520  			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
   521  			p1->scond = C_SCOND_LO;
   522  		} else {
   523  			//	MOVW	bh>>(v-32), al
   524  			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
   525  			p1->scond = C_SCOND_LO;
   526  		}
   527  
   528  		//	BLO	end
   529  		p5 = gbranch(ABLO, T, 0);
   530  
   531  		// s >= 64
   532  		if(p6 != P)
   533  			patch(p6, pc);
   534  		if(bh.type->etype == TINT32) {
   535  			//	MOVW	bh->31, al
   536  			gshift(AMOVW, &bh, SHIFT_AR, 31, &al);
   537  		} else {
   538  			gins(AEOR, &al, &al);
   539  		}
   540  
   541  		patch(p2, pc);
   542  		patch(p3, pc);
   543  		patch(p4, pc);
   544  		patch(p5, pc);
   545  		regfree(&s);
   546  		regfree(&creg);
   547  
   548  
   549  orsh_break:
   550  		regfree(&bl);
   551  		regfree(&bh);
   552  		break;
   553  
   554  	case OXOR:
   555  	case OAND:
   556  	case OOR:
   557  		// TODO(kaib): literal optimizations
   558  		// make constant the right side (it usually is anyway).
   559  //		if(lo1.op == OLITERAL) {
   560  //			nswap(&lo1, &lo2);
   561  //			nswap(&hi1, &hi2);
   562  //		}
   563  //		if(lo2.op == OLITERAL) {
   564  //			// special cases for constants.
   565  //			lv = mpgetfix(lo2.val.u.xval);
   566  //			hv = mpgetfix(hi2.val.u.xval);
   567  //			splitclean();	// right side
   568  //			split64(res, &lo2, &hi2);
   569  //			switch(n->op) {
   570  //			case OXOR:
   571  //				gmove(&lo1, &lo2);
   572  //				gmove(&hi1, &hi2);
   573  //				switch(lv) {
   574  //				case 0:
   575  //					break;
   576  //				case 0xffffffffu:
   577  //					gins(ANOTL, N, &lo2);
   578  //					break;
   579  //				default:
   580  //					gins(AXORL, ncon(lv), &lo2);
   581  //					break;
   582  //				}
   583  //				switch(hv) {
   584  //				case 0:
   585  //					break;
   586  //				case 0xffffffffu:
   587  //					gins(ANOTL, N, &hi2);
   588  //					break;
   589  //				default:
   590  //					gins(AXORL, ncon(hv), &hi2);
   591  //					break;
   592  //				}
   593  //				break;
   594  
   595  //			case OAND:
   596  //				switch(lv) {
   597  //				case 0:
   598  //					gins(AMOVL, ncon(0), &lo2);
   599  //					break;
   600  //				default:
   601  //					gmove(&lo1, &lo2);
   602  //					if(lv != 0xffffffffu)
   603  //						gins(AANDL, ncon(lv), &lo2);
   604  //					break;
   605  //				}
   606  //				switch(hv) {
   607  //				case 0:
   608  //					gins(AMOVL, ncon(0), &hi2);
   609  //					break;
   610  //				default:
   611  //					gmove(&hi1, &hi2);
   612  //					if(hv != 0xffffffffu)
   613  //						gins(AANDL, ncon(hv), &hi2);
   614  //					break;
   615  //				}
   616  //				break;
   617  
   618  //			case OOR:
   619  //				switch(lv) {
   620  //				case 0:
   621  //					gmove(&lo1, &lo2);
   622  //					break;
   623  //				case 0xffffffffu:
   624  //					gins(AMOVL, ncon(0xffffffffu), &lo2);
   625  //					break;
   626  //				default:
   627  //					gmove(&lo1, &lo2);
   628  //					gins(AORL, ncon(lv), &lo2);
   629  //					break;
   630  //				}
   631  //				switch(hv) {
   632  //				case 0:
   633  //					gmove(&hi1, &hi2);
   634  //					break;
   635  //				case 0xffffffffu:
   636  //					gins(AMOVL, ncon(0xffffffffu), &hi2);
   637  //					break;
   638  //				default:
   639  //					gmove(&hi1, &hi2);
   640  //					gins(AORL, ncon(hv), &hi2);
   641  //					break;
   642  //				}
   643  //				break;
   644  //			}
   645  //			splitclean();
   646  //			splitclean();
   647  //			goto out;
   648  //		}
   649  		regalloc(&n1, lo1.type, N);
   650  		gins(AMOVW, &lo1, &al);
   651  		gins(AMOVW, &hi1, &ah);
   652  		gins(AMOVW, &lo2, &n1);
   653  		gins(optoas(n->op, lo1.type), &n1, &al);
   654  		gins(AMOVW, &hi2, &n1);
   655  		gins(optoas(n->op, lo1.type), &n1, &ah);
   656  		regfree(&n1);
   657  		break;
   658  	}
   659  	if(is64(r->type))
   660  		splitclean();
   661  	splitclean();
   662  
   663  	split64(res, &lo1, &hi1);
   664  	gins(AMOVW, &al, &lo1);
   665  	gins(AMOVW, &ah, &hi1);
   666  	splitclean();
   667  
   668  //out:
   669  	regfree(&al);
   670  	regfree(&ah);
   671  }
   672  
   673  /*
   674   * generate comparison of nl, nr, both 64-bit.
   675   * nl is memory; nr is constant or memory.
   676   */
   677  void
   678  cmp64(Node *nl, Node *nr, int op, int likely, Prog *to)
   679  {
   680  	Node lo1, hi1, lo2, hi2, r1, r2;
   681  	Prog *br;
   682  	Type *t;
   683  
   684  	split64(nl, &lo1, &hi1);
   685  	split64(nr, &lo2, &hi2);
   686  
   687  	// compare most significant word;
   688  	// if they differ, we're done.
   689  	t = hi1.type;
   690  	regalloc(&r1, types[TINT32], N);
   691  	regalloc(&r2, types[TINT32], N);
   692  	gins(AMOVW, &hi1, &r1);
   693  	gins(AMOVW, &hi2, &r2);
   694  	gcmp(ACMP, &r1, &r2);
   695  	regfree(&r1);
   696  	regfree(&r2);
   697  
   698  	br = P;
   699  	switch(op) {
   700  	default:
   701  		fatal("cmp64 %O %T", op, t);
   702  	case OEQ:
   703  		// cmp hi
   704  		// bne L
   705  		// cmp lo
   706  		// beq to
   707  		// L:
   708  		br = gbranch(ABNE, T, -likely);
   709  		break;
   710  	case ONE:
   711  		// cmp hi
   712  		// bne to
   713  		// cmp lo
   714  		// bne to
   715  		patch(gbranch(ABNE, T, likely), to);
   716  		break;
   717  	case OGE:
   718  	case OGT:
   719  		// cmp hi
   720  		// bgt to
   721  		// blt L
   722  		// cmp lo
   723  		// bge to (or bgt to)
   724  		// L:
   725  		patch(gbranch(optoas(OGT, t), T, likely), to);
   726  		br = gbranch(optoas(OLT, t), T, -likely);
   727  		break;
   728  	case OLE:
   729  	case OLT:
   730  		// cmp hi
   731  		// blt to
   732  		// bgt L
   733  		// cmp lo
   734  		// ble to (or jlt to)
   735  		// L:
   736  		patch(gbranch(optoas(OLT, t), T, likely), to);
   737  		br = gbranch(optoas(OGT, t), T, -likely);
   738  		break;
   739  	}
   740  
   741  	// compare least significant word
   742  	t = lo1.type;
   743  	regalloc(&r1, types[TINT32], N);
   744  	regalloc(&r2, types[TINT32], N);
   745  	gins(AMOVW, &lo1, &r1);
   746  	gins(AMOVW, &lo2, &r2);
   747  	gcmp(ACMP, &r1, &r2);
   748  	regfree(&r1);
   749  	regfree(&r2);
   750  
   751  	// jump again
   752  	patch(gbranch(optoas(op, t), T, likely), to);
   753  
   754  	// point first branch down here if appropriate
   755  	if(br != P)
   756  		patch(br, pc);
   757  
   758  	splitclean();
   759  	splitclean();
   760  }