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

View as plain text