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

View as plain text