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