asm7.go raw

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