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

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

View as plain text