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  	return uint32(bits.Len64(x) - 1)
  1678  }
  1679  
  1680  func autoclass(l int64) int {
  1681  	if l == 0 {
  1682  		return C_ZAUTO
  1683  	}
  1684  
  1685  	if l < 0 {
  1686  		if l >= -256 && (l&15) == 0 {
  1687  			return C_NSAUTO_16
  1688  		}
  1689  		if l >= -256 && (l&7) == 0 {
  1690  			return C_NSAUTO_8
  1691  		}
  1692  		if l >= -256 && (l&3) == 0 {
  1693  			return C_NSAUTO_4
  1694  		}
  1695  		if l >= -256 {
  1696  			return C_NSAUTO
  1697  		}
  1698  		if l >= -512 && (l&15) == 0 {
  1699  			return C_NPAUTO_16
  1700  		}
  1701  		if l >= -512 && (l&7) == 0 {
  1702  			return C_NPAUTO
  1703  		}
  1704  		if l >= -1024 && (l&15) == 0 {
  1705  			return C_NQAUTO_16
  1706  		}
  1707  		if l >= -4095 {
  1708  			return C_NAUTO4K
  1709  		}
  1710  		return C_LAUTO
  1711  	}
  1712  
  1713  	if l <= 255 {
  1714  		if (l & 15) == 0 {
  1715  			return C_PSAUTO_16
  1716  		}
  1717  		if (l & 7) == 0 {
  1718  			return C_PSAUTO_8
  1719  		}
  1720  		if (l & 3) == 0 {
  1721  			return C_PSAUTO_4
  1722  		}
  1723  		return C_PSAUTO
  1724  	}
  1725  	if l <= 504 {
  1726  		if l&15 == 0 {
  1727  			return C_PPAUTO_16
  1728  		}
  1729  		if l&7 == 0 {
  1730  			return C_PPAUTO
  1731  		}
  1732  	}
  1733  	if l <= 1008 {
  1734  		if l&15 == 0 {
  1735  			return C_PQAUTO_16
  1736  		}
  1737  	}
  1738  	if l <= 4095 {
  1739  		if l&15 == 0 {
  1740  			return C_UAUTO4K_16
  1741  		}
  1742  		if l&7 == 0 {
  1743  			return C_UAUTO4K_8
  1744  		}
  1745  		if l&3 == 0 {
  1746  			return C_UAUTO4K_4
  1747  		}
  1748  		if l&1 == 0 {
  1749  			return C_UAUTO4K_2
  1750  		}
  1751  		return C_UAUTO4K
  1752  	}
  1753  	if l <= 8190 {
  1754  		if l&15 == 0 {
  1755  			return C_UAUTO8K_16
  1756  		}
  1757  		if l&7 == 0 {
  1758  			return C_UAUTO8K_8
  1759  		}
  1760  		if l&3 == 0 {
  1761  			return C_UAUTO8K_4
  1762  		}
  1763  		if l&1 == 0 {
  1764  			return C_UAUTO8K
  1765  		}
  1766  	}
  1767  	if l <= 16380 {
  1768  		if l&15 == 0 {
  1769  			return C_UAUTO16K_16
  1770  		}
  1771  		if l&7 == 0 {
  1772  			return C_UAUTO16K_8
  1773  		}
  1774  		if l&3 == 0 {
  1775  			return C_UAUTO16K
  1776  		}
  1777  	}
  1778  	if l <= 32760 {
  1779  		if l&15 == 0 {
  1780  			return C_UAUTO32K_16
  1781  		}
  1782  		if l&7 == 0 {
  1783  			return C_UAUTO32K
  1784  		}
  1785  	}
  1786  	if l <= 65520 && (l&15) == 0 {
  1787  		return C_UAUTO64K
  1788  	}
  1789  	return C_LAUTO
  1790  }
  1791  
  1792  func oregclass(l int64) int {
  1793  	return autoclass(l) - C_ZAUTO + C_ZOREG
  1794  }
  1795  
  1796  /*
  1797   * given an offset v and a class c (see above)
  1798   * return the offset value to use in the instruction,
  1799   * scaled if necessary
  1800   */
  1801  func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
  1802  	s := 0
  1803  	if cls >= C_SEXT1 && cls <= C_SEXT16 {
  1804  		s = cls - C_SEXT1
  1805  	} else {
  1806  		switch cls {
  1807  		case C_UAUTO4K, C_UOREG4K, C_ZOREG:
  1808  			s = 0
  1809  		case C_UAUTO8K, C_UOREG8K:
  1810  			s = 1
  1811  		case C_UAUTO16K, C_UOREG16K:
  1812  			s = 2
  1813  		case C_UAUTO32K, C_UOREG32K:
  1814  			s = 3
  1815  		case C_UAUTO64K, C_UOREG64K:
  1816  			s = 4
  1817  		default:
  1818  			c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
  1819  		}
  1820  	}
  1821  	vs := v >> uint(s)
  1822  	if vs<<uint(s) != v {
  1823  		c.ctxt.Diag("odd offset: %d\n%v", v, p)
  1824  	}
  1825  	return vs
  1826  }
  1827  
  1828  // movcon checks if v contains a single 16 bit value that is aligned on
  1829  // a 16 bit boundary, suitable for use with a movk/movn instruction. The
  1830  // field offset in bits is returned (being a multiple 16), otherwise -1 is
  1831  // returned indicating an unsuitable value.
  1832  func movcon(v int64) int {
  1833  	for s := 0; s < 64; s += 16 {
  1834  		if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
  1835  			return s
  1836  		}
  1837  	}
  1838  	return -1
  1839  }
  1840  
  1841  func rclass(r int16) int {
  1842  	switch {
  1843  	case REG_R0 <= r && r <= REG_R30: // not 31
  1844  		return C_REG
  1845  	case r == REGZERO:
  1846  		return C_ZREG
  1847  	case REG_F0 <= r && r <= REG_F31:
  1848  		return C_FREG
  1849  	case REG_V0 <= r && r <= REG_V31:
  1850  		return C_VREG
  1851  	case r == REGSP:
  1852  		return C_RSP
  1853  	case r >= REG_ARNG && r < REG_ELEM:
  1854  		return C_ARNG
  1855  	case r >= REG_ELEM && r < REG_ELEM_END:
  1856  		return C_ELEM
  1857  	case r >= REG_UXTB && r < REG_SPECIAL,
  1858  		r >= REG_LSL && r < REG_ARNG:
  1859  		return C_EXTREG
  1860  	case r >= REG_SPECIAL:
  1861  		return C_SPR
  1862  	}
  1863  	return C_GOK
  1864  }
  1865  
  1866  // conclass classifies a constant.
  1867  func conclass(v int64, mode int) int {
  1868  	// For constants used with instructions that produce 32 bit results, rewrite the
  1869  	// high 32 bits to be a repetition of the low 32 bits, so that the BITCON test can
  1870  	// be shared for both 32 bit and 64 bit inputs. A 32 bit operation will zero the
  1871  	// high 32 bit of the destination register anyway.
  1872  	vbitcon := uint64(v)
  1873  	if mode == 32 {
  1874  		vbitcon = uint64(v)<<32 | uint64(v)
  1875  	}
  1876  
  1877  	vnotcon := ^v
  1878  	if mode == 32 {
  1879  		vnotcon = int64(uint32(vnotcon))
  1880  	}
  1881  
  1882  	if v == 0 {
  1883  		return C_ZCON
  1884  	}
  1885  	if isaddcon(v) {
  1886  		if v <= 0xFFF {
  1887  			if isbitcon(vbitcon) {
  1888  				return C_ABCON0
  1889  			}
  1890  			return C_ADDCON0
  1891  		}
  1892  		if isbitcon(vbitcon) {
  1893  			return C_ABCON
  1894  		}
  1895  		if movcon(v) >= 0 {
  1896  			return C_AMCON
  1897  		}
  1898  		if movcon(vnotcon) >= 0 {
  1899  			return C_AMCON
  1900  		}
  1901  		return C_ADDCON
  1902  	}
  1903  
  1904  	if t := movcon(v); t >= 0 {
  1905  		if isbitcon(vbitcon) {
  1906  			return C_MBCON
  1907  		}
  1908  		return C_MOVCON
  1909  	}
  1910  	if t := movcon(vnotcon); t >= 0 {
  1911  		if isbitcon(vbitcon) {
  1912  			return C_MBCON
  1913  		}
  1914  		return C_MOVCON
  1915  	}
  1916  
  1917  	if isbitcon(vbitcon) {
  1918  		return C_BITCON
  1919  	}
  1920  
  1921  	if isaddcon2(v) {
  1922  		return C_ADDCON2
  1923  	}
  1924  
  1925  	if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
  1926  		return C_LCON
  1927  	}
  1928  
  1929  	return C_VCON
  1930  }
  1931  
  1932  // con32class reclassifies the constant used with an instruction that produces
  1933  // a 32 bit result. The constant is at most 32 bits but is saved in Offset as
  1934  // a int64. con32class treats it as uint32 type and reclassifies it.
  1935  func (c *ctxt7) con32class(a *obj.Addr) int {
  1936  	return conclass(int64(uint32(a.Offset)), 32)
  1937  }
  1938  
  1939  // con64class reclassifies the constant of C_VCON and C_LCON class.
  1940  func (c *ctxt7) con64class(a *obj.Addr) int {
  1941  	zeroCount := 0
  1942  	negCount := 0
  1943  	for i := uint(0); i < 4; i++ {
  1944  		immh := uint32(a.Offset >> (i * 16) & 0xffff)
  1945  		if immh == 0 {
  1946  			zeroCount++
  1947  		} else if immh == 0xffff {
  1948  			negCount++
  1949  		}
  1950  	}
  1951  	if zeroCount >= 3 || negCount >= 3 {
  1952  		return C_MOVCON
  1953  	} else if zeroCount == 2 || negCount == 2 {
  1954  		return C_MOVCON2
  1955  	}
  1956  	// See omovlconst for description of this loop.
  1957  	for i := 0; i < 4; i++ {
  1958  		mask := uint64(0xffff) << (i * 16)
  1959  		for period := 2; period <= 32; period *= 2 {
  1960  			x := uint64(a.Offset)&^mask | bits.RotateLeft64(uint64(a.Offset), max(period, 16))&mask
  1961  			if isbitcon(x) {
  1962  				return C_MOVCON2
  1963  			}
  1964  		}
  1965  	}
  1966  	if zeroCount == 1 || negCount == 1 {
  1967  		return C_MOVCON3
  1968  	} else {
  1969  		return C_VCON
  1970  	}
  1971  }
  1972  
  1973  // loadStoreClass reclassifies a load or store operation based on its offset.
  1974  func (c *ctxt7) loadStoreClass(p *obj.Prog, lsc int, v int64) int {
  1975  	// Avoid reclassification of pre/post-indexed loads and stores.
  1976  	if p.Scond == C_XPRE || p.Scond == C_XPOST {
  1977  		return lsc
  1978  	}
  1979  	if cmp(C_NSAUTO, lsc) || cmp(C_NSOREG, lsc) {
  1980  		return lsc
  1981  	}
  1982  
  1983  	needsPool := true
  1984  	if v >= -4095 && v <= 4095 {
  1985  		needsPool = false
  1986  	}
  1987  
  1988  	switch p.As {
  1989  	case AMOVB, AMOVBU:
  1990  		if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) {
  1991  			return lsc
  1992  		}
  1993  		if v >= 0 && v <= 0xffffff {
  1994  			needsPool = false
  1995  		}
  1996  	case AMOVH, AMOVHU:
  1997  		if cmp(C_UAUTO8K, lsc) || cmp(C_UOREG8K, lsc) {
  1998  			return lsc
  1999  		}
  2000  		if v >= 0 && v <= 0xfff000+0xfff<<1 && v&1 == 0 {
  2001  			needsPool = false
  2002  		}
  2003  	case AMOVW, AMOVWU, AFMOVS:
  2004  		if cmp(C_UAUTO16K, lsc) || cmp(C_UOREG16K, lsc) {
  2005  			return lsc
  2006  		}
  2007  		if v >= 0 && v <= 0xfff000+0xfff<<2 && v&3 == 0 {
  2008  			needsPool = false
  2009  		}
  2010  	case AMOVD, AFMOVD:
  2011  		if cmp(C_UAUTO32K, lsc) || cmp(C_UOREG32K, lsc) {
  2012  			return lsc
  2013  		}
  2014  		if v >= 0 && v <= 0xfff000+0xfff<<3 && v&7 == 0 {
  2015  			needsPool = false
  2016  		}
  2017  	case AFMOVQ:
  2018  		if cmp(C_UAUTO64K, lsc) || cmp(C_UOREG64K, lsc) {
  2019  			return lsc
  2020  		}
  2021  		if v >= 0 && v <= 0xfff000+0xfff<<4 && v&15 == 0 {
  2022  			needsPool = false
  2023  		}
  2024  	}
  2025  	if needsPool && cmp(C_LAUTO, lsc) {
  2026  		return C_LAUTOPOOL
  2027  	}
  2028  	if needsPool && cmp(C_LOREG, lsc) {
  2029  		return C_LOREGPOOL
  2030  	}
  2031  	return lsc
  2032  }
  2033  
  2034  // loadStorePairClass reclassifies a load or store pair operation based on its offset.
  2035  func (c *ctxt7) loadStorePairClass(p *obj.Prog, lsc int, v int64) int {
  2036  	// Avoid reclassification of pre/post-indexed loads and stores.
  2037  	if p.Scond == C_XPRE || p.Scond == C_XPOST {
  2038  		return lsc
  2039  	}
  2040  
  2041  	if cmp(C_NAUTO4K, lsc) || cmp(C_NOREG4K, lsc) {
  2042  		return lsc
  2043  	}
  2044  	if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) {
  2045  		return lsc
  2046  	}
  2047  
  2048  	needsPool := true
  2049  	if v >= 0 && v <= 0xffffff {
  2050  		needsPool = false
  2051  	}
  2052  	if needsPool && cmp(C_LAUTO, lsc) {
  2053  		return C_LAUTOPOOL
  2054  	}
  2055  	if needsPool && cmp(C_LOREG, lsc) {
  2056  		return C_LOREGPOOL
  2057  	}
  2058  	return lsc
  2059  }
  2060  
  2061  func (c *ctxt7) aclass(a *obj.Addr) int {
  2062  	switch a.Type {
  2063  	case obj.TYPE_NONE:
  2064  		return C_NONE
  2065  
  2066  	case obj.TYPE_REG:
  2067  		return rclass(a.Reg)
  2068  
  2069  	case obj.TYPE_REGREG:
  2070  		return C_PAIR
  2071  
  2072  	case obj.TYPE_SHIFT:
  2073  		return C_SHIFT
  2074  
  2075  	case obj.TYPE_REGLIST:
  2076  		return C_LIST
  2077  
  2078  	case obj.TYPE_MEM:
  2079  		// The base register should be an integer register.
  2080  		if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
  2081  			break
  2082  		}
  2083  		switch a.Name {
  2084  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2085  			if a.Sym == nil {
  2086  				break
  2087  			}
  2088  			c.instoffset = a.Offset
  2089  			if a.Sym != nil { // use relocation
  2090  				if a.Sym.Type == objabi.STLSBSS {
  2091  					if c.ctxt.Flag_shared {
  2092  						return C_TLS_IE
  2093  					} else {
  2094  						return C_TLS_LE
  2095  					}
  2096  				}
  2097  				return C_ADDR
  2098  			}
  2099  			return C_LEXT
  2100  
  2101  		case obj.NAME_GOTREF:
  2102  			return C_GOTADDR
  2103  
  2104  		case obj.NAME_AUTO:
  2105  			if a.Reg == REGSP {
  2106  				// unset base register for better printing, since
  2107  				// a.Offset is still relative to pseudo-SP.
  2108  				a.Reg = obj.REG_NONE
  2109  			}
  2110  			// The frame top 8 or 16 bytes are for FP
  2111  			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  2112  			return autoclass(c.instoffset)
  2113  
  2114  		case obj.NAME_PARAM:
  2115  			if a.Reg == REGSP {
  2116  				// unset base register for better printing, since
  2117  				// a.Offset is still relative to pseudo-FP.
  2118  				a.Reg = obj.REG_NONE
  2119  			}
  2120  			c.instoffset = int64(c.autosize) + a.Offset + 8
  2121  			return autoclass(c.instoffset)
  2122  
  2123  		case obj.NAME_NONE:
  2124  			if a.Index != 0 {
  2125  				if a.Offset != 0 {
  2126  					if isRegShiftOrExt(a) {
  2127  						// extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
  2128  						return C_ROFF
  2129  					}
  2130  					return C_GOK
  2131  				}
  2132  				// register offset, (Rn)(Rm)
  2133  				return C_ROFF
  2134  			}
  2135  			c.instoffset = a.Offset
  2136  			return oregclass(c.instoffset)
  2137  		}
  2138  		return C_GOK
  2139  
  2140  	case obj.TYPE_FCONST:
  2141  		return C_FCON
  2142  
  2143  	case obj.TYPE_TEXTSIZE:
  2144  		return C_TEXTSIZE
  2145  
  2146  	case obj.TYPE_CONST, obj.TYPE_ADDR:
  2147  		switch a.Name {
  2148  		case obj.NAME_NONE:
  2149  			c.instoffset = a.Offset
  2150  			if a.Reg != 0 && a.Reg != REGZERO {
  2151  				break
  2152  			}
  2153  			return conclass(c.instoffset, 64)
  2154  
  2155  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2156  			if a.Sym == nil {
  2157  				return C_GOK
  2158  			}
  2159  			if a.Sym.Type == objabi.STLSBSS {
  2160  				c.ctxt.Diag("taking address of TLS variable is not supported")
  2161  			}
  2162  			c.instoffset = a.Offset
  2163  			return C_VCONADDR
  2164  
  2165  		case obj.NAME_AUTO:
  2166  			if a.Reg == REGSP {
  2167  				// unset base register for better printing, since
  2168  				// a.Offset is still relative to pseudo-SP.
  2169  				a.Reg = obj.REG_NONE
  2170  			}
  2171  			// The frame top 8 or 16 bytes are for FP
  2172  			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  2173  
  2174  		case obj.NAME_PARAM:
  2175  			if a.Reg == REGSP {
  2176  				// unset base register for better printing, since
  2177  				// a.Offset is still relative to pseudo-FP.
  2178  				a.Reg = obj.REG_NONE
  2179  			}
  2180  			c.instoffset = int64(c.autosize) + a.Offset + 8
  2181  		default:
  2182  			return C_GOK
  2183  		}
  2184  		cf := c.instoffset
  2185  		if isaddcon(cf) || isaddcon(-cf) {
  2186  			return C_AACON
  2187  		}
  2188  		if isaddcon2(cf) {
  2189  			return C_AACON2
  2190  		}
  2191  
  2192  		return C_LACON
  2193  
  2194  	case obj.TYPE_BRANCH:
  2195  		return C_SBRA
  2196  
  2197  	case obj.TYPE_SPECIAL:
  2198  		opd := SpecialOperand(a.Offset)
  2199  		if SPOP_EQ <= opd && opd <= SPOP_NV {
  2200  			return C_COND
  2201  		}
  2202  		return C_SPOP
  2203  	}
  2204  	return C_GOK
  2205  }
  2206  
  2207  func (c *ctxt7) oplook(p *obj.Prog) *Optab {
  2208  	a1 := int(p.Optab)
  2209  	if a1 != 0 {
  2210  		return &optab[a1-1]
  2211  	}
  2212  	a1 = int(p.From.Class)
  2213  	if a1 == 0 {
  2214  		a1 = c.aclass(&p.From)
  2215  		// do not break C_ADDCON2 when S bit is set
  2216  		if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a1 == C_ADDCON2 {
  2217  			a1 = C_LCON
  2218  		}
  2219  		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
  2220  			if p.As == AMOVW || isADDWop(p.As) || isANDWop(p.As) {
  2221  				// For 32-bit instruction with constant, we need to
  2222  				// treat its offset value as 32 bits to classify it.
  2223  				a1 = c.con32class(&p.From)
  2224  				// do not break C_ADDCON2 when S bit is set
  2225  				if (p.As == AADDSW || p.As == ASUBSW) && a1 == C_ADDCON2 {
  2226  					a1 = C_LCON
  2227  				}
  2228  			}
  2229  			if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a1 == C_LCON || a1 == C_VCON) {
  2230  				// more specific classification of 64-bit integers
  2231  				a1 = c.con64class(&p.From)
  2232  			}
  2233  		}
  2234  		if p.From.Type == obj.TYPE_MEM {
  2235  			if isMOVop(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) {
  2236  				// More specific classification of large offset loads and stores.
  2237  				a1 = c.loadStoreClass(p, a1, c.instoffset)
  2238  			}
  2239  			if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) {
  2240  				// More specific classification of large offset loads and stores.
  2241  				a1 = c.loadStorePairClass(p, a1, c.instoffset)
  2242  			}
  2243  		}
  2244  		p.From.Class = int8(a1)
  2245  	}
  2246  
  2247  	a2 := C_NONE
  2248  	if p.Reg != 0 {
  2249  		a2 = rclass(p.Reg)
  2250  	}
  2251  
  2252  	a3 := C_NONE
  2253  	if p.GetFrom3() != nil {
  2254  		a3 = int(p.GetFrom3().Class)
  2255  		if a3 == 0 {
  2256  			a3 = c.aclass(p.GetFrom3())
  2257  			p.GetFrom3().Class = int8(a3)
  2258  		}
  2259  	}
  2260  
  2261  	a4 := int(p.To.Class)
  2262  	if a4 == 0 {
  2263  		a4 = c.aclass(&p.To)
  2264  		if p.To.Type == obj.TYPE_MEM {
  2265  			if isMOVop(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) {
  2266  				// More specific classification of large offset loads and stores.
  2267  				a4 = c.loadStoreClass(p, a4, c.instoffset)
  2268  			}
  2269  			if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) {
  2270  				// More specific classification of large offset loads and stores.
  2271  				a4 = c.loadStorePairClass(p, a4, c.instoffset)
  2272  			}
  2273  		}
  2274  		p.To.Class = int8(a4)
  2275  	}
  2276  
  2277  	a5 := C_NONE
  2278  	if p.RegTo2 != 0 {
  2279  		a5 = rclass(p.RegTo2)
  2280  	} else if p.GetTo2() != nil {
  2281  		a5 = int(p.GetTo2().Class)
  2282  		if a5 == 0 {
  2283  			a5 = c.aclass(p.GetTo2())
  2284  			p.GetTo2().Class = int8(a5)
  2285  		}
  2286  	}
  2287  
  2288  	if false {
  2289  		fmt.Printf("oplook %v %d %d %d %d %d\n", p.As, a1, a2, a3, a4, a5)
  2290  		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  2291  	}
  2292  
  2293  	ops := oprange[p.As&obj.AMask]
  2294  	c1 := &xcmp[a1]
  2295  	c2 := &xcmp[a2]
  2296  	c3 := &xcmp[a3]
  2297  	c4 := &xcmp[a4]
  2298  	c5 := &xcmp[a5]
  2299  	for i := range ops {
  2300  		op := &ops[i]
  2301  		if c1[op.a1] && c2[op.a2] && c3[op.a3] && c4[op.a4] && c5[op.a5] && p.Scond == op.scond {
  2302  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  2303  			return op
  2304  		}
  2305  	}
  2306  
  2307  	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)
  2308  	// Turn illegal instruction into an UNDEF, avoid crashing in asmout
  2309  	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
  2310  }
  2311  
  2312  func cmp(a int, b int) bool {
  2313  	if a == b {
  2314  		return true
  2315  	}
  2316  	switch a {
  2317  	case C_RSP:
  2318  		if b == C_REG {
  2319  			return true
  2320  		}
  2321  
  2322  	case C_ZREG:
  2323  		if b == C_REG {
  2324  			return true
  2325  		}
  2326  
  2327  	case C_ADDCON0:
  2328  		if b == C_ZCON || b == C_ABCON0 {
  2329  			return true
  2330  		}
  2331  
  2332  	case C_ADDCON:
  2333  		if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
  2334  			return true
  2335  		}
  2336  
  2337  	case C_MBCON:
  2338  		if b == C_ABCON0 {
  2339  			return true
  2340  		}
  2341  
  2342  	case C_BITCON:
  2343  		if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
  2344  			return true
  2345  		}
  2346  
  2347  	case C_MOVCON:
  2348  		if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON {
  2349  			return true
  2350  		}
  2351  
  2352  	case C_ADDCON2:
  2353  		if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
  2354  			return true
  2355  		}
  2356  
  2357  	case C_LCON:
  2358  		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 {
  2359  			return true
  2360  		}
  2361  
  2362  	case C_MOVCON2:
  2363  		return cmp(C_LCON, b)
  2364  
  2365  	case C_VCON:
  2366  		return cmp(C_LCON, b)
  2367  
  2368  	case C_LACON:
  2369  		if b == C_AACON || b == C_AACON2 {
  2370  			return true
  2371  		}
  2372  
  2373  	case C_SEXT2:
  2374  		if b == C_SEXT1 {
  2375  			return true
  2376  		}
  2377  
  2378  	case C_SEXT4:
  2379  		if b == C_SEXT1 || b == C_SEXT2 {
  2380  			return true
  2381  		}
  2382  
  2383  	case C_SEXT8:
  2384  		if b >= C_SEXT1 && b <= C_SEXT4 {
  2385  			return true
  2386  		}
  2387  
  2388  	case C_SEXT16:
  2389  		if b >= C_SEXT1 && b <= C_SEXT8 {
  2390  			return true
  2391  		}
  2392  
  2393  	case C_LEXT:
  2394  		if b >= C_SEXT1 && b <= C_SEXT16 {
  2395  			return true
  2396  		}
  2397  
  2398  	case C_NSAUTO_8:
  2399  		if b == C_NSAUTO_16 {
  2400  			return true
  2401  		}
  2402  
  2403  	case C_NSAUTO_4:
  2404  		if b == C_NSAUTO_16 || b == C_NSAUTO_8 {
  2405  			return true
  2406  		}
  2407  
  2408  	case C_NSAUTO:
  2409  		switch b {
  2410  		case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16:
  2411  			return true
  2412  		}
  2413  
  2414  	case C_NPAUTO_16:
  2415  		switch b {
  2416  		case C_NSAUTO_16:
  2417  			return true
  2418  		}
  2419  
  2420  	case C_NPAUTO:
  2421  		switch b {
  2422  		case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16:
  2423  			return true
  2424  		}
  2425  
  2426  	case C_NQAUTO_16:
  2427  		switch b {
  2428  		case C_NSAUTO_16, C_NPAUTO_16:
  2429  			return true
  2430  		}
  2431  
  2432  	case C_NAUTO4K:
  2433  		switch b {
  2434  		case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16,
  2435  			C_NPAUTO, C_NQAUTO_16:
  2436  			return true
  2437  		}
  2438  
  2439  	case C_PSAUTO_16:
  2440  		if b == C_ZAUTO {
  2441  			return true
  2442  		}
  2443  
  2444  	case C_PSAUTO_8:
  2445  		if b == C_ZAUTO || b == C_PSAUTO_16 {
  2446  			return true
  2447  		}
  2448  
  2449  	case C_PSAUTO_4:
  2450  		switch b {
  2451  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8:
  2452  			return true
  2453  		}
  2454  
  2455  	case C_PSAUTO:
  2456  		switch b {
  2457  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4:
  2458  			return true
  2459  		}
  2460  
  2461  	case C_PPAUTO_16:
  2462  		switch b {
  2463  		case C_ZAUTO, C_PSAUTO_16:
  2464  			return true
  2465  		}
  2466  
  2467  	case C_PPAUTO:
  2468  		switch b {
  2469  		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16:
  2470  			return true
  2471  		}
  2472  
  2473  	case C_PQAUTO_16:
  2474  		switch b {
  2475  		case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16:
  2476  			return true
  2477  		}
  2478  
  2479  	case C_UAUTO4K:
  2480  		switch b {
  2481  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2482  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2483  			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16:
  2484  			return true
  2485  		}
  2486  
  2487  	case C_UAUTO8K:
  2488  		switch b {
  2489  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2490  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2491  			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2492  			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16:
  2493  			return true
  2494  		}
  2495  
  2496  	case C_UAUTO16K:
  2497  		switch b {
  2498  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2499  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2500  			C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2501  			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
  2502  			C_UAUTO16K_8, C_UAUTO16K_16:
  2503  			return true
  2504  		}
  2505  
  2506  	case C_UAUTO32K:
  2507  		switch b {
  2508  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2509  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2510  			C_UAUTO4K_8, C_UAUTO4K_16,
  2511  			C_UAUTO8K_8, C_UAUTO8K_16,
  2512  			C_UAUTO16K_8, C_UAUTO16K_16,
  2513  			C_UAUTO32K_16:
  2514  			return true
  2515  		}
  2516  
  2517  	case C_UAUTO64K:
  2518  		switch b {
  2519  		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2520  			C_PPAUTO_16, C_PQAUTO_16, C_UAUTO4K_16, C_UAUTO8K_16, C_UAUTO16K_16,
  2521  			C_UAUTO32K_16:
  2522  			return true
  2523  		}
  2524  
  2525  	case C_LAUTO:
  2526  		switch b {
  2527  		case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16, C_NPAUTO_16, C_NPAUTO, C_NQAUTO_16, C_NAUTO4K,
  2528  			C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
  2529  			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
  2530  			C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
  2531  			C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
  2532  			C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K_16,
  2533  			C_UAUTO32K, C_UAUTO32K_16,
  2534  			C_UAUTO64K:
  2535  			return true
  2536  		}
  2537  
  2538  	case C_NSOREG_8:
  2539  		if b == C_NSOREG_16 {
  2540  			return true
  2541  		}
  2542  
  2543  	case C_NSOREG_4:
  2544  		if b == C_NSOREG_8 || b == C_NSOREG_16 {
  2545  			return true
  2546  		}
  2547  
  2548  	case C_NSOREG:
  2549  		switch b {
  2550  		case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16:
  2551  			return true
  2552  		}
  2553  
  2554  	case C_NPOREG_16:
  2555  		switch b {
  2556  		case C_NSOREG_16:
  2557  			return true
  2558  		}
  2559  
  2560  	case C_NPOREG:
  2561  		switch b {
  2562  		case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16:
  2563  			return true
  2564  		}
  2565  
  2566  	case C_NQOREG_16:
  2567  		switch b {
  2568  		case C_NSOREG_16, C_NPOREG_16:
  2569  			return true
  2570  		}
  2571  
  2572  	case C_NOREG4K:
  2573  		switch b {
  2574  		case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16:
  2575  			return true
  2576  		}
  2577  
  2578  	case C_PSOREG_16:
  2579  		if b == C_ZOREG {
  2580  			return true
  2581  		}
  2582  
  2583  	case C_PSOREG_8:
  2584  		if b == C_ZOREG || b == C_PSOREG_16 {
  2585  			return true
  2586  		}
  2587  
  2588  	case C_PSOREG_4:
  2589  		switch b {
  2590  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8:
  2591  			return true
  2592  		}
  2593  
  2594  	case C_PSOREG:
  2595  		switch b {
  2596  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4:
  2597  			return true
  2598  		}
  2599  
  2600  	case C_PPOREG_16:
  2601  		switch b {
  2602  		case C_ZOREG, C_PSOREG_16:
  2603  			return true
  2604  		}
  2605  
  2606  	case C_PPOREG:
  2607  		switch b {
  2608  		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16:
  2609  			return true
  2610  		}
  2611  
  2612  	case C_PQOREG_16:
  2613  		switch b {
  2614  		case C_ZOREG, C_PSOREG_16, C_PPOREG_16:
  2615  			return true
  2616  		}
  2617  
  2618  	case C_UOREG4K:
  2619  		switch b {
  2620  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2621  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2622  			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16:
  2623  			return true
  2624  		}
  2625  
  2626  	case C_UOREG8K:
  2627  		switch b {
  2628  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2629  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2630  			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2631  			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16:
  2632  			return true
  2633  		}
  2634  
  2635  	case C_UOREG16K:
  2636  		switch b {
  2637  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2638  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2639  			C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2640  			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
  2641  			C_UOREG16K_8, C_UOREG16K_16:
  2642  			return true
  2643  		}
  2644  
  2645  	case C_UOREG32K:
  2646  		switch b {
  2647  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2648  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2649  			C_UOREG4K_8, C_UOREG4K_16,
  2650  			C_UOREG8K_8, C_UOREG8K_16,
  2651  			C_UOREG16K_8, C_UOREG16K_16,
  2652  			C_UOREG32K_16:
  2653  			return true
  2654  		}
  2655  
  2656  	case C_UOREG64K:
  2657  		switch b {
  2658  		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2659  			C_PPOREG_16, C_PQOREG_16, C_UOREG4K_16, C_UOREG8K_16, C_UOREG16K_16,
  2660  			C_UOREG32K_16:
  2661  			return true
  2662  		}
  2663  
  2664  	case C_LOREG:
  2665  		switch b {
  2666  		case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NSOREG_16, C_NPOREG, C_NPOREG_16, C_NQOREG_16, C_NOREG4K,
  2667  			C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
  2668  			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
  2669  			C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
  2670  			C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
  2671  			C_UOREG16K, C_UOREG16K_8, C_UOREG16K_16,
  2672  			C_UOREG32K, C_UOREG32K_16,
  2673  			C_UOREG64K:
  2674  			return true
  2675  		}
  2676  
  2677  	case C_LBRA:
  2678  		if b == C_SBRA {
  2679  			return true
  2680  		}
  2681  	}
  2682  
  2683  	return false
  2684  }
  2685  
  2686  func ocmp(p1, p2 Optab) int {
  2687  	if p1.as != p2.as {
  2688  		return int(p1.as) - int(p2.as)
  2689  	}
  2690  	if p1.a1 != p2.a1 {
  2691  		return int(p1.a1) - int(p2.a1)
  2692  	}
  2693  	if p1.a2 != p2.a2 {
  2694  		return int(p1.a2) - int(p2.a2)
  2695  	}
  2696  	if p1.a3 != p2.a3 {
  2697  		return int(p1.a3) - int(p2.a3)
  2698  	}
  2699  	if p1.a4 != p2.a4 {
  2700  		return int(p1.a4) - int(p2.a4)
  2701  	}
  2702  	if p1.scond != p2.scond {
  2703  		return int(p1.scond) - int(p2.scond)
  2704  	}
  2705  	return 0
  2706  }
  2707  
  2708  func oprangeset(a obj.As, t []Optab) {
  2709  	oprange[a&obj.AMask] = t
  2710  }
  2711  
  2712  func buildop(ctxt *obj.Link) {
  2713  	if oprange[AAND&obj.AMask] != nil {
  2714  		// Already initialized; stop now.
  2715  		// This happens in the cmd/asm tests,
  2716  		// each of which re-initializes the arch.
  2717  		return
  2718  	}
  2719  
  2720  	for i := 0; i < C_GOK; i++ {
  2721  		for j := 0; j < C_GOK; j++ {
  2722  			if cmp(j, i) {
  2723  				xcmp[i][j] = true
  2724  			}
  2725  		}
  2726  	}
  2727  
  2728  	slices.SortFunc(optab, ocmp)
  2729  	for i := 0; i < len(optab); i++ {
  2730  		as, start := optab[i].as, i
  2731  		for ; i < len(optab)-1; i++ {
  2732  			if optab[i+1].as != as {
  2733  				break
  2734  			}
  2735  		}
  2736  		t := optab[start : i+1]
  2737  		oprangeset(as, t)
  2738  		switch as {
  2739  		default:
  2740  			ctxt.Diag("unknown op in build: %v", as)
  2741  			ctxt.DiagFlush()
  2742  			log.Fatalf("bad code")
  2743  
  2744  		case AADD:
  2745  			oprangeset(AADDS, t)
  2746  			oprangeset(ASUB, t)
  2747  			oprangeset(ASUBS, t)
  2748  			oprangeset(AADDW, t)
  2749  			oprangeset(AADDSW, t)
  2750  			oprangeset(ASUBW, t)
  2751  			oprangeset(ASUBSW, t)
  2752  
  2753  		case AAND: /* logical immediate, logical shifted register */
  2754  			oprangeset(AANDW, t)
  2755  			oprangeset(AEOR, t)
  2756  			oprangeset(AEORW, t)
  2757  			oprangeset(AORR, t)
  2758  			oprangeset(AORRW, t)
  2759  			oprangeset(ABIC, t)
  2760  			oprangeset(ABICW, t)
  2761  			oprangeset(AEON, t)
  2762  			oprangeset(AEONW, t)
  2763  			oprangeset(AORN, t)
  2764  			oprangeset(AORNW, t)
  2765  
  2766  		case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
  2767  			oprangeset(AANDSW, t)
  2768  			oprangeset(ABICS, t)
  2769  			oprangeset(ABICSW, t)
  2770  
  2771  		case ANEG:
  2772  			oprangeset(ANEGS, t)
  2773  			oprangeset(ANEGSW, t)
  2774  			oprangeset(ANEGW, t)
  2775  
  2776  		case AADC: /* rn=Rd */
  2777  			oprangeset(AADCW, t)
  2778  
  2779  			oprangeset(AADCS, t)
  2780  			oprangeset(AADCSW, t)
  2781  			oprangeset(ASBC, t)
  2782  			oprangeset(ASBCW, t)
  2783  			oprangeset(ASBCS, t)
  2784  			oprangeset(ASBCSW, t)
  2785  
  2786  		case ANGC: /* rn=REGZERO */
  2787  			oprangeset(ANGCW, t)
  2788  
  2789  			oprangeset(ANGCS, t)
  2790  			oprangeset(ANGCSW, t)
  2791  
  2792  		case ACMP:
  2793  			oprangeset(ACMPW, t)
  2794  			oprangeset(ACMN, t)
  2795  			oprangeset(ACMNW, t)
  2796  
  2797  		case ATST:
  2798  			oprangeset(ATSTW, t)
  2799  
  2800  			/* register/register, and shifted */
  2801  		case AMVN:
  2802  			oprangeset(AMVNW, t)
  2803  
  2804  		case AMOVK:
  2805  			oprangeset(AMOVKW, t)
  2806  			oprangeset(AMOVN, t)
  2807  			oprangeset(AMOVNW, t)
  2808  			oprangeset(AMOVZ, t)
  2809  			oprangeset(AMOVZW, t)
  2810  
  2811  		case ASWPD:
  2812  			for i := range atomicLDADD {
  2813  				oprangeset(i, t)
  2814  			}
  2815  			for i := range atomicSWP {
  2816  				if i == ASWPD {
  2817  					continue
  2818  				}
  2819  				oprangeset(i, t)
  2820  			}
  2821  
  2822  		case ACASPD:
  2823  			oprangeset(ACASPW, t)
  2824  		case ABEQ:
  2825  			oprangeset(ABNE, t)
  2826  			oprangeset(ABCS, t)
  2827  			oprangeset(ABHS, t)
  2828  			oprangeset(ABCC, t)
  2829  			oprangeset(ABLO, t)
  2830  			oprangeset(ABMI, t)
  2831  			oprangeset(ABPL, t)
  2832  			oprangeset(ABVS, t)
  2833  			oprangeset(ABVC, t)
  2834  			oprangeset(ABHI, t)
  2835  			oprangeset(ABLS, t)
  2836  			oprangeset(ABGE, t)
  2837  			oprangeset(ABLT, t)
  2838  			oprangeset(ABGT, t)
  2839  			oprangeset(ABLE, t)
  2840  
  2841  		case ALSL:
  2842  			oprangeset(ALSLW, t)
  2843  			oprangeset(ALSR, t)
  2844  			oprangeset(ALSRW, t)
  2845  			oprangeset(AASR, t)
  2846  			oprangeset(AASRW, t)
  2847  			oprangeset(AROR, t)
  2848  			oprangeset(ARORW, t)
  2849  
  2850  		case ACLS:
  2851  			oprangeset(ACLSW, t)
  2852  			oprangeset(ACLZ, t)
  2853  			oprangeset(ACLZW, t)
  2854  			oprangeset(ARBIT, t)
  2855  			oprangeset(ARBITW, t)
  2856  			oprangeset(AREV, t)
  2857  			oprangeset(AREVW, t)
  2858  			oprangeset(AREV16, t)
  2859  			oprangeset(AREV16W, t)
  2860  			oprangeset(AREV32, t)
  2861  
  2862  		case ASDIV:
  2863  			oprangeset(ASDIVW, t)
  2864  			oprangeset(AUDIV, t)
  2865  			oprangeset(AUDIVW, t)
  2866  			oprangeset(ACRC32B, t)
  2867  			oprangeset(ACRC32CB, t)
  2868  			oprangeset(ACRC32CH, t)
  2869  			oprangeset(ACRC32CW, t)
  2870  			oprangeset(ACRC32CX, t)
  2871  			oprangeset(ACRC32H, t)
  2872  			oprangeset(ACRC32W, t)
  2873  			oprangeset(ACRC32X, t)
  2874  
  2875  		case AMADD:
  2876  			oprangeset(AMADDW, t)
  2877  			oprangeset(AMSUB, t)
  2878  			oprangeset(AMSUBW, t)
  2879  			oprangeset(ASMADDL, t)
  2880  			oprangeset(ASMSUBL, t)
  2881  			oprangeset(AUMADDL, t)
  2882  			oprangeset(AUMSUBL, t)
  2883  
  2884  		case AREM:
  2885  			oprangeset(AREMW, t)
  2886  			oprangeset(AUREM, t)
  2887  			oprangeset(AUREMW, t)
  2888  
  2889  		case AMUL:
  2890  			oprangeset(AMULW, t)
  2891  			oprangeset(AMNEG, t)
  2892  			oprangeset(AMNEGW, t)
  2893  			oprangeset(ASMNEGL, t)
  2894  			oprangeset(ASMULL, t)
  2895  			oprangeset(ASMULH, t)
  2896  			oprangeset(AUMNEGL, t)
  2897  			oprangeset(AUMULH, t)
  2898  			oprangeset(AUMULL, t)
  2899  
  2900  		case AMOVB:
  2901  			oprangeset(AMOVBU, t)
  2902  
  2903  		case AMOVH:
  2904  			oprangeset(AMOVHU, t)
  2905  
  2906  		case AMOVW:
  2907  			oprangeset(AMOVWU, t)
  2908  
  2909  		case ABFM:
  2910  			oprangeset(ABFMW, t)
  2911  			oprangeset(ASBFM, t)
  2912  			oprangeset(ASBFMW, t)
  2913  			oprangeset(AUBFM, t)
  2914  			oprangeset(AUBFMW, t)
  2915  
  2916  		case ABFI:
  2917  			oprangeset(ABFIW, t)
  2918  			oprangeset(ABFXIL, t)
  2919  			oprangeset(ABFXILW, t)
  2920  			oprangeset(ASBFIZ, t)
  2921  			oprangeset(ASBFIZW, t)
  2922  			oprangeset(ASBFX, t)
  2923  			oprangeset(ASBFXW, t)
  2924  			oprangeset(AUBFIZ, t)
  2925  			oprangeset(AUBFIZW, t)
  2926  			oprangeset(AUBFX, t)
  2927  			oprangeset(AUBFXW, t)
  2928  
  2929  		case AEXTR:
  2930  			oprangeset(AEXTRW, t)
  2931  
  2932  		case ASXTB:
  2933  			oprangeset(ASXTBW, t)
  2934  			oprangeset(ASXTH, t)
  2935  			oprangeset(ASXTHW, t)
  2936  			oprangeset(ASXTW, t)
  2937  			oprangeset(AUXTB, t)
  2938  			oprangeset(AUXTH, t)
  2939  			oprangeset(AUXTW, t)
  2940  			oprangeset(AUXTBW, t)
  2941  			oprangeset(AUXTHW, t)
  2942  
  2943  		case ACCMN:
  2944  			oprangeset(ACCMNW, t)
  2945  			oprangeset(ACCMP, t)
  2946  			oprangeset(ACCMPW, t)
  2947  
  2948  		case ACSEL:
  2949  			oprangeset(ACSELW, t)
  2950  			oprangeset(ACSINC, t)
  2951  			oprangeset(ACSINCW, t)
  2952  			oprangeset(ACSINV, t)
  2953  			oprangeset(ACSINVW, t)
  2954  			oprangeset(ACSNEG, t)
  2955  			oprangeset(ACSNEGW, t)
  2956  
  2957  		case ACINC:
  2958  			// aliases Rm=Rn, !cond
  2959  			oprangeset(ACINCW, t)
  2960  			oprangeset(ACINV, t)
  2961  			oprangeset(ACINVW, t)
  2962  			oprangeset(ACNEG, t)
  2963  			oprangeset(ACNEGW, t)
  2964  
  2965  			// aliases, Rm=Rn=REGZERO, !cond
  2966  		case ACSET:
  2967  			oprangeset(ACSETW, t)
  2968  
  2969  			oprangeset(ACSETM, t)
  2970  			oprangeset(ACSETMW, t)
  2971  
  2972  		case AMOVD,
  2973  			AB,
  2974  			ABL,
  2975  			AWORD,
  2976  			ADWORD,
  2977  			ABTI,
  2978  			obj.ARET,
  2979  			obj.ATEXT:
  2980  			break
  2981  
  2982  		case AFLDPQ:
  2983  			break
  2984  		case AFSTPQ:
  2985  			break
  2986  		case ALDP:
  2987  			oprangeset(AFLDPD, t)
  2988  
  2989  		case ASTP:
  2990  			oprangeset(AFSTPD, t)
  2991  
  2992  		case ASTPW:
  2993  			oprangeset(AFSTPS, t)
  2994  
  2995  		case ALDPW:
  2996  			oprangeset(ALDPSW, t)
  2997  			oprangeset(AFLDPS, t)
  2998  
  2999  		case AERET:
  3000  			oprangeset(AWFE, t)
  3001  			oprangeset(AWFI, t)
  3002  			oprangeset(AYIELD, t)
  3003  			oprangeset(ASEV, t)
  3004  			oprangeset(ASEVL, t)
  3005  			oprangeset(ANOOP, t)
  3006  			oprangeset(ADRPS, t)
  3007  
  3008  			oprangeset(APACIASP, t)
  3009  			oprangeset(AAUTIASP, t)
  3010  			oprangeset(APACIBSP, t)
  3011  			oprangeset(AAUTIBSP, t)
  3012  			oprangeset(AAUTIA1716, t)
  3013  			oprangeset(AAUTIB1716, t)
  3014  
  3015  		case ACBZ:
  3016  			oprangeset(ACBZW, t)
  3017  			oprangeset(ACBNZ, t)
  3018  			oprangeset(ACBNZW, t)
  3019  
  3020  		case ATBZ:
  3021  			oprangeset(ATBNZ, t)
  3022  
  3023  		case AADR, AADRP:
  3024  			break
  3025  
  3026  		case ACLREX:
  3027  			break
  3028  
  3029  		case ASVC:
  3030  			oprangeset(AHVC, t)
  3031  			oprangeset(AHLT, t)
  3032  			oprangeset(ASMC, t)
  3033  			oprangeset(ABRK, t)
  3034  			oprangeset(ADCPS1, t)
  3035  			oprangeset(ADCPS2, t)
  3036  			oprangeset(ADCPS3, t)
  3037  
  3038  		case AFADDS:
  3039  			oprangeset(AFADDD, t)
  3040  			oprangeset(AFSUBS, t)
  3041  			oprangeset(AFSUBD, t)
  3042  			oprangeset(AFMULS, t)
  3043  			oprangeset(AFMULD, t)
  3044  			oprangeset(AFNMULS, t)
  3045  			oprangeset(AFNMULD, t)
  3046  			oprangeset(AFDIVS, t)
  3047  			oprangeset(AFMAXD, t)
  3048  			oprangeset(AFMAXS, t)
  3049  			oprangeset(AFMIND, t)
  3050  			oprangeset(AFMINS, t)
  3051  			oprangeset(AFMAXNMD, t)
  3052  			oprangeset(AFMAXNMS, t)
  3053  			oprangeset(AFMINNMD, t)
  3054  			oprangeset(AFMINNMS, t)
  3055  			oprangeset(AFDIVD, t)
  3056  
  3057  		case AFMSUBD:
  3058  			oprangeset(AFMSUBS, t)
  3059  			oprangeset(AFMADDS, t)
  3060  			oprangeset(AFMADDD, t)
  3061  			oprangeset(AFNMSUBS, t)
  3062  			oprangeset(AFNMSUBD, t)
  3063  			oprangeset(AFNMADDS, t)
  3064  			oprangeset(AFNMADDD, t)
  3065  
  3066  		case AFCVTSD:
  3067  			oprangeset(AFCVTDS, t)
  3068  			oprangeset(AFABSD, t)
  3069  			oprangeset(AFABSS, t)
  3070  			oprangeset(AFNEGD, t)
  3071  			oprangeset(AFNEGS, t)
  3072  			oprangeset(AFSQRTD, t)
  3073  			oprangeset(AFSQRTS, t)
  3074  			oprangeset(AFRINTNS, t)
  3075  			oprangeset(AFRINTND, t)
  3076  			oprangeset(AFRINTPS, t)
  3077  			oprangeset(AFRINTPD, t)
  3078  			oprangeset(AFRINTMS, t)
  3079  			oprangeset(AFRINTMD, t)
  3080  			oprangeset(AFRINTZS, t)
  3081  			oprangeset(AFRINTZD, t)
  3082  			oprangeset(AFRINTAS, t)
  3083  			oprangeset(AFRINTAD, t)
  3084  			oprangeset(AFRINTXS, t)
  3085  			oprangeset(AFRINTXD, t)
  3086  			oprangeset(AFRINTIS, t)
  3087  			oprangeset(AFRINTID, t)
  3088  			oprangeset(AFCVTDH, t)
  3089  			oprangeset(AFCVTHS, t)
  3090  			oprangeset(AFCVTHD, t)
  3091  			oprangeset(AFCVTSH, t)
  3092  
  3093  		case AFCMPS:
  3094  			oprangeset(AFCMPD, t)
  3095  			oprangeset(AFCMPES, t)
  3096  			oprangeset(AFCMPED, t)
  3097  
  3098  		case AFCCMPS:
  3099  			oprangeset(AFCCMPD, t)
  3100  			oprangeset(AFCCMPES, t)
  3101  			oprangeset(AFCCMPED, t)
  3102  
  3103  		case AFCSELD:
  3104  			oprangeset(AFCSELS, t)
  3105  
  3106  		case AFMOVQ, AFMOVD, AFMOVS,
  3107  			AVMOVQ, AVMOVD, AVMOVS:
  3108  			break
  3109  
  3110  		case AFCVTZSD:
  3111  			oprangeset(AFCVTZSDW, t)
  3112  			oprangeset(AFCVTZSS, t)
  3113  			oprangeset(AFCVTZSSW, t)
  3114  			oprangeset(AFCVTZUD, t)
  3115  			oprangeset(AFCVTZUDW, t)
  3116  			oprangeset(AFCVTZUS, t)
  3117  			oprangeset(AFCVTZUSW, t)
  3118  
  3119  		case ASCVTFD:
  3120  			oprangeset(ASCVTFS, t)
  3121  			oprangeset(ASCVTFWD, t)
  3122  			oprangeset(ASCVTFWS, t)
  3123  			oprangeset(AUCVTFD, t)
  3124  			oprangeset(AUCVTFS, t)
  3125  			oprangeset(AUCVTFWD, t)
  3126  			oprangeset(AUCVTFWS, t)
  3127  
  3128  		case ASYS:
  3129  			oprangeset(AAT, t)
  3130  			oprangeset(AIC, t)
  3131  
  3132  		case ATLBI:
  3133  			oprangeset(ADC, t)
  3134  
  3135  		case ASYSL, AHINT:
  3136  			break
  3137  
  3138  		case ADMB:
  3139  			oprangeset(ADSB, t)
  3140  			oprangeset(AISB, t)
  3141  
  3142  		case AMRS, AMSR:
  3143  			break
  3144  
  3145  		case ALDAR:
  3146  			oprangeset(ALDARW, t)
  3147  			oprangeset(ALDARB, t)
  3148  			oprangeset(ALDARH, t)
  3149  			fallthrough
  3150  
  3151  		case ALDXR:
  3152  			oprangeset(ALDXRB, t)
  3153  			oprangeset(ALDXRH, t)
  3154  			oprangeset(ALDXRW, t)
  3155  
  3156  		case ALDAXR:
  3157  			oprangeset(ALDAXRB, t)
  3158  			oprangeset(ALDAXRH, t)
  3159  			oprangeset(ALDAXRW, t)
  3160  
  3161  		case ALDXP:
  3162  			oprangeset(ALDXPW, t)
  3163  			oprangeset(ALDAXP, t)
  3164  			oprangeset(ALDAXPW, t)
  3165  
  3166  		case ASTLR:
  3167  			oprangeset(ASTLRB, t)
  3168  			oprangeset(ASTLRH, t)
  3169  			oprangeset(ASTLRW, t)
  3170  
  3171  		case ASTXR:
  3172  			oprangeset(ASTXRB, t)
  3173  			oprangeset(ASTXRH, t)
  3174  			oprangeset(ASTXRW, t)
  3175  
  3176  		case ASTLXR:
  3177  			oprangeset(ASTLXRB, t)
  3178  			oprangeset(ASTLXRH, t)
  3179  			oprangeset(ASTLXRW, t)
  3180  
  3181  		case ASTXP:
  3182  			oprangeset(ASTLXP, t)
  3183  			oprangeset(ASTLXPW, t)
  3184  			oprangeset(ASTXPW, t)
  3185  
  3186  		case AVADDP:
  3187  			oprangeset(AVAND, t)
  3188  			oprangeset(AVCMEQ, t)
  3189  			oprangeset(AVORR, t)
  3190  			oprangeset(AVEOR, t)
  3191  			oprangeset(AVBSL, t)
  3192  			oprangeset(AVBIT, t)
  3193  			oprangeset(AVCMTST, t)
  3194  			oprangeset(AVUMAX, t)
  3195  			oprangeset(AVUMIN, t)
  3196  			oprangeset(AVUZP1, t)
  3197  			oprangeset(AVUZP2, t)
  3198  			oprangeset(AVBIF, t)
  3199  
  3200  		case AVADD:
  3201  			oprangeset(AVSUB, t)
  3202  			oprangeset(AVRAX1, t)
  3203  
  3204  		case AAESD:
  3205  			oprangeset(AAESE, t)
  3206  			oprangeset(AAESMC, t)
  3207  			oprangeset(AAESIMC, t)
  3208  			oprangeset(ASHA1SU1, t)
  3209  			oprangeset(ASHA256SU0, t)
  3210  			oprangeset(ASHA512SU0, t)
  3211  			oprangeset(ASHA1H, t)
  3212  
  3213  		case ASHA1C:
  3214  			oprangeset(ASHA1P, t)
  3215  			oprangeset(ASHA1M, t)
  3216  			oprangeset(ASHA256H, t)
  3217  			oprangeset(ASHA256H2, t)
  3218  			oprangeset(ASHA512H, t)
  3219  			oprangeset(ASHA512H2, t)
  3220  
  3221  		case ASHA1SU0:
  3222  			oprangeset(ASHA256SU1, t)
  3223  			oprangeset(ASHA512SU1, t)
  3224  
  3225  		case AVADDV:
  3226  			oprangeset(AVUADDLV, t)
  3227  
  3228  		case AVFMLA:
  3229  			oprangeset(AVFMLS, t)
  3230  
  3231  		case AVPMULL:
  3232  			oprangeset(AVPMULL2, t)
  3233  
  3234  		case AVUSHR:
  3235  			oprangeset(AVSHL, t)
  3236  			oprangeset(AVSRI, t)
  3237  			oprangeset(AVSLI, t)
  3238  			oprangeset(AVUSRA, t)
  3239  
  3240  		case AVREV32:
  3241  			oprangeset(AVCNT, t)
  3242  			oprangeset(AVRBIT, t)
  3243  			oprangeset(AVREV64, t)
  3244  			oprangeset(AVREV16, t)
  3245  
  3246  		case AVZIP1:
  3247  			oprangeset(AVZIP2, t)
  3248  			oprangeset(AVTRN1, t)
  3249  			oprangeset(AVTRN2, t)
  3250  
  3251  		case AVUXTL:
  3252  			oprangeset(AVUXTL2, t)
  3253  
  3254  		case AVUSHLL:
  3255  			oprangeset(AVUSHLL2, t)
  3256  
  3257  		case AVLD1R:
  3258  			oprangeset(AVLD2, t)
  3259  			oprangeset(AVLD2R, t)
  3260  			oprangeset(AVLD3, t)
  3261  			oprangeset(AVLD3R, t)
  3262  			oprangeset(AVLD4, t)
  3263  			oprangeset(AVLD4R, t)
  3264  
  3265  		case AVEOR3:
  3266  			oprangeset(AVBCAX, t)
  3267  
  3268  		case AVUADDW:
  3269  			oprangeset(AVUADDW2, t)
  3270  
  3271  		case AVTBL:
  3272  			oprangeset(AVTBX, t)
  3273  
  3274  		case AVCNT,
  3275  			AVMOV,
  3276  			AVLD1,
  3277  			AVST1,
  3278  			AVST2,
  3279  			AVST3,
  3280  			AVST4,
  3281  			AVDUP,
  3282  			AVMOVI,
  3283  			APRFM,
  3284  			AVEXT,
  3285  			AVXAR:
  3286  			break
  3287  
  3288  		case obj.ANOP,
  3289  			obj.AUNDEF,
  3290  			obj.AFUNCDATA,
  3291  			obj.APCALIGN,
  3292  			obj.APCALIGNMAX,
  3293  			obj.APCDATA:
  3294  			break
  3295  		}
  3296  	}
  3297  }
  3298  
  3299  // chipfloat7() checks if the immediate constants available in  FMOVS/FMOVD instructions.
  3300  // For details of the range of constants available, see
  3301  // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
  3302  func (c *ctxt7) chipfloat7(e float64) int {
  3303  	ei := math.Float64bits(e)
  3304  	l := uint32(int32(ei))
  3305  	h := uint32(int32(ei >> 32))
  3306  
  3307  	if l != 0 || h&0xffff != 0 {
  3308  		return -1
  3309  	}
  3310  	h1 := h & 0x7fc00000
  3311  	if h1 != 0x40000000 && h1 != 0x3fc00000 {
  3312  		return -1
  3313  	}
  3314  	n := 0
  3315  
  3316  	// sign bit (a)
  3317  	if h&0x80000000 != 0 {
  3318  		n |= 1 << 7
  3319  	}
  3320  
  3321  	// exp sign bit (b)
  3322  	if h1 == 0x3fc00000 {
  3323  		n |= 1 << 6
  3324  	}
  3325  
  3326  	// rest of exp and mantissa (cd-efgh)
  3327  	n |= int((h >> 16) & 0x3f)
  3328  
  3329  	//print("match %.8lux %.8lux %d\n", l, h, n);
  3330  	return n
  3331  }
  3332  
  3333  /* form offset parameter to SYS; special register number */
  3334  func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
  3335  	return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
  3336  }
  3337  
  3338  func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
  3339  	return SYSARG5(0, op1, Cn, Cm, op2)
  3340  }
  3341  
  3342  // checkUnpredictable checks if the source and transfer registers are the same register.
  3343  // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
  3344  func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
  3345  	if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
  3346  		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3347  	}
  3348  	if isload && rt1 == rt2 {
  3349  		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3350  	}
  3351  }
  3352  
  3353  /* checkindex checks if index >= 0 && index <= maxindex */
  3354  func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
  3355  	if index < 0 || index > maxindex {
  3356  		c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
  3357  	}
  3358  }
  3359  
  3360  /* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
  3361  func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
  3362  	var offset, list, n, expect int64
  3363  	switch as {
  3364  	case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  3365  		offset = p.From.Offset
  3366  		list = p.To.Offset
  3367  	case AVST1, AVST2, AVST3, AVST4:
  3368  		offset = p.To.Offset
  3369  		list = p.From.Offset
  3370  	default:
  3371  		c.ctxt.Diag("invalid operation on op %v", p.As)
  3372  	}
  3373  	opcode := (list >> 12) & 15
  3374  	q := (list >> 30) & 1
  3375  	size := (list >> 10) & 3
  3376  	if offset == 0 {
  3377  		return
  3378  	}
  3379  	switch opcode {
  3380  	case 0x7:
  3381  		n = 1 // one register
  3382  	case 0xa:
  3383  		n = 2 // two registers
  3384  	case 0x6:
  3385  		n = 3 // three registers
  3386  	case 0x2:
  3387  		n = 4 // four registers
  3388  	default:
  3389  		c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  3390  	}
  3391  
  3392  	switch as {
  3393  	case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  3394  		if offset != n*(1<<uint(size)) {
  3395  			c.ctxt.Diag("invalid post-increment offset: %v", p)
  3396  		}
  3397  	default:
  3398  		if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
  3399  			c.ctxt.Diag("invalid post-increment offset: %v", p)
  3400  		}
  3401  	}
  3402  
  3403  	switch as {
  3404  	case AVLD1, AVST1:
  3405  		return
  3406  	case AVLD1R:
  3407  		expect = 1
  3408  	case AVLD2, AVST2, AVLD2R:
  3409  		expect = 2
  3410  	case AVLD3, AVST3, AVLD3R:
  3411  		expect = 3
  3412  	case AVLD4, AVST4, AVLD4R:
  3413  		expect = 4
  3414  	}
  3415  
  3416  	if expect != n {
  3417  		c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
  3418  	}
  3419  }
  3420  
  3421  /* checkShiftAmount checks whether the index shift amount is valid */
  3422  /* for load with register offset instructions */
  3423  func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
  3424  	var amount int16
  3425  	amount = (a.Index >> 5) & 7
  3426  	switch p.As {
  3427  	case AMOVB, AMOVBU:
  3428  		if amount != 0 {
  3429  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3430  		}
  3431  	case AMOVH, AMOVHU:
  3432  		if amount != 1 && amount != 0 {
  3433  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3434  		}
  3435  	case AMOVW, AMOVWU, AFMOVS:
  3436  		if amount != 2 && amount != 0 {
  3437  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3438  		}
  3439  	case AMOVD, AFMOVD:
  3440  		if amount != 3 && amount != 0 {
  3441  			c.ctxt.Diag("invalid index shift amount: %v", p)
  3442  		}
  3443  	default:
  3444  		panic("invalid operation")
  3445  	}
  3446  }
  3447  
  3448  func (c *ctxt7) asmout(p *obj.Prog, out []uint32) (count int) {
  3449  	o := c.oplook(p)
  3450  
  3451  	var os [5]uint32
  3452  	o1 := uint32(0)
  3453  	o2 := uint32(0)
  3454  	o3 := uint32(0)
  3455  	o4 := uint32(0)
  3456  	o5 := uint32(0)
  3457  	if false { /*debug['P']*/
  3458  		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  3459  	}
  3460  	switch o.type_ {
  3461  	default:
  3462  		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  3463  
  3464  	case 0: /* pseudo ops */
  3465  		break
  3466  
  3467  	case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
  3468  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  3469  		if p.To.Type == obj.TYPE_NONE {
  3470  			rt = REGZERO
  3471  		}
  3472  		if r == obj.REG_NONE {
  3473  			r = rt
  3474  		}
  3475  		o1 = c.oprrr(p, p.As, rt, r, rf)
  3476  
  3477  	case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
  3478  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3479  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3480  		}
  3481  		o1 = c.opirr(p, p.As)
  3482  
  3483  		rt, r := p.To.Reg, p.Reg
  3484  		if p.To.Type == obj.TYPE_NONE {
  3485  			if (o1 & Sbit) == 0 {
  3486  				c.ctxt.Diag("ineffective ZR destination\n%v", p)
  3487  			}
  3488  			rt = REGZERO
  3489  		}
  3490  		if r == obj.REG_NONE {
  3491  			r = rt
  3492  		}
  3493  		v := c.regoff(&p.From)
  3494  		o1 = c.oaddi(p, p.As, v, rt, r)
  3495  
  3496  	case 3: /* op R<<n[,R],R (shifted register) */
  3497  		rt, r := p.To.Reg, p.Reg
  3498  		if p.To.Type == obj.TYPE_NONE {
  3499  			rt = REGZERO
  3500  		}
  3501  		if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) {
  3502  			r = REGZERO
  3503  		} else if r == obj.REG_NONE {
  3504  			r = rt
  3505  		}
  3506  		o1 = c.oprrr(p, p.As, rt, r, obj.REG_NONE)
  3507  
  3508  		amount := (p.From.Offset >> 10) & 63
  3509  		is64bit := o1 & (1 << 31)
  3510  		if is64bit == 0 && amount >= 32 {
  3511  			c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
  3512  		}
  3513  		shift := (p.From.Offset >> 22) & 3
  3514  		if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) {
  3515  			c.ctxt.Diag("unsupported shift operator: %v", p)
  3516  		}
  3517  		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  3518  
  3519  	case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
  3520  		rt, r := p.To.Reg, o.param
  3521  		if r == obj.REG_NONE {
  3522  			r = REGZERO
  3523  		} else if r == REGFROM {
  3524  			r = p.From.Reg
  3525  		}
  3526  		if r == obj.REG_NONE {
  3527  			r = REGSP
  3528  		}
  3529  
  3530  		v := c.regoff(&p.From)
  3531  		a := AADD
  3532  		if v < 0 {
  3533  			a = ASUB
  3534  			v = -v
  3535  		}
  3536  
  3537  		if o.size(c.ctxt, p) == 8 {
  3538  			// NOTE: this case does not use REGTMP. If it ever does,
  3539  			// remove the NOTUSETMP flag in optab.
  3540  			o1 = c.oaddi(p, a, v&0xfff000, rt, r)
  3541  			o2 = c.oaddi(p, a, v&0x000fff, rt, rt)
  3542  			break
  3543  		}
  3544  
  3545  		o1 = c.oaddi(p, a, v, rt, r)
  3546  
  3547  	case 5: /* b s; bl s */
  3548  		o1 = c.opbra(p, p.As)
  3549  
  3550  		if p.To.Sym == nil {
  3551  			o1 |= uint32(c.brdist(p, 0, 26, 2))
  3552  			break
  3553  		}
  3554  
  3555  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  3556  			Type: objabi.R_CALLARM64,
  3557  			Off:  int32(c.pc),
  3558  			Siz:  4,
  3559  			Sym:  p.To.Sym,
  3560  			Add:  p.To.Offset,
  3561  		})
  3562  
  3563  	case 6: /* b ,O(R); bl ,O(R) */
  3564  		o1 = c.opbrr(p, p.As)
  3565  		o1 |= uint32(p.To.Reg&31) << 5
  3566  		if p.As == obj.ACALL {
  3567  			c.cursym.AddRel(c.ctxt, obj.Reloc{
  3568  				Type: objabi.R_CALLIND,
  3569  				Off:  int32(c.pc),
  3570  			})
  3571  		}
  3572  
  3573  	case 7: /* beq s */
  3574  		o1 = c.opbra(p, p.As)
  3575  
  3576  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  3577  
  3578  	case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
  3579  		rt, rf := p.To.Reg, p.Reg
  3580  		if rf == obj.REG_NONE {
  3581  			rf = rt
  3582  		}
  3583  		v := p.From.Offset
  3584  		switch p.As {
  3585  		case AASR:
  3586  			o1 = c.opbfm(p, ASBFM, v, 63, rf, rt)
  3587  
  3588  		case AASRW:
  3589  			o1 = c.opbfm(p, ASBFMW, v, 31, rf, rt)
  3590  
  3591  		case ALSL:
  3592  			o1 = c.opbfm(p, AUBFM, (64-v)&63, 63-v, rf, rt)
  3593  
  3594  		case ALSLW:
  3595  			o1 = c.opbfm(p, AUBFMW, (32-v)&31, 31-v, rf, rt)
  3596  
  3597  		case ALSR:
  3598  			o1 = c.opbfm(p, AUBFM, v, 63, rf, rt)
  3599  
  3600  		case ALSRW:
  3601  			o1 = c.opbfm(p, AUBFMW, v, 31, rf, rt)
  3602  
  3603  		case AROR:
  3604  			o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
  3605  
  3606  		case ARORW:
  3607  			o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
  3608  
  3609  		default:
  3610  			c.ctxt.Diag("bad shift $con\n%v", p)
  3611  			break
  3612  		}
  3613  
  3614  	case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
  3615  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  3616  		if r == obj.REG_NONE {
  3617  			r = rt
  3618  		}
  3619  		o1 = c.oprrr(p, p.As, rt, r, rf)
  3620  
  3621  	case 10: /* brk/hvc/.../svc [$con] */
  3622  		o1 = c.opimm(p, p.As)
  3623  
  3624  		if p.From.Type != obj.TYPE_NONE {
  3625  			o1 |= uint32((p.From.Offset & 0xffff) << 5)
  3626  		}
  3627  
  3628  	case 11: /* dword */
  3629  		c.aclass(&p.To)
  3630  
  3631  		o1 = uint32(c.instoffset)
  3632  		o2 = uint32(c.instoffset >> 32)
  3633  		if p.To.Sym != nil {
  3634  			c.cursym.AddRel(c.ctxt, obj.Reloc{
  3635  				Type: objabi.R_ADDR,
  3636  				Off:  int32(c.pc),
  3637  				Siz:  8,
  3638  				Sym:  p.To.Sym,
  3639  				Add:  p.To.Offset,
  3640  			})
  3641  			o2 = 0
  3642  			o1 = o2
  3643  		}
  3644  
  3645  	case 12: /* movT $vcon, reg */
  3646  		// NOTE: this case does not use REGTMP. If it ever does,
  3647  		// remove the NOTUSETMP flag in optab.
  3648  		num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
  3649  		if num == 0 {
  3650  			c.ctxt.Diag("invalid constant: %v", p)
  3651  		}
  3652  		o1 = os[0]
  3653  		o2 = os[1]
  3654  		o3 = os[2]
  3655  		o4 = os[3]
  3656  
  3657  	case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
  3658  		if p.Reg == REGTMP {
  3659  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  3660  		}
  3661  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3662  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3663  		}
  3664  		o := uint32(0)
  3665  		num := uint8(0)
  3666  		cls := int(p.From.Class)
  3667  		if isADDWop(p.As) {
  3668  			if !cmp(C_LCON, cls) {
  3669  				c.ctxt.Diag("illegal combination: %v", p)
  3670  			}
  3671  			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3672  		} else {
  3673  			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3674  		}
  3675  		if num == 0 {
  3676  			c.ctxt.Diag("invalid constant: %v", p)
  3677  		}
  3678  
  3679  		rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP)
  3680  		if p.To.Type == obj.TYPE_NONE {
  3681  			rt = REGZERO
  3682  		}
  3683  		if r == obj.REG_NONE {
  3684  			r = rt
  3685  		}
  3686  		if p.To.Type != obj.TYPE_NONE && (rt == REGSP || r == REGSP) {
  3687  			o = c.opxrrr(p, p.As, rt, r, rf, false)
  3688  			o |= LSL0_64
  3689  		} else {
  3690  			o = c.oprrr(p, p.As, rt, r, rf)
  3691  		}
  3692  
  3693  		os[num] = o
  3694  		o1 = os[0]
  3695  		o2 = os[1]
  3696  		o3 = os[2]
  3697  		o4 = os[3]
  3698  		o5 = os[4]
  3699  
  3700  	case 14: /* word */
  3701  		if c.aclass(&p.To) == C_ADDR {
  3702  			c.ctxt.Diag("address constant needs DWORD\n%v", p)
  3703  		}
  3704  		o1 = uint32(c.instoffset)
  3705  		if p.To.Sym != nil {
  3706  			// This case happens with words generated
  3707  			// in the PC stream as part of the literal pool.
  3708  			c.cursym.AddRel(c.ctxt, obj.Reloc{
  3709  				Type: objabi.R_ADDR,
  3710  				Off:  int32(c.pc),
  3711  				Siz:  4,
  3712  				Sym:  p.To.Sym,
  3713  				Add:  p.To.Offset,
  3714  			})
  3715  			o1 = 0
  3716  		}
  3717  
  3718  	case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
  3719  		rt, r, rf, ra := p.To.Reg, p.Reg, p.From.Reg, int16(REGZERO)
  3720  		if r == obj.REG_NONE {
  3721  			r = rt
  3722  		}
  3723  		if p.From3Type() == obj.TYPE_REG {
  3724  			r, ra = p.GetFrom3().Reg, p.Reg
  3725  			if ra == obj.REG_NONE {
  3726  				ra = REGZERO
  3727  			}
  3728  		}
  3729  		o1 = c.oprrrr(p, p.As, rt, r, rf, ra)
  3730  
  3731  	case 16: /* XremY R[,R],R -> XdivY; XmsubY */
  3732  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  3733  		if r == obj.REG_NONE {
  3734  			r = rt
  3735  		}
  3736  		o1 = c.oprrr(p, p.As, REGTMP, r, rf)
  3737  		o2 = c.oprrrr(p, AMSUBW, rt, REGTMP, rf, r)
  3738  		o2 |= o1 & (1 << 31) /* same size */
  3739  
  3740  	case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
  3741  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  3742  		if p.To.Type == obj.TYPE_NONE {
  3743  			rt = REGZERO
  3744  		}
  3745  		if r == obj.REG_NONE {
  3746  			r = REGZERO
  3747  		}
  3748  		o1 = c.oprrr(p, p.As, rt, r, rf)
  3749  
  3750  	case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
  3751  		cond := SpecialOperand(p.From.Offset)
  3752  		if cond < SPOP_EQ || cond > SPOP_NV || (cond == SPOP_AL || cond == SPOP_NV) && p.From3Type() == obj.TYPE_NONE {
  3753  			c.ctxt.Diag("invalid condition: %v", p)
  3754  		} else {
  3755  			cond -= SPOP_EQ
  3756  		}
  3757  
  3758  		rt, r, rf := p.To.Reg, p.Reg, p.Reg
  3759  		if p.From3Type() == obj.TYPE_NONE {
  3760  			/* CINC/CINV/CNEG or CSET/CSETM*/
  3761  			if r == obj.REG_NONE {
  3762  				/* CSET/CSETM */
  3763  				r, rf = REGZERO, REGZERO
  3764  			}
  3765  			cond ^= 1
  3766  		} else {
  3767  			rf = p.GetFrom3().Reg /* CSEL */
  3768  		}
  3769  		o1 = c.oprrr(p, p.As, rt, r, rf)
  3770  		o1 |= uint32(cond&15) << 12
  3771  
  3772  	case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
  3773  		nzcv := int(p.To.Offset)
  3774  
  3775  		cond := SpecialOperand(p.From.Offset)
  3776  		if cond < SPOP_EQ || cond > SPOP_NV {
  3777  			c.ctxt.Diag("invalid condition\n%v", p)
  3778  		} else {
  3779  			cond -= SPOP_EQ
  3780  		}
  3781  		if p.GetFrom3().Type == obj.TYPE_REG {
  3782  			r, rf := p.Reg, p.GetFrom3().Reg
  3783  			o1 = c.oprrr(p, p.As, obj.REG_NONE, r, rf)
  3784  			o1 |= (uint32(cond&15) << 12) | uint32(nzcv)
  3785  		} else {
  3786  			rf := int(p.GetFrom3().Offset & 0x1F)
  3787  			o1 = c.opirr(p, p.As)
  3788  			o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
  3789  		}
  3790  
  3791  	case 20: /* movT R,O(R) -> strT */
  3792  		v := c.regoff(&p.To)
  3793  		sz := int32(1 << uint(movesize(p.As)))
  3794  
  3795  		rt, rf := p.To.Reg, p.From.Reg
  3796  		if rt == obj.REG_NONE {
  3797  			rt = o.param
  3798  		}
  3799  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3800  			o1 = c.olsr9s(p, c.opstr(p, p.As), v, rt, rf)
  3801  		} else {
  3802  			v = int32(c.offsetshift(p, int64(v), int(o.a4)))
  3803  			o1 = c.olsr12u(p, c.opstr(p, p.As), v, rt, rf)
  3804  		}
  3805  
  3806  	case 21: /* movT O(R),R -> ldrT */
  3807  		v := c.regoff(&p.From)
  3808  		sz := int32(1 << uint(movesize(p.As)))
  3809  
  3810  		rt, rf := p.To.Reg, p.From.Reg
  3811  		if rf == obj.REG_NONE {
  3812  			rf = o.param
  3813  		}
  3814  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3815  			o1 = c.olsr9s(p, c.opldr(p, p.As), v, rf, rt)
  3816  		} else {
  3817  			v = int32(c.offsetshift(p, int64(v), int(o.a1)))
  3818  			o1 = c.olsr12u(p, c.opldr(p, p.As), v, rf, rt)
  3819  		}
  3820  
  3821  	case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
  3822  		if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
  3823  			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3824  		}
  3825  
  3826  		v := int32(p.From.Offset)
  3827  
  3828  		if v < -256 || v > 255 {
  3829  			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
  3830  		}
  3831  		o1 = c.opldr(p, p.As)
  3832  		if o.scond == C_XPOST {
  3833  			o1 |= 1 << 10
  3834  		} else {
  3835  			o1 |= 3 << 10
  3836  		}
  3837  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
  3838  
  3839  	case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
  3840  		if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
  3841  			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3842  		}
  3843  
  3844  		v := int32(p.To.Offset)
  3845  
  3846  		if v < -256 || v > 255 {
  3847  			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
  3848  		}
  3849  		o1 = c.opstr(p, p.As)
  3850  		if o.scond == C_XPOST {
  3851  			o1 |= 1 << 10
  3852  		} else {
  3853  			o1 |= 3 << 10
  3854  		}
  3855  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
  3856  
  3857  	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
  3858  		rt, r, rf := p.To.Reg, int16(REGZERO), p.From.Reg
  3859  		if rt == REGSP || rf == REGSP {
  3860  			if p.As == AMVN || p.As == AMVNW {
  3861  				c.ctxt.Diag("illegal SP reference\n%v", p)
  3862  			}
  3863  			o1 = c.opirr(p, p.As)
  3864  			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3865  		} else {
  3866  			o1 = c.oprrr(p, p.As, rt, r, rf)
  3867  		}
  3868  
  3869  	case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
  3870  		rt, r, rf := p.To.Reg, int16(REGZERO), p.From.Reg
  3871  		if rf == obj.REG_NONE {
  3872  			rf = rt
  3873  		}
  3874  		o1 = c.oprrr(p, p.As, rt, r, rf)
  3875  
  3876  	case 26: /* op Vn, Vd; op Vn.<T>, Vd.<T> */
  3877  		rt, rf := p.To.Reg, p.From.Reg
  3878  		af := (rf >> 5) & 15
  3879  		at := (rt >> 5) & 15
  3880  		cf := c.aclass(&p.From)
  3881  		var sz int16
  3882  		switch p.As {
  3883  		case AAESD, AAESE, AAESIMC, AAESMC:
  3884  			sz = ARNG_16B
  3885  		case ASHA1SU1, ASHA256SU0:
  3886  			sz = ARNG_4S
  3887  		case ASHA512SU0:
  3888  			sz = ARNG_2D
  3889  		}
  3890  
  3891  		if cf == C_ARNG {
  3892  			if p.As == ASHA1H {
  3893  				c.ctxt.Diag("invalid operands: %v", p)
  3894  			} else {
  3895  				if af != sz || af != at {
  3896  					c.ctxt.Diag("invalid arrangement: %v", p)
  3897  				}
  3898  			}
  3899  		}
  3900  		o1 = c.oprrr(p, p.As, rt, rf, obj.REG_NONE)
  3901  
  3902  	case 27: /* op Rm<<n[,Rn],Rd (extended register) */
  3903  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  3904  			c.ctxt.Diag("illegal destination register: %v\n", p)
  3905  		}
  3906  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  3907  		if p.To.Type == obj.TYPE_NONE {
  3908  			rt = REGZERO
  3909  		}
  3910  		if r == obj.REG_NONE {
  3911  			r = rt
  3912  		}
  3913  		if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 ||
  3914  			(p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) {
  3915  			amount := (p.From.Reg >> 5) & 7
  3916  			if amount > 4 {
  3917  				c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
  3918  			}
  3919  			o1 = c.opxrrr(p, p.As, rt, r, obj.REG_NONE, true)
  3920  			o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
  3921  		} else {
  3922  			o1 = c.opxrrr(p, p.As, rt, r, rf, false)
  3923  		}
  3924  
  3925  	case 28: /* logop $vcon, [R], R (64 bit literal) */
  3926  		if p.Reg == REGTMP {
  3927  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  3928  		}
  3929  		o := uint32(0)
  3930  		num := uint8(0)
  3931  		cls := int(p.From.Class)
  3932  		if isANDWop(p.As) {
  3933  			if !cmp(C_LCON, cls) {
  3934  				c.ctxt.Diag("illegal combination: %v", p)
  3935  			}
  3936  			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3937  		} else {
  3938  			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3939  		}
  3940  
  3941  		if num == 0 {
  3942  			c.ctxt.Diag("invalid constant: %v", p)
  3943  		}
  3944  		rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP)
  3945  		if p.To.Type == obj.TYPE_NONE {
  3946  			rt = REGZERO
  3947  		}
  3948  		if r == obj.REG_NONE {
  3949  			r = rt
  3950  		}
  3951  		o = c.oprrr(p, p.As, rt, r, rf)
  3952  
  3953  		os[num] = o
  3954  		o1 = os[0]
  3955  		o2 = os[1]
  3956  		o3 = os[2]
  3957  		o4 = os[3]
  3958  		o5 = os[4]
  3959  
  3960  	case 29: /* op Rn, Rd */
  3961  		fc := c.aclass(&p.From)
  3962  		tc := c.aclass(&p.To)
  3963  		if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZREG || tc == C_REG || tc == C_ZREG) {
  3964  			// FMOV Rx, Fy or FMOV Fy, Rx
  3965  			o1 = FPCVTI(0, 0, 0, 0, 6)
  3966  			if p.As == AFMOVD {
  3967  				o1 |= 1<<31 | 1<<22 // 64-bit
  3968  			}
  3969  			if fc == C_REG || fc == C_ZREG {
  3970  				o1 |= 1 << 16 // FMOV Rx, Fy
  3971  			}
  3972  			o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
  3973  		} else {
  3974  			o1 = c.oprrr(p, p.As, p.To.Reg, p.From.Reg, obj.REG_NONE)
  3975  		}
  3976  
  3977  	case 30: /* movT R,L(R) -> strT */
  3978  		// If offset L fits in a 12 bit unsigned immediate:
  3979  		//	add $L, R, Rtmp  or  sub $L, R, Rtmp
  3980  		//	str R, (Rtmp)
  3981  		// Otherwise, if offset L can be split into hi+lo, and both fit into instructions:
  3982  		//	add $hi, R, Rtmp
  3983  		//	str R, lo(Rtmp)
  3984  		// Otherwise, use constant pool:
  3985  		//	mov $L, Rtmp (from constant pool)
  3986  		//	str R, (R+Rtmp)
  3987  		s := movesize(o.as)
  3988  		if s < 0 {
  3989  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3990  		}
  3991  
  3992  		rt, rf := p.To.Reg, p.From.Reg
  3993  		if rt == obj.REG_NONE {
  3994  			rt = o.param
  3995  		}
  3996  
  3997  		v := c.regoff(&p.To)
  3998  		if v >= -256 && v <= 256 {
  3999  			c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate store)", p, v)
  4000  		}
  4001  		if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 {
  4002  			c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate store)", p, v)
  4003  		}
  4004  
  4005  		// Handle smaller unaligned and negative offsets via addition or subtraction.
  4006  		if v >= -4095 && v <= 4095 {
  4007  			o1 = c.oaddi12(p, v, REGTMP, rt)
  4008  			o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, rf)
  4009  			break
  4010  		}
  4011  
  4012  		hi, lo, err := splitImm24uScaled(v, s)
  4013  		if err != nil {
  4014  			goto storeusepool
  4015  		}
  4016  		if p.Pool != nil {
  4017  			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
  4018  		}
  4019  		o1 = c.oaddi(p, AADD, hi, REGTMP, rt)
  4020  		o2 = c.olsr12u(p, c.opstr(p, p.As), lo, REGTMP, rf)
  4021  		break
  4022  
  4023  	storeusepool:
  4024  		if p.Pool == nil {
  4025  			c.ctxt.Diag("%v: constant is not in pool", p)
  4026  		}
  4027  		if rt == REGTMP || rf == REGTMP {
  4028  			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  4029  		}
  4030  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  4031  		o2 = c.opstrr(p, p.As, rf, rt, REGTMP, false)
  4032  
  4033  	case 31: /* movT L(R), R -> ldrT */
  4034  		// If offset L fits in a 12 bit unsigned immediate:
  4035  		//	add $L, R, Rtmp  or  sub $L, R, Rtmp
  4036  		//	ldr R, (Rtmp)
  4037  		// Otherwise, if offset L can be split into hi+lo, and both fit into instructions:
  4038  		//	add $hi, R, Rtmp
  4039  		//	ldr lo(Rtmp), R
  4040  		// Otherwise, use constant pool:
  4041  		//	mov $L, Rtmp (from constant pool)
  4042  		//	ldr (R+Rtmp), R
  4043  		s := movesize(o.as)
  4044  		if s < 0 {
  4045  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  4046  		}
  4047  
  4048  		rt, rf := p.To.Reg, p.From.Reg
  4049  		if rf == obj.REG_NONE {
  4050  			rf = o.param
  4051  		}
  4052  
  4053  		v := c.regoff(&p.From)
  4054  		if v >= -256 && v <= 256 {
  4055  			c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate load)", p, v)
  4056  		}
  4057  		if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 {
  4058  			c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate load)", p, v)
  4059  		}
  4060  
  4061  		// Handle smaller unaligned and negative offsets via addition or subtraction.
  4062  		if v >= -4095 && v <= 4095 {
  4063  			o1 = c.oaddi12(p, v, REGTMP, rf)
  4064  			o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, rt)
  4065  			break
  4066  		}
  4067  
  4068  		hi, lo, err := splitImm24uScaled(v, s)
  4069  		if err != nil {
  4070  			goto loadusepool
  4071  		}
  4072  		if p.Pool != nil {
  4073  			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
  4074  		}
  4075  		o1 = c.oaddi(p, AADD, hi, REGTMP, rf)
  4076  		o2 = c.olsr12u(p, c.opldr(p, p.As), lo, REGTMP, rt)
  4077  		break
  4078  
  4079  	loadusepool:
  4080  		if p.Pool == nil {
  4081  			c.ctxt.Diag("%v: constant is not in pool", p)
  4082  		}
  4083  		if rt == REGTMP || rf == REGTMP {
  4084  			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  4085  		}
  4086  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  4087  		o2 = c.opldrr(p, p.As, rt, rf, REGTMP, false)
  4088  
  4089  	case 32: /* mov $con, R -> movz/movn */
  4090  		o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
  4091  
  4092  	case 33: /* movk $uimm16 << pos */
  4093  		o1 = c.opirr(p, p.As)
  4094  
  4095  		d := p.From.Offset
  4096  		if d == 0 {
  4097  			c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p)
  4098  		}
  4099  		s := movcon(d)
  4100  		if s < 0 || s >= 64 {
  4101  			c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
  4102  		}
  4103  		if (o1&S64) == 0 && s >= 32 {
  4104  			c.ctxt.Diag("illegal bit position\n%v", p)
  4105  		}
  4106  		if ((uint64(d) >> uint(s)) >> 16) != 0 {
  4107  			c.ctxt.Diag("requires uimm16\n%v", p)
  4108  		}
  4109  		rt := int(p.To.Reg)
  4110  
  4111  		o1 |= uint32((((d >> uint(s)) & 0xFFFF) << 5) | int64((uint32(s>>4)&3)<<21) | int64(rt&31))
  4112  
  4113  	case 34: /* mov $lacon,R */
  4114  		rt, r, rf := p.To.Reg, p.From.Reg, int16(REGTMP)
  4115  		if r == obj.REG_NONE {
  4116  			r = o.param
  4117  		}
  4118  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  4119  		o2 = c.opxrrr(p, AADD, rt, r, rf, false)
  4120  		o2 |= LSL0_64
  4121  
  4122  	case 35: /* mov SPR,R -> mrs */
  4123  		o1 = c.oprrr(p, AMRS, p.To.Reg, obj.REG_NONE, obj.REG_NONE)
  4124  
  4125  		// SysRegEnc function returns the system register encoding and accessFlags.
  4126  		_, v, accessFlags := SysRegEnc(p.From.Reg)
  4127  		if v == 0 {
  4128  			c.ctxt.Diag("illegal system register:\n%v", p)
  4129  		}
  4130  		if (o1 & (v &^ (3 << 19))) != 0 {
  4131  			c.ctxt.Diag("MRS register value overlap\n%v", p)
  4132  		}
  4133  		if accessFlags&SR_READ == 0 {
  4134  			c.ctxt.Diag("system register is not readable: %v", p)
  4135  		}
  4136  		o1 |= v
  4137  
  4138  	case 36: /* mov R,SPR */
  4139  		o1 = c.oprrr(p, AMSR, p.From.Reg, obj.REG_NONE, obj.REG_NONE)
  4140  
  4141  		// SysRegEnc function returns the system register encoding and accessFlags.
  4142  		_, v, accessFlags := SysRegEnc(p.To.Reg)
  4143  		if v == 0 {
  4144  			c.ctxt.Diag("illegal system register:\n%v", p)
  4145  		}
  4146  		if (o1 & (v &^ (3 << 19))) != 0 {
  4147  			c.ctxt.Diag("MSR register value overlap\n%v", p)
  4148  		}
  4149  		if accessFlags&SR_WRITE == 0 {
  4150  			c.ctxt.Diag("system register is not writable: %v", p)
  4151  		}
  4152  		o1 |= v
  4153  
  4154  	case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
  4155  		if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
  4156  			c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
  4157  		}
  4158  		o1 = c.opirr(p, AMSR)
  4159  		o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
  4160  		v := uint32(0)
  4161  		// PSTATEfield can be special registers and special operands.
  4162  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SPSel {
  4163  			v = 0<<16 | 4<<12 | 5<<5
  4164  		} else if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_DIT {
  4165  			// op1 = 011 (3) op2 = 010 (2)
  4166  			v = 3<<16 | 2<<5
  4167  		} else if p.To.Type == obj.TYPE_SPECIAL {
  4168  			opd := SpecialOperand(p.To.Offset)
  4169  			for _, pf := range pstatefield {
  4170  				if pf.opd == opd {
  4171  					v = pf.enc
  4172  					break
  4173  				}
  4174  			}
  4175  		}
  4176  
  4177  		if v == 0 {
  4178  			c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
  4179  		}
  4180  		o1 |= v
  4181  
  4182  	case 38: /* clrex [$imm] */
  4183  		o1 = c.opimm(p, p.As)
  4184  
  4185  		if p.To.Type == obj.TYPE_NONE {
  4186  			o1 |= 0xF << 8
  4187  		} else {
  4188  			o1 |= uint32((p.To.Offset & 0xF) << 8)
  4189  		}
  4190  
  4191  	case 39: /* cbz R, rel */
  4192  		o1 = c.opirr(p, p.As)
  4193  
  4194  		o1 |= uint32(p.From.Reg & 31)
  4195  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  4196  
  4197  	case 40: /* tbz */
  4198  		o1 = c.opirr(p, p.As)
  4199  
  4200  		v := int32(p.From.Offset)
  4201  		if v < 0 || v > 63 {
  4202  			c.ctxt.Diag("illegal bit number\n%v", p)
  4203  		}
  4204  		o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
  4205  		o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
  4206  		o1 |= uint32(p.Reg & 31)
  4207  
  4208  	case 41: /* eret, nop, others with no operands */
  4209  		o1 = c.op0(p, p.As)
  4210  
  4211  	case 42: /* bfm R,r,s,R */
  4212  		o1 = c.opbfm(p, p.As, p.From.Offset, p.GetFrom3().Offset, p.Reg, p.To.Reg)
  4213  
  4214  	case 43: /* bfm aliases */
  4215  		rt, rf := p.To.Reg, p.Reg
  4216  		if rf == obj.REG_NONE {
  4217  			rf = rt
  4218  		}
  4219  		r, s := p.From.Offset, p.GetFrom3().Offset
  4220  		switch p.As {
  4221  		case ABFI:
  4222  			if r != 0 {
  4223  				r = 64 - r
  4224  			}
  4225  			o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
  4226  
  4227  		case ABFIW:
  4228  			if r != 0 {
  4229  				r = 32 - r
  4230  			}
  4231  			o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
  4232  
  4233  		case ABFXIL:
  4234  			o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
  4235  
  4236  		case ABFXILW:
  4237  			o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
  4238  
  4239  		case ASBFIZ:
  4240  			if r != 0 {
  4241  				r = 64 - r
  4242  			}
  4243  			o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
  4244  
  4245  		case ASBFIZW:
  4246  			if r != 0 {
  4247  				r = 32 - r
  4248  			}
  4249  			o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
  4250  
  4251  		case ASBFX:
  4252  			o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
  4253  
  4254  		case ASBFXW:
  4255  			o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
  4256  
  4257  		case AUBFIZ:
  4258  			if r != 0 {
  4259  				r = 64 - r
  4260  			}
  4261  			o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
  4262  
  4263  		case AUBFIZW:
  4264  			if r != 0 {
  4265  				r = 32 - r
  4266  			}
  4267  			o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
  4268  
  4269  		case AUBFX:
  4270  			o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
  4271  
  4272  		case AUBFXW:
  4273  			o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
  4274  
  4275  		default:
  4276  			c.ctxt.Diag("bad bfm alias\n%v", p)
  4277  			break
  4278  		}
  4279  
  4280  	case 44: /* extr $b, Rn, Rm, Rd */
  4281  		o1 = c.opextr(p, p.As, p.From.Offset, p.GetFrom3().Reg, p.Reg, p.To.Reg)
  4282  
  4283  	case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
  4284  		as := p.As
  4285  		rt, rf := p.To.Reg, p.From.Reg
  4286  		if rf == REGZERO {
  4287  			as = AMOVWU /* clearer in disassembly */
  4288  		}
  4289  		switch as {
  4290  		case AMOVB, ASXTB:
  4291  			o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
  4292  
  4293  		case AMOVH, ASXTH:
  4294  			o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
  4295  
  4296  		case AMOVW, ASXTW:
  4297  			o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
  4298  
  4299  		case AMOVBU, AUXTB:
  4300  			o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
  4301  
  4302  		case AMOVHU, AUXTH:
  4303  			o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
  4304  
  4305  		case AMOVWU:
  4306  			o1 = c.oprrr(p, as, p.To.Reg, REGZERO, p.From.Reg)
  4307  
  4308  		case AUXTW:
  4309  			o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
  4310  
  4311  		case ASXTBW:
  4312  			o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
  4313  
  4314  		case ASXTHW:
  4315  			o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
  4316  
  4317  		case AUXTBW:
  4318  			o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
  4319  
  4320  		case AUXTHW:
  4321  			o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
  4322  
  4323  		default:
  4324  			c.ctxt.Diag("bad sxt %v", as)
  4325  			break
  4326  		}
  4327  
  4328  	case 46: /* cls */
  4329  		o1 = c.opbit(p, p.As)
  4330  
  4331  		o1 |= uint32(p.From.Reg&31) << 5
  4332  		o1 |= uint32(p.To.Reg & 31)
  4333  
  4334  	case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt
  4335  		rs := p.From.Reg
  4336  		rt := p.RegTo2
  4337  		rb := p.To.Reg
  4338  
  4339  		// rt can't be sp.
  4340  		if rt == REG_RSP {
  4341  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4342  		}
  4343  
  4344  		o1 = atomicLDADD[p.As] | atomicSWP[p.As]
  4345  		o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  4346  
  4347  	case 48: /* ADD $C_ADDCON2, Rm, Rd */
  4348  		// NOTE: this case does not use REGTMP. If it ever does,
  4349  		// remove the NOTUSETMP flag in optab.
  4350  		op := c.opirr(p, p.As)
  4351  		if op&Sbit != 0 {
  4352  			c.ctxt.Diag("can not break addition/subtraction when S bit is set (%v)", p)
  4353  		}
  4354  		rt, r := p.To.Reg, p.Reg
  4355  		if r == obj.REG_NONE {
  4356  			r = rt
  4357  		}
  4358  		o1 = c.oaddi(p, p.As, c.regoff(&p.From)&0x000fff, rt, r)
  4359  		o2 = c.oaddi(p, p.As, c.regoff(&p.From)&0xfff000, rt, rt)
  4360  
  4361  	case 49: /* op Vm.<T>, Vn, Vd */
  4362  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  4363  		cf := c.aclass(&p.From)
  4364  		af := (rf >> 5) & 15
  4365  		sz := ARNG_4S
  4366  		if p.As == ASHA512H || p.As == ASHA512H2 {
  4367  			sz = ARNG_2D
  4368  		}
  4369  		if cf == C_ARNG && af != int16(sz) {
  4370  			c.ctxt.Diag("invalid arrangement: %v", p)
  4371  		}
  4372  		o1 = c.oprrr(p, p.As, rt, r, rf)
  4373  
  4374  	case 50: /* sys/sysl */
  4375  		o1 = c.opirr(p, p.As)
  4376  
  4377  		if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
  4378  			c.ctxt.Diag("illegal SYS argument\n%v", p)
  4379  		}
  4380  		o1 |= uint32(p.From.Offset)
  4381  		if p.To.Type == obj.TYPE_REG {
  4382  			o1 |= uint32(p.To.Reg & 31)
  4383  		} else {
  4384  			o1 |= 0x1F
  4385  		}
  4386  
  4387  	case 51: /* dmb */
  4388  		o1 = c.opirr(p, p.As)
  4389  
  4390  		if p.From.Type == obj.TYPE_CONST {
  4391  			o1 |= uint32((p.From.Offset & 0xF) << 8)
  4392  		}
  4393  
  4394  	case 52: /* hint */
  4395  		o1 = c.opirr(p, p.As)
  4396  
  4397  		o1 |= uint32((p.From.Offset & 0x7F) << 5)
  4398  
  4399  	case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
  4400  		a := p.As
  4401  		rt := int(p.To.Reg)
  4402  		if p.To.Type == obj.TYPE_NONE {
  4403  			rt = REGZERO
  4404  		}
  4405  		r := int(p.Reg)
  4406  		if r == obj.REG_NONE {
  4407  			r = rt
  4408  		}
  4409  		if r == REG_RSP {
  4410  			c.ctxt.Diag("illegal source register: %v", p)
  4411  			break
  4412  		}
  4413  		mode := 64
  4414  		v := uint64(p.From.Offset)
  4415  		switch p.As {
  4416  		case AANDW, AORRW, AEORW, AANDSW, ATSTW:
  4417  			mode = 32
  4418  		case ABIC, AORN, AEON, ABICS:
  4419  			v = ^v
  4420  		case ABICW, AORNW, AEONW, ABICSW:
  4421  			v = ^v
  4422  			mode = 32
  4423  		}
  4424  		o1 = c.opirr(p, a)
  4425  		o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
  4426  
  4427  	case 54: /* floating point arith */
  4428  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  4429  		o1 = c.oprrr(p, p.As, obj.REG_NONE, obj.REG_NONE, obj.REG_NONE)
  4430  		if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
  4431  			r, rf = rf, obj.REG_NONE
  4432  		} else if r == obj.REG_NONE {
  4433  			r = rt
  4434  		}
  4435  		o1 = c.oprrr(p, p.As, rt, r, rf)
  4436  
  4437  	case 55: /* floating-point constant */
  4438  		var rf int
  4439  		o1 = 0xf<<25 | 1<<21 | 1<<12
  4440  		rf = c.chipfloat7(p.From.Val.(float64))
  4441  		if rf < 0 {
  4442  			c.ctxt.Diag("invalid floating-point immediate\n%v", p)
  4443  		}
  4444  		if p.As == AFMOVD {
  4445  			o1 |= 1 << 22
  4446  		}
  4447  		o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
  4448  
  4449  	case 56: /* floating point compare */
  4450  		r, rf := p.Reg, p.From.Reg
  4451  		if p.From.Type == obj.TYPE_FCONST {
  4452  			o1 |= 8 /* zero */
  4453  			rf = obj.REG_NONE
  4454  		}
  4455  		o1 |= c.oprrr(p, p.As, obj.REG_NONE, r, rf)
  4456  
  4457  	case 57: /* floating point conditional compare */
  4458  		cond := SpecialOperand(p.From.Offset)
  4459  		if cond < SPOP_EQ || cond > SPOP_NV {
  4460  			c.ctxt.Diag("invalid condition\n%v", p)
  4461  		} else {
  4462  			cond -= SPOP_EQ
  4463  		}
  4464  
  4465  		nzcv := int(p.To.Offset)
  4466  		if nzcv&^0xF != 0 {
  4467  			c.ctxt.Diag("implausible condition\n%v", p)
  4468  		}
  4469  
  4470  		if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
  4471  			c.ctxt.Diag("illegal FCCMP\n%v", p)
  4472  			break
  4473  		}
  4474  		o1 = c.oprrr(p, p.As, obj.REG_NONE, p.GetFrom3().Reg, p.Reg)
  4475  		o1 |= uint32(cond&15)<<12 | uint32(nzcv)
  4476  
  4477  	case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
  4478  		o1 = c.opload(p, p.As)
  4479  
  4480  		o1 |= 0x1F << 16
  4481  		o1 |= uint32(p.From.Reg&31) << 5
  4482  		if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
  4483  			if int(p.To.Reg) == int(p.To.Offset) {
  4484  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4485  			}
  4486  			o1 |= uint32(p.To.Offset&31) << 10
  4487  		} else {
  4488  			o1 |= 0x1F << 10
  4489  		}
  4490  		o1 |= uint32(p.To.Reg & 31)
  4491  
  4492  	case 59: /* stxr/stlxr/stxp/stlxp */
  4493  		s := p.RegTo2
  4494  		n := p.To.Reg
  4495  		t := p.From.Reg
  4496  		if isSTLXRop(p.As) {
  4497  			if s == t || (s == n && n != REGSP) {
  4498  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4499  			}
  4500  		} else if isSTXPop(p.As) {
  4501  			t2 := int16(p.From.Offset)
  4502  			if (s == t || s == t2) || (s == n && n != REGSP) {
  4503  				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  4504  			}
  4505  		}
  4506  		if s == REG_RSP {
  4507  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4508  		}
  4509  		o1 = c.opstore(p, p.As)
  4510  
  4511  		if p.RegTo2 != obj.REG_NONE {
  4512  			o1 |= uint32(p.RegTo2&31) << 16
  4513  		} else {
  4514  			o1 |= 0x1F << 16
  4515  		}
  4516  		if isSTXPop(p.As) {
  4517  			o1 |= uint32(p.From.Offset&31) << 10
  4518  		}
  4519  		o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
  4520  
  4521  	case 60: /* adrp label,r */
  4522  		d := c.brdist(p, 12, 21, 0)
  4523  
  4524  		o1 = ADR(1, uint32(d), uint32(p.To.Reg))
  4525  
  4526  	case 61: /* adr label, r */
  4527  		d := c.brdist(p, 0, 21, 0)
  4528  
  4529  		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
  4530  
  4531  	case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
  4532  		if p.Reg == REGTMP {
  4533  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  4534  		}
  4535  		if p.To.Reg == REG_RSP && isADDSop(p.As) {
  4536  			c.ctxt.Diag("illegal destination register: %v\n", p)
  4537  		}
  4538  		lsl0 := LSL0_64
  4539  		if isADDWop(p.As) || isANDWop(p.As) {
  4540  			o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
  4541  			lsl0 = LSL0_32
  4542  		} else {
  4543  			o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
  4544  		}
  4545  
  4546  		rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP)
  4547  		if p.To.Type == obj.TYPE_NONE {
  4548  			rt = REGZERO
  4549  		}
  4550  		if r == obj.REG_NONE {
  4551  			r = rt
  4552  		}
  4553  		if rt == REGSP || r == REGSP {
  4554  			o2 = c.opxrrr(p, p.As, rt, r, rf, false)
  4555  			o2 |= uint32(lsl0)
  4556  		} else {
  4557  			o2 = c.oprrr(p, p.As, rt, r, rf)
  4558  		}
  4559  
  4560  	case 63: /* op Vm.<t>, Vn.<T>, Vd.<T> */
  4561  		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
  4562  		af := (rf >> 5) & 15
  4563  		at := (rt >> 5) & 15
  4564  		ar := (r >> 5) & 15
  4565  		sz := ARNG_4S
  4566  		if p.As == ASHA512SU1 {
  4567  			sz = ARNG_2D
  4568  		}
  4569  		if af != at || af != ar || af != int16(sz) {
  4570  			c.ctxt.Diag("invalid arrangement: %v", p)
  4571  		}
  4572  		o1 |= c.oprrr(p, p.As, rt, r, rf)
  4573  
  4574  	/* reloc ops */
  4575  	case 64: /* movT R,addr -> adrp + movT R, (REGTMP) */
  4576  		if p.From.Reg == REGTMP {
  4577  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  4578  		}
  4579  		o1 = ADR(1, 0, REGTMP)
  4580  		var typ objabi.RelocType
  4581  		// For unaligned access, fall back to adrp + add + movT R, (REGTMP).
  4582  		if o.size(c.ctxt, p) != 8 {
  4583  			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4584  			o3 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg)
  4585  			typ = objabi.R_ADDRARM64
  4586  		} else {
  4587  			o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg)
  4588  			typ = c.addrRelocType(p)
  4589  		}
  4590  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4591  			Type: typ,
  4592  			Off:  int32(c.pc),
  4593  			Siz:  8,
  4594  			Sym:  p.To.Sym,
  4595  			Add:  p.To.Offset,
  4596  		})
  4597  
  4598  	case 65: /* movT addr,R -> adrp + movT (REGTMP), R */
  4599  		o1 = ADR(1, 0, REGTMP)
  4600  		var typ objabi.RelocType
  4601  		// For unaligned access, fall back to adrp + add + movT (REGTMP), R.
  4602  		if o.size(c.ctxt, p) != 8 {
  4603  			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4604  			o3 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg)
  4605  			typ = objabi.R_ADDRARM64
  4606  		} else {
  4607  			o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg)
  4608  			typ = c.addrRelocType(p)
  4609  		}
  4610  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4611  			Type: typ,
  4612  			Off:  int32(c.pc),
  4613  			Siz:  8,
  4614  			Sym:  p.From.Sym,
  4615  			Add:  p.From.Offset,
  4616  		})
  4617  
  4618  	case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
  4619  		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
  4620  		if rf == obj.REG_NONE {
  4621  			rf = o.param
  4622  		}
  4623  		if rf == obj.REG_NONE {
  4624  			c.ctxt.Diag("invalid ldp source: %v\n", p)
  4625  		}
  4626  		v := c.regoff(&p.From)
  4627  		o1 = c.opldpstp(p, o, v, rf, rt1, rt2, 1)
  4628  
  4629  	case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
  4630  		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
  4631  		if rt == obj.REG_NONE {
  4632  			rt = o.param
  4633  		}
  4634  		if rt == obj.REG_NONE {
  4635  			c.ctxt.Diag("invalid stp destination: %v\n", p)
  4636  		}
  4637  		v := c.regoff(&p.To)
  4638  		o1 = c.opldpstp(p, o, v, rt, rf1, rf2, 0)
  4639  
  4640  	case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
  4641  		// NOTE: this case does not use REGTMP. If it ever does,
  4642  		// remove the NOTUSETMP flag in optab.
  4643  		if p.As == AMOVW {
  4644  			c.ctxt.Diag("invalid load of 32-bit address: %v", p)
  4645  		}
  4646  		o1 = ADR(1, 0, uint32(p.To.Reg))
  4647  		o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
  4648  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4649  			Type: objabi.R_ADDRARM64,
  4650  			Off:  int32(c.pc),
  4651  			Siz:  8,
  4652  			Sym:  p.From.Sym,
  4653  			Add:  p.From.Offset,
  4654  		})
  4655  
  4656  	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
  4657  		o1 = c.opirr(p, AMOVZ)
  4658  		o1 |= uint32(p.To.Reg & 31)
  4659  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4660  			Type: objabi.R_ARM64_TLS_LE,
  4661  			Off:  int32(c.pc),
  4662  			Siz:  4,
  4663  			Sym:  p.From.Sym,
  4664  		})
  4665  		if p.From.Offset != 0 {
  4666  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4667  		}
  4668  
  4669  	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
  4670  		o1 = ADR(1, 0, REGTMP)
  4671  		o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg)
  4672  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4673  			Type: objabi.R_ARM64_TLS_IE,
  4674  			Off:  int32(c.pc),
  4675  			Siz:  8,
  4676  			Sym:  p.From.Sym,
  4677  		})
  4678  		if p.From.Offset != 0 {
  4679  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  4680  		}
  4681  
  4682  	case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
  4683  		o1 = ADR(1, 0, REGTMP)
  4684  		o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg)
  4685  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  4686  			Type: objabi.R_ARM64_GOTPCREL,
  4687  			Off:  int32(c.pc),
  4688  			Siz:  8,
  4689  			Sym:  p.From.Sym,
  4690  		})
  4691  
  4692  	case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2/vrax1 Vm.<T>, Vn.<T>, Vd.<T> */
  4693  		af := int((p.From.Reg >> 5) & 15)
  4694  		af3 := int((p.Reg >> 5) & 15)
  4695  		at := int((p.To.Reg >> 5) & 15)
  4696  		if af != af3 || af != at {
  4697  			c.ctxt.Diag("operand mismatch: %v", p)
  4698  			break
  4699  		}
  4700  
  4701  		Q := 0
  4702  		size := 0
  4703  		switch af {
  4704  		case ARNG_16B:
  4705  			Q = 1
  4706  			size = 0
  4707  		case ARNG_2D:
  4708  			Q = 1
  4709  			size = 3
  4710  		case ARNG_2S:
  4711  			Q = 0
  4712  			size = 2
  4713  		case ARNG_4H:
  4714  			Q = 0
  4715  			size = 1
  4716  		case ARNG_4S:
  4717  			Q = 1
  4718  			size = 2
  4719  		case ARNG_8B:
  4720  			Q = 0
  4721  			size = 0
  4722  		case ARNG_8H:
  4723  			Q = 1
  4724  			size = 1
  4725  		default:
  4726  			c.ctxt.Diag("invalid arrangement: %v", p)
  4727  		}
  4728  
  4729  		switch p.As {
  4730  		case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
  4731  			if af != ARNG_16B && af != ARNG_8B {
  4732  				c.ctxt.Diag("invalid arrangement: %v", p)
  4733  			}
  4734  		case AVFMLA, AVFMLS:
  4735  			if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
  4736  				c.ctxt.Diag("invalid arrangement: %v", p)
  4737  			}
  4738  		case AVUMAX, AVUMIN:
  4739  			if af == ARNG_2D {
  4740  				c.ctxt.Diag("invalid arrangement: %v", p)
  4741  			}
  4742  		}
  4743  		switch p.As {
  4744  		case AVAND, AVEOR:
  4745  			size = 0
  4746  		case AVBSL:
  4747  			size = 1
  4748  		case AVORR, AVBIT, AVBIF:
  4749  			size = 2
  4750  		case AVFMLA, AVFMLS:
  4751  			if af == ARNG_2D {
  4752  				size = 1
  4753  			} else {
  4754  				size = 0
  4755  			}
  4756  		case AVRAX1:
  4757  			if af != ARNG_2D {
  4758  				c.ctxt.Diag("invalid arrangement: %v", p)
  4759  			}
  4760  			size = 0
  4761  			Q = 0
  4762  		}
  4763  
  4764  		o1 = c.oprrr(p, p.As, p.To.Reg, p.Reg, p.From.Reg)
  4765  		o1 |= uint32(Q&1)<<30 | uint32(size&3)<<22
  4766  
  4767  	case 73: /* vmov V.<T>[index], R */
  4768  		rf := int(p.From.Reg)
  4769  		rt := int(p.To.Reg)
  4770  		imm5 := 0
  4771  		o1 = 7<<25 | 0xf<<10
  4772  		index := int(p.From.Index)
  4773  		switch (p.From.Reg >> 5) & 15 {
  4774  		case ARNG_B:
  4775  			c.checkindex(p, index, 15)
  4776  			imm5 |= 1
  4777  			imm5 |= index << 1
  4778  		case ARNG_H:
  4779  			c.checkindex(p, index, 7)
  4780  			imm5 |= 2
  4781  			imm5 |= index << 2
  4782  		case ARNG_S:
  4783  			c.checkindex(p, index, 3)
  4784  			imm5 |= 4
  4785  			imm5 |= index << 3
  4786  		case ARNG_D:
  4787  			c.checkindex(p, index, 1)
  4788  			imm5 |= 8
  4789  			imm5 |= index << 4
  4790  			o1 |= 1 << 30
  4791  		default:
  4792  			c.ctxt.Diag("invalid arrangement: %v", p)
  4793  		}
  4794  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4795  
  4796  	case 74:
  4797  		//	add $O, R, Rtmp or sub $O, R, Rtmp
  4798  		//	ldp (Rtmp), (R1, R2)
  4799  		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
  4800  		if rf == obj.REG_NONE {
  4801  			rf = o.param
  4802  		}
  4803  		if rf == obj.REG_NONE {
  4804  			c.ctxt.Diag("invalid ldp source: %v", p)
  4805  		}
  4806  		v := c.regoff(&p.From)
  4807  		o1 = c.oaddi12(p, v, REGTMP, rf)
  4808  		o2 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
  4809  
  4810  	case 75:
  4811  		// If offset L fits in a 24 bit unsigned immediate:
  4812  		//	add $lo, R, Rtmp
  4813  		//	add $hi, Rtmp, Rtmp
  4814  		//	ldr (Rtmp), R
  4815  		// Otherwise, use constant pool:
  4816  		//	mov $L, Rtmp (from constant pool)
  4817  		//	add Rtmp, R, Rtmp
  4818  		//	ldp (Rtmp), (R1, R2)
  4819  		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
  4820  		if rf == REGTMP {
  4821  			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  4822  		}
  4823  		if rf == obj.REG_NONE {
  4824  			rf = o.param
  4825  		}
  4826  		if rf == obj.REG_NONE {
  4827  			c.ctxt.Diag("invalid ldp source: %v", p)
  4828  		}
  4829  
  4830  		v := c.regoff(&p.From)
  4831  		if v >= -4095 && v <= 4095 {
  4832  			c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+ldp)", p, v)
  4833  		}
  4834  
  4835  		hi, lo, err := splitImm24uScaled(v, 0)
  4836  		if err != nil {
  4837  			goto loadpairusepool
  4838  		}
  4839  		if p.Pool != nil {
  4840  			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
  4841  		}
  4842  		o1 = c.oaddi(p, AADD, lo, REGTMP, rf)
  4843  		o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP)
  4844  		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
  4845  		break
  4846  
  4847  	loadpairusepool:
  4848  		if p.Pool == nil {
  4849  			c.ctxt.Diag("%v: constant is not in pool", p)
  4850  		}
  4851  		if rf == REGTMP || p.From.Reg == REGTMP {
  4852  			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  4853  		}
  4854  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  4855  		o2 = c.opxrrr(p, AADD, REGTMP, rf, REGTMP, false)
  4856  		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
  4857  
  4858  	case 76:
  4859  		//	add $O, R, Rtmp or sub $O, R, Rtmp
  4860  		//	stp (R1, R2), (Rtmp)
  4861  		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
  4862  		if rf1 == REGTMP || rf2 == REGTMP {
  4863  			c.ctxt.Diag("cannot use REGTMP as source: %v", p)
  4864  		}
  4865  		if rt == obj.REG_NONE {
  4866  			rt = o.param
  4867  		}
  4868  		if rt == obj.REG_NONE {
  4869  			c.ctxt.Diag("invalid stp destination: %v", p)
  4870  		}
  4871  		v := c.regoff(&p.To)
  4872  		o1 = c.oaddi12(p, v, REGTMP, rt)
  4873  		o2 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
  4874  
  4875  	case 77:
  4876  		// If offset L fits in a 24 bit unsigned immediate:
  4877  		//	add $lo, R, Rtmp
  4878  		//	add $hi, Rtmp, Rtmp
  4879  		//	stp (R1, R2), (Rtmp)
  4880  		// Otherwise, use constant pool:
  4881  		//	mov $L, Rtmp (from constant pool)
  4882  		//	add Rtmp, R, Rtmp
  4883  		//	stp (R1, R2), (Rtmp)
  4884  		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
  4885  		if rt == REGTMP || rf1 == REGTMP || rf2 == REGTMP {
  4886  			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  4887  		}
  4888  		if rt == obj.REG_NONE {
  4889  			rt = o.param
  4890  		}
  4891  		if rt == obj.REG_NONE {
  4892  			c.ctxt.Diag("invalid stp destination: %v", p)
  4893  		}
  4894  
  4895  		v := c.regoff(&p.To)
  4896  		if v >= -4095 && v <= 4095 {
  4897  			c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+stp)", p, v)
  4898  		}
  4899  
  4900  		hi, lo, err := splitImm24uScaled(v, 0)
  4901  		if err != nil {
  4902  			goto storepairusepool
  4903  		}
  4904  		if p.Pool != nil {
  4905  			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
  4906  		}
  4907  		o1 = c.oaddi(p, AADD, lo, REGTMP, rt)
  4908  		o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP)
  4909  		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
  4910  		break
  4911  
  4912  	storepairusepool:
  4913  		if p.Pool == nil {
  4914  			c.ctxt.Diag("%v: constant is not in pool", p)
  4915  		}
  4916  		if rt == REGTMP || p.From.Reg == REGTMP {
  4917  			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  4918  		}
  4919  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  4920  		o2 = c.opxrrr(p, AADD, REGTMP, rt, REGTMP, false)
  4921  		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
  4922  
  4923  	case 78: /* vmov R, V.<T>[index] */
  4924  		rf := int(p.From.Reg)
  4925  		rt := int(p.To.Reg)
  4926  		imm5 := 0
  4927  		o1 = 1<<30 | 7<<25 | 7<<10
  4928  		index := int(p.To.Index)
  4929  		switch (p.To.Reg >> 5) & 15 {
  4930  		case ARNG_B:
  4931  			c.checkindex(p, index, 15)
  4932  			imm5 |= 1
  4933  			imm5 |= index << 1
  4934  		case ARNG_H:
  4935  			c.checkindex(p, index, 7)
  4936  			imm5 |= 2
  4937  			imm5 |= index << 2
  4938  		case ARNG_S:
  4939  			c.checkindex(p, index, 3)
  4940  			imm5 |= 4
  4941  			imm5 |= index << 3
  4942  		case ARNG_D:
  4943  			c.checkindex(p, index, 1)
  4944  			imm5 |= 8
  4945  			imm5 |= index << 4
  4946  		default:
  4947  			c.ctxt.Diag("invalid arrangement: %v", p)
  4948  		}
  4949  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4950  
  4951  	case 79: /* vdup Vn.<T>[index], Vd.<T> */
  4952  		rf := int(p.From.Reg)
  4953  		rt := int(p.To.Reg)
  4954  		o1 = 7<<25 | 1<<10
  4955  		var imm5, Q int
  4956  		index := int(p.From.Index)
  4957  		switch (p.To.Reg >> 5) & 15 {
  4958  		case ARNG_16B:
  4959  			c.checkindex(p, index, 15)
  4960  			Q = 1
  4961  			imm5 = 1
  4962  			imm5 |= index << 1
  4963  		case ARNG_2D:
  4964  			c.checkindex(p, index, 1)
  4965  			Q = 1
  4966  			imm5 = 8
  4967  			imm5 |= index << 4
  4968  		case ARNG_2S:
  4969  			c.checkindex(p, index, 3)
  4970  			Q = 0
  4971  			imm5 = 4
  4972  			imm5 |= index << 3
  4973  		case ARNG_4H:
  4974  			c.checkindex(p, index, 7)
  4975  			Q = 0
  4976  			imm5 = 2
  4977  			imm5 |= index << 2
  4978  		case ARNG_4S:
  4979  			c.checkindex(p, index, 3)
  4980  			Q = 1
  4981  			imm5 = 4
  4982  			imm5 |= index << 3
  4983  		case ARNG_8B:
  4984  			c.checkindex(p, index, 15)
  4985  			Q = 0
  4986  			imm5 = 1
  4987  			imm5 |= index << 1
  4988  		case ARNG_8H:
  4989  			c.checkindex(p, index, 7)
  4990  			Q = 1
  4991  			imm5 = 2
  4992  			imm5 |= index << 2
  4993  		default:
  4994  			c.ctxt.Diag("invalid arrangement: %v", p)
  4995  		}
  4996  		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  4997  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4998  
  4999  	case 80: /* vmov/vdup V.<T>[index], Vn */
  5000  		rf := int(p.From.Reg)
  5001  		rt := int(p.To.Reg)
  5002  		imm5 := 0
  5003  		index := int(p.From.Index)
  5004  		switch p.As {
  5005  		case AVMOV, AVDUP:
  5006  			o1 = 1<<30 | 15<<25 | 1<<10
  5007  			switch (p.From.Reg >> 5) & 15 {
  5008  			case ARNG_B:
  5009  				c.checkindex(p, index, 15)
  5010  				imm5 |= 1
  5011  				imm5 |= index << 1
  5012  			case ARNG_H:
  5013  				c.checkindex(p, index, 7)
  5014  				imm5 |= 2
  5015  				imm5 |= index << 2
  5016  			case ARNG_S:
  5017  				c.checkindex(p, index, 3)
  5018  				imm5 |= 4
  5019  				imm5 |= index << 3
  5020  			case ARNG_D:
  5021  				c.checkindex(p, index, 1)
  5022  				imm5 |= 8
  5023  				imm5 |= index << 4
  5024  			default:
  5025  				c.ctxt.Diag("invalid arrangement: %v", p)
  5026  			}
  5027  		default:
  5028  			c.ctxt.Diag("unsupported op %v", p.As)
  5029  		}
  5030  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  5031  
  5032  	case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
  5033  		c.checkoffset(p, p.As)
  5034  		rn := p.From.Reg
  5035  		o1 = c.oprrr(p, p.As, obj.REG_NONE, rn, obj.REG_NONE)
  5036  		if o.scond == C_XPOST {
  5037  			o1 |= 1 << 23
  5038  			if p.From.Index == 0 {
  5039  				// immediate offset variant
  5040  				o1 |= 0x1f << 16
  5041  			} else {
  5042  				// register offset variant
  5043  				if isRegShiftOrExt(&p.From) {
  5044  					c.ctxt.Diag("invalid extended register op: %v\n", p)
  5045  				}
  5046  				o1 |= uint32(p.From.Index&0x1f) << 16
  5047  			}
  5048  		}
  5049  		o1 |= uint32(p.To.Offset)
  5050  		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  5051  		// add opcode(bit 12-15) for vld1, mask it off if it's not vld1
  5052  		o1 = c.maskOpvldvst(p, o1)
  5053  
  5054  	case 82: /* vmov/vdup Rn, Vd.<T> */
  5055  		rf := int(p.From.Reg)
  5056  		rt := int(p.To.Reg)
  5057  		o1 = 7<<25 | 3<<10
  5058  		var imm5, Q uint32
  5059  		switch (p.To.Reg >> 5) & 15 {
  5060  		case ARNG_16B:
  5061  			Q = 1
  5062  			imm5 = 1
  5063  		case ARNG_2D:
  5064  			Q = 1
  5065  			imm5 = 8
  5066  		case ARNG_2S:
  5067  			Q = 0
  5068  			imm5 = 4
  5069  		case ARNG_4H:
  5070  			Q = 0
  5071  			imm5 = 2
  5072  		case ARNG_4S:
  5073  			Q = 1
  5074  			imm5 = 4
  5075  		case ARNG_8B:
  5076  			Q = 0
  5077  			imm5 = 1
  5078  		case ARNG_8H:
  5079  			Q = 1
  5080  			imm5 = 2
  5081  		default:
  5082  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5083  		}
  5084  		o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
  5085  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  5086  
  5087  	case 83: /* vmov Vn.<T>, Vd.<T> */
  5088  		af := int((p.From.Reg >> 5) & 15)
  5089  		at := int((p.To.Reg >> 5) & 15)
  5090  		if af != at {
  5091  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5092  		}
  5093  
  5094  		var Q, size uint32
  5095  		switch af {
  5096  		case ARNG_8B:
  5097  			Q = 0
  5098  			size = 0
  5099  		case ARNG_16B:
  5100  			Q = 1
  5101  			size = 0
  5102  		case ARNG_4H:
  5103  			Q = 0
  5104  			size = 1
  5105  		case ARNG_8H:
  5106  			Q = 1
  5107  			size = 1
  5108  		case ARNG_2S:
  5109  			Q = 0
  5110  			size = 2
  5111  		case ARNG_4S:
  5112  			Q = 1
  5113  			size = 2
  5114  		default:
  5115  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5116  		}
  5117  
  5118  		if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
  5119  			c.ctxt.Diag("invalid arrangement: %v", p)
  5120  		}
  5121  
  5122  		if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
  5123  			c.ctxt.Diag("invalid arrangement: %v", p)
  5124  		}
  5125  
  5126  		if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
  5127  			c.ctxt.Diag("invalid arrangement: %v", p)
  5128  		}
  5129  
  5130  		if p.As == AVRBIT {
  5131  			size = 1
  5132  		}
  5133  
  5134  		rt, r, rf := p.To.Reg, int16(obj.REG_NONE), p.From.Reg
  5135  		if p.As == AVMOV {
  5136  			r = rf
  5137  		}
  5138  		o1 = c.oprrr(p, p.As, rt, rf, r)
  5139  		o1 |= (Q&1)<<30 | (size&3)<<22
  5140  
  5141  	case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
  5142  		c.checkoffset(p, p.As)
  5143  		r := int(p.To.Reg)
  5144  		o1 = 3 << 26
  5145  		if o.scond == C_XPOST {
  5146  			o1 |= 1 << 23
  5147  			if p.To.Index == 0 {
  5148  				// immediate offset variant
  5149  				o1 |= 0x1f << 16
  5150  			} else {
  5151  				// register offset variant
  5152  				if isRegShiftOrExt(&p.To) {
  5153  					c.ctxt.Diag("invalid extended register: %v\n", p)
  5154  				}
  5155  				o1 |= uint32(p.To.Index&31) << 16
  5156  			}
  5157  		}
  5158  		o1 |= uint32(p.From.Offset)
  5159  		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  5160  		// add opcode(bit 12-15) for vst1, mask it off if it's not vst1
  5161  		o1 = c.maskOpvldvst(p, o1)
  5162  		o1 |= uint32(r&31) << 5
  5163  
  5164  	case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
  5165  		af := int((p.From.Reg >> 5) & 15)
  5166  		Q := 0
  5167  		size := 0
  5168  		switch af {
  5169  		case ARNG_8B:
  5170  			Q = 0
  5171  			size = 0
  5172  		case ARNG_16B:
  5173  			Q = 1
  5174  			size = 0
  5175  		case ARNG_4H:
  5176  			Q = 0
  5177  			size = 1
  5178  		case ARNG_8H:
  5179  			Q = 1
  5180  			size = 1
  5181  		case ARNG_4S:
  5182  			Q = 1
  5183  			size = 2
  5184  		default:
  5185  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5186  		}
  5187  		o1 = c.oprrr(p, p.As, p.To.Reg, p.From.Reg, obj.REG_NONE)
  5188  		o1 |= uint32(Q&1)<<30 | uint32(size&3)<<22
  5189  
  5190  	case 86: /* vmovi $imm8, Vd.<T>*/
  5191  		at := int((p.To.Reg >> 5) & 15)
  5192  		r := int(p.From.Offset)
  5193  		if r > 255 || r < 0 {
  5194  			c.ctxt.Diag("immediate constant out of range: %v\n", p)
  5195  		}
  5196  		rt := int((p.To.Reg) & 31)
  5197  		Q := 0
  5198  		switch at {
  5199  		case ARNG_8B:
  5200  			Q = 0
  5201  		case ARNG_16B:
  5202  			Q = 1
  5203  		default:
  5204  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5205  		}
  5206  		o1 = 0xf<<24 | 0xe<<12 | 1<<10
  5207  		o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
  5208  
  5209  	case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
  5210  		rf1, rf2 := p.From.Reg, int16(p.From.Offset)
  5211  		if rf1 == REGTMP || rf2 == REGTMP {
  5212  			c.ctxt.Diag("cannot use REGTMP as source: %v", p)
  5213  		}
  5214  		o1 = ADR(1, 0, REGTMP)
  5215  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  5216  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  5217  			Type: objabi.R_ADDRARM64,
  5218  			Off:  int32(c.pc),
  5219  			Siz:  8,
  5220  			Sym:  p.To.Sym,
  5221  			Add:  p.To.Offset,
  5222  		})
  5223  		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
  5224  
  5225  	case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
  5226  		rt1, rt2 := p.To.Reg, int16(p.To.Offset)
  5227  		o1 = ADR(1, 0, REGTMP)
  5228  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  5229  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  5230  			Type: objabi.R_ADDRARM64,
  5231  			Off:  int32(c.pc),
  5232  			Siz:  8,
  5233  			Sym:  p.From.Sym,
  5234  			Add:  p.From.Offset,
  5235  		})
  5236  		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
  5237  
  5238  	case 89: /* vadd/vsub Vm, Vn, Vd */
  5239  		switch p.As {
  5240  		case AVADD:
  5241  			o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  5242  
  5243  		case AVSUB:
  5244  			o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  5245  
  5246  		default:
  5247  			c.ctxt.Diag("bad opcode: %v\n", p)
  5248  			break
  5249  		}
  5250  
  5251  		rf := int(p.From.Reg)
  5252  		rt := int(p.To.Reg)
  5253  		r := int(p.Reg)
  5254  		if r == obj.REG_NONE {
  5255  			r = rt
  5256  		}
  5257  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  5258  
  5259  	// This is supposed to be something that stops execution.
  5260  	// It's not supposed to be reached, ever, but if it is, we'd
  5261  	// like to be able to tell how we got there. Assemble as
  5262  	// UDF which is guaranteed to raise the undefined instruction
  5263  	// exception.
  5264  	case 90:
  5265  		o1 = 0x0
  5266  
  5267  	case 91: /* prfm imm(Rn), <prfop | $imm5> */
  5268  		imm := uint32(p.From.Offset)
  5269  		r := p.From.Reg
  5270  		var v uint32
  5271  		var ok bool
  5272  		if p.To.Type == obj.TYPE_CONST {
  5273  			v = uint32(p.To.Offset)
  5274  			ok = v <= 31
  5275  		} else {
  5276  			v, ok = prfopfield[SpecialOperand(p.To.Offset)]
  5277  		}
  5278  		if !ok {
  5279  			c.ctxt.Diag("illegal prefetch operation:\n%v", p)
  5280  		}
  5281  
  5282  		o1 = c.opirr(p, p.As)
  5283  		o1 |= (uint32(r&31) << 5) | ((imm >> 3) & 0xfff << 10) | (v & 31)
  5284  
  5285  	case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
  5286  		rf := int(p.From.Reg)
  5287  		rt := int(p.To.Reg)
  5288  		imm4 := 0
  5289  		imm5 := 0
  5290  		o1 = 3<<29 | 7<<25 | 1<<10
  5291  		index1 := int(p.To.Index)
  5292  		index2 := int(p.From.Index)
  5293  		if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
  5294  			c.ctxt.Diag("operand mismatch: %v", p)
  5295  		}
  5296  		switch (p.To.Reg >> 5) & 15 {
  5297  		case ARNG_B:
  5298  			c.checkindex(p, index1, 15)
  5299  			c.checkindex(p, index2, 15)
  5300  			imm5 |= 1
  5301  			imm5 |= index1 << 1
  5302  			imm4 |= index2
  5303  		case ARNG_H:
  5304  			c.checkindex(p, index1, 7)
  5305  			c.checkindex(p, index2, 7)
  5306  			imm5 |= 2
  5307  			imm5 |= index1 << 2
  5308  			imm4 |= index2 << 1
  5309  		case ARNG_S:
  5310  			c.checkindex(p, index1, 3)
  5311  			c.checkindex(p, index2, 3)
  5312  			imm5 |= 4
  5313  			imm5 |= index1 << 3
  5314  			imm4 |= index2 << 2
  5315  		case ARNG_D:
  5316  			c.checkindex(p, index1, 1)
  5317  			c.checkindex(p, index2, 1)
  5318  			imm5 |= 8
  5319  			imm5 |= index1 << 4
  5320  			imm4 |= index2 << 3
  5321  		default:
  5322  			c.ctxt.Diag("invalid arrangement: %v", p)
  5323  		}
  5324  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  5325  
  5326  	case 93: /* vpmull{2} Vm.<Tb>, Vn.<Tb>, Vd.<Ta> */
  5327  		af := uint8((p.From.Reg >> 5) & 15)
  5328  		at := uint8((p.To.Reg >> 5) & 15)
  5329  		a := uint8((p.Reg >> 5) & 15)
  5330  		if af != a {
  5331  			c.ctxt.Diag("invalid arrangement: %v", p)
  5332  		}
  5333  
  5334  		var Q, size uint32
  5335  		if p.As == AVPMULL2 {
  5336  			Q = 1
  5337  		}
  5338  		switch pack(Q, at, af) {
  5339  		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
  5340  			size = 0
  5341  		case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D):
  5342  			size = 3
  5343  		default:
  5344  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5345  		}
  5346  
  5347  		o1 = c.oprrr(p, p.As, p.To.Reg, p.Reg, p.From.Reg)
  5348  		o1 |= (Q&1)<<30 | (size&3)<<22
  5349  
  5350  	case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  5351  		af := int(((p.GetFrom3().Reg) >> 5) & 15)
  5352  		at := int((p.To.Reg >> 5) & 15)
  5353  		a := int((p.Reg >> 5) & 15)
  5354  		index := int(p.From.Offset)
  5355  
  5356  		if af != a || af != at {
  5357  			c.ctxt.Diag("invalid arrangement: %v", p)
  5358  			break
  5359  		}
  5360  
  5361  		var Q uint32
  5362  		var b int
  5363  		if af == ARNG_8B {
  5364  			Q = 0
  5365  			b = 7
  5366  		} else if af == ARNG_16B {
  5367  			Q = 1
  5368  			b = 15
  5369  		} else {
  5370  			c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
  5371  			break
  5372  		}
  5373  
  5374  		if index < 0 || index > b {
  5375  			c.ctxt.Diag("illegal offset: %v", p)
  5376  		}
  5377  
  5378  		o1 = c.opirr(p, p.As)
  5379  		rf := int((p.GetFrom3().Reg) & 31)
  5380  		rt := int((p.To.Reg) & 31)
  5381  		r := int((p.Reg) & 31)
  5382  
  5383  		o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  5384  
  5385  	case 95: /* vushr/vshl/vsri/vsli/vusra $shift, Vn.<T>, Vd.<T> */
  5386  		at := int((p.To.Reg >> 5) & 15)
  5387  		af := int((p.Reg >> 5) & 15)
  5388  		shift := int(p.From.Offset)
  5389  
  5390  		if af != at {
  5391  			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  5392  		}
  5393  
  5394  		var Q uint32
  5395  		var imax, esize int
  5396  
  5397  		switch af {
  5398  		case ARNG_8B, ARNG_4H, ARNG_2S:
  5399  			Q = 0
  5400  		case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
  5401  			Q = 1
  5402  		default:
  5403  			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  5404  		}
  5405  
  5406  		switch af {
  5407  		case ARNG_8B, ARNG_16B:
  5408  			imax = 15
  5409  			esize = 8
  5410  		case ARNG_4H, ARNG_8H:
  5411  			imax = 31
  5412  			esize = 16
  5413  		case ARNG_2S, ARNG_4S:
  5414  			imax = 63
  5415  			esize = 32
  5416  		case ARNG_2D:
  5417  			imax = 127
  5418  			esize = 64
  5419  		}
  5420  
  5421  		imm := 0
  5422  		switch p.As {
  5423  		case AVUSHR, AVSRI, AVUSRA:
  5424  			imm = esize*2 - shift
  5425  			if imm < esize || imm > imax {
  5426  				c.ctxt.Diag("shift out of range: %v", p)
  5427  			}
  5428  		case AVSHL, AVSLI:
  5429  			imm = esize + shift
  5430  			if imm > imax {
  5431  				c.ctxt.Diag("shift out of range: %v", p)
  5432  			}
  5433  		default:
  5434  			c.ctxt.Diag("invalid instruction %v\n", p)
  5435  		}
  5436  
  5437  		o1 = c.opirr(p, p.As)
  5438  		rt := int((p.To.Reg) & 31)
  5439  		rf := int((p.Reg) & 31)
  5440  
  5441  		o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  5442  
  5443  	case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
  5444  		af := int((p.From.Reg >> 5) & 15)
  5445  		rt := int((p.From.Reg) & 31)
  5446  		rf := int((p.To.Reg) & 31)
  5447  		r := int(p.To.Index & 31)
  5448  		index := int(p.From.Index)
  5449  		offset := c.regoff(&p.To)
  5450  
  5451  		if o.scond == C_XPOST {
  5452  			if (p.To.Index != 0) && (offset != 0) {
  5453  				c.ctxt.Diag("invalid offset: %v", p)
  5454  			}
  5455  			if p.To.Index == 0 && offset == 0 {
  5456  				c.ctxt.Diag("invalid offset: %v", p)
  5457  			}
  5458  		}
  5459  
  5460  		if offset != 0 {
  5461  			r = 31
  5462  		}
  5463  
  5464  		var Q, S, size int
  5465  		var opcode uint32
  5466  		switch af {
  5467  		case ARNG_B:
  5468  			c.checkindex(p, index, 15)
  5469  			if o.scond == C_XPOST && offset != 0 && offset != 1 {
  5470  				c.ctxt.Diag("invalid offset: %v", p)
  5471  			}
  5472  			Q = index >> 3
  5473  			S = (index >> 2) & 1
  5474  			size = index & 3
  5475  			opcode = 0
  5476  		case ARNG_H:
  5477  			c.checkindex(p, index, 7)
  5478  			if o.scond == C_XPOST && offset != 0 && offset != 2 {
  5479  				c.ctxt.Diag("invalid offset: %v", p)
  5480  			}
  5481  			Q = index >> 2
  5482  			S = (index >> 1) & 1
  5483  			size = (index & 1) << 1
  5484  			opcode = 2
  5485  		case ARNG_S:
  5486  			c.checkindex(p, index, 3)
  5487  			if o.scond == C_XPOST && offset != 0 && offset != 4 {
  5488  				c.ctxt.Diag("invalid offset: %v", p)
  5489  			}
  5490  			Q = index >> 1
  5491  			S = index & 1
  5492  			size = 0
  5493  			opcode = 4
  5494  		case ARNG_D:
  5495  			c.checkindex(p, index, 1)
  5496  			if o.scond == C_XPOST && offset != 0 && offset != 8 {
  5497  				c.ctxt.Diag("invalid offset: %v", p)
  5498  			}
  5499  			Q = index
  5500  			S = 0
  5501  			size = 1
  5502  			opcode = 4
  5503  		default:
  5504  			c.ctxt.Diag("invalid arrangement: %v", p)
  5505  		}
  5506  
  5507  		if o.scond == C_XPOST {
  5508  			o1 |= 27 << 23
  5509  		} else {
  5510  			o1 |= 26 << 23
  5511  		}
  5512  
  5513  		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)
  5514  
  5515  	case 97: /* vld1 offset(Rn), vt.<T>[index] */
  5516  		at := int((p.To.Reg >> 5) & 15)
  5517  		rt := int((p.To.Reg) & 31)
  5518  		rf := int((p.From.Reg) & 31)
  5519  		r := int(p.From.Index & 31)
  5520  		index := int(p.To.Index)
  5521  		offset := c.regoff(&p.From)
  5522  
  5523  		if o.scond == C_XPOST {
  5524  			if (p.From.Index != 0) && (offset != 0) {
  5525  				c.ctxt.Diag("invalid offset: %v", p)
  5526  			}
  5527  			if p.From.Index == 0 && offset == 0 {
  5528  				c.ctxt.Diag("invalid offset: %v", p)
  5529  			}
  5530  		}
  5531  
  5532  		if offset != 0 {
  5533  			r = 31
  5534  		}
  5535  
  5536  		Q := 0
  5537  		S := 0
  5538  		size := 0
  5539  		var opcode uint32
  5540  		switch at {
  5541  		case ARNG_B:
  5542  			c.checkindex(p, index, 15)
  5543  			if o.scond == C_XPOST && offset != 0 && offset != 1 {
  5544  				c.ctxt.Diag("invalid offset: %v", p)
  5545  			}
  5546  			Q = index >> 3
  5547  			S = (index >> 2) & 1
  5548  			size = index & 3
  5549  			opcode = 0
  5550  		case ARNG_H:
  5551  			c.checkindex(p, index, 7)
  5552  			if o.scond == C_XPOST && offset != 0 && offset != 2 {
  5553  				c.ctxt.Diag("invalid offset: %v", p)
  5554  			}
  5555  			Q = index >> 2
  5556  			S = (index >> 1) & 1
  5557  			size = (index & 1) << 1
  5558  			opcode = 2
  5559  		case ARNG_S:
  5560  			c.checkindex(p, index, 3)
  5561  			if o.scond == C_XPOST && offset != 0 && offset != 4 {
  5562  				c.ctxt.Diag("invalid offset: %v", p)
  5563  			}
  5564  			Q = index >> 1
  5565  			S = index & 1
  5566  			size = 0
  5567  			opcode = 4
  5568  		case ARNG_D:
  5569  			c.checkindex(p, index, 1)
  5570  			if o.scond == C_XPOST && offset != 0 && offset != 8 {
  5571  				c.ctxt.Diag("invalid offset: %v", p)
  5572  			}
  5573  			Q = index
  5574  			S = 0
  5575  			size = 1
  5576  			opcode = 4
  5577  		default:
  5578  			c.ctxt.Diag("invalid arrangement: %v", p)
  5579  		}
  5580  
  5581  		if o.scond == C_XPOST {
  5582  			o1 |= 110 << 21
  5583  		} else {
  5584  			o1 |= 106 << 21
  5585  		}
  5586  
  5587  		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)
  5588  
  5589  	case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
  5590  		rt, rf := p.To.Reg, p.From.Reg
  5591  		if isRegShiftOrExt(&p.From) {
  5592  			// extended or shifted offset register.
  5593  			c.checkShiftAmount(p, &p.From)
  5594  
  5595  			o1 = c.opldrr(p, p.As, rt, rf, obj.REG_NONE, true)
  5596  			o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
  5597  		} else {
  5598  			// (Rn)(Rm), no extension or shift.
  5599  			o1 = c.opldrr(p, p.As, rt, rf, obj.REG_NONE, false)
  5600  			o1 |= uint32(p.From.Index&31) << 16
  5601  		}
  5602  
  5603  	case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
  5604  		rt, rf := p.To.Reg, p.From.Reg
  5605  		if isRegShiftOrExt(&p.To) {
  5606  			// extended or shifted offset register.
  5607  			c.checkShiftAmount(p, &p.To)
  5608  
  5609  			o1 = c.opstrr(p, p.As, rf, rt, obj.REG_NONE, true)
  5610  			o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
  5611  		} else {
  5612  			// (Rn)(Rm), no extension or shift.
  5613  			o1 = c.opstrr(p, p.As, rf, rt, obj.REG_NONE, false)
  5614  			o1 |= uint32(p.To.Index&31) << 16
  5615  		}
  5616  
  5617  	case 100: /* VTBL/VTBX Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
  5618  		af := int((p.From.Reg >> 5) & 15)
  5619  		at := int((p.To.Reg >> 5) & 15)
  5620  		if af != at {
  5621  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  5622  		}
  5623  		var q, len uint32
  5624  		switch af {
  5625  		case ARNG_8B:
  5626  			q = 0
  5627  		case ARNG_16B:
  5628  			q = 1
  5629  		default:
  5630  			c.ctxt.Diag("invalid arrangement: %v", p)
  5631  		}
  5632  		rf := int(p.From.Reg)
  5633  		rt := int(p.To.Reg)
  5634  		offset := int(p.GetFrom3().Offset)
  5635  		opcode := (offset >> 12) & 15
  5636  		switch opcode {
  5637  		case 0x7:
  5638  			len = 0 // one register
  5639  		case 0xa:
  5640  			len = 1 // two register
  5641  		case 0x6:
  5642  			len = 2 // three registers
  5643  		case 0x2:
  5644  			len = 3 // four registers
  5645  		default:
  5646  			c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  5647  		}
  5648  		var op uint32
  5649  		switch p.As {
  5650  		case AVTBL:
  5651  			op = 0
  5652  		case AVTBX:
  5653  			op = 1
  5654  		}
  5655  		o1 = q<<30 | 0xe<<24 | len<<13 | op<<12
  5656  		o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
  5657  
  5658  	case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
  5659  		o1 = c.opirr(p, p.As)
  5660  		rf := p.Reg
  5661  		af := uint8((p.Reg >> 5) & 15)
  5662  		at := uint8((p.To.Reg >> 5) & 15)
  5663  		shift := int(p.From.Offset)
  5664  		if p.As == AVUXTL || p.As == AVUXTL2 {
  5665  			rf = p.From.Reg
  5666  			af = uint8((p.From.Reg >> 5) & 15)
  5667  			shift = 0
  5668  		}
  5669  
  5670  		Q := (o1 >> 30) & 1
  5671  		var immh, width uint8
  5672  		switch pack(Q, af, at) {
  5673  		case pack(0, ARNG_8B, ARNG_8H):
  5674  			immh, width = 1, 8
  5675  		case pack(1, ARNG_16B, ARNG_8H):
  5676  			immh, width = 1, 8
  5677  		case pack(0, ARNG_4H, ARNG_4S):
  5678  			immh, width = 2, 16
  5679  		case pack(1, ARNG_8H, ARNG_4S):
  5680  			immh, width = 2, 16
  5681  		case pack(0, ARNG_2S, ARNG_2D):
  5682  			immh, width = 4, 32
  5683  		case pack(1, ARNG_4S, ARNG_2D):
  5684  			immh, width = 4, 32
  5685  		default:
  5686  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5687  		}
  5688  		if !(0 <= shift && shift <= int(width-1)) {
  5689  			c.ctxt.Diag("shift amount out of range: %v\n", p)
  5690  		}
  5691  		o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
  5692  
  5693  	case 103: /* VEOR3/VBCAX Va.B16, Vm.B16, Vn.B16, Vd.B16 */
  5694  		ta := (p.From.Reg >> 5) & 15
  5695  		tm := (p.Reg >> 5) & 15
  5696  		td := (p.To.Reg >> 5) & 15
  5697  		tn := ((p.GetFrom3().Reg) >> 5) & 15
  5698  
  5699  		if ta != tm || ta != tn || ta != td || ta != ARNG_16B {
  5700  			c.ctxt.Diag("invalid arrangement: %v", p)
  5701  			break
  5702  		}
  5703  
  5704  		o1 = c.oprrrr(p, p.As, p.To.Reg, p.GetFrom3().Reg, p.Reg, p.From.Reg)
  5705  
  5706  	case 104: /* vxar $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  5707  		af := ((p.GetFrom3().Reg) >> 5) & 15
  5708  		at := (p.To.Reg >> 5) & 15
  5709  		a := (p.Reg >> 5) & 15
  5710  		index := int(p.From.Offset)
  5711  
  5712  		if af != a || af != at {
  5713  			c.ctxt.Diag("invalid arrangement: %v", p)
  5714  			break
  5715  		}
  5716  
  5717  		if af != ARNG_2D {
  5718  			c.ctxt.Diag("invalid arrangement, should be D2: %v", p)
  5719  			break
  5720  		}
  5721  
  5722  		if index < 0 || index > 63 {
  5723  			c.ctxt.Diag("illegal offset: %v", p)
  5724  		}
  5725  
  5726  		o1 = c.opirr(p, p.As)
  5727  		rf := (p.GetFrom3().Reg) & 31
  5728  		rt := (p.To.Reg) & 31
  5729  		r := (p.Reg) & 31
  5730  
  5731  		o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
  5732  
  5733  	case 105: /* vuaddw{2} Vm.<Tb>, Vn.<Ta>, Vd.<Ta> */
  5734  		af := uint8((p.From.Reg >> 5) & 15)
  5735  		at := uint8((p.To.Reg >> 5) & 15)
  5736  		a := uint8((p.Reg >> 5) & 15)
  5737  		if at != a {
  5738  			c.ctxt.Diag("invalid arrangement: %v", p)
  5739  			break
  5740  		}
  5741  
  5742  		var Q, size uint32
  5743  		if p.As == AVUADDW2 {
  5744  			Q = 1
  5745  		}
  5746  		switch pack(Q, at, af) {
  5747  		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
  5748  			size = 0
  5749  		case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H):
  5750  			size = 1
  5751  		case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S):
  5752  			size = 2
  5753  		default:
  5754  			c.ctxt.Diag("operand mismatch: %v\n", p)
  5755  		}
  5756  
  5757  		o1 = c.oprrr(p, p.As, p.To.Reg, p.Reg, p.From.Reg)
  5758  		o1 |= (Q&1)<<30 | (size&3)<<22
  5759  
  5760  	case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1)
  5761  		rs := p.From.Reg
  5762  		rt := p.GetTo2().Reg
  5763  		rb := p.To.Reg
  5764  		rs1 := int16(p.From.Offset)
  5765  		rt1 := int16(p.GetTo2().Offset)
  5766  
  5767  		enc, ok := atomicCASP[p.As]
  5768  		if !ok {
  5769  			c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p)
  5770  		}
  5771  		// for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1
  5772  		switch {
  5773  		case rs&1 != 0:
  5774  			c.ctxt.Diag("source register pair must start from even register: %v\n", p)
  5775  			break
  5776  		case rt&1 != 0:
  5777  			c.ctxt.Diag("destination register pair must start from even register: %v\n", p)
  5778  			break
  5779  		case rs != rs1-1:
  5780  			c.ctxt.Diag("source register pair must be contiguous: %v\n", p)
  5781  			break
  5782  		case rt != rt1-1:
  5783  			c.ctxt.Diag("destination register pair must be contiguous: %v\n", p)
  5784  			break
  5785  		}
  5786  		// rt can't be sp.
  5787  		if rt == REG_RSP {
  5788  			c.ctxt.Diag("illegal destination register: %v\n", p)
  5789  		}
  5790  		o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  5791  
  5792  	case 107: /* tlbi, dc */
  5793  		op, ok := sysInstFields[SpecialOperand(p.From.Offset)]
  5794  		if !ok || (p.As == ATLBI && op.cn != 8) || (p.As == ADC && op.cn != 7) {
  5795  			c.ctxt.Diag("illegal argument: %v\n", p)
  5796  			break
  5797  		}
  5798  		o1 = c.opirr(p, p.As)
  5799  		if op.hasOperand2 {
  5800  			if p.To.Reg == obj.REG_NONE {
  5801  				c.ctxt.Diag("missing register at operand 2: %v\n", p)
  5802  			}
  5803  			o1 |= uint32(p.To.Reg & 0x1F)
  5804  		} else {
  5805  			if p.To.Reg != obj.REG_NONE || p.Reg != obj.REG_NONE {
  5806  				c.ctxt.Diag("extraneous register at operand 2: %v\n", p)
  5807  			}
  5808  			o1 |= uint32(0x1F)
  5809  		}
  5810  		o1 |= uint32(SYSARG4(int(op.op1), int(op.cn), int(op.cm), int(op.op2)))
  5811  
  5812  	case 108: /* bti */
  5813  		o1 = SYSHINT(32)
  5814  		if p.From.Type != obj.TYPE_SPECIAL {
  5815  			c.ctxt.Diag("missing operand: %v\n", p)
  5816  			break
  5817  		}
  5818  		switch SpecialOperand(p.From.Offset) {
  5819  		case SPOP_C:
  5820  			o1 |= 1 << 6
  5821  		case SPOP_J:
  5822  			o1 |= 2 << 6
  5823  		case SPOP_JC:
  5824  			o1 |= 3 << 6
  5825  		default:
  5826  			c.ctxt.Diag("illegal argument: %v\n", p)
  5827  			break
  5828  		}
  5829  	}
  5830  	out[0] = o1
  5831  	out[1] = o2
  5832  	out[2] = o3
  5833  	out[3] = o4
  5834  	out[4] = o5
  5835  
  5836  	return o.size(c.ctxt, p) / 4
  5837  }
  5838  
  5839  func (c *ctxt7) addrRelocType(p *obj.Prog) objabi.RelocType {
  5840  	switch movesize(p.As) {
  5841  	case 0:
  5842  		return objabi.R_ARM64_PCREL_LDST8
  5843  	case 1:
  5844  		return objabi.R_ARM64_PCREL_LDST16
  5845  	case 2:
  5846  		return objabi.R_ARM64_PCREL_LDST32
  5847  	case 3:
  5848  		return objabi.R_ARM64_PCREL_LDST64
  5849  	default:
  5850  		c.ctxt.Diag("use R_ADDRARM64 relocation type for: %v\n", p)
  5851  	}
  5852  	return -1
  5853  }
  5854  
  5855  /*
  5856   * basic Rm op Rn -> Rd (using shifted register with 0)
  5857   * also op Rn -> Rt
  5858   * also Rm*Rn op Ra -> Rd
  5859   * also Vm op Vn -> Vd
  5860   */
  5861  func (c *ctxt7) oprrr(p *obj.Prog, a obj.As, rd, rn, rm int16) uint32 {
  5862  	var op uint32
  5863  
  5864  	switch a {
  5865  	case AADC:
  5866  		op = S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5867  
  5868  	case AADCW:
  5869  		op = S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5870  
  5871  	case AADCS:
  5872  		op = S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5873  
  5874  	case AADCSW:
  5875  		op = S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5876  
  5877  	case ANGC, ASBC:
  5878  		op = S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5879  
  5880  	case ANGCS, ASBCS:
  5881  		op = S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5882  
  5883  	case ANGCW, ASBCW:
  5884  		op = S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  5885  
  5886  	case ANGCSW, ASBCSW:
  5887  		op = S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  5888  
  5889  	case AADD:
  5890  		op = S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5891  
  5892  	case AADDW:
  5893  		op = S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5894  
  5895  	case ACMN, AADDS:
  5896  		op = S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5897  
  5898  	case ACMNW, AADDSW:
  5899  		op = S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5900  
  5901  	case ASUB:
  5902  		op = S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5903  
  5904  	case ASUBW:
  5905  		op = S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5906  
  5907  	case ACMP, ASUBS:
  5908  		op = S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5909  
  5910  	case ACMPW, ASUBSW:
  5911  		op = S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  5912  
  5913  	case AAND:
  5914  		op = S64 | 0<<29 | 0xA<<24
  5915  
  5916  	case AANDW:
  5917  		op = S32 | 0<<29 | 0xA<<24
  5918  
  5919  	case AMOVD, AORR:
  5920  		op = S64 | 1<<29 | 0xA<<24
  5921  
  5922  		//	case AMOVW:
  5923  	case AMOVWU, AORRW:
  5924  		op = S32 | 1<<29 | 0xA<<24
  5925  
  5926  	case AEOR:
  5927  		op = S64 | 2<<29 | 0xA<<24
  5928  
  5929  	case AEORW:
  5930  		op = S32 | 2<<29 | 0xA<<24
  5931  
  5932  	case AANDS, ATST:
  5933  		op = S64 | 3<<29 | 0xA<<24
  5934  
  5935  	case AANDSW, ATSTW:
  5936  		op = S32 | 3<<29 | 0xA<<24
  5937  
  5938  	case ABIC:
  5939  		op = S64 | 0<<29 | 0xA<<24 | 1<<21
  5940  
  5941  	case ABICW:
  5942  		op = S32 | 0<<29 | 0xA<<24 | 1<<21
  5943  
  5944  	case ABICS:
  5945  		op = S64 | 3<<29 | 0xA<<24 | 1<<21
  5946  
  5947  	case ABICSW:
  5948  		op = S32 | 3<<29 | 0xA<<24 | 1<<21
  5949  
  5950  	case AEON:
  5951  		op = S64 | 2<<29 | 0xA<<24 | 1<<21
  5952  
  5953  	case AEONW:
  5954  		op = S32 | 2<<29 | 0xA<<24 | 1<<21
  5955  
  5956  	case AMVN, AORN:
  5957  		op = S64 | 1<<29 | 0xA<<24 | 1<<21
  5958  
  5959  	case AMVNW, AORNW:
  5960  		op = S32 | 1<<29 | 0xA<<24 | 1<<21
  5961  
  5962  	case AASR:
  5963  		op = S64 | OPDP2(10) /* also ASRV */
  5964  
  5965  	case AASRW:
  5966  		op = S32 | OPDP2(10)
  5967  
  5968  	case ALSL:
  5969  		op = S64 | OPDP2(8)
  5970  
  5971  	case ALSLW:
  5972  		op = S32 | OPDP2(8)
  5973  
  5974  	case ALSR:
  5975  		op = S64 | OPDP2(9)
  5976  
  5977  	case ALSRW:
  5978  		op = S32 | OPDP2(9)
  5979  
  5980  	case AROR:
  5981  		op = S64 | OPDP2(11)
  5982  
  5983  	case ARORW:
  5984  		op = S32 | OPDP2(11)
  5985  
  5986  	case ACCMN:
  5987  		op = S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
  5988  
  5989  	case ACCMNW:
  5990  		op = S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5991  
  5992  	case ACCMP:
  5993  		op = S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5994  
  5995  	case ACCMPW:
  5996  		op = S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  5997  
  5998  	case ACRC32B:
  5999  		op = S32 | OPDP2(16)
  6000  
  6001  	case ACRC32H:
  6002  		op = S32 | OPDP2(17)
  6003  
  6004  	case ACRC32W:
  6005  		op = S32 | OPDP2(18)
  6006  
  6007  	case ACRC32X:
  6008  		op = S64 | OPDP2(19)
  6009  
  6010  	case ACRC32CB:
  6011  		op = S32 | OPDP2(20)
  6012  
  6013  	case ACRC32CH:
  6014  		op = S32 | OPDP2(21)
  6015  
  6016  	case ACRC32CW:
  6017  		op = S32 | OPDP2(22)
  6018  
  6019  	case ACRC32CX:
  6020  		op = S64 | OPDP2(23)
  6021  
  6022  	case ACSEL:
  6023  		op = S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6024  
  6025  	case ACSELW:
  6026  		op = S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6027  
  6028  	case ACSET:
  6029  		op = S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6030  
  6031  	case ACSETW:
  6032  		op = S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6033  
  6034  	case ACSETM:
  6035  		op = S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6036  
  6037  	case ACSETMW:
  6038  		op = S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6039  
  6040  	case ACINC, ACSINC:
  6041  		op = S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6042  
  6043  	case ACINCW, ACSINCW:
  6044  		op = S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6045  
  6046  	case ACINV, ACSINV:
  6047  		op = S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6048  
  6049  	case ACINVW, ACSINVW:
  6050  		op = S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  6051  
  6052  	case ACNEG, ACSNEG:
  6053  		op = S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6054  
  6055  	case ACNEGW, ACSNEGW:
  6056  		op = S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  6057  
  6058  	case AMUL, AMADD:
  6059  		op = S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  6060  
  6061  	case AMULW, AMADDW:
  6062  		op = S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  6063  
  6064  	case AMNEG, AMSUB:
  6065  		op = S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  6066  
  6067  	case AMNEGW, AMSUBW:
  6068  		op = S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  6069  
  6070  	case AMRS:
  6071  		op = SYSOP(1, 2, 0, 0, 0, 0, 0)
  6072  
  6073  	case AMSR:
  6074  		op = SYSOP(0, 2, 0, 0, 0, 0, 0)
  6075  
  6076  	case ANEG:
  6077  		op = S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  6078  
  6079  	case ANEGW:
  6080  		op = S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  6081  
  6082  	case ANEGS:
  6083  		op = S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  6084  
  6085  	case ANEGSW:
  6086  		op = S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  6087  
  6088  	case AREM, ASDIV:
  6089  		op = S64 | OPDP2(3)
  6090  
  6091  	case AREMW, ASDIVW:
  6092  		op = S32 | OPDP2(3)
  6093  
  6094  	case ASMULL, ASMADDL:
  6095  		op = OPDP3(1, 0, 1, 0)
  6096  
  6097  	case ASMNEGL, ASMSUBL:
  6098  		op = OPDP3(1, 0, 1, 1)
  6099  
  6100  	case ASMULH:
  6101  		op = OPDP3(1, 0, 2, 0)
  6102  
  6103  	case AUMULL, AUMADDL:
  6104  		op = OPDP3(1, 0, 5, 0)
  6105  
  6106  	case AUMNEGL, AUMSUBL:
  6107  		op = OPDP3(1, 0, 5, 1)
  6108  
  6109  	case AUMULH:
  6110  		op = OPDP3(1, 0, 6, 0)
  6111  
  6112  	case AUREM, AUDIV:
  6113  		op = S64 | OPDP2(2)
  6114  
  6115  	case AUREMW, AUDIVW:
  6116  		op = S32 | OPDP2(2)
  6117  
  6118  	case AAESE:
  6119  		op = 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
  6120  
  6121  	case AAESD:
  6122  		op = 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
  6123  
  6124  	case AAESMC:
  6125  		op = 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
  6126  
  6127  	case AAESIMC:
  6128  		op = 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
  6129  
  6130  	case ASHA1C:
  6131  		op = 0x5E<<24 | 0<<12
  6132  
  6133  	case ASHA1P:
  6134  		op = 0x5E<<24 | 1<<12
  6135  
  6136  	case ASHA1M:
  6137  		op = 0x5E<<24 | 2<<12
  6138  
  6139  	case ASHA1SU0:
  6140  		op = 0x5E<<24 | 3<<12
  6141  
  6142  	case ASHA256H:
  6143  		op = 0x5E<<24 | 4<<12
  6144  
  6145  	case ASHA256H2:
  6146  		op = 0x5E<<24 | 5<<12
  6147  
  6148  	case ASHA256SU1:
  6149  		op = 0x5E<<24 | 6<<12
  6150  
  6151  	case ASHA1H:
  6152  		op = 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
  6153  
  6154  	case ASHA1SU1:
  6155  		op = 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
  6156  
  6157  	case ASHA256SU0:
  6158  		op = 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
  6159  
  6160  	case ASHA512H:
  6161  		op = 0xCE<<24 | 3<<21 | 8<<12
  6162  
  6163  	case ASHA512H2:
  6164  		op = 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
  6165  
  6166  	case ASHA512SU1:
  6167  		op = 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
  6168  
  6169  	case ASHA512SU0:
  6170  		op = 0xCE<<24 | 3<<22 | 8<<12
  6171  
  6172  	case AFCVTZSD:
  6173  		op = FPCVTI(1, 0, 1, 3, 0)
  6174  
  6175  	case AFCVTZSDW:
  6176  		op = FPCVTI(0, 0, 1, 3, 0)
  6177  
  6178  	case AFCVTZSS:
  6179  		op = FPCVTI(1, 0, 0, 3, 0)
  6180  
  6181  	case AFCVTZSSW:
  6182  		op = FPCVTI(0, 0, 0, 3, 0)
  6183  
  6184  	case AFCVTZUD:
  6185  		op = FPCVTI(1, 0, 1, 3, 1)
  6186  
  6187  	case AFCVTZUDW:
  6188  		op = FPCVTI(0, 0, 1, 3, 1)
  6189  
  6190  	case AFCVTZUS:
  6191  		op = FPCVTI(1, 0, 0, 3, 1)
  6192  
  6193  	case AFCVTZUSW:
  6194  		op = FPCVTI(0, 0, 0, 3, 1)
  6195  
  6196  	case ASCVTFD:
  6197  		op = FPCVTI(1, 0, 1, 0, 2)
  6198  
  6199  	case ASCVTFS:
  6200  		op = FPCVTI(1, 0, 0, 0, 2)
  6201  
  6202  	case ASCVTFWD:
  6203  		op = FPCVTI(0, 0, 1, 0, 2)
  6204  
  6205  	case ASCVTFWS:
  6206  		op = FPCVTI(0, 0, 0, 0, 2)
  6207  
  6208  	case AUCVTFD:
  6209  		op = FPCVTI(1, 0, 1, 0, 3)
  6210  
  6211  	case AUCVTFS:
  6212  		op = FPCVTI(1, 0, 0, 0, 3)
  6213  
  6214  	case AUCVTFWD:
  6215  		op = FPCVTI(0, 0, 1, 0, 3)
  6216  
  6217  	case AUCVTFWS:
  6218  		op = FPCVTI(0, 0, 0, 0, 3)
  6219  
  6220  	case AFADDS:
  6221  		op = FPOP2S(0, 0, 0, 2)
  6222  
  6223  	case AFADDD:
  6224  		op = FPOP2S(0, 0, 1, 2)
  6225  
  6226  	case AFSUBS:
  6227  		op = FPOP2S(0, 0, 0, 3)
  6228  
  6229  	case AFSUBD:
  6230  		op = FPOP2S(0, 0, 1, 3)
  6231  
  6232  	case AFMADDD:
  6233  		op = FPOP3S(0, 0, 1, 0, 0)
  6234  
  6235  	case AFMADDS:
  6236  		op = FPOP3S(0, 0, 0, 0, 0)
  6237  
  6238  	case AFMSUBD:
  6239  		op = FPOP3S(0, 0, 1, 0, 1)
  6240  
  6241  	case AFMSUBS:
  6242  		op = FPOP3S(0, 0, 0, 0, 1)
  6243  
  6244  	case AFNMADDD:
  6245  		op = FPOP3S(0, 0, 1, 1, 0)
  6246  
  6247  	case AFNMADDS:
  6248  		op = FPOP3S(0, 0, 0, 1, 0)
  6249  
  6250  	case AFNMSUBD:
  6251  		op = FPOP3S(0, 0, 1, 1, 1)
  6252  
  6253  	case AFNMSUBS:
  6254  		op = FPOP3S(0, 0, 0, 1, 1)
  6255  
  6256  	case AFMULS:
  6257  		op = FPOP2S(0, 0, 0, 0)
  6258  
  6259  	case AFMULD:
  6260  		op = FPOP2S(0, 0, 1, 0)
  6261  
  6262  	case AFDIVS:
  6263  		op = FPOP2S(0, 0, 0, 1)
  6264  
  6265  	case AFDIVD:
  6266  		op = FPOP2S(0, 0, 1, 1)
  6267  
  6268  	case AFMAXS:
  6269  		op = FPOP2S(0, 0, 0, 4)
  6270  
  6271  	case AFMINS:
  6272  		op = FPOP2S(0, 0, 0, 5)
  6273  
  6274  	case AFMAXD:
  6275  		op = FPOP2S(0, 0, 1, 4)
  6276  
  6277  	case AFMIND:
  6278  		op = FPOP2S(0, 0, 1, 5)
  6279  
  6280  	case AFMAXNMS:
  6281  		op = FPOP2S(0, 0, 0, 6)
  6282  
  6283  	case AFMAXNMD:
  6284  		op = FPOP2S(0, 0, 1, 6)
  6285  
  6286  	case AFMINNMS:
  6287  		op = FPOP2S(0, 0, 0, 7)
  6288  
  6289  	case AFMINNMD:
  6290  		op = FPOP2S(0, 0, 1, 7)
  6291  
  6292  	case AFNMULS:
  6293  		op = FPOP2S(0, 0, 0, 8)
  6294  
  6295  	case AFNMULD:
  6296  		op = FPOP2S(0, 0, 1, 8)
  6297  
  6298  	case AFCMPS:
  6299  		op = FPCMP(0, 0, 0, 0, 0)
  6300  
  6301  	case AFCMPD:
  6302  		op = FPCMP(0, 0, 1, 0, 0)
  6303  
  6304  	case AFCMPES:
  6305  		op = FPCMP(0, 0, 0, 0, 16)
  6306  
  6307  	case AFCMPED:
  6308  		op = FPCMP(0, 0, 1, 0, 16)
  6309  
  6310  	case AFCCMPS:
  6311  		op = FPCCMP(0, 0, 0, 0)
  6312  
  6313  	case AFCCMPD:
  6314  		op = FPCCMP(0, 0, 1, 0)
  6315  
  6316  	case AFCCMPES:
  6317  		op = FPCCMP(0, 0, 0, 1)
  6318  
  6319  	case AFCCMPED:
  6320  		op = FPCCMP(0, 0, 1, 1)
  6321  
  6322  	case AFCSELS:
  6323  		op = 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
  6324  
  6325  	case AFCSELD:
  6326  		op = 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
  6327  
  6328  	case AFMOVS:
  6329  		op = FPOP1S(0, 0, 0, 0)
  6330  
  6331  	case AFABSS:
  6332  		op = FPOP1S(0, 0, 0, 1)
  6333  
  6334  	case AFNEGS:
  6335  		op = FPOP1S(0, 0, 0, 2)
  6336  
  6337  	case AFSQRTS:
  6338  		op = FPOP1S(0, 0, 0, 3)
  6339  
  6340  	case AFCVTSD:
  6341  		op = FPOP1S(0, 0, 0, 5)
  6342  
  6343  	case AFCVTSH:
  6344  		op = FPOP1S(0, 0, 0, 7)
  6345  
  6346  	case AFRINTNS:
  6347  		op = FPOP1S(0, 0, 0, 8)
  6348  
  6349  	case AFRINTPS:
  6350  		op = FPOP1S(0, 0, 0, 9)
  6351  
  6352  	case AFRINTMS:
  6353  		op = FPOP1S(0, 0, 0, 10)
  6354  
  6355  	case AFRINTZS:
  6356  		op = FPOP1S(0, 0, 0, 11)
  6357  
  6358  	case AFRINTAS:
  6359  		op = FPOP1S(0, 0, 0, 12)
  6360  
  6361  	case AFRINTXS:
  6362  		op = FPOP1S(0, 0, 0, 14)
  6363  
  6364  	case AFRINTIS:
  6365  		op = FPOP1S(0, 0, 0, 15)
  6366  
  6367  	case AFMOVD:
  6368  		op = FPOP1S(0, 0, 1, 0)
  6369  
  6370  	case AFABSD:
  6371  		op = FPOP1S(0, 0, 1, 1)
  6372  
  6373  	case AFNEGD:
  6374  		op = FPOP1S(0, 0, 1, 2)
  6375  
  6376  	case AFSQRTD:
  6377  		op = FPOP1S(0, 0, 1, 3)
  6378  
  6379  	case AFCVTDS:
  6380  		op = FPOP1S(0, 0, 1, 4)
  6381  
  6382  	case AFCVTDH:
  6383  		op = FPOP1S(0, 0, 1, 7)
  6384  
  6385  	case AFRINTND:
  6386  		op = FPOP1S(0, 0, 1, 8)
  6387  
  6388  	case AFRINTPD:
  6389  		op = FPOP1S(0, 0, 1, 9)
  6390  
  6391  	case AFRINTMD:
  6392  		op = FPOP1S(0, 0, 1, 10)
  6393  
  6394  	case AFRINTZD:
  6395  		op = FPOP1S(0, 0, 1, 11)
  6396  
  6397  	case AFRINTAD:
  6398  		op = FPOP1S(0, 0, 1, 12)
  6399  
  6400  	case AFRINTXD:
  6401  		op = FPOP1S(0, 0, 1, 14)
  6402  
  6403  	case AFRINTID:
  6404  		op = FPOP1S(0, 0, 1, 15)
  6405  
  6406  	case AFCVTHS:
  6407  		op = FPOP1S(0, 0, 3, 4)
  6408  
  6409  	case AFCVTHD:
  6410  		op = FPOP1S(0, 0, 3, 5)
  6411  
  6412  	case AVADD:
  6413  		op = 7<<25 | 1<<21 | 1<<15 | 1<<10
  6414  
  6415  	case AVSUB:
  6416  		op = 0x17<<25 | 1<<21 | 1<<15 | 1<<10
  6417  
  6418  	case AVADDP:
  6419  		op = 7<<25 | 1<<21 | 1<<15 | 15<<10
  6420  
  6421  	case AVAND:
  6422  		op = 7<<25 | 1<<21 | 7<<10
  6423  
  6424  	case AVBCAX:
  6425  		op = 0xCE<<24 | 1<<21
  6426  
  6427  	case AVCMEQ:
  6428  		op = 1<<29 | 0x71<<21 | 0x23<<10
  6429  
  6430  	case AVCNT:
  6431  		op = 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
  6432  
  6433  	case AVZIP1:
  6434  		op = 0xE<<24 | 3<<12 | 2<<10
  6435  
  6436  	case AVZIP2:
  6437  		op = 0xE<<24 | 1<<14 | 3<<12 | 2<<10
  6438  
  6439  	case AVEOR:
  6440  		op = 1<<29 | 0x71<<21 | 7<<10
  6441  
  6442  	case AVEOR3:
  6443  		op = 0xCE << 24
  6444  
  6445  	case AVORR:
  6446  		op = 7<<25 | 5<<21 | 7<<10
  6447  
  6448  	case AVREV16:
  6449  		op = 3<<26 | 2<<24 | 1<<21 | 3<<11
  6450  
  6451  	case AVRAX1:
  6452  		op = 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
  6453  
  6454  	case AVREV32:
  6455  		op = 11<<26 | 2<<24 | 1<<21 | 1<<11
  6456  
  6457  	case AVREV64:
  6458  		op = 3<<26 | 2<<24 | 1<<21 | 1<<11
  6459  
  6460  	case AVMOV:
  6461  		op = 7<<25 | 5<<21 | 7<<10
  6462  
  6463  	case AVADDV:
  6464  		op = 7<<25 | 3<<20 | 3<<15 | 7<<11
  6465  
  6466  	case AVUADDLV:
  6467  		op = 1<<29 | 7<<25 | 3<<20 | 7<<11
  6468  
  6469  	case AVFMLA:
  6470  		op = 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
  6471  
  6472  	case AVFMLS:
  6473  		op = 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
  6474  
  6475  	case AVPMULL, AVPMULL2:
  6476  		op = 0xE<<24 | 1<<21 | 0x38<<10
  6477  
  6478  	case AVRBIT:
  6479  		op = 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
  6480  
  6481  	case AVLD1, AVLD2, AVLD3, AVLD4:
  6482  		op = 3<<26 | 1<<22
  6483  
  6484  	case AVLD1R, AVLD3R:
  6485  		op = 0xD<<24 | 1<<22
  6486  
  6487  	case AVLD2R, AVLD4R:
  6488  		op = 0xD<<24 | 3<<21
  6489  
  6490  	case AVBIF:
  6491  		op = 1<<29 | 7<<25 | 7<<21 | 7<<10
  6492  
  6493  	case AVBIT:
  6494  		op = 1<<29 | 0x75<<21 | 7<<10
  6495  
  6496  	case AVBSL:
  6497  		op = 1<<29 | 0x73<<21 | 7<<10
  6498  
  6499  	case AVCMTST:
  6500  		op = 0xE<<24 | 1<<21 | 0x23<<10
  6501  
  6502  	case AVUMAX:
  6503  		op = 1<<29 | 7<<25 | 1<<21 | 0x19<<10
  6504  
  6505  	case AVUMIN:
  6506  		op = 1<<29 | 7<<25 | 1<<21 | 0x1b<<10
  6507  
  6508  	case AVUZP1:
  6509  		op = 7<<25 | 3<<11
  6510  
  6511  	case AVUZP2:
  6512  		op = 7<<25 | 1<<14 | 3<<11
  6513  
  6514  	case AVUADDW, AVUADDW2:
  6515  		op = 0x17<<25 | 1<<21 | 1<<12
  6516  
  6517  	case AVTRN1:
  6518  		op = 7<<25 | 5<<11
  6519  
  6520  	case AVTRN2:
  6521  		op = 7<<25 | 1<<14 | 5<<11
  6522  
  6523  	default:
  6524  		c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
  6525  		return 0
  6526  	}
  6527  
  6528  	op |= uint32(rm&0x1f)<<16 | uint32(rn&0x1f)<<5 | uint32(rd&0x1f)
  6529  
  6530  	return op
  6531  }
  6532  
  6533  func (c *ctxt7) oprrrr(p *obj.Prog, a obj.As, rd, rn, rm, ra int16) uint32 {
  6534  	return c.oprrr(p, a, rd, rn, rm) | uint32(ra&0x1f)<<10
  6535  }
  6536  
  6537  /*
  6538   * imm -> Rd
  6539   * imm op Rn -> Rd
  6540   */
  6541  func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
  6542  	switch a {
  6543  	/* op $addcon, Rn, Rd */
  6544  	case AMOVD, AADD:
  6545  		return S64 | 0<<30 | 0<<29 | 0x11<<24
  6546  
  6547  	case ACMN, AADDS:
  6548  		return S64 | 0<<30 | 1<<29 | 0x11<<24
  6549  
  6550  	case AMOVW, AADDW:
  6551  		return S32 | 0<<30 | 0<<29 | 0x11<<24
  6552  
  6553  	case ACMNW, AADDSW:
  6554  		return S32 | 0<<30 | 1<<29 | 0x11<<24
  6555  
  6556  	case ASUB:
  6557  		return S64 | 1<<30 | 0<<29 | 0x11<<24
  6558  
  6559  	case ACMP, ASUBS:
  6560  		return S64 | 1<<30 | 1<<29 | 0x11<<24
  6561  
  6562  	case ASUBW:
  6563  		return S32 | 1<<30 | 0<<29 | 0x11<<24
  6564  
  6565  	case ACMPW, ASUBSW:
  6566  		return S32 | 1<<30 | 1<<29 | 0x11<<24
  6567  
  6568  		/* op $imm(SB), Rd; op label, Rd */
  6569  	case AADR:
  6570  		return 0<<31 | 0x10<<24
  6571  
  6572  	case AADRP:
  6573  		return 1<<31 | 0x10<<24
  6574  
  6575  		/* op $bimm, Rn, Rd */
  6576  	case AAND, ABIC:
  6577  		return S64 | 0<<29 | 0x24<<23
  6578  
  6579  	case AANDW, ABICW:
  6580  		return S32 | 0<<29 | 0x24<<23 | 0<<22
  6581  
  6582  	case AORR, AORN:
  6583  		return S64 | 1<<29 | 0x24<<23
  6584  
  6585  	case AORRW, AORNW:
  6586  		return S32 | 1<<29 | 0x24<<23 | 0<<22
  6587  
  6588  	case AEOR, AEON:
  6589  		return S64 | 2<<29 | 0x24<<23
  6590  
  6591  	case AEORW, AEONW:
  6592  		return S32 | 2<<29 | 0x24<<23 | 0<<22
  6593  
  6594  	case AANDS, ABICS, ATST:
  6595  		return S64 | 3<<29 | 0x24<<23
  6596  
  6597  	case AANDSW, ABICSW, ATSTW:
  6598  		return S32 | 3<<29 | 0x24<<23 | 0<<22
  6599  
  6600  	case AASR:
  6601  		return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
  6602  
  6603  	case AASRW:
  6604  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  6605  
  6606  		/* op $width, $lsb, Rn, Rd */
  6607  	case ABFI:
  6608  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  6609  		/* alias of BFM */
  6610  
  6611  	case ABFIW:
  6612  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  6613  
  6614  		/* op $imms, $immr, Rn, Rd */
  6615  	case ABFM:
  6616  		return S64 | 1<<29 | 0x26<<23 | 1<<22
  6617  
  6618  	case ABFMW:
  6619  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  6620  
  6621  	case ASBFM:
  6622  		return S64 | 0<<29 | 0x26<<23 | 1<<22
  6623  
  6624  	case ASBFMW:
  6625  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  6626  
  6627  	case AUBFM:
  6628  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  6629  
  6630  	case AUBFMW:
  6631  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  6632  
  6633  	case ABFXIL:
  6634  		return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
  6635  
  6636  	case ABFXILW:
  6637  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  6638  
  6639  	case AEXTR:
  6640  		return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
  6641  
  6642  	case AEXTRW:
  6643  		return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
  6644  
  6645  	case ACBNZ:
  6646  		return S64 | 0x1A<<25 | 1<<24
  6647  
  6648  	case ACBNZW:
  6649  		return S32 | 0x1A<<25 | 1<<24
  6650  
  6651  	case ACBZ:
  6652  		return S64 | 0x1A<<25 | 0<<24
  6653  
  6654  	case ACBZW:
  6655  		return S32 | 0x1A<<25 | 0<<24
  6656  
  6657  	case ACCMN:
  6658  		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  6659  
  6660  	case ACCMNW:
  6661  		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  6662  
  6663  	case ACCMP:
  6664  		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  6665  
  6666  	case ACCMPW:
  6667  		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  6668  
  6669  	case AMOVK:
  6670  		return S64 | 3<<29 | 0x25<<23
  6671  
  6672  	case AMOVKW:
  6673  		return S32 | 3<<29 | 0x25<<23
  6674  
  6675  	case AMOVN:
  6676  		return S64 | 0<<29 | 0x25<<23
  6677  
  6678  	case AMOVNW:
  6679  		return S32 | 0<<29 | 0x25<<23
  6680  
  6681  	case AMOVZ:
  6682  		return S64 | 2<<29 | 0x25<<23
  6683  
  6684  	case AMOVZW:
  6685  		return S32 | 2<<29 | 0x25<<23
  6686  
  6687  	case AMSR:
  6688  		return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
  6689  
  6690  	case AAT,
  6691  		ADC,
  6692  		AIC,
  6693  		ATLBI,
  6694  		ASYS:
  6695  		return SYSOP(0, 1, 0, 0, 0, 0, 0)
  6696  
  6697  	case ASYSL:
  6698  		return SYSOP(1, 1, 0, 0, 0, 0, 0)
  6699  
  6700  	case ATBZ:
  6701  		return 0x36 << 24
  6702  
  6703  	case ATBNZ:
  6704  		return 0x37 << 24
  6705  
  6706  	case ADSB:
  6707  		return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
  6708  
  6709  	case ADMB:
  6710  		return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
  6711  
  6712  	case AISB:
  6713  		return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
  6714  
  6715  	case AHINT:
  6716  		return SYSHINT(0)
  6717  
  6718  	case AVEXT:
  6719  		return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
  6720  
  6721  	case AVUSHR:
  6722  		return 0x5E<<23 | 1<<10
  6723  
  6724  	case AVSHL:
  6725  		return 0x1E<<23 | 21<<10
  6726  
  6727  	case AVSRI:
  6728  		return 0x5E<<23 | 17<<10
  6729  
  6730  	case AVSLI:
  6731  		return 0x5E<<23 | 21<<10
  6732  
  6733  	case AVUSHLL, AVUXTL:
  6734  		return 1<<29 | 15<<24 | 0x29<<10
  6735  
  6736  	case AVUSHLL2, AVUXTL2:
  6737  		return 3<<29 | 15<<24 | 0x29<<10
  6738  
  6739  	case AVXAR:
  6740  		return 0xCE<<24 | 1<<23
  6741  
  6742  	case AVUSRA:
  6743  		return 1<<29 | 15<<24 | 5<<10
  6744  
  6745  	case APRFM:
  6746  		return 0xf9<<24 | 2<<22
  6747  	}
  6748  
  6749  	c.ctxt.Diag("%v: bad irr %v", p, a)
  6750  	return 0
  6751  }
  6752  
  6753  func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
  6754  	switch a {
  6755  	case ACLS:
  6756  		return S64 | OPBIT(5)
  6757  
  6758  	case ACLSW:
  6759  		return S32 | OPBIT(5)
  6760  
  6761  	case ACLZ:
  6762  		return S64 | OPBIT(4)
  6763  
  6764  	case ACLZW:
  6765  		return S32 | OPBIT(4)
  6766  
  6767  	case ARBIT:
  6768  		return S64 | OPBIT(0)
  6769  
  6770  	case ARBITW:
  6771  		return S32 | OPBIT(0)
  6772  
  6773  	case AREV:
  6774  		return S64 | OPBIT(3)
  6775  
  6776  	case AREVW:
  6777  		return S32 | OPBIT(2)
  6778  
  6779  	case AREV16:
  6780  		return S64 | OPBIT(1)
  6781  
  6782  	case AREV16W:
  6783  		return S32 | OPBIT(1)
  6784  
  6785  	case AREV32:
  6786  		return S64 | OPBIT(2)
  6787  
  6788  	default:
  6789  		c.ctxt.Diag("bad bit op\n%v", p)
  6790  		return 0
  6791  	}
  6792  }
  6793  
  6794  /*
  6795   * add/subtract sign or zero-extended register
  6796   */
  6797  func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, rd, rn, rm int16, extend bool) uint32 {
  6798  	extension := uint32(0)
  6799  	if !extend {
  6800  		if isADDop(a) {
  6801  			extension = LSL0_64
  6802  		}
  6803  		if isADDWop(a) {
  6804  			extension = LSL0_32
  6805  		}
  6806  	}
  6807  
  6808  	var op uint32
  6809  
  6810  	switch a {
  6811  	case AADD:
  6812  		op = S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6813  
  6814  	case AADDW:
  6815  		op = S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6816  
  6817  	case ACMN, AADDS:
  6818  		op = S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6819  
  6820  	case ACMNW, AADDSW:
  6821  		op = S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6822  
  6823  	case ASUB:
  6824  		op = S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6825  
  6826  	case ASUBW:
  6827  		op = S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6828  
  6829  	case ACMP, ASUBS:
  6830  		op = S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6831  
  6832  	case ACMPW, ASUBSW:
  6833  		op = S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  6834  
  6835  	default:
  6836  		c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
  6837  		return 0
  6838  	}
  6839  
  6840  	op |= uint32(rm&0x1f)<<16 | uint32(rn&0x1f)<<5 | uint32(rd&0x1f)
  6841  
  6842  	return op
  6843  }
  6844  
  6845  func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
  6846  	switch a {
  6847  	case ASVC:
  6848  		return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
  6849  
  6850  	case AHVC:
  6851  		return 0xD4<<24 | 0<<21 | 2
  6852  
  6853  	case ASMC:
  6854  		return 0xD4<<24 | 0<<21 | 3
  6855  
  6856  	case ABRK:
  6857  		return 0xD4<<24 | 1<<21 | 0
  6858  
  6859  	case AHLT:
  6860  		return 0xD4<<24 | 2<<21 | 0
  6861  
  6862  	case ADCPS1:
  6863  		return 0xD4<<24 | 5<<21 | 1
  6864  
  6865  	case ADCPS2:
  6866  		return 0xD4<<24 | 5<<21 | 2
  6867  
  6868  	case ADCPS3:
  6869  		return 0xD4<<24 | 5<<21 | 3
  6870  
  6871  	case ACLREX:
  6872  		return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
  6873  	}
  6874  
  6875  	c.ctxt.Diag("%v: bad imm %v", p, a)
  6876  	return 0
  6877  }
  6878  
  6879  func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
  6880  	v := int64(0)
  6881  	t := int64(0)
  6882  	var q *obj.Prog
  6883  	if p.To.Type == obj.TYPE_BRANCH {
  6884  		q = p.To.Target()
  6885  	} else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp
  6886  		q = p.From.Target()
  6887  	}
  6888  	if q == nil {
  6889  		// TODO: don't use brdist for this case, as it isn't a branch.
  6890  		// (Calls from omovlit, and maybe adr/adrp opcodes as well.)
  6891  		q = p.Pool
  6892  	}
  6893  	if q != nil {
  6894  		v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
  6895  		if (v & ((1 << uint(shift)) - 1)) != 0 {
  6896  			c.ctxt.Diag("misaligned label\n%v", p)
  6897  		}
  6898  		v >>= uint(shift)
  6899  		t = int64(1) << uint(flen-1)
  6900  		if v < -t || v >= t {
  6901  			c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
  6902  			panic("branch too far")
  6903  		}
  6904  	}
  6905  
  6906  	return v & ((t << 1) - 1)
  6907  }
  6908  
  6909  /*
  6910   * pc-relative branches
  6911   */
  6912  func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
  6913  	switch a {
  6914  	case ABEQ:
  6915  		return OPBcc(0x0)
  6916  
  6917  	case ABNE:
  6918  		return OPBcc(0x1)
  6919  
  6920  	case ABCS:
  6921  		return OPBcc(0x2)
  6922  
  6923  	case ABHS:
  6924  		return OPBcc(0x2)
  6925  
  6926  	case ABCC:
  6927  		return OPBcc(0x3)
  6928  
  6929  	case ABLO:
  6930  		return OPBcc(0x3)
  6931  
  6932  	case ABMI:
  6933  		return OPBcc(0x4)
  6934  
  6935  	case ABPL:
  6936  		return OPBcc(0x5)
  6937  
  6938  	case ABVS:
  6939  		return OPBcc(0x6)
  6940  
  6941  	case ABVC:
  6942  		return OPBcc(0x7)
  6943  
  6944  	case ABHI:
  6945  		return OPBcc(0x8)
  6946  
  6947  	case ABLS:
  6948  		return OPBcc(0x9)
  6949  
  6950  	case ABGE:
  6951  		return OPBcc(0xa)
  6952  
  6953  	case ABLT:
  6954  		return OPBcc(0xb)
  6955  
  6956  	case ABGT:
  6957  		return OPBcc(0xc)
  6958  
  6959  	case ABLE:
  6960  		return OPBcc(0xd) /* imm19<<5 | cond */
  6961  
  6962  	case AB:
  6963  		return 0<<31 | 5<<26 /* imm26 */
  6964  
  6965  	case ABL:
  6966  		return 1<<31 | 5<<26
  6967  	}
  6968  
  6969  	c.ctxt.Diag("%v: bad bra %v", p, a)
  6970  	return 0
  6971  }
  6972  
  6973  func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
  6974  	switch a {
  6975  	case ABL:
  6976  		return OPBLR(1) /* BLR */
  6977  
  6978  	case AB:
  6979  		return OPBLR(0) /* BR */
  6980  
  6981  	case obj.ARET:
  6982  		return OPBLR(2) /* RET */
  6983  	}
  6984  
  6985  	c.ctxt.Diag("%v: bad brr %v", p, a)
  6986  	return 0
  6987  }
  6988  
  6989  func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
  6990  	switch a {
  6991  	case ADRPS:
  6992  		return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
  6993  
  6994  	case AERET:
  6995  		return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
  6996  
  6997  	case ANOOP:
  6998  		return SYSHINT(0)
  6999  
  7000  	case AYIELD:
  7001  		return SYSHINT(1)
  7002  
  7003  	case AWFE:
  7004  		return SYSHINT(2)
  7005  
  7006  	case AWFI:
  7007  		return SYSHINT(3)
  7008  
  7009  	case ASEV:
  7010  		return SYSHINT(4)
  7011  
  7012  	case ASEVL:
  7013  		return SYSHINT(5)
  7014  
  7015  	case APACIASP:
  7016  		return SYSHINT(25)
  7017  
  7018  	case AAUTIASP:
  7019  		return SYSHINT(29)
  7020  
  7021  	case APACIBSP:
  7022  		return SYSHINT(27)
  7023  
  7024  	case AAUTIBSP:
  7025  		return SYSHINT(31)
  7026  
  7027  	case AAUTIA1716:
  7028  		return SYSHINT(12)
  7029  
  7030  	case AAUTIB1716:
  7031  		return SYSHINT(14)
  7032  	}
  7033  
  7034  	c.ctxt.Diag("%v: bad op0 %v", p, a)
  7035  	return 0
  7036  }
  7037  
  7038  /*
  7039   * register offset
  7040   */
  7041  func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
  7042  	switch a {
  7043  	case ALDAR:
  7044  		return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
  7045  
  7046  	case ALDARW:
  7047  		return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
  7048  
  7049  	case ALDARB:
  7050  		return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
  7051  
  7052  	case ALDARH:
  7053  		return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
  7054  
  7055  	case ALDAXP:
  7056  		return LDSTX(3, 0, 1, 1, 1)
  7057  
  7058  	case ALDAXPW:
  7059  		return LDSTX(2, 0, 1, 1, 1)
  7060  
  7061  	case ALDAXR:
  7062  		return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
  7063  
  7064  	case ALDAXRW:
  7065  		return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
  7066  
  7067  	case ALDAXRB:
  7068  		return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
  7069  
  7070  	case ALDAXRH:
  7071  		return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
  7072  
  7073  	case ALDXR:
  7074  		return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
  7075  
  7076  	case ALDXRB:
  7077  		return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
  7078  
  7079  	case ALDXRH:
  7080  		return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
  7081  
  7082  	case ALDXRW:
  7083  		return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
  7084  
  7085  	case ALDXP:
  7086  		return LDSTX(3, 0, 1, 1, 0)
  7087  
  7088  	case ALDXPW:
  7089  		return LDSTX(2, 0, 1, 1, 0)
  7090  	}
  7091  
  7092  	c.ctxt.Diag("bad opload %v\n%v", a, p)
  7093  	return 0
  7094  }
  7095  
  7096  func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
  7097  	switch a {
  7098  	case ASTLR:
  7099  		return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
  7100  
  7101  	case ASTLRB:
  7102  		return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
  7103  
  7104  	case ASTLRH:
  7105  		return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
  7106  
  7107  	case ASTLRW:
  7108  		return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
  7109  
  7110  	case ASTLXP:
  7111  		return LDSTX(3, 0, 0, 1, 1)
  7112  
  7113  	case ASTLXPW:
  7114  		return LDSTX(2, 0, 0, 1, 1)
  7115  
  7116  	case ASTLXR:
  7117  		return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
  7118  
  7119  	case ASTLXRB:
  7120  		return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
  7121  
  7122  	case ASTLXRH:
  7123  		return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
  7124  
  7125  	case ASTLXRW:
  7126  		return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
  7127  
  7128  	case ASTXR:
  7129  		return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
  7130  
  7131  	case ASTXRB:
  7132  		return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
  7133  
  7134  	case ASTXRH:
  7135  		return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
  7136  
  7137  	case ASTXP:
  7138  		return LDSTX(3, 0, 0, 1, 0)
  7139  
  7140  	case ASTXPW:
  7141  		return LDSTX(2, 0, 0, 1, 0)
  7142  
  7143  	case ASTXRW:
  7144  		return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
  7145  	}
  7146  
  7147  	c.ctxt.Diag("bad opstore %v\n%v", a, p)
  7148  	return 0
  7149  }
  7150  
  7151  /*
  7152   * load/store register (scaled 12-bit unsigned immediate) C3.3.13
  7153   *	these produce 64-bit values (when there's an option)
  7154   */
  7155  func (c *ctxt7) olsr12u(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 {
  7156  	if v < 0 || v >= (1<<12) {
  7157  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  7158  	}
  7159  	o |= uint32(v&0xFFF) << 10
  7160  	o |= uint32(rn&31) << 5
  7161  	o |= uint32(rt & 31)
  7162  	o |= 1 << 24
  7163  	return o
  7164  }
  7165  
  7166  /*
  7167   * load/store register (unscaled 9-bit signed immediate) C3.3.12
  7168   */
  7169  func (c *ctxt7) olsr9s(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 {
  7170  	if v < -256 || v > 255 {
  7171  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  7172  	}
  7173  	o |= uint32((v & 0x1FF) << 12)
  7174  	o |= uint32(rn&31) << 5
  7175  	o |= uint32(rt & 31)
  7176  	return o
  7177  }
  7178  
  7179  // store(immediate)
  7180  // scaled 12-bit unsigned immediate offset.
  7181  // unscaled 9-bit signed immediate offset.
  7182  // pre/post-indexed store.
  7183  // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
  7184  func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 {
  7185  	enc := c.opldr(p, a)
  7186  	switch p.As {
  7187  	case AFMOVQ:
  7188  		enc = enc &^ (1 << 22)
  7189  	default:
  7190  		enc = LD2STR(enc)
  7191  	}
  7192  	return enc
  7193  }
  7194  
  7195  // load(immediate)
  7196  // scaled 12-bit unsigned immediate offset.
  7197  // unscaled 9-bit signed immediate offset.
  7198  // pre/post-indexed load.
  7199  // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
  7200  func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 {
  7201  	switch a {
  7202  	case AMOVD:
  7203  		return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
  7204  
  7205  	case AMOVW:
  7206  		return LDSTR(2, 0, 2)
  7207  
  7208  	case AMOVWU:
  7209  		return LDSTR(2, 0, 1)
  7210  
  7211  	case AMOVH:
  7212  		return LDSTR(1, 0, 2)
  7213  
  7214  	case AMOVHU:
  7215  		return LDSTR(1, 0, 1)
  7216  
  7217  	case AMOVB:
  7218  		return LDSTR(0, 0, 2)
  7219  
  7220  	case AMOVBU:
  7221  		return LDSTR(0, 0, 1)
  7222  
  7223  	case AFMOVS, AVMOVS:
  7224  		return LDSTR(2, 1, 1)
  7225  
  7226  	case AFMOVD, AVMOVD:
  7227  		return LDSTR(3, 1, 1)
  7228  
  7229  	case AFMOVQ, AVMOVQ:
  7230  		return LDSTR(0, 1, 3)
  7231  	}
  7232  
  7233  	c.ctxt.Diag("bad opldr %v\n%v", a, p)
  7234  	return 0
  7235  }
  7236  
  7237  // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  7238  // for load instruction with register offset.
  7239  // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  7240  func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, rt, rn, rm int16, extension bool) uint32 {
  7241  	var op uint32
  7242  
  7243  	OptionS := uint32(0x1a)
  7244  	if extension {
  7245  		OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
  7246  	}
  7247  	switch a {
  7248  	case AMOVD:
  7249  		op = OptionS<<10 | 0x3<<21 | 0x1f<<27
  7250  	case AMOVW:
  7251  		op = OptionS<<10 | 0x5<<21 | 0x17<<27
  7252  	case AMOVWU:
  7253  		op = OptionS<<10 | 0x3<<21 | 0x17<<27
  7254  	case AMOVH:
  7255  		op = OptionS<<10 | 0x5<<21 | 0x0f<<27
  7256  	case AMOVHU:
  7257  		op = OptionS<<10 | 0x3<<21 | 0x0f<<27
  7258  	case AMOVB:
  7259  		op = OptionS<<10 | 0x5<<21 | 0x07<<27
  7260  	case AMOVBU:
  7261  		op = OptionS<<10 | 0x3<<21 | 0x07<<27
  7262  	case AFMOVS:
  7263  		op = OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
  7264  	case AFMOVD:
  7265  		op = OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
  7266  	case AFMOVQ:
  7267  		op = OptionS<<10 | 0x7<<21 | 0x07<<27 | 1<<26
  7268  	default:
  7269  		c.ctxt.Diag("bad opldrr %v\n%v", a, p)
  7270  		return 0
  7271  	}
  7272  	op |= uint32(rm&31)<<16 | uint32(rn&31)<<5 | uint32(rt&31)
  7273  
  7274  	return op
  7275  }
  7276  
  7277  // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  7278  // for store instruction with register offset.
  7279  // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  7280  func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, rt, rn, rm int16, extension bool) uint32 {
  7281  	var op uint32
  7282  
  7283  	OptionS := uint32(0x1a)
  7284  	if extension {
  7285  		OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
  7286  	}
  7287  	switch a {
  7288  	case AMOVD:
  7289  		op = OptionS<<10 | 0x1<<21 | 0x1f<<27
  7290  	case AMOVW, AMOVWU:
  7291  		op = OptionS<<10 | 0x1<<21 | 0x17<<27
  7292  	case AMOVH, AMOVHU:
  7293  		op = OptionS<<10 | 0x1<<21 | 0x0f<<27
  7294  	case AMOVB, AMOVBU:
  7295  		op = OptionS<<10 | 0x1<<21 | 0x07<<27
  7296  	case AFMOVS:
  7297  		op = OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
  7298  	case AFMOVD:
  7299  		op = OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
  7300  	case AFMOVQ:
  7301  		op = OptionS<<10 | 0x5<<21 | 0x07<<27 | 1<<26
  7302  	default:
  7303  		c.ctxt.Diag("bad opstrr %v\n%v", a, p)
  7304  		return 0
  7305  	}
  7306  	op |= uint32(rm&31)<<16 | uint32(rn&31)<<5 | uint32(rt&31)
  7307  
  7308  	return op
  7309  }
  7310  
  7311  func (c *ctxt7) oaddi(p *obj.Prog, a obj.As, v int32, rd, rn int16) uint32 {
  7312  	op := c.opirr(p, a)
  7313  
  7314  	if (v & 0xFFF000) != 0 {
  7315  		if v&0xFFF != 0 {
  7316  			c.ctxt.Diag("%v misuses oaddi", p)
  7317  		}
  7318  		v >>= 12
  7319  		op |= 1 << 22
  7320  	}
  7321  
  7322  	op |= (uint32(v&0xFFF) << 10) | (uint32(rn&31) << 5) | uint32(rd&31)
  7323  
  7324  	return op
  7325  }
  7326  
  7327  func (c *ctxt7) oaddi12(p *obj.Prog, v int32, rd, rn int16) uint32 {
  7328  	if v < -4095 || v > 4095 {
  7329  		c.ctxt.Diag("%v is not a 12 bit immediate: %v", v, p)
  7330  		return 0
  7331  	}
  7332  	a := AADD
  7333  	if v < 0 {
  7334  		a = ASUB
  7335  		v = -v
  7336  	}
  7337  	return c.oaddi(p, a, v, rd, rn)
  7338  }
  7339  
  7340  /*
  7341   * load a literal value into dr
  7342   */
  7343  func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
  7344  	var o1 int32
  7345  	if p.Pool == nil { /* not in literal pool */
  7346  		c.aclass(a)
  7347  		c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
  7348  
  7349  		/* TODO: could be clever, and use general constant builder */
  7350  		o1 = int32(c.opirr(p, AADD))
  7351  
  7352  		v := int32(c.instoffset)
  7353  		if v != 0 && (v&0xFFF) == 0 {
  7354  			v >>= 12
  7355  			o1 |= 1 << 22 /* shift, by 12 */
  7356  		}
  7357  
  7358  		o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
  7359  	} else {
  7360  		fp, w := 0, 0
  7361  		switch as {
  7362  		case AFMOVS, AVMOVS:
  7363  			fp = 1
  7364  			w = 0 /* 32-bit SIMD/FP */
  7365  
  7366  		case AFMOVD, AVMOVD:
  7367  			fp = 1
  7368  			w = 1 /* 64-bit SIMD/FP */
  7369  
  7370  		case AVMOVQ:
  7371  			fp = 1
  7372  			w = 2 /* 128-bit SIMD/FP */
  7373  
  7374  		case AMOVD:
  7375  			if p.Pool.As == ADWORD {
  7376  				w = 1 /* 64-bit */
  7377  			} else if p.Pool.To.Offset < 0 {
  7378  				w = 2 /* 32-bit, sign-extended to 64-bit */
  7379  			} else if p.Pool.To.Offset >= 0 {
  7380  				w = 0 /* 32-bit, zero-extended to 64-bit */
  7381  			} else {
  7382  				c.ctxt.Diag("invalid operand %v in %v", a, p)
  7383  			}
  7384  
  7385  		case AMOVBU, AMOVHU, AMOVWU:
  7386  			w = 0 /* 32-bit, zero-extended to 64-bit */
  7387  
  7388  		case AMOVB, AMOVH, AMOVW:
  7389  			w = 2 /* 32-bit, sign-extended to 64-bit */
  7390  
  7391  		default:
  7392  			c.ctxt.Diag("invalid operation %v in %v", as, p)
  7393  		}
  7394  
  7395  		v := int32(c.brdist(p, 0, 19, 2))
  7396  		o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
  7397  		o1 |= (v & 0x7FFFF) << 5
  7398  		o1 |= int32(dr & 31)
  7399  	}
  7400  
  7401  	return uint32(o1)
  7402  }
  7403  
  7404  // load a constant (MOVCON or BITCON) in a into rt
  7405  func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
  7406  	if cls := int(a.Class); (cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0) && rt != REGZERO {
  7407  		// or $bitcon, REGZERO, rt. rt can't be ZR.
  7408  		mode := 64
  7409  		var as1 obj.As
  7410  		switch as {
  7411  		case AMOVW:
  7412  			as1 = AORRW
  7413  			mode = 32
  7414  		case AMOVD:
  7415  			as1 = AORR
  7416  		}
  7417  		o1 = c.opirr(p, as1)
  7418  		o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  7419  		return o1
  7420  	}
  7421  
  7422  	if as == AMOVW {
  7423  		d := uint32(a.Offset)
  7424  		s := movcon(int64(d))
  7425  		if s < 0 || s >= 32 {
  7426  			d = ^d
  7427  			s = movcon(int64(d))
  7428  			if s < 0 || s >= 32 {
  7429  				c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
  7430  			}
  7431  			o1 = c.opirr(p, AMOVNW)
  7432  		} else {
  7433  			o1 = c.opirr(p, AMOVZW)
  7434  		}
  7435  		o1 |= MOVCONST(int64(d), s>>4, rt)
  7436  	}
  7437  	if as == AMOVD {
  7438  		d := a.Offset
  7439  		s := movcon(d)
  7440  		if s < 0 || s >= 64 {
  7441  			d = ^d
  7442  			s = movcon(d)
  7443  			if s < 0 || s >= 64 {
  7444  				c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
  7445  			}
  7446  			o1 = c.opirr(p, AMOVN)
  7447  		} else {
  7448  			o1 = c.opirr(p, AMOVZ)
  7449  		}
  7450  		o1 |= MOVCONST(d, s>>4, rt)
  7451  	}
  7452  	return o1
  7453  }
  7454  
  7455  // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
  7456  // put the instruction sequence in os and return the number of instructions.
  7457  func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
  7458  	switch as {
  7459  	case AMOVW:
  7460  		d := uint32(a.Offset)
  7461  		// use MOVZW and MOVKW to load a constant to rt
  7462  		os[0] = c.opirr(p, AMOVZW)
  7463  		os[0] |= MOVCONST(int64(d), 0, rt)
  7464  		os[1] = c.opirr(p, AMOVKW)
  7465  		os[1] |= MOVCONST(int64(d), 1, rt)
  7466  		return 2
  7467  
  7468  	case AMOVD:
  7469  		d := a.Offset
  7470  		dn := ^d
  7471  		var immh [4]uint64
  7472  		var i int
  7473  		zeroCount := int(0)
  7474  		negCount := int(0)
  7475  		for i = 0; i < 4; i++ {
  7476  			immh[i] = uint64((d >> uint(i*16)) & 0xffff)
  7477  			if immh[i] == 0 {
  7478  				zeroCount++
  7479  			} else if immh[i] == 0xffff {
  7480  				negCount++
  7481  			}
  7482  		}
  7483  
  7484  		if zeroCount == 4 || negCount == 4 {
  7485  			c.ctxt.Diag("the immediate should be MOVCON: %v", p)
  7486  		}
  7487  		switch {
  7488  		case zeroCount == 3:
  7489  			// one MOVZ
  7490  			for i = 0; i < 4; i++ {
  7491  				if immh[i] != 0 {
  7492  					os[0] = c.opirr(p, AMOVZ)
  7493  					os[0] |= MOVCONST(d, i, rt)
  7494  					break
  7495  				}
  7496  			}
  7497  			return 1
  7498  
  7499  		case negCount == 3:
  7500  			// one MOVN
  7501  			for i = 0; i < 4; i++ {
  7502  				if immh[i] != 0xffff {
  7503  					os[0] = c.opirr(p, AMOVN)
  7504  					os[0] |= MOVCONST(dn, i, rt)
  7505  					break
  7506  				}
  7507  			}
  7508  			return 1
  7509  
  7510  		case zeroCount == 2:
  7511  			// one MOVZ and one MOVK
  7512  			for i = 0; i < 4; i++ {
  7513  				if immh[i] != 0 {
  7514  					os[0] = c.opirr(p, AMOVZ)
  7515  					os[0] |= MOVCONST(d, i, rt)
  7516  					i++
  7517  					break
  7518  				}
  7519  			}
  7520  			for ; i < 4; i++ {
  7521  				if immh[i] != 0 {
  7522  					os[1] = c.opirr(p, AMOVK)
  7523  					os[1] |= MOVCONST(d, i, rt)
  7524  				}
  7525  			}
  7526  			return 2
  7527  
  7528  		case negCount == 2:
  7529  			// one MOVN and one MOVK
  7530  			for i = 0; i < 4; i++ {
  7531  				if immh[i] != 0xffff {
  7532  					os[0] = c.opirr(p, AMOVN)
  7533  					os[0] |= MOVCONST(dn, i, rt)
  7534  					i++
  7535  					break
  7536  				}
  7537  			}
  7538  			for ; i < 4; i++ {
  7539  				if immh[i] != 0xffff {
  7540  					os[1] = c.opirr(p, AMOVK)
  7541  					os[1] |= MOVCONST(d, i, rt)
  7542  				}
  7543  			}
  7544  			return 2
  7545  		}
  7546  
  7547  		// Look for a two instruction pair, a bit pattern encodeable
  7548  		// as a bitcon immediate plus a fixup MOVK instruction.
  7549  		// Constants like this often occur from strength reduction of divides.
  7550  		for i = 0; i < 4; i++ {
  7551  			mask := uint64(0xffff) << (i * 16)
  7552  			for period := 2; period <= 32; period *= 2 { // TODO: handle period==64 somehow?
  7553  				// Copy in bits from outside of the masked region
  7554  				x := uint64(d)&^mask | bits.RotateLeft64(uint64(d), max(period, 16))&mask
  7555  				if isbitcon(x) {
  7556  					// ORR $c1, ZR, rt
  7557  					os[0] = c.opirr(p, AORR)
  7558  					os[0] |= bitconEncode(x, 64) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  7559  					// MOVK $c2<<(i*16), rt
  7560  					os[1] = c.opirr(p, AMOVK)
  7561  					os[1] |= MOVCONST(d, i, rt)
  7562  					return 2
  7563  				}
  7564  			}
  7565  		}
  7566  		// TODO: other fixups, like ADD or SUB?
  7567  		// TODO: 3-instruction variant, instead of the full MOVD+3*MOVK version below?
  7568  
  7569  		switch {
  7570  
  7571  		case zeroCount == 1:
  7572  			// one MOVZ and two MOVKs
  7573  			for i = 0; i < 4; i++ {
  7574  				if immh[i] != 0 {
  7575  					os[0] = c.opirr(p, AMOVZ)
  7576  					os[0] |= MOVCONST(d, i, rt)
  7577  					i++
  7578  					break
  7579  				}
  7580  			}
  7581  
  7582  			for j := 1; i < 4; i++ {
  7583  				if immh[i] != 0 {
  7584  					os[j] = c.opirr(p, AMOVK)
  7585  					os[j] |= MOVCONST(d, i, rt)
  7586  					j++
  7587  				}
  7588  			}
  7589  			return 3
  7590  
  7591  		case negCount == 1:
  7592  			// one MOVN and two MOVKs
  7593  			for i = 0; i < 4; i++ {
  7594  				if immh[i] != 0xffff {
  7595  					os[0] = c.opirr(p, AMOVN)
  7596  					os[0] |= MOVCONST(dn, i, rt)
  7597  					i++
  7598  					break
  7599  				}
  7600  			}
  7601  
  7602  			for j := 1; i < 4; i++ {
  7603  				if immh[i] != 0xffff {
  7604  					os[j] = c.opirr(p, AMOVK)
  7605  					os[j] |= MOVCONST(d, i, rt)
  7606  					j++
  7607  				}
  7608  			}
  7609  			return 3
  7610  
  7611  		default:
  7612  			// one MOVZ and 3 MOVKs
  7613  			os[0] = c.opirr(p, AMOVZ)
  7614  			os[0] |= MOVCONST(d, 0, rt)
  7615  			for i = 1; i < 4; i++ {
  7616  				os[i] = c.opirr(p, AMOVK)
  7617  				os[i] |= MOVCONST(d, i, rt)
  7618  			}
  7619  			return 4
  7620  		}
  7621  	default:
  7622  		return 0
  7623  	}
  7624  }
  7625  
  7626  func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r, s int64, rf, rt int16) uint32 {
  7627  	var b uint32
  7628  	o := c.opirr(p, a)
  7629  	if (o & (1 << 31)) == 0 {
  7630  		b = 32
  7631  	} else {
  7632  		b = 64
  7633  	}
  7634  	if r < 0 || uint32(r) >= b {
  7635  		c.ctxt.Diag("illegal bit number\n%v", p)
  7636  	}
  7637  	o |= (uint32(r) & 0x3F) << 16
  7638  	if s < 0 || uint32(s) >= b {
  7639  		c.ctxt.Diag("illegal bit number\n%v", p)
  7640  	}
  7641  	o |= (uint32(s) & 0x3F) << 10
  7642  	o |= (uint32(rf&31) << 5) | uint32(rt&31)
  7643  	return o
  7644  }
  7645  
  7646  func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int64, rn, rm, rt int16) uint32 {
  7647  	var b uint32
  7648  	o := c.opirr(p, a)
  7649  	if (o & (1 << 31)) != 0 {
  7650  		b = 63
  7651  	} else {
  7652  		b = 31
  7653  	}
  7654  	if v < 0 || uint32(v) > b {
  7655  		c.ctxt.Diag("illegal bit number\n%v", p)
  7656  	}
  7657  	o |= uint32(v) << 10
  7658  	o |= uint32(rn&31) << 5
  7659  	o |= uint32(rm&31) << 16
  7660  	o |= uint32(rt & 31)
  7661  	return o
  7662  }
  7663  
  7664  /* generate instruction encoding for ldp and stp series */
  7665  func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh int16, ldp uint32) uint32 {
  7666  	wback := false
  7667  	if o.scond == C_XPOST || o.scond == C_XPRE {
  7668  		wback = true
  7669  	}
  7670  	switch p.As {
  7671  	case ALDP, ALDPW, ALDPSW:
  7672  		c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  7673  	case ASTP, ASTPW:
  7674  		if wback {
  7675  			c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
  7676  		}
  7677  	case AFLDPD, AFLDPQ, AFLDPS:
  7678  		c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  7679  	}
  7680  	var ret uint32
  7681  	// check offset
  7682  	switch p.As {
  7683  	case AFLDPQ, AFSTPQ:
  7684  		if vo < -1024 || vo > 1008 || vo%16 != 0 {
  7685  			c.ctxt.Diag("invalid offset %v\n", p)
  7686  		}
  7687  		vo /= 16
  7688  		ret = 2<<30 | 1<<26
  7689  	case AFLDPD, AFSTPD:
  7690  		if vo < -512 || vo > 504 || vo%8 != 0 {
  7691  			c.ctxt.Diag("invalid offset %v\n", p)
  7692  		}
  7693  		vo /= 8
  7694  		ret = 1<<30 | 1<<26
  7695  	case AFLDPS, AFSTPS:
  7696  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7697  			c.ctxt.Diag("invalid offset %v\n", p)
  7698  		}
  7699  		vo /= 4
  7700  		ret = 1 << 26
  7701  	case ALDP, ASTP:
  7702  		if vo < -512 || vo > 504 || vo%8 != 0 {
  7703  			c.ctxt.Diag("invalid offset %v\n", p)
  7704  		}
  7705  		vo /= 8
  7706  		ret = 2 << 30
  7707  	case ALDPW, ASTPW:
  7708  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7709  			c.ctxt.Diag("invalid offset %v\n", p)
  7710  		}
  7711  		vo /= 4
  7712  		ret = 0
  7713  	case ALDPSW:
  7714  		if vo < -256 || vo > 252 || vo%4 != 0 {
  7715  			c.ctxt.Diag("invalid offset %v\n", p)
  7716  		}
  7717  		vo /= 4
  7718  		ret = 1 << 30
  7719  	default:
  7720  		c.ctxt.Diag("invalid instruction %v\n", p)
  7721  	}
  7722  	// check register pair
  7723  	switch p.As {
  7724  	case AFLDPQ, AFLDPD, AFLDPS, AFSTPQ, AFSTPD, AFSTPS:
  7725  		if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
  7726  			c.ctxt.Diag("invalid register pair %v\n", p)
  7727  		}
  7728  	case ALDP, ALDPW, ALDPSW:
  7729  		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
  7730  			c.ctxt.Diag("invalid register pair %v\n", p)
  7731  		}
  7732  	case ASTP, ASTPW:
  7733  		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
  7734  			c.ctxt.Diag("invalid register pair %v\n", p)
  7735  		}
  7736  	}
  7737  	// other conditional flag bits
  7738  	switch o.scond {
  7739  	case C_XPOST:
  7740  		ret |= 1 << 23
  7741  	case C_XPRE:
  7742  		ret |= 3 << 23
  7743  	default:
  7744  		ret |= 2 << 23
  7745  	}
  7746  	ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | uint32(rh&31)<<10 | uint32(rbase&31)<<5 | uint32(rl&31)
  7747  	return ret
  7748  }
  7749  
  7750  func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
  7751  	if p.As == AVLD1 || p.As == AVST1 {
  7752  		return o1
  7753  	}
  7754  
  7755  	o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
  7756  	switch p.As {
  7757  	case AVLD1R, AVLD2R:
  7758  		o1 |= 0xC << 12
  7759  	case AVLD3R, AVLD4R:
  7760  		o1 |= 0xE << 12
  7761  	case AVLD2, AVST2:
  7762  		o1 |= 8 << 12
  7763  	case AVLD3, AVST3:
  7764  		o1 |= 4 << 12
  7765  	case AVLD4, AVST4:
  7766  	default:
  7767  		c.ctxt.Diag("unsupported instruction:%v\n", p.As)
  7768  	}
  7769  	return o1
  7770  }
  7771  
  7772  /*
  7773   * size in log2(bytes)
  7774   */
  7775  func movesize(a obj.As) int {
  7776  	switch a {
  7777  	case AFMOVQ:
  7778  		return 4
  7779  
  7780  	case AMOVD, AFMOVD:
  7781  		return 3
  7782  
  7783  	case AMOVW, AMOVWU, AFMOVS:
  7784  		return 2
  7785  
  7786  	case AMOVH, AMOVHU:
  7787  		return 1
  7788  
  7789  	case AMOVB, AMOVBU:
  7790  		return 0
  7791  
  7792  	default:
  7793  		return -1
  7794  	}
  7795  }
  7796  
  7797  // rm is the Rm register value, o is the extension, amount is the left shift value.
  7798  func roff(rm int16, o uint32, amount int16) uint32 {
  7799  	return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
  7800  }
  7801  
  7802  // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
  7803  func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 {
  7804  	var num, rm int16
  7805  	num = (r >> 5) & 7
  7806  	rm = r & 31
  7807  	switch {
  7808  	case REG_UXTB <= r && r < REG_UXTH:
  7809  		return roff(rm, 0, num)
  7810  	case REG_UXTH <= r && r < REG_UXTW:
  7811  		return roff(rm, 1, num)
  7812  	case REG_UXTW <= r && r < REG_UXTX:
  7813  		if a.Type == obj.TYPE_MEM {
  7814  			if num == 0 {
  7815  				// According to the arm64 specification, for instructions MOVB, MOVBU and FMOVB,
  7816  				// the extension amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present.
  7817  				// But in Go, we don't distinguish between Rn.UXTW and Rn.UXTW<<0, so we encode it as
  7818  				// that does not present. This makes no difference to the function of the instruction.
  7819  				// This is also true for extensions LSL, SXTW and SXTX.
  7820  				return roff(rm, 2, 2)
  7821  			} else {
  7822  				return roff(rm, 2, 6)
  7823  			}
  7824  		} else {
  7825  			return roff(rm, 2, num)
  7826  		}
  7827  	case REG_UXTX <= r && r < REG_SXTB:
  7828  		return roff(rm, 3, num)
  7829  	case REG_SXTB <= r && r < REG_SXTH:
  7830  		return roff(rm, 4, num)
  7831  	case REG_SXTH <= r && r < REG_SXTW:
  7832  		return roff(rm, 5, num)
  7833  	case REG_SXTW <= r && r < REG_SXTX:
  7834  		if a.Type == obj.TYPE_MEM {
  7835  			if num == 0 {
  7836  				return roff(rm, 6, 2)
  7837  			} else {
  7838  				return roff(rm, 6, 6)
  7839  			}
  7840  		} else {
  7841  			return roff(rm, 6, num)
  7842  		}
  7843  	case REG_SXTX <= r && r < REG_SPECIAL:
  7844  		if a.Type == obj.TYPE_MEM {
  7845  			if num == 0 {
  7846  				return roff(rm, 7, 2)
  7847  			} else {
  7848  				return roff(rm, 7, 6)
  7849  			}
  7850  		} else {
  7851  			return roff(rm, 7, num)
  7852  		}
  7853  	case REG_LSL <= r && r < REG_ARNG:
  7854  		if a.Type == obj.TYPE_MEM { // (R1)(R2<<1)
  7855  			if num == 0 {
  7856  				return roff(rm, 3, 2)
  7857  			} else {
  7858  				return roff(rm, 3, 6)
  7859  			}
  7860  		} else if isADDWop(p.As) {
  7861  			return roff(rm, 2, num)
  7862  		}
  7863  		return roff(rm, 3, num)
  7864  	default:
  7865  		c.ctxt.Diag("unsupported register extension type.")
  7866  	}
  7867  
  7868  	return 0
  7869  }
  7870  
  7871  // pack returns the encoding of the "Q" field and two arrangement specifiers.
  7872  func pack(q uint32, arngA, arngB uint8) uint32 {
  7873  	return q<<16 | uint32(arngA)<<8 | uint32(arngB)
  7874  }
  7875  
  7876  // ARM64RegisterExtension constructs an ARM64 register with extension or arrangement.
  7877  func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
  7878  	Rnum := (reg & 31) + num<<5
  7879  	if isAmount {
  7880  		if num < 0 || num > 7 {
  7881  			return errors.New("index shift amount is out of range")
  7882  		}
  7883  	}
  7884  	if reg <= REG_R31 && reg >= REG_R0 {
  7885  		if !isAmount {
  7886  			return errors.New("invalid register extension")
  7887  		}
  7888  		switch ext {
  7889  		case "UXTB":
  7890  			if a.Type == obj.TYPE_MEM {
  7891  				return errors.New("invalid shift for the register offset addressing mode")
  7892  			}
  7893  			a.Reg = REG_UXTB + Rnum
  7894  		case "UXTH":
  7895  			if a.Type == obj.TYPE_MEM {
  7896  				return errors.New("invalid shift for the register offset addressing mode")
  7897  			}
  7898  			a.Reg = REG_UXTH + Rnum
  7899  		case "UXTW":
  7900  			// effective address of memory is a base register value and an offset register value.
  7901  			if a.Type == obj.TYPE_MEM {
  7902  				a.Index = REG_UXTW + Rnum
  7903  			} else {
  7904  				a.Reg = REG_UXTW + Rnum
  7905  			}
  7906  		case "UXTX":
  7907  			if a.Type == obj.TYPE_MEM {
  7908  				return errors.New("invalid shift for the register offset addressing mode")
  7909  			}
  7910  			a.Reg = REG_UXTX + Rnum
  7911  		case "SXTB":
  7912  			if a.Type == obj.TYPE_MEM {
  7913  				return errors.New("invalid shift for the register offset addressing mode")
  7914  			}
  7915  			a.Reg = REG_SXTB + Rnum
  7916  		case "SXTH":
  7917  			if a.Type == obj.TYPE_MEM {
  7918  				return errors.New("invalid shift for the register offset addressing mode")
  7919  			}
  7920  			a.Reg = REG_SXTH + Rnum
  7921  		case "SXTW":
  7922  			if a.Type == obj.TYPE_MEM {
  7923  				a.Index = REG_SXTW + Rnum
  7924  			} else {
  7925  				a.Reg = REG_SXTW + Rnum
  7926  			}
  7927  		case "SXTX":
  7928  			if a.Type == obj.TYPE_MEM {
  7929  				a.Index = REG_SXTX + Rnum
  7930  			} else {
  7931  				a.Reg = REG_SXTX + Rnum
  7932  			}
  7933  		case "LSL":
  7934  			a.Index = REG_LSL + Rnum
  7935  		default:
  7936  			return errors.New("unsupported general register extension type: " + ext)
  7937  
  7938  		}
  7939  	} else if reg <= REG_V31 && reg >= REG_V0 {
  7940  		switch ext {
  7941  		case "B8":
  7942  			if isIndex {
  7943  				return errors.New("invalid register extension")
  7944  			}
  7945  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8B & 15) << 5)
  7946  		case "B16":
  7947  			if isIndex {
  7948  				return errors.New("invalid register extension")
  7949  			}
  7950  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_16B & 15) << 5)
  7951  		case "H4":
  7952  			if isIndex {
  7953  				return errors.New("invalid register extension")
  7954  			}
  7955  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4H & 15) << 5)
  7956  		case "H8":
  7957  			if isIndex {
  7958  				return errors.New("invalid register extension")
  7959  			}
  7960  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_8H & 15) << 5)
  7961  		case "S2":
  7962  			if isIndex {
  7963  				return errors.New("invalid register extension")
  7964  			}
  7965  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2S & 15) << 5)
  7966  		case "S4":
  7967  			if isIndex {
  7968  				return errors.New("invalid register extension")
  7969  			}
  7970  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_4S & 15) << 5)
  7971  		case "D1":
  7972  			if isIndex {
  7973  				return errors.New("invalid register extension")
  7974  			}
  7975  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1D & 15) << 5)
  7976  		case "D2":
  7977  			if isIndex {
  7978  				return errors.New("invalid register extension")
  7979  			}
  7980  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_2D & 15) << 5)
  7981  		case "Q1":
  7982  			if isIndex {
  7983  				return errors.New("invalid register extension")
  7984  			}
  7985  			a.Reg = REG_ARNG + (reg & 31) + ((ARNG_1Q & 15) << 5)
  7986  		case "B":
  7987  			if !isIndex {
  7988  				return nil
  7989  			}
  7990  			a.Reg = REG_ELEM + (reg & 31) + ((ARNG_B & 15) << 5)
  7991  			a.Index = num
  7992  		case "H":
  7993  			if !isIndex {
  7994  				return nil
  7995  			}
  7996  			a.Reg = REG_ELEM + (reg & 31) + ((ARNG_H & 15) << 5)
  7997  			a.Index = num
  7998  		case "S":
  7999  			if !isIndex {
  8000  				return nil
  8001  			}
  8002  			a.Reg = REG_ELEM + (reg & 31) + ((ARNG_S & 15) << 5)
  8003  			a.Index = num
  8004  		case "D":
  8005  			if !isIndex {
  8006  				return nil
  8007  			}
  8008  			a.Reg = REG_ELEM + (reg & 31) + ((ARNG_D & 15) << 5)
  8009  			a.Index = num
  8010  		default:
  8011  			return errors.New("unsupported simd register extension type: " + ext)
  8012  		}
  8013  	} else {
  8014  		return errors.New("invalid register and extension combination")
  8015  	}
  8016  	return nil
  8017  }
  8018  

View as plain text