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

View as plain text