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

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

View as plain text