github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/cmd/compile/internal/amd64/gsubr.go (about)

     1  // Derived from Inferno utils/6c/txt.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.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  package amd64
    32  
    33  import (
    34  	"cmd/compile/internal/big"
    35  	"cmd/compile/internal/gc"
    36  	"cmd/internal/obj"
    37  	"cmd/internal/obj/x86"
    38  	"fmt"
    39  )
    40  
    41  var resvd = []int{
    42  	x86.REG_DI, // for movstring
    43  	x86.REG_SI, // for movstring
    44  
    45  	x86.REG_AX, // for divide
    46  	x86.REG_CX, // for shift
    47  	x86.REG_DX, // for divide
    48  	x86.REG_SP, // for stack
    49  }
    50  
    51  /*
    52   * generate
    53   *	as $c, reg
    54   */
    55  func gconreg(as int, c int64, reg int) {
    56  	var nr gc.Node
    57  
    58  	switch as {
    59  	case x86.AADDL,
    60  		x86.AMOVL,
    61  		x86.ALEAL:
    62  		gc.Nodreg(&nr, gc.Types[gc.TINT32], reg)
    63  
    64  	default:
    65  		gc.Nodreg(&nr, gc.Types[gc.TINT64], reg)
    66  	}
    67  
    68  	ginscon(as, c, &nr)
    69  }
    70  
    71  /*
    72   * generate
    73   *	as $c, n
    74   */
    75  func ginscon(as int, c int64, n2 *gc.Node) {
    76  	var n1 gc.Node
    77  
    78  	switch as {
    79  	case x86.AADDL,
    80  		x86.AMOVL,
    81  		x86.ALEAL:
    82  		gc.Nodconst(&n1, gc.Types[gc.TINT32], c)
    83  
    84  	default:
    85  		gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    86  	}
    87  
    88  	if as != x86.AMOVQ && (c < -(1<<31) || c >= 1<<31) {
    89  		// cannot have 64-bit immediate in ADD, etc.
    90  		// instead, MOV into register first.
    91  		var ntmp gc.Node
    92  		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    93  
    94  		gins(x86.AMOVQ, &n1, &ntmp)
    95  		gins(as, &ntmp, n2)
    96  		gc.Regfree(&ntmp)
    97  		return
    98  	}
    99  
   100  	gins(as, &n1, n2)
   101  }
   102  
   103  func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
   104  	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
   105  		// Reverse comparison to place constant last.
   106  		op = gc.Brrev(op)
   107  		n1, n2 = n2, n1
   108  	}
   109  	// General case.
   110  	var r1, r2, g1, g2 gc.Node
   111  	if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
   112  		r1 = *n1
   113  	} else {
   114  		gc.Regalloc(&r1, t, n1)
   115  		gc.Regalloc(&g1, n1.Type, &r1)
   116  		gc.Cgen(n1, &g1)
   117  		gmove(&g1, &r1)
   118  	}
   119  	if n2.Op == gc.OLITERAL && gc.Isint[t.Etype] && gc.Smallintconst(n2) {
   120  		r2 = *n2
   121  	} else {
   122  		gc.Regalloc(&r2, t, n2)
   123  		gc.Regalloc(&g2, n1.Type, &r2)
   124  		gc.Cgen(n2, &g2)
   125  		gmove(&g2, &r2)
   126  	}
   127  	gins(optoas(gc.OCMP, t), &r1, &r2)
   128  	if r1.Op == gc.OREGISTER {
   129  		gc.Regfree(&g1)
   130  		gc.Regfree(&r1)
   131  	}
   132  	if r2.Op == gc.OREGISTER {
   133  		gc.Regfree(&g2)
   134  		gc.Regfree(&r2)
   135  	}
   136  	return gc.Gbranch(optoas(op, t), nil, likely)
   137  }
   138  
   139  func ginsboolval(a int, n *gc.Node) {
   140  	gins(jmptoset(a), nil, n)
   141  }
   142  
   143  // set up nodes representing 2^63
   144  var (
   145  	bigi         gc.Node
   146  	bigf         gc.Node
   147  	bignodes_did bool
   148  )
   149  
   150  func bignodes() {
   151  	if bignodes_did {
   152  		return
   153  	}
   154  	bignodes_did = true
   155  
   156  	var i big.Int
   157  	i.SetInt64(1)
   158  	i.Lsh(&i, 63)
   159  
   160  	gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
   161  	bigi.SetBigInt(&i)
   162  
   163  	bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
   164  }
   165  
   166  /*
   167   * generate move:
   168   *	t = f
   169   * hard part is conversions.
   170   */
   171  func gmove(f *gc.Node, t *gc.Node) {
   172  	if gc.Debug['M'] != 0 {
   173  		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
   174  	}
   175  
   176  	ft := gc.Simsimtype(f.Type)
   177  	tt := gc.Simsimtype(t.Type)
   178  	cvt := t.Type
   179  
   180  	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
   181  		gc.Complexmove(f, t)
   182  		return
   183  	}
   184  
   185  	// cannot have two memory operands
   186  	var a int
   187  	if gc.Ismem(f) && gc.Ismem(t) {
   188  		goto hard
   189  	}
   190  
   191  	// convert constant to desired type
   192  	if f.Op == gc.OLITERAL {
   193  		var con gc.Node
   194  		f.Convconst(&con, t.Type)
   195  		f = &con
   196  		ft = tt // so big switch will choose a simple mov
   197  
   198  		// some constants can't move directly to memory.
   199  		if gc.Ismem(t) {
   200  			// float constants come from memory.
   201  			if gc.Isfloat[tt] {
   202  				goto hard
   203  			}
   204  
   205  			// 64-bit immediates are really 32-bit sign-extended
   206  			// unless moving into a register.
   207  			if gc.Isint[tt] {
   208  				if i := con.Int(); int64(int32(i)) != i {
   209  					goto hard
   210  				}
   211  			}
   212  		}
   213  	}
   214  
   215  	// value -> value copy, only one memory operand.
   216  	// figure out the instruction to use.
   217  	// break out of switch for one-instruction gins.
   218  	// goto rdst for "destination must be register".
   219  	// goto hard for "convert to cvt type first".
   220  	// otherwise handle and return.
   221  
   222  	switch uint32(ft)<<16 | uint32(tt) {
   223  	default:
   224  		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
   225  
   226  		/*
   227  		 * integer copy and truncate
   228  		 */
   229  	case gc.TINT8<<16 | gc.TINT8, // same size
   230  		gc.TINT8<<16 | gc.TUINT8,
   231  		gc.TUINT8<<16 | gc.TINT8,
   232  		gc.TUINT8<<16 | gc.TUINT8,
   233  		gc.TINT16<<16 | gc.TINT8,
   234  		// truncate
   235  		gc.TUINT16<<16 | gc.TINT8,
   236  		gc.TINT32<<16 | gc.TINT8,
   237  		gc.TUINT32<<16 | gc.TINT8,
   238  		gc.TINT64<<16 | gc.TINT8,
   239  		gc.TUINT64<<16 | gc.TINT8,
   240  		gc.TINT16<<16 | gc.TUINT8,
   241  		gc.TUINT16<<16 | gc.TUINT8,
   242  		gc.TINT32<<16 | gc.TUINT8,
   243  		gc.TUINT32<<16 | gc.TUINT8,
   244  		gc.TINT64<<16 | gc.TUINT8,
   245  		gc.TUINT64<<16 | gc.TUINT8:
   246  		a = x86.AMOVB
   247  
   248  	case gc.TINT16<<16 | gc.TINT16, // same size
   249  		gc.TINT16<<16 | gc.TUINT16,
   250  		gc.TUINT16<<16 | gc.TINT16,
   251  		gc.TUINT16<<16 | gc.TUINT16,
   252  		gc.TINT32<<16 | gc.TINT16,
   253  		// truncate
   254  		gc.TUINT32<<16 | gc.TINT16,
   255  		gc.TINT64<<16 | gc.TINT16,
   256  		gc.TUINT64<<16 | gc.TINT16,
   257  		gc.TINT32<<16 | gc.TUINT16,
   258  		gc.TUINT32<<16 | gc.TUINT16,
   259  		gc.TINT64<<16 | gc.TUINT16,
   260  		gc.TUINT64<<16 | gc.TUINT16:
   261  		a = x86.AMOVW
   262  
   263  	case gc.TINT32<<16 | gc.TINT32, // same size
   264  		gc.TINT32<<16 | gc.TUINT32,
   265  		gc.TUINT32<<16 | gc.TINT32,
   266  		gc.TUINT32<<16 | gc.TUINT32:
   267  		a = x86.AMOVL
   268  
   269  	case gc.TINT64<<16 | gc.TINT32, // truncate
   270  		gc.TUINT64<<16 | gc.TINT32,
   271  		gc.TINT64<<16 | gc.TUINT32,
   272  		gc.TUINT64<<16 | gc.TUINT32:
   273  		a = x86.AMOVQL
   274  
   275  	case gc.TINT64<<16 | gc.TINT64, // same size
   276  		gc.TINT64<<16 | gc.TUINT64,
   277  		gc.TUINT64<<16 | gc.TINT64,
   278  		gc.TUINT64<<16 | gc.TUINT64:
   279  		a = x86.AMOVQ
   280  
   281  		/*
   282  		 * integer up-conversions
   283  		 */
   284  	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
   285  		gc.TINT8<<16 | gc.TUINT16:
   286  		a = x86.AMOVBWSX
   287  
   288  		goto rdst
   289  
   290  	case gc.TINT8<<16 | gc.TINT32,
   291  		gc.TINT8<<16 | gc.TUINT32:
   292  		a = x86.AMOVBLSX
   293  		goto rdst
   294  
   295  	case gc.TINT8<<16 | gc.TINT64,
   296  		gc.TINT8<<16 | gc.TUINT64:
   297  		a = x86.AMOVBQSX
   298  		goto rdst
   299  
   300  	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
   301  		gc.TUINT8<<16 | gc.TUINT16:
   302  		a = x86.AMOVBWZX
   303  
   304  		goto rdst
   305  
   306  	case gc.TUINT8<<16 | gc.TINT32,
   307  		gc.TUINT8<<16 | gc.TUINT32:
   308  		a = x86.AMOVBLZX
   309  		goto rdst
   310  
   311  	case gc.TUINT8<<16 | gc.TINT64,
   312  		gc.TUINT8<<16 | gc.TUINT64:
   313  		a = x86.AMOVBQZX
   314  		goto rdst
   315  
   316  	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
   317  		gc.TINT16<<16 | gc.TUINT32:
   318  		a = x86.AMOVWLSX
   319  
   320  		goto rdst
   321  
   322  	case gc.TINT16<<16 | gc.TINT64,
   323  		gc.TINT16<<16 | gc.TUINT64:
   324  		a = x86.AMOVWQSX
   325  		goto rdst
   326  
   327  	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
   328  		gc.TUINT16<<16 | gc.TUINT32:
   329  		a = x86.AMOVWLZX
   330  
   331  		goto rdst
   332  
   333  	case gc.TUINT16<<16 | gc.TINT64,
   334  		gc.TUINT16<<16 | gc.TUINT64:
   335  		a = x86.AMOVWQZX
   336  		goto rdst
   337  
   338  	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
   339  		gc.TINT32<<16 | gc.TUINT64:
   340  		a = x86.AMOVLQSX
   341  
   342  		goto rdst
   343  
   344  		// AMOVL into a register zeros the top of the register,
   345  	// so this is not always necessary, but if we rely on AMOVL
   346  	// the optimizer is almost certain to screw with us.
   347  	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
   348  		gc.TUINT32<<16 | gc.TUINT64:
   349  		a = x86.AMOVLQZX
   350  
   351  		goto rdst
   352  
   353  		/*
   354  		* float to integer
   355  		 */
   356  	case gc.TFLOAT32<<16 | gc.TINT32:
   357  		a = x86.ACVTTSS2SL
   358  
   359  		goto rdst
   360  
   361  	case gc.TFLOAT64<<16 | gc.TINT32:
   362  		a = x86.ACVTTSD2SL
   363  		goto rdst
   364  
   365  	case gc.TFLOAT32<<16 | gc.TINT64:
   366  		a = x86.ACVTTSS2SQ
   367  		goto rdst
   368  
   369  	case gc.TFLOAT64<<16 | gc.TINT64:
   370  		a = x86.ACVTTSD2SQ
   371  		goto rdst
   372  
   373  		// convert via int32.
   374  	case gc.TFLOAT32<<16 | gc.TINT16,
   375  		gc.TFLOAT32<<16 | gc.TINT8,
   376  		gc.TFLOAT32<<16 | gc.TUINT16,
   377  		gc.TFLOAT32<<16 | gc.TUINT8,
   378  		gc.TFLOAT64<<16 | gc.TINT16,
   379  		gc.TFLOAT64<<16 | gc.TINT8,
   380  		gc.TFLOAT64<<16 | gc.TUINT16,
   381  		gc.TFLOAT64<<16 | gc.TUINT8:
   382  		cvt = gc.Types[gc.TINT32]
   383  
   384  		goto hard
   385  
   386  		// convert via int64.
   387  	case gc.TFLOAT32<<16 | gc.TUINT32,
   388  		gc.TFLOAT64<<16 | gc.TUINT32:
   389  		cvt = gc.Types[gc.TINT64]
   390  
   391  		goto hard
   392  
   393  		// algorithm is:
   394  	//	if small enough, use native float64 -> int64 conversion.
   395  	//	otherwise, subtract 2^63, convert, and add it back.
   396  	case gc.TFLOAT32<<16 | gc.TUINT64,
   397  		gc.TFLOAT64<<16 | gc.TUINT64:
   398  		a := x86.ACVTTSS2SQ
   399  
   400  		if ft == gc.TFLOAT64 {
   401  			a = x86.ACVTTSD2SQ
   402  		}
   403  		bignodes()
   404  		var r1 gc.Node
   405  		gc.Regalloc(&r1, gc.Types[ft], nil)
   406  		var r2 gc.Node
   407  		gc.Regalloc(&r2, gc.Types[tt], t)
   408  		var r3 gc.Node
   409  		gc.Regalloc(&r3, gc.Types[ft], nil)
   410  		var r4 gc.Node
   411  		gc.Regalloc(&r4, gc.Types[tt], nil)
   412  		gins(optoas(gc.OAS, f.Type), f, &r1)
   413  		gins(optoas(gc.OCMP, f.Type), &bigf, &r1)
   414  		p1 := gc.Gbranch(optoas(gc.OLE, f.Type), nil, +1)
   415  		gins(a, &r1, &r2)
   416  		p2 := gc.Gbranch(obj.AJMP, nil, 0)
   417  		gc.Patch(p1, gc.Pc)
   418  		gins(optoas(gc.OAS, f.Type), &bigf, &r3)
   419  		gins(optoas(gc.OSUB, f.Type), &r3, &r1)
   420  		gins(a, &r1, &r2)
   421  		gins(x86.AMOVQ, &bigi, &r4)
   422  		gins(x86.AXORQ, &r4, &r2)
   423  		gc.Patch(p2, gc.Pc)
   424  		gmove(&r2, t)
   425  		gc.Regfree(&r4)
   426  		gc.Regfree(&r3)
   427  		gc.Regfree(&r2)
   428  		gc.Regfree(&r1)
   429  		return
   430  
   431  		/*
   432  		 * integer to float
   433  		 */
   434  	case gc.TINT32<<16 | gc.TFLOAT32:
   435  		a = x86.ACVTSL2SS
   436  
   437  		goto rdst
   438  
   439  	case gc.TINT32<<16 | gc.TFLOAT64:
   440  		a = x86.ACVTSL2SD
   441  		goto rdst
   442  
   443  	case gc.TINT64<<16 | gc.TFLOAT32:
   444  		a = x86.ACVTSQ2SS
   445  		goto rdst
   446  
   447  	case gc.TINT64<<16 | gc.TFLOAT64:
   448  		a = x86.ACVTSQ2SD
   449  		goto rdst
   450  
   451  		// convert via int32
   452  	case gc.TINT16<<16 | gc.TFLOAT32,
   453  		gc.TINT16<<16 | gc.TFLOAT64,
   454  		gc.TINT8<<16 | gc.TFLOAT32,
   455  		gc.TINT8<<16 | gc.TFLOAT64,
   456  		gc.TUINT16<<16 | gc.TFLOAT32,
   457  		gc.TUINT16<<16 | gc.TFLOAT64,
   458  		gc.TUINT8<<16 | gc.TFLOAT32,
   459  		gc.TUINT8<<16 | gc.TFLOAT64:
   460  		cvt = gc.Types[gc.TINT32]
   461  
   462  		goto hard
   463  
   464  		// convert via int64.
   465  	case gc.TUINT32<<16 | gc.TFLOAT32,
   466  		gc.TUINT32<<16 | gc.TFLOAT64:
   467  		cvt = gc.Types[gc.TINT64]
   468  
   469  		goto hard
   470  
   471  		// algorithm is:
   472  	//	if small enough, use native int64 -> uint64 conversion.
   473  	//	otherwise, halve (rounding to odd?), convert, and double.
   474  	case gc.TUINT64<<16 | gc.TFLOAT32,
   475  		gc.TUINT64<<16 | gc.TFLOAT64:
   476  		a := x86.ACVTSQ2SS
   477  
   478  		if tt == gc.TFLOAT64 {
   479  			a = x86.ACVTSQ2SD
   480  		}
   481  		var zero gc.Node
   482  		gc.Nodconst(&zero, gc.Types[gc.TUINT64], 0)
   483  		var one gc.Node
   484  		gc.Nodconst(&one, gc.Types[gc.TUINT64], 1)
   485  		var r1 gc.Node
   486  		gc.Regalloc(&r1, f.Type, f)
   487  		var r2 gc.Node
   488  		gc.Regalloc(&r2, t.Type, t)
   489  		var r3 gc.Node
   490  		gc.Regalloc(&r3, f.Type, nil)
   491  		var r4 gc.Node
   492  		gc.Regalloc(&r4, f.Type, nil)
   493  		gmove(f, &r1)
   494  		gins(x86.ACMPQ, &r1, &zero)
   495  		p1 := gc.Gbranch(x86.AJLT, nil, +1)
   496  		gins(a, &r1, &r2)
   497  		p2 := gc.Gbranch(obj.AJMP, nil, 0)
   498  		gc.Patch(p1, gc.Pc)
   499  		gmove(&r1, &r3)
   500  		gins(x86.ASHRQ, &one, &r3)
   501  		gmove(&r1, &r4)
   502  		gins(x86.AANDL, &one, &r4)
   503  		gins(x86.AORQ, &r4, &r3)
   504  		gins(a, &r3, &r2)
   505  		gins(optoas(gc.OADD, t.Type), &r2, &r2)
   506  		gc.Patch(p2, gc.Pc)
   507  		gmove(&r2, t)
   508  		gc.Regfree(&r4)
   509  		gc.Regfree(&r3)
   510  		gc.Regfree(&r2)
   511  		gc.Regfree(&r1)
   512  		return
   513  
   514  		/*
   515  		 * float to float
   516  		 */
   517  	case gc.TFLOAT32<<16 | gc.TFLOAT32:
   518  		a = x86.AMOVSS
   519  
   520  	case gc.TFLOAT64<<16 | gc.TFLOAT64:
   521  		a = x86.AMOVSD
   522  
   523  	case gc.TFLOAT32<<16 | gc.TFLOAT64:
   524  		a = x86.ACVTSS2SD
   525  		goto rdst
   526  
   527  	case gc.TFLOAT64<<16 | gc.TFLOAT32:
   528  		a = x86.ACVTSD2SS
   529  		goto rdst
   530  	}
   531  
   532  	gins(a, f, t)
   533  	return
   534  
   535  	// requires register destination
   536  rdst:
   537  	{
   538  		var r1 gc.Node
   539  		gc.Regalloc(&r1, t.Type, t)
   540  
   541  		gins(a, f, &r1)
   542  		gmove(&r1, t)
   543  		gc.Regfree(&r1)
   544  		return
   545  	}
   546  
   547  	// requires register intermediate
   548  hard:
   549  	var r1 gc.Node
   550  	gc.Regalloc(&r1, cvt, t)
   551  
   552  	gmove(f, &r1)
   553  	gmove(&r1, t)
   554  	gc.Regfree(&r1)
   555  	return
   556  }
   557  
   558  func samaddr(f *gc.Node, t *gc.Node) bool {
   559  	if f.Op != t.Op {
   560  		return false
   561  	}
   562  
   563  	switch f.Op {
   564  	case gc.OREGISTER:
   565  		if f.Reg != t.Reg {
   566  			break
   567  		}
   568  		return true
   569  	}
   570  
   571  	return false
   572  }
   573  
   574  /*
   575   * generate one instruction:
   576   *	as f, t
   577   */
   578  func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
   579  	//	Node nod;
   580  
   581  	//	if(f != N && f->op == OINDEX) {
   582  	//		gc.Regalloc(&nod, &regnode, Z);
   583  	//		v = constnode.vconst;
   584  	//		gc.Cgen(f->right, &nod);
   585  	//		constnode.vconst = v;
   586  	//		idx.reg = nod.reg;
   587  	//		gc.Regfree(&nod);
   588  	//	}
   589  	//	if(t != N && t->op == OINDEX) {
   590  	//		gc.Regalloc(&nod, &regnode, Z);
   591  	//		v = constnode.vconst;
   592  	//		gc.Cgen(t->right, &nod);
   593  	//		constnode.vconst = v;
   594  	//		idx.reg = nod.reg;
   595  	//		gc.Regfree(&nod);
   596  	//	}
   597  
   598  	if f != nil && f.Op == gc.OADDR && (as == x86.AMOVL || as == x86.AMOVQ) {
   599  		// Turn MOVL $xxx into LEAL xxx.
   600  		// These should be equivalent but most of the backend
   601  		// only expects to see LEAL, because that's what we had
   602  		// historically generated. Various hidden assumptions are baked in by now.
   603  		if as == x86.AMOVL {
   604  			as = x86.ALEAL
   605  		} else {
   606  			as = x86.ALEAQ
   607  		}
   608  		f = f.Left
   609  	}
   610  
   611  	switch as {
   612  	case x86.AMOVB,
   613  		x86.AMOVW,
   614  		x86.AMOVL,
   615  		x86.AMOVQ,
   616  		x86.AMOVSS,
   617  		x86.AMOVSD:
   618  		if f != nil && t != nil && samaddr(f, t) {
   619  			return nil
   620  		}
   621  
   622  	case x86.ALEAQ:
   623  		if f != nil && gc.Isconst(f, gc.CTNIL) {
   624  			gc.Fatal("gins LEAQ nil %v", f.Type)
   625  		}
   626  	}
   627  
   628  	p := gc.Prog(as)
   629  	gc.Naddr(&p.From, f)
   630  	gc.Naddr(&p.To, t)
   631  
   632  	if gc.Debug['g'] != 0 {
   633  		fmt.Printf("%v\n", p)
   634  	}
   635  
   636  	w := int32(0)
   637  	switch as {
   638  	case x86.AMOVB:
   639  		w = 1
   640  
   641  	case x86.AMOVW:
   642  		w = 2
   643  
   644  	case x86.AMOVL:
   645  		w = 4
   646  
   647  	case x86.AMOVQ:
   648  		w = 8
   649  	}
   650  
   651  	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Width > int64(w))) {
   652  		gc.Dump("f", f)
   653  		gc.Dump("t", t)
   654  		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
   655  	}
   656  
   657  	if p.To.Type == obj.TYPE_ADDR && w > 0 {
   658  		gc.Fatal("bad use of addr: %v", p)
   659  	}
   660  
   661  	return p
   662  }
   663  
   664  func ginsnop() {
   665  	// This is actually not the x86 NOP anymore,
   666  	// but at the point where it gets used, AX is dead
   667  	// so it's okay if we lose the high bits.
   668  	var reg gc.Node
   669  	gc.Nodreg(&reg, gc.Types[gc.TINT], x86.REG_AX)
   670  	gins(x86.AXCHGL, &reg, &reg)
   671  }
   672  
   673  /*
   674   * return Axxx for Oxxx on type t.
   675   */
   676  func optoas(op int, t *gc.Type) int {
   677  	if t == nil {
   678  		gc.Fatal("optoas: t is nil")
   679  	}
   680  
   681  	a := obj.AXXX
   682  	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
   683  	default:
   684  		gc.Fatal("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
   685  
   686  	case gc.OADDR<<16 | gc.TPTR32:
   687  		a = x86.ALEAL
   688  
   689  	case gc.OADDR<<16 | gc.TPTR64:
   690  		a = x86.ALEAQ
   691  
   692  	case gc.OEQ<<16 | gc.TBOOL,
   693  		gc.OEQ<<16 | gc.TINT8,
   694  		gc.OEQ<<16 | gc.TUINT8,
   695  		gc.OEQ<<16 | gc.TINT16,
   696  		gc.OEQ<<16 | gc.TUINT16,
   697  		gc.OEQ<<16 | gc.TINT32,
   698  		gc.OEQ<<16 | gc.TUINT32,
   699  		gc.OEQ<<16 | gc.TINT64,
   700  		gc.OEQ<<16 | gc.TUINT64,
   701  		gc.OEQ<<16 | gc.TPTR32,
   702  		gc.OEQ<<16 | gc.TPTR64,
   703  		gc.OEQ<<16 | gc.TFLOAT32,
   704  		gc.OEQ<<16 | gc.TFLOAT64:
   705  		a = x86.AJEQ
   706  
   707  	case gc.ONE<<16 | gc.TBOOL,
   708  		gc.ONE<<16 | gc.TINT8,
   709  		gc.ONE<<16 | gc.TUINT8,
   710  		gc.ONE<<16 | gc.TINT16,
   711  		gc.ONE<<16 | gc.TUINT16,
   712  		gc.ONE<<16 | gc.TINT32,
   713  		gc.ONE<<16 | gc.TUINT32,
   714  		gc.ONE<<16 | gc.TINT64,
   715  		gc.ONE<<16 | gc.TUINT64,
   716  		gc.ONE<<16 | gc.TPTR32,
   717  		gc.ONE<<16 | gc.TPTR64,
   718  		gc.ONE<<16 | gc.TFLOAT32,
   719  		gc.ONE<<16 | gc.TFLOAT64:
   720  		a = x86.AJNE
   721  
   722  	case gc.OPS<<16 | gc.TBOOL,
   723  		gc.OPS<<16 | gc.TINT8,
   724  		gc.OPS<<16 | gc.TUINT8,
   725  		gc.OPS<<16 | gc.TINT16,
   726  		gc.OPS<<16 | gc.TUINT16,
   727  		gc.OPS<<16 | gc.TINT32,
   728  		gc.OPS<<16 | gc.TUINT32,
   729  		gc.OPS<<16 | gc.TINT64,
   730  		gc.OPS<<16 | gc.TUINT64,
   731  		gc.OPS<<16 | gc.TPTR32,
   732  		gc.OPS<<16 | gc.TPTR64,
   733  		gc.OPS<<16 | gc.TFLOAT32,
   734  		gc.OPS<<16 | gc.TFLOAT64:
   735  		a = x86.AJPS
   736  
   737  	case gc.OPC<<16 | gc.TBOOL,
   738  		gc.OPC<<16 | gc.TINT8,
   739  		gc.OPC<<16 | gc.TUINT8,
   740  		gc.OPC<<16 | gc.TINT16,
   741  		gc.OPC<<16 | gc.TUINT16,
   742  		gc.OPC<<16 | gc.TINT32,
   743  		gc.OPC<<16 | gc.TUINT32,
   744  		gc.OPC<<16 | gc.TINT64,
   745  		gc.OPC<<16 | gc.TUINT64,
   746  		gc.OPC<<16 | gc.TPTR32,
   747  		gc.OPC<<16 | gc.TPTR64,
   748  		gc.OPC<<16 | gc.TFLOAT32,
   749  		gc.OPC<<16 | gc.TFLOAT64:
   750  		a = x86.AJPC
   751  
   752  	case gc.OLT<<16 | gc.TINT8,
   753  		gc.OLT<<16 | gc.TINT16,
   754  		gc.OLT<<16 | gc.TINT32,
   755  		gc.OLT<<16 | gc.TINT64:
   756  		a = x86.AJLT
   757  
   758  	case gc.OLT<<16 | gc.TUINT8,
   759  		gc.OLT<<16 | gc.TUINT16,
   760  		gc.OLT<<16 | gc.TUINT32,
   761  		gc.OLT<<16 | gc.TUINT64:
   762  		a = x86.AJCS
   763  
   764  	case gc.OLE<<16 | gc.TINT8,
   765  		gc.OLE<<16 | gc.TINT16,
   766  		gc.OLE<<16 | gc.TINT32,
   767  		gc.OLE<<16 | gc.TINT64:
   768  		a = x86.AJLE
   769  
   770  	case gc.OLE<<16 | gc.TUINT8,
   771  		gc.OLE<<16 | gc.TUINT16,
   772  		gc.OLE<<16 | gc.TUINT32,
   773  		gc.OLE<<16 | gc.TUINT64:
   774  		a = x86.AJLS
   775  
   776  	case gc.OGT<<16 | gc.TINT8,
   777  		gc.OGT<<16 | gc.TINT16,
   778  		gc.OGT<<16 | gc.TINT32,
   779  		gc.OGT<<16 | gc.TINT64:
   780  		a = x86.AJGT
   781  
   782  	case gc.OGT<<16 | gc.TUINT8,
   783  		gc.OGT<<16 | gc.TUINT16,
   784  		gc.OGT<<16 | gc.TUINT32,
   785  		gc.OGT<<16 | gc.TUINT64,
   786  		gc.OLT<<16 | gc.TFLOAT32,
   787  		gc.OLT<<16 | gc.TFLOAT64:
   788  		a = x86.AJHI
   789  
   790  	case gc.OGE<<16 | gc.TINT8,
   791  		gc.OGE<<16 | gc.TINT16,
   792  		gc.OGE<<16 | gc.TINT32,
   793  		gc.OGE<<16 | gc.TINT64:
   794  		a = x86.AJGE
   795  
   796  	case gc.OGE<<16 | gc.TUINT8,
   797  		gc.OGE<<16 | gc.TUINT16,
   798  		gc.OGE<<16 | gc.TUINT32,
   799  		gc.OGE<<16 | gc.TUINT64,
   800  		gc.OLE<<16 | gc.TFLOAT32,
   801  		gc.OLE<<16 | gc.TFLOAT64:
   802  		a = x86.AJCC
   803  
   804  	case gc.OCMP<<16 | gc.TBOOL,
   805  		gc.OCMP<<16 | gc.TINT8,
   806  		gc.OCMP<<16 | gc.TUINT8:
   807  		a = x86.ACMPB
   808  
   809  	case gc.OCMP<<16 | gc.TINT16,
   810  		gc.OCMP<<16 | gc.TUINT16:
   811  		a = x86.ACMPW
   812  
   813  	case gc.OCMP<<16 | gc.TINT32,
   814  		gc.OCMP<<16 | gc.TUINT32,
   815  		gc.OCMP<<16 | gc.TPTR32:
   816  		a = x86.ACMPL
   817  
   818  	case gc.OCMP<<16 | gc.TINT64,
   819  		gc.OCMP<<16 | gc.TUINT64,
   820  		gc.OCMP<<16 | gc.TPTR64:
   821  		a = x86.ACMPQ
   822  
   823  	case gc.OCMP<<16 | gc.TFLOAT32:
   824  		a = x86.AUCOMISS
   825  
   826  	case gc.OCMP<<16 | gc.TFLOAT64:
   827  		a = x86.AUCOMISD
   828  
   829  	case gc.OAS<<16 | gc.TBOOL,
   830  		gc.OAS<<16 | gc.TINT8,
   831  		gc.OAS<<16 | gc.TUINT8:
   832  		a = x86.AMOVB
   833  
   834  	case gc.OAS<<16 | gc.TINT16,
   835  		gc.OAS<<16 | gc.TUINT16:
   836  		a = x86.AMOVW
   837  
   838  	case gc.OAS<<16 | gc.TINT32,
   839  		gc.OAS<<16 | gc.TUINT32,
   840  		gc.OAS<<16 | gc.TPTR32:
   841  		a = x86.AMOVL
   842  
   843  	case gc.OAS<<16 | gc.TINT64,
   844  		gc.OAS<<16 | gc.TUINT64,
   845  		gc.OAS<<16 | gc.TPTR64:
   846  		a = x86.AMOVQ
   847  
   848  	case gc.OAS<<16 | gc.TFLOAT32:
   849  		a = x86.AMOVSS
   850  
   851  	case gc.OAS<<16 | gc.TFLOAT64:
   852  		a = x86.AMOVSD
   853  
   854  	case gc.OADD<<16 | gc.TINT8,
   855  		gc.OADD<<16 | gc.TUINT8:
   856  		a = x86.AADDB
   857  
   858  	case gc.OADD<<16 | gc.TINT16,
   859  		gc.OADD<<16 | gc.TUINT16:
   860  		a = x86.AADDW
   861  
   862  	case gc.OADD<<16 | gc.TINT32,
   863  		gc.OADD<<16 | gc.TUINT32,
   864  		gc.OADD<<16 | gc.TPTR32:
   865  		a = x86.AADDL
   866  
   867  	case gc.OADD<<16 | gc.TINT64,
   868  		gc.OADD<<16 | gc.TUINT64,
   869  		gc.OADD<<16 | gc.TPTR64:
   870  		a = x86.AADDQ
   871  
   872  	case gc.OADD<<16 | gc.TFLOAT32:
   873  		a = x86.AADDSS
   874  
   875  	case gc.OADD<<16 | gc.TFLOAT64:
   876  		a = x86.AADDSD
   877  
   878  	case gc.OSUB<<16 | gc.TINT8,
   879  		gc.OSUB<<16 | gc.TUINT8:
   880  		a = x86.ASUBB
   881  
   882  	case gc.OSUB<<16 | gc.TINT16,
   883  		gc.OSUB<<16 | gc.TUINT16:
   884  		a = x86.ASUBW
   885  
   886  	case gc.OSUB<<16 | gc.TINT32,
   887  		gc.OSUB<<16 | gc.TUINT32,
   888  		gc.OSUB<<16 | gc.TPTR32:
   889  		a = x86.ASUBL
   890  
   891  	case gc.OSUB<<16 | gc.TINT64,
   892  		gc.OSUB<<16 | gc.TUINT64,
   893  		gc.OSUB<<16 | gc.TPTR64:
   894  		a = x86.ASUBQ
   895  
   896  	case gc.OSUB<<16 | gc.TFLOAT32:
   897  		a = x86.ASUBSS
   898  
   899  	case gc.OSUB<<16 | gc.TFLOAT64:
   900  		a = x86.ASUBSD
   901  
   902  	case gc.OINC<<16 | gc.TINT8,
   903  		gc.OINC<<16 | gc.TUINT8:
   904  		a = x86.AINCB
   905  
   906  	case gc.OINC<<16 | gc.TINT16,
   907  		gc.OINC<<16 | gc.TUINT16:
   908  		a = x86.AINCW
   909  
   910  	case gc.OINC<<16 | gc.TINT32,
   911  		gc.OINC<<16 | gc.TUINT32,
   912  		gc.OINC<<16 | gc.TPTR32:
   913  		a = x86.AINCL
   914  
   915  	case gc.OINC<<16 | gc.TINT64,
   916  		gc.OINC<<16 | gc.TUINT64,
   917  		gc.OINC<<16 | gc.TPTR64:
   918  		a = x86.AINCQ
   919  
   920  	case gc.ODEC<<16 | gc.TINT8,
   921  		gc.ODEC<<16 | gc.TUINT8:
   922  		a = x86.ADECB
   923  
   924  	case gc.ODEC<<16 | gc.TINT16,
   925  		gc.ODEC<<16 | gc.TUINT16:
   926  		a = x86.ADECW
   927  
   928  	case gc.ODEC<<16 | gc.TINT32,
   929  		gc.ODEC<<16 | gc.TUINT32,
   930  		gc.ODEC<<16 | gc.TPTR32:
   931  		a = x86.ADECL
   932  
   933  	case gc.ODEC<<16 | gc.TINT64,
   934  		gc.ODEC<<16 | gc.TUINT64,
   935  		gc.ODEC<<16 | gc.TPTR64:
   936  		a = x86.ADECQ
   937  
   938  	case gc.OMINUS<<16 | gc.TINT8,
   939  		gc.OMINUS<<16 | gc.TUINT8:
   940  		a = x86.ANEGB
   941  
   942  	case gc.OMINUS<<16 | gc.TINT16,
   943  		gc.OMINUS<<16 | gc.TUINT16:
   944  		a = x86.ANEGW
   945  
   946  	case gc.OMINUS<<16 | gc.TINT32,
   947  		gc.OMINUS<<16 | gc.TUINT32,
   948  		gc.OMINUS<<16 | gc.TPTR32:
   949  		a = x86.ANEGL
   950  
   951  	case gc.OMINUS<<16 | gc.TINT64,
   952  		gc.OMINUS<<16 | gc.TUINT64,
   953  		gc.OMINUS<<16 | gc.TPTR64:
   954  		a = x86.ANEGQ
   955  
   956  	case gc.OAND<<16 | gc.TBOOL,
   957  		gc.OAND<<16 | gc.TINT8,
   958  		gc.OAND<<16 | gc.TUINT8:
   959  		a = x86.AANDB
   960  
   961  	case gc.OAND<<16 | gc.TINT16,
   962  		gc.OAND<<16 | gc.TUINT16:
   963  		a = x86.AANDW
   964  
   965  	case gc.OAND<<16 | gc.TINT32,
   966  		gc.OAND<<16 | gc.TUINT32,
   967  		gc.OAND<<16 | gc.TPTR32:
   968  		a = x86.AANDL
   969  
   970  	case gc.OAND<<16 | gc.TINT64,
   971  		gc.OAND<<16 | gc.TUINT64,
   972  		gc.OAND<<16 | gc.TPTR64:
   973  		a = x86.AANDQ
   974  
   975  	case gc.OOR<<16 | gc.TBOOL,
   976  		gc.OOR<<16 | gc.TINT8,
   977  		gc.OOR<<16 | gc.TUINT8:
   978  		a = x86.AORB
   979  
   980  	case gc.OOR<<16 | gc.TINT16,
   981  		gc.OOR<<16 | gc.TUINT16:
   982  		a = x86.AORW
   983  
   984  	case gc.OOR<<16 | gc.TINT32,
   985  		gc.OOR<<16 | gc.TUINT32,
   986  		gc.OOR<<16 | gc.TPTR32:
   987  		a = x86.AORL
   988  
   989  	case gc.OOR<<16 | gc.TINT64,
   990  		gc.OOR<<16 | gc.TUINT64,
   991  		gc.OOR<<16 | gc.TPTR64:
   992  		a = x86.AORQ
   993  
   994  	case gc.OXOR<<16 | gc.TINT8,
   995  		gc.OXOR<<16 | gc.TUINT8:
   996  		a = x86.AXORB
   997  
   998  	case gc.OXOR<<16 | gc.TINT16,
   999  		gc.OXOR<<16 | gc.TUINT16:
  1000  		a = x86.AXORW
  1001  
  1002  	case gc.OXOR<<16 | gc.TINT32,
  1003  		gc.OXOR<<16 | gc.TUINT32,
  1004  		gc.OXOR<<16 | gc.TPTR32:
  1005  		a = x86.AXORL
  1006  
  1007  	case gc.OXOR<<16 | gc.TINT64,
  1008  		gc.OXOR<<16 | gc.TUINT64,
  1009  		gc.OXOR<<16 | gc.TPTR64:
  1010  		a = x86.AXORQ
  1011  
  1012  	case gc.OLROT<<16 | gc.TINT8,
  1013  		gc.OLROT<<16 | gc.TUINT8:
  1014  		a = x86.AROLB
  1015  
  1016  	case gc.OLROT<<16 | gc.TINT16,
  1017  		gc.OLROT<<16 | gc.TUINT16:
  1018  		a = x86.AROLW
  1019  
  1020  	case gc.OLROT<<16 | gc.TINT32,
  1021  		gc.OLROT<<16 | gc.TUINT32,
  1022  		gc.OLROT<<16 | gc.TPTR32:
  1023  		a = x86.AROLL
  1024  
  1025  	case gc.OLROT<<16 | gc.TINT64,
  1026  		gc.OLROT<<16 | gc.TUINT64,
  1027  		gc.OLROT<<16 | gc.TPTR64:
  1028  		a = x86.AROLQ
  1029  
  1030  	case gc.OLSH<<16 | gc.TINT8,
  1031  		gc.OLSH<<16 | gc.TUINT8:
  1032  		a = x86.ASHLB
  1033  
  1034  	case gc.OLSH<<16 | gc.TINT16,
  1035  		gc.OLSH<<16 | gc.TUINT16:
  1036  		a = x86.ASHLW
  1037  
  1038  	case gc.OLSH<<16 | gc.TINT32,
  1039  		gc.OLSH<<16 | gc.TUINT32,
  1040  		gc.OLSH<<16 | gc.TPTR32:
  1041  		a = x86.ASHLL
  1042  
  1043  	case gc.OLSH<<16 | gc.TINT64,
  1044  		gc.OLSH<<16 | gc.TUINT64,
  1045  		gc.OLSH<<16 | gc.TPTR64:
  1046  		a = x86.ASHLQ
  1047  
  1048  	case gc.ORSH<<16 | gc.TUINT8:
  1049  		a = x86.ASHRB
  1050  
  1051  	case gc.ORSH<<16 | gc.TUINT16:
  1052  		a = x86.ASHRW
  1053  
  1054  	case gc.ORSH<<16 | gc.TUINT32,
  1055  		gc.ORSH<<16 | gc.TPTR32:
  1056  		a = x86.ASHRL
  1057  
  1058  	case gc.ORSH<<16 | gc.TUINT64,
  1059  		gc.ORSH<<16 | gc.TPTR64:
  1060  		a = x86.ASHRQ
  1061  
  1062  	case gc.ORSH<<16 | gc.TINT8:
  1063  		a = x86.ASARB
  1064  
  1065  	case gc.ORSH<<16 | gc.TINT16:
  1066  		a = x86.ASARW
  1067  
  1068  	case gc.ORSH<<16 | gc.TINT32:
  1069  		a = x86.ASARL
  1070  
  1071  	case gc.ORSH<<16 | gc.TINT64:
  1072  		a = x86.ASARQ
  1073  
  1074  	case gc.ORROTC<<16 | gc.TINT8,
  1075  		gc.ORROTC<<16 | gc.TUINT8:
  1076  		a = x86.ARCRB
  1077  
  1078  	case gc.ORROTC<<16 | gc.TINT16,
  1079  		gc.ORROTC<<16 | gc.TUINT16:
  1080  		a = x86.ARCRW
  1081  
  1082  	case gc.ORROTC<<16 | gc.TINT32,
  1083  		gc.ORROTC<<16 | gc.TUINT32:
  1084  		a = x86.ARCRL
  1085  
  1086  	case gc.ORROTC<<16 | gc.TINT64,
  1087  		gc.ORROTC<<16 | gc.TUINT64:
  1088  		a = x86.ARCRQ
  1089  
  1090  	case gc.OHMUL<<16 | gc.TINT8,
  1091  		gc.OMUL<<16 | gc.TINT8,
  1092  		gc.OMUL<<16 | gc.TUINT8:
  1093  		a = x86.AIMULB
  1094  
  1095  	case gc.OHMUL<<16 | gc.TINT16,
  1096  		gc.OMUL<<16 | gc.TINT16,
  1097  		gc.OMUL<<16 | gc.TUINT16:
  1098  		a = x86.AIMULW
  1099  
  1100  	case gc.OHMUL<<16 | gc.TINT32,
  1101  		gc.OMUL<<16 | gc.TINT32,
  1102  		gc.OMUL<<16 | gc.TUINT32,
  1103  		gc.OMUL<<16 | gc.TPTR32:
  1104  		a = x86.AIMULL
  1105  
  1106  	case gc.OHMUL<<16 | gc.TINT64,
  1107  		gc.OMUL<<16 | gc.TINT64,
  1108  		gc.OMUL<<16 | gc.TUINT64,
  1109  		gc.OMUL<<16 | gc.TPTR64:
  1110  		a = x86.AIMULQ
  1111  
  1112  	case gc.OHMUL<<16 | gc.TUINT8:
  1113  		a = x86.AMULB
  1114  
  1115  	case gc.OHMUL<<16 | gc.TUINT16:
  1116  		a = x86.AMULW
  1117  
  1118  	case gc.OHMUL<<16 | gc.TUINT32,
  1119  		gc.OHMUL<<16 | gc.TPTR32:
  1120  		a = x86.AMULL
  1121  
  1122  	case gc.OHMUL<<16 | gc.TUINT64,
  1123  		gc.OHMUL<<16 | gc.TPTR64:
  1124  		a = x86.AMULQ
  1125  
  1126  	case gc.OMUL<<16 | gc.TFLOAT32:
  1127  		a = x86.AMULSS
  1128  
  1129  	case gc.OMUL<<16 | gc.TFLOAT64:
  1130  		a = x86.AMULSD
  1131  
  1132  	case gc.ODIV<<16 | gc.TINT8,
  1133  		gc.OMOD<<16 | gc.TINT8:
  1134  		a = x86.AIDIVB
  1135  
  1136  	case gc.ODIV<<16 | gc.TUINT8,
  1137  		gc.OMOD<<16 | gc.TUINT8:
  1138  		a = x86.ADIVB
  1139  
  1140  	case gc.ODIV<<16 | gc.TINT16,
  1141  		gc.OMOD<<16 | gc.TINT16:
  1142  		a = x86.AIDIVW
  1143  
  1144  	case gc.ODIV<<16 | gc.TUINT16,
  1145  		gc.OMOD<<16 | gc.TUINT16:
  1146  		a = x86.ADIVW
  1147  
  1148  	case gc.ODIV<<16 | gc.TINT32,
  1149  		gc.OMOD<<16 | gc.TINT32:
  1150  		a = x86.AIDIVL
  1151  
  1152  	case gc.ODIV<<16 | gc.TUINT32,
  1153  		gc.ODIV<<16 | gc.TPTR32,
  1154  		gc.OMOD<<16 | gc.TUINT32,
  1155  		gc.OMOD<<16 | gc.TPTR32:
  1156  		a = x86.ADIVL
  1157  
  1158  	case gc.ODIV<<16 | gc.TINT64,
  1159  		gc.OMOD<<16 | gc.TINT64:
  1160  		a = x86.AIDIVQ
  1161  
  1162  	case gc.ODIV<<16 | gc.TUINT64,
  1163  		gc.ODIV<<16 | gc.TPTR64,
  1164  		gc.OMOD<<16 | gc.TUINT64,
  1165  		gc.OMOD<<16 | gc.TPTR64:
  1166  		a = x86.ADIVQ
  1167  
  1168  	case gc.OEXTEND<<16 | gc.TINT16:
  1169  		a = x86.ACWD
  1170  
  1171  	case gc.OEXTEND<<16 | gc.TINT32:
  1172  		a = x86.ACDQ
  1173  
  1174  	case gc.OEXTEND<<16 | gc.TINT64:
  1175  		a = x86.ACQO
  1176  
  1177  	case gc.ODIV<<16 | gc.TFLOAT32:
  1178  		a = x86.ADIVSS
  1179  
  1180  	case gc.ODIV<<16 | gc.TFLOAT64:
  1181  		a = x86.ADIVSD
  1182  
  1183  	case gc.OSQRT<<16 | gc.TFLOAT64:
  1184  		a = x86.ASQRTSD
  1185  	}
  1186  
  1187  	return a
  1188  }
  1189  
  1190  // jmptoset returns ASETxx for AJxx.
  1191  func jmptoset(jmp int) int {
  1192  	switch jmp {
  1193  	case x86.AJEQ:
  1194  		return x86.ASETEQ
  1195  	case x86.AJNE:
  1196  		return x86.ASETNE
  1197  	case x86.AJLT:
  1198  		return x86.ASETLT
  1199  	case x86.AJCS:
  1200  		return x86.ASETCS
  1201  	case x86.AJLE:
  1202  		return x86.ASETLE
  1203  	case x86.AJLS:
  1204  		return x86.ASETLS
  1205  	case x86.AJGT:
  1206  		return x86.ASETGT
  1207  	case x86.AJHI:
  1208  		return x86.ASETHI
  1209  	case x86.AJGE:
  1210  		return x86.ASETGE
  1211  	case x86.AJCC:
  1212  		return x86.ASETCC
  1213  	case x86.AJMI:
  1214  		return x86.ASETMI
  1215  	case x86.AJOC:
  1216  		return x86.ASETOC
  1217  	case x86.AJOS:
  1218  		return x86.ASETOS
  1219  	case x86.AJPC:
  1220  		return x86.ASETPC
  1221  	case x86.AJPL:
  1222  		return x86.ASETPL
  1223  	case x86.AJPS:
  1224  		return x86.ASETPS
  1225  	}
  1226  	gc.Fatal("jmptoset: no entry for %v", gc.Oconv(jmp, 0))
  1227  	panic("unreachable")
  1228  }
  1229  
  1230  const (
  1231  	ODynam   = 1 << 0
  1232  	OAddable = 1 << 1
  1233  )
  1234  
  1235  var clean [20]gc.Node
  1236  
  1237  var cleani int = 0
  1238  
  1239  func sudoclean() {
  1240  	if clean[cleani-1].Op != gc.OEMPTY {
  1241  		gc.Regfree(&clean[cleani-1])
  1242  	}
  1243  	if clean[cleani-2].Op != gc.OEMPTY {
  1244  		gc.Regfree(&clean[cleani-2])
  1245  	}
  1246  	cleani -= 2
  1247  }
  1248  
  1249  /*
  1250   * generate code to compute address of n,
  1251   * a reference to a (perhaps nested) field inside
  1252   * an array or struct.
  1253   * return 0 on failure, 1 on success.
  1254   * on success, leaves usable address in a.
  1255   *
  1256   * caller is responsible for calling sudoclean
  1257   * after successful sudoaddable,
  1258   * to release the register used for a.
  1259   */
  1260  func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
  1261  	if n.Type == nil {
  1262  		return false
  1263  	}
  1264  
  1265  	*a = obj.Addr{}
  1266  
  1267  	switch n.Op {
  1268  	case gc.OLITERAL:
  1269  		if !gc.Isconst(n, gc.CTINT) {
  1270  			break
  1271  		}
  1272  		v := n.Int()
  1273  		if v >= 32000 || v <= -32000 {
  1274  			break
  1275  		}
  1276  		switch as {
  1277  		default:
  1278  			return false
  1279  
  1280  		case x86.AADDB,
  1281  			x86.AADDW,
  1282  			x86.AADDL,
  1283  			x86.AADDQ,
  1284  			x86.ASUBB,
  1285  			x86.ASUBW,
  1286  			x86.ASUBL,
  1287  			x86.ASUBQ,
  1288  			x86.AANDB,
  1289  			x86.AANDW,
  1290  			x86.AANDL,
  1291  			x86.AANDQ,
  1292  			x86.AORB,
  1293  			x86.AORW,
  1294  			x86.AORL,
  1295  			x86.AORQ,
  1296  			x86.AXORB,
  1297  			x86.AXORW,
  1298  			x86.AXORL,
  1299  			x86.AXORQ,
  1300  			x86.AINCB,
  1301  			x86.AINCW,
  1302  			x86.AINCL,
  1303  			x86.AINCQ,
  1304  			x86.ADECB,
  1305  			x86.ADECW,
  1306  			x86.ADECL,
  1307  			x86.ADECQ,
  1308  			x86.AMOVB,
  1309  			x86.AMOVW,
  1310  			x86.AMOVL,
  1311  			x86.AMOVQ:
  1312  			break
  1313  		}
  1314  
  1315  		cleani += 2
  1316  		reg := &clean[cleani-1]
  1317  		reg1 := &clean[cleani-2]
  1318  		reg.Op = gc.OEMPTY
  1319  		reg1.Op = gc.OEMPTY
  1320  		gc.Naddr(a, n)
  1321  		return true
  1322  
  1323  	case gc.ODOT,
  1324  		gc.ODOTPTR:
  1325  		cleani += 2
  1326  		reg := &clean[cleani-1]
  1327  		reg1 := &clean[cleani-2]
  1328  		reg.Op = gc.OEMPTY
  1329  		reg1.Op = gc.OEMPTY
  1330  		var nn *gc.Node
  1331  		var oary [10]int64
  1332  		o := gc.Dotoffset(n, oary[:], &nn)
  1333  		if nn == nil {
  1334  			sudoclean()
  1335  			return false
  1336  		}
  1337  
  1338  		if nn.Addable && o == 1 && oary[0] >= 0 {
  1339  			// directly addressable set of DOTs
  1340  			n1 := *nn
  1341  
  1342  			n1.Type = n.Type
  1343  			n1.Xoffset += oary[0]
  1344  			gc.Naddr(a, &n1)
  1345  			return true
  1346  		}
  1347  
  1348  		gc.Regalloc(reg, gc.Types[gc.Tptr], nil)
  1349  		n1 := *reg
  1350  		n1.Op = gc.OINDREG
  1351  		if oary[0] >= 0 {
  1352  			gc.Agen(nn, reg)
  1353  			n1.Xoffset = oary[0]
  1354  		} else {
  1355  			gc.Cgen(nn, reg)
  1356  			gc.Cgen_checknil(reg)
  1357  			n1.Xoffset = -(oary[0] + 1)
  1358  		}
  1359  
  1360  		for i := 1; i < o; i++ {
  1361  			if oary[i] >= 0 {
  1362  				gc.Fatal("can't happen")
  1363  			}
  1364  			gins(movptr, &n1, reg)
  1365  			gc.Cgen_checknil(reg)
  1366  			n1.Xoffset = -(oary[i] + 1)
  1367  		}
  1368  
  1369  		a.Type = obj.TYPE_NONE
  1370  		a.Index = obj.TYPE_NONE
  1371  		gc.Fixlargeoffset(&n1)
  1372  		gc.Naddr(a, &n1)
  1373  		return true
  1374  
  1375  	case gc.OINDEX:
  1376  		return false
  1377  	}
  1378  
  1379  	return false
  1380  }