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