github.com/bir3/gocompiler@v0.3.205/src/cmd/internal/obj/arm64/asm7.go (about)

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