Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/internal/obj/arm64/asm7.go

Documentation: cmd/internal/obj/arm64

     1  // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
     2  // https://code.google.com/p/ken-cc/source/browse/
     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/internal/obj"
    35  	"cmd/internal/objabi"
    36  	"fmt"
    37  	"log"
    38  	"math"
    39  	"sort"
    40  )
    41  
    42  // ctxt7 holds state while assembling a single function.
    43  // Each function gets a fresh ctxt7.
    44  // This allows for multiple functions to be safely concurrently assembled.
    45  type ctxt7 struct {
    46  	ctxt       *obj.Link
    47  	newprog    obj.ProgAlloc
    48  	cursym     *obj.LSym
    49  	blitrl     *obj.Prog
    50  	elitrl     *obj.Prog
    51  	autosize   int32
    52  	extrasize  int32
    53  	instoffset int64
    54  	pc         int64
    55  	pool       struct {
    56  		start uint32
    57  		size  uint32
    58  	}
    59  }
    60  
    61  const (
    62  	funcAlign = 16
    63  )
    64  
    65  const (
    66  	REGFROM = 1
    67  )
    68  
    69  type Optab struct {
    70  	as    obj.As
    71  	a1    uint8
    72  	a2    uint8
    73  	a3    uint8
    74  	a4    uint8
    75  	type_ int8
    76  	size  int8
    77  	param int16
    78  	flag  int8
    79  	scond uint16
    80  }
    81  
    82  func IsAtomicInstruction(as obj.As) bool {
    83  	if _, ok := atomicLDADD[as]; ok {
    84  		return true
    85  	}
    86  	if _, ok := atomicSWP[as]; ok {
    87  		return true
    88  	}
    89  	return false
    90  }
    91  
    92  // known field values of an instruction.
    93  var atomicLDADD = map[obj.As]uint32{
    94  	ALDADDAD:  3<<30 | 0x1c5<<21 | 0x00<<10,
    95  	ALDADDAW:  2<<30 | 0x1c5<<21 | 0x00<<10,
    96  	ALDADDAH:  1<<30 | 0x1c5<<21 | 0x00<<10,
    97  	ALDADDAB:  0<<30 | 0x1c5<<21 | 0x00<<10,
    98  	ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
    99  	ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
   100  	ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
   101  	ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
   102  	ALDADDD:   3<<30 | 0x1c1<<21 | 0x00<<10,
   103  	ALDADDW:   2<<30 | 0x1c1<<21 | 0x00<<10,
   104  	ALDADDH:   1<<30 | 0x1c1<<21 | 0x00<<10,
   105  	ALDADDB:   0<<30 | 0x1c1<<21 | 0x00<<10,
   106  	ALDADDLD:  3<<30 | 0x1c3<<21 | 0x00<<10,
   107  	ALDADDLW:  2<<30 | 0x1c3<<21 | 0x00<<10,
   108  	ALDADDLH:  1<<30 | 0x1c3<<21 | 0x00<<10,
   109  	ALDADDLB:  0<<30 | 0x1c3<<21 | 0x00<<10,
   110  	ALDCLRAD:  3<<30 | 0x1c5<<21 | 0x04<<10,
   111  	ALDCLRAW:  2<<30 | 0x1c5<<21 | 0x04<<10,
   112  	ALDCLRAH:  1<<30 | 0x1c5<<21 | 0x04<<10,
   113  	ALDCLRAB:  0<<30 | 0x1c5<<21 | 0x04<<10,
   114  	ALDCLRALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
   115  	ALDCLRALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
   116  	ALDCLRALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
   117  	ALDCLRALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
   118  	ALDCLRD:   3<<30 | 0x1c1<<21 | 0x04<<10,
   119  	ALDCLRW:   2<<30 | 0x1c1<<21 | 0x04<<10,
   120  	ALDCLRH:   1<<30 | 0x1c1<<21 | 0x04<<10,
   121  	ALDCLRB:   0<<30 | 0x1c1<<21 | 0x04<<10,
   122  	ALDCLRLD:  3<<30 | 0x1c3<<21 | 0x04<<10,
   123  	ALDCLRLW:  2<<30 | 0x1c3<<21 | 0x04<<10,
   124  	ALDCLRLH:  1<<30 | 0x1c3<<21 | 0x04<<10,
   125  	ALDCLRLB:  0<<30 | 0x1c3<<21 | 0x04<<10,
   126  	ALDEORAD:  3<<30 | 0x1c5<<21 | 0x08<<10,
   127  	ALDEORAW:  2<<30 | 0x1c5<<21 | 0x08<<10,
   128  	ALDEORAH:  1<<30 | 0x1c5<<21 | 0x08<<10,
   129  	ALDEORAB:  0<<30 | 0x1c5<<21 | 0x08<<10,
   130  	ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
   131  	ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
   132  	ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
   133  	ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
   134  	ALDEORD:   3<<30 | 0x1c1<<21 | 0x08<<10,
   135  	ALDEORW:   2<<30 | 0x1c1<<21 | 0x08<<10,
   136  	ALDEORH:   1<<30 | 0x1c1<<21 | 0x08<<10,
   137  	ALDEORB:   0<<30 | 0x1c1<<21 | 0x08<<10,
   138  	ALDEORLD:  3<<30 | 0x1c3<<21 | 0x08<<10,
   139  	ALDEORLW:  2<<30 | 0x1c3<<21 | 0x08<<10,
   140  	ALDEORLH:  1<<30 | 0x1c3<<21 | 0x08<<10,
   141  	ALDEORLB:  0<<30 | 0x1c3<<21 | 0x08<<10,
   142  	ALDORAD:   3<<30 | 0x1c5<<21 | 0x0c<<10,
   143  	ALDORAW:   2<<30 | 0x1c5<<21 | 0x0c<<10,
   144  	ALDORAH:   1<<30 | 0x1c5<<21 | 0x0c<<10,
   145  	ALDORAB:   0<<30 | 0x1c5<<21 | 0x0c<<10,
   146  	ALDORALD:  3<<30 | 0x1c7<<21 | 0x0c<<10,
   147  	ALDORALW:  2<<30 | 0x1c7<<21 | 0x0c<<10,
   148  	ALDORALH:  1<<30 | 0x1c7<<21 | 0x0c<<10,
   149  	ALDORALB:  0<<30 | 0x1c7<<21 | 0x0c<<10,
   150  	ALDORD:    3<<30 | 0x1c1<<21 | 0x0c<<10,
   151  	ALDORW:    2<<30 | 0x1c1<<21 | 0x0c<<10,
   152  	ALDORH:    1<<30 | 0x1c1<<21 | 0x0c<<10,
   153  	ALDORB:    0<<30 | 0x1c1<<21 | 0x0c<<10,
   154  	ALDORLD:   3<<30 | 0x1c3<<21 | 0x0c<<10,
   155  	ALDORLW:   2<<30 | 0x1c3<<21 | 0x0c<<10,
   156  	ALDORLH:   1<<30 | 0x1c3<<21 | 0x0c<<10,
   157  	ALDORLB:   0<<30 | 0x1c3<<21 | 0x0c<<10,
   158  }
   159  
   160  var atomicSWP = map[obj.As]uint32{
   161  	ASWPAD:  3<<30 | 0x1c5<<21 | 0x20<<10,
   162  	ASWPAW:  2<<30 | 0x1c5<<21 | 0x20<<10,
   163  	ASWPAH:  1<<30 | 0x1c5<<21 | 0x20<<10,
   164  	ASWPAB:  0<<30 | 0x1c5<<21 | 0x20<<10,
   165  	ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10,
   166  	ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10,
   167  	ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10,
   168  	ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10,
   169  	ASWPD:   3<<30 | 0x1c1<<21 | 0x20<<10,
   170  	ASWPW:   2<<30 | 0x1c1<<21 | 0x20<<10,
   171  	ASWPH:   1<<30 | 0x1c1<<21 | 0x20<<10,
   172  	ASWPB:   0<<30 | 0x1c1<<21 | 0x20<<10,
   173  	ASWPLD:  3<<30 | 0x1c3<<21 | 0x20<<10,
   174  	ASWPLW:  2<<30 | 0x1c3<<21 | 0x20<<10,
   175  	ASWPLH:  1<<30 | 0x1c3<<21 | 0x20<<10,
   176  	ASWPLB:  0<<30 | 0x1c3<<21 | 0x20<<10,
   177  	ACASD:   3<<30 | 0x45<<21 | 0x1f<<10,
   178  	ACASW:   2<<30 | 0x45<<21 | 0x1f<<10,
   179  	ACASH:   1<<30 | 0x45<<21 | 0x1f<<10,
   180  	ACASB:   0<<30 | 0x45<<21 | 0x1f<<10,
   181  	ACASAD:  3<<30 | 0x47<<21 | 0x1f<<10,
   182  	ACASAW:  2<<30 | 0x47<<21 | 0x1f<<10,
   183  	ACASLD:  3<<30 | 0x45<<21 | 0x3f<<10,
   184  	ACASLW:  2<<30 | 0x45<<21 | 0x3f<<10,
   185  	ACASALD: 3<<30 | 0x47<<21 | 0x3f<<10,
   186  	ACASALW: 2<<30 | 0x47<<21 | 0x3f<<10,
   187  	ACASALH: 1<<30 | 0x47<<21 | 0x3f<<10,
   188  	ACASALB: 0<<30 | 0x47<<21 | 0x3f<<10,
   189  }
   190  var atomicCASP = map[obj.As]uint32{
   191  	ACASPD: 1<<30 | 0x41<<21 | 0x1f<<10,
   192  	ACASPW: 0<<30 | 0x41<<21 | 0x1f<<10,
   193  }
   194  
   195  var oprange [ALAST & obj.AMask][]Optab
   196  
   197  var xcmp [C_NCLASS][C_NCLASS]bool
   198  
   199  const (
   200  	S32     = 0 << 31
   201  	S64     = 1 << 31
   202  	Sbit    = 1 << 29
   203  	LSL0_32 = 2 << 13
   204  	LSL0_64 = 3 << 13
   205  )
   206  
   207  func OPDP2(x uint32) uint32 {
   208  	return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
   209  }
   210  
   211  func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
   212  	return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
   213  }
   214  
   215  func OPBcc(x uint32) uint32 {
   216  	return 0x2A<<25 | 0<<24 | 0<<4 | x&15
   217  }
   218  
   219  func OPBLR(x uint32) uint32 {
   220  	/* x=0, JMP; 1, CALL; 2, RET */
   221  	return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
   222  }
   223  
   224  func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
   225  	return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
   226  }
   227  
   228  func SYSHINT(x uint32) uint32 {
   229  	return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
   230  }
   231  
   232  func LDSTR(sz uint32, v uint32, opc uint32) uint32 {
   233  	return sz<<30 | 7<<27 | v<<26 | opc<<22
   234  }
   235  
   236  func LD2STR(o uint32) uint32 {
   237  	return o &^ (3 << 22)
   238  }
   239  
   240  func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
   241  	return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
   242  }
   243  
   244  func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
   245  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
   246  }
   247  
   248  func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   249  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
   250  }
   251  
   252  func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   253  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
   254  }
   255  
   256  func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   257  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
   258  }
   259  
   260  func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
   261  	return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
   262  }
   263  
   264  func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
   265  	return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
   266  }
   267  
   268  func ADR(p uint32, o uint32, rt uint32) uint32 {
   269  	return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
   270  }
   271  
   272  func OPBIT(x uint32) uint32 {
   273  	return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
   274  }
   275  
   276  func MOVCONST(d int64, s int, rt int) uint32 {
   277  	return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
   278  }
   279  
   280  const (
   281  	// Optab.flag
   282  	LFROM     = 1 << 0 // p.From uses constant pool
   283  	LFROM128  = 1 << 1 // p.From3<<64+p.From forms a 128-bit constant in literal pool
   284  	LTO       = 1 << 2 // p.To uses constant pool
   285  	NOTUSETMP = 1 << 3 // p expands to multiple instructions, but does NOT use REGTMP
   286  )
   287  
   288  var optab = []Optab{
   289  	/* struct Optab:
   290  	OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */
   291  	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
   292  
   293  	/* arithmetic operations */
   294  	{AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   295  	{AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   296  	{AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   297  	{AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   298  	{ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
   299  	{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
   300  	{ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0},
   301  	{ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
   302  	{AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0},
   303  	{AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0},
   304  	{ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0},
   305  	{AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   306  	{AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   307  	{ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   308  	{AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   309  	{AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   310  	{ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   311  	{AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
   312  	{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
   313  	{AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
   314  	{AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
   315  	{AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
   316  	{AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
   317  	{AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
   318  	{AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
   319  	{ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
   320  	{ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
   321  	{ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
   322  	{AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   323  	{AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   324  	{AADD, C_SHIFT, C_RSP, C_NONE, C_RSP, 26, 4, 0, 0, 0},
   325  	{AADD, C_SHIFT, C_NONE, C_NONE, C_RSP, 26, 4, 0, 0, 0},
   326  	{AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   327  	{ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
   328  	{ACMP, C_SHIFT, C_RSP, C_NONE, C_NONE, 26, 4, 0, 0, 0},
   329  	{ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   330  	{AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   331  	{AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   332  	{ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
   333  	{AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   334  	{AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   335  	{ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
   336  	{AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   337  	{AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   338  	{AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
   339  	{AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0},
   340  	{AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
   341  	{AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0},
   342  	{AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0},
   343  	{ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   344  	{ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   345  
   346  	{AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   347  	{AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   348  	{AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0},
   349  	{AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
   350  	{AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
   351  	{AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   352  	{AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   353  	{AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
   354  	{AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0},
   355  	{AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0},
   356  
   357  	/* logical operations */
   358  	{AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   359  	{AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   360  	{AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   361  	{AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
   362  	{ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
   363  	{AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
   364  	{AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   365  	{AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
   366  	{AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   367  	{ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
   368  	{AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
   369  	{AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   370  	{AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
   371  	{AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
   372  	{ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
   373  	{AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
   374  	{AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
   375  	{AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
   376  	{AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
   377  	{ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
   378  	{AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
   379  	{AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
   380  	{AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
   381  	{AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
   382  	{AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
   383  	{AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
   384  	{AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
   385  	{AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
   386  	{AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
   387  	{AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
   388  	{AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
   389  	{AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
   390  	{ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
   391  	{ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
   392  	{ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
   393  	{AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   394  	{AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   395  	{AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
   396  	{AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
   397  	{ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
   398  	{AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0},
   399  	{AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0},
   400  	{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   401  	{AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   402  	{AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */
   403  	{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */
   404  	/* TODO: MVN C_SHIFT */
   405  
   406  	/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
   407  	{AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   408  	{AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
   409  	{AMOVW, C_BITCON, C_NONE, C_NONE, C_RSP, 32, 4, 0, 0, 0},
   410  	{AMOVD, C_BITCON, C_NONE, C_NONE, C_RSP, 32, 4, 0, 0, 0},
   411  	{AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
   412  	{AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
   413  	{AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, NOTUSETMP, 0},
   414  	{AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, NOTUSETMP, 0},
   415  
   416  	{AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
   417  	{AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0},
   418  	{AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0},
   419  
   420  	/* load long effective stack address (load int32 offset and add) */
   421  	{AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0},
   422  
   423  	// Move a large constant to a vector register.
   424  	{AVMOVQ, C_VCON, C_NONE, C_VCON, C_VREG, 101, 4, 0, LFROM128, 0},
   425  	{AVMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
   426  	{AVMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
   427  
   428  	/* jump operations */
   429  	{AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   430  	{ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   431  	{AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   432  	{ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   433  	{ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   434  	{ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   435  	{obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   436  	{obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   437  	{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
   438  	{ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
   439  	{ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0},
   440  	{AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
   441  
   442  	// get a PC-relative address
   443  	{AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0},
   444  	{AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0},
   445  
   446  	{ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
   447  	{ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
   448  	{ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0},
   449  	{ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0},
   450  	{AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0},
   451  	{ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
   452  	{ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0},
   453  	{ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0},
   454  	{ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0},
   455  	{ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0},
   456  	{ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
   457  	{ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   458  	{ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   459  	{ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0},
   460  	{ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0},
   461  	{ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0},
   462  	{ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0},
   463  	{AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
   464  	{AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
   465  	{AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
   466  	{AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
   467  	{AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
   468  	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   469  	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   470  	{AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   471  	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   472  	{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   473  	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   474  	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   475  	{AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   476  	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   477  	{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
   478  	{AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0},
   479  	{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0},
   480  	{AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0},
   481  
   482  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   483  	{AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   484  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   485  	{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   486  	{AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   487  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   488  	{AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
   489  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   490  	{AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   491  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   492  	{AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   493  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   494  	{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
   495  	{ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   496  	{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   497  	{AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
   498  	{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
   499  	{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
   500  	{AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
   501  	{AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
   502  	{AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   503  	{AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
   504  	{AVDUP, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
   505  	{AVDUP, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
   506  	{AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
   507  	{AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   508  	{AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
   509  	{AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
   510  	{AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
   511  	{AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
   512  	{AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
   513  	{AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
   514  	{AVUADDW, C_ARNG, C_ARNG, C_NONE, C_ARNG, 105, 4, 0, 0, 0},
   515  
   516  	/* conditional operations */
   517  	{ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0},
   518  	{ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0},
   519  	{ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0},
   520  	{AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
   521  	{ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0},
   522  	{ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
   523  	{AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
   524  
   525  	/* scaled 12-bit unsigned displacement store */
   526  	{AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   527  	{AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   528  	{AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   529  	{AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   530  	{AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
   531  	{AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
   532  	{AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   533  	{AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   534  	{AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   535  	{AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   536  
   537  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   538  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   539  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   540  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   541  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_UAUTO64K, 20, 4, REGSP, 0, 0},
   542  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_UOREG64K, 20, 4, 0, 0, 0},
   543  
   544  	/* unscaled 9-bit signed displacement store */
   545  	{AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   546  	{AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   547  	{AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   548  	{AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   549  	{AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   550  	{AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   551  	{AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   552  	{AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   553  	{AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   554  	{AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   555  
   556  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   557  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   558  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   559  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   560  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   561  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   562  
   563  	/* scaled 12-bit unsigned displacement load */
   564  	{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   565  	{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   566  	{AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   567  	{AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   568  	{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   569  	{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   570  	{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   571  	{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   572  	{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   573  	{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   574  
   575  	{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   576  	{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   577  	{AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   578  	{AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   579  	{AFMOVQ, C_UAUTO64K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   580  	{AFMOVQ, C_UOREG64K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   581  
   582  	/* unscaled 9-bit signed displacement load */
   583  	{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   584  	{AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   585  	{AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   586  	{AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   587  	{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   588  	{AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   589  	{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   590  	{AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   591  	{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   592  	{AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
   593  
   594  	{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   595  	{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   596  	{AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   597  	{AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   598  	{AFMOVQ, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   599  	{AFMOVQ, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   600  
   601  	/* long displacement store */
   602  	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   603  	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   604  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   605  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   606  	{AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   607  	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   608  	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   609  	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   610  	{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   611  	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   612  
   613  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   614  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   615  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   616  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   617  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   618  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   619  
   620  	/* long displacement load */
   621  	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   622  	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   623  	{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   624  	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   625  	{AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   626  	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   627  	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   628  	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   629  	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   630  	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   631  
   632  	{AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   633  	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   634  	{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   635  	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   636  	{AFMOVQ, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   637  	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   638  
   639  	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
   640  	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   641  	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   642  	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   643  	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   644  	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   645  	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   646  	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   647  	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   648  
   649  	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   650  	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   651  	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   652  	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   653  	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   654  	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   655  	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   656  	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   657  
   658  	/* pre/post-indexed store (unscaled, signed 9-bit offset) */
   659  	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   660  	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   661  	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   662  	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   663  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   664  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   665  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   666  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   667  
   668  	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   669  	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   670  	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   671  	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   672  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   673  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   674  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   675  	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   676  
   677  	/* load with shifted or extended register offset */
   678  	{AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   679  	{AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   680  	{AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   681  	{AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   682  	{AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
   683  	{AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
   684  	{AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
   685  
   686  	/* store with extended register offset */
   687  	{AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   688  	{AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   689  	{AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   690  	{AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   691  	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   692  	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
   693  
   694  	/* pre/post-indexed/signed-offset load/store register pair
   695  	   (unscaled, signed 10-bit quad-aligned and long offset) */
   696  	{AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   697  	{AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   698  	{AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   699  	{AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   700  	{AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   701  	{AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   702  	{AFLDPQ, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   703  	{AFLDPQ, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   704  	{AFLDPQ, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   705  	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   706  	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   707  	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   708  	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   709  	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   710  	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   711  	{AFLDPQ, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   712  	{AFLDPQ, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   713  	{AFLDPQ, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   714  	{AFLDPQ, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   715  
   716  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, 0},
   717  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, C_XPRE},
   718  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, C_XPOST},
   719  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, 0},
   720  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, C_XPRE},
   721  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, C_XPOST},
   722  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   723  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
   724  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   725  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, 0},
   726  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, C_XPRE},
   727  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, C_XPOST},
   728  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, 0},
   729  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, C_XPRE},
   730  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, C_XPOST},
   731  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   732  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
   733  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   734  	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   735  
   736  	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   737  	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   738  	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   739  	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   740  	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   741  	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   742  	{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   743  	{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   744  	{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   745  	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   746  	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   747  	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   748  	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   749  	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   750  	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   751  	{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   752  	{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   753  	{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   754  	{ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   755  
   756  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
   757  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
   758  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
   759  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
   760  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
   761  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
   762  	{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   763  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
   764  	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   765  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
   766  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
   767  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
   768  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
   769  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
   770  	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
   771  	{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   772  	{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
   773  	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   774  	{ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   775  
   776  	// differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
   777  	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   778  	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   779  	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   780  	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   781  	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   782  	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   783  	{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   784  	{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   785  	{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   786  	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   787  	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   788  	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   789  	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   790  	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   791  	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   792  	{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   793  	{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   794  	{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   795  	{ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   796  
   797  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
   798  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
   799  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
   800  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
   801  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
   802  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
   803  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   804  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
   805  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   806  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
   807  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
   808  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
   809  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
   810  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
   811  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
   812  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   813  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
   814  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   815  	{ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   816  
   817  	{ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0},        // RegTo2=C_REG
   818  	{ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0},    // RegTo2=C_REG
   819  	{ACASPD, C_PAIR, C_NONE, C_NONE, C_ZOREG, 106, 4, 0, 0, 0},     // RegTo2=C_REGREG
   820  	{ACASPD, C_PAIR, C_NONE, C_NONE, C_ZAUTO, 106, 4, REGSP, 0, 0}, // RegTo2=C_REGREG
   821  	{ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   822  	{ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   823  	{ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
   824  	{ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
   825  	{ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_NONE
   826  	{ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_REG
   827  	{ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
   828  	{ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
   829  
   830  	/* VLD[1-4]/VST[1-4] */
   831  	{AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
   832  	{AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   833  	{AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   834  	{AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
   835  	{AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   836  	{AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   837  	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
   838  	{AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
   839  	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
   840  	{AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   841  	{AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   842  	{AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   843  	{AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   844  	{AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   845  	{AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   846  	{AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   847  	{AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   848  	{AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   849  	{AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   850  	{AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   851  	{AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   852  	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
   853  	{AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
   854  	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
   855  
   856  	/* special */
   857  	{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
   858  	{AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
   859  	{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   860  	{AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   861  	{AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   862  	{AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   863  	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0},
   864  	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
   865  	{ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
   866  	{AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
   867  	{ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
   868  	{ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0},
   869  	{ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0},
   870  
   871  	/* encryption instructions */
   872  	{AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
   873  	{AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
   874  	{ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   875  	{ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   876  	{ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0},
   877  	{ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0},
   878  	{ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
   879  	{AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   880  	{AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0},
   881  	{AVEOR3, C_ARNG, C_ARNG, C_ARNG, C_ARNG, 103, 4, 0, 0, 0},
   882  	{AVXAR, C_VCON, C_ARNG, C_ARNG, C_ARNG, 104, 4, 0, 0, 0},
   883  
   884  	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
   885  	{obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
   886  	{obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
   887  	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   888  	{obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
   889  	{obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   890  	{obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   891  	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   892  	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   893  	{obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},  // align code
   894  
   895  	{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
   896  }
   897  
   898  /*
   899   * valid pstate field values, and value to use in instruction
   900   */
   901  var pstatefield = []struct {
   902  	reg int16
   903  	enc uint32
   904  }{
   905  	{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
   906  	{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
   907  	{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
   908  }
   909  
   910  var prfopfield = []struct {
   911  	reg int16
   912  	enc uint32
   913  }{
   914  	{REG_PLDL1KEEP, 0},
   915  	{REG_PLDL1STRM, 1},
   916  	{REG_PLDL2KEEP, 2},
   917  	{REG_PLDL2STRM, 3},
   918  	{REG_PLDL3KEEP, 4},
   919  	{REG_PLDL3STRM, 5},
   920  	{REG_PLIL1KEEP, 8},
   921  	{REG_PLIL1STRM, 9},
   922  	{REG_PLIL2KEEP, 10},
   923  	{REG_PLIL2STRM, 11},
   924  	{REG_PLIL3KEEP, 12},
   925  	{REG_PLIL3STRM, 13},
   926  	{REG_PSTL1KEEP, 16},
   927  	{REG_PSTL1STRM, 17},
   928  	{REG_PSTL2KEEP, 18},
   929  	{REG_PSTL2STRM, 19},
   930  	{REG_PSTL3KEEP, 20},
   931  	{REG_PSTL3STRM, 21},
   932  }
   933  
   934  // Used for padinng NOOP instruction
   935  const OP_NOOP = 0xd503201f
   936  
   937  // align code to a certain length by padding bytes.
   938  func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int {
   939  	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
   940  		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
   941  	}
   942  	return int(-pc & (alignedValue - 1))
   943  }
   944  
   945  func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   946  	if ctxt.Retpoline {
   947  		ctxt.Diag("-spectre=ret not supported on arm64")
   948  		ctxt.Retpoline = false // don't keep printing
   949  	}
   950  
   951  	p := cursym.Func().Text
   952  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   953  		return
   954  	}
   955  
   956  	if oprange[AAND&obj.AMask] == nil {
   957  		ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
   958  	}
   959  
   960  	c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
   961  	p.To.Offset &= 0xffffffff // extrasize is no longer needed
   962  
   963  	bflag := 1
   964  	pc := int64(0)
   965  	p.Pc = pc
   966  	var m int
   967  	var o *Optab
   968  	for p = p.Link; p != nil; p = p.Link {
   969  		if p.As == ADWORD && (pc&7) != 0 {
   970  			pc += 4
   971  		}
   972  		p.Pc = pc
   973  		o = c.oplook(p)
   974  		m = int(o.size)
   975  		if m == 0 {
   976  			switch p.As {
   977  			case obj.APCALIGN:
   978  				alignedValue := p.From.Offset
   979  				m = pcAlignPadLength(pc, alignedValue, ctxt)
   980  				// Update the current text symbol alignment value.
   981  				if int32(alignedValue) > cursym.Func().Align {
   982  					cursym.Func().Align = int32(alignedValue)
   983  				}
   984  				break
   985  			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
   986  				continue
   987  			default:
   988  				c.ctxt.Diag("zero-width instruction\n%v", p)
   989  			}
   990  		}
   991  		if o.flag&LFROM != 0 {
   992  			c.addpool(p, &p.From)
   993  		}
   994  		if o.flag&LFROM128 != 0 {
   995  			c.addpool128(p, &p.From, p.GetFrom3())
   996  		}
   997  		if o.flag&LTO != 0 {
   998  			c.addpool(p, &p.To)
   999  		}
  1000  
  1001  		if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
  1002  			c.checkpool(p, 0)
  1003  		}
  1004  		pc += int64(m)
  1005  		if c.blitrl != nil {
  1006  			c.checkpool(p, 1)
  1007  		}
  1008  	}
  1009  
  1010  	c.cursym.Size = pc
  1011  
  1012  	/*
  1013  	 * if any procedure is large enough to
  1014  	 * generate a large SBRA branch, then
  1015  	 * generate extra passes putting branches
  1016  	 * around jmps to fix. this is rare.
  1017  	 */
  1018  	for bflag != 0 {
  1019  		bflag = 0
  1020  		pc = 0
  1021  		for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
  1022  			if p.As == ADWORD && (pc&7) != 0 {
  1023  				pc += 4
  1024  			}
  1025  			p.Pc = pc
  1026  			o = c.oplook(p)
  1027  
  1028  			/* very large branches */
  1029  			if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.To.Target() != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
  1030  				otxt := p.To.Target().Pc - pc
  1031  				var toofar bool
  1032  				switch o.type_ {
  1033  				case 7, 39: // branch instruction encodes 19 bits
  1034  					toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
  1035  				case 40: // branch instruction encodes 14 bits
  1036  					toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
  1037  				}
  1038  				if toofar {
  1039  					q := c.newprog()
  1040  					q.Link = p.Link
  1041  					p.Link = q
  1042  					q.As = AB
  1043  					q.To.Type = obj.TYPE_BRANCH
  1044  					q.To.SetTarget(p.To.Target())
  1045  					p.To.SetTarget(q)
  1046  					q = c.newprog()
  1047  					q.Link = p.Link
  1048  					p.Link = q
  1049  					q.As = AB
  1050  					q.To.Type = obj.TYPE_BRANCH
  1051  					q.To.SetTarget(q.Link.Link)
  1052  					bflag = 1
  1053  				}
  1054  			}
  1055  			m = int(o.size)
  1056  
  1057  			if m == 0 {
  1058  				switch p.As {
  1059  				case obj.APCALIGN:
  1060  					alignedValue := p.From.Offset
  1061  					m = pcAlignPadLength(pc, alignedValue, ctxt)
  1062  					break
  1063  				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
  1064  					continue
  1065  				default:
  1066  					c.ctxt.Diag("zero-width instruction\n%v", p)
  1067  				}
  1068  			}
  1069  
  1070  			pc += int64(m)
  1071  		}
  1072  	}
  1073  
  1074  	pc += -pc & (funcAlign - 1)
  1075  	c.cursym.Size = pc
  1076  
  1077  	/*
  1078  	 * lay out the code, emitting code and data relocations.
  1079  	 */
  1080  	c.cursym.Grow(c.cursym.Size)
  1081  	bp := c.cursym.P
  1082  	psz := int32(0)
  1083  	var i int
  1084  	var out [6]uint32
  1085  	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
  1086  		c.pc = p.Pc
  1087  		o = c.oplook(p)
  1088  
  1089  		// need to align DWORDs on 8-byte boundary. The ISA doesn't
  1090  		// require it, but the various 64-bit loads we generate assume it.
  1091  		if o.as == ADWORD && psz%8 != 0 {
  1092  			bp[3] = 0
  1093  			bp[2] = bp[3]
  1094  			bp[1] = bp[2]
  1095  			bp[0] = bp[1]
  1096  			bp = bp[4:]
  1097  			psz += 4
  1098  		}
  1099  
  1100  		if int(o.size) > 4*len(out) {
  1101  			log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
  1102  		}
  1103  		if p.As == obj.APCALIGN {
  1104  			alignedValue := p.From.Offset
  1105  			v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt)
  1106  			for i = 0; i < int(v/4); i++ {
  1107  				// emit ANOOP instruction by the padding size
  1108  				c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
  1109  				bp = bp[4:]
  1110  				psz += 4
  1111  			}
  1112  		} else {
  1113  			c.asmout(p, o, out[:])
  1114  			for i = 0; i < int(o.size/4); i++ {
  1115  				c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
  1116  				bp = bp[4:]
  1117  				psz += 4
  1118  			}
  1119  		}
  1120  	}
  1121  
  1122  	// Mark nonpreemptible instruction sequences.
  1123  	// We use REGTMP as a scratch register during call injection,
  1124  	// so instruction sequences that use REGTMP are unsafe to
  1125  	// preempt asynchronously.
  1126  	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
  1127  }
  1128  
  1129  // isUnsafePoint returns whether p is an unsafe point.
  1130  func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
  1131  	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
  1132  	// preemption sequence clobbers REGTMP.
  1133  	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
  1134  }
  1135  
  1136  // isRestartable returns whether p is a multi-instruction sequence that,
  1137  // if preempted, can be restarted.
  1138  func (c *ctxt7) isRestartable(p *obj.Prog) bool {
  1139  	if c.isUnsafePoint(p) {
  1140  		return false
  1141  	}
  1142  	// If p is a multi-instruction sequence with uses REGTMP inserted by
  1143  	// the assembler in order to materialize a large constant/offset, we
  1144  	// can restart p (at the start of the instruction sequence), recompute
  1145  	// the content of REGTMP, upon async preemption. Currently, all cases
  1146  	// of assembler-inserted REGTMP fall into this category.
  1147  	// If p doesn't use REGTMP, it can be simply preempted, so we don't
  1148  	// mark it.
  1149  	o := c.oplook(p)
  1150  	return o.size > 4 && o.flag&NOTUSETMP == 0
  1151  }
  1152  
  1153  /*
  1154   * when the first reference to the literal pool threatens
  1155   * to go out of range of a 1Mb PC-relative offset
  1156   * drop the pool now, and branch round it.
  1157   */
  1158  func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
  1159  	if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
  1160  		c.flushpool(p, skip)
  1161  	} else if p.Link == nil {
  1162  		c.flushpool(p, 2)
  1163  	}
  1164  }
  1165  
  1166  func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
  1167  	if c.blitrl != nil {
  1168  		if skip != 0 {
  1169  			if c.ctxt.Debugvlog && skip == 1 {
  1170  				fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
  1171  			}
  1172  			q := c.newprog()
  1173  			q.As = AB
  1174  			q.To.Type = obj.TYPE_BRANCH
  1175  			q.To.SetTarget(p.Link)
  1176  			q.Link = c.blitrl
  1177  			q.Pos = p.Pos
  1178  			c.blitrl = q
  1179  		} else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
  1180  			return
  1181  		}
  1182  
  1183  		// The line number for constant pool entries doesn't really matter.
  1184  		// We set it to the line number of the preceding instruction so that
  1185  		// there are no deltas to encode in the pc-line tables.
  1186  		for q := c.blitrl; q != nil; q = q.Link {
  1187  			q.Pos = p.Pos
  1188  		}
  1189  
  1190  		c.elitrl.Link = p.Link
  1191  		p.Link = c.blitrl
  1192  
  1193  		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
  1194  		c.elitrl = nil
  1195  		c.pool.size = 0
  1196  		c.pool.start = 0
  1197  	}
  1198  }
  1199  
  1200  // addpool128 adds a 128-bit constant to literal pool by two consecutive DWORD
  1201  // instructions, the 128-bit constant is formed by ah.Offset<<64+al.Offset.
  1202  func (c *ctxt7) addpool128(p *obj.Prog, al, ah *obj.Addr) {
  1203  	q := c.newprog()
  1204  	q.As = ADWORD
  1205  	q.To.Type = obj.TYPE_CONST
  1206  	q.To.Offset = al.Offset
  1207  
  1208  	t := c.newprog()
  1209  	t.As = ADWORD
  1210  	t.To.Type = obj.TYPE_CONST
  1211  	t.To.Offset = ah.Offset
  1212  
  1213  	q.Link = t
  1214  
  1215  	if c.blitrl == nil {
  1216  		c.blitrl = q
  1217  		c.pool.start = uint32(p.Pc)
  1218  	} else {
  1219  		c.elitrl.Link = q
  1220  	}
  1221  
  1222  	c.elitrl = t
  1223  	c.pool.size = roundUp(c.pool.size, 16)
  1224  	c.pool.size += 16
  1225  	p.Pool = q
  1226  }
  1227  
  1228  /*
  1229   * MOVD foo(SB), R is actually
  1230   *   MOVD addr, REGTMP
  1231   *   MOVD REGTMP, R
  1232   * where addr is the address of the DWORD containing the address of foo.
  1233   *
  1234   * TODO: hash
  1235   */
  1236  func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
  1237  	cls := c.aclass(a)
  1238  	lit := c.instoffset
  1239  	t := c.newprog()
  1240  	t.As = AWORD
  1241  	sz := 4
  1242  
  1243  	if a.Type == obj.TYPE_CONST {
  1244  		if (lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit))) || p.As == AVMOVQ || p.As == AVMOVD {
  1245  			// out of range -0x80000000 ~ 0xffffffff or VMOVQ or VMOVD operand, must store 64-bit.
  1246  			t.As = ADWORD
  1247  			sz = 8
  1248  		} // else store 32-bit
  1249  	} else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) {
  1250  		// conservative: don't know if we want signed or unsigned extension.
  1251  		// in case of ambiguity, store 64-bit
  1252  		t.As = ADWORD
  1253  		sz = 8
  1254  	}
  1255  
  1256  	t.To.Type = obj.TYPE_CONST
  1257  	t.To.Offset = lit
  1258  
  1259  	for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
  1260  		if q.To == t.To {
  1261  			p.Pool = q
  1262  			return
  1263  		}
  1264  	}
  1265  
  1266  	q := c.newprog()
  1267  	*q = *t
  1268  	if c.blitrl == nil {
  1269  		c.blitrl = q
  1270  		c.pool.start = uint32(p.Pc)
  1271  	} else {
  1272  		c.elitrl.Link = q
  1273  	}
  1274  	c.elitrl = q
  1275  	if q.As == ADWORD {
  1276  		// make DWORD 8-byte aligned, this is not required by ISA,
  1277  		// just to avoid performance penalties when loading from
  1278  		// the constant pool across a cache line.
  1279  		c.pool.size = roundUp(c.pool.size, 8)
  1280  	}
  1281  	c.pool.size += uint32(sz)
  1282  	p.Pool = q
  1283  }
  1284  
  1285  // roundUp rounds up x to "to".
  1286  func roundUp(x, to uint32) uint32 {
  1287  	if to == 0 || to&(to-1) != 0 {
  1288  		log.Fatalf("rounded up to a value that is not a power of 2: %d\n", to)
  1289  	}
  1290  	return (x + to - 1) &^ (to - 1)
  1291  }
  1292  
  1293  func (c *ctxt7) regoff(a *obj.Addr) uint32 {
  1294  	c.instoffset = 0
  1295  	c.aclass(a)
  1296  	return uint32(c.instoffset)
  1297  }
  1298  
  1299  func isSTLXRop(op obj.As) bool {
  1300  	switch op {
  1301  	case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
  1302  		ASTXR, ASTXRW, ASTXRB, ASTXRH:
  1303  		return true
  1304  	}
  1305  	return false
  1306  }
  1307  
  1308  func isSTXPop(op obj.As) bool {
  1309  	switch op {
  1310  	case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
  1311  		return true
  1312  	}
  1313  	return false
  1314  }
  1315  
  1316  func isANDop(op obj.As) bool {
  1317  	switch op {
  1318  	case AAND, AORR, AEOR, AANDS, ATST,
  1319  		ABIC, AEON, AORN, ABICS:
  1320  		return true
  1321  	}
  1322  	return false
  1323  }
  1324  
  1325  func isANDWop(op obj.As) bool {
  1326  	switch op {
  1327  	case AANDW, AORRW, AEORW, AANDSW, ATSTW,
  1328  		ABICW, AEONW, AORNW, ABICSW:
  1329  		return true
  1330  	}
  1331  	return false
  1332  }
  1333  
  1334  func isADDop(op obj.As) bool {
  1335  	switch op {
  1336  	case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
  1337  		return true
  1338  	}
  1339  	return false
  1340  }
  1341  
  1342  func isADDWop(op obj.As) bool {
  1343  	switch op {
  1344  	case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
  1345  		return true
  1346  	}
  1347  	return false
  1348  }
  1349  
  1350  func isADDSop(op obj.As) bool {
  1351  	switch op {
  1352  	case AADDS, AADDSW, ASUBS, ASUBSW:
  1353  		return true
  1354  	}
  1355  	return false
  1356  }
  1357  
  1358  func isNEGop(op obj.As) bool {
  1359  	switch op {
  1360  	case ANEG, ANEGW, ANEGS, ANEGSW:
  1361  		return true
  1362  	}
  1363  	return false
  1364  }
  1365  
  1366  func isRegShiftOrExt(a *obj.Addr) bool {
  1367  	return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
  1368  }
  1369  
  1370  // Maximum PC-relative displacement.
  1371  // The actual limit is ±2²⁰, but we are conservative
  1372  // to avoid needing to recompute the literal pool flush points
  1373  // as span-dependent jumps are enlarged.
  1374  const maxPCDisp = 512 * 1024
  1375  
  1376  // ispcdisp reports whether v is a valid PC-relative displacement.
  1377  func ispcdisp(v int32) bool {
  1378  	return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
  1379  }
  1380  
  1381  func isaddcon(v int64) bool {
  1382  	/* uimm12 or uimm24? */
  1383  	if v < 0 {
  1384  		return false
  1385  	}
  1386  	if (v & 0xFFF) == 0 {
  1387  		v >>= 12
  1388  	}
  1389  	return v <= 0xFFF
  1390  }
  1391  
  1392  func isaddcon2(v int64) bool {
  1393  	return 0 <= v && v <= 0xFFFFFF
  1394  }
  1395  
  1396  // isbitcon reports whether a constant can be encoded into a logical instruction.
  1397  // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
  1398  // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
  1399  // special cases: 0 and -1 are not bitcon.
  1400  // this function needs to run against virtually all the constants, so it needs to be fast.
  1401  // for this reason, bitcon testing and bitcon encoding are separate functions.
  1402  func isbitcon(x uint64) bool {
  1403  	if x == 1<<64-1 || x == 0 {
  1404  		return false
  1405  	}
  1406  	// determine the period and sign-extend a unit to 64 bits
  1407  	switch {
  1408  	case x != x>>32|x<<32:
  1409  		// period is 64
  1410  		// nothing to do
  1411  	case x != x>>16|x<<48:
  1412  		// period is 32
  1413  		x = uint64(int64(int32(x)))
  1414  	case x != x>>8|x<<56:
  1415  		// period is 16
  1416  		x = uint64(int64(int16(x)))
  1417  	case x != x>>4|x<<60:
  1418  		// period is 8
  1419  		x = uint64(int64(int8(x)))
  1420  	default:
  1421  		// period is 4 or 2, always true
  1422  		// 0001, 0010, 0100, 1000 -- 0001 rotate
  1423  		// 0011, 0110, 1100, 1001 -- 0011 rotate
  1424  		// 0111, 1011, 1101, 1110 -- 0111 rotate
  1425  		// 0101, 1010             -- 01   rotate, repeat
  1426  		return true
  1427  	}
  1428  	return sequenceOfOnes(x) || sequenceOfOnes(^x)
  1429  }
  1430  
  1431  // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
  1432  func sequenceOfOnes(x uint64) bool {
  1433  	y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
  1434  	y += x
  1435  	return (y-1)&y == 0
  1436  }
  1437  
  1438  // bitconEncode returns the encoding of a bitcon used in logical instructions
  1439  // x is known to be a bitcon
  1440  // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
  1441  // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
  1442  // it is encoded in logical instructions with 3 bitfields
  1443  // N (1 bit) : R (6 bits) : S (6 bits), where
  1444  // N=1           -- period=64
  1445  // N=0, S=0xxxxx -- period=32
  1446  // N=0, S=10xxxx -- period=16
  1447  // N=0, S=110xxx -- period=8
  1448  // N=0, S=1110xx -- period=4
  1449  // N=0, S=11110x -- period=2
  1450  // R is the shift amount, low bits of S = n-1
  1451  func bitconEncode(x uint64, mode int) uint32 {
  1452  	var period uint32
  1453  	// determine the period and sign-extend a unit to 64 bits
  1454  	switch {
  1455  	case x != x>>32|x<<32:
  1456  		period = 64
  1457  	case x != x>>16|x<<48:
  1458  		period = 32
  1459  		x = uint64(int64(int32(x)))
  1460  	case x != x>>8|x<<56:
  1461  		period = 16
  1462  		x = uint64(int64(int16(x)))
  1463  	case x != x>>4|x<<60:
  1464  		period = 8
  1465  		x = uint64(int64(int8(x)))
  1466  	case x != x>>2|x<<62:
  1467  		period = 4
  1468  		x = uint64(int64(x<<60) >> 60)
  1469  	default:
  1470  		period = 2
  1471  		x = uint64(int64(x<<62) >> 62)
  1472  	}
  1473  	neg := false
  1474  	if int64(x) < 0 {
  1475  		x = ^x
  1476  		neg = true
  1477  	}
  1478  	y := x & -x // lowest set bit of x.
  1479  	s := log2(y)
  1480  	n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
  1481  	if neg {
  1482  		// ^x is a sequence of n ones left shifted by s bits
  1483  		// adjust n, s for x
  1484  		s = n + s
  1485  		n = period - n
  1486  	}
  1487  
  1488  	N := uint32(0)
  1489  	if mode == 64 && period == 64 {
  1490  		N = 1
  1491  	}
  1492  	R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
  1493  	S := (n - 1) | 63&^(period<<1-1)                  // low bits = #ones - 1, high bits encodes period
  1494  	return N<<22 | R<<16 | S<<10
  1495  }
  1496  
  1497  func log2(x uint64) uint32 {
  1498  	if x == 0 {
  1499  		panic("log2 of 0")
  1500  	}
  1501  	n := uint32(0)
  1502  	if x >= 1<<32 {
  1503  		x >>= 32
  1504  		n += 32
  1505  	}
  1506  	if x >= 1<<16 {
  1507  		x >>= 16
  1508  		n += 16
  1509  	}
  1510  	if x >= 1<<8 {
  1511  		x >>= 8
  1512  		n += 8
  1513  	}
  1514  	if x >= 1<<4 {
  1515  		x >>= 4
  1516  		n += 4
  1517  	}
  1518  	if x >= 1<<2 {
  1519  		x >>= 2
  1520  		n += 2
  1521  	}
  1522  	if x >= 1<<1 {
  1523  		x >>= 1
  1524  		n += 1
  1525  	}
  1526  	return n
  1527  }
  1528  
  1529  func autoclass(l int64) int {
  1530  	if l == 0 {
  1531  		return C_ZAUTO
  1532  	}
  1533  
  1534  	if l < 0 {
  1535  		if l >= -256 && (l&15) == 0 {
  1536  			return C_NSAUTO_16
  1537  		}
  1538  		if l >= -256 && (l&7) == 0 {
  1539  			return C_NSAUTO_8
  1540  		}
  1541  		if l >= -256 && (l&3) == 0 {
  1542  			return C_NSAUTO_4
  1543  		}
  1544  		if l >= -256 {
  1545  			return C_NSAUTO
  1546  		}
  1547  		if l >= -512 && (l&15) == 0 {
  1548  			return C_NPAUTO_16
  1549  		}
  1550  		if l >= -512 && (l&7) == 0 {
  1551  			return C_NPAUTO
  1552  		}
  1553  		if l >= -1024 && (l&15) == 0 {
  1554  			return C_NQAUTO_16
  1555  		}
  1556  		if l >= -4095 {
  1557  			return C_NAUTO4K
  1558  		}
  1559  		return C_LAUTO
  1560  	}
  1561  
  1562  	if l <= 255 {
  1563  		if (l & 15) == 0 {
  1564  			return C_PSAUTO_16
  1565  		}
  1566  		if (l & 7) == 0 {
  1567  			return C_PSAUTO_8
  1568  		}
  1569  		if (l & 3) == 0 {
  1570  			return C_PSAUTO_4
  1571  		}
  1572  		return C_PSAUTO
  1573  	}
  1574  	if l <= 504 {
  1575  		if l&15 == 0 {
  1576  			return C_PPAUTO_16
  1577  		}
  1578  		if l&7 == 0 {
  1579  			return C_PPAUTO
  1580  		}
  1581  	}
  1582  	if l <= 1008 {
  1583  		if l&15 == 0 {
  1584  			return C_PQAUTO_16
  1585  		}
  1586  	}
  1587  	if l <= 4095 {
  1588  		if l&15 == 0 {
  1589  			return C_UAUTO4K_16
  1590  		}
  1591  		if l&7 == 0 {
  1592  			return C_UAUTO4K_8
  1593  		}
  1594  		if l&3 == 0 {
  1595  			return C_UAUTO4K_4
  1596  		}
  1597  		if l&1 == 0 {
  1598  			return C_UAUTO4K_2
  1599  		}
  1600  		return C_UAUTO4K
  1601  	}
  1602  	if l <= 8190 {
  1603  		if l&15 == 0 {
  1604  			return C_UAUTO8K_16
  1605  		}
  1606  		if l&7 == 0 {
  1607  			return C_UAUTO8K_8
  1608  		}
  1609  		if l&3 == 0 {
  1610  			return C_UAUTO8K_4
  1611  		}
  1612  		if l&1 == 0 {
  1613  			return C_UAUTO8K
  1614  		}
  1615  	}
  1616  	if l <= 16380 {
  1617  		if l&15 == 0 {
  1618  			return C_UAUTO16K_16
  1619  		}
  1620  		if l&7 == 0 {
  1621  			return C_UAUTO16K_8
  1622  		}
  1623  		if l&3 == 0 {
  1624  			return C_UAUTO16K
  1625  		}
  1626  	}
  1627  	if l <= 32760 {
  1628  		if l&15 == 0 {
  1629  			return C_UAUTO32K_16
  1630  		}
  1631  		if l&7 == 0 {
  1632  			return C_UAUTO32K
  1633  		}
  1634  	}
  1635  	if l <= 65520 && (l&15) == 0 {
  1636  		return C_UAUTO64K
  1637  	}
  1638  	return C_LAUTO
  1639  }
  1640  
  1641  func oregclass(l int64) int {
  1642  	return autoclass(l) - C_ZAUTO + C_ZOREG
  1643  }
  1644  
  1645  /*
  1646   * given an offset v and a class c (see above)
  1647   * return the offset value to use in the instruction,
  1648   * scaled if necessary
  1649   */
  1650  func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
  1651  	s := 0
  1652  	if cls >= C_SEXT1 && cls <= C_SEXT16 {
  1653  		s = cls - C_SEXT1
  1654  	} else {
  1655  		switch cls {
  1656  		case C_UAUTO4K, C_UOREG4K, C_ZOREG:
  1657  			s = 0
  1658  		case C_UAUTO8K, C_UOREG8K:
  1659  			s = 1
  1660  		case C_UAUTO16K, C_UOREG16K:
  1661  			s = 2
  1662  		case C_UAUTO32K, C_UOREG32K:
  1663  			s = 3
  1664  		case C_UAUTO64K, C_UOREG64K:
  1665  			s = 4
  1666  		default:
  1667  			c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
  1668  		}
  1669  	}
  1670  	vs := v >> uint(s)
  1671  	if vs<<uint(s) != v {
  1672  		c.ctxt.Diag("odd offset: %d\n%v", v, p)
  1673  	}
  1674  	return vs
  1675  }
  1676  
  1677  /*
  1678   * if v contains a single 16-bit value aligned
  1679   * on a 16-bit field, and thus suitable for movk/movn,
  1680   * return the field index 0 to 3; otherwise return -1
  1681   */
  1682  func movcon(v int64) int {
  1683  	for s := 0; s < 64; s += 16 {
  1684  		if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
  1685  			return s / 16
  1686  		}
  1687  	}
  1688  	return -1
  1689  }
  1690  
  1691  func rclass(r int16) int {
  1692  	switch {
  1693  	case REG_R0 <= r && r <= REG_R30: // not 31
  1694  		return C_REG
  1695  	case r == REGZERO:
  1696  		return C_ZCON
  1697  	case REG_F0 <= r && r <= REG_F31:
  1698  		return C_FREG
  1699  	case REG_V0 <= r && r <= REG_V31:
  1700  		return C_VREG
  1701  	case COND_EQ <= r && r <= COND_NV:
  1702  		return C_COND
  1703  	case r == REGSP:
  1704  		return C_RSP
  1705  	case r >= REG_ARNG && r < REG_ELEM:
  1706  		return C_ARNG
  1707  	case r >= REG_ELEM && r < REG_ELEM_END:
  1708  		return C_ELEM
  1709  	case r >= REG_UXTB && r < REG_SPECIAL:
  1710  		return C_EXTREG
  1711  	case r >= REG_SPECIAL:
  1712  		return C_SPR
  1713  	}
  1714  	return C_GOK
  1715  }
  1716  
  1717  // con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
  1718  // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
  1719  func (c *ctxt7) con32class(a *obj.Addr) int {
  1720  	v := uint32(a.Offset)
  1721  	if v == 0 {
  1722  		return C_ZCON
  1723  	}
  1724  	if isaddcon(int64(v)) {
  1725  		if v <= 0xFFF {
  1726  			if isbitcon(uint64(a.Offset)) {
  1727  				return C_ABCON0
  1728  			}
  1729  			return C_ADDCON0
  1730  		}
  1731  		if isbitcon(uint64(a.Offset)) {
  1732  			return C_ABCON
  1733  		}
  1734  		if movcon(int64(v)) >= 0 {
  1735  			return C_AMCON
  1736  		}
  1737  		if movcon(int64(^v)) >= 0 {
  1738  			return C_AMCON
  1739  		}
  1740  		return C_ADDCON
  1741  	}
  1742  
  1743  	t := movcon(int64(v))
  1744  	if t >= 0 {
  1745  		if isbitcon(uint64(a.Offset)) {
  1746  			return C_MBCON
  1747  		}
  1748  		return C_MOVCON
  1749  	}
  1750  
  1751  	t = movcon(int64(^v))
  1752  	if t >= 0 {
  1753  		if isbitcon(uint64(a.Offset)) {
  1754  			return C_MBCON
  1755  		}
  1756  		return C_MOVCON
  1757  	}
  1758  
  1759  	if isbitcon(uint64(a.Offset)) {
  1760  		return C_BITCON
  1761  	}
  1762  
  1763  	if 0 <= v && v <= 0xffffff {
  1764  		return C_ADDCON2
  1765  	}
  1766  	return C_LCON
  1767  }
  1768  
  1769  // con64class reclassifies the constant of C_VCON and C_LCON class.
  1770  func (c *ctxt7) con64class(a *obj.Addr) int {
  1771  	zeroCount := 0
  1772  	negCount := 0
  1773  	for i := uint(0); i < 4; i++ {
  1774  		immh := uint32(a.Offset >> (i * 16) & 0xffff)
  1775  		if immh == 0 {
  1776  			zeroCount++
  1777  		} else if immh == 0xffff {
  1778  			negCount++
  1779  		}
  1780  	}
  1781  	if zeroCount >= 3 || negCount >= 3 {
  1782  		return C_MOVCON
  1783  	} else if zeroCount == 2 || negCount == 2 {
  1784  		return C_MOVCON2
  1785  	} else if zeroCount == 1 || negCount == 1 {
  1786  		return C_MOVCON3
  1787  	} else {
  1788  		return C_VCON
  1789  	}
  1790  }
  1791  
  1792  func (c *ctxt7) aclass(a *obj.Addr) int {
  1793  	switch a.Type {
  1794  	case obj.TYPE_NONE:
  1795  		return C_NONE
  1796  
  1797  	case obj.TYPE_REG:
  1798  		return rclass(a.Reg)
  1799  
  1800  	case obj.TYPE_REGREG:
  1801  		return C_PAIR
  1802  
  1803  	case obj.TYPE_SHIFT:
  1804  		return C_SHIFT
  1805  
  1806  	case obj.TYPE_REGLIST:
  1807  		return C_LIST
  1808  
  1809  	case obj.TYPE_MEM:
  1810  		// The base register should be an integer register.
  1811  		if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
  1812  			break
  1813  		}
  1814  		switch a.Name {
  1815  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  1816  			if a.Sym == nil {
  1817  				break
  1818  			}
  1819  			c.instoffset = a.Offset
  1820  			if a.Sym != nil { // use relocation
  1821  				if a.Sym.Type == objabi.STLSBSS {
  1822  					if c.ctxt.Flag_shared {
  1823  						return C_TLS_IE
  1824  					} else {
  1825  						return C_TLS_LE
  1826  					}
  1827  				}
  1828  				return C_ADDR
  1829  			}
  1830  			return C_LEXT
  1831  
  1832  		case obj.NAME_GOTREF:
  1833  			return C_GOTADDR
  1834  
  1835  		case obj.NAME_AUTO:
  1836  			if a.Reg == REGSP {
  1837  				// unset base register for better printing, since
  1838  				// a.Offset is still relative to pseudo-SP.
  1839  				a.Reg = obj.REG_NONE
  1840  			}
  1841  			// The frame top 8 or 16 bytes are for FP
  1842  			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1843  			return autoclass(c.instoffset)
  1844  
  1845  		case obj.NAME_PARAM:
  1846  			if a.Reg == REGSP {
  1847  				// unset base register for better printing, since
  1848  				// a.Offset is still relative to pseudo-FP.
  1849  				a.Reg = obj.REG_NONE
  1850  			}
  1851  			c.instoffset = int64(c.autosize) + a.Offset + 8
  1852  			return autoclass(c.instoffset)
  1853  
  1854  		case obj.NAME_NONE:
  1855  			if a.Index != 0 {
  1856  				if a.Offset != 0 {
  1857  					if isRegShiftOrExt(a) {
  1858  						// extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
  1859  						return C_ROFF
  1860  					}
  1861  					return C_GOK
  1862  				}
  1863  				// register offset, (Rn)(Rm)
  1864  				return C_ROFF
  1865  			}
  1866  			c.instoffset = a.Offset
  1867  			return oregclass(c.instoffset)
  1868  		}
  1869  		return C_GOK
  1870  
  1871  	case obj.TYPE_FCONST:
  1872  		return C_FCON
  1873  
  1874  	case obj.TYPE_TEXTSIZE:
  1875  		return C_TEXTSIZE
  1876  
  1877  	case obj.TYPE_CONST, obj.TYPE_ADDR:
  1878  		switch a.Name {
  1879  		case obj.NAME_NONE:
  1880  			c.instoffset = a.Offset
  1881  			if a.Reg != 0 && a.Reg != REGZERO {
  1882  				break
  1883  			}
  1884  			v := c.instoffset
  1885  			if v == 0 {
  1886  				return C_ZCON
  1887  			}
  1888  			if isaddcon(v) {
  1889  				if v <= 0xFFF {
  1890  					if isbitcon(uint64(v)) {
  1891  						return C_ABCON0
  1892  					}
  1893  					return C_ADDCON0
  1894  				}
  1895  				if isbitcon(uint64(v)) {
  1896  					return C_ABCON
  1897  				}
  1898  				if movcon(v) >= 0 {
  1899  					return C_AMCON
  1900  				}
  1901  				if movcon(^v) >= 0 {
  1902  					return C_AMCON
  1903  				}
  1904  				return C_ADDCON
  1905  			}
  1906  
  1907  			t := movcon(v)
  1908  			if t >= 0 {
  1909  				if isbitcon(uint64(v)) {
  1910  					return C_MBCON
  1911  				}
  1912  				return C_MOVCON
  1913  			}
  1914  
  1915  			t = movcon(^v)
  1916  			if t >= 0 {
  1917  				if isbitcon(uint64(v)) {
  1918  					return C_MBCON
  1919  				}
  1920  				return C_MOVCON
  1921  			}
  1922  
  1923  			if isbitcon(uint64(v)) {
  1924  				return C_BITCON
  1925  			}
  1926  
  1927  			if 0 <= v && v <= 0xffffff {
  1928  				return C_ADDCON2
  1929  			}
  1930  
  1931  			if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
  1932  				return C_LCON
  1933  			}
  1934  			return C_VCON
  1935  
  1936  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  1937  			if a.Sym == nil {
  1938  				return C_GOK
  1939  			}
  1940  			if a.Sym.Type == objabi.STLSBSS {
  1941  				c.ctxt.Diag("taking address of TLS variable is not supported")
  1942  			}
  1943  			c.instoffset = a.Offset
  1944  			return C_VCONADDR
  1945  
  1946  		case obj.NAME_AUTO:
  1947  			if a.Reg == REGSP {
  1948  				// unset base register for better printing, since
  1949  				// a.Offset is still relative to pseudo-SP.
  1950  				a.Reg = obj.REG_NONE
  1951  			}
  1952  			// The frame top 8 or 16 bytes are for FP
  1953  			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1954  
  1955  		case obj.NAME_PARAM:
  1956  			if a.Reg == REGSP {
  1957  				// unset base register for better printing, since
  1958  				// a.Offset is still relative to pseudo-FP.
  1959  				a.Reg = obj.REG_NONE
  1960  			}
  1961  			c.instoffset = int64(c.autosize) + a.Offset + 8
  1962  		default:
  1963  			return C_GOK
  1964  		}
  1965  		cf := c.instoffset
  1966  		if isaddcon(cf) || isaddcon(-cf) {
  1967  			return C_AACON
  1968  		}
  1969  		if isaddcon2(cf) {
  1970  			return C_AACON2
  1971  		}
  1972  
  1973  		return C_LACON
  1974  
  1975  	case obj.TYPE_BRANCH:
  1976  		return C_SBRA
  1977  	}
  1978  
  1979  	return C_GOK
  1980  }
  1981  
  1982  func oclass(a *obj.Addr) int {
  1983  	return int(a.Class) - 1
  1984  }
  1985  
  1986  func (c *ctxt7) oplook(p *obj.Prog) *Optab {
  1987  	a1 := int(p.Optab)
  1988  	if a1 != 0 {
  1989  		return &optab[a1-1]
  1990  	}
  1991  	a1 = int(p.From.Class)
  1992  	if a1 == 0 {
  1993  		a0 := c.aclass(&p.From)
  1994  		// do not break C_ADDCON2 when S bit is set
  1995  		if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
  1996  			a0 = C_LCON
  1997  		}
  1998  		a1 = a0 + 1
  1999  		p.From.Class = int8(a1)
  2000  		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
  2001  			if p.As == AMOVW || isADDWop(p.As) || isANDWop(p.As) {
  2002  				// For 32-bit instruction with constant, we need to
  2003  				// treat its offset value as 32 bits to classify it.
  2004  				ra0 := c.con32class(&p.From)
  2005  				// do not break C_ADDCON2 when S bit is set
  2006  				if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
  2007  					ra0 = C_LCON
  2008  				}
  2009  				a1 = ra0 + 1
  2010  				p.From.Class = int8(a1)
  2011  			}
  2012  			if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
  2013  				// more specific classification of 64-bit integers
  2014  				a1 = c.con64class(&p.From) + 1
  2015  				p.From.Class = int8(a1)
  2016  			}
  2017  		}
  2018  	}
  2019  
  2020  	a1--
  2021  	a3 := C_NONE + 1
  2022  	if p.GetFrom3() != nil && p.RestArgs[0].Pos == 0 {
  2023  		a3 = int(p.GetFrom3().Class)
  2024  		if a3 == 0 {
  2025  			a3 = c.aclass(p.GetFrom3()) + 1
  2026  			p.GetFrom3().Class = int8(a3)
  2027  		}
  2028  	}
  2029  
  2030  	a3--
  2031  	a4 := int(p.To.Class)
  2032  	if a4 == 0 {
  2033  		a4 = c.aclass(&p.To) + 1
  2034  		p.To.Class = int8(a4)
  2035  	}
  2036  
  2037  	a4--
  2038  	a2 := C_NONE
  2039  	if p.Reg != 0 {
  2040  		a2 = rclass(p.Reg)
  2041  	}
  2042  
  2043  	if false {
  2044  		fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
  2045  		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  2046  	}
  2047  
  2048  	ops := oprange[p.As&obj.AMask]
  2049  	c1 := &xcmp[a1]
  2050  	c2 := &xcmp[a2]
  2051  	c3 := &xcmp[a3]
  2052  	c4 := &xcmp[a4]
  2053  	c5 := &xcmp[p.Scond>>5]
  2054  	for i := range ops {
  2055  		op := &ops[i]
  2056  		if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
  2057  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  2058  			return op
  2059  		}
  2060  	}
  2061  
  2062  	c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type)
  2063  	// Turn illegal instruction into an UNDEF, avoid crashing in asmout
  2064  	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
  2065  }
  2066  
  2067  func cmp(a int, b int) bool {
  2068  	if a == b {
  2069  		return true
  2070  	}
  2071  	switch a {
  2072  	case C_RSP:
  2073  		if b == C_REG {
  2074  			return true
  2075  		}
  2076  
  2077  	case C_REG:
  2078  		if b == C_ZCON {
  2079  			return true
  2080  		}
  2081  
  2082  	case C_ADDCON0:
  2083  		if b == C_ZCON || b == C_ABCON0 {
  2084  			return true
  2085  		}
  2086  
  2087  	case C_ADDCON:
  2088  		if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
  2089  			return true
  2090  		}
  2091  
  2092  	case C_BITCON:
  2093  		if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
  2094  			return true
  2095  		}
  2096  
  2097  	case C_MOVCON:
  2098  		if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
  2099  			return true
  2100  		}
  2101  
  2102  	case C_ADDCON2:
  2103  		if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
  2104  			return true
  2105  		}
  2106  
  2107  	case C_LCON:
  2108  		if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
  2109  			return true
  2110  		}
  2111  
  2112  	case C_MOVCON2:
  2113  		return cmp(C_LCON, b)
  2114  
  2115  	case C_VCON:
  2116  		return cmp(C_LCON, b)
  2117  
  2118  	case C_LACON:
  2119  		if b == C_AACON || b == C_AACON2 {
  2120  			return true
  2121  		}
  2122  
  2123  	case C_SEXT2:
  2124  		if b == C_SEXT1 {
  2125  			return true
  2126  		}
  2127  
  2128  	case C_SEXT4:
  2129  		if b == C_SEXT1 || b == C_SEXT2 {
  2130  			return true
  2131  		}
  2132  
  2133  	case C_SEXT8:
  2134  		if b >= C_SEXT1 && b <= C_SEXT4 {
  2135  			return true
  2136  		}
  2137  
  2138  	case C_SEXT16:
  2139  		if b >= C_SEXT1 && b <= C_SEXT8 {
  2140  			return true
  2141  		}
  2142  
  2143  	case C_LEXT:
  2144  		if b >= C_SEXT1 && b <= C_SEXT16 {
  2145  			return true
  2146  		}
  2147  
  2148  	case C_NSAUTO_8:
  2149  		if b == C_NSAUTO_16 {
  2150  			return true
  2151  		}
  2152  
  2153  	case C_NSAUTO_4:
  2154  		if b == C_NSAUTO_16 || b == C_NSAUTO_8 {
  2155  			return true
  2156  		}
  2157  
  2158  	case C_NSAUTO:
  2159  		switch b {
  2160  		case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16:
  2161  			return true
  2162  		}
  2163  
  2164  	case C_NPAUTO_16:
  2165  		switch b {
  2166  		case C_NSAUTO_16:
  2167  			return true
  2168  		}
  2169  
  2170  	case C_NPAUTO:
  2171  		switch b {
  2172  		case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16:
  2173  			return true
  2174  		}
  2175  
  2176  	case C_NQAUTO_16:
  2177  		switch b {
  2178  		case C_NSAUTO_16, C_NPAUTO_16:
  2179  			return true
  2180  		}
  2181  
  2182  	case C_NAUTO4K:
  2183  		switch b {
  2184  		case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16,
  2185  			C_NPAUTO, C_NQAUTO_16:
  2186  			return true
  2187  		}
  2188  
  2189  	case C_PSAUTO_16:
  2190  		if b == C_ZAUTO {
  2191  			return true
  2192  		}
  2193  
  2194  	case C_PSAUTO_8:
  2195  		if b == C_ZAUTO || b == C_PSAUTO_16 {
  2196  			return true
  2197  		}
  2198  
  2199  	case C_PSAUTO_4:
  2200  		switch b {
  2201  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8:
  2202  			return true
  2203  		}
  2204  
  2205  	case C_PSAUTO:
  2206  		switch b {
  2207  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4:
  2208  			return true
  2209  		}
  2210  
  2211  	case C_PPAUTO_16:
  2212  		switch b {
  2213  		case C_ZAUTO, C_PSAUTO_16:
  2214  			return true
  2215  		}
  2216  
  2217  	case C_PPAUTO:
  2218  		switch b {
  2219  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16:
  2220  			return true
  2221  		}
  2222  
  2223  	case C_PQAUTO_16:
  2224  		switch b {
  2225  		case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16:
  2226  			return true
  2227  		}
  2228  
  2229  	case C_UAUTO4K:
  2230  		switch b {
  2231  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2232  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2233  			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16:
  2234  			return true
  2235  		}
  2236  
  2237  	case C_UAUTO8K:
  2238  		switch b {
  2239  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2240  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2241  			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2242  			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16:
  2243  			return true
  2244  		}
  2245  
  2246  	case C_UAUTO16K:
  2247  		switch b {
  2248  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2249  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2250  			C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2251  			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
  2252  			C_UAUTO16K_8, C_UAUTO16K_16:
  2253  			return true
  2254  		}
  2255  
  2256  	case C_UAUTO32K:
  2257  		switch b {
  2258  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2259  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2260  			C_UAUTO4K_8, C_UAUTO4K_16,
  2261  			C_UAUTO8K_8, C_UAUTO8K_16,
  2262  			C_UAUTO16K_8, C_UAUTO16K_16,
  2263  			C_UAUTO32K_16:
  2264  			return true
  2265  		}
  2266  
  2267  	case C_UAUTO64K:
  2268  		switch b {
  2269  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2270  			C_PPAUTO_16, C_PQAUTO_16, C_UAUTO4K_16, C_UAUTO8K_16, C_UAUTO16K_16,
  2271  			C_UAUTO32K_16:
  2272  			return true
  2273  		}
  2274  
  2275  	case C_LAUTO:
  2276  		switch b {
  2277  		case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16, C_NPAUTO_16, C_NPAUTO, C_NQAUTO_16, C_NAUTO4K,
  2278  			C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2279  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2280  			C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2281  			C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
  2282  			C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K_16,
  2283  			C_UAUTO32K, C_UAUTO32K_16,
  2284  			C_UAUTO64K:
  2285  			return true
  2286  		}
  2287  
  2288  	case C_NSOREG_8:
  2289  		if b == C_NSOREG_16 {
  2290  			return true
  2291  		}
  2292  
  2293  	case C_NSOREG_4:
  2294  		if b == C_NSOREG_8 || b == C_NSOREG_16 {
  2295  			return true
  2296  		}
  2297  
  2298  	case C_NSOREG:
  2299  		switch b {
  2300  		case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16:
  2301  			return true
  2302  		}
  2303  
  2304  	case C_NPOREG_16:
  2305  		switch b {
  2306  		case C_NSOREG_16:
  2307  			return true
  2308  		}
  2309  
  2310  	case C_NPOREG:
  2311  		switch b {
  2312  		case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16:
  2313  			return true
  2314  		}
  2315  
  2316  	case C_NQOREG_16:
  2317  		switch b {
  2318  		case C_NSOREG_16, C_NPOREG_16:
  2319  			return true
  2320  		}
  2321  
  2322  	case C_NOREG4K:
  2323  		switch b {
  2324  		case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16:
  2325  			return true
  2326  		}
  2327  
  2328  	case C_PSOREG_16:
  2329  		if b == C_ZOREG {
  2330  			return true
  2331  		}
  2332  
  2333  	case C_PSOREG_8:
  2334  		if b == C_ZOREG || b == C_PSOREG_16 {
  2335  			return true
  2336  		}
  2337  
  2338  	case C_PSOREG_4:
  2339  		switch b {
  2340  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8:
  2341  			return true
  2342  		}
  2343  
  2344  	case C_PSOREG:
  2345  		switch b {
  2346  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4:
  2347  			return true
  2348  		}
  2349  
  2350  	case C_PPOREG_16:
  2351  		switch b {
  2352  		case C_ZOREG, C_PSOREG_16:
  2353  			return true
  2354  		}
  2355  
  2356  	case C_PPOREG:
  2357  		switch b {
  2358  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16:
  2359  			return true
  2360  		}
  2361  
  2362  	case C_PQOREG_16:
  2363  		switch b {
  2364  		case C_ZOREG, C_PSOREG_16, C_PPOREG_16:
  2365  			return true
  2366  		}
  2367  
  2368  	case C_UOREG4K:
  2369  		switch b {
  2370  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2371  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2372  			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16:
  2373  			return true
  2374  		}
  2375  
  2376  	case C_UOREG8K:
  2377  		switch b {
  2378  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2379  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2380  			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2381  			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16:
  2382  			return true
  2383  		}
  2384  
  2385  	case C_UOREG16K:
  2386  		switch b {
  2387  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2388  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2389  			C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2390  			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
  2391  			C_UOREG16K_8, C_UOREG16K_16:
  2392  			return true
  2393  		}
  2394  
  2395  	case C_UOREG32K:
  2396  		switch b {
  2397  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2398  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2399  			C_UOREG4K_8, C_UOREG4K_16,
  2400  			C_UOREG8K_8, C_UOREG8K_16,
  2401  			C_UOREG16K_8, C_UOREG16K_16,
  2402  			C_UOREG32K_16:
  2403  			return true
  2404  		}
  2405  
  2406  	case C_UOREG64K:
  2407  		switch b {
  2408  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2409  			C_PPOREG_16, C_PQOREG_16, C_UOREG4K_16, C_UOREG8K_16, C_UOREG16K_16,
  2410  			C_UOREG32K_16:
  2411  			return true
  2412  		}
  2413  
  2414  	case C_LOREG:
  2415  		switch b {
  2416  		case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NSOREG_16, C_NPOREG, C_NPOREG_16, C_NQOREG_16, C_NOREG4K,
  2417  			C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2418  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2419  			C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2420  			C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
  2421  			C_UOREG16K, C_UOREG16K_8, C_UOREG16K_16,
  2422  			C_UOREG32K, C_UOREG32K_16,
  2423  			C_UOREG64K:
  2424  			return true
  2425  		}
  2426  
  2427  	case C_LBRA:
  2428  		if b == C_SBRA {
  2429  			return true
  2430  		}
  2431  	}
  2432  
  2433  	return false
  2434  }
  2435  
  2436  type ocmp []Optab
  2437  
  2438  func (x ocmp) Len() int {
  2439  	return len(x)
  2440  }
  2441  
  2442  func (x ocmp) Swap(i, j int) {
  2443  	x[i], x[j] = x[j], x[i]
  2444  }
  2445  
  2446  func (x ocmp) Less(i, j int) bool {
  2447  	p1 := &x[i]
  2448  	p2 := &x[j]
  2449  	if p1.as != p2.as {
  2450  		return p1.as < p2.as
  2451  	}
  2452  	if p1.a1 != p2.a1 {
  2453  		return p1.a1 < p2.a1
  2454  	}
  2455  	if p1.a2 != p2.a2 {
  2456  		return p1.a2 < p2.a2
  2457  	}
  2458  	if p1.a3 != p2.a3 {
  2459  		return p1.a3 < p2.a3
  2460  	}
  2461  	if p1.a4 != p2.a4 {
  2462  		return p1.a4 < p2.a4
  2463  	}
  2464  	if p1.scond != p2.scond {
  2465  		return p1.scond < p2.scond
  2466  	}
  2467  	return false
  2468  }
  2469  
  2470  func oprangeset(a obj.As, t []Optab) {
  2471  	oprange[a&obj.AMask] = t
  2472  }
  2473  
  2474  func buildop(ctxt *obj.Link) {
  2475  	if oprange[AAND&obj.AMask] != nil {
  2476  		// Already initialized; stop now.
  2477  		// This happens in the cmd/asm tests,
  2478  		// each of which re-initializes the arch.
  2479  		return
  2480  	}
  2481  
  2482  	var n int
  2483  	for i := 0; i < C_GOK; i++ {
  2484  		for n = 0; n < C_GOK; n++ {
  2485  			if cmp(n, i) {
  2486  				xcmp[i][n] = true
  2487  			}
  2488  		}
  2489  	}
  2490  	for n = 0; optab[n].as != obj.AXXX; n++ {
  2491  	}
  2492  	sort.Sort(ocmp(optab[:n]))
  2493  	for i := 0; i < n; i++ {
  2494  		r := optab[i].as
  2495  		start := i
  2496  		for optab[i].as == r {
  2497  			i++
  2498  		}
  2499  		t := optab[start:i]
  2500  		i--
  2501  		oprangeset(r, t)
  2502  		switch r {
  2503  		default:
  2504  			ctxt.Diag("unknown op in build: %v", r)
  2505  			ctxt.DiagFlush()
  2506  			log.Fatalf("bad code")
  2507  
  2508  		case AADD:
  2509  			oprangeset(AADDS, t)
  2510  			oprangeset(ASUB, t)
  2511  			oprangeset(ASUBS, t)
  2512  			oprangeset(AADDW, t)
  2513  			oprangeset(AADDSW, t)
  2514  			oprangeset(ASUBW, t)
  2515  			oprangeset(ASUBSW, t)
  2516  
  2517  		case AAND: /* logical immediate, logical shifted register */
  2518  			oprangeset(AANDW, t)
  2519  			oprangeset(AEOR, t)
  2520  			oprangeset(AEORW, t)
  2521  			oprangeset(AORR, t)
  2522  			oprangeset(AORRW, t)
  2523  			oprangeset(ABIC, t)
  2524  			oprangeset(ABICW, t)
  2525  			oprangeset(AEON, t)
  2526  			oprangeset(AEONW, t)
  2527  			oprangeset(AORN, t)
  2528  			oprangeset(AORNW, t)
  2529  
  2530  		case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
  2531  			oprangeset(AANDSW, t)
  2532  			oprangeset(ABICS, t)
  2533  			oprangeset(ABICSW, t)
  2534  
  2535  		case ANEG:
  2536  			oprangeset(ANEGS, t)
  2537  			oprangeset(ANEGSW, t)
  2538  			oprangeset(ANEGW, t)
  2539  
  2540  		case AADC: /* rn=Rd */
  2541  			oprangeset(AADCW, t)
  2542  
  2543  			oprangeset(AADCS, t)
  2544  			oprangeset(AADCSW, t)
  2545  			oprangeset(ASBC, t)
  2546  			oprangeset(ASBCW, t)
  2547  			oprangeset(ASBCS, t)
  2548  			oprangeset(ASBCSW, t)
  2549  
  2550  		case ANGC: /* rn=REGZERO */
  2551  			oprangeset(ANGCW, t)
  2552  
  2553  			oprangeset(ANGCS, t)
  2554  			oprangeset(ANGCSW, t)
  2555  
  2556  		case ACMP:
  2557  			oprangeset(ACMPW, t)
  2558  			oprangeset(ACMN, t)
  2559  			oprangeset(ACMNW, t)
  2560  
  2561  		case ATST:
  2562  			oprangeset(ATSTW, t)
  2563  
  2564  			/* register/register, and shifted */
  2565  		case AMVN:
  2566  			oprangeset(AMVNW, t)
  2567  
  2568  		case AMOVK:
  2569  			oprangeset(AMOVKW, t)
  2570  			oprangeset(AMOVN, t)
  2571  			oprangeset(AMOVNW, t)
  2572  			oprangeset(AMOVZ, t)
  2573  			oprangeset(AMOVZW, t)
  2574  
  2575  		case ASWPD:
  2576  			for i := range atomicLDADD {
  2577  				oprangeset(i, t)
  2578  			}
  2579  			for i := range atomicSWP {
  2580  				if i == ASWPD {
  2581  					continue
  2582  				}
  2583  				oprangeset(i, t)
  2584  			}
  2585  
  2586  		case ACASPD:
  2587  			oprangeset(ACASPW, t)
  2588  		case ABEQ:
  2589  			oprangeset(ABNE, t)
  2590  			oprangeset(ABCS, t)
  2591  			oprangeset(ABHS, t)
  2592  			oprangeset(ABCC, t)
  2593  			oprangeset(ABLO, t)
  2594  			oprangeset(ABMI, t)
  2595  			oprangeset(ABPL, t)
  2596  			oprangeset(ABVS, t)
  2597  			oprangeset(ABVC, t)
  2598  			oprangeset(ABHI, t)
  2599  			oprangeset(ABLS, t)
  2600  			oprangeset(ABGE, t)
  2601  			oprangeset(ABLT, t)
  2602  			oprangeset(ABGT, t)
  2603  			oprangeset(ABLE, t)
  2604  
  2605  		case ALSL:
  2606  			oprangeset(ALSLW, t)
  2607  			oprangeset(ALSR, t)
  2608  			oprangeset(ALSRW, t)
  2609  			oprangeset(AASR, t)
  2610  			oprangeset(AASRW, t)
  2611  			oprangeset(AROR, t)
  2612  			oprangeset(ARORW, t)
  2613  
  2614  		case ACLS:
  2615  			oprangeset(ACLSW, t)
  2616  			oprangeset(ACLZ, t)
  2617  			oprangeset(ACLZW, t)
  2618  			oprangeset(ARBIT, t)
  2619  			oprangeset(ARBITW, t)
  2620  			oprangeset(AREV, t)
  2621  			oprangeset(AREVW, t)
  2622  			oprangeset(AREV16, t)
  2623  			oprangeset(AREV16W, t)
  2624  			oprangeset(AREV32, t)
  2625  
  2626  		case ASDIV:
  2627  			oprangeset(ASDIVW, t)
  2628  			oprangeset(AUDIV, t)
  2629  			oprangeset(AUDIVW, t)
  2630  			oprangeset(ACRC32B, t)
  2631  			oprangeset(ACRC32CB, t)
  2632  			oprangeset(ACRC32CH, t)
  2633  			oprangeset(ACRC32CW, t)
  2634  			oprangeset(ACRC32CX, t)
  2635  			oprangeset(ACRC32H, t)
  2636  			oprangeset(ACRC32W, t)
  2637  			oprangeset(ACRC32X, t)
  2638  
  2639  		case AMADD:
  2640  			oprangeset(AMADDW, t)
  2641  			oprangeset(AMSUB, t)
  2642  			oprangeset(AMSUBW, t)
  2643  			oprangeset(ASMADDL, t)
  2644  			oprangeset(ASMSUBL, t)
  2645  			oprangeset(AUMADDL, t)
  2646  			oprangeset(AUMSUBL, t)
  2647  
  2648  		case AREM:
  2649  			oprangeset(AREMW, t)
  2650  			oprangeset(AUREM, t)
  2651  			oprangeset(AUREMW, t)
  2652  
  2653  		case AMUL:
  2654  			oprangeset(AMULW, t)
  2655  			oprangeset(AMNEG, t)
  2656  			oprangeset(AMNEGW, t)
  2657  			oprangeset(ASMNEGL, t)
  2658  			oprangeset(ASMULL, t)
  2659  			oprangeset(ASMULH, t)
  2660  			oprangeset(AUMNEGL, t)
  2661  			oprangeset(AUMULH, t)
  2662  			oprangeset(AUMULL, t)
  2663  
  2664  		case AMOVB:
  2665  			oprangeset(AMOVBU, t)
  2666  
  2667  		case AMOVH:
  2668  			oprangeset(AMOVHU, t)
  2669  
  2670  		case AMOVW:
  2671  			oprangeset(AMOVWU, t)
  2672  
  2673  		case ABFM:
  2674  			oprangeset(ABFMW, t)
  2675  			oprangeset(ASBFM, t)
  2676  			oprangeset(ASBFMW, t)
  2677  			oprangeset(AUBFM, t)
  2678  			oprangeset(AUBFMW, t)
  2679  
  2680  		case ABFI:
  2681  			oprangeset(ABFIW, t)
  2682  			oprangeset(ABFXIL, t)
  2683  			oprangeset(ABFXILW, t)
  2684  			oprangeset(ASBFIZ, t)
  2685  			oprangeset(ASBFIZW, t)
  2686  			oprangeset(ASBFX, t)
  2687  			oprangeset(ASBFXW, t)
  2688  			oprangeset(AUBFIZ, t)
  2689  			oprangeset(AUBFIZW, t)
  2690  			oprangeset(AUBFX, t)
  2691  			oprangeset(AUBFXW, t)
  2692  
  2693  		case AEXTR:
  2694  			oprangeset(AEXTRW, t)
  2695  
  2696  		case ASXTB:
  2697  			oprangeset(ASXTBW, t)
  2698  			oprangeset(ASXTH, t)
  2699  			oprangeset(ASXTHW, t)
  2700  			oprangeset(ASXTW, t)
  2701  			oprangeset(AUXTB, t)
  2702  			oprangeset(AUXTH, t)
  2703  			oprangeset(AUXTW, t)
  2704  			oprangeset(AUXTBW, t)
  2705  			oprangeset(AUXTHW, t)
  2706  
  2707  		case ACCMN:
  2708  			oprangeset(ACCMNW, t)
  2709  			oprangeset(ACCMP, t)
  2710  			oprangeset(ACCMPW, t)
  2711  
  2712  		case ACSEL:
  2713  			oprangeset(ACSELW, t)
  2714  			oprangeset(ACSINC, t)
  2715  			oprangeset(ACSINCW, t)
  2716  			oprangeset(ACSINV, t)
  2717  			oprangeset(ACSINVW, t)
  2718  			oprangeset(ACSNEG, t)
  2719  			oprangeset(ACSNEGW, t)
  2720  
  2721  		case ACINC:
  2722  			// aliases Rm=Rn, !cond
  2723  			oprangeset(ACINCW, t)
  2724  			oprangeset(ACINV, t)
  2725  			oprangeset(ACINVW, t)
  2726  			oprangeset(ACNEG, t)
  2727  			oprangeset(ACNEGW, t)
  2728  
  2729  			// aliases, Rm=Rn=REGZERO, !cond
  2730  		case ACSET:
  2731  			oprangeset(ACSETW, t)
  2732  
  2733  			oprangeset(ACSETM, t)
  2734  			oprangeset(ACSETMW, t)
  2735  
  2736  		case AMOVD,
  2737  			AMOVBU,
  2738  			AB,
  2739  			ABL,
  2740  			AWORD,
  2741  			ADWORD,
  2742  			obj.ARET,
  2743  			obj.ATEXT:
  2744  			break
  2745  
  2746  		case AFLDPQ:
  2747  			break
  2748  		case AFSTPQ:
  2749  			break
  2750  		case ALDP:
  2751  			oprangeset(AFLDPD, t)
  2752  
  2753  		case ASTP:
  2754  			oprangeset(AFSTPD, t)
  2755  
  2756  		case ASTPW:
  2757  			oprangeset(AFSTPS, t)
  2758  
  2759  		case ALDPW:
  2760  			oprangeset(ALDPSW, t)
  2761  			oprangeset(AFLDPS, t)
  2762  
  2763  		case AERET:
  2764  			oprangeset(AWFE, t)
  2765  			oprangeset(AWFI, t)
  2766  			oprangeset(AYIELD, t)
  2767  			oprangeset(ASEV, t)
  2768  			oprangeset(ASEVL, t)
  2769  			oprangeset(ANOOP, t)
  2770  			oprangeset(ADRPS, t)
  2771  
  2772  		case ACBZ:
  2773  			oprangeset(ACBZW, t)
  2774  			oprangeset(ACBNZ, t)
  2775  			oprangeset(ACBNZW, t)
  2776  
  2777  		case ATBZ:
  2778  			oprangeset(ATBNZ, t)
  2779  
  2780  		case AADR, AADRP:
  2781  			break
  2782  
  2783  		case ACLREX:
  2784  			break
  2785  
  2786  		case ASVC:
  2787  			oprangeset(AHVC, t)
  2788  			oprangeset(AHLT, t)
  2789  			oprangeset(ASMC, t)
  2790  			oprangeset(ABRK, t)
  2791  			oprangeset(ADCPS1, t)
  2792  			oprangeset(ADCPS2, t)
  2793  			oprangeset(ADCPS3, t)
  2794  
  2795  		case AFADDS:
  2796  			oprangeset(AFADDD, t)
  2797  			oprangeset(AFSUBS, t)
  2798  			oprangeset(AFSUBD, t)
  2799  			oprangeset(AFMULS, t)
  2800  			oprangeset(AFMULD, t)
  2801  			oprangeset(AFNMULS, t)
  2802  			oprangeset(AFNMULD, t)
  2803  			oprangeset(AFDIVS, t)
  2804  			oprangeset(AFMAXD, t)
  2805  			oprangeset(AFMAXS, t)
  2806  			oprangeset(AFMIND, t)
  2807  			oprangeset(AFMINS, t)
  2808  			oprangeset(AFMAXNMD, t)
  2809  			oprangeset(AFMAXNMS, t)
  2810  			oprangeset(AFMINNMD, t)
  2811  			oprangeset(AFMINNMS, t)
  2812  			oprangeset(AFDIVD, t)
  2813  
  2814  		case AFMSUBD:
  2815  			oprangeset(AFMSUBS, t)
  2816  			oprangeset(AFMADDS, t)
  2817  			oprangeset(AFMADDD, t)
  2818  			oprangeset(AFNMSUBS, t)
  2819  			oprangeset(AFNMSUBD, t)
  2820  			oprangeset(AFNMADDS, t)
  2821  			oprangeset(AFNMADDD, t)
  2822  
  2823  		case AFCVTSD:
  2824  			oprangeset(AFCVTDS, t)
  2825  			oprangeset(AFABSD, t)
  2826  			oprangeset(AFABSS, t)
  2827  			oprangeset(AFNEGD, t)
  2828  			oprangeset(AFNEGS, t)
  2829  			oprangeset(AFSQRTD, t)
  2830  			oprangeset(AFSQRTS, t)
  2831  			oprangeset(AFRINTNS, t)
  2832  			oprangeset(AFRINTND, t)
  2833  			oprangeset(AFRINTPS, t)
  2834  			oprangeset(AFRINTPD, t)
  2835  			oprangeset(AFRINTMS, t)
  2836  			oprangeset(AFRINTMD, t)
  2837  			oprangeset(AFRINTZS, t)
  2838  			oprangeset(AFRINTZD, t)
  2839  			oprangeset(AFRINTAS, t)
  2840  			oprangeset(AFRINTAD, t)
  2841  			oprangeset(AFRINTXS, t)
  2842  			oprangeset(AFRINTXD, t)
  2843  			oprangeset(AFRINTIS, t)
  2844  			oprangeset(AFRINTID, t)
  2845  			oprangeset(AFCVTDH, t)
  2846  			oprangeset(AFCVTHS, t)
  2847  			oprangeset(AFCVTHD, t)
  2848  			oprangeset(AFCVTSH, t)
  2849  
  2850  		case AFCMPS:
  2851  			oprangeset(AFCMPD, t)
  2852  			oprangeset(AFCMPES, t)
  2853  			oprangeset(AFCMPED, t)
  2854  
  2855  		case AFCCMPS:
  2856  			oprangeset(AFCCMPD, t)
  2857  			oprangeset(AFCCMPES, t)
  2858  			oprangeset(AFCCMPED, t)
  2859  
  2860  		case AFCSELD:
  2861  			oprangeset(AFCSELS, t)
  2862  
  2863  		case AFMOVQ, AFMOVD, AFMOVS,
  2864  			AVMOVQ, AVMOVD, AVMOVS:
  2865  			break
  2866  
  2867  		case AFCVTZSD:
  2868  			oprangeset(AFCVTZSDW, t)
  2869  			oprangeset(AFCVTZSS, t)
  2870  			oprangeset(AFCVTZSSW, t)
  2871  			oprangeset(AFCVTZUD, t)
  2872  			oprangeset(AFCVTZUDW, t)
  2873  			oprangeset(AFCVTZUS, t)
  2874  			oprangeset(AFCVTZUSW, t)
  2875  
  2876  		case ASCVTFD:
  2877  			oprangeset(ASCVTFS, t)
  2878  			oprangeset(ASCVTFWD, t)
  2879  			oprangeset(ASCVTFWS, t)
  2880  			oprangeset(AUCVTFD, t)
  2881  			oprangeset(AUCVTFS, t)
  2882  			oprangeset(AUCVTFWD, t)
  2883  			oprangeset(AUCVTFWS, t)
  2884  
  2885  		case ASYS:
  2886  			oprangeset(AAT, t)
  2887  			oprangeset(ADC, t)
  2888  			oprangeset(AIC, t)
  2889  			oprangeset(ATLBI, t)
  2890  
  2891  		case ASYSL, AHINT:
  2892  			break
  2893  
  2894  		case ADMB:
  2895  			oprangeset(ADSB, t)
  2896  			oprangeset(AISB, t)
  2897  
  2898  		case AMRS, AMSR:
  2899  			break
  2900  
  2901  		case ALDAR:
  2902  			oprangeset(ALDARW, t)
  2903  			oprangeset(ALDARB, t)
  2904  			oprangeset(ALDARH, t)
  2905  			fallthrough
  2906  
  2907  		case ALDXR:
  2908  			oprangeset(ALDXRB, t)
  2909  			oprangeset(ALDXRH, t)
  2910  			oprangeset(ALDXRW, t)
  2911  
  2912  		case ALDAXR:
  2913  			oprangeset(ALDAXRB, t)
  2914  			oprangeset(ALDAXRH, t)
  2915  			oprangeset(ALDAXRW, t)
  2916  
  2917  		case ALDXP:
  2918  			oprangeset(ALDXPW, t)
  2919  			oprangeset(ALDAXP, t)
  2920  			oprangeset(ALDAXPW, t)
  2921  
  2922  		case ASTLR:
  2923  			oprangeset(ASTLRB, t)
  2924  			oprangeset(ASTLRH, t)
  2925  			oprangeset(ASTLRW, t)
  2926  
  2927  		case ASTXR:
  2928  			oprangeset(ASTXRB, t)
  2929  			oprangeset(ASTXRH, t)
  2930  			oprangeset(ASTXRW, t)
  2931  
  2932  		case ASTLXR:
  2933  			oprangeset(ASTLXRB, t)
  2934  			oprangeset(ASTLXRH, t)
  2935  			oprangeset(ASTLXRW, t)
  2936  
  2937  		case ASTXP:
  2938  			oprangeset(ASTLXP, t)
  2939  			oprangeset(ASTLXPW, t)
  2940  			oprangeset(ASTXPW, t)
  2941  
  2942  		case AVADDP:
  2943  			oprangeset(AVAND, t)
  2944  			oprangeset(AVCMEQ, t)
  2945  			oprangeset(AVORR, t)
  2946  			oprangeset(AVEOR, t)
  2947  			oprangeset(AVBSL, t)
  2948  			oprangeset(AVBIT, t)
  2949  			oprangeset(AVCMTST, t)
  2950  			oprangeset(AVUMAX, t)
  2951  			oprangeset(AVUMIN, t)
  2952  			oprangeset(AVUZP1, t)
  2953  			oprangeset(AVUZP2, t)
  2954  			oprangeset(AVBIF, t)
  2955  
  2956  		case AVADD:
  2957  			oprangeset(AVSUB, t)
  2958  			oprangeset(AVRAX1, t)
  2959  
  2960  		case AAESD:
  2961  			oprangeset(AAESE, t)
  2962  			oprangeset(AAESMC, t)
  2963  			oprangeset(AAESIMC, t)
  2964  			oprangeset(ASHA1SU1, t)
  2965  			oprangeset(ASHA256SU0, t)
  2966  			oprangeset(ASHA512SU0, t)
  2967  
  2968  		case ASHA1C:
  2969  			oprangeset(ASHA1P, t)
  2970  			oprangeset(ASHA1M, t)
  2971  
  2972  		case ASHA256H:
  2973  			oprangeset(ASHA256H2, t)
  2974  			oprangeset(ASHA512H, t)
  2975  			oprangeset(ASHA512H2, t)
  2976  
  2977  		case ASHA1SU0:
  2978  			oprangeset(ASHA256SU1, t)
  2979  			oprangeset(ASHA512SU1, t)
  2980  
  2981  		case AVADDV:
  2982  			oprangeset(AVUADDLV, t)
  2983  
  2984  		case AVFMLA:
  2985  			oprangeset(AVFMLS, t)
  2986  
  2987  		case AVPMULL:
  2988  			oprangeset(AVPMULL2, t)
  2989  
  2990  		case AVUSHR:
  2991  			oprangeset(AVSHL, t)
  2992  			oprangeset(AVSRI, t)
  2993  			oprangeset(AVSLI, t)
  2994  			oprangeset(AVUSRA, t)
  2995  
  2996  		case AVREV32:
  2997  			oprangeset(AVCNT, t)
  2998  			oprangeset(AVRBIT, t)
  2999  			oprangeset(AVREV64, t)
  3000  			oprangeset(AVREV16, t)
  3001  
  3002  		case AVZIP1:
  3003  			oprangeset(AVZIP2, t)
  3004  
  3005  		case AVUXTL:
  3006  			oprangeset(AVUXTL2, t)
  3007  
  3008  		case AVUSHLL:
  3009  			oprangeset(AVUSHLL2, t)
  3010  
  3011  		case AVLD1R:
  3012  			oprangeset(AVLD2, t)
  3013  			oprangeset(AVLD2R, t)
  3014  			oprangeset(AVLD3, t)
  3015  			oprangeset(AVLD3R, t)
  3016  			oprangeset(AVLD4, t)
  3017  			oprangeset(AVLD4R, t)
  3018  
  3019  		case AVEOR3:
  3020  			oprangeset(AVBCAX, t)
  3021  
  3022  		case AVUADDW:
  3023  			oprangeset(AVUADDW2, t)
  3024  
  3025  		case ASHA1H,
  3026  			AVCNT,
  3027  			AVMOV,
  3028  			AVLD1,
  3029  			AVST1,
  3030  			AVST2,
  3031  			AVST3,
  3032  			AVST4,
  3033  			AVTBL,
  3034  			AVDUP,
  3035  			AVMOVI,
  3036  			APRFM,
  3037  			AVEXT,
  3038  			AVXAR:
  3039  			break
  3040  
  3041  		case obj.ANOP,
  3042  			obj.AUNDEF,
  3043  			obj.AFUNCDATA,
  3044  			obj.APCALIGN,
  3045  			obj.APCDATA,
  3046  			obj.ADUFFZERO,
  3047  			obj.ADUFFCOPY:
  3048  			break
  3049  		}
  3050  	}
  3051  }
  3052  
  3053  // chipfloat7() checks if the immediate constants available in  FMOVS/FMOVD instructions.
  3054  // For details of the range of constants available, see
  3055  // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
  3056  func (c *ctxt7) chipfloat7(e float64) int {
  3057  	ei := math.Float64bits(e)
  3058  	l := uint32(int32(ei))
  3059  	h := uint32(int32(ei >> 32))
  3060  
  3061  	if l != 0 || h&0xffff != 0 {
  3062  		return -1
  3063  	}
  3064  	h1 := h & 0x7fc00000
  3065  	if h1 != 0x40000000 && h1 != 0x3fc00000 {
  3066  		return -1
  3067  	}
  3068  	n := 0
  3069  
  3070  	// sign bit (a)
  3071  	if h&0x80000000 != 0 {
  3072  		n |= 1 << 7
  3073  	}
  3074  
  3075  	// exp sign bit (b)
  3076  	if h1 == 0x3fc00000 {
  3077  		n |= 1 << 6
  3078  	}
  3079  
  3080  	// rest of exp and mantissa (cd-efgh)
  3081  	n |= int((h >> 16) & 0x3f)
  3082  
  3083  	//print("match %.8lux %.8lux %d\n", l, h, n);
  3084  	return n
  3085  }
  3086  
  3087  /* form offset parameter to SYS; special register number */
  3088  func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
  3089  	return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
  3090  }
  3091  
  3092  func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
  3093  	return SYSARG5(0, op1, Cn, Cm, op2)
  3094  }
  3095  
  3096  // checkUnpredictable checks if the sourse and transfer registers are the same register.
  3097  // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
  3098  func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
  3099  	if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
  3100  		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3101  	}
  3102  	if isload && rt1 == rt2 {
  3103  		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3104  	}
  3105  }
  3106  
  3107  /* checkindex checks if index >= 0 && index <= maxindex */
  3108  func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
  3109  	if index < 0 || index > maxindex {
  3110  		c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
  3111  	}
  3112  }
  3113  
  3114  /* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
  3115  func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
  3116  	var offset, list, n, expect int64
  3117  	switch as {
  3118  	case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  3119  		offset = p.From.Offset
  3120  		list = p.To.Offset
  3121  	case AVST1, AVST2, AVST3, AVST4:
  3122  		offset = p.To.Offset
  3123  		list = p.From.Offset
  3124  	default:
  3125  		c.ctxt.Diag("invalid operation on op %v", p.As)
  3126  	}
  3127  	opcode := (list >> 12) & 15
  3128  	q := (list >> 30) & 1
  3129  	size := (list >> 10) & 3
  3130  	if offset == 0 {
  3131  		return
  3132  	}
  3133  	switch opcode {
  3134  	case 0x7:
  3135  		n = 1 // one register
  3136  	case 0xa:
  3137  		n = 2 // two registers
  3138  	case 0x6:
  3139  		n = 3 // three registers
  3140  	case 0x2:
  3141  		n = 4 // four registers
  3142  	default:
  3143  		c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  3144  	}
  3145  
  3146  	switch as {
  3147  	case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  3148  		if offset != n*(1<<uint(size)) {
  3149  			c.ctxt.Diag("invalid post-increment offset: %v", p)
  3150  		}
  3151  	default:
  3152  		if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
  3153  			c.ctxt.Diag("invalid post-increment offset: %v", p)
  3154  		}
  3155  	}
  3156  
  3157  	switch as {
  3158  	case AVLD1, AVST1:
  3159  		return
  3160  	case AVLD1R:
  3161  		expect = 1
  3162  	case AVLD2, AVST2, AVLD2R:
  3163  		expect = 2
  3164  	case AVLD3, AVST3, AVLD3R:
  3165  		expect = 3
  3166  	case AVLD4, AVST4, AVLD4R:
  3167  		expect = 4
  3168  	}
  3169  
  3170  	if expect != n {
  3171  		c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
  3172  	}
  3173  }
  3174  
  3175  /* checkShiftAmount checks whether the index shift amount is valid */
  3176  /* for load with register offset instructions */
  3177  func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
  3178  	var amount int16
  3179  	amount = (a.Index >> 5) & 7
  3180  	switch p.As {
  3181  	case AMOVB, AMOVBU:
  3182  		if amount != 0 {
  3183  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3184  		}
  3185  	case AMOVH, AMOVHU:
  3186  		if amount != 1 && amount != 0 {
  3187  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3188  		}
  3189  	case AMOVW, AMOVWU, AFMOVS:
  3190  		if amount != 2 && amount != 0 {
  3191  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3192  		}
  3193  	case AMOVD, AFMOVD:
  3194  		if amount != 3 && amount != 0 {
  3195  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3196  		}
  3197  	default:
  3198  		panic("invalid operation")
  3199  	}
  3200  }
  3201  
  3202  func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
  3203  	var os [5]uint32
  3204  	o1 := uint32(0)
  3205  	o2 := uint32(0)
  3206  	o3 := uint32(0)
  3207  	o4 := uint32(0)
  3208  	o5 := uint32(0)
  3209  	if false { /*debug['P']*/
  3210  		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  3211  	}
  3212  	switch o.type_ {
  3213  	default:
  3214  		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  3215  
  3216  	case 0: /* pseudo ops */
  3217  		break
  3218  
  3219  	case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
  3220  		o1 = c.oprrr(p, p.As)
  3221  
  3222  		rf := int(p.From.Reg)
  3223  		rt := int(p.To.Reg)
  3224  		r := int(p.Reg)
  3225  		if p.To.Type == obj.TYPE_NONE {
  3226  			rt = REGZERO
  3227  		}
  3228  		if r == 0 {
  3229  			r = rt
  3230  		}
  3231  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3232  
  3233  	case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
  3234  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3235  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3236  		}
  3237  		o1 = c.opirr(p, p.As)
  3238  
  3239  		rt := int(p.To.Reg)
  3240  		if p.To.Type == obj.TYPE_NONE {
  3241  			if (o1 & Sbit) == 0 {
  3242  				c.ctxt.Diag("ineffective ZR destination\n%v", p)
  3243  			}
  3244  			rt = REGZERO
  3245  		}
  3246  
  3247  		r := int(p.Reg)
  3248  		if r == 0 {
  3249  			r = rt
  3250  		}
  3251  		v := int32(c.regoff(&p.From))
  3252  		o1 = c.oaddi(p, int32(o1), v, r, rt)
  3253  
  3254  	case 3: /* op R<<n[,R],R (shifted register) */
  3255  		o1 = c.oprrr(p, p.As)
  3256  
  3257  		amount := (p.From.Offset >> 10) & 63
  3258  		is64bit := o1 & (1 << 31)
  3259  		if is64bit == 0 && amount >= 32 {
  3260  			c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
  3261  		}
  3262  		shift := (p.From.Offset >> 22) & 3
  3263  		if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) {
  3264  			c.ctxt.Diag("unsupported shift operator: %v", p)
  3265  		}
  3266  		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  3267  		rt := int(p.To.Reg)
  3268  		if p.To.Type == obj.TYPE_NONE {
  3269  			rt = REGZERO
  3270  		}
  3271  		r := int(p.Reg)
  3272  		if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) {
  3273  			r = REGZERO
  3274  		} else if r == 0 {
  3275  			r = rt
  3276  		}
  3277  		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  3278  
  3279  	case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
  3280  		rt := int(p.To.Reg)
  3281  		r := int(o.param)
  3282  
  3283  		if r == 0 {
  3284  			r = REGZERO
  3285  		} else if r == REGFROM {
  3286  			r = int(p.From.Reg)
  3287  		}
  3288  		if r == 0 {
  3289  			r = REGSP
  3290  		}
  3291  
  3292  		v := int32(c.regoff(&p.From))
  3293  		var op int32
  3294  		if v < 0 {
  3295  			v = -v
  3296  			op = int32(c.opirr(p, ASUB))
  3297  		} else {
  3298  			op = int32(c.opirr(p, AADD))
  3299  		}
  3300  
  3301  		if int(o.size) == 8 {
  3302  			o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP)
  3303  			o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt)
  3304  			break
  3305  		}
  3306  
  3307  		o1 = c.oaddi(p, op, v, r, rt)
  3308  
  3309  	case 5: /* b s; bl s */
  3310  		o1 = c.opbra(p, p.As)
  3311  
  3312  		if p.To.Sym == nil {
  3313  			o1 |= uint32(c.brdist(p, 0, 26, 2))
  3314  			break
  3315  		}
  3316  
  3317  		rel := obj.Addrel(c.cursym)
  3318  		rel.Off = int32(c.pc)
  3319  		rel.Siz = 4
  3320  		rel.Sym = p.To.Sym
  3321  		rel.Add = p.To.Offset
  3322  		rel.Type = objabi.R_CALLARM64
  3323  
  3324  	case 6: /* b ,O(R); bl ,O(R) */
  3325  		o1 = c.opbrr(p, p.As)
  3326  		o1 |= uint32(p.To.Reg&31) << 5
  3327  		if p.As == obj.ACALL {
  3328  			rel := obj.Addrel(c.cursym)
  3329  			rel.Off = int32(c.pc)
  3330  			rel.Siz = 0
  3331  			rel.Type = objabi.R_CALLIND
  3332  		}
  3333  
  3334  	case 7: /* beq s */
  3335  		o1 = c.opbra(p, p.As)
  3336  
  3337  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  3338  
  3339  	case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
  3340  		rt := int(p.To.Reg)
  3341  
  3342  		rf := int(p.Reg)
  3343  		if rf == 0 {
  3344  			rf = rt
  3345  		}
  3346  		v := int32(p.From.Offset)
  3347  		switch p.As {
  3348  		case AASR:
  3349  			o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
  3350  
  3351  		case AASRW:
  3352  			o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
  3353  
  3354  		case ALSL:
  3355  			o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
  3356  
  3357  		case ALSLW:
  3358  			o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
  3359  
  3360  		case ALSR:
  3361  			o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
  3362  
  3363  		case ALSRW:
  3364  			o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
  3365  
  3366  		case AROR:
  3367  			o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
  3368  
  3369  		case ARORW:
  3370  			o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
  3371  
  3372  		default:
  3373  			c.ctxt.Diag("bad shift $con\n%v", p)
  3374  			break
  3375  		}
  3376  
  3377  	case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
  3378  		o1 = c.oprrr(p, p.As)
  3379  
  3380  		r := int(p.Reg)
  3381  		if r == 0 {
  3382  			r = int(p.To.Reg)
  3383  		}
  3384  		o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
  3385  
  3386  	case 10: /* brk/hvc/.../svc [$con] */
  3387  		o1 = c.opimm(p, p.As)
  3388  
  3389  		if p.From.Type != obj.TYPE_NONE {
  3390  			o1 |= uint32((p.From.Offset & 0xffff) << 5)
  3391  		}
  3392  
  3393  	case 11: /* dword */
  3394  		c.aclass(&p.To)
  3395  
  3396  		o1 = uint32(c.instoffset)
  3397  		o2 = uint32(c.instoffset >> 32)
  3398  		if p.To.Sym != nil {
  3399  			rel := obj.Addrel(c.cursym)
  3400  			rel.Off = int32(c.pc)
  3401  			rel.Siz = 8
  3402  			rel.Sym = p.To.Sym
  3403  			rel.Add = p.To.Offset
  3404  			rel.Type = objabi.R_ADDR
  3405  			o2 = 0
  3406  			o1 = o2
  3407  		}
  3408  
  3409  	case 12: /* movT $vcon, reg */
  3410  		// NOTE: this case does not use REGTMP. If it ever does,
  3411  		// remove the NOTUSETMP flag in optab.
  3412  		num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
  3413  		if num == 0 {
  3414  			c.ctxt.Diag("invalid constant: %v", p)
  3415  		}
  3416  		o1 = os[0]
  3417  		o2 = os[1]
  3418  		o3 = os[2]
  3419  		o4 = os[3]
  3420  
  3421  	case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
  3422  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3423  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3424  		}
  3425  		o := uint32(0)
  3426  		num := uint8(0)
  3427  		cls := oclass(&p.From)
  3428  		if isADDWop(p.As) {
  3429  			if !cmp(C_LCON, cls) {
  3430  				c.ctxt.Diag("illegal combination: %v", p)
  3431  			}
  3432  			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3433  		} else {
  3434  			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3435  		}
  3436  		if num == 0 {
  3437  			c.ctxt.Diag("invalid constant: %v", p)
  3438  		}
  3439  		rt := int(p.To.Reg)
  3440  		if p.To.Type == obj.TYPE_NONE {
  3441  			rt = REGZERO
  3442  		}
  3443  		r := int(p.Reg)
  3444  		if r == 0 {
  3445  			r = rt
  3446  		}
  3447  		if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
  3448  			o = c.opxrrr(p, p.As, false)
  3449  			o |= REGTMP & 31 << 16
  3450  			o |= LSL0_64
  3451  		} else {
  3452  			o = c.oprrr(p, p.As)
  3453  			o |= REGTMP & 31 << 16 /* shift is 0 */
  3454  		}
  3455  
  3456  		o |= uint32(r&31) << 5
  3457  		o |= uint32(rt & 31)
  3458  
  3459  		os[num] = o
  3460  		o1 = os[0]
  3461  		o2 = os[1]
  3462  		o3 = os[2]
  3463  		o4 = os[3]
  3464  		o5 = os[4]
  3465  
  3466  	case 14: /* word */
  3467  		if c.aclass(&p.To) == C_ADDR {
  3468  			c.ctxt.Diag("address constant needs DWORD\n%v", p)
  3469  		}
  3470  		o1 = uint32(c.instoffset)
  3471  		if p.To.Sym != nil {
  3472  			// This case happens with words generated
  3473  			// in the PC stream as part of the literal pool.
  3474  			rel := obj.Addrel(c.cursym)
  3475  
  3476  			rel.Off = int32(c.pc)
  3477  			rel.Siz = 4
  3478  			rel.Sym = p.To.Sym
  3479  			rel.Add = p.To.Offset
  3480  			rel.Type = objabi.R_ADDR
  3481  			o1 = 0
  3482  		}
  3483  
  3484  	case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
  3485  		o1 = c.oprrr(p, p.As)
  3486  
  3487  		rf := int(p.From.Reg)
  3488  		rt := int(p.To.Reg)
  3489  		var r int
  3490  		var ra int
  3491  		if p.From3Type() == obj.TYPE_REG {
  3492  			r = int(p.GetFrom3().Reg)
  3493  			ra = int(p.Reg)
  3494  			if ra == 0 {
  3495  				ra = REGZERO
  3496  			}
  3497  		} else {
  3498  			r = int(p.Reg)
  3499  			if r == 0 {
  3500  				r = rt
  3501  			}
  3502  			ra = REGZERO
  3503  		}
  3504  
  3505  		o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  3506  
  3507  	case 16: /* XremY R[,R],R -> XdivY; XmsubY */
  3508  		o1 = c.oprrr(p, p.As)
  3509  
  3510  		rf := int(p.From.Reg)
  3511  		rt := int(p.To.Reg)
  3512  		r := int(p.Reg)
  3513  		if r == 0 {
  3514  			r = rt
  3515  		}
  3516  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
  3517  		o2 = c.oprrr(p, AMSUBW)
  3518  		o2 |= o1 & (1 << 31) /* same size */
  3519  		o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
  3520  
  3521  	case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
  3522  		o1 = c.oprrr(p, p.As)
  3523  
  3524  		rf := int(p.From.Reg)
  3525  		rt := int(p.To.Reg)
  3526  		r := int(p.Reg)
  3527  		if p.To.Type == obj.TYPE_NONE {
  3528  			rt = REGZERO
  3529  		}
  3530  		if r == 0 {
  3531  			r = REGZERO
  3532  		}
  3533  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3534  
  3535  	case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
  3536  		o1 = c.oprrr(p, p.As)
  3537  
  3538  		cond := int(p.From.Reg)
  3539  		// AL and NV are not allowed for CINC/CINV/CNEG/CSET/CSETM instructions
  3540  		if cond < COND_EQ || cond > COND_NV || (cond == COND_AL || cond == COND_NV) && p.From3Type() == obj.TYPE_NONE {
  3541  			c.ctxt.Diag("invalid condition: %v", p)
  3542  		} else {
  3543  			cond -= COND_EQ
  3544  		}
  3545  
  3546  		r := int(p.Reg)
  3547  		var rf int = r
  3548  		if p.From3Type() == obj.TYPE_NONE {
  3549  			/* CINC/CINV/CNEG or CSET/CSETM*/
  3550  			if r == 0 {
  3551  				/* CSET/CSETM */
  3552  				rf = REGZERO
  3553  				r = rf
  3554  			}
  3555  			cond ^= 1
  3556  		} else {
  3557  			rf = int(p.GetFrom3().Reg) /* CSEL */
  3558  		}
  3559  
  3560  		rt := int(p.To.Reg)
  3561  		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
  3562  
  3563  	case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
  3564  		nzcv := int(p.To.Offset)
  3565  
  3566  		cond := int(p.From.Reg)
  3567  		if cond < COND_EQ || cond > COND_NV {
  3568  			c.ctxt.Diag("invalid condition\n%v", p)
  3569  		} else {
  3570  			cond -= COND_EQ
  3571  		}
  3572  		var rf int
  3573  		if p.GetFrom3().Type == obj.TYPE_REG {
  3574  			o1 = c.oprrr(p, p.As)
  3575  			rf = int(p.GetFrom3().Reg) /* Rm */
  3576  		} else {
  3577  			o1 = c.opirr(p, p.As)
  3578  			rf = int(p.GetFrom3().Offset & 0x1F)
  3579  		}
  3580  
  3581  		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
  3582  
  3583  	case 20: /* movT R,O(R) -> strT */
  3584  		v := int32(c.regoff(&p.To))
  3585  		sz := int32(1 << uint(movesize(p.As)))
  3586  
  3587  		r := int(p.To.Reg)
  3588  		if r == 0 {
  3589  			r = int(o.param)
  3590  		}
  3591  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3592  			o1 = c.olsr9s(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
  3593  		} else {
  3594  			v = int32(c.offsetshift(p, int64(v), int(o.a4)))
  3595  			o1 = c.olsr12u(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
  3596  		}
  3597  
  3598  	case 21: /* movT O(R),R -> ldrT */
  3599  		v := int32(c.regoff(&p.From))
  3600  		sz := int32(1 << uint(movesize(p.As)))
  3601  
  3602  		r := int(p.From.Reg)
  3603  		if r == 0 {
  3604  			r = int(o.param)
  3605  		}
  3606  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3607  			o1 = c.olsr9s(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
  3608  		} else {
  3609  			v = int32(c.offsetshift(p, int64(v), int(o.a1)))
  3610  			//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
  3611  			o1 = c.olsr12u(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
  3612  		}
  3613  
  3614  	case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
  3615  		if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
  3616  			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3617  		}
  3618  
  3619  		v := int32(p.From.Offset)
  3620  
  3621  		if v < -256 || v > 255 {
  3622  			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
  3623  		}
  3624  		o1 = c.opldr(p, p.As)
  3625  		if o.scond == C_XPOST {
  3626  			o1 |= 1 << 10
  3627  		} else {
  3628  			o1 |= 3 << 10
  3629  		}
  3630  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
  3631  
  3632  	case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
  3633  		if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
  3634  			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3635  		}
  3636  
  3637  		v := int32(p.To.Offset)
  3638  
  3639  		if v < -256 || v > 255 {
  3640  			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
  3641  		}
  3642  		o1 = c.opstr(p, p.As)
  3643  		if o.scond == C_XPOST {
  3644  			o1 |= 1 << 10
  3645  		} else {
  3646  			o1 |= 3 << 10
  3647  		}
  3648  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
  3649  
  3650  	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
  3651  		rf := int(p.From.Reg)
  3652  		rt := int(p.To.Reg)
  3653  		s := rf == REGSP || rt == REGSP
  3654  		if p.As == AMVN || p.As == AMVNW {
  3655  			if s {
  3656  				c.ctxt.Diag("illegal SP reference\n%v", p)
  3657  			}
  3658  			o1 = c.oprrr(p, p.As)
  3659  			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3660  		} else if s {
  3661  			o1 = c.opirr(p, p.As)
  3662  			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3663  		} else {
  3664  			o1 = c.oprrr(p, p.As)
  3665  			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3666  		}
  3667  
  3668  	case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
  3669  		o1 = c.oprrr(p, p.As)
  3670  
  3671  		rf := int(p.From.Reg)
  3672  		if rf == C_NONE {
  3673  			rf = int(p.To.Reg)
  3674  		}
  3675  		rt := int(p.To.Reg)
  3676  		o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3677  
  3678  	case 26: // op R<<n, RSP, RSP (extended register)
  3679  		// Refer to ARM reference manual, if "Rd" or "Rn" is RSP,
  3680  		// it can be encoded as op(extended regster) instruction.
  3681  		if !(p.To.Reg == REGSP || p.Reg == REGSP) {
  3682  			c.ctxt.Diag("expected SP reference: %v", p)
  3683  			break
  3684  		}
  3685  		if p.To.Reg == REGSP && (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) {
  3686  			c.ctxt.Diag("unexpected SP reference: %v", p)
  3687  			break
  3688  		}
  3689  		amount := (p.From.Offset >> 10) & 63
  3690  		shift := (p.From.Offset >> 22) & 3
  3691  		if shift != 0 {
  3692  			c.ctxt.Diag("illegal combination: %v", p)
  3693  			break
  3694  		}
  3695  
  3696  		if amount > 4 {
  3697  			c.ctxt.Diag("the left shift amount out of range 0 to 4: %v", p)
  3698  			break
  3699  		}
  3700  		rf := (p.From.Offset >> 16) & 31
  3701  		rt := int(p.To.Reg)
  3702  		r := int(p.Reg)
  3703  		if p.To.Type == obj.TYPE_NONE {
  3704  			rt = REGZERO
  3705  		}
  3706  		if r == 0 {
  3707  			r = rt
  3708  		}
  3709  
  3710  		o1 = c.opxrrr(p, p.As, false)
  3711  		o1 |= uint32(rf)<<16 | uint32(amount&7)<<10 | (uint32(r&31) << 5) | uint32(rt&31)
  3712  
  3713  	case 27: /* op Rm<<n[,Rn],Rd (extended register) */
  3714  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3715  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3716  		}
  3717  		if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
  3718  			amount := (p.From.Reg >> 5) & 7
  3719  			if amount > 4 {
  3720  				c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
  3721  			}
  3722  			o1 = c.opxrrr(p, p.As, true)
  3723  			o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
  3724  		} else {
  3725  			o1 = c.opxrrr(p, p.As, false)
  3726  			o1 |= uint32(p.From.Reg&31) << 16
  3727  		}
  3728  		rt := int(p.To.Reg)
  3729  		if p.To.Type == obj.TYPE_NONE {
  3730  			rt = REGZERO
  3731  		}
  3732  		r := int(p.Reg)
  3733  		if r == 0 {
  3734  			r = rt
  3735  		}
  3736  		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  3737  
  3738  	case 28: /* logop $vcon, [R], R (64 bit literal) */
  3739  		o := uint32(0)
  3740  		num := uint8(0)
  3741  		cls := oclass(&p.From)
  3742  		if isANDWop(p.As) {
  3743  			if !cmp(C_LCON, cls) {
  3744  				c.ctxt.Diag("illegal combination: %v", p)
  3745  			}
  3746  			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3747  		} else {
  3748  			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3749  		}
  3750  
  3751  		if num == 0 {
  3752  			c.ctxt.Diag("invalid constant: %v", p)
  3753  		}
  3754  		rt := int(p.To.Reg)
  3755  		if p.To.Type == obj.TYPE_NONE {
  3756  			rt = REGZERO
  3757  		}
  3758  		r := int(p.Reg)
  3759  		if r == 0 {
  3760  			r = rt
  3761  		}
  3762  		o = c.oprrr(p, p.As)
  3763  		o |= REGTMP & 31 << 16 /* shift is 0 */
  3764  		o |= uint32(r&31) << 5
  3765  		o |= uint32(rt & 31)
  3766  
  3767  		os[num] = o
  3768  		o1 = os[0]
  3769  		o2 = os[1]
  3770  		o3 = os[2]
  3771  		o4 = os[3]
  3772  		o5 = os[4]
  3773  
  3774  	case 29: /* op Rn, Rd */
  3775  		fc := c.aclass(&p.From)
  3776  		tc := c.aclass(&p.To)
  3777  		if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
  3778  			// FMOV Rx, Fy or FMOV Fy, Rx
  3779  			o1 = FPCVTI(0, 0, 0, 0, 6)
  3780  			if p.As == AFMOVD {
  3781  				o1 |= 1<<31 | 1<<22 // 64-bit
  3782  			}
  3783  			if fc == C_REG || fc == C_ZCON {
  3784  				o1 |= 1 << 16 // FMOV Rx, Fy
  3785  			}
  3786  		} else {
  3787  			o1 = c.oprrr(p, p.As)
  3788  		}
  3789  		o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
  3790  
  3791  	case 30: /* movT R,L(R) -> strT */
  3792  		// if offset L can be split into hi+lo, and both fit into instructions, do
  3793  		//	add $hi, R, Rtmp
  3794  		//	str R, lo(Rtmp)
  3795  		// otherwise, use constant pool
  3796  		//	mov $L, Rtmp (from constant pool)
  3797  		//	str R, (R+Rtmp)
  3798  		s := movesize(o.as)
  3799  		if s < 0 {
  3800  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3801  		}
  3802  
  3803  		r := int(p.To.Reg)
  3804  		if r == 0 {
  3805  			r = int(o.param)
  3806  		}
  3807  
  3808  		v := int32(c.regoff(&p.To))
  3809  		var hi int32
  3810  		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3811  			// negative or unaligned offset, use constant pool
  3812  			goto storeusepool
  3813  		}
  3814  
  3815  		hi = v - (v & (0xFFF << uint(s)))
  3816  		if hi&0xFFF != 0 {
  3817  			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3818  		}
  3819  		if hi&^0xFFF000 != 0 {
  3820  			// hi doesn't fit into an ADD instruction
  3821  			goto storeusepool
  3822  		}
  3823  
  3824  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3825  		o2 = c.olsr12u(p, int32(c.opstr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
  3826  		break
  3827  
  3828  	storeusepool:
  3829  		if r == REGTMP || p.From.Reg == REGTMP {
  3830  			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  3831  		}
  3832  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  3833  		o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
  3834  
  3835  	case 31: /* movT L(R), R -> ldrT */
  3836  		// if offset L can be split into hi+lo, and both fit into instructions, do
  3837  		//	add $hi, R, Rtmp
  3838  		//	ldr lo(Rtmp), R
  3839  		// otherwise, use constant pool
  3840  		//	mov $L, Rtmp (from constant pool)
  3841  		//	ldr (R+Rtmp), R
  3842  		s := movesize(o.as)
  3843  		if s < 0 {
  3844  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3845  		}
  3846  
  3847  		r := int(p.From.Reg)
  3848  		if r == 0 {
  3849  			r = int(o.param)
  3850  		}
  3851  
  3852  		v := int32(c.regoff(&p.From))
  3853  		var hi int32
  3854  		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3855  			// negative or unaligned offset, use constant pool
  3856  			goto loadusepool
  3857  		}
  3858  
  3859  		hi = v - (v & (0xFFF << uint(s)))
  3860  		if (hi & 0xFFF) != 0 {
  3861  			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3862  		}
  3863  		if hi&^0xFFF000 != 0 {
  3864  			// hi doesn't fit into an ADD instruction
  3865  			goto loadusepool
  3866  		}
  3867  
  3868  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3869  		o2 = c.olsr12u(p, int32(c.opldr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
  3870  		break
  3871  
  3872  	loadusepool:
  3873  		if r == REGTMP || p.From.Reg == REGTMP {
  3874  			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  3875  		}
  3876  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3877  		o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
  3878  
  3879  	case 32: /* mov $con, R -> movz/movn */
  3880  		o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
  3881  
  3882  	case 33: /* movk $uimm16 << pos */
  3883  		o1 = c.opirr(p, p.As)
  3884  
  3885  		d := p.From.Offset
  3886  		s := movcon(d)
  3887  		if s < 0 || s >= 4 {
  3888  			c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
  3889  		}
  3890  		if (o1&S64) == 0 && s >= 2 {
  3891  			c.ctxt.Diag("illegal bit position\n%v", p)
  3892  		}
  3893  		if ((d >> uint(s*16)) >> 16) != 0 {
  3894  			c.ctxt.Diag("requires uimm16\n%v", p)
  3895  		}
  3896  		rt := int(p.To.Reg)
  3897  
  3898  		o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
  3899  
  3900  	case 34: /* mov $lacon,R */
  3901  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3902  
  3903  		if o1 == 0 {
  3904  			break
  3905  		}
  3906  		o2 = c.opxrrr(p, AADD, false)
  3907  		o2 |= REGTMP & 31 << 16
  3908  		o2 |= LSL0_64
  3909  		r := int(p.From.Reg)
  3910  		if r == 0 {
  3911  			r = int(o.param)
  3912  		}
  3913  		o2 |= uint32(r&31) << 5
  3914  		o2 |= uint32(p.To.Reg & 31)
  3915  
  3916  	case 35: /* mov SPR,R -> mrs */
  3917  		o1 = c.oprrr(p, AMRS)
  3918  
  3919  		// SysRegEnc function returns the system register encoding and accessFlags.
  3920  		_, v, accessFlags := SysRegEnc(p.From.Reg)
  3921  		if v == 0 {
  3922  			c.ctxt.Diag("illegal system register:\n%v", p)
  3923  		}
  3924  		if (o1 & (v &^ (3 << 19))) != 0 {
  3925  			c.ctxt.Diag("MRS register value overlap\n%v", p)
  3926  		}
  3927  		if accessFlags&SR_READ == 0 {
  3928  			c.ctxt.Diag("system register is not readable: %v", p)
  3929  		}
  3930  
  3931  		o1 |= v
  3932  		o1 |= uint32(p.To.Reg & 31)
  3933  
  3934  	case 36: /* mov R,SPR */
  3935  		o1 = c.oprrr(p, AMSR)
  3936  
  3937  		// SysRegEnc function returns the system register encoding and accessFlags.
  3938  		_, v, accessFlags := SysRegEnc(p.To.Reg)
  3939  		if v == 0 {
  3940  			c.ctxt.Diag("illegal system register:\n%v", p)
  3941  		}
  3942  		if (o1 & (v &^ (3 << 19))) != 0 {
  3943  			c.ctxt.Diag("MSR register value overlap\n%v", p)
  3944  		}
  3945  		if accessFlags&SR_WRITE == 0 {
  3946  			c.ctxt.Diag("system register is not writable: %v", p)
  3947  		}
  3948  
  3949  		o1 |= v
  3950  		o1 |= uint32(p.From.Reg & 31)
  3951  
  3952  	case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
  3953  		if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
  3954  			c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
  3955  		}
  3956  		o1 = c.opirr(p, AMSR)
  3957  		o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
  3958  		v := uint32(0)
  3959  		for i := 0; i < len(pstatefield); i++ {
  3960  			if pstatefield[i].reg == p.To.Reg {
  3961  				v = pstatefield[i].enc
  3962  				break
  3963  			}
  3964  		}
  3965  
  3966  		if v == 0 {
  3967  			c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
  3968  		}
  3969  		o1 |= v
  3970  
  3971  	case 38: /* clrex [$imm] */
  3972  		o1 = c.opimm(p, p.As)
  3973  
  3974  		if p.To.Type == obj.TYPE_NONE {
  3975  			o1 |= 0xF << 8
  3976  		} else {
  3977  			o1 |= uint32((p.To.Offset & 0xF) << 8)
  3978  		}
  3979  
  3980  	case 39: /* cbz R, rel */
  3981  		o1 = c.opirr(p, p.As)
  3982  
  3983  		o1 |= uint32(p.From.Reg & 31)
  3984  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  3985  
  3986  	case 40: /* tbz */
  3987  		o1 = c.opirr(p, p.As)
  3988  
  3989  		v := int32(p.From.Offset)
  3990  		if v < 0 || v > 63 {
  3991  			c.ctxt.Diag("illegal bit number\n%v", p)
  3992  		}
  3993  		o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
  3994  		o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
  3995  		o1 |= uint32(p.Reg & 31)
  3996  
  3997  	case 41: /* eret, nop, others with no operands */
  3998  		o1 = c.op0(p, p.As)
  3999  
  4000  	case 42: /* bfm R,r,s,R */
  4001  		o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
  4002  
  4003  	case 43: /* bfm aliases */
  4004  		r := int(p.From.Offset)
  4005  		s := int(p.GetFrom3().Offset)
  4006  		rf := int(p.Reg)
  4007  		rt := int(p.To.Reg)
  4008  		if rf == 0 {
  4009  			rf = rt
  4010  		}
  4011  		switch p.As {
  4012  		case ABFI:
  4013  			if r != 0 {
  4014  				r = 64 - r
  4015  			}
  4016  			o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
  4017  
  4018  		case ABFIW:
  4019  			if r != 0 {
  4020  				r = 32 - r
  4021  			}
  4022  			o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
  4023  
  4024  		case ABFXIL:
  4025  			o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
  4026  
  4027  		case ABFXILW:
  4028  			o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
  4029  
  4030  		case ASBFIZ:
  4031  			if r != 0 {
  4032  				r = 64 - r
  4033  			}
  4034  			o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
  4035  
  4036  		case ASBFIZW:
  4037  			if r != 0 {
  4038  				r = 32 - r
  4039  			}
  4040  			o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
  4041  
  4042  		case ASBFX:
  4043  			o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
  4044  
  4045  		case ASBFXW:
  4046  			o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
  4047  
  4048  		case AUBFIZ:
  4049  			if r != 0 {
  4050  				r = 64 - r
  4051  			}
  4052  			o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
  4053  
  4054  		case AUBFIZW:
  4055  			if r != 0 {
  4056  				r = 32 - r
  4057  			}
  4058  			o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
  4059  
  4060  		case AUBFX:
  4061  			o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
  4062  
  4063  		case AUBFXW:
  4064  			o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
  4065  
  4066  		default:
  4067  			c.ctxt.Diag("bad bfm alias\n%v", p)
  4068  			break
  4069  		}
  4070  
  4071  	case 44: /* extr $b, Rn, Rm, Rd */
  4072  		o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
  4073  
  4074  	case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
  4075  		rf := int(p.From.Reg)
  4076  
  4077  		rt := int(p.To.Reg)
  4078  		as := p.As
  4079  		if rf == REGZERO {
  4080  			as = AMOVWU /* clearer in disassembly */
  4081  		}
  4082  		switch as {
  4083  		case AMOVB, ASXTB:
  4084  			o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
  4085  
  4086  		case AMOVH, ASXTH:
  4087  			o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
  4088  
  4089  		case AMOVW, ASXTW:
  4090  			o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
  4091  
  4092  		case AMOVBU, AUXTB:
  4093  			o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
  4094  
  4095  		case AMOVHU, AUXTH:
  4096  			o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
  4097  
  4098  		case AMOVWU:
  4099  			o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  4100  
  4101  		case AUXTW:
  4102  			o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
  4103  
  4104  		case ASXTBW:
  4105  			o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
  4106  
  4107  		case ASXTHW:
  4108  			o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
  4109  
  4110  		case AUXTBW:
  4111  			o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
  4112  
  4113  		case AUXTHW:
  4114  			o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
  4115  
  4116  		default:
  4117  			c.ctxt.Diag("bad sxt %v", as)
  4118  			break
  4119  		}
  4120  
  4121  	case 46: /* cls */
  4122  		o1 = c.opbit(p, p.As)
  4123  
  4124  		o1 |= uint32(p.From.Reg&31) << 5
  4125  		o1 |= uint32(p.To.Reg & 31)
  4126  
  4127  	case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt
  4128  		rs := p.From.Reg
  4129  		rt := p.RegTo2
  4130  		rb := p.To.Reg
  4131  
  4132  		// rt can't be sp.
  4133  		if rt == REG_RSP {
  4134  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4135  		}
  4136  		if enc, ok := atomicLDADD[p.As]; ok {
  4137  			// for LDADDx-like instructions, rt can't be r31 when field.enc A is 0, A bit is the 23rd bit.
  4138  			if (rt == REGZERO) && (enc&(1<<23) == 0) {
  4139  				c.ctxt.Diag("illegal destination register: %v\n", p)
  4140  			}
  4141  			o1 |= enc
  4142  		} else if enc, ok := atomicSWP[p.As]; ok {
  4143  			o1 |= enc
  4144  		} else {
  4145  			c.ctxt.Diag("invalid atomic instructions: %v\n", p)
  4146  		}
  4147  		o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  4148  
  4149  	case 48: /* ADD $C_ADDCON2, Rm, Rd */
  4150  		// NOTE: this case does not use REGTMP. If it ever does,
  4151  		// remove the NOTUSETMP flag in optab.
  4152  		op := c.opirr(p, p.As)
  4153  		if op&Sbit != 0 {
  4154  			c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
  4155  		}
  4156  		rt := int(p.To.Reg)
  4157  		r := int(p.Reg)
  4158  		if r == 0 {
  4159  			r = rt
  4160  		}
  4161  		o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
  4162  		o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
  4163  
  4164  	case 50: /* sys/sysl */
  4165  		o1 = c.opirr(p, p.As)
  4166  
  4167  		if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
  4168  			c.ctxt.Diag("illegal SYS argument\n%v", p)
  4169  		}
  4170  		o1 |= uint32(p.From.Offset)
  4171  		if p.To.Type == obj.TYPE_REG {
  4172  			o1 |= uint32(p.To.Reg & 31)
  4173  		} else if p.Reg != 0 {
  4174  			o1 |= uint32(p.Reg & 31)
  4175  		} else {
  4176  			o1 |= 0x1F
  4177  		}
  4178  
  4179  	case 51: /* dmb */
  4180  		o1 = c.opirr(p, p.As)
  4181  
  4182  		if p.From.Type == obj.TYPE_CONST {
  4183  			o1 |= uint32((p.From.Offset & 0xF) << 8)
  4184  		}
  4185  
  4186  	case 52: /* hint */
  4187  		o1 = c.opirr(p, p.As)
  4188  
  4189  		o1 |= uint32((p.From.Offset & 0x7F) << 5)
  4190  
  4191  	case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
  4192  		a := p.As
  4193  		rt := int(p.To.Reg)
  4194  		if p.To.Type == obj.TYPE_NONE {
  4195  			rt = REGZERO
  4196  		}
  4197  		r := int(p.Reg)
  4198  		if r == 0 {
  4199  			r = rt
  4200  		}
  4201  		mode := 64
  4202  		v := uint64(p.From.Offset)
  4203  		switch p.As {
  4204  		case AANDW, AORRW, AEORW, AANDSW, ATSTW:
  4205  			mode = 32
  4206  		case ABIC, AORN, AEON, ABICS:
  4207  			v = ^v
  4208  		case ABICW, AORNW, AEONW, ABICSW:
  4209  			v = ^v
  4210  			mode = 32
  4211  		}
  4212  		o1 = c.opirr(p, a)
  4213  		o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
  4214  
  4215  	case 54: /* floating point arith */
  4216  		o1 = c.oprrr(p, p.As)
  4217  		rf := int(p.From.Reg)
  4218  		rt := int(p.To.Reg)
  4219  		r := int(p.Reg)
  4220  		if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
  4221  			r = rf
  4222  			rf = 0
  4223  		} else if r == 0 {
  4224  			r = rt
  4225  		}
  4226  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4227  
  4228  	case 55: /* floating-point constant */
  4229  		var rf int
  4230  		o1 = 0xf<<25 | 1<<21 | 1<<12
  4231  		rf = c.chipfloat7(p.From.Val.(float64))
  4232  		if rf < 0 {
  4233  			c.ctxt.Diag("invalid floating-point immediate\n%v", p)
  4234  		}
  4235  		if p.As == AFMOVD {
  4236  			o1 |= 1 << 22
  4237  		}
  4238  		o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
  4239  
  4240  	case 56: /* floating point compare */
  4241  		o1 = c.oprrr(p, p.As)
  4242  
  4243  		var rf int
  4244  		if p.From.Type == obj.TYPE_FCONST {
  4245  			o1 |= 8 /* zero */
  4246  			rf = 0
  4247  		} else {
  4248  			rf = int(p.From.Reg)
  4249  		}
  4250  		rt := int(p.Reg)
  4251  		o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
  4252  
  4253  	case 57: /* floating point conditional compare */
  4254  		o1 = c.oprrr(p, p.As)
  4255  
  4256  		cond := int(p.From.Reg)
  4257  		if cond < COND_EQ || cond > COND_NV {
  4258  			c.ctxt.Diag("invalid condition\n%v", p)
  4259  		} else {
  4260  			cond -= COND_EQ
  4261  		}
  4262  
  4263  		nzcv := int(p.To.Offset)
  4264  		if nzcv&^0xF != 0 {
  4265  			c.ctxt.Diag("implausible condition\n%v", p)
  4266  		}
  4267  		rf := int(p.Reg)
  4268  		if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
  4269  			c.ctxt.Diag("illegal FCCMP\n%v", p)
  4270  			break
  4271  		}
  4272  		rt := int(p.GetFrom3().Reg)
  4273  		o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
  4274  
  4275  	case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
  4276  		o1 = c.opload(p, p.As)
  4277  
  4278  		o1 |= 0x1F << 16
  4279  		o1 |= uint32(p.From.Reg&31) << 5
  4280  		if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
  4281  			if int(p.To.Reg) == int(p.To.Offset) {
  4282  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4283  			}
  4284  			o1 |= uint32(p.To.Offset&31) << 10
  4285  		} else {
  4286  			o1 |= 0x1F << 10
  4287  		}
  4288  		o1 |= uint32(p.To.Reg & 31)
  4289  
  4290  	case 59: /* stxr/stlxr/stxp/stlxp */
  4291  		s := p.RegTo2
  4292  		n := p.To.Reg
  4293  		t := p.From.Reg
  4294  		if isSTLXRop(p.As) {
  4295  			if s == t || (s == n && n != REGSP) {
  4296  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4297  			}
  4298  		} else if isSTXPop(p.As) {
  4299  			t2 := int16(p.From.Offset)
  4300  			if (s == t || s == t2) || (s == n && n != REGSP) {
  4301  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4302  			}
  4303  		}
  4304  		if s == REG_RSP {
  4305  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4306  		}
  4307  		o1 = c.opstore(p, p.As)
  4308  
  4309  		if p.RegTo2 != obj.REG_NONE {
  4310  			o1 |= uint32(p.RegTo2&31) << 16
  4311  		} else {
  4312  			o1 |= 0x1F << 16
  4313  		}
  4314  		if isSTXPop(p.As) {
  4315  			o1 |= uint32(p.From.Offset&31) << 10
  4316  		}
  4317  		o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
  4318  
  4319  	case 60: /* adrp label,r */
  4320  		d := c.brdist(p, 12, 21, 0)
  4321  
  4322  		o1 = ADR(1, uint32(d), uint32(p.To.Reg))
  4323  
  4324  	case 61: /* adr label, r */
  4325  		d := c.brdist(p, 0, 21, 0)
  4326  
  4327  		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
  4328  
  4329  	case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
  4330  		if p.Reg == REGTMP {
  4331  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  4332  		}
  4333  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  4334  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4335  		}
  4336  		lsl0 := LSL0_64
  4337  		if isADDWop(p.As) || isANDWop(p.As) {
  4338  			o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
  4339  			lsl0 = LSL0_32
  4340  		} else {
  4341  			o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
  4342  		}
  4343  
  4344  		rt := int(p.To.Reg)
  4345  		if p.To.Type == obj.TYPE_NONE {
  4346  			rt = REGZERO
  4347  		}
  4348  		r := int(p.Reg)
  4349  		if r == 0 {
  4350  			r = rt
  4351  		}
  4352  		if p.To.Reg == REGSP || r == REGSP {
  4353  			o2 = c.opxrrr(p, p.As, false)
  4354  			o2 |= REGTMP & 31 << 16
  4355  			o2 |= uint32(lsl0)
  4356  		} else {
  4357  			o2 = c.oprrr(p, p.As)
  4358  			o2 |= REGTMP & 31 << 16 /* shift is 0 */
  4359  		}
  4360  		o2 |= uint32(r&31) << 5
  4361  		o2 |= uint32(rt & 31)
  4362  
  4363  		/* reloc ops */
  4364  	case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
  4365  		o1 = ADR(1, 0, REGTMP)
  4366  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4367  		rel := obj.Addrel(c.cursym)
  4368  		rel.Off = int32(c.pc)
  4369  		rel.Siz = 8
  4370  		rel.Sym = p.To.Sym
  4371  		rel.Add = p.To.Offset
  4372  		rel.Type = objabi.R_ADDRARM64
  4373  		o3 = c.olsr12u(p, int32(c.opstr(p, p.As)), 0, REGTMP, int(p.From.Reg))
  4374  
  4375  	case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
  4376  		o1 = ADR(1, 0, REGTMP)
  4377  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4378  		rel := obj.Addrel(c.cursym)
  4379  		rel.Off = int32(c.pc)
  4380  		rel.Siz = 8
  4381  		rel.Sym = p.From.Sym
  4382  		rel.Add = p.From.Offset
  4383  		rel.Type = objabi.R_ADDRARM64
  4384  		o3 = c.olsr12u(p, int32(c.opldr(p, p.As)), 0, REGTMP, int(p.To.Reg))
  4385  
  4386  	case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
  4387  		v := int32(c.regoff(&p.From))
  4388  		r := int(p.From.Reg)
  4389  		if r == obj.REG_NONE {
  4390  			r = int(o.param)
  4391  		}
  4392  		if r == obj.REG_NONE {
  4393  			c.ctxt.Diag("invalid ldp source: %v\n", p)
  4394  		}
  4395  		o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4396  
  4397  	case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
  4398  		r := int(p.To.Reg)
  4399  		if r == obj.REG_NONE {
  4400  			r = int(o.param)
  4401  		}
  4402  		if r == obj.REG_NONE {
  4403  			c.ctxt.Diag("invalid stp destination: %v\n", p)
  4404  		}
  4405  		v := int32(c.regoff(&p.To))
  4406  		o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4407  
  4408  	case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
  4409  		// NOTE: this case does not use REGTMP. If it ever does,
  4410  		// remove the NOTUSETMP flag in optab.
  4411  		if p.As == AMOVW {
  4412  			c.ctxt.Diag("invalid load of 32-bit address: %v", p)
  4413  		}
  4414  		o1 = ADR(1, 0, uint32(p.To.Reg))
  4415  		o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
  4416  		rel := obj.Addrel(c.cursym)
  4417  		rel.Off = int32(c.pc)
  4418  		rel.Siz = 8
  4419  		rel.Sym = p.From.Sym
  4420  		rel.Add = p.From.Offset
  4421  		rel.Type = objabi.R_ADDRARM64
  4422  
  4423  	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
  4424  		o1 = c.opirr(p, AMOVZ)
  4425  		o1 |= uint32(p.To.Reg & 31)
  4426  		rel := obj.Addrel(c.cursym)
  4427  		rel.Off = int32(c.pc)
  4428  		rel.Siz = 4
  4429  		rel.Sym = p.From.Sym
  4430  		rel.Type = objabi.R_ARM64_TLS_LE
  4431  		if p.From.Offset != 0 {
  4432  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4433  		}
  4434  
  4435  	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
  4436  		o1 = ADR(1, 0, REGTMP)
  4437  		o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  4438  		rel := obj.Addrel(c.cursym)
  4439  		rel.Off = int32(c.pc)
  4440  		rel.Siz = 8
  4441  		rel.Sym = p.From.Sym
  4442  		rel.Add = 0
  4443  		rel.Type = objabi.R_ARM64_TLS_IE
  4444  		if p.From.Offset != 0 {
  4445  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4446  		}
  4447  
  4448  	case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
  4449  		o1 = ADR(1, 0, REGTMP)
  4450  		o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  4451  		rel := obj.Addrel(c.cursym)
  4452  		rel.Off = int32(c.pc)
  4453  		rel.Siz = 8
  4454  		rel.Sym = p.From.Sym
  4455  		rel.Add = 0
  4456  		rel.Type = objabi.R_ARM64_GOTPCREL
  4457  
  4458  	case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2/vrax1 Vm.<T>, Vn.<T>, Vd.<T> */
  4459  		af := int((p.From.Reg >> 5) & 15)
  4460  		af3 := int((p.Reg >> 5) & 15)
  4461  		at := int((p.To.Reg >> 5) & 15)
  4462  		if af != af3 || af != at {
  4463  			c.ctxt.Diag("operand mismatch: %v", p)
  4464  			break
  4465  		}
  4466  		o1 = c.oprrr(p, p.As)
  4467  		rf := int((p.From.Reg) & 31)
  4468  		rt := int((p.To.Reg) & 31)
  4469  		r := int((p.Reg) & 31)
  4470  
  4471  		Q := 0
  4472  		size := 0
  4473  		switch af {
  4474  		case ARNG_16B:
  4475  			Q = 1
  4476  			size = 0
  4477  		case ARNG_2D:
  4478  			Q = 1
  4479  			size = 3
  4480  		case ARNG_2S:
  4481  			Q = 0
  4482  			size = 2
  4483  		case ARNG_4H:
  4484  			Q = 0
  4485  			size = 1
  4486  		case ARNG_4S:
  4487  			Q = 1
  4488  			size = 2
  4489  		case ARNG_8B:
  4490  			Q = 0
  4491  			size = 0
  4492  		case ARNG_8H:
  4493  			Q = 1
  4494  			size = 1
  4495  		default:
  4496  			c.ctxt.Diag("invalid arrangement: %v", p)
  4497  		}
  4498  
  4499  		switch p.As {
  4500  		case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
  4501  			if af != ARNG_16B && af != ARNG_8B {
  4502  				c.ctxt.Diag("invalid arrangement: %v", p)
  4503  			}
  4504  		case AVFMLA, AVFMLS:
  4505  			if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
  4506  				c.ctxt.Diag("invalid arrangement: %v", p)
  4507  			}
  4508  		case AVUMAX, AVUMIN:
  4509  			if af == ARNG_2D {
  4510  				c.ctxt.Diag("invalid arrangement: %v", p)
  4511  			}
  4512  		}
  4513  		switch p.As {
  4514  		case AVAND, AVEOR:
  4515  			size = 0
  4516  		case AVBSL:
  4517  			size = 1
  4518  		case AVORR, AVBIT, AVBIF:
  4519  			size = 2
  4520  		case AVFMLA, AVFMLS:
  4521  			if af == ARNG_2D {
  4522  				size = 1
  4523  			} else {
  4524  				size = 0
  4525  			}
  4526  		case AVRAX1:
  4527  			if af != ARNG_2D {
  4528  				c.ctxt.Diag("invalid arrangement: %v", p)
  4529  			}
  4530  			size = 0
  4531  			Q = 0
  4532  		}
  4533  
  4534  		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4535  
  4536  	case 73: /* vmov V.<T>[index], R */
  4537  		rf := int(p.From.Reg)
  4538  		rt := int(p.To.Reg)
  4539  		imm5 := 0
  4540  		o1 = 7<<25 | 0xf<<10
  4541  		index := int(p.From.Index)
  4542  		switch (p.From.Reg >> 5) & 15 {
  4543  		case ARNG_B:
  4544  			c.checkindex(p, index, 15)
  4545  			imm5 |= 1
  4546  			imm5 |= index << 1
  4547  		case ARNG_H:
  4548  			c.checkindex(p, index, 7)
  4549  			imm5 |= 2
  4550  			imm5 |= index << 2
  4551  		case ARNG_S:
  4552  			c.checkindex(p, index, 3)
  4553  			imm5 |= 4
  4554  			imm5 |= index << 3
  4555  		case ARNG_D:
  4556  			c.checkindex(p, index, 1)
  4557  			imm5 |= 8
  4558  			imm5 |= index << 4
  4559  			o1 |= 1 << 30
  4560  		default:
  4561  			c.ctxt.Diag("invalid arrangement: %v", p)
  4562  		}
  4563  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4564  
  4565  	case 74:
  4566  		//	add $O, R, Rtmp or sub $O, R, Rtmp
  4567  		//	ldp (Rtmp), (R1, R2)
  4568  		r := int(p.From.Reg)
  4569  		if r == obj.REG_NONE {
  4570  			r = int(o.param)
  4571  		}
  4572  		if r == obj.REG_NONE {
  4573  			c.ctxt.Diag("invalid ldp source: %v", p)
  4574  		}
  4575  		v := int32(c.regoff(&p.From))
  4576  
  4577  		if v > 0 {
  4578  			if v > 4095 {
  4579  				c.ctxt.Diag("offset out of range: %v", p)
  4580  			}
  4581  			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  4582  		}
  4583  		if v < 0 {
  4584  			if v < -4095 {
  4585  				c.ctxt.Diag("offset out of range: %v", p)
  4586  			}
  4587  			o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  4588  		}
  4589  		o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4590  
  4591  	case 75:
  4592  		//	mov $L, Rtmp (from constant pool)
  4593  		//	add Rtmp, R, Rtmp
  4594  		//	ldp (Rtmp), (R1, R2)
  4595  		r := int(p.From.Reg)
  4596  		if r == obj.REG_NONE {
  4597  			r = int(o.param)
  4598  		}
  4599  		if r == obj.REG_NONE {
  4600  			c.ctxt.Diag("invalid ldp source: %v", p)
  4601  		}
  4602  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  4603  		o2 = c.opxrrr(p, AADD, false)
  4604  		o2 |= (REGTMP & 31) << 16
  4605  		o2 |= uint32(r&31) << 5
  4606  		o2 |= uint32(REGTMP & 31)
  4607  		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4608  
  4609  	case 76:
  4610  		//	add $O, R, Rtmp or sub $O, R, Rtmp
  4611  		//	stp (R1, R2), (Rtmp)
  4612  		r := int(p.To.Reg)
  4613  		if r == obj.REG_NONE {
  4614  			r = int(o.param)
  4615  		}
  4616  		if r == obj.REG_NONE {
  4617  			c.ctxt.Diag("invalid stp destination: %v", p)
  4618  		}
  4619  		v := int32(c.regoff(&p.To))
  4620  		if v > 0 {
  4621  			if v > 4095 {
  4622  				c.ctxt.Diag("offset out of range: %v", p)
  4623  			}
  4624  			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  4625  		}
  4626  		if v < 0 {
  4627  			if v < -4095 {
  4628  				c.ctxt.Diag("offset out of range: %v", p)
  4629  			}
  4630  			o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  4631  		}
  4632  		o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4633  
  4634  	case 77:
  4635  		//	mov $L, Rtmp (from constant pool)
  4636  		//	add Rtmp, R, Rtmp
  4637  		//	stp (R1, R2), (Rtmp)
  4638  		r := int(p.To.Reg)
  4639  		if r == obj.REG_NONE {
  4640  			r = int(o.param)
  4641  		}
  4642  		if r == obj.REG_NONE {
  4643  			c.ctxt.Diag("invalid stp destination: %v", p)
  4644  		}
  4645  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  4646  		o2 = c.opxrrr(p, AADD, false)
  4647  		o2 |= REGTMP & 31 << 16
  4648  		o2 |= uint32(r&31) << 5
  4649  		o2 |= uint32(REGTMP & 31)
  4650  		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4651  
  4652  	case 78: /* vmov R, V.<T>[index] */
  4653  		rf := int(p.From.Reg)
  4654  		rt := int(p.To.Reg)
  4655  		imm5 := 0
  4656  		o1 = 1<<30 | 7<<25 | 7<<10
  4657  		index := int(p.To.Index)
  4658  		switch (p.To.Reg >> 5) & 15 {
  4659  		case ARNG_B:
  4660  			c.checkindex(p, index, 15)
  4661  			imm5 |= 1
  4662  			imm5 |= index << 1
  4663  		case ARNG_H:
  4664  			c.checkindex(p, index, 7)
  4665  			imm5 |= 2
  4666  			imm5 |= index << 2
  4667  		case ARNG_S:
  4668  			c.checkindex(p, index, 3)
  4669  			imm5 |= 4
  4670  			imm5 |= index << 3
  4671  		case ARNG_D:
  4672  			c.checkindex(p, index, 1)
  4673  			imm5 |= 8
  4674  			imm5 |= index << 4
  4675  		default:
  4676  			c.ctxt.Diag("invalid arrangement: %v", p)
  4677  		}
  4678  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4679  
  4680  	case 79: /* vdup Vn.<T>[index], Vd.<T> */
  4681  		rf := int(p.From.Reg)
  4682  		rt := int(p.To.Reg)
  4683  		o1 = 7<<25 | 1<<10
  4684  		var imm5, Q int
  4685  		index := int(p.From.Index)
  4686  		switch (p.To.Reg >> 5) & 15 {
  4687  		case ARNG_16B:
  4688  			c.checkindex(p, index, 15)
  4689  			Q = 1
  4690  			imm5 = 1
  4691  			imm5 |= index << 1
  4692  		case ARNG_2D:
  4693  			c.checkindex(p, index, 1)
  4694  			Q = 1
  4695  			imm5 = 8
  4696  			imm5 |= index << 4
  4697  		case ARNG_2S:
  4698  			c.checkindex(p, index, 3)
  4699  			Q = 0
  4700  			imm5 = 4
  4701  			imm5 |= index << 3
  4702  		case ARNG_4H:
  4703  			c.checkindex(p, index, 7)
  4704  			Q = 0
  4705  			imm5 = 2
  4706  			imm5 |= index << 2
  4707  		case ARNG_4S:
  4708  			c.checkindex(p, index, 3)
  4709  			Q = 1
  4710  			imm5 = 4
  4711  			imm5 |= index << 3
  4712  		case ARNG_8B:
  4713  			c.checkindex(p, index, 15)
  4714  			Q = 0
  4715  			imm5 = 1
  4716  			imm5 |= index << 1
  4717  		case ARNG_8H:
  4718  			c.checkindex(p, index, 7)
  4719  			Q = 1
  4720  			imm5 = 2
  4721  			imm5 |= index << 2
  4722  		default:
  4723  			c.ctxt.Diag("invalid arrangement: %v", p)
  4724  		}
  4725  		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  4726  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4727  
  4728  	case 80: /* vmov/vdup V.<T>[index], Vn */
  4729  		rf := int(p.From.Reg)
  4730  		rt := int(p.To.Reg)
  4731  		imm5 := 0
  4732  		index := int(p.From.Index)
  4733  		switch p.As {
  4734  		case AVMOV, AVDUP:
  4735  			o1 = 1<<30 | 15<<25 | 1<<10
  4736  			switch (p.From.Reg >> 5) & 15 {
  4737  			case ARNG_B:
  4738  				c.checkindex(p, index, 15)
  4739  				imm5 |= 1
  4740  				imm5 |= index << 1
  4741  			case ARNG_H:
  4742  				c.checkindex(p, index, 7)
  4743  				imm5 |= 2
  4744  				imm5 |= index << 2
  4745  			case ARNG_S:
  4746  				c.checkindex(p, index, 3)
  4747  				imm5 |= 4
  4748  				imm5 |= index << 3
  4749  			case ARNG_D:
  4750  				c.checkindex(p, index, 1)
  4751  				imm5 |= 8
  4752  				imm5 |= index << 4
  4753  			default:
  4754  				c.ctxt.Diag("invalid arrangement: %v", p)
  4755  			}
  4756  		default:
  4757  			c.ctxt.Diag("unsupported op %v", p.As)
  4758  		}
  4759  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4760  
  4761  	case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
  4762  		c.checkoffset(p, p.As)
  4763  		r := int(p.From.Reg)
  4764  		o1 = c.oprrr(p, p.As)
  4765  		if o.scond == C_XPOST {
  4766  			o1 |= 1 << 23
  4767  			if p.From.Index == 0 {
  4768  				// immediate offset variant
  4769  				o1 |= 0x1f << 16
  4770  			} else {
  4771  				// register offset variant
  4772  				if isRegShiftOrExt(&p.From) {
  4773  					c.ctxt.Diag("invalid extended register op: %v\n", p)
  4774  				}
  4775  				o1 |= uint32(p.From.Index&0x1f) << 16
  4776  			}
  4777  		}
  4778  		o1 |= uint32(p.To.Offset)
  4779  		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  4780  		// add opcode(bit 12-15) for vld1, mask it off if it's not vld1
  4781  		o1 = c.maskOpvldvst(p, o1)
  4782  		o1 |= uint32(r&31) << 5
  4783  
  4784  	case 82: /* vmov/vdup Rn, Vd.<T> */
  4785  		rf := int(p.From.Reg)
  4786  		rt := int(p.To.Reg)
  4787  		o1 = 7<<25 | 3<<10
  4788  		var imm5, Q uint32
  4789  		switch (p.To.Reg >> 5) & 15 {
  4790  		case ARNG_16B:
  4791  			Q = 1
  4792  			imm5 = 1
  4793  		case ARNG_2D:
  4794  			Q = 1
  4795  			imm5 = 8
  4796  		case ARNG_2S:
  4797  			Q = 0
  4798  			imm5 = 4
  4799  		case ARNG_4H:
  4800  			Q = 0
  4801  			imm5 = 2
  4802  		case ARNG_4S:
  4803  			Q = 1
  4804  			imm5 = 4
  4805  		case ARNG_8B:
  4806  			Q = 0
  4807  			imm5 = 1
  4808  		case ARNG_8H:
  4809  			Q = 1
  4810  			imm5 = 2
  4811  		default:
  4812  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  4813  		}
  4814  		o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
  4815  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4816  
  4817  	case 83: /* vmov Vn.<T>, Vd.<T> */
  4818  		af := int((p.From.Reg >> 5) & 15)
  4819  		at := int((p.To.Reg >> 5) & 15)
  4820  		if af != at {
  4821  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  4822  		}
  4823  		o1 = c.oprrr(p, p.As)
  4824  		rf := int((p.From.Reg) & 31)
  4825  		rt := int((p.To.Reg) & 31)
  4826  
  4827  		var Q, size uint32
  4828  		switch af {
  4829  		case ARNG_8B:
  4830  			Q = 0
  4831  			size = 0
  4832  		case ARNG_16B:
  4833  			Q = 1
  4834  			size = 0
  4835  		case ARNG_4H:
  4836  			Q = 0
  4837  			size = 1
  4838  		case ARNG_8H:
  4839  			Q = 1
  4840  			size = 1
  4841  		case ARNG_2S:
  4842  			Q = 0
  4843  			size = 2
  4844  		case ARNG_4S:
  4845  			Q = 1
  4846  			size = 2
  4847  		default:
  4848  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  4849  		}
  4850  
  4851  		if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
  4852  			c.ctxt.Diag("invalid arrangement: %v", p)
  4853  		}
  4854  
  4855  		if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
  4856  			c.ctxt.Diag("invalid arrangement: %v", p)
  4857  		}
  4858  
  4859  		if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
  4860  			c.ctxt.Diag("invalid arrangement: %v", p)
  4861  		}
  4862  
  4863  		if p.As == AVMOV {
  4864  			o1 |= uint32(rf&31) << 16
  4865  		}
  4866  
  4867  		if p.As == AVRBIT {
  4868  			size = 1
  4869  		}
  4870  
  4871  		o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
  4872  
  4873  	case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
  4874  		c.checkoffset(p, p.As)
  4875  		r := int(p.To.Reg)
  4876  		o1 = 3 << 26
  4877  		if o.scond == C_XPOST {
  4878  			o1 |= 1 << 23
  4879  			if p.To.Index == 0 {
  4880  				// immediate offset variant
  4881  				o1 |= 0x1f << 16
  4882  			} else {
  4883  				// register offset variant
  4884  				if isRegShiftOrExt(&p.To) {
  4885  					c.ctxt.Diag("invalid extended register: %v\n", p)
  4886  				}
  4887  				o1 |= uint32(p.To.Index&31) << 16
  4888  			}
  4889  		}
  4890  		o1 |= uint32(p.From.Offset)
  4891  		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  4892  		// add opcode(bit 12-15) for vst1, mask it off if it's not vst1
  4893  		o1 = c.maskOpvldvst(p, o1)
  4894  		o1 |= uint32(r&31) << 5
  4895  
  4896  	case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
  4897  		af := int((p.From.Reg >> 5) & 15)
  4898  		o1 = c.oprrr(p, p.As)
  4899  		rf := int((p.From.Reg) & 31)
  4900  		rt := int((p.To.Reg) & 31)
  4901  		Q := 0
  4902  		size := 0
  4903  		switch af {
  4904  		case ARNG_8B:
  4905  			Q = 0
  4906  			size = 0
  4907  		case ARNG_16B:
  4908  			Q = 1
  4909  			size = 0
  4910  		case ARNG_4H:
  4911  			Q = 0
  4912  			size = 1
  4913  		case ARNG_8H:
  4914  			Q = 1
  4915  			size = 1
  4916  		case ARNG_4S:
  4917  			Q = 1
  4918  			size = 2
  4919  		default:
  4920  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  4921  		}
  4922  		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
  4923  
  4924  	case 86: /* vmovi $imm8, Vd.<T>*/
  4925  		at := int((p.To.Reg >> 5) & 15)
  4926  		r := int(p.From.Offset)
  4927  		if r > 255 || r < 0 {
  4928  			c.ctxt.Diag("immediate constant out of range: %v\n", p)
  4929  		}
  4930  		rt := int((p.To.Reg) & 31)
  4931  		Q := 0
  4932  		switch at {
  4933  		case ARNG_8B:
  4934  			Q = 0
  4935  		case ARNG_16B:
  4936  			Q = 1
  4937  		default:
  4938  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  4939  		}
  4940  		o1 = 0xf<<24 | 0xe<<12 | 1<<10
  4941  		o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
  4942  
  4943  	case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
  4944  		o1 = ADR(1, 0, REGTMP)
  4945  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4946  		rel := obj.Addrel(c.cursym)
  4947  		rel.Off = int32(c.pc)
  4948  		rel.Siz = 8
  4949  		rel.Sym = p.To.Sym
  4950  		rel.Add = p.To.Offset
  4951  		rel.Type = objabi.R_ADDRARM64
  4952  		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4953  
  4954  	case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
  4955  		o1 = ADR(1, 0, REGTMP)
  4956  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4957  		rel := obj.Addrel(c.cursym)
  4958  		rel.Off = int32(c.pc)
  4959  		rel.Siz = 8
  4960  		rel.Sym = p.From.Sym
  4961  		rel.Add = p.From.Offset
  4962  		rel.Type = objabi.R_ADDRARM64
  4963  		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4964  
  4965  	case 89: /* vadd/vsub Vm, Vn, Vd */
  4966  		switch p.As {
  4967  		case AVADD:
  4968  			o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4969  
  4970  		case AVSUB:
  4971  			o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4972  
  4973  		default:
  4974  			c.ctxt.Diag("bad opcode: %v\n", p)
  4975  			break
  4976  		}
  4977  
  4978  		rf := int(p.From.Reg)
  4979  		rt := int(p.To.Reg)
  4980  		r := int(p.Reg)
  4981  		if r == 0 {
  4982  			r = rt
  4983  		}
  4984  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4985  
  4986  	// This is supposed to be something that stops execution.
  4987  	// It's not supposed to be reached, ever, but if it is, we'd
  4988  	// like to be able to tell how we got there. Assemble as
  4989  	// 0xbea71700 which is guaranteed to raise undefined instruction
  4990  	// exception.
  4991  	case 90:
  4992  		o1 = 0xbea71700
  4993  
  4994  	case 91: /* prfm imm(Rn), <prfop | $imm5> */
  4995  		imm := uint32(p.From.Offset)
  4996  		r := p.From.Reg
  4997  		v := uint32(0xff)
  4998  		if p.To.Type == obj.TYPE_CONST {
  4999  			v = uint32(p.To.Offset)
  5000  			if v > 31 {
  5001  				c.ctxt.Diag("illegal prefetch operation\n%v", p)
  5002  			}
  5003  		} else {
  5004  			for i := 0; i < len(prfopfield); i++ {
  5005  				if prfopfield[i].reg == p.To.Reg {
  5006  					v = prfopfield[i].enc
  5007  					break
  5008  				}
  5009  			}
  5010  			if v == 0xff {
  5011  				c.ctxt.Diag("illegal prefetch operation:\n%v", p)
  5012  			}
  5013  		}
  5014  
  5015  		o1 = c.opirr(p, p.As)
  5016  		o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
  5017  
  5018  	case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
  5019  		rf := int(p.From.Reg)
  5020  		rt := int(p.To.Reg)
  5021  		imm4 := 0
  5022  		imm5 := 0
  5023  		o1 = 3<<29 | 7<<25 | 1<<10
  5024  		index1 := int(p.To.Index)
  5025  		index2 := int(p.From.Index)
  5026  		if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
  5027  			c.ctxt.Diag("operand mismatch: %v", p)
  5028  		}
  5029  		switch (p.To.Reg >> 5) & 15 {
  5030  		case ARNG_B:
  5031  			c.checkindex(p, index1, 15)
  5032  			c.checkindex(p, index2, 15)
  5033  			imm5 |= 1
  5034  			imm5 |= index1 << 1
  5035  			imm4 |= index2
  5036  		case ARNG_H:
  5037  			c.checkindex(p, index1, 7)
  5038  			c.checkindex(p, index2, 7)
  5039  			imm5 |= 2
  5040  			imm5 |= index1 << 2
  5041  			imm4 |= index2 << 1
  5042  		case ARNG_S:
  5043  			c.checkindex(p, index1, 3)
  5044  			c.checkindex(p, index2, 3)
  5045  			imm5 |= 4
  5046  			imm5 |= index1 << 3
  5047  			imm4 |= index2 << 2
  5048  		case ARNG_D:
  5049  			c.checkindex(p, index1, 1)
  5050  			c.checkindex(p, index2, 1)
  5051  			imm5 |= 8
  5052  			imm5 |= index1 << 4
  5053  			imm4 |= index2 << 3
  5054  		default:
  5055  			c.ctxt.Diag("invalid arrangement: %v", p)
  5056  		}
  5057  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  5058  
  5059  	case 93: /* vpmull{2} Vm.<Tb>, Vn.<Tb>, Vd.<Ta> */
  5060  		af := uint8((p.From.Reg >> 5) & 15)
  5061  		at := uint8((p.To.Reg >> 5) & 15)
  5062  		a := uint8((p.Reg >> 5) & 15)
  5063  		if af != a {
  5064  			c.ctxt.Diag("invalid arrangement: %v", p)
  5065  		}
  5066  
  5067  		var Q, size uint32
  5068  		if p.As == AVPMULL2 {
  5069  			Q = 1
  5070  		}
  5071  		switch pack(Q, at, af) {
  5072  		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
  5073  			size = 0
  5074  		case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D):
  5075  			size = 3
  5076  		default:
  5077  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5078  		}
  5079  
  5080  		o1 = c.oprrr(p, p.As)
  5081  		rf := int((p.From.Reg) & 31)
  5082  		rt := int((p.To.Reg) & 31)
  5083  		r := int((p.Reg) & 31)
  5084  		o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  5085  
  5086  	case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  5087  		af := int(((p.GetFrom3().Reg) >> 5) & 15)
  5088  		at := int((p.To.Reg >> 5) & 15)
  5089  		a := int((p.Reg >> 5) & 15)
  5090  		index := int(p.From.Offset)
  5091  
  5092  		if af != a || af != at {
  5093  			c.ctxt.Diag("invalid arrangement: %v", p)
  5094  			break
  5095  		}
  5096  
  5097  		var Q uint32
  5098  		var b int
  5099  		if af == ARNG_8B {
  5100  			Q = 0
  5101  			b = 7
  5102  		} else if af == ARNG_16B {
  5103  			Q = 1
  5104  			b = 15
  5105  		} else {
  5106  			c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
  5107  			break
  5108  		}
  5109  
  5110  		if index < 0 || index > b {
  5111  			c.ctxt.Diag("illegal offset: %v", p)
  5112  		}
  5113  
  5114  		o1 = c.opirr(p, p.As)
  5115  		rf := int((p.GetFrom3().Reg) & 31)
  5116  		rt := int((p.To.Reg) & 31)
  5117  		r := int((p.Reg) & 31)
  5118  
  5119  		o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  5120  
  5121  	case 95: /* vushr/vshl/vsri/vsli/vusra $shift, Vn.<T>, Vd.<T> */
  5122  		at := int((p.To.Reg >> 5) & 15)
  5123  		af := int((p.Reg >> 5) & 15)
  5124  		shift := int(p.From.Offset)
  5125  
  5126  		if af != at {
  5127  			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  5128  		}
  5129  
  5130  		var Q uint32
  5131  		var imax, esize int
  5132  
  5133  		switch af {
  5134  		case ARNG_8B, ARNG_4H, ARNG_2S:
  5135  			Q = 0
  5136  		case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
  5137  			Q = 1
  5138  		default:
  5139  			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  5140  		}
  5141  
  5142  		switch af {
  5143  		case ARNG_8B, ARNG_16B:
  5144  			imax = 15
  5145  			esize = 8
  5146  		case ARNG_4H, ARNG_8H:
  5147  			imax = 31
  5148  			esize = 16
  5149  		case ARNG_2S, ARNG_4S:
  5150  			imax = 63
  5151  			esize = 32
  5152  		case ARNG_2D:
  5153  			imax = 127
  5154  			esize = 64
  5155  		}
  5156  
  5157  		imm := 0
  5158  		switch p.As {
  5159  		case AVUSHR, AVSRI, AVUSRA:
  5160  			imm = esize*2 - shift
  5161  			if imm < esize || imm > imax {
  5162  				c.ctxt.Diag("shift out of range: %v", p)
  5163  			}
  5164  		case AVSHL, AVSLI:
  5165  			imm = esize + shift
  5166  			if imm > imax {
  5167  				c.ctxt.Diag("shift out of range: %v", p)
  5168  			}
  5169  		default:
  5170  			c.ctxt.Diag("invalid instruction %v\n", p)
  5171  		}
  5172  
  5173  		o1 = c.opirr(p, p.As)
  5174  		rt := int((p.To.Reg) & 31)
  5175  		rf := int((p.Reg) & 31)
  5176  
  5177  		o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  5178  
  5179  	case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
  5180  		af := int((p.From.Reg >> 5) & 15)
  5181  		rt := int((p.From.Reg) & 31)
  5182  		rf := int((p.To.Reg) & 31)
  5183  		r := int(p.To.Index & 31)
  5184  		index := int(p.From.Index)
  5185  		offset := int32(c.regoff(&p.To))
  5186  
  5187  		if o.scond == C_XPOST {
  5188  			if (p.To.Index != 0) && (offset != 0) {
  5189  				c.ctxt.Diag("invalid offset: %v", p)
  5190  			}
  5191  			if p.To.Index == 0 && offset == 0 {
  5192  				c.ctxt.Diag("invalid offset: %v", p)
  5193  			}
  5194  		}
  5195  
  5196  		if offset != 0 {
  5197  			r = 31
  5198  		}
  5199  
  5200  		var Q, S, size int
  5201  		var opcode uint32
  5202  		switch af {
  5203  		case ARNG_B:
  5204  			c.checkindex(p, index, 15)
  5205  			if o.scond == C_XPOST && offset != 0 && offset != 1 {
  5206  				c.ctxt.Diag("invalid offset: %v", p)
  5207  			}
  5208  			Q = index >> 3
  5209  			S = (index >> 2) & 1
  5210  			size = index & 3
  5211  			opcode = 0
  5212  		case ARNG_H:
  5213  			c.checkindex(p, index, 7)
  5214  			if o.scond == C_XPOST && offset != 0 && offset != 2 {
  5215  				c.ctxt.Diag("invalid offset: %v", p)
  5216  			}
  5217  			Q = index >> 2
  5218  			S = (index >> 1) & 1
  5219  			size = (index & 1) << 1
  5220  			opcode = 2
  5221  		case ARNG_S:
  5222  			c.checkindex(p, index, 3)
  5223  			if o.scond == C_XPOST && offset != 0 && offset != 4 {
  5224  				c.ctxt.Diag("invalid offset: %v", p)
  5225  			}
  5226  			Q = index >> 1
  5227  			S = index & 1
  5228  			size = 0
  5229  			opcode = 4
  5230  		case ARNG_D:
  5231  			c.checkindex(p, index, 1)
  5232  			if o.scond == C_XPOST && offset != 0 && offset != 8 {
  5233  				c.ctxt.Diag("invalid offset: %v", p)
  5234  			}
  5235  			Q = index
  5236  			S = 0
  5237  			size = 1
  5238  			opcode = 4
  5239  		default:
  5240  			c.ctxt.Diag("invalid arrangement: %v", p)
  5241  		}
  5242  
  5243  		if o.scond == C_XPOST {
  5244  			o1 |= 27 << 23
  5245  		} else {
  5246  			o1 |= 26 << 23
  5247  		}
  5248  
  5249  		o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  5250  
  5251  	case 97: /* vld1 offset(Rn), vt.<T>[index] */
  5252  		at := int((p.To.Reg >> 5) & 15)
  5253  		rt := int((p.To.Reg) & 31)
  5254  		rf := int((p.From.Reg) & 31)
  5255  		r := int(p.From.Index & 31)
  5256  		index := int(p.To.Index)
  5257  		offset := int32(c.regoff(&p.From))
  5258  
  5259  		if o.scond == C_XPOST {
  5260  			if (p.From.Index != 0) && (offset != 0) {
  5261  				c.ctxt.Diag("invalid offset: %v", p)
  5262  			}
  5263  			if p.From.Index == 0 && offset == 0 {
  5264  				c.ctxt.Diag("invalid offset: %v", p)
  5265  			}
  5266  		}
  5267  
  5268  		if offset != 0 {
  5269  			r = 31
  5270  		}
  5271  
  5272  		Q := 0
  5273  		S := 0
  5274  		size := 0
  5275  		var opcode uint32
  5276  		switch at {
  5277  		case ARNG_B:
  5278  			c.checkindex(p, index, 15)
  5279  			if o.scond == C_XPOST && offset != 0 && offset != 1 {
  5280  				c.ctxt.Diag("invalid offset: %v", p)
  5281  			}
  5282  			Q = index >> 3
  5283  			S = (index >> 2) & 1
  5284  			size = index & 3
  5285  			opcode = 0
  5286  		case ARNG_H:
  5287  			c.checkindex(p, index, 7)
  5288  			if o.scond == C_XPOST && offset != 0 && offset != 2 {
  5289  				c.ctxt.Diag("invalid offset: %v", p)
  5290  			}
  5291  			Q = index >> 2
  5292  			S = (index >> 1) & 1
  5293  			size = (index & 1) << 1
  5294  			opcode = 2
  5295  		case ARNG_S:
  5296  			c.checkindex(p, index, 3)
  5297  			if o.scond == C_XPOST && offset != 0 && offset != 4 {
  5298  				c.ctxt.Diag("invalid offset: %v", p)
  5299  			}
  5300  			Q = index >> 1
  5301  			S = index & 1
  5302  			size = 0
  5303  			opcode = 4
  5304  		case ARNG_D:
  5305  			c.checkindex(p, index, 1)
  5306  			if o.scond == C_XPOST && offset != 0 && offset != 8 {
  5307  				c.ctxt.Diag("invalid offset: %v", p)
  5308  			}
  5309  			Q = index
  5310  			S = 0
  5311  			size = 1
  5312  			opcode = 4
  5313  		default:
  5314  			c.ctxt.Diag("invalid arrangement: %v", p)
  5315  		}
  5316  
  5317  		if o.scond == C_XPOST {
  5318  			o1 |= 110 << 21
  5319  		} else {
  5320  			o1 |= 106 << 21
  5321  		}
  5322  
  5323  		o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  5324  
  5325  	case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
  5326  		if isRegShiftOrExt(&p.From) {
  5327  			// extended or shifted offset register.
  5328  			c.checkShiftAmount(p, &p.From)
  5329  
  5330  			o1 = c.opldrr(p, p.As, true)
  5331  			o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
  5332  		} else {
  5333  			// (Rn)(Rm), no extension or shift.
  5334  			o1 = c.opldrr(p, p.As, false)
  5335  			o1 |= uint32(p.From.Index&31) << 16
  5336  		}
  5337  		o1 |= uint32(p.From.Reg&31) << 5
  5338  		rt := int(p.To.Reg)
  5339  		o1 |= uint32(rt & 31)
  5340  
  5341  	case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
  5342  		if isRegShiftOrExt(&p.To) {
  5343  			// extended or shifted offset register.
  5344  			c.checkShiftAmount(p, &p.To)
  5345  
  5346  			o1 = c.opstrr(p, p.As, true)
  5347  			o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
  5348  		} else {
  5349  			// (Rn)(Rm), no extension or shift.
  5350  			o1 = c.opstrr(p, p.As, false)
  5351  			o1 |= uint32(p.To.Index&31) << 16
  5352  		}
  5353  		o1 |= uint32(p.To.Reg&31) << 5
  5354  		rf := int(p.From.Reg)
  5355  		o1 |= uint32(rf & 31)
  5356  
  5357  	case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
  5358  		af := int((p.From.Reg >> 5) & 15)
  5359  		at := int((p.To.Reg >> 5) & 15)
  5360  		if af != at {
  5361  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5362  		}
  5363  		var q, len uint32
  5364  		switch af {
  5365  		case ARNG_8B:
  5366  			q = 0
  5367  		case ARNG_16B:
  5368  			q = 1
  5369  		default:
  5370  			c.ctxt.Diag("invalid arrangement: %v", p)
  5371  		}
  5372  		rf := int(p.From.Reg)
  5373  		rt := int(p.To.Reg)
  5374  		offset := int(p.GetFrom3().Offset)
  5375  		opcode := (offset >> 12) & 15
  5376  		switch opcode {
  5377  		case 0x7:
  5378  			len = 0 // one register
  5379  		case 0xa:
  5380  			len = 1 // two register
  5381  		case 0x6:
  5382  			len = 2 // three registers
  5383  		case 0x2:
  5384  			len = 3 // four registers
  5385  		default:
  5386  			c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  5387  		}
  5388  		o1 = q<<30 | 0xe<<24 | len<<13
  5389  		o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
  5390  
  5391  	case 101: // VMOVQ $vcon1, $vcon2, Vd or VMOVD|VMOVS $vcon, Vd -> FMOVQ/FMOVD/FMOVS pool(PC), Vd: load from constant pool.
  5392  		o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
  5393  
  5394  	case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
  5395  		o1 = c.opirr(p, p.As)
  5396  		rf := p.Reg
  5397  		af := uint8((p.Reg >> 5) & 15)
  5398  		at := uint8((p.To.Reg >> 5) & 15)
  5399  		shift := int(p.From.Offset)
  5400  		if p.As == AVUXTL || p.As == AVUXTL2 {
  5401  			rf = p.From.Reg
  5402  			af = uint8((p.From.Reg >> 5) & 15)
  5403  			shift = 0
  5404  		}
  5405  
  5406  		Q := (o1 >> 30) & 1
  5407  		var immh, width uint8
  5408  		switch pack(Q, af, at) {
  5409  		case pack(0, ARNG_8B, ARNG_8H):
  5410  			immh, width = 1, 8
  5411  		case pack(1, ARNG_16B, ARNG_8H):
  5412  			immh, width = 1, 8
  5413  		case pack(0, ARNG_4H, ARNG_4S):
  5414  			immh, width = 2, 16
  5415  		case pack(1, ARNG_8H, ARNG_4S):
  5416  			immh, width = 2, 16
  5417  		case pack(0, ARNG_2S, ARNG_2D):
  5418  			immh, width = 4, 32
  5419  		case pack(1, ARNG_4S, ARNG_2D):
  5420  			immh, width = 4, 32
  5421  		default:
  5422  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5423  		}
  5424  		if !(0 <= shift && shift <= int(width-1)) {
  5425  			c.ctxt.Diag("shift amount out of range: %v\n", p)
  5426  		}
  5427  		o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
  5428  
  5429  	case 103: /* VEOR3/VBCAX Va.B16, Vm.B16, Vn.B16, Vd.B16 */
  5430  		ta := (p.From.Reg >> 5) & 15
  5431  		tm := (p.Reg >> 5) & 15
  5432  		td := (p.To.Reg >> 5) & 15
  5433  		tn := ((p.GetFrom3().Reg) >> 5) & 15
  5434  
  5435  		if ta != tm || ta != tn || ta != td || ta != ARNG_16B {
  5436  			c.ctxt.Diag("invalid arrangement: %v", p)
  5437  			break
  5438  		}
  5439  
  5440  		o1 = c.oprrr(p, p.As)
  5441  		ra := int(p.From.Reg)
  5442  		rm := int(p.Reg)
  5443  		rn := int(p.GetFrom3().Reg)
  5444  		rd := int(p.To.Reg)
  5445  		o1 |= uint32(rm&31)<<16 | uint32(ra&31)<<10 | uint32(rn&31)<<5 | uint32(rd)&31
  5446  
  5447  	case 104: /* vxar $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  5448  		af := ((p.GetFrom3().Reg) >> 5) & 15
  5449  		at := (p.To.Reg >> 5) & 15
  5450  		a := (p.Reg >> 5) & 15
  5451  		index := int(p.From.Offset)
  5452  
  5453  		if af != a || af != at {
  5454  			c.ctxt.Diag("invalid arrangement: %v", p)
  5455  			break
  5456  		}
  5457  
  5458  		if af != ARNG_2D {
  5459  			c.ctxt.Diag("invalid arrangement, should be D2: %v", p)
  5460  			break
  5461  		}
  5462  
  5463  		if index < 0 || index > 63 {
  5464  			c.ctxt.Diag("illegal offset: %v", p)
  5465  		}
  5466  
  5467  		o1 = c.opirr(p, p.As)
  5468  		rf := (p.GetFrom3().Reg) & 31
  5469  		rt := (p.To.Reg) & 31
  5470  		r := (p.Reg) & 31
  5471  
  5472  		o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  5473  
  5474  	case 105: /* vuaddw{2} Vm.<Tb>, Vn.<Ta>, Vd.<Ta> */
  5475  		af := uint8((p.From.Reg >> 5) & 15)
  5476  		at := uint8((p.To.Reg >> 5) & 15)
  5477  		a := uint8((p.Reg >> 5) & 15)
  5478  		if at != a {
  5479  			c.ctxt.Diag("invalid arrangement: %v", p)
  5480  			break
  5481  		}
  5482  
  5483  		var Q, size uint32
  5484  		if p.As == AVUADDW2 {
  5485  			Q = 1
  5486  		}
  5487  		switch pack(Q, at, af) {
  5488  		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
  5489  			size = 0
  5490  		case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H):
  5491  			size = 1
  5492  		case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S):
  5493  			size = 2
  5494  		default:
  5495  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5496  		}
  5497  
  5498  		o1 = c.oprrr(p, p.As)
  5499  		rf := int((p.From.Reg) & 31)
  5500  		rt := int((p.To.Reg) & 31)
  5501  		r := int((p.Reg) & 31)
  5502  		o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  5503  
  5504  	case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1)
  5505  		rs := p.From.Reg
  5506  		rt := p.GetTo2().Reg
  5507  		rb := p.To.Reg
  5508  		rs1 := int16(p.From.Offset)
  5509  		rt1 := int16(p.GetTo2().Offset)
  5510  
  5511  		enc, ok := atomicCASP[p.As]
  5512  		if !ok {
  5513  			c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p)
  5514  		}
  5515  		// for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1
  5516  		switch {
  5517  		case rs&1 != 0:
  5518  			c.ctxt.Diag("source register pair must start from even register: %v\n", p)
  5519  			break
  5520  		case rt&1 != 0:
  5521  			c.ctxt.Diag("destination register pair must start from even register: %v\n", p)
  5522  			break
  5523  		case rs != rs1-1:
  5524  			c.ctxt.Diag("source register pair must be contiguous: %v\n", p)
  5525  			break
  5526  		case rt != rt1-1:
  5527  			c.ctxt.Diag("destination register pair must be contiguous: %v\n", p)
  5528  			break
  5529  		}
  5530  		// rt can't be sp.
  5531  		if rt == REG_RSP {
  5532  			c.ctxt.Diag("illegal destination register: %v\n", p)
  5533  		}
  5534  		o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  5535  	}
  5536  	out[0] = o1
  5537  	out[1] = o2
  5538  	out[2] = o3
  5539  	out[3] = o4
  5540  	out[4] = o5
  5541  }
  5542  
  5543  /*
  5544   * basic Rm op Rn -> Rd (using shifted register with 0)
  5545   * also op Rn -> Rt
  5546   * also Rm*Rn op Ra -> Rd
  5547   * also Vm op Vn -> Vd
  5548   */
  5549  func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
  5550  	switch a {
  5551  	case AADC:
  5552  		return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5553  
  5554  	case AADCW:
  5555  		return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5556  
  5557  	case AADCS:
  5558  		return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5559  
  5560  	case AADCSW:
  5561  		return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5562  
  5563  	case ANGC, ASBC:
  5564  		return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5565  
  5566  	case ANGCS, ASBCS:
  5567  		return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5568  
  5569  	case ANGCW, ASBCW:
  5570  		return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5571  
  5572  	case ANGCSW, ASBCSW:
  5573  		return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5574  
  5575  	case AADD:
  5576  		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5577  
  5578  	case AADDW:
  5579  		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5580  
  5581  	case ACMN, AADDS:
  5582  		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5583  
  5584  	case ACMNW, AADDSW:
  5585  		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5586  
  5587  	case ASUB:
  5588  		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5589  
  5590  	case ASUBW:
  5591  		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5592  
  5593  	case ACMP, ASUBS:
  5594  		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5595  
  5596  	case ACMPW, ASUBSW:
  5597  		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5598  
  5599  	case AAND:
  5600  		return S64 | 0<<29 | 0xA<<24
  5601  
  5602  	case AANDW:
  5603  		return S32 | 0<<29 | 0xA<<24
  5604  
  5605  	case AMOVD, AORR:
  5606  		return S64 | 1<<29 | 0xA<<24
  5607  
  5608  		//	case AMOVW:
  5609  	case AMOVWU, AORRW:
  5610  		return S32 | 1<<29 | 0xA<<24
  5611  
  5612  	case AEOR:
  5613  		return S64 | 2<<29 | 0xA<<24
  5614  
  5615  	case AEORW:
  5616  		return S32 | 2<<29 | 0xA<<24
  5617  
  5618  	case AANDS, ATST:
  5619  		return S64 | 3<<29 | 0xA<<24
  5620  
  5621  	case AANDSW, ATSTW:
  5622  		return S32 | 3<<29 | 0xA<<24
  5623  
  5624  	case ABIC:
  5625  		return S64 | 0<<29 | 0xA<<24 | 1<<21
  5626  
  5627  	case ABICW:
  5628  		return S32 | 0<<29 | 0xA<<24 | 1<<21
  5629  
  5630  	case ABICS:
  5631  		return S64 | 3<<29 | 0xA<<24 | 1<<21
  5632  
  5633  	case ABICSW:
  5634  		return S32 | 3<<29 | 0xA<<24 | 1<<21
  5635  
  5636  	case AEON:
  5637  		return S64 | 2<<29 | 0xA<<24 | 1<<21
  5638  
  5639  	case AEONW:
  5640  		return S32 | 2<<29 | 0xA<<24 | 1<<21
  5641  
  5642  	case AMVN, AORN:
  5643  		return S64 | 1<<29 | 0xA<<24 | 1<<21
  5644  
  5645  	case AMVNW, AORNW:
  5646  		return S32 | 1<<29 | 0xA<<24 | 1<<21
  5647  
  5648  	case AASR:
  5649  		return S64 | OPDP2(10) /* also ASRV */
  5650  
  5651  	case AASRW:
  5652  		return S32 | OPDP2(10)
  5653  
  5654  	case ALSL:
  5655  		return S64 | OPDP2(8)
  5656  
  5657  	case ALSLW:
  5658  		return S32 | OPDP2(8)
  5659  
  5660  	case ALSR:
  5661  		return S64 | OPDP2(9)
  5662  
  5663  	case ALSRW:
  5664  		return S32 | OPDP2(9)
  5665  
  5666  	case AROR:
  5667  		return S64 | OPDP2(11)
  5668  
  5669  	case ARORW:
  5670  		return S32 | OPDP2(11)
  5671  
  5672  	case ACCMN:
  5673  		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
  5674  
  5675  	case ACCMNW:
  5676  		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5677  
  5678  	case ACCMP:
  5679  		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5680  
  5681  	case ACCMPW:
  5682  		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5683  
  5684  	case ACRC32B:
  5685  		return S32 | OPDP2(16)
  5686  
  5687  	case ACRC32H:
  5688  		return S32 | OPDP2(17)
  5689  
  5690  	case ACRC32W:
  5691  		return S32 | OPDP2(18)
  5692  
  5693  	case ACRC32X:
  5694  		return S64 | OPDP2(19)
  5695  
  5696  	case ACRC32CB:
  5697  		return S32 | OPDP2(20)
  5698  
  5699  	case ACRC32CH:
  5700  		return S32 | OPDP2(21)
  5701  
  5702  	case ACRC32CW:
  5703  		return S32 | OPDP2(22)
  5704  
  5705  	case ACRC32CX:
  5706  		return S64 | OPDP2(23)
  5707  
  5708  	case ACSEL:
  5709  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5710  
  5711  	case ACSELW:
  5712  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5713  
  5714  	case ACSET:
  5715  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5716  
  5717  	case ACSETW:
  5718  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5719  
  5720  	case ACSETM:
  5721  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5722  
  5723  	case ACSETMW:
  5724  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5725  
  5726  	case ACINC, ACSINC:
  5727  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5728  
  5729  	case ACINCW, ACSINCW:
  5730  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5731  
  5732  	case ACINV, ACSINV:
  5733  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5734  
  5735  	case ACINVW, ACSINVW:
  5736  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  5737  
  5738  	case ACNEG, ACSNEG:
  5739  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5740  
  5741  	case ACNEGW, ACSNEGW:
  5742  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  5743  
  5744  	case AMUL, AMADD:
  5745  		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  5746  
  5747  	case AMULW, AMADDW:
  5748  		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  5749  
  5750  	case AMNEG, AMSUB:
  5751  		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  5752  
  5753  	case AMNEGW, AMSUBW:
  5754  		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  5755  
  5756  	case AMRS:
  5757  		return SYSOP(1, 2, 0, 0, 0, 0, 0)
  5758  
  5759  	case AMSR:
  5760  		return SYSOP(0, 2, 0, 0, 0, 0, 0)
  5761  
  5762  	case ANEG:
  5763  		return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  5764  
  5765  	case ANEGW:
  5766  		return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  5767  
  5768  	case ANEGS:
  5769  		return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  5770  
  5771  	case ANEGSW:
  5772  		return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  5773  
  5774  	case AREM, ASDIV:
  5775  		return S64 | OPDP2(3)
  5776  
  5777  	case AREMW, ASDIVW:
  5778  		return S32 | OPDP2(3)
  5779  
  5780  	case ASMULL, ASMADDL:
  5781  		return OPDP3(1, 0, 1, 0)
  5782  
  5783  	case ASMNEGL, ASMSUBL:
  5784  		return OPDP3(1, 0, 1, 1)
  5785  
  5786  	case ASMULH:
  5787  		return OPDP3(1, 0, 2, 0)
  5788  
  5789  	case AUMULL, AUMADDL:
  5790  		return OPDP3(1, 0, 5, 0)
  5791  
  5792  	case AUMNEGL, AUMSUBL:
  5793  		return OPDP3(1, 0, 5, 1)
  5794  
  5795  	case AUMULH:
  5796  		return OPDP3(1, 0, 6, 0)
  5797  
  5798  	case AUREM, AUDIV:
  5799  		return S64 | OPDP2(2)
  5800  
  5801  	case AUREMW, AUDIVW:
  5802  		return S32 | OPDP2(2)
  5803  
  5804  	case AAESE:
  5805  		return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
  5806  
  5807  	case AAESD:
  5808  		return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
  5809  
  5810  	case AAESMC:
  5811  		return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
  5812  
  5813  	case AAESIMC:
  5814  		return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
  5815  
  5816  	case ASHA1C:
  5817  		return 0x5E<<24 | 0<<12
  5818  
  5819  	case ASHA1P:
  5820  		return 0x5E<<24 | 1<<12
  5821  
  5822  	case ASHA1M:
  5823  		return 0x5E<<24 | 2<<12
  5824  
  5825  	case ASHA1SU0:
  5826  		return 0x5E<<24 | 3<<12
  5827  
  5828  	case ASHA256H:
  5829  		return 0x5E<<24 | 4<<12
  5830  
  5831  	case ASHA256H2:
  5832  		return 0x5E<<24 | 5<<12
  5833  
  5834  	case ASHA256SU1:
  5835  		return 0x5E<<24 | 6<<12
  5836  
  5837  	case ASHA1H:
  5838  		return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
  5839  
  5840  	case ASHA1SU1:
  5841  		return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
  5842  
  5843  	case ASHA256SU0:
  5844  		return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
  5845  
  5846  	case ASHA512H:
  5847  		return 0xCE<<24 | 3<<21 | 8<<12
  5848  
  5849  	case ASHA512H2:
  5850  		return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
  5851  
  5852  	case ASHA512SU1:
  5853  		return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
  5854  
  5855  	case ASHA512SU0:
  5856  		return 0xCE<<24 | 3<<22 | 8<<12
  5857  
  5858  	case AFCVTZSD:
  5859  		return FPCVTI(1, 0, 1, 3, 0)
  5860  
  5861  	case AFCVTZSDW:
  5862  		return FPCVTI(0, 0, 1, 3, 0)
  5863  
  5864  	case AFCVTZSS:
  5865  		return FPCVTI(1, 0, 0, 3, 0)
  5866  
  5867  	case AFCVTZSSW:
  5868  		return FPCVTI(0, 0, 0, 3, 0)
  5869  
  5870  	case AFCVTZUD:
  5871  		return FPCVTI(1, 0, 1, 3, 1)
  5872  
  5873  	case AFCVTZUDW:
  5874  		return FPCVTI(0, 0, 1, 3, 1)
  5875  
  5876  	case AFCVTZUS:
  5877  		return FPCVTI(1, 0, 0, 3, 1)
  5878  
  5879  	case AFCVTZUSW:
  5880  		return FPCVTI(0, 0, 0, 3, 1)
  5881  
  5882  	case ASCVTFD:
  5883  		return FPCVTI(1, 0, 1, 0, 2)
  5884  
  5885  	case ASCVTFS:
  5886  		return FPCVTI(1, 0, 0, 0, 2)
  5887  
  5888  	case ASCVTFWD:
  5889  		return FPCVTI(0, 0, 1, 0, 2)
  5890  
  5891  	case ASCVTFWS:
  5892  		return FPCVTI(0, 0, 0, 0, 2)
  5893  
  5894  	case AUCVTFD:
  5895  		return FPCVTI(1, 0, 1, 0, 3)
  5896  
  5897  	case AUCVTFS:
  5898  		return FPCVTI(1, 0, 0, 0, 3)
  5899  
  5900  	case AUCVTFWD:
  5901  		return FPCVTI(0, 0, 1, 0, 3)
  5902  
  5903  	case AUCVTFWS:
  5904  		return FPCVTI(0, 0, 0, 0, 3)
  5905  
  5906  	case AFADDS:
  5907  		return FPOP2S(0, 0, 0, 2)
  5908  
  5909  	case AFADDD:
  5910  		return FPOP2S(0, 0, 1, 2)
  5911  
  5912  	case AFSUBS:
  5913  		return FPOP2S(0, 0, 0, 3)
  5914  
  5915  	case AFSUBD:
  5916  		return FPOP2S(0, 0, 1, 3)
  5917  
  5918  	case AFMADDD:
  5919  		return FPOP3S(0, 0, 1, 0, 0)
  5920  
  5921  	case AFMADDS:
  5922  		return FPOP3S(0, 0, 0, 0, 0)
  5923  
  5924  	case AFMSUBD:
  5925  		return FPOP3S(0, 0, 1, 0, 1)
  5926  
  5927  	case AFMSUBS:
  5928  		return FPOP3S(0, 0, 0, 0, 1)
  5929  
  5930  	case AFNMADDD:
  5931  		return FPOP3S(0, 0, 1, 1, 0)
  5932  
  5933  	case AFNMADDS:
  5934  		return FPOP3S(0, 0, 0, 1, 0)
  5935  
  5936  	case AFNMSUBD:
  5937  		return FPOP3S(0, 0, 1, 1, 1)
  5938  
  5939  	case AFNMSUBS:
  5940  		return FPOP3S(0, 0, 0, 1, 1)
  5941  
  5942  	case AFMULS:
  5943  		return FPOP2S(0, 0, 0, 0)
  5944  
  5945  	case AFMULD:
  5946  		return FPOP2S(0, 0, 1, 0)
  5947  
  5948  	case AFDIVS:
  5949  		return FPOP2S(0, 0, 0, 1)
  5950  
  5951  	case AFDIVD:
  5952  		return FPOP2S(0, 0, 1, 1)
  5953  
  5954  	case AFMAXS:
  5955  		return FPOP2S(0, 0, 0, 4)
  5956  
  5957  	case AFMINS:
  5958  		return FPOP2S(0, 0, 0, 5)
  5959  
  5960  	case AFMAXD:
  5961  		return FPOP2S(0, 0, 1, 4)
  5962  
  5963  	case AFMIND:
  5964  		return FPOP2S(0, 0, 1, 5)
  5965  
  5966  	case AFMAXNMS:
  5967  		return FPOP2S(0, 0, 0, 6)
  5968  
  5969  	case AFMAXNMD:
  5970  		return FPOP2S(0, 0, 1, 6)
  5971  
  5972  	case AFMINNMS:
  5973  		return FPOP2S(0, 0, 0, 7)
  5974  
  5975  	case AFMINNMD:
  5976  		return FPOP2S(0, 0, 1, 7)
  5977  
  5978  	case AFNMULS:
  5979  		return FPOP2S(0, 0, 0, 8)
  5980  
  5981  	case AFNMULD:
  5982  		return FPOP2S(0, 0, 1, 8)
  5983  
  5984  	case AFCMPS:
  5985  		return FPCMP(0, 0, 0, 0, 0)
  5986  
  5987  	case AFCMPD:
  5988  		return FPCMP(0, 0, 1, 0, 0)
  5989  
  5990  	case AFCMPES:
  5991  		return FPCMP(0, 0, 0, 0, 16)
  5992  
  5993  	case AFCMPED:
  5994  		return FPCMP(0, 0, 1, 0, 16)
  5995  
  5996  	case AFCCMPS:
  5997  		return FPCCMP(0, 0, 0, 0)
  5998  
  5999  	case AFCCMPD:
  6000  		return FPCCMP(0, 0, 1, 0)
  6001  
  6002  	case AFCCMPES:
  6003  		return FPCCMP(0, 0, 0, 1)
  6004  
  6005  	case AFCCMPED:
  6006  		return FPCCMP(0, 0, 1, 1)
  6007  
  6008  	case AFCSELS:
  6009  		return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
  6010  
  6011  	case AFCSELD:
  6012  		return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
  6013  
  6014  	case AFMOVS:
  6015  		return FPOP1S(0, 0, 0, 0)
  6016  
  6017  	case AFABSS:
  6018  		return FPOP1S(0, 0, 0, 1)
  6019  
  6020  	case AFNEGS:
  6021  		return FPOP1S(0, 0, 0, 2)
  6022  
  6023  	case AFSQRTS:
  6024  		return FPOP1S(0, 0, 0, 3)
  6025  
  6026  	case AFCVTSD:
  6027  		return FPOP1S(0, 0, 0, 5)
  6028  
  6029  	case AFCVTSH:
  6030  		return FPOP1S(0, 0, 0, 7)
  6031  
  6032  	case AFRINTNS:
  6033  		return FPOP1S(0, 0, 0, 8)
  6034  
  6035  	case AFRINTPS:
  6036  		return FPOP1S(0, 0, 0, 9)
  6037  
  6038  	case AFRINTMS:
  6039  		return FPOP1S(0, 0, 0, 10)
  6040  
  6041  	case AFRINTZS:
  6042  		return FPOP1S(0, 0, 0, 11)
  6043  
  6044  	case AFRINTAS:
  6045  		return FPOP1S(0, 0, 0, 12)
  6046  
  6047  	case AFRINTXS:
  6048  		return FPOP1S(0, 0, 0, 14)
  6049  
  6050  	case AFRINTIS:
  6051  		return FPOP1S(0, 0, 0, 15)
  6052  
  6053  	case AFMOVD:
  6054  		return FPOP1S(0, 0, 1, 0)
  6055  
  6056  	case AFABSD:
  6057  		return FPOP1S(0, 0, 1, 1)
  6058  
  6059  	case AFNEGD:
  6060  		return FPOP1S(0, 0, 1, 2)
  6061  
  6062  	case AFSQRTD:
  6063  		return FPOP1S(0, 0, 1, 3)
  6064  
  6065  	case AFCVTDS:
  6066  		return FPOP1S(0, 0, 1, 4)
  6067  
  6068  	case AFCVTDH:
  6069  		return FPOP1S(0, 0, 1, 7)
  6070  
  6071  	case AFRINTND:
  6072  		return FPOP1S(0, 0, 1, 8)
  6073  
  6074  	case AFRINTPD:
  6075  		return FPOP1S(0, 0, 1, 9)
  6076  
  6077  	case AFRINTMD:
  6078  		return FPOP1S(0, 0, 1, 10)
  6079  
  6080  	case AFRINTZD:
  6081  		return FPOP1S(0, 0, 1, 11)
  6082  
  6083  	case AFRINTAD:
  6084  		return FPOP1S(0, 0, 1, 12)
  6085  
  6086  	case AFRINTXD:
  6087  		return FPOP1S(0, 0, 1, 14)
  6088  
  6089  	case AFRINTID:
  6090  		return FPOP1S(0, 0, 1, 15)
  6091  
  6092  	case AFCVTHS:
  6093  		return FPOP1S(0, 0, 3, 4)
  6094  
  6095  	case AFCVTHD:
  6096  		return FPOP1S(0, 0, 3, 5)
  6097  
  6098  	case AVADD:
  6099  		return 7<<25 | 1<<21 | 1<<15 | 1<<10
  6100  
  6101  	case AVSUB:
  6102  		return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
  6103  
  6104  	case AVADDP:
  6105  		return 7<<25 | 1<<21 | 1<<15 | 15<<10
  6106  
  6107  	case AVAND:
  6108  		return 7<<25 | 1<<21 | 7<<10
  6109  
  6110  	case AVBCAX:
  6111  		return 0xCE<<24 | 1<<21
  6112  
  6113  	case AVCMEQ:
  6114  		return 1<<29 | 0x71<<21 | 0x23<<10
  6115  
  6116  	case AVCNT:
  6117  		return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
  6118  
  6119  	case AVZIP1:
  6120  		return 0xE<<24 | 3<<12 | 2<<10
  6121  
  6122  	case AVZIP2:
  6123  		return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
  6124  
  6125  	case AVEOR:
  6126  		return 1<<29 | 0x71<<21 | 7<<10
  6127  
  6128  	case AVEOR3:
  6129  		return 0xCE << 24
  6130  
  6131  	case AVORR:
  6132  		return 7<<25 | 5<<21 | 7<<10
  6133  
  6134  	case AVREV16:
  6135  		return 3<<26 | 2<<24 | 1<<21 | 3<<11
  6136  
  6137  	case AVRAX1:
  6138  		return 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
  6139  
  6140  	case AVREV32:
  6141  		return 11<<26 | 2<<24 | 1<<21 | 1<<11
  6142  
  6143  	case AVREV64:
  6144  		return 3<<26 | 2<<24 | 1<<21 | 1<<11
  6145  
  6146  	case AVMOV:
  6147  		return 7<<25 | 5<<21 | 7<<10
  6148  
  6149  	case AVADDV:
  6150  		return 7<<25 | 3<<20 | 3<<15 | 7<<11
  6151  
  6152  	case AVUADDLV:
  6153  		return 1<<29 | 7<<25 | 3<<20 | 7<<11
  6154  
  6155  	case AVFMLA:
  6156  		return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
  6157  
  6158  	case AVFMLS:
  6159  		return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
  6160  
  6161  	case AVPMULL, AVPMULL2:
  6162  		return 0xE<<24 | 1<<21 | 0x38<<10
  6163  
  6164  	case AVRBIT:
  6165  		return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
  6166  
  6167  	case AVLD1, AVLD2, AVLD3, AVLD4:
  6168  		return 3<<26 | 1<<22
  6169  
  6170  	case AVLD1R, AVLD3R:
  6171  		return 0xD<<24 | 1<<22
  6172  
  6173  	case AVLD2R, AVLD4R:
  6174  		return 0xD<<24 | 3<<21
  6175  
  6176  	case AVBIF:
  6177  		return 1<<29 | 7<<25 | 7<<21 | 7<<10
  6178  
  6179  	case AVBIT:
  6180  		return 1<<29 | 0x75<<21 | 7<<10
  6181  
  6182  	case AVBSL:
  6183  		return 1<<29 | 0x73<<21 | 7<<10
  6184  
  6185  	case AVCMTST:
  6186  		return 0xE<<24 | 1<<21 | 0x23<<10
  6187  
  6188  	case AVUMAX:
  6189  		return 1<<29 | 7<<25 | 1<<21 | 0x19<<10
  6190  
  6191  	case AVUMIN:
  6192  		return 1<<29 | 7<<25 | 1<<21 | 0x1b<<10
  6193  
  6194  	case AVUZP1:
  6195  		return 7<<25 | 3<<11
  6196  
  6197  	case AVUZP2:
  6198  		return 7<<25 | 1<<14 | 3<<11
  6199  
  6200  	case AVUADDW, AVUADDW2:
  6201  		return 0x17<<25 | 1<<21 | 1<<12
  6202  	}
  6203  
  6204  	c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
  6205  	return 0
  6206  }
  6207  
  6208  /*
  6209   * imm -> Rd
  6210   * imm op Rn -> Rd
  6211   */
  6212  func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
  6213  	switch a {
  6214  	/* op $addcon, Rn, Rd */
  6215  	case AMOVD, AADD:
  6216  		return S64 | 0<<30 | 0<<29 | 0x11<<24
  6217  
  6218  	case ACMN, AADDS:
  6219  		return S64 | 0<<30 | 1<<29 | 0x11<<24
  6220  
  6221  	case AMOVW, AADDW:
  6222  		return S32 | 0<<30 | 0<<29 | 0x11<<24
  6223  
  6224  	case ACMNW, AADDSW:
  6225  		return S32 | 0<<30 | 1<<29 | 0x11<<24
  6226  
  6227  	case ASUB:
  6228  		return S64 | 1<<30 | 0<<29 | 0x11<<24
  6229  
  6230  	case ACMP, ASUBS:
  6231  		return S64 | 1<<30 | 1<<29 | 0x11<<24
  6232  
  6233  	case ASUBW:
  6234  		return S32 | 1<<30 | 0<<29 | 0x11<<24
  6235  
  6236  	case ACMPW, ASUBSW:
  6237  		return S32 | 1<<30 | 1<<29 | 0x11<<24
  6238  
  6239  		/* op $imm(SB), Rd; op label, Rd */
  6240  	case AADR:
  6241  		return 0<<31 | 0x10<<24
  6242  
  6243  	case AADRP:
  6244  		return 1<<31 | 0x10<<24
  6245  
  6246  		/* op $bimm, Rn, Rd */
  6247  	case AAND, ABIC:
  6248  		return S64 | 0<<29 | 0x24<<23
  6249  
  6250  	case AANDW, ABICW:
  6251  		return S32 | 0<<29 | 0x24<<23 | 0<<22
  6252  
  6253  	case AORR, AORN:
  6254  		return S64 | 1<<29 | 0x24<<23
  6255  
  6256  	case AORRW, AORNW:
  6257  		return S32 | 1<<29 | 0x24<<23 | 0<<22
  6258  
  6259  	case AEOR, AEON:
  6260  		return S64 | 2<<29 | 0x24<<23
  6261  
  6262  	case AEORW, AEONW:
  6263  		return S32 | 2<<29 | 0x24<<23 | 0<<22
  6264  
  6265  	case AANDS, ABICS, ATST:
  6266  		return S64 | 3<<29 | 0x24<<23
  6267  
  6268  	case AANDSW, ABICSW, ATSTW:
  6269  		return S32 | 3<<29 | 0x24<<23 | 0<<22
  6270  
  6271  	case AASR:
  6272  		return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
  6273  
  6274  	case AASRW:
  6275  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  6276  
  6277  		/* op $width, $lsb, Rn, Rd */
  6278  	case ABFI:
  6279  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  6280  		/* alias of BFM */
  6281  
  6282  	case ABFIW:
  6283  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  6284  
  6285  		/* op $imms, $immr, Rn, Rd */
  6286  	case ABFM:
  6287  		return S64 | 1<<29 | 0x26<<23 | 1<<22
  6288  
  6289  	case ABFMW:
  6290  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  6291  
  6292  	case ASBFM:
  6293  		return S64 | 0<<29 | 0x26<<23 | 1<<22
  6294  
  6295  	case ASBFMW:
  6296  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  6297  
  6298  	case AUBFM:
  6299  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  6300  
  6301  	case AUBFMW:
  6302  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  6303  
  6304  	case ABFXIL:
  6305  		return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
  6306  
  6307  	case ABFXILW:
  6308  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  6309  
  6310  	case AEXTR:
  6311  		return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
  6312  
  6313  	case AEXTRW:
  6314  		return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
  6315  
  6316  	case ACBNZ:
  6317  		return S64 | 0x1A<<25 | 1<<24
  6318  
  6319  	case ACBNZW:
  6320  		return S32 | 0x1A<<25 | 1<<24
  6321  
  6322  	case ACBZ:
  6323  		return S64 | 0x1A<<25 | 0<<24
  6324  
  6325  	case ACBZW:
  6326  		return S32 | 0x1A<<25 | 0<<24
  6327  
  6328  	case ACCMN:
  6329  		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  6330  
  6331  	case ACCMNW:
  6332  		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  6333  
  6334  	case ACCMP:
  6335  		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  6336  
  6337  	case ACCMPW:
  6338  		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  6339  
  6340  	case AMOVK:
  6341  		return S64 | 3<<29 | 0x25<<23
  6342  
  6343  	case AMOVKW:
  6344  		return S32 | 3<<29 | 0x25<<23
  6345  
  6346  	case AMOVN:
  6347  		return S64 | 0<<29 | 0x25<<23
  6348  
  6349  	case AMOVNW:
  6350  		return S32 | 0<<29 | 0x25<<23
  6351  
  6352  	case AMOVZ:
  6353  		return S64 | 2<<29 | 0x25<<23
  6354  
  6355  	case AMOVZW:
  6356  		return S32 | 2<<29 | 0x25<<23
  6357  
  6358  	case AMSR:
  6359  		return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
  6360  
  6361  	case AAT,
  6362  		ADC,
  6363  		AIC,
  6364  		ATLBI,
  6365  		ASYS:
  6366  		return SYSOP(0, 1, 0, 0, 0, 0, 0)
  6367  
  6368  	case ASYSL:
  6369  		return SYSOP(1, 1, 0, 0, 0, 0, 0)
  6370  
  6371  	case ATBZ:
  6372  		return 0x36 << 24
  6373  
  6374  	case ATBNZ:
  6375  		return 0x37 << 24
  6376  
  6377  	case ADSB:
  6378  		return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
  6379  
  6380  	case ADMB:
  6381  		return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
  6382  
  6383  	case AISB:
  6384  		return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
  6385  
  6386  	case AHINT:
  6387  		return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
  6388  
  6389  	case AVEXT:
  6390  		return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
  6391  
  6392  	case AVUSHR:
  6393  		return 0x5E<<23 | 1<<10
  6394  
  6395  	case AVSHL:
  6396  		return 0x1E<<23 | 21<<10
  6397  
  6398  	case AVSRI:
  6399  		return 0x5E<<23 | 17<<10
  6400  
  6401  	case AVSLI:
  6402  		return 0x5E<<23 | 21<<10
  6403  
  6404  	case AVUSHLL, AVUXTL:
  6405  		return 1<<29 | 15<<24 | 0x29<<10
  6406  
  6407  	case AVUSHLL2, AVUXTL2:
  6408  		return 3<<29 | 15<<24 | 0x29<<10
  6409  
  6410  	case AVXAR:
  6411  		return 0xCE<<24 | 1<<23
  6412  
  6413  	case AVUSRA:
  6414  		return 1<<29 | 15<<24 | 5<<10
  6415  
  6416  	case APRFM:
  6417  		return 0xf9<<24 | 2<<22
  6418  	}
  6419  
  6420  	c.ctxt.Diag("%v: bad irr %v", p, a)
  6421  	return 0
  6422  }
  6423  
  6424  func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
  6425  	switch a {
  6426  	case ACLS:
  6427  		return S64 | OPBIT(5)
  6428  
  6429  	case ACLSW:
  6430  		return S32 | OPBIT(5)
  6431  
  6432  	case ACLZ:
  6433  		return S64 | OPBIT(4)
  6434  
  6435  	case ACLZW:
  6436  		return S32 | OPBIT(4)
  6437  
  6438  	case ARBIT:
  6439  		return S64 | OPBIT(0)
  6440  
  6441  	case ARBITW:
  6442  		return S32 | OPBIT(0)
  6443  
  6444  	case AREV:
  6445  		return S64 | OPBIT(3)
  6446  
  6447  	case AREVW:
  6448  		return S32 | OPBIT(2)
  6449  
  6450  	case AREV16:
  6451  		return S64 | OPBIT(1)
  6452  
  6453  	case AREV16W:
  6454  		return S32 | OPBIT(1)
  6455  
  6456  	case AREV32:
  6457  		return S64 | OPBIT(2)
  6458  
  6459  	default:
  6460  		c.ctxt.Diag("bad bit op\n%v", p)
  6461  		return 0
  6462  	}
  6463  }
  6464  
  6465  /*
  6466   * add/subtract sign or zero-extended register
  6467   */
  6468  func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
  6469  	extension := uint32(0)
  6470  	if !extend {
  6471  		if isADDop(a) {
  6472  			extension = LSL0_64
  6473  		}
  6474  		if isADDWop(a) {
  6475  			extension = LSL0_32
  6476  		}
  6477  	}
  6478  
  6479  	switch a {
  6480  	case AADD:
  6481  		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6482  
  6483  	case AADDW:
  6484  		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6485  
  6486  	case ACMN, AADDS:
  6487  		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6488  
  6489  	case ACMNW, AADDSW:
  6490  		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6491  
  6492  	case ASUB:
  6493  		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6494  
  6495  	case ASUBW:
  6496  		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6497  
  6498  	case ACMP, ASUBS:
  6499  		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6500  
  6501  	case ACMPW, ASUBSW:
  6502  		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6503  	}
  6504  
  6505  	c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
  6506  	return 0
  6507  }
  6508  
  6509  func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
  6510  	switch a {
  6511  	case ASVC:
  6512  		return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
  6513  
  6514  	case AHVC:
  6515  		return 0xD4<<24 | 0<<21 | 2
  6516  
  6517  	case ASMC:
  6518  		return 0xD4<<24 | 0<<21 | 3
  6519  
  6520  	case ABRK:
  6521  		return 0xD4<<24 | 1<<21 | 0
  6522  
  6523  	case AHLT:
  6524  		return 0xD4<<24 | 2<<21 | 0
  6525  
  6526  	case ADCPS1:
  6527  		return 0xD4<<24 | 5<<21 | 1
  6528  
  6529  	case ADCPS2:
  6530  		return 0xD4<<24 | 5<<21 | 2
  6531  
  6532  	case ADCPS3:
  6533  		return 0xD4<<24 | 5<<21 | 3
  6534  
  6535  	case ACLREX:
  6536  		return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
  6537  	}
  6538  
  6539  	c.ctxt.Diag("%v: bad imm %v", p, a)
  6540  	return 0
  6541  }
  6542  
  6543  func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
  6544  	v := int64(0)
  6545  	t := int64(0)
  6546  	q := p.To.Target()
  6547  	if q == nil {
  6548  		// TODO: don't use brdist for this case, as it isn't a branch.
  6549  		// (Calls from omovlit, and maybe adr/adrp opcodes as well.)
  6550  		q = p.Pool
  6551  	}
  6552  	if q != nil {
  6553  		v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
  6554  		if (v & ((1 << uint(shift)) - 1)) != 0 {
  6555  			c.ctxt.Diag("misaligned label\n%v", p)
  6556  		}
  6557  		v >>= uint(shift)
  6558  		t = int64(1) << uint(flen-1)
  6559  		if v < -t || v >= t {
  6560  			c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
  6561  			panic("branch too far")
  6562  		}
  6563  	}
  6564  
  6565  	return v & ((t << 1) - 1)
  6566  }
  6567  
  6568  /*
  6569   * pc-relative branches
  6570   */
  6571  func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
  6572  	switch a {
  6573  	case ABEQ:
  6574  		return OPBcc(0x0)
  6575  
  6576  	case ABNE:
  6577  		return OPBcc(0x1)
  6578  
  6579  	case ABCS:
  6580  		return OPBcc(0x2)
  6581  
  6582  	case ABHS:
  6583  		return OPBcc(0x2)
  6584  
  6585  	case ABCC:
  6586  		return OPBcc(0x3)
  6587  
  6588  	case ABLO:
  6589  		return OPBcc(0x3)
  6590  
  6591  	case ABMI:
  6592  		return OPBcc(0x4)
  6593  
  6594  	case ABPL:
  6595  		return OPBcc(0x5)
  6596  
  6597  	case ABVS:
  6598  		return OPBcc(0x6)
  6599  
  6600  	case ABVC:
  6601  		return OPBcc(0x7)
  6602  
  6603  	case ABHI:
  6604  		return OPBcc(0x8)
  6605  
  6606  	case ABLS:
  6607  		return OPBcc(0x9)
  6608  
  6609  	case ABGE:
  6610  		return OPBcc(0xa)
  6611  
  6612  	case ABLT:
  6613  		return OPBcc(0xb)
  6614  
  6615  	case ABGT:
  6616  		return OPBcc(0xc)
  6617  
  6618  	case ABLE:
  6619  		return OPBcc(0xd) /* imm19<<5 | cond */
  6620  
  6621  	case AB:
  6622  		return 0<<31 | 5<<26 /* imm26 */
  6623  
  6624  	case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
  6625  		return 1<<31 | 5<<26
  6626  	}
  6627  
  6628  	c.ctxt.Diag("%v: bad bra %v", p, a)
  6629  	return 0
  6630  }
  6631  
  6632  func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
  6633  	switch a {
  6634  	case ABL:
  6635  		return OPBLR(1) /* BLR */
  6636  
  6637  	case AB:
  6638  		return OPBLR(0) /* BR */
  6639  
  6640  	case obj.ARET:
  6641  		return OPBLR(2) /* RET */
  6642  	}
  6643  
  6644  	c.ctxt.Diag("%v: bad brr %v", p, a)
  6645  	return 0
  6646  }
  6647  
  6648  func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
  6649  	switch a {
  6650  	case ADRPS:
  6651  		return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
  6652  
  6653  	case AERET:
  6654  		return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
  6655  
  6656  	case ANOOP:
  6657  		return SYSHINT(0)
  6658  
  6659  	case AYIELD:
  6660  		return SYSHINT(1)
  6661  
  6662  	case AWFE:
  6663  		return SYSHINT(2)
  6664  
  6665  	case AWFI:
  6666  		return SYSHINT(3)
  6667  
  6668  	case ASEV:
  6669  		return SYSHINT(4)
  6670  
  6671  	case ASEVL:
  6672  		return SYSHINT(5)
  6673  	}
  6674  
  6675  	c.ctxt.Diag("%v: bad op0 %v", p, a)
  6676  	return 0
  6677  }
  6678  
  6679  /*
  6680   * register offset
  6681   */
  6682  func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
  6683  	switch a {
  6684  	case ALDAR:
  6685  		return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
  6686  
  6687  	case ALDARW:
  6688  		return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
  6689  
  6690  	case ALDARB:
  6691  		return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
  6692  
  6693  	case ALDARH:
  6694  		return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
  6695  
  6696  	case ALDAXP:
  6697  		return LDSTX(3, 0, 1, 1, 1)
  6698  
  6699  	case ALDAXPW:
  6700  		return LDSTX(2, 0, 1, 1, 1)
  6701  
  6702  	case ALDAXR:
  6703  		return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
  6704  
  6705  	case ALDAXRW:
  6706  		return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
  6707  
  6708  	case ALDAXRB:
  6709  		return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
  6710  
  6711  	case ALDAXRH:
  6712  		return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
  6713  
  6714  	case ALDXR:
  6715  		return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
  6716  
  6717  	case ALDXRB:
  6718  		return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
  6719  
  6720  	case ALDXRH:
  6721  		return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
  6722  
  6723  	case ALDXRW:
  6724  		return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
  6725  
  6726  	case ALDXP:
  6727  		return LDSTX(3, 0, 1, 1, 0)
  6728  
  6729  	case ALDXPW:
  6730  		return LDSTX(2, 0, 1, 1, 0)
  6731  
  6732  	case AMOVNP:
  6733  		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6734  
  6735  	case AMOVNPW:
  6736  		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6737  	}
  6738  
  6739  	c.ctxt.Diag("bad opload %v\n%v", a, p)
  6740  	return 0
  6741  }
  6742  
  6743  func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
  6744  	switch a {
  6745  	case ASTLR:
  6746  		return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
  6747  
  6748  	case ASTLRB:
  6749  		return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
  6750  
  6751  	case ASTLRH:
  6752  		return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
  6753  
  6754  	case ASTLP:
  6755  		return LDSTX(3, 0, 0, 1, 1)
  6756  
  6757  	case ASTLPW:
  6758  		return LDSTX(2, 0, 0, 1, 1)
  6759  
  6760  	case ASTLRW:
  6761  		return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
  6762  
  6763  	case ASTLXP:
  6764  		return LDSTX(3, 0, 0, 1, 1)
  6765  
  6766  	case ASTLXPW:
  6767  		return LDSTX(2, 0, 0, 1, 1)
  6768  
  6769  	case ASTLXR:
  6770  		return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
  6771  
  6772  	case ASTLXRB:
  6773  		return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
  6774  
  6775  	case ASTLXRH:
  6776  		return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
  6777  
  6778  	case ASTLXRW:
  6779  		return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
  6780  
  6781  	case ASTXR:
  6782  		return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
  6783  
  6784  	case ASTXRB:
  6785  		return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
  6786  
  6787  	case ASTXRH:
  6788  		return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
  6789  
  6790  	case ASTXP:
  6791  		return LDSTX(3, 0, 0, 1, 0)
  6792  
  6793  	case ASTXPW:
  6794  		return LDSTX(2, 0, 0, 1, 0)
  6795  
  6796  	case ASTXRW:
  6797  		return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
  6798  
  6799  	case AMOVNP:
  6800  		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6801  
  6802  	case AMOVNPW:
  6803  		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  6804  	}
  6805  
  6806  	c.ctxt.Diag("bad opstore %v\n%v", a, p)
  6807  	return 0
  6808  }
  6809  
  6810  /*
  6811   * load/store register (scaled 12-bit unsigned immediate) C3.3.13
  6812   *	these produce 64-bit values (when there's an option)
  6813   */
  6814  func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  6815  	if v < 0 || v >= (1<<12) {
  6816  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  6817  	}
  6818  	o |= (v & 0xFFF) << 10
  6819  	o |= int32(b&31) << 5
  6820  	o |= int32(r & 31)
  6821  	o |= 1 << 24
  6822  	return uint32(o)
  6823  }
  6824  
  6825  /*
  6826   * load/store register (unscaled 9-bit signed immediate) C3.3.12
  6827   */
  6828  func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  6829  	if v < -256 || v > 255 {
  6830  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  6831  	}
  6832  	o |= (v & 0x1FF) << 12
  6833  	o |= int32(b&31) << 5
  6834  	o |= int32(r & 31)
  6835  	return uint32(o)
  6836  }
  6837  
  6838  // store(immediate)
  6839  // scaled 12-bit unsigned immediate offset.
  6840  // unscaled 9-bit signed immediate offset.
  6841  // pre/post-indexed store.
  6842  // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
  6843  func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 {
  6844  	enc := c.opldr(p, a)
  6845  	switch p.As {
  6846  	case AFMOVQ:
  6847  		enc = enc &^ (1 << 22)
  6848  	default:
  6849  		enc = LD2STR(enc)
  6850  	}
  6851  	return enc
  6852  }
  6853  
  6854  // load(immediate)
  6855  // scaled 12-bit unsigned immediate offset.
  6856  // unscaled 9-bit signed immediate offset.
  6857  // pre/post-indexed load.
  6858  // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
  6859  func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 {
  6860  	switch a {
  6861  	case AMOVD:
  6862  		return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
  6863  
  6864  	case AMOVW:
  6865  		return LDSTR(2, 0, 2)
  6866  
  6867  	case AMOVWU:
  6868  		return LDSTR(2, 0, 1)
  6869  
  6870  	case AMOVH:
  6871  		return LDSTR(1, 0, 2)
  6872  
  6873  	case AMOVHU:
  6874  		return LDSTR(1, 0, 1)
  6875  
  6876  	case AMOVB:
  6877  		return LDSTR(0, 0, 2)
  6878  
  6879  	case AMOVBU:
  6880  		return LDSTR(0, 0, 1)
  6881  
  6882  	case AFMOVS:
  6883  		return LDSTR(2, 1, 1)
  6884  
  6885  	case AFMOVD:
  6886  		return LDSTR(3, 1, 1)
  6887  
  6888  	case AFMOVQ:
  6889  		return LDSTR(0, 1, 3)
  6890  	}
  6891  
  6892  	c.ctxt.Diag("bad opldr %v\n%v", a, p)
  6893  	return 0
  6894  }
  6895  
  6896  // olsxrr attaches register operands to a load/store opcode supplied in o.
  6897  // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
  6898  func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
  6899  	o |= int32(r1&31) << 5
  6900  	o |= int32(r2&31) << 16
  6901  	o |= int32(r & 31)
  6902  	return uint32(o)
  6903  }
  6904  
  6905  // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  6906  // for load instruction with register offset.
  6907  // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  6908  func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  6909  	OptionS := uint32(0x1a)
  6910  	if extension {
  6911  		OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
  6912  	}
  6913  	switch a {
  6914  	case AMOVD:
  6915  		return OptionS<<10 | 0x3<<21 | 0x1f<<27
  6916  	case AMOVW:
  6917  		return OptionS<<10 | 0x5<<21 | 0x17<<27
  6918  	case AMOVWU:
  6919  		return OptionS<<10 | 0x3<<21 | 0x17<<27
  6920  	case AMOVH:
  6921  		return OptionS<<10 | 0x5<<21 | 0x0f<<27
  6922  	case AMOVHU:
  6923  		return OptionS<<10 | 0x3<<21 | 0x0f<<27
  6924  	case AMOVB:
  6925  		return OptionS<<10 | 0x5<<21 | 0x07<<27
  6926  	case AMOVBU:
  6927  		return OptionS<<10 | 0x3<<21 | 0x07<<27
  6928  	case AFMOVS:
  6929  		return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
  6930  	case AFMOVD:
  6931  		return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
  6932  	}
  6933  	c.ctxt.Diag("bad opldrr %v\n%v", a, p)
  6934  	return 0
  6935  }
  6936  
  6937  // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  6938  // for store instruction with register offset.
  6939  // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  6940  func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  6941  	OptionS := uint32(0x1a)
  6942  	if extension {
  6943  		OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
  6944  	}
  6945  	switch a {
  6946  	case AMOVD:
  6947  		return OptionS<<10 | 0x1<<21 | 0x1f<<27
  6948  	case AMOVW, AMOVWU:
  6949  		return OptionS<<10 | 0x1<<21 | 0x17<<27
  6950  	case AMOVH, AMOVHU:
  6951  		return OptionS<<10 | 0x1<<21 | 0x0f<<27
  6952  	case AMOVB, AMOVBU:
  6953  		return OptionS<<10 | 0x1<<21 | 0x07<<27
  6954  	case AFMOVS:
  6955  		return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
  6956  	case AFMOVD:
  6957  		return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
  6958  	}
  6959  	c.ctxt.Diag("bad opstrr %v\n%v", a, p)
  6960  	return 0
  6961  }
  6962  
  6963  func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
  6964  	if (v & 0xFFF000) != 0 {
  6965  		if v&0xFFF != 0 {
  6966  			c.ctxt.Diag("%v misuses oaddi", p)
  6967  		}
  6968  		v >>= 12
  6969  		o1 |= 1 << 22
  6970  	}
  6971  
  6972  	o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
  6973  	return uint32(o1)
  6974  }
  6975  
  6976  /*
  6977   * load a literal value into dr
  6978   */
  6979  func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
  6980  	var o1 int32
  6981  	if p.Pool == nil { /* not in literal pool */
  6982  		c.aclass(a)
  6983  		c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
  6984  
  6985  		/* TODO: could be clever, and use general constant builder */
  6986  		o1 = int32(c.opirr(p, AADD))
  6987  
  6988  		v := int32(c.instoffset)
  6989  		if v != 0 && (v&0xFFF) == 0 {
  6990  			v >>= 12
  6991  			o1 |= 1 << 22 /* shift, by 12 */
  6992  		}
  6993  
  6994  		o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
  6995  	} else {
  6996  		fp, w := 0, 0
  6997  		switch as {
  6998  		case AFMOVS, AVMOVS:
  6999  			fp = 1
  7000  			w = 0 /* 32-bit SIMD/FP */
  7001  
  7002  		case AFMOVD, AVMOVD:
  7003  			fp = 1
  7004  			w = 1 /* 64-bit SIMD/FP */
  7005  
  7006  		case AVMOVQ:
  7007  			fp = 1
  7008  			w = 2 /* 128-bit SIMD/FP */
  7009  
  7010  		case AMOVD:
  7011  			if p.Pool.As == ADWORD {
  7012  				w = 1 /* 64-bit */
  7013  			} else if p.Pool.To.Offset < 0 {
  7014  				w = 2 /* 32-bit, sign-extended to 64-bit */
  7015  			} else if p.Pool.To.Offset >= 0 {
  7016  				w = 0 /* 32-bit, zero-extended to 64-bit */
  7017  			} else {
  7018  				c.ctxt.Diag("invalid operand %v in %v", a, p)
  7019  			}
  7020  
  7021  		case AMOVBU, AMOVHU, AMOVWU:
  7022  			w = 0 /* 32-bit, zero-extended to 64-bit */
  7023  
  7024  		case AMOVB, AMOVH, AMOVW:
  7025  			w = 2 /* 32-bit, sign-extended to 64-bit */
  7026  
  7027  		default:
  7028  			c.ctxt.Diag("invalid operation %v in %v", as, p)
  7029  		}
  7030  
  7031  		v := int32(c.brdist(p, 0, 19, 2))
  7032  		o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
  7033  		o1 |= (v & 0x7FFFF) << 5
  7034  		o1 |= int32(dr & 31)
  7035  	}
  7036  
  7037  	return uint32(o1)
  7038  }
  7039  
  7040  // load a constant (MOVCON or BITCON) in a into rt
  7041  func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
  7042  	if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
  7043  		// or $bitcon, REGZERO, rt
  7044  		mode := 64
  7045  		var as1 obj.As
  7046  		switch as {
  7047  		case AMOVW:
  7048  			as1 = AORRW
  7049  			mode = 32
  7050  		case AMOVD:
  7051  			as1 = AORR
  7052  		}
  7053  		o1 = c.opirr(p, as1)
  7054  		o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  7055  		return o1
  7056  	}
  7057  
  7058  	if as == AMOVW {
  7059  		d := uint32(a.Offset)
  7060  		s := movcon(int64(d))
  7061  		if s < 0 || 16*s >= 32 {
  7062  			d = ^d
  7063  			s = movcon(int64(d))
  7064  			if s < 0 || 16*s >= 32 {
  7065  				c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
  7066  			}
  7067  			o1 = c.opirr(p, AMOVNW)
  7068  		} else {
  7069  			o1 = c.opirr(p, AMOVZW)
  7070  		}
  7071  		o1 |= MOVCONST(int64(d), s, rt)
  7072  	}
  7073  	if as == AMOVD {
  7074  		d := a.Offset
  7075  		s := movcon(d)
  7076  		if s < 0 || 16*s >= 64 {
  7077  			d = ^d
  7078  			s = movcon(d)
  7079  			if s < 0 || 16*s >= 64 {
  7080  				c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
  7081  			}
  7082  			o1 = c.opirr(p, AMOVN)
  7083  		} else {
  7084  			o1 = c.opirr(p, AMOVZ)
  7085  		}
  7086  		o1 |= MOVCONST(d, s, rt)
  7087  	}
  7088  	return o1
  7089  }
  7090  
  7091  // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
  7092  // put the instruction sequence in os and return the number of instructions.
  7093  func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
  7094  	switch as {
  7095  	case AMOVW:
  7096  		d := uint32(a.Offset)
  7097  		// use MOVZW and MOVKW to load a constant to rt
  7098  		os[0] = c.opirr(p, AMOVZW)
  7099  		os[0] |= MOVCONST(int64(d), 0, rt)
  7100  		os[1] = c.opirr(p, AMOVKW)
  7101  		os[1] |= MOVCONST(int64(d), 1, rt)
  7102  		return 2
  7103  
  7104  	case AMOVD:
  7105  		d := a.Offset
  7106  		dn := ^d
  7107  		var immh [4]uint64
  7108  		var i int
  7109  		zeroCount := int(0)
  7110  		negCount := int(0)
  7111  		for i = 0; i < 4; i++ {
  7112  			immh[i] = uint64((d >> uint(i*16)) & 0xffff)
  7113  			if immh[i] == 0 {
  7114  				zeroCount++
  7115  			} else if immh[i] == 0xffff {
  7116  				negCount++
  7117  			}
  7118  		}
  7119  
  7120  		if zeroCount == 4 || negCount == 4 {
  7121  			c.ctxt.Diag("the immediate should be MOVCON: %v", p)
  7122  		}
  7123  		switch {
  7124  		case zeroCount == 3:
  7125  			// one MOVZ
  7126  			for i = 0; i < 4; i++ {
  7127  				if immh[i] != 0 {
  7128  					os[0] = c.opirr(p, AMOVZ)
  7129  					os[0] |= MOVCONST(d, i, rt)
  7130  					break
  7131  				}
  7132  			}
  7133  			return 1
  7134  
  7135  		case negCount == 3:
  7136  			// one MOVN
  7137  			for i = 0; i < 4; i++ {
  7138  				if immh[i] != 0xffff {
  7139  					os[0] = c.opirr(p, AMOVN)
  7140  					os[0] |= MOVCONST(dn, i, rt)
  7141  					break
  7142  				}
  7143  			}
  7144  			return 1
  7145  
  7146  		case zeroCount == 2:
  7147  			// one MOVZ and one MOVK
  7148  			for i = 0; i < 4; i++ {
  7149  				if immh[i] != 0 {
  7150  					os[0] = c.opirr(p, AMOVZ)
  7151  					os[0] |= MOVCONST(d, i, rt)
  7152  					i++
  7153  					break
  7154  				}
  7155  			}
  7156  			for ; i < 4; i++ {
  7157  				if immh[i] != 0 {
  7158  					os[1] = c.opirr(p, AMOVK)
  7159  					os[1] |= MOVCONST(d, i, rt)
  7160  				}
  7161  			}
  7162  			return 2
  7163  
  7164  		case negCount == 2:
  7165  			// one MOVN and one MOVK
  7166  			for i = 0; i < 4; i++ {
  7167  				if immh[i] != 0xffff {
  7168  					os[0] = c.opirr(p, AMOVN)
  7169  					os[0] |= MOVCONST(dn, i, rt)
  7170  					i++
  7171  					break
  7172  				}
  7173  			}
  7174  			for ; i < 4; i++ {
  7175  				if immh[i] != 0xffff {
  7176  					os[1] = c.opirr(p, AMOVK)
  7177  					os[1] |= MOVCONST(d, i, rt)
  7178  				}
  7179  			}
  7180  			return 2
  7181  
  7182  		case zeroCount == 1:
  7183  			// one MOVZ and two MOVKs
  7184  			for i = 0; i < 4; i++ {
  7185  				if immh[i] != 0 {
  7186  					os[0] = c.opirr(p, AMOVZ)
  7187  					os[0] |= MOVCONST(d, i, rt)
  7188  					i++
  7189  					break
  7190  				}
  7191  			}
  7192  
  7193  			for j := 1; i < 4; i++ {
  7194  				if immh[i] != 0 {
  7195  					os[j] = c.opirr(p, AMOVK)
  7196  					os[j] |= MOVCONST(d, i, rt)
  7197  					j++
  7198  				}
  7199  			}
  7200  			return 3
  7201  
  7202  		case negCount == 1:
  7203  			// one MOVN and two MOVKs
  7204  			for i = 0; i < 4; i++ {
  7205  				if immh[i] != 0xffff {
  7206  					os[0] = c.opirr(p, AMOVN)
  7207  					os[0] |= MOVCONST(dn, i, rt)
  7208  					i++
  7209  					break
  7210  				}
  7211  			}
  7212  
  7213  			for j := 1; i < 4; i++ {
  7214  				if immh[i] != 0xffff {
  7215  					os[j] = c.opirr(p, AMOVK)
  7216  					os[j] |= MOVCONST(d, i, rt)
  7217  					j++
  7218  				}
  7219  			}
  7220  			return 3
  7221  
  7222  		default:
  7223  			// one MOVZ and 3 MOVKs
  7224  			os[0] = c.opirr(p, AMOVZ)
  7225  			os[0] |= MOVCONST(d, 0, rt)
  7226  			for i = 1; i < 4; i++ {
  7227  				os[i] = c.opirr(p, AMOVK)
  7228  				os[i] |= MOVCONST(d, i, rt)
  7229  			}
  7230  			return 4
  7231  		}
  7232  	default:
  7233  		return 0
  7234  	}
  7235  }
  7236  
  7237  func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
  7238  	var b uint32
  7239  	o := c.opirr(p, a)
  7240  	if (o & (1 << 31)) == 0 {
  7241  		b = 32
  7242  	} else {
  7243  		b = 64
  7244  	}
  7245  	if r < 0 || uint32(r) >= b {
  7246  		c.ctxt.Diag("illegal bit number\n%v", p)
  7247  	}
  7248  	o |= (uint32(r) & 0x3F) << 16
  7249  	if s < 0 || uint32(s) >= b {
  7250  		c.ctxt.Diag("illegal bit number\n%v", p)
  7251  	}
  7252  	o |= (uint32(s) & 0x3F) << 10
  7253  	o |= (uint32(rf&31) << 5) | uint32(rt&31)
  7254  	return o
  7255  }
  7256  
  7257  func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
  7258  	var b uint32
  7259  	o := c.opirr(p, a)
  7260  	if (o & (1 << 31)) != 0 {
  7261  		b = 63
  7262  	} else {
  7263  		b = 31
  7264  	}
  7265  	if v < 0 || uint32(v) > b {
  7266  		c.ctxt.Diag("illegal bit number\n%v", p)
  7267  	}
  7268  	o |= uint32(v) << 10
  7269  	o |= uint32(rn&31) << 5
  7270  	o |= uint32(rm&31) << 16
  7271  	o |= uint32(rt & 31)
  7272  	return o
  7273  }
  7274  
  7275  /* genrate instruction encoding for ldp and stp series */
  7276  func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
  7277  	wback := false
  7278  	if o.scond == C_XPOST || o.scond == C_XPRE {
  7279  		wback = true
  7280  	}
  7281  	switch p.As {
  7282  	case ALDP, ALDPW, ALDPSW:
  7283  		c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  7284  	case ASTP, ASTPW:
  7285  		if wback == true {
  7286  			c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
  7287  		}
  7288  	case AFLDPD, AFLDPQ, AFLDPS:
  7289  		c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  7290  	}
  7291  	var ret uint32
  7292  	// check offset
  7293  	switch p.As {
  7294  	case AFLDPQ, AFSTPQ:
  7295  		if vo < -1024 || vo > 1008 || vo%16 != 0 {
  7296  			c.ctxt.Diag("invalid offset %v\n", p)
  7297  		}
  7298  		vo /= 16
  7299  		ret = 2<<30 | 1<<26
  7300  	case AFLDPD, AFSTPD:
  7301  		if vo < -512 || vo > 504 || vo%8 != 0 {
  7302  			c.ctxt.Diag("invalid offset %v\n", p)
  7303  		}
  7304  		vo /= 8
  7305  		ret = 1<<30 | 1<<26
  7306  	case AFLDPS, AFSTPS:
  7307  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7308  			c.ctxt.Diag("invalid offset %v\n", p)
  7309  		}
  7310  		vo /= 4
  7311  		ret = 1 << 26
  7312  	case ALDP, ASTP:
  7313  		if vo < -512 || vo > 504 || vo%8 != 0 {
  7314  			c.ctxt.Diag("invalid offset %v\n", p)
  7315  		}
  7316  		vo /= 8
  7317  		ret = 2 << 30
  7318  	case ALDPW, ASTPW:
  7319  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7320  			c.ctxt.Diag("invalid offset %v\n", p)
  7321  		}
  7322  		vo /= 4
  7323  		ret = 0
  7324  	case ALDPSW:
  7325  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7326  			c.ctxt.Diag("invalid offset %v\n", p)
  7327  		}
  7328  		vo /= 4
  7329  		ret = 1 << 30
  7330  	default:
  7331  		c.ctxt.Diag("invalid instruction %v\n", p)
  7332  	}
  7333  	// check register pair
  7334  	switch p.As {
  7335  	case AFLDPQ, AFLDPD, AFLDPS, AFSTPQ, AFSTPD, AFSTPS:
  7336  		if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
  7337  			c.ctxt.Diag("invalid register pair %v\n", p)
  7338  		}
  7339  	case ALDP, ALDPW, ALDPSW:
  7340  		if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
  7341  			c.ctxt.Diag("invalid register pair %v\n", p)
  7342  		}
  7343  	case ASTP, ASTPW:
  7344  		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
  7345  			c.ctxt.Diag("invalid register pair %v\n", p)
  7346  		}
  7347  	}
  7348  	// other conditional flag bits
  7349  	switch o.scond {
  7350  	case C_XPOST:
  7351  		ret |= 1 << 23
  7352  	case C_XPRE:
  7353  		ret |= 3 << 23
  7354  	default:
  7355  		ret |= 2 << 23
  7356  	}
  7357  	ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
  7358  	return ret
  7359  }
  7360  
  7361  func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
  7362  	if p.As == AVLD1 || p.As == AVST1 {
  7363  		return o1
  7364  	}
  7365  
  7366  	o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
  7367  	switch p.As {
  7368  	case AVLD1R, AVLD2R:
  7369  		o1 |= 0xC << 12
  7370  	case AVLD3R, AVLD4R:
  7371  		o1 |= 0xE << 12
  7372  	case AVLD2, AVST2:
  7373  		o1 |= 8 << 12
  7374  	case AVLD3, AVST3:
  7375  		o1 |= 4 << 12
  7376  	case AVLD4, AVST4:
  7377  	default:
  7378  		c.ctxt.Diag("unsupported instruction:%v\n", p.As)
  7379  	}
  7380  	return o1
  7381  }
  7382  
  7383  /*
  7384   * size in log2(bytes)
  7385   */
  7386  func movesize(a obj.As) int {
  7387  	switch a {
  7388  	case AFMOVQ:
  7389  		return 4
  7390  
  7391  	case AMOVD, AFMOVD:
  7392  		return 3
  7393  
  7394  	case AMOVW, AMOVWU, AFMOVS:
  7395  		return 2
  7396  
  7397  	case AMOVH, AMOVHU:
  7398  		return 1
  7399  
  7400  	case AMOVB, AMOVBU:
  7401  		return 0
  7402  
  7403  	default:
  7404  		return -1
  7405  	}
  7406  }
  7407  
  7408  // rm is the Rm register value, o is the extension, amount is the left shift value.
  7409  func roff(rm int16, o uint32, amount int16) uint32 {
  7410  	return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
  7411  }
  7412  
  7413  // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
  7414  func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
  7415  	var num, rm int16
  7416  	num = (r >> 5) & 7
  7417  	rm = r & 31
  7418  	switch {
  7419  	case REG_UXTB <= r && r < REG_UXTH:
  7420  		return roff(rm, 0, num)
  7421  	case REG_UXTH <= r && r < REG_UXTW:
  7422  		return roff(rm, 1, num)
  7423  	case REG_UXTW <= r && r < REG_UXTX:
  7424  		if a.Type == obj.TYPE_MEM {
  7425  			if num == 0 {
  7426  				return roff(rm, 2, 2)
  7427  			} else {
  7428  				return roff(rm, 2, 6)
  7429  			}
  7430  		} else {
  7431  			return roff(rm, 2, num)
  7432  		}
  7433  	case REG_UXTX <= r && r < REG_SXTB:
  7434  		return roff(rm, 3, num)
  7435  	case REG_SXTB <= r && r < REG_SXTH:
  7436  		return roff(rm, 4, num)
  7437  	case REG_SXTH <= r && r < REG_SXTW:
  7438  		return roff(rm, 5, num)
  7439  	case REG_SXTW <= r && r < REG_SXTX:
  7440  		if a.Type == obj.TYPE_MEM {
  7441  			if num == 0 {
  7442  				return roff(rm, 6, 2)
  7443  			} else {
  7444  				return roff(rm, 6, 6)
  7445  			}
  7446  		} else {
  7447  			return roff(rm, 6, num)
  7448  		}
  7449  	case REG_SXTX <= r && r < REG_SPECIAL:
  7450  		if a.Type == obj.TYPE_MEM {
  7451  			if num == 0 {
  7452  				return roff(rm, 7, 2)
  7453  			} else {
  7454  				return roff(rm, 7, 6)
  7455  			}
  7456  		} else {
  7457  			return roff(rm, 7, num)
  7458  		}
  7459  	case REG_LSL <= r && r < (REG_LSL+1<<8):
  7460  		return roff(rm, 3, 6)
  7461  	default:
  7462  		c.ctxt.Diag("unsupported register extension type.")
  7463  	}
  7464  
  7465  	return 0
  7466  }
  7467  
  7468  // pack returns the encoding of the "Q" field and two arrangement specifiers.
  7469  func pack(q uint32, arngA, arngB uint8) uint32 {
  7470  	return uint32(q)<<16 | uint32(arngA)<<8 | uint32(arngB)
  7471  }
  7472  

View as plain text