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

View as plain text