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

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

View as plain text