...

Source file src/github.com/twitchyliquid64/golang-asm/obj/arm64/asm7.go

Documentation: github.com/twitchyliquid64/golang-asm/obj/arm64

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

View as plain text