github.com/rsc/go@v0.0.0-20150416155037-e040fd465409/src/cmd/7g/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/arm64"
    37  	"fmt"
    38  )
    39  
    40  var resvd = []int{
    41  	arm64.REGTMP,
    42  	arm64.REGG,
    43  	arm64.REGRT1,
    44  	arm64.REGRT2,
    45  	arm64.REG_R31, // REGZERO and REGSP
    46  	arm64.FREGZERO,
    47  	arm64.FREGHALF,
    48  	arm64.FREGONE,
    49  	arm64.FREGTWO,
    50  }
    51  
    52  /*
    53   * generate
    54   *	as $c, n
    55   */
    56  func ginscon(as int, c int64, n2 *gc.Node) {
    57  	var n1 gc.Node
    58  
    59  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    60  
    61  	if as != arm64.AMOVD && (c < -arm64.BIG || c > arm64.BIG) || as == arm64.AMUL || n2 != nil && n2.Op != gc.OREGISTER {
    62  		// cannot have more than 16-bit of immediate in ADD, etc.
    63  		// instead, MOV into register first.
    64  		var ntmp gc.Node
    65  		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    66  
    67  		gins(arm64.AMOVD, &n1, &ntmp)
    68  		gins(as, &ntmp, n2)
    69  		gc.Regfree(&ntmp)
    70  		return
    71  	}
    72  
    73  	rawgins(as, &n1, n2)
    74  }
    75  
    76  /*
    77   * generate
    78   *	as n, $c (CMP)
    79   */
    80  func ginscon2(as int, n2 *gc.Node, c int64) {
    81  	var n1 gc.Node
    82  
    83  	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
    84  
    85  	switch as {
    86  	default:
    87  		gc.Fatal("ginscon2")
    88  
    89  	case arm64.ACMP:
    90  		if -arm64.BIG <= c && c <= arm64.BIG {
    91  			gcmp(as, n2, &n1)
    92  			return
    93  		}
    94  	}
    95  
    96  	// MOV n1 into register first
    97  	var ntmp gc.Node
    98  	gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
    99  
   100  	rawgins(arm64.AMOVD, &n1, &ntmp)
   101  	gcmp(as, n2, &ntmp)
   102  	gc.Regfree(&ntmp)
   103  }
   104  
   105  /*
   106   * generate move:
   107   *	t = f
   108   * hard part is conversions.
   109   */
   110  func gmove(f *gc.Node, t *gc.Node) {
   111  	if gc.Debug['M'] != 0 {
   112  		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
   113  	}
   114  
   115  	ft := int(gc.Simsimtype(f.Type))
   116  	tt := int(gc.Simsimtype(t.Type))
   117  	cvt := (*gc.Type)(t.Type)
   118  
   119  	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
   120  		gc.Complexmove(f, t)
   121  		return
   122  	}
   123  
   124  	// cannot have two memory operands
   125  	var r1 gc.Node
   126  	var a int
   127  	if gc.Ismem(f) && gc.Ismem(t) {
   128  		goto hard
   129  	}
   130  
   131  	// convert constant to desired type
   132  	if f.Op == gc.OLITERAL {
   133  		var con gc.Node
   134  		switch tt {
   135  		default:
   136  			gc.Convconst(&con, t.Type, &f.Val)
   137  
   138  		case gc.TINT32,
   139  			gc.TINT16,
   140  			gc.TINT8:
   141  			var con gc.Node
   142  			gc.Convconst(&con, gc.Types[gc.TINT64], &f.Val)
   143  			var r1 gc.Node
   144  			gc.Regalloc(&r1, con.Type, t)
   145  			gins(arm64.AMOVD, &con, &r1)
   146  			gmove(&r1, t)
   147  			gc.Regfree(&r1)
   148  			return
   149  
   150  		case gc.TUINT32,
   151  			gc.TUINT16,
   152  			gc.TUINT8:
   153  			var con gc.Node
   154  			gc.Convconst(&con, gc.Types[gc.TUINT64], &f.Val)
   155  			var r1 gc.Node
   156  			gc.Regalloc(&r1, con.Type, t)
   157  			gins(arm64.AMOVD, &con, &r1)
   158  			gmove(&r1, t)
   159  			gc.Regfree(&r1)
   160  			return
   161  		}
   162  
   163  		f = &con
   164  		ft = tt // so big switch will choose a simple mov
   165  
   166  		// constants can't move directly to memory.
   167  		if gc.Ismem(t) {
   168  			goto hard
   169  		}
   170  	}
   171  
   172  	// value -> value copy, first operand in memory.
   173  	// any floating point operand requires register
   174  	// src, so goto hard to copy to register first.
   175  	if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) {
   176  		cvt = gc.Types[ft]
   177  		goto hard
   178  	}
   179  
   180  	// value -> value copy, only one memory operand.
   181  	// figure out the instruction to use.
   182  	// break out of switch for one-instruction gins.
   183  	// goto rdst for "destination must be register".
   184  	// goto hard for "convert to cvt type first".
   185  	// otherwise handle and return.
   186  
   187  	switch uint32(ft)<<16 | uint32(tt) {
   188  	default:
   189  		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
   190  
   191  		/*
   192  		 * integer copy and truncate
   193  		 */
   194  	case gc.TINT8<<16 | gc.TINT8, // same size
   195  		gc.TUINT8<<16 | gc.TINT8,
   196  		gc.TINT16<<16 | gc.TINT8,
   197  		// truncate
   198  		gc.TUINT16<<16 | gc.TINT8,
   199  		gc.TINT32<<16 | gc.TINT8,
   200  		gc.TUINT32<<16 | gc.TINT8,
   201  		gc.TINT64<<16 | gc.TINT8,
   202  		gc.TUINT64<<16 | gc.TINT8:
   203  		a = arm64.AMOVB
   204  
   205  	case gc.TINT8<<16 | gc.TUINT8, // same size
   206  		gc.TUINT8<<16 | gc.TUINT8,
   207  		gc.TINT16<<16 | gc.TUINT8,
   208  		// truncate
   209  		gc.TUINT16<<16 | gc.TUINT8,
   210  		gc.TINT32<<16 | gc.TUINT8,
   211  		gc.TUINT32<<16 | gc.TUINT8,
   212  		gc.TINT64<<16 | gc.TUINT8,
   213  		gc.TUINT64<<16 | gc.TUINT8:
   214  		a = arm64.AMOVBU
   215  
   216  	case gc.TINT16<<16 | gc.TINT16, // same size
   217  		gc.TUINT16<<16 | gc.TINT16,
   218  		gc.TINT32<<16 | gc.TINT16,
   219  		// truncate
   220  		gc.TUINT32<<16 | gc.TINT16,
   221  		gc.TINT64<<16 | gc.TINT16,
   222  		gc.TUINT64<<16 | gc.TINT16:
   223  		a = arm64.AMOVH
   224  
   225  	case gc.TINT16<<16 | gc.TUINT16, // same size
   226  		gc.TUINT16<<16 | gc.TUINT16,
   227  		gc.TINT32<<16 | gc.TUINT16,
   228  		// truncate
   229  		gc.TUINT32<<16 | gc.TUINT16,
   230  		gc.TINT64<<16 | gc.TUINT16,
   231  		gc.TUINT64<<16 | gc.TUINT16:
   232  		a = arm64.AMOVHU
   233  
   234  	case gc.TINT32<<16 | gc.TINT32, // same size
   235  		gc.TUINT32<<16 | gc.TINT32,
   236  		gc.TINT64<<16 | gc.TINT32,
   237  		// truncate
   238  		gc.TUINT64<<16 | gc.TINT32:
   239  		a = arm64.AMOVW
   240  
   241  	case gc.TINT32<<16 | gc.TUINT32, // same size
   242  		gc.TUINT32<<16 | gc.TUINT32,
   243  		gc.TINT64<<16 | gc.TUINT32,
   244  		gc.TUINT64<<16 | gc.TUINT32:
   245  		a = arm64.AMOVWU
   246  
   247  	case gc.TINT64<<16 | gc.TINT64, // same size
   248  		gc.TINT64<<16 | gc.TUINT64,
   249  		gc.TUINT64<<16 | gc.TINT64,
   250  		gc.TUINT64<<16 | gc.TUINT64:
   251  		a = arm64.AMOVD
   252  
   253  		/*
   254  		 * integer up-conversions
   255  		 */
   256  	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
   257  		gc.TINT8<<16 | gc.TUINT16,
   258  		gc.TINT8<<16 | gc.TINT32,
   259  		gc.TINT8<<16 | gc.TUINT32,
   260  		gc.TINT8<<16 | gc.TINT64,
   261  		gc.TINT8<<16 | gc.TUINT64:
   262  		a = arm64.AMOVB
   263  
   264  		goto rdst
   265  
   266  	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
   267  		gc.TUINT8<<16 | gc.TUINT16,
   268  		gc.TUINT8<<16 | gc.TINT32,
   269  		gc.TUINT8<<16 | gc.TUINT32,
   270  		gc.TUINT8<<16 | gc.TINT64,
   271  		gc.TUINT8<<16 | gc.TUINT64:
   272  		a = arm64.AMOVBU
   273  
   274  		goto rdst
   275  
   276  	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
   277  		gc.TINT16<<16 | gc.TUINT32,
   278  		gc.TINT16<<16 | gc.TINT64,
   279  		gc.TINT16<<16 | gc.TUINT64:
   280  		a = arm64.AMOVH
   281  
   282  		goto rdst
   283  
   284  	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
   285  		gc.TUINT16<<16 | gc.TUINT32,
   286  		gc.TUINT16<<16 | gc.TINT64,
   287  		gc.TUINT16<<16 | gc.TUINT64:
   288  		a = arm64.AMOVHU
   289  
   290  		goto rdst
   291  
   292  	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
   293  		gc.TINT32<<16 | gc.TUINT64:
   294  		a = arm64.AMOVW
   295  
   296  		goto rdst
   297  
   298  	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
   299  		gc.TUINT32<<16 | gc.TUINT64:
   300  		a = arm64.AMOVWU
   301  
   302  		goto rdst
   303  
   304  	/*
   305  	* float to integer
   306  	 */
   307  	case gc.TFLOAT32<<16 | gc.TINT32:
   308  		a = arm64.AFCVTZSSW
   309  		goto rdst
   310  
   311  	case gc.TFLOAT64<<16 | gc.TINT32:
   312  		a = arm64.AFCVTZSDW
   313  		goto rdst
   314  
   315  	case gc.TFLOAT32<<16 | gc.TINT64:
   316  		a = arm64.AFCVTZSS
   317  		goto rdst
   318  
   319  	case gc.TFLOAT64<<16 | gc.TINT64:
   320  		a = arm64.AFCVTZSD
   321  		goto rdst
   322  
   323  	case gc.TFLOAT32<<16 | gc.TUINT32:
   324  		a = arm64.AFCVTZUSW
   325  		goto rdst
   326  
   327  	case gc.TFLOAT64<<16 | gc.TUINT32:
   328  		a = arm64.AFCVTZUDW
   329  		goto rdst
   330  
   331  	case gc.TFLOAT32<<16 | gc.TUINT64:
   332  		a = arm64.AFCVTZUS
   333  		goto rdst
   334  
   335  	case gc.TFLOAT64<<16 | gc.TUINT64:
   336  		a = arm64.AFCVTZUD
   337  		goto rdst
   338  
   339  	case gc.TFLOAT32<<16 | gc.TINT16,
   340  		gc.TFLOAT32<<16 | gc.TINT8,
   341  		gc.TFLOAT64<<16 | gc.TINT16,
   342  		gc.TFLOAT64<<16 | gc.TINT8:
   343  		cvt = gc.Types[gc.TINT32]
   344  
   345  		goto hard
   346  
   347  	case gc.TFLOAT32<<16 | gc.TUINT16,
   348  		gc.TFLOAT32<<16 | gc.TUINT8,
   349  		gc.TFLOAT64<<16 | gc.TUINT16,
   350  		gc.TFLOAT64<<16 | gc.TUINT8:
   351  		cvt = gc.Types[gc.TUINT32]
   352  
   353  		goto hard
   354  
   355  	/*
   356  	 * integer to float
   357  	 */
   358  	case gc.TINT8<<16 | gc.TFLOAT32,
   359  		gc.TINT16<<16 | gc.TFLOAT32,
   360  		gc.TINT32<<16 | gc.TFLOAT32:
   361  		a = arm64.ASCVTFWS
   362  
   363  		goto rdst
   364  
   365  	case gc.TINT8<<16 | gc.TFLOAT64,
   366  		gc.TINT16<<16 | gc.TFLOAT64,
   367  		gc.TINT32<<16 | gc.TFLOAT64:
   368  		a = arm64.ASCVTFWD
   369  
   370  		goto rdst
   371  
   372  	case gc.TINT64<<16 | gc.TFLOAT32:
   373  		a = arm64.ASCVTFS
   374  		goto rdst
   375  
   376  	case gc.TINT64<<16 | gc.TFLOAT64:
   377  		a = arm64.ASCVTFD
   378  		goto rdst
   379  
   380  	case gc.TUINT8<<16 | gc.TFLOAT32,
   381  		gc.TUINT16<<16 | gc.TFLOAT32,
   382  		gc.TUINT32<<16 | gc.TFLOAT32:
   383  		a = arm64.AUCVTFWS
   384  
   385  		goto rdst
   386  
   387  	case gc.TUINT8<<16 | gc.TFLOAT64,
   388  		gc.TUINT16<<16 | gc.TFLOAT64,
   389  		gc.TUINT32<<16 | gc.TFLOAT64:
   390  		a = arm64.AUCVTFWD
   391  
   392  		goto rdst
   393  
   394  	case gc.TUINT64<<16 | gc.TFLOAT32:
   395  		a = arm64.AUCVTFS
   396  		goto rdst
   397  
   398  	case gc.TUINT64<<16 | gc.TFLOAT64:
   399  		a = arm64.AUCVTFD
   400  		goto rdst
   401  
   402  		/*
   403  		 * float to float
   404  		 */
   405  	case gc.TFLOAT32<<16 | gc.TFLOAT32:
   406  		a = arm64.AFMOVS
   407  
   408  	case gc.TFLOAT64<<16 | gc.TFLOAT64:
   409  		a = arm64.AFMOVD
   410  
   411  	case gc.TFLOAT32<<16 | gc.TFLOAT64:
   412  		a = arm64.AFCVTSD
   413  		goto rdst
   414  
   415  	case gc.TFLOAT64<<16 | gc.TFLOAT32:
   416  		a = arm64.AFCVTDS
   417  		goto rdst
   418  	}
   419  
   420  	gins(a, f, t)
   421  	return
   422  
   423  	// requires register destination
   424  rdst:
   425  	gc.Regalloc(&r1, t.Type, t)
   426  
   427  	gins(a, f, &r1)
   428  	gmove(&r1, t)
   429  	gc.Regfree(&r1)
   430  	return
   431  
   432  	// requires register intermediate
   433  hard:
   434  	gc.Regalloc(&r1, cvt, t)
   435  
   436  	gmove(f, &r1)
   437  	gmove(&r1, t)
   438  	gc.Regfree(&r1)
   439  	return
   440  }
   441  
   442  func intLiteral(n *gc.Node) (x int64, ok bool) {
   443  	if n == nil || n.Op != gc.OLITERAL {
   444  		return
   445  	}
   446  	switch n.Val.Ctype {
   447  	case gc.CTINT, gc.CTRUNE:
   448  		return gc.Mpgetfix(n.Val.U.Xval), true
   449  	case gc.CTBOOL:
   450  		return int64(bool2int(n.Val.U.Bval)), true
   451  	}
   452  	return
   453  }
   454  
   455  // gins is called by the front end.
   456  // It synthesizes some multiple-instruction sequences
   457  // so the front end can stay simpler.
   458  func gins(as int, f, t *gc.Node) *obj.Prog {
   459  	if as >= obj.A_ARCHSPECIFIC {
   460  		if x, ok := intLiteral(f); ok {
   461  			ginscon(as, x, t)
   462  			return nil // caller must not use
   463  		}
   464  	}
   465  	if as == arm64.ACMP {
   466  		if x, ok := intLiteral(t); ok {
   467  			ginscon2(as, f, x)
   468  			return nil // caller must not use
   469  		}
   470  	}
   471  	return rawgins(as, f, t)
   472  }
   473  
   474  /*
   475   * generate one instruction:
   476   *	as f, t
   477   */
   478  func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
   479  	// TODO(austin): Add self-move test like in 6g (but be careful
   480  	// of truncation moves)
   481  
   482  	p := gc.Prog(as)
   483  	gc.Naddr(&p.From, f)
   484  	gc.Naddr(&p.To, t)
   485  
   486  	switch as {
   487  	case arm64.ACMP, arm64.AFCMPS, arm64.AFCMPD:
   488  		if t != nil {
   489  			if f.Op != gc.OREGISTER {
   490  				gc.Fatal("bad operands to gcmp")
   491  			}
   492  			p.From = p.To
   493  			p.To = obj.Addr{}
   494  			raddr(f, p)
   495  		}
   496  	}
   497  
   498  	// Bad things the front end has done to us. Crash to find call stack.
   499  	switch as {
   500  	case arm64.AAND, arm64.AMUL:
   501  		if p.From.Type == obj.TYPE_CONST {
   502  			gc.Debug['h'] = 1
   503  			gc.Fatal("bad inst: %v", p)
   504  		}
   505  	case arm64.ACMP:
   506  		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
   507  			gc.Debug['h'] = 1
   508  			gc.Fatal("bad inst: %v", p)
   509  		}
   510  	}
   511  
   512  	if gc.Debug['g'] != 0 {
   513  		fmt.Printf("%v\n", p)
   514  	}
   515  
   516  	w := int32(0)
   517  	switch as {
   518  	case arm64.AMOVB,
   519  		arm64.AMOVBU:
   520  		w = 1
   521  
   522  	case arm64.AMOVH,
   523  		arm64.AMOVHU:
   524  		w = 2
   525  
   526  	case arm64.AMOVW,
   527  		arm64.AMOVWU:
   528  		w = 4
   529  
   530  	case arm64.AMOVD:
   531  		if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
   532  			break
   533  		}
   534  		w = 8
   535  	}
   536  
   537  	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
   538  		gc.Dump("f", f)
   539  		gc.Dump("t", t)
   540  		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
   541  	}
   542  
   543  	return p
   544  }
   545  
   546  func fixlargeoffset(n *gc.Node) {
   547  	if n == nil {
   548  		return
   549  	}
   550  	if n.Op != gc.OINDREG {
   551  		return
   552  	}
   553  	if -4096 <= n.Xoffset && n.Xoffset < 4096 {
   554  		return
   555  	}
   556  	a := gc.Node(*n)
   557  	a.Op = gc.OREGISTER
   558  	a.Type = gc.Types[gc.Tptr]
   559  	a.Xoffset = 0
   560  	gc.Cgen_checknil(&a)
   561  	ginscon(optoas(gc.OADD, gc.Types[gc.Tptr]), n.Xoffset, &a)
   562  	n.Xoffset = 0
   563  }
   564  
   565  /*
   566   * insert n into reg slot of p
   567   */
   568  func raddr(n *gc.Node, p *obj.Prog) {
   569  	var a obj.Addr
   570  
   571  	gc.Naddr(&a, n)
   572  	if a.Type != obj.TYPE_REG {
   573  		if n != nil {
   574  			gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
   575  		} else {
   576  			gc.Fatal("bad in raddr: <null>")
   577  		}
   578  		p.Reg = 0
   579  	} else {
   580  		p.Reg = a.Reg
   581  	}
   582  }
   583  
   584  func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog {
   585  	if lhs.Op != gc.OREGISTER {
   586  		gc.Fatal("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0))
   587  	}
   588  
   589  	p := rawgins(as, rhs, nil)
   590  	raddr(lhs, p)
   591  	return p
   592  }
   593  
   594  /*
   595   * return Axxx for Oxxx on type t.
   596   */
   597  func optoas(op int, t *gc.Type) int {
   598  	if t == nil {
   599  		gc.Fatal("optoas: t is nil")
   600  	}
   601  
   602  	a := int(obj.AXXX)
   603  	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
   604  	default:
   605  		gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), gc.Tconv(t, 0))
   606  
   607  	case gc.OEQ<<16 | gc.TBOOL,
   608  		gc.OEQ<<16 | gc.TINT8,
   609  		gc.OEQ<<16 | gc.TUINT8,
   610  		gc.OEQ<<16 | gc.TINT16,
   611  		gc.OEQ<<16 | gc.TUINT16,
   612  		gc.OEQ<<16 | gc.TINT32,
   613  		gc.OEQ<<16 | gc.TUINT32,
   614  		gc.OEQ<<16 | gc.TINT64,
   615  		gc.OEQ<<16 | gc.TUINT64,
   616  		gc.OEQ<<16 | gc.TPTR32,
   617  		gc.OEQ<<16 | gc.TPTR64,
   618  		gc.OEQ<<16 | gc.TFLOAT32,
   619  		gc.OEQ<<16 | gc.TFLOAT64:
   620  		a = arm64.ABEQ
   621  
   622  	case gc.ONE<<16 | gc.TBOOL,
   623  		gc.ONE<<16 | gc.TINT8,
   624  		gc.ONE<<16 | gc.TUINT8,
   625  		gc.ONE<<16 | gc.TINT16,
   626  		gc.ONE<<16 | gc.TUINT16,
   627  		gc.ONE<<16 | gc.TINT32,
   628  		gc.ONE<<16 | gc.TUINT32,
   629  		gc.ONE<<16 | gc.TINT64,
   630  		gc.ONE<<16 | gc.TUINT64,
   631  		gc.ONE<<16 | gc.TPTR32,
   632  		gc.ONE<<16 | gc.TPTR64,
   633  		gc.ONE<<16 | gc.TFLOAT32,
   634  		gc.ONE<<16 | gc.TFLOAT64:
   635  		a = arm64.ABNE
   636  
   637  	case gc.OLT<<16 | gc.TINT8,
   638  		gc.OLT<<16 | gc.TINT16,
   639  		gc.OLT<<16 | gc.TINT32,
   640  		gc.OLT<<16 | gc.TINT64:
   641  		a = arm64.ABLT
   642  
   643  	case gc.OLT<<16 | gc.TUINT8,
   644  		gc.OLT<<16 | gc.TUINT16,
   645  		gc.OLT<<16 | gc.TUINT32,
   646  		gc.OLT<<16 | gc.TUINT64,
   647  		gc.OLT<<16 | gc.TFLOAT32,
   648  		gc.OLT<<16 | gc.TFLOAT64:
   649  		a = arm64.ABLO
   650  
   651  	case gc.OLE<<16 | gc.TINT8,
   652  		gc.OLE<<16 | gc.TINT16,
   653  		gc.OLE<<16 | gc.TINT32,
   654  		gc.OLE<<16 | gc.TINT64:
   655  		a = arm64.ABLE
   656  
   657  	case gc.OLE<<16 | gc.TUINT8,
   658  		gc.OLE<<16 | gc.TUINT16,
   659  		gc.OLE<<16 | gc.TUINT32,
   660  		gc.OLE<<16 | gc.TUINT64,
   661  		gc.OLE<<16 | gc.TFLOAT32,
   662  		gc.OLE<<16 | gc.TFLOAT64:
   663  		a = arm64.ABLS
   664  
   665  	case gc.OGT<<16 | gc.TINT8,
   666  		gc.OGT<<16 | gc.TINT16,
   667  		gc.OGT<<16 | gc.TINT32,
   668  		gc.OGT<<16 | gc.TINT64,
   669  		gc.OGT<<16 | gc.TFLOAT32,
   670  		gc.OGT<<16 | gc.TFLOAT64:
   671  		a = arm64.ABGT
   672  
   673  	case gc.OGT<<16 | gc.TUINT8,
   674  		gc.OGT<<16 | gc.TUINT16,
   675  		gc.OGT<<16 | gc.TUINT32,
   676  		gc.OGT<<16 | gc.TUINT64:
   677  		a = arm64.ABHI
   678  
   679  	case gc.OGE<<16 | gc.TINT8,
   680  		gc.OGE<<16 | gc.TINT16,
   681  		gc.OGE<<16 | gc.TINT32,
   682  		gc.OGE<<16 | gc.TINT64,
   683  		gc.OGE<<16 | gc.TFLOAT32,
   684  		gc.OGE<<16 | gc.TFLOAT64:
   685  		a = arm64.ABGE
   686  
   687  	case gc.OGE<<16 | gc.TUINT8,
   688  		gc.OGE<<16 | gc.TUINT16,
   689  		gc.OGE<<16 | gc.TUINT32,
   690  		gc.OGE<<16 | gc.TUINT64:
   691  		a = arm64.ABHS
   692  
   693  	case gc.OCMP<<16 | gc.TBOOL,
   694  		gc.OCMP<<16 | gc.TINT8,
   695  		gc.OCMP<<16 | gc.TINT16,
   696  		gc.OCMP<<16 | gc.TINT32,
   697  		gc.OCMP<<16 | gc.TPTR32,
   698  		gc.OCMP<<16 | gc.TINT64,
   699  		gc.OCMP<<16 | gc.TUINT8,
   700  		gc.OCMP<<16 | gc.TUINT16,
   701  		gc.OCMP<<16 | gc.TUINT32,
   702  		gc.OCMP<<16 | gc.TUINT64,
   703  		gc.OCMP<<16 | gc.TPTR64:
   704  		a = arm64.ACMP
   705  
   706  	case gc.OCMP<<16 | gc.TFLOAT32:
   707  		a = arm64.AFCMPS
   708  
   709  	case gc.OCMP<<16 | gc.TFLOAT64:
   710  		a = arm64.AFCMPD
   711  
   712  	case gc.OAS<<16 | gc.TBOOL,
   713  		gc.OAS<<16 | gc.TINT8:
   714  		a = arm64.AMOVB
   715  
   716  	case gc.OAS<<16 | gc.TUINT8:
   717  		a = arm64.AMOVBU
   718  
   719  	case gc.OAS<<16 | gc.TINT16:
   720  		a = arm64.AMOVH
   721  
   722  	case gc.OAS<<16 | gc.TUINT16:
   723  		a = arm64.AMOVHU
   724  
   725  	case gc.OAS<<16 | gc.TINT32:
   726  		a = arm64.AMOVW
   727  
   728  	case gc.OAS<<16 | gc.TUINT32,
   729  		gc.OAS<<16 | gc.TPTR32:
   730  		a = arm64.AMOVWU
   731  
   732  	case gc.OAS<<16 | gc.TINT64,
   733  		gc.OAS<<16 | gc.TUINT64,
   734  		gc.OAS<<16 | gc.TPTR64:
   735  		a = arm64.AMOVD
   736  
   737  	case gc.OAS<<16 | gc.TFLOAT32:
   738  		a = arm64.AFMOVS
   739  
   740  	case gc.OAS<<16 | gc.TFLOAT64:
   741  		a = arm64.AFMOVD
   742  
   743  	case gc.OADD<<16 | gc.TINT8,
   744  		gc.OADD<<16 | gc.TUINT8,
   745  		gc.OADD<<16 | gc.TINT16,
   746  		gc.OADD<<16 | gc.TUINT16,
   747  		gc.OADD<<16 | gc.TINT32,
   748  		gc.OADD<<16 | gc.TUINT32,
   749  		gc.OADD<<16 | gc.TPTR32,
   750  		gc.OADD<<16 | gc.TINT64,
   751  		gc.OADD<<16 | gc.TUINT64,
   752  		gc.OADD<<16 | gc.TPTR64:
   753  		a = arm64.AADD
   754  
   755  	case gc.OADD<<16 | gc.TFLOAT32:
   756  		a = arm64.AFADDS
   757  
   758  	case gc.OADD<<16 | gc.TFLOAT64:
   759  		a = arm64.AFADDD
   760  
   761  	case gc.OSUB<<16 | gc.TINT8,
   762  		gc.OSUB<<16 | gc.TUINT8,
   763  		gc.OSUB<<16 | gc.TINT16,
   764  		gc.OSUB<<16 | gc.TUINT16,
   765  		gc.OSUB<<16 | gc.TINT32,
   766  		gc.OSUB<<16 | gc.TUINT32,
   767  		gc.OSUB<<16 | gc.TPTR32,
   768  		gc.OSUB<<16 | gc.TINT64,
   769  		gc.OSUB<<16 | gc.TUINT64,
   770  		gc.OSUB<<16 | gc.TPTR64:
   771  		a = arm64.ASUB
   772  
   773  	case gc.OSUB<<16 | gc.TFLOAT32:
   774  		a = arm64.AFSUBS
   775  
   776  	case gc.OSUB<<16 | gc.TFLOAT64:
   777  		a = arm64.AFSUBD
   778  
   779  	case gc.OMINUS<<16 | gc.TINT8,
   780  		gc.OMINUS<<16 | gc.TUINT8,
   781  		gc.OMINUS<<16 | gc.TINT16,
   782  		gc.OMINUS<<16 | gc.TUINT16,
   783  		gc.OMINUS<<16 | gc.TINT32,
   784  		gc.OMINUS<<16 | gc.TUINT32,
   785  		gc.OMINUS<<16 | gc.TPTR32,
   786  		gc.OMINUS<<16 | gc.TINT64,
   787  		gc.OMINUS<<16 | gc.TUINT64,
   788  		gc.OMINUS<<16 | gc.TPTR64:
   789  		a = arm64.ANEG
   790  
   791  	case gc.OMINUS<<16 | gc.TFLOAT32:
   792  		a = arm64.AFNEGS
   793  
   794  	case gc.OMINUS<<16 | gc.TFLOAT64:
   795  		a = arm64.AFNEGD
   796  
   797  	case gc.OAND<<16 | gc.TINT8,
   798  		gc.OAND<<16 | gc.TUINT8,
   799  		gc.OAND<<16 | gc.TINT16,
   800  		gc.OAND<<16 | gc.TUINT16,
   801  		gc.OAND<<16 | gc.TINT32,
   802  		gc.OAND<<16 | gc.TUINT32,
   803  		gc.OAND<<16 | gc.TPTR32,
   804  		gc.OAND<<16 | gc.TINT64,
   805  		gc.OAND<<16 | gc.TUINT64,
   806  		gc.OAND<<16 | gc.TPTR64:
   807  		a = arm64.AAND
   808  
   809  	case gc.OOR<<16 | gc.TINT8,
   810  		gc.OOR<<16 | gc.TUINT8,
   811  		gc.OOR<<16 | gc.TINT16,
   812  		gc.OOR<<16 | gc.TUINT16,
   813  		gc.OOR<<16 | gc.TINT32,
   814  		gc.OOR<<16 | gc.TUINT32,
   815  		gc.OOR<<16 | gc.TPTR32,
   816  		gc.OOR<<16 | gc.TINT64,
   817  		gc.OOR<<16 | gc.TUINT64,
   818  		gc.OOR<<16 | gc.TPTR64:
   819  		a = arm64.AORR
   820  
   821  	case gc.OXOR<<16 | gc.TINT8,
   822  		gc.OXOR<<16 | gc.TUINT8,
   823  		gc.OXOR<<16 | gc.TINT16,
   824  		gc.OXOR<<16 | gc.TUINT16,
   825  		gc.OXOR<<16 | gc.TINT32,
   826  		gc.OXOR<<16 | gc.TUINT32,
   827  		gc.OXOR<<16 | gc.TPTR32,
   828  		gc.OXOR<<16 | gc.TINT64,
   829  		gc.OXOR<<16 | gc.TUINT64,
   830  		gc.OXOR<<16 | gc.TPTR64:
   831  		a = arm64.AEOR
   832  
   833  		// TODO(minux): handle rotates
   834  	//case CASE(OLROT, TINT8):
   835  	//case CASE(OLROT, TUINT8):
   836  	//case CASE(OLROT, TINT16):
   837  	//case CASE(OLROT, TUINT16):
   838  	//case CASE(OLROT, TINT32):
   839  	//case CASE(OLROT, TUINT32):
   840  	//case CASE(OLROT, TPTR32):
   841  	//case CASE(OLROT, TINT64):
   842  	//case CASE(OLROT, TUINT64):
   843  	//case CASE(OLROT, TPTR64):
   844  	//	a = 0//???; RLDC?
   845  	//	break;
   846  
   847  	case gc.OLSH<<16 | gc.TINT8,
   848  		gc.OLSH<<16 | gc.TUINT8,
   849  		gc.OLSH<<16 | gc.TINT16,
   850  		gc.OLSH<<16 | gc.TUINT16,
   851  		gc.OLSH<<16 | gc.TINT32,
   852  		gc.OLSH<<16 | gc.TUINT32,
   853  		gc.OLSH<<16 | gc.TPTR32,
   854  		gc.OLSH<<16 | gc.TINT64,
   855  		gc.OLSH<<16 | gc.TUINT64,
   856  		gc.OLSH<<16 | gc.TPTR64:
   857  		a = arm64.ALSL
   858  
   859  	case gc.ORSH<<16 | gc.TUINT8,
   860  		gc.ORSH<<16 | gc.TUINT16,
   861  		gc.ORSH<<16 | gc.TUINT32,
   862  		gc.ORSH<<16 | gc.TPTR32,
   863  		gc.ORSH<<16 | gc.TUINT64,
   864  		gc.ORSH<<16 | gc.TPTR64:
   865  		a = arm64.ALSR
   866  
   867  	case gc.ORSH<<16 | gc.TINT8,
   868  		gc.ORSH<<16 | gc.TINT16,
   869  		gc.ORSH<<16 | gc.TINT32,
   870  		gc.ORSH<<16 | gc.TINT64:
   871  		a = arm64.AASR
   872  
   873  		// TODO(minux): handle rotates
   874  	//case CASE(ORROTC, TINT8):
   875  	//case CASE(ORROTC, TUINT8):
   876  	//case CASE(ORROTC, TINT16):
   877  	//case CASE(ORROTC, TUINT16):
   878  	//case CASE(ORROTC, TINT32):
   879  	//case CASE(ORROTC, TUINT32):
   880  	//case CASE(ORROTC, TINT64):
   881  	//case CASE(ORROTC, TUINT64):
   882  	//	a = 0//??? RLDC??
   883  	//	break;
   884  
   885  	case gc.OHMUL<<16 | gc.TINT64:
   886  		a = arm64.ASMULH
   887  
   888  	case gc.OHMUL<<16 | gc.TUINT64,
   889  		gc.OHMUL<<16 | gc.TPTR64:
   890  		a = arm64.AUMULH
   891  
   892  	case gc.OMUL<<16 | gc.TINT8,
   893  		gc.OMUL<<16 | gc.TINT16,
   894  		gc.OMUL<<16 | gc.TINT32:
   895  		a = arm64.ASMULL
   896  
   897  	case gc.OMUL<<16 | gc.TINT64:
   898  		a = arm64.AMUL
   899  
   900  	case gc.OMUL<<16 | gc.TUINT8,
   901  		gc.OMUL<<16 | gc.TUINT16,
   902  		gc.OMUL<<16 | gc.TUINT32,
   903  		gc.OMUL<<16 | gc.TPTR32:
   904  		// don't use word multiply, the high 32-bit are undefined.
   905  		a = arm64.AUMULL
   906  
   907  	case gc.OMUL<<16 | gc.TUINT64,
   908  		gc.OMUL<<16 | gc.TPTR64:
   909  		a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter.
   910  
   911  	case gc.OMUL<<16 | gc.TFLOAT32:
   912  		a = arm64.AFMULS
   913  
   914  	case gc.OMUL<<16 | gc.TFLOAT64:
   915  		a = arm64.AFMULD
   916  
   917  	case gc.ODIV<<16 | gc.TINT8,
   918  		gc.ODIV<<16 | gc.TINT16,
   919  		gc.ODIV<<16 | gc.TINT32,
   920  		gc.ODIV<<16 | gc.TINT64:
   921  		a = arm64.ASDIV
   922  
   923  	case gc.ODIV<<16 | gc.TUINT8,
   924  		gc.ODIV<<16 | gc.TUINT16,
   925  		gc.ODIV<<16 | gc.TUINT32,
   926  		gc.ODIV<<16 | gc.TPTR32,
   927  		gc.ODIV<<16 | gc.TUINT64,
   928  		gc.ODIV<<16 | gc.TPTR64:
   929  		a = arm64.AUDIV
   930  
   931  	case gc.ODIV<<16 | gc.TFLOAT32:
   932  		a = arm64.AFDIVS
   933  
   934  	case gc.ODIV<<16 | gc.TFLOAT64:
   935  		a = arm64.AFDIVD
   936  
   937  	case gc.OSQRT<<16 | gc.TFLOAT64:
   938  		a = arm64.AFSQRTD
   939  	}
   940  
   941  	return a
   942  }
   943  
   944  const (
   945  	ODynam   = 1 << 0
   946  	OAddable = 1 << 1
   947  )
   948  
   949  func xgen(n *gc.Node, a *gc.Node, o int) bool {
   950  	// TODO(minux)
   951  
   952  	return -1 != 0 /*TypeKind(100016)*/
   953  }
   954  
   955  func sudoclean() {
   956  	return
   957  }
   958  
   959  /*
   960   * generate code to compute address of n,
   961   * a reference to a (perhaps nested) field inside
   962   * an array or struct.
   963   * return 0 on failure, 1 on success.
   964   * on success, leaves usable address in a.
   965   *
   966   * caller is responsible for calling sudoclean
   967   * after successful sudoaddable,
   968   * to release the register used for a.
   969   */
   970  func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
   971  	// TODO(minux)
   972  
   973  	*a = obj.Addr{}
   974  	return false
   975  }