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

View as plain text