Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/internal/obj/arm64

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

View as plain text