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

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

View as plain text