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

View as plain text