github.com/epfl-dcsl/gotee@v0.0.0-20200909122901-014b35f5e5e9/src/cmd/internal/obj/arm64/asm7.go (about)

     1  // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
     2  // https://code.google.com/p/ken-cc/source/browse/
     3  //
     4  // 	Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
     5  // 	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  // 	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  // 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  // 	Portions Copyright © 2004,2006 Bruce Ellis
     9  // 	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  // 	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  // 	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package arm64
    32  
    33  import (
    34  	"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  	instoffset int64
    53  	pc         int64
    54  	pool       struct {
    55  		start uint32
    56  		size  uint32
    57  	}
    58  }
    59  
    60  const (
    61  	funcAlign = 16
    62  )
    63  
    64  const (
    65  	REGFROM = 1
    66  )
    67  
    68  type Optab struct {
    69  	as    obj.As
    70  	a1    uint8
    71  	a2    uint8
    72  	a3    uint8
    73  	type_ int8
    74  	size  int8
    75  	param int16
    76  	flag  int8
    77  	scond uint16
    78  }
    79  
    80  var oprange [ALAST & obj.AMask][]Optab
    81  
    82  var xcmp [C_NCLASS][C_NCLASS]bool
    83  
    84  const (
    85  	S32     = 0 << 31
    86  	S64     = 1 << 31
    87  	Sbit    = 1 << 29
    88  	LSL0_32 = 2 << 13
    89  	LSL0_64 = 3 << 13
    90  )
    91  
    92  func OPDP2(x uint32) uint32 {
    93  	return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
    94  }
    95  
    96  func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
    97  	return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
    98  }
    99  
   100  func OPBcc(x uint32) uint32 {
   101  	return 0x2A<<25 | 0<<24 | 0<<4 | x&15
   102  }
   103  
   104  func OPBLR(x uint32) uint32 {
   105  	/* x=0, JMP; 1, CALL; 2, RET */
   106  	return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
   107  }
   108  
   109  func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
   110  	return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
   111  }
   112  
   113  func SYSHINT(x uint32) uint32 {
   114  	return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
   115  }
   116  
   117  func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 {
   118  	return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22
   119  }
   120  
   121  func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
   122  	return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
   123  }
   124  
   125  func LD2STR(o uint32) uint32 {
   126  	return o &^ (3 << 22)
   127  }
   128  
   129  func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
   130  	return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
   131  }
   132  
   133  func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
   134  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
   135  }
   136  
   137  func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   138  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
   139  }
   140  
   141  func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   142  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
   143  }
   144  
   145  func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
   146  	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
   147  }
   148  
   149  func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
   150  	return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
   151  }
   152  
   153  func ADR(p uint32, o uint32, rt uint32) uint32 {
   154  	return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
   155  }
   156  
   157  func OPBIT(x uint32) uint32 {
   158  	return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
   159  }
   160  
   161  const (
   162  	LFROM = 1 << 0
   163  	LTO   = 1 << 1
   164  )
   165  
   166  var optab = []Optab{
   167  	/* struct Optab:
   168  	OPCODE, from, prog->reg, to, type,size,param,flag,scond */
   169  	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
   170  
   171  	/* arithmetic operations */
   172  	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   173  	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   174  	{AADC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   175  	{AADC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   176  	{ANEG, C_REG, C_NONE, C_REG, 25, 4, 0, 0, 0},
   177  	{ANEG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
   178  	{ANGC, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
   179  	{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
   180  	{AADD, C_ADDCON, C_RSP, C_RSP, 2, 4, 0, 0, 0},
   181  	{AADD, C_ADDCON, C_NONE, C_RSP, 2, 4, 0, 0, 0},
   182  	{ACMP, C_ADDCON, C_RSP, C_NONE, 2, 4, 0, 0, 0},
   183  	{AADD, C_MOVCON, C_RSP, C_RSP, 62, 8, 0, 0, 0},
   184  	{AADD, C_MOVCON, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   185  	{ACMP, C_MOVCON, C_RSP, C_NONE, 62, 8, 0, 0, 0},
   186  	{AADD, C_BITCON, C_RSP, C_RSP, 62, 8, 0, 0, 0},
   187  	{AADD, C_BITCON, C_NONE, C_RSP, 62, 8, 0, 0, 0},
   188  	{ACMP, C_BITCON, C_RSP, C_NONE, 62, 8, 0, 0, 0},
   189  	{AADD, C_VCON, C_RSP, C_RSP, 13, 8, 0, LFROM, 0},
   190  	{AADD, C_VCON, C_NONE, C_RSP, 13, 8, 0, LFROM, 0},
   191  	{ACMP, C_VCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
   192  	{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   193  	{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   194  	{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   195  	{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
   196  	{ANEG, C_SHIFT, C_NONE, C_REG, 26, 4, 0, 0, 0},
   197  	{AADD, C_REG, C_RSP, C_RSP, 27, 4, 0, 0, 0},
   198  	{AADD, C_REG, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   199  	{ACMP, C_REG, C_RSP, C_NONE, 27, 4, 0, 0, 0},
   200  	{AADD, C_EXTREG, C_RSP, C_RSP, 27, 4, 0, 0, 0},
   201  	{AADD, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   202  	{AMVN, C_EXTREG, C_NONE, C_RSP, 27, 4, 0, 0, 0},
   203  	{ACMP, C_EXTREG, C_RSP, C_NONE, 27, 4, 0, 0, 0},
   204  	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   205  	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   206  
   207  	/* logical operations */
   208  	{AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   209  	{AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   210  	{ABIC, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   211  	{ABIC, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   212  	{AAND, C_MBCON, C_REG, C_REG, 53, 4, 0, 0, 0},
   213  	{AAND, C_MBCON, C_NONE, C_REG, 53, 4, 0, 0, 0},
   214  	{ABIC, C_MBCON, C_REG, C_REG, 53, 4, 0, 0, 0},
   215  	{ABIC, C_MBCON, C_NONE, C_REG, 53, 4, 0, 0, 0},
   216  	{AAND, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0},
   217  	{AAND, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0},
   218  	{ABIC, C_BITCON, C_REG, C_REG, 53, 4, 0, 0, 0},
   219  	{ABIC, C_BITCON, C_NONE, C_REG, 53, 4, 0, 0, 0},
   220  	{AAND, C_MOVCON, C_REG, C_REG, 62, 8, 0, 0, 0},
   221  	{AAND, C_MOVCON, C_NONE, C_REG, 62, 8, 0, 0, 0},
   222  	{ABIC, C_MOVCON, C_REG, C_REG, 62, 8, 0, 0, 0},
   223  	{ABIC, C_MOVCON, C_NONE, C_REG, 62, 8, 0, 0, 0},
   224  	{AAND, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0},
   225  	{AAND, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
   226  	{ABIC, C_VCON, C_REG, C_REG, 28, 8, 0, LFROM, 0},
   227  	{ABIC, C_VCON, C_NONE, C_REG, 28, 8, 0, LFROM, 0},
   228  	{AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   229  	{AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   230  	{ABIC, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
   231  	{ABIC, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
   232  	{AMOVD, C_RSP, C_NONE, C_RSP, 24, 4, 0, 0, 0},
   233  	{AMVN, C_REG, C_NONE, C_REG, 24, 4, 0, 0, 0},
   234  	{AMOVB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0},
   235  	{AMOVBU, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0},
   236  	{AMOVH, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */
   237  	{AMOVW, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */
   238  	/* TODO: MVN C_SHIFT */
   239  
   240  	/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
   241  	{AMOVW, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0},
   242  	{AMOVD, C_MOVCON, C_NONE, C_REG, 32, 4, 0, 0, 0},
   243  
   244  	// TODO: these don't work properly.
   245  	// { AMOVW,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 , 0},
   246  	// { AMOVD,		C_ADDCON,	C_NONE,	C_REG,		2, 4, 0 , 0},
   247  	{AMOVW, C_BITCON, C_NONE, C_REG, 32, 4, 0, 0, 0},
   248  	{AMOVD, C_BITCON, C_NONE, C_REG, 32, 4, 0, 0, 0},
   249  
   250  	{AMOVK, C_VCON, C_NONE, C_REG, 33, 4, 0, 0, 0},
   251  	{AMOVD, C_AACON, C_NONE, C_REG, 4, 4, REGFROM, 0, 0},
   252  	{ASDIV, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
   253  	{ASDIV, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
   254  	{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   255  	{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
   256  	{AB, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   257  	{ABL, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   258  	{ABL, C_REG, C_NONE, C_REG, 6, 4, 0, 0, 0},
   259  	{ABL, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   260  	{obj.ARET, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
   261  	{obj.ARET, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
   262  	{AADRP, C_SBRA, C_NONE, C_REG, 60, 4, 0, 0, 0},
   263  	{AADR, C_SBRA, C_NONE, C_REG, 61, 4, 0, 0, 0},
   264  	{ABFM, C_VCON, C_REG, C_REG, 42, 4, 0, 0, 0},
   265  	{ABFI, C_VCON, C_REG, C_REG, 43, 4, 0, 0, 0},
   266  	{AEXTR, C_VCON, C_REG, C_REG, 44, 4, 0, 0, 0},
   267  	{ASXTB, C_REG, C_NONE, C_REG, 45, 4, 0, 0, 0},
   268  	{ACLS, C_REG, C_NONE, C_REG, 46, 4, 0, 0, 0},
   269  	{ABEQ, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
   270  	{ALSL, C_VCON, C_REG, C_REG, 8, 4, 0, 0, 0},
   271  	{ALSL, C_VCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
   272  	{ALSL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
   273  	{ALSL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
   274  	{ASVC, C_VCON, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   275  	{ASVC, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
   276  	{ADWORD, C_NONE, C_NONE, C_VCON, 11, 8, 0, 0, 0},
   277  	{ADWORD, C_NONE, C_NONE, C_LEXT, 11, 8, 0, 0, 0},
   278  	{ADWORD, C_NONE, C_NONE, C_ADDR, 11, 8, 0, 0, 0},
   279  	{ADWORD, C_NONE, C_NONE, C_LACON, 11, 8, 0, 0, 0},
   280  	{AWORD, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
   281  	{AWORD, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
   282  	{AWORD, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
   283  	{AMOVW, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
   284  	{AMOVW, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
   285  	{AMOVD, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
   286  	{AMOVD, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
   287  	{AMOVB, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   288  	{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   289  	{AMOVH, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   290  	{AMOVW, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   291  	{AMOVD, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   292  	{AMOVB, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
   293  	{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
   294  	{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
   295  	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
   296  	{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
   297  	{AMOVD, C_GOTADDR, C_NONE, C_REG, 71, 8, 0, 0, 0},
   298  	{AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
   299  	{AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
   300  	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
   301  	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
   302  	{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
   303  	{AREM, C_REG, C_REG, C_REG, 16, 8, 0, 0, 0},
   304  	{AREM, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0},
   305  	{ACSEL, C_COND, C_REG, C_REG, 18, 4, 0, 0, 0}, /* from3 optional */
   306  	{ACSET, C_COND, C_NONE, C_REG, 18, 4, 0, 0, 0},
   307  	{ACCMN, C_COND, C_REG, C_VCON, 19, 4, 0, 0, 0}, /* from3 either C_REG or C_VCON */
   308  
   309  	/* scaled 12-bit unsigned displacement store */
   310  	{AMOVB, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   311  	{AMOVB, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   312  	{AMOVBU, C_REG, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
   313  	{AMOVBU, C_REG, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
   314  
   315  	{AMOVH, C_REG, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
   316  	{AMOVH, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   317  	{AMOVH, C_REG, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
   318  
   319  	{AMOVW, C_REG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   320  	{AMOVW, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   321  	{AMOVW, C_REG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   322  
   323  	{AVMOVS, C_VREG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   324  	{AVMOVS, C_VREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   325  	{AVMOVS, C_VREG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   326  
   327  	/* unscaled 9-bit signed displacement store */
   328  	{AMOVB, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   329  	{AMOVB, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   330  	{AMOVBU, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   331  	{AMOVBU, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   332  
   333  	{AMOVH, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   334  	{AMOVH, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   335  	{AMOVW, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   336  	{AMOVW, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   337  
   338  	{AMOVD, C_REG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   339  	{AMOVD, C_REG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   340  	{AMOVD, C_REG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   341  	{AMOVD, C_REG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   342  	{AMOVD, C_REG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   343  
   344  	/* short displacement load */
   345  	{AMOVB, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   346  	{AMOVB, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   347  	{AMOVB, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   348  	{AMOVB, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   349  	{AMOVB, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   350  
   351  	{AMOVBU, C_UAUTO4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   352  	{AMOVBU, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   353  	{AMOVBU, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   354  	{AMOVBU, C_UOREG4K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   355  	{AMOVBU, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   356  
   357  	{AMOVH, C_UAUTO8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   358  	{AMOVH, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   359  	{AMOVH, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   360  	{AMOVH, C_UOREG8K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   361  	{AMOVH, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   362  
   363  	{AMOVW, C_UAUTO16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   364  	{AMOVW, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   365  	{AMOVW, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   366  	{AMOVW, C_UOREG16K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   367  	{AMOVW, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   368  
   369  	{AMOVD, C_UAUTO32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   370  	{AMOVD, C_NSAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   371  	{AMOVD, C_ZOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
   372  	{AMOVD, C_UOREG32K, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   373  	{AMOVD, C_NSOREG, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
   374  
   375  	{AVMOVS, C_UAUTO16K, C_NONE, C_VREG, 21, 4, REGSP, 0, 0},
   376  	{AVMOVS, C_ZOREG, C_NONE, C_VREG, 21, 4, 0, 0, 0},
   377  	{AVMOVS, C_UOREG16K, C_NONE, C_VREG, 21, 4, 0, 0, 0},
   378  
   379  	/* long displacement store */
   380  	{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   381  	{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   382  	{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   383  	{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   384  	{AMOVH, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   385  	{AMOVH, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   386  	{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   387  	{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   388  	{AMOVD, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   389  	{AMOVD, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   390  
   391  	/* long displacement load */
   392  	{AMOVB, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   393  	{AMOVB, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   394  	{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   395  	{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   396  	{AMOVH, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   397  	{AMOVH, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   398  	{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   399  	{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   400  	{AMOVD, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
   401  	{AMOVD, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
   402  
   403  	/* load long effective stack address (load int32 offset and add) */
   404  	{AMOVD, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
   405  
   406  	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
   407  	{AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   408  	{AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   409  	{AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   410  	{AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   411  	{AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
   412  	{AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   413  	{AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
   414  	{AVMOVS, C_LOREG, C_NONE, C_VREG, 22, 4, 0, 0, C_XPOST},
   415  	{AMOVD, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   416  	{AMOVW, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   417  	{AMOVH, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   418  	{AMOVB, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   419  	{AMOVBU, C_LOREG, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
   420  	{AFMOVS, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   421  	{AFMOVD, C_LOREG, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
   422  	{AVMOVS, C_LOREG, C_NONE, C_VREG, 22, 4, 0, 0, C_XPRE},
   423  
   424  	/* pre/post-indexed store (unscaled, signed 9-bit offset) */
   425  	{AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   426  	{AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   427  	{AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   428  	{AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   429  	{AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   430  	{AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   431  	{AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   432  	{AVMOVS, C_VREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
   433  	{AMOVD, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   434  	{AMOVW, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   435  	{AMOVH, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   436  	{AMOVB, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   437  	{AMOVBU, C_REG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   438  	{AFMOVS, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   439  	{AFMOVD, C_FREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   440  	{AVMOVS, C_VREG, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
   441  
   442  	/* pre/post-indexed/signed-offset load/store register pair
   443  	   (unscaled, signed 10-bit quad-aligned and long offset) */
   444  	{ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   445  	{ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   446  	{ALDP, C_NPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   447  	{ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
   448  	{ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
   449  	{ALDP, C_PPAUTO, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
   450  	{ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
   451  	{ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
   452  	{ALDP, C_UAUTO4K, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
   453  	{ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
   454  	{ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
   455  	{ALDP, C_LAUTO, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
   456  	{ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   457  	{ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   458  	{ALDP, C_NPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   459  	{ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
   460  	{ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
   461  	{ALDP, C_PPOREG, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
   462  	{ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
   463  	{ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
   464  	{ALDP, C_UOREG4K, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
   465  	{ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
   466  	{ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
   467  	{ALDP, C_LOREG, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
   468  	{ALDP, C_ADDR, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
   469  
   470  	{ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
   471  	{ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
   472  	{ASTP, C_PAIR, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
   473  	{ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
   474  	{ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
   475  	{ASTP, C_PAIR, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
   476  	{ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
   477  	{ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
   478  	{ASTP, C_PAIR, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
   479  	{ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
   480  	{ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
   481  	{ASTP, C_PAIR, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
   482  	{ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
   483  	{ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
   484  	{ASTP, C_PAIR, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
   485  	{ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
   486  	{ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
   487  	{ASTP, C_PAIR, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
   488  	{ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
   489  	{ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
   490  	{ASTP, C_PAIR, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
   491  	{ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
   492  	{ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
   493  	{ASTP, C_PAIR, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
   494  	{ASTP, C_PAIR, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
   495  
   496  	/* special */
   497  	{AMOVD, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0},
   498  	{AMRS, C_SPR, C_NONE, C_REG, 35, 4, 0, 0, 0},
   499  	{AMOVD, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   500  	{AMSR, C_REG, C_NONE, C_SPR, 36, 4, 0, 0, 0},
   501  	{AMOVD, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   502  	{AMSR, C_VCON, C_NONE, C_SPR, 37, 4, 0, 0, 0},
   503  	{AERET, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
   504  	{AFMOVS, C_FREG, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
   505  	{AFMOVS, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   506  	{AFMOVS, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   507  	{AFMOVS, C_FREG, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
   508  	{AFMOVS, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   509  	{AFMOVD, C_FREG, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
   510  	{AFMOVD, C_FREG, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
   511  	{AFMOVD, C_FREG, C_NONE, C_ZOREG, 20, 4, 0, 0, 0},
   512  	{AFMOVD, C_FREG, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
   513  	{AFMOVD, C_FREG, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
   514  	{AFMOVS, C_UAUTO16K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   515  	{AFMOVS, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   516  	{AFMOVS, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   517  	{AFMOVS, C_UOREG16K, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   518  	{AFMOVS, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   519  	{AFMOVD, C_UAUTO32K, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   520  	{AFMOVD, C_NSAUTO, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
   521  	{AFMOVD, C_ZOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   522  	{AFMOVD, C_UOREG32K, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   523  	{AFMOVD, C_NSOREG, C_NONE, C_FREG, 21, 4, 0, 0, 0},
   524  	{AFMOVS, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   525  	{AFMOVS, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   526  	{AFMOVD, C_FREG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
   527  	{AFMOVD, C_FREG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
   528  	{AFMOVS, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   529  	{AFMOVS, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   530  	{AFMOVD, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
   531  	{AFMOVD, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
   532  	{AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   533  	{AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   534  	{AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
   535  	{AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
   536  	{AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   537  	{AFADDS, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0},
   538  	{AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   539  	{AFADDS, C_FCON, C_FREG, C_FREG, 54, 4, 0, 0, 0},
   540  	{AFMOVS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   541  	{AFMOVS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   542  	{AFMOVD, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   543  	{AFMOVD, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
   544  	{AFCVTZSD, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0},
   545  	{ASCVTFD, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   546  	{AFMOVS, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   547  	{AFMOVS, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0},
   548  	{AFMOVD, C_REG, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   549  	{AFMOVD, C_FREG, C_NONE, C_REG, 29, 4, 0, 0, 0},
   550  	{AFCMPS, C_FREG, C_FREG, C_NONE, 56, 4, 0, 0, 0},
   551  	{AFCMPS, C_FCON, C_FREG, C_NONE, 56, 4, 0, 0, 0},
   552  	{AFCCMPS, C_COND, C_FREG, C_VCON, 57, 4, 0, 0, 0},
   553  	{AFCSELD, C_COND, C_FREG, C_FREG, 18, 4, 0, 0, 0},
   554  	{AFCVTSD, C_FREG, C_NONE, C_FREG, 29, 4, 0, 0, 0},
   555  	{ACLREX, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
   556  	{ACLREX, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
   557  	{ACBZ, C_REG, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
   558  	{ATBZ, C_VCON, C_REG, C_SBRA, 40, 4, 0, 0, 0},
   559  	{ASYS, C_VCON, C_NONE, C_NONE, 50, 4, 0, 0, 0},
   560  	{ASYS, C_VCON, C_REG, C_NONE, 50, 4, 0, 0, 0},
   561  	{ASYSL, C_VCON, C_NONE, C_REG, 50, 4, 0, 0, 0},
   562  	{ADMB, C_VCON, C_NONE, C_NONE, 51, 4, 0, 0, 0},
   563  	{AHINT, C_VCON, C_NONE, C_NONE, 52, 4, 0, 0, 0},
   564  	{ALDAR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0},
   565  	{ALDXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0},
   566  	{ALDAXR, C_ZOREG, C_NONE, C_REG, 58, 4, 0, 0, 0},
   567  	{ALDXP, C_ZOREG, C_REG, C_REG, 58, 4, 0, 0, 0},
   568  	{ASTLR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // to3=C_NONE
   569  	{ASTXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // to3=C_REG
   570  	{ASTLXR, C_REG, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // to3=C_REG
   571  
   572  	//	{ ASTXP,		C_REG, C_NONE,	C_ZOREG,		59, 4, 0 , 0}, // TODO(aram):
   573  
   574  	{AAESD, C_VREG, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
   575  	{AAESD, C_ARNG, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
   576  	{ASHA1C, C_VREG, C_REG, C_VREG, 1, 4, 0, 0, 0},
   577  	{ASHA1C, C_ARNG, C_VREG, C_VREG, 1, 4, 0, 0, 0},
   578  	{ASHA1H, C_VREG, C_NONE, C_VREG, 29, 4, 0, 0, 0},
   579  	{ASHA1SU0, C_ARNG, C_ARNG, C_ARNG, 1, 4, 0, 0, 0},
   580  	{ASHA256H, C_ARNG, C_VREG, C_VREG, 1, 4, 0, 0, 0},
   581  	{AVADDP, C_ARNG, C_ARNG, C_ARNG, 72, 4, 0, 0, 0},
   582  	{AVADD, C_ARNG, C_ARNG, C_ARNG, 72, 4, 0, 0, 0},
   583  	{AVADD, C_VREG, C_VREG, C_VREG, 89, 4, 0, 0, 0},
   584  	{AVADD, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
   585  	{AVLD1, C_ZOREG, C_NONE, C_LIST, 81, 4, 0, 0, 0},
   586  	{AVLD1, C_LOREG, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   587  	{AVLD1, C_ROFF, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
   588  	{AVMOV, C_ELEM, C_NONE, C_REG, 73, 4, 0, 0, 0},
   589  	{AVMOV, C_REG, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
   590  	{AVMOV, C_ARNG, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   591  	{AVMOV, C_REG, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
   592  	{AVMOV, C_ELEM, C_NONE, C_VREG, 80, 4, 0, 0, 0},
   593  	{AVREV32, C_ARNG, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
   594  	{AVST1, C_LIST, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
   595  	{AVST1, C_LIST, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
   596  	{AVST1, C_LIST, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
   597  	{AVDUP, C_ELEM, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
   598  	{AVADDV, C_ARNG, C_NONE, C_VREG, 85, 4, 0, 0, 0},
   599  	{AVMOVI, C_ADDCON, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
   600  
   601  	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
   602  	{obj.APCDATA, C_VCON, C_NONE, C_VCON, 0, 0, 0, 0, 0},
   603  	{obj.AFUNCDATA, C_VCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
   604  	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
   605  	{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   606  	{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
   607  
   608  	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
   609  }
   610  
   611  /*
   612   * valid pstate field values, and value to use in instruction
   613   */
   614  var pstatefield = []struct {
   615  	reg int16
   616  	enc uint32
   617  }{
   618  	{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
   619  	{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
   620  	{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
   621  }
   622  
   623  // the System register values, and value to use in instruction
   624  var systemreg = []struct {
   625  	reg int16
   626  	enc uint32
   627  }{
   628  	{REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5},
   629  }
   630  
   631  func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   632  	p := cursym.Func.Text
   633  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   634  		return
   635  	}
   636  
   637  	if oprange[AAND&obj.AMask] == nil {
   638  		ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
   639  	}
   640  
   641  	c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset&0xffffffff) + 8}
   642  
   643  	bflag := 1
   644  	pc := int64(0)
   645  	p.Pc = pc
   646  	var m int
   647  	var o *Optab
   648  	for p = p.Link; p != nil; p = p.Link {
   649  		if p.As == ADWORD && (pc&7) != 0 {
   650  			pc += 4
   651  		}
   652  		p.Pc = pc
   653  		o = c.oplook(p)
   654  		m = int(o.size)
   655  		if m == 0 {
   656  			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
   657  				c.ctxt.Diag("zero-width instruction\n%v", p)
   658  			}
   659  			continue
   660  		}
   661  
   662  		switch o.flag & (LFROM | LTO) {
   663  		case LFROM:
   664  			c.addpool(p, &p.From)
   665  
   666  		case LTO:
   667  			c.addpool(p, &p.To)
   668  			break
   669  		}
   670  
   671  		if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
   672  			c.checkpool(p, 0)
   673  		}
   674  		pc += int64(m)
   675  		if c.blitrl != nil {
   676  			c.checkpool(p, 1)
   677  		}
   678  	}
   679  
   680  	c.cursym.Size = pc
   681  
   682  	/*
   683  	 * if any procedure is large enough to
   684  	 * generate a large SBRA branch, then
   685  	 * generate extra passes putting branches
   686  	 * around jmps to fix. this is rare.
   687  	 */
   688  	for bflag != 0 {
   689  		bflag = 0
   690  		pc = 0
   691  		for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
   692  			if p.As == ADWORD && (pc&7) != 0 {
   693  				pc += 4
   694  			}
   695  			p.Pc = pc
   696  			o = c.oplook(p)
   697  
   698  			/* very large branches */
   699  			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
   700  				otxt := p.Pcond.Pc - pc
   701  				var toofar bool
   702  				switch o.type_ {
   703  				case 7, 39: // branch instruction encodes 19 bits
   704  					toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
   705  				case 40: // branch instruction encodes 14 bits
   706  					toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
   707  				}
   708  				if toofar {
   709  					q := c.newprog()
   710  					q.Link = p.Link
   711  					p.Link = q
   712  					q.As = AB
   713  					q.To.Type = obj.TYPE_BRANCH
   714  					q.Pcond = p.Pcond
   715  					p.Pcond = q
   716  					q = c.newprog()
   717  					q.Link = p.Link
   718  					p.Link = q
   719  					q.As = AB
   720  					q.To.Type = obj.TYPE_BRANCH
   721  					q.Pcond = q.Link.Link
   722  					bflag = 1
   723  				}
   724  			}
   725  			m = int(o.size)
   726  
   727  			if m == 0 {
   728  				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
   729  					c.ctxt.Diag("zero-width instruction\n%v", p)
   730  				}
   731  				continue
   732  			}
   733  
   734  			pc += int64(m)
   735  		}
   736  	}
   737  
   738  	pc += -pc & (funcAlign - 1)
   739  	c.cursym.Size = pc
   740  
   741  	/*
   742  	 * lay out the code, emitting code and data relocations.
   743  	 */
   744  	c.cursym.Grow(c.cursym.Size)
   745  	bp := c.cursym.P
   746  	psz := int32(0)
   747  	var i int
   748  	var out [6]uint32
   749  	for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
   750  		c.pc = p.Pc
   751  		o = c.oplook(p)
   752  
   753  		// need to align DWORDs on 8-byte boundary. The ISA doesn't
   754  		// require it, but the various 64-bit loads we generate assume it.
   755  		if o.as == ADWORD && psz%8 != 0 {
   756  			bp[3] = 0
   757  			bp[2] = bp[3]
   758  			bp[1] = bp[2]
   759  			bp[0] = bp[1]
   760  			bp = bp[4:]
   761  			psz += 4
   762  		}
   763  
   764  		if int(o.size) > 4*len(out) {
   765  			log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
   766  		}
   767  		c.asmout(p, o, out[:])
   768  		for i = 0; i < int(o.size/4); i++ {
   769  			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
   770  			bp = bp[4:]
   771  			psz += 4
   772  		}
   773  	}
   774  }
   775  
   776  /*
   777   * when the first reference to the literal pool threatens
   778   * to go out of range of a 1Mb PC-relative offset
   779   * drop the pool now, and branch round it.
   780   */
   781  func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
   782  	if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
   783  		c.flushpool(p, skip)
   784  	} else if p.Link == nil {
   785  		c.flushpool(p, 2)
   786  	}
   787  }
   788  
   789  func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
   790  	if c.blitrl != nil {
   791  		if skip != 0 {
   792  			if c.ctxt.Debugvlog && skip == 1 {
   793  				fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
   794  			}
   795  			q := c.newprog()
   796  			q.As = AB
   797  			q.To.Type = obj.TYPE_BRANCH
   798  			q.Pcond = p.Link
   799  			q.Link = c.blitrl
   800  			q.Pos = p.Pos
   801  			c.blitrl = q
   802  		} else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
   803  			return
   804  		}
   805  
   806  		// The line number for constant pool entries doesn't really matter.
   807  		// We set it to the line number of the preceding instruction so that
   808  		// there are no deltas to encode in the pc-line tables.
   809  		for q := c.blitrl; q != nil; q = q.Link {
   810  			q.Pos = p.Pos
   811  		}
   812  
   813  		c.elitrl.Link = p.Link
   814  		p.Link = c.blitrl
   815  
   816  		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
   817  		c.elitrl = nil
   818  		c.pool.size = 0
   819  		c.pool.start = 0
   820  	}
   821  }
   822  
   823  /*
   824   * TODO: hash
   825   */
   826  func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
   827  	cls := c.aclass(a)
   828  	lit := c.instoffset
   829  	t := c.newprog()
   830  	t.As = AWORD
   831  	sz := 4
   832  
   833  	// MOVD foo(SB), R is actually
   834  	//	MOVD addr, REGTMP
   835  	//	MOVD REGTMP, R
   836  	// where addr is the address of the DWORD containing the address of foo.
   837  	if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || int64(lit) != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) {
   838  		// conservative: don't know if we want signed or unsigned extension.
   839  		// in case of ambiguity, store 64-bit
   840  		t.As = ADWORD
   841  		sz = 8
   842  	}
   843  
   844  	switch cls {
   845  	// TODO(aram): remove.
   846  	default:
   847  		if a.Name != obj.NAME_EXTERN {
   848  			fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p)
   849  		}
   850  
   851  		t.To.Offset = a.Offset
   852  		t.To.Sym = a.Sym
   853  		t.To.Type = a.Type
   854  		t.To.Name = a.Name
   855  
   856  	/* This is here because MOV uint12<<12, R is disabled in optab.
   857  	Because of this, we need to load the constant from memory. */
   858  	case C_ADDCON:
   859  		fallthrough
   860  
   861  	case C_PSAUTO,
   862  		C_PSAUTO_8,
   863  		C_PPAUTO,
   864  		C_UAUTO4K_8,
   865  		C_UAUTO4K_4,
   866  		C_UAUTO4K_2,
   867  		C_UAUTO4K,
   868  		C_UAUTO8K_8,
   869  		C_UAUTO8K_4,
   870  		C_UAUTO8K,
   871  		C_UAUTO16K_8,
   872  		C_UAUTO16K,
   873  		C_UAUTO32K,
   874  		C_NSAUTO,
   875  		C_NPAUTO,
   876  		C_LAUTO,
   877  		C_PPOREG,
   878  		C_PSOREG,
   879  		C_PSOREG_8,
   880  		C_UOREG4K_8,
   881  		C_UOREG4K_4,
   882  		C_UOREG4K_2,
   883  		C_UOREG4K,
   884  		C_UOREG8K_8,
   885  		C_UOREG8K_4,
   886  		C_UOREG8K,
   887  		C_UOREG16K_8,
   888  		C_UOREG16K,
   889  		C_UOREG32K,
   890  		C_NSOREG,
   891  		C_NPOREG,
   892  		C_LOREG,
   893  		C_LACON,
   894  		C_LCON,
   895  		C_VCON:
   896  		if a.Name == obj.NAME_EXTERN {
   897  			fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p)
   898  		}
   899  
   900  		t.To.Type = obj.TYPE_CONST
   901  		t.To.Offset = lit
   902  		break
   903  	}
   904  
   905  	for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
   906  		if q.To == t.To {
   907  			p.Pcond = q
   908  			return
   909  		}
   910  	}
   911  
   912  	q := c.newprog()
   913  	*q = *t
   914  	q.Pc = int64(c.pool.size)
   915  	if c.blitrl == nil {
   916  		c.blitrl = q
   917  		c.pool.start = uint32(p.Pc)
   918  	} else {
   919  		c.elitrl.Link = q
   920  	}
   921  	c.elitrl = q
   922  	c.pool.size = -c.pool.size & (funcAlign - 1)
   923  	c.pool.size += uint32(sz)
   924  	p.Pcond = q
   925  }
   926  
   927  func (c *ctxt7) regoff(a *obj.Addr) uint32 {
   928  	c.instoffset = 0
   929  	c.aclass(a)
   930  	return uint32(c.instoffset)
   931  }
   932  
   933  // Maximum PC-relative displacement.
   934  // The actual limit is ±2²⁰, but we are conservative
   935  // to avoid needing to recompute the literal pool flush points
   936  // as span-dependent jumps are enlarged.
   937  const maxPCDisp = 512 * 1024
   938  
   939  // ispcdisp reports whether v is a valid PC-relative displacement.
   940  func ispcdisp(v int32) bool {
   941  	return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
   942  }
   943  
   944  func isaddcon(v int64) bool {
   945  	/* uimm12 or uimm24? */
   946  	if v < 0 {
   947  		return false
   948  	}
   949  	if (v & 0xFFF) == 0 {
   950  		v >>= 12
   951  	}
   952  	return v <= 0xFFF
   953  }
   954  
   955  // isbitcon returns whether a constant can be encoded into a logical instruction.
   956  // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
   957  // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
   958  // special cases: 0 and -1 are not bitcon.
   959  // this function needs to run against virtually all the constants, so it needs to be fast.
   960  // for this reason, bitcon testing and bitcon encoding are separate functions.
   961  func isbitcon(x uint64) bool {
   962  	if x == 1<<64-1 || x == 0 {
   963  		return false
   964  	}
   965  	// determine the period and sign-extend a unit to 64 bits
   966  	switch {
   967  	case x != x>>32|x<<32:
   968  		// period is 64
   969  		// nothing to do
   970  	case x != x>>16|x<<48:
   971  		// period is 32
   972  		x = uint64(int64(int32(x)))
   973  	case x != x>>8|x<<56:
   974  		// period is 16
   975  		x = uint64(int64(int16(x)))
   976  	case x != x>>4|x<<60:
   977  		// period is 8
   978  		x = uint64(int64(int8(x)))
   979  	default:
   980  		// period is 4 or 2, always true
   981  		// 0001, 0010, 0100, 1000 -- 0001 rotate
   982  		// 0011, 0110, 1100, 1001 -- 0011 rotate
   983  		// 0111, 1011, 1101, 1110 -- 0111 rotate
   984  		// 0101, 1010             -- 01   rotate, repeat
   985  		return true
   986  	}
   987  	return sequenceOfOnes(x) || sequenceOfOnes(^x)
   988  }
   989  
   990  // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
   991  func sequenceOfOnes(x uint64) bool {
   992  	y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
   993  	y += x
   994  	return (y-1)&y == 0
   995  }
   996  
   997  // bitconEncode returns the encoding of a bitcon used in logical instructions
   998  // x is known to be a bitcon
   999  // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
  1000  // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
  1001  // it is encoded in logical instructions with 3 bitfields
  1002  // N (1 bit) : R (6 bits) : S (6 bits), where
  1003  // N=1           -- period=64
  1004  // N=0, S=0xxxxx -- period=32
  1005  // N=0, S=10xxxx -- period=16
  1006  // N=0, S=110xxx -- period=8
  1007  // N=0, S=1110xx -- period=4
  1008  // N=0, S=11110x -- period=2
  1009  // R is the shift amount, low bits of S = n-1
  1010  func bitconEncode(x uint64, mode int) uint32 {
  1011  	var period uint32
  1012  	// determine the period and sign-extend a unit to 64 bits
  1013  	switch {
  1014  	case x != x>>32|x<<32:
  1015  		period = 64
  1016  	case x != x>>16|x<<48:
  1017  		period = 32
  1018  		x = uint64(int64(int32(x)))
  1019  	case x != x>>8|x<<56:
  1020  		period = 16
  1021  		x = uint64(int64(int16(x)))
  1022  	case x != x>>4|x<<60:
  1023  		period = 8
  1024  		x = uint64(int64(int8(x)))
  1025  	case x != x>>2|x<<62:
  1026  		period = 4
  1027  		x = uint64(int64(x<<60) >> 60)
  1028  	default:
  1029  		period = 2
  1030  		x = uint64(int64(x<<62) >> 62)
  1031  	}
  1032  	neg := false
  1033  	if int64(x) < 0 {
  1034  		x = ^x
  1035  		neg = true
  1036  	}
  1037  	y := x & -x // lowest set bit of x.
  1038  	s := log2(y)
  1039  	n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
  1040  	if neg {
  1041  		// ^x is a sequence of n ones left shifted by s bits
  1042  		// adjust n, s for x
  1043  		s = n + s
  1044  		n = period - n
  1045  	}
  1046  
  1047  	N := uint32(0)
  1048  	if mode == 64 && period == 64 {
  1049  		N = 1
  1050  	}
  1051  	R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
  1052  	S := (n - 1) | 63&^(period<<1-1)                  // low bits = #ones - 1, high bits encodes period
  1053  	return N<<22 | R<<16 | S<<10
  1054  }
  1055  
  1056  func log2(x uint64) uint32 {
  1057  	if x == 0 {
  1058  		panic("log2 of 0")
  1059  	}
  1060  	n := uint32(0)
  1061  	if x >= 1<<32 {
  1062  		x >>= 32
  1063  		n += 32
  1064  	}
  1065  	if x >= 1<<16 {
  1066  		x >>= 16
  1067  		n += 16
  1068  	}
  1069  	if x >= 1<<8 {
  1070  		x >>= 8
  1071  		n += 8
  1072  	}
  1073  	if x >= 1<<4 {
  1074  		x >>= 4
  1075  		n += 4
  1076  	}
  1077  	if x >= 1<<2 {
  1078  		x >>= 2
  1079  		n += 2
  1080  	}
  1081  	if x >= 1<<1 {
  1082  		x >>= 1
  1083  		n += 1
  1084  	}
  1085  	return n
  1086  }
  1087  
  1088  func autoclass(l int64) int {
  1089  	if l < 0 {
  1090  		if l >= -256 {
  1091  			return C_NSAUTO
  1092  		}
  1093  		if l >= -512 && (l&7) == 0 {
  1094  			return C_NPAUTO
  1095  		}
  1096  		return C_LAUTO
  1097  	}
  1098  
  1099  	if l <= 255 {
  1100  		if (l & 7) == 0 {
  1101  			return C_PSAUTO_8
  1102  		}
  1103  		return C_PSAUTO
  1104  	}
  1105  	if l <= 504 && l&7 == 0 {
  1106  		return C_PPAUTO
  1107  	}
  1108  	if l <= 4095 {
  1109  		if l&7 == 0 {
  1110  			return C_UAUTO4K_8
  1111  		}
  1112  		if l&3 == 0 {
  1113  			return C_UAUTO4K_4
  1114  		}
  1115  		if l&1 == 0 {
  1116  			return C_UAUTO4K_2
  1117  		}
  1118  		return C_UAUTO4K
  1119  	}
  1120  	if l <= 8190 {
  1121  		if l&7 == 0 {
  1122  			return C_UAUTO8K_8
  1123  		}
  1124  		if l&3 == 0 {
  1125  			return C_UAUTO8K_4
  1126  		}
  1127  		if l&1 == 0 {
  1128  			return C_UAUTO8K
  1129  		}
  1130  	}
  1131  	if l <= 16380 {
  1132  		if l&7 == 0 {
  1133  			return C_UAUTO16K_8
  1134  		}
  1135  		if l&3 == 0 {
  1136  			return C_UAUTO16K
  1137  		}
  1138  	}
  1139  	if l <= 32760 && (l&7) == 0 {
  1140  		return C_UAUTO32K
  1141  	}
  1142  	return C_LAUTO
  1143  }
  1144  
  1145  func oregclass(l int64) int {
  1146  	if l == 0 {
  1147  		return C_ZOREG
  1148  	}
  1149  	return autoclass(l) - C_NPAUTO + C_NPOREG
  1150  }
  1151  
  1152  /*
  1153   * given an offset v and a class c (see above)
  1154   * return the offset value to use in the instruction,
  1155   * scaled if necessary
  1156   */
  1157  func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
  1158  	s := 0
  1159  	if cls >= C_SEXT1 && cls <= C_SEXT16 {
  1160  		s = cls - C_SEXT1
  1161  	} else {
  1162  		switch cls {
  1163  		case C_UAUTO4K, C_UOREG4K, C_ZOREG:
  1164  			s = 0
  1165  		case C_UAUTO8K, C_UOREG8K:
  1166  			s = 1
  1167  		case C_UAUTO16K, C_UOREG16K:
  1168  			s = 2
  1169  		case C_UAUTO32K, C_UOREG32K:
  1170  			s = 3
  1171  		default:
  1172  			c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
  1173  		}
  1174  	}
  1175  	vs := v >> uint(s)
  1176  	if vs<<uint(s) != v {
  1177  		c.ctxt.Diag("odd offset: %d\n%v", v, p)
  1178  	}
  1179  	return vs
  1180  }
  1181  
  1182  /*
  1183   * if v contains a single 16-bit value aligned
  1184   * on a 16-bit field, and thus suitable for movk/movn,
  1185   * return the field index 0 to 3; otherwise return -1
  1186   */
  1187  func movcon(v int64) int {
  1188  	for s := 0; s < 64; s += 16 {
  1189  		if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
  1190  			return s / 16
  1191  		}
  1192  	}
  1193  	return -1
  1194  }
  1195  
  1196  func rclass(r int16) int {
  1197  	switch {
  1198  	case REG_R0 <= r && r <= REG_R30: // not 31
  1199  		return C_REG
  1200  	case r == REGZERO:
  1201  		return C_ZCON
  1202  	case REG_F0 <= r && r <= REG_F31:
  1203  		return C_FREG
  1204  	case REG_V0 <= r && r <= REG_V31:
  1205  		return C_VREG
  1206  	case COND_EQ <= r && r <= COND_NV:
  1207  		return C_COND
  1208  	case r == REGSP:
  1209  		return C_RSP
  1210  	case r >= REG_ARNG && r < REG_ELEM:
  1211  		return C_ARNG
  1212  	case r >= REG_ELEM && r < REG_ELEM_END:
  1213  		return C_ELEM
  1214  	case r >= REG_UXTB && r < REG_SPECIAL:
  1215  		return C_EXTREG
  1216  	case r >= REG_SPECIAL:
  1217  		return C_SPR
  1218  	}
  1219  	return C_GOK
  1220  }
  1221  
  1222  func (c *ctxt7) aclass(a *obj.Addr) int {
  1223  	switch a.Type {
  1224  	case obj.TYPE_NONE:
  1225  		return C_NONE
  1226  
  1227  	case obj.TYPE_REG:
  1228  		return rclass(a.Reg)
  1229  
  1230  	case obj.TYPE_REGREG:
  1231  		return C_PAIR
  1232  
  1233  	case obj.TYPE_SHIFT:
  1234  		return C_SHIFT
  1235  
  1236  	case obj.TYPE_REGLIST:
  1237  		return C_LIST
  1238  
  1239  	case obj.TYPE_MEM:
  1240  		switch a.Name {
  1241  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  1242  			if a.Sym == nil {
  1243  				break
  1244  			}
  1245  			c.instoffset = a.Offset
  1246  			if a.Sym != nil { // use relocation
  1247  				if a.Sym.Type == objabi.STLSBSS {
  1248  					if c.ctxt.Flag_shared {
  1249  						return C_TLS_IE
  1250  					} else {
  1251  						return C_TLS_LE
  1252  					}
  1253  				}
  1254  				return C_ADDR
  1255  			}
  1256  			return C_LEXT
  1257  
  1258  		case obj.NAME_GOTREF:
  1259  			return C_GOTADDR
  1260  
  1261  		case obj.NAME_AUTO:
  1262  			if a.Reg == REGSP {
  1263  				// unset base register for better printing, since
  1264  				// a.Offset is still relative to pseudo-SP.
  1265  				a.Reg = obj.REG_NONE
  1266  			}
  1267  			c.instoffset = int64(c.autosize) + a.Offset
  1268  			return autoclass(c.instoffset)
  1269  
  1270  		case obj.NAME_PARAM:
  1271  			if a.Reg == REGSP {
  1272  				// unset base register for better printing, since
  1273  				// a.Offset is still relative to pseudo-FP.
  1274  				a.Reg = obj.REG_NONE
  1275  			}
  1276  			c.instoffset = int64(c.autosize) + a.Offset + 8
  1277  			return autoclass(c.instoffset)
  1278  
  1279  		case obj.NAME_NONE:
  1280  			if a.Index != 0 {
  1281  				if a.Offset != 0 {
  1282  					return C_GOK
  1283  				}
  1284  				return C_ROFF
  1285  			}
  1286  			c.instoffset = a.Offset
  1287  			return oregclass(c.instoffset)
  1288  		}
  1289  		return C_GOK
  1290  
  1291  	case obj.TYPE_FCONST:
  1292  		return C_FCON
  1293  
  1294  	case obj.TYPE_TEXTSIZE:
  1295  		return C_TEXTSIZE
  1296  
  1297  	case obj.TYPE_CONST, obj.TYPE_ADDR:
  1298  		switch a.Name {
  1299  		case obj.NAME_NONE:
  1300  			c.instoffset = a.Offset
  1301  			if a.Reg != 0 && a.Reg != REGZERO {
  1302  				goto aconsize
  1303  			}
  1304  			v := c.instoffset
  1305  			if v == 0 {
  1306  				return C_ZCON
  1307  			}
  1308  			if isaddcon(v) {
  1309  				if v <= 0xFFF {
  1310  					if isbitcon(uint64(v)) {
  1311  						return C_ABCON0
  1312  					}
  1313  					return C_ADDCON0
  1314  				}
  1315  				if isbitcon(uint64(v)) {
  1316  					return C_ABCON
  1317  				}
  1318  				return C_ADDCON
  1319  			}
  1320  
  1321  			t := movcon(v)
  1322  			if t >= 0 {
  1323  				if isbitcon(uint64(v)) {
  1324  					return C_MBCON
  1325  				}
  1326  				return C_MOVCON
  1327  			}
  1328  
  1329  			t = movcon(^v)
  1330  			if t >= 0 {
  1331  				if isbitcon(uint64(v)) {
  1332  					return C_MBCON
  1333  				}
  1334  				return C_MOVCON
  1335  			}
  1336  
  1337  			if isbitcon(uint64(v)) {
  1338  				return C_BITCON
  1339  			}
  1340  
  1341  			if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
  1342  				return C_LCON
  1343  			}
  1344  			return C_VCON
  1345  
  1346  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  1347  			if a.Sym == nil {
  1348  				break
  1349  			}
  1350  			if a.Sym.Type == objabi.STLSBSS {
  1351  				c.ctxt.Diag("taking address of TLS variable is not supported")
  1352  			}
  1353  			c.instoffset = a.Offset
  1354  			return C_VCONADDR
  1355  
  1356  		case obj.NAME_AUTO:
  1357  			if a.Reg == REGSP {
  1358  				// unset base register for better printing, since
  1359  				// a.Offset is still relative to pseudo-SP.
  1360  				a.Reg = obj.REG_NONE
  1361  			}
  1362  			c.instoffset = int64(c.autosize) + a.Offset
  1363  			goto aconsize
  1364  
  1365  		case obj.NAME_PARAM:
  1366  			if a.Reg == REGSP {
  1367  				// unset base register for better printing, since
  1368  				// a.Offset is still relative to pseudo-FP.
  1369  				a.Reg = obj.REG_NONE
  1370  			}
  1371  			c.instoffset = int64(c.autosize) + a.Offset + 8
  1372  			goto aconsize
  1373  		}
  1374  		return C_GOK
  1375  
  1376  	aconsize:
  1377  		if isaddcon(c.instoffset) {
  1378  			return C_AACON
  1379  		}
  1380  		return C_LACON
  1381  
  1382  	case obj.TYPE_BRANCH:
  1383  		return C_SBRA
  1384  	}
  1385  
  1386  	return C_GOK
  1387  }
  1388  
  1389  func oclass(a *obj.Addr) int {
  1390  	return int(a.Class) - 1
  1391  }
  1392  
  1393  func (c *ctxt7) oplook(p *obj.Prog) *Optab {
  1394  	a1 := int(p.Optab)
  1395  	if a1 != 0 {
  1396  		return &optab[a1-1]
  1397  	}
  1398  	a1 = int(p.From.Class)
  1399  	if a1 == 0 {
  1400  		a1 = c.aclass(&p.From) + 1
  1401  		p.From.Class = int8(a1)
  1402  	}
  1403  
  1404  	a1--
  1405  	a3 := int(p.To.Class)
  1406  	if a3 == 0 {
  1407  		a3 = c.aclass(&p.To) + 1
  1408  		p.To.Class = int8(a3)
  1409  	}
  1410  
  1411  	a3--
  1412  	a2 := C_NONE
  1413  	if p.Reg != 0 {
  1414  		a2 = rclass(p.Reg)
  1415  	}
  1416  
  1417  	if false {
  1418  		fmt.Printf("oplook %v %d %d %d\n", p.As, a1, a2, a3)
  1419  		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  1420  	}
  1421  
  1422  	ops := oprange[p.As&obj.AMask]
  1423  	c1 := &xcmp[a1]
  1424  	c2 := &xcmp[a2]
  1425  	c3 := &xcmp[a3]
  1426  	c4 := &xcmp[p.Scond>>5]
  1427  	for i := range ops {
  1428  		op := &ops[i]
  1429  		if (int(op.a2) == a2 || c2[op.a2]) && c4[op.scond>>5] && c1[op.a1] && c3[op.a3] {
  1430  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1431  			return op
  1432  		}
  1433  	}
  1434  
  1435  	c.ctxt.Diag("illegal combination: %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.To.Type)
  1436  	if ops == nil {
  1437  		ops = optab
  1438  	}
  1439  	return &ops[0]
  1440  }
  1441  
  1442  func cmp(a int, b int) bool {
  1443  	if a == b {
  1444  		return true
  1445  	}
  1446  	switch a {
  1447  	case C_RSP:
  1448  		if b == C_REG {
  1449  			return true
  1450  		}
  1451  
  1452  	case C_REG:
  1453  		if b == C_ZCON {
  1454  			return true
  1455  		}
  1456  
  1457  	case C_ADDCON0:
  1458  		if b == C_ZCON || b == C_ABCON0 {
  1459  			return true
  1460  		}
  1461  
  1462  	case C_ADDCON:
  1463  		if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON {
  1464  			return true
  1465  		}
  1466  
  1467  	case C_BITCON:
  1468  		if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
  1469  			return true
  1470  		}
  1471  
  1472  	case C_MOVCON:
  1473  		if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 {
  1474  			return true
  1475  		}
  1476  
  1477  	case C_LCON:
  1478  		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 {
  1479  			return true
  1480  		}
  1481  
  1482  	case C_VCON:
  1483  		return cmp(C_LCON, b)
  1484  
  1485  	case C_LACON:
  1486  		if b == C_AACON {
  1487  			return true
  1488  		}
  1489  
  1490  	case C_SEXT2:
  1491  		if b == C_SEXT1 {
  1492  			return true
  1493  		}
  1494  
  1495  	case C_SEXT4:
  1496  		if b == C_SEXT1 || b == C_SEXT2 {
  1497  			return true
  1498  		}
  1499  
  1500  	case C_SEXT8:
  1501  		if b >= C_SEXT1 && b <= C_SEXT4 {
  1502  			return true
  1503  		}
  1504  
  1505  	case C_SEXT16:
  1506  		if b >= C_SEXT1 && b <= C_SEXT8 {
  1507  			return true
  1508  		}
  1509  
  1510  	case C_LEXT:
  1511  		if b >= C_SEXT1 && b <= C_SEXT16 {
  1512  			return true
  1513  		}
  1514  
  1515  	case C_PSAUTO:
  1516  		if b == C_PSAUTO_8 {
  1517  			return true
  1518  		}
  1519  
  1520  	case C_PPAUTO:
  1521  		if b == C_PSAUTO_8 {
  1522  			return true
  1523  		}
  1524  
  1525  	case C_UAUTO4K:
  1526  		switch b {
  1527  		case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
  1528  			return true
  1529  		}
  1530  
  1531  	case C_UAUTO8K:
  1532  		switch b {
  1533  		case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
  1534  			return true
  1535  		}
  1536  
  1537  	case C_UAUTO16K:
  1538  		switch b {
  1539  		case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
  1540  			return true
  1541  		}
  1542  
  1543  	case C_UAUTO32K:
  1544  		switch b {
  1545  		case C_PSAUTO, C_PSAUTO_8, C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
  1546  			return true
  1547  		}
  1548  
  1549  	case C_NPAUTO:
  1550  		return cmp(C_NSAUTO, b)
  1551  
  1552  	case C_LAUTO:
  1553  		switch b {
  1554  		case C_PSAUTO, C_PSAUTO_8, C_PPAUTO,
  1555  			C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
  1556  			C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
  1557  			C_UAUTO16K, C_UAUTO16K_8,
  1558  			C_UAUTO32K:
  1559  			return true
  1560  		}
  1561  		return cmp(C_NPAUTO, b)
  1562  
  1563  	case C_PSOREG:
  1564  		if b == C_ZOREG || b == C_PSOREG_8 {
  1565  			return true
  1566  		}
  1567  
  1568  	case C_PPOREG:
  1569  		switch b {
  1570  		case C_ZOREG, C_PSOREG_8:
  1571  			return true
  1572  		}
  1573  
  1574  	case C_UOREG4K:
  1575  		switch b {
  1576  		case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8:
  1577  			return true
  1578  		}
  1579  
  1580  	case C_UOREG8K:
  1581  		switch b {
  1582  		case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8:
  1583  			return true
  1584  		}
  1585  
  1586  	case C_UOREG16K:
  1587  		switch b {
  1588  		case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4, C_UOREG8K_8, C_UOREG16K_8:
  1589  			return true
  1590  		}
  1591  
  1592  	case C_UOREG32K:
  1593  		switch b {
  1594  		case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8:
  1595  			return true
  1596  		}
  1597  
  1598  	case C_NPOREG:
  1599  		return cmp(C_NSOREG, b)
  1600  
  1601  	case C_LOREG:
  1602  		switch b {
  1603  		case C_ZOREG, C_PSOREG_8, C_PSOREG, C_PPOREG,
  1604  			C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
  1605  			C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8,
  1606  			C_UOREG16K, C_UOREG16K_8,
  1607  			C_UOREG32K:
  1608  			return true
  1609  		}
  1610  		return cmp(C_NPOREG, b)
  1611  
  1612  	case C_LBRA:
  1613  		if b == C_SBRA {
  1614  			return true
  1615  		}
  1616  	}
  1617  
  1618  	return false
  1619  }
  1620  
  1621  type ocmp []Optab
  1622  
  1623  func (x ocmp) Len() int {
  1624  	return len(x)
  1625  }
  1626  
  1627  func (x ocmp) Swap(i, j int) {
  1628  	x[i], x[j] = x[j], x[i]
  1629  }
  1630  
  1631  func (x ocmp) Less(i, j int) bool {
  1632  	p1 := &x[i]
  1633  	p2 := &x[j]
  1634  	if p1.as != p2.as {
  1635  		return p1.as < p2.as
  1636  	}
  1637  	if p1.a1 != p2.a1 {
  1638  		return p1.a1 < p2.a1
  1639  	}
  1640  	if p1.a2 != p2.a2 {
  1641  		return p1.a2 < p2.a2
  1642  	}
  1643  	if p1.a3 != p2.a3 {
  1644  		return p1.a3 < p2.a3
  1645  	}
  1646  	if p1.scond != p2.scond {
  1647  		return p1.scond < p2.scond
  1648  	}
  1649  	return false
  1650  }
  1651  
  1652  func oprangeset(a obj.As, t []Optab) {
  1653  	oprange[a&obj.AMask] = t
  1654  }
  1655  
  1656  func buildop(ctxt *obj.Link) {
  1657  	if oprange[AAND&obj.AMask] != nil {
  1658  		// Already initialized; stop now.
  1659  		// This happens in the cmd/asm tests,
  1660  		// each of which re-initializes the arch.
  1661  		return
  1662  	}
  1663  
  1664  	var n int
  1665  	for i := 0; i < C_GOK; i++ {
  1666  		for n = 0; n < C_GOK; n++ {
  1667  			if cmp(n, i) {
  1668  				xcmp[i][n] = true
  1669  			}
  1670  		}
  1671  	}
  1672  	for n = 0; optab[n].as != obj.AXXX; n++ {
  1673  	}
  1674  	sort.Sort(ocmp(optab[:n]))
  1675  	for i := 0; i < n; i++ {
  1676  		r := optab[i].as
  1677  		start := i
  1678  		for optab[i].as == r {
  1679  			i++
  1680  		}
  1681  		t := optab[start:i]
  1682  		i--
  1683  		oprangeset(r, t)
  1684  		switch r {
  1685  		default:
  1686  			ctxt.Diag("unknown op in build: %v", r)
  1687  			ctxt.DiagFlush()
  1688  			log.Fatalf("bad code")
  1689  
  1690  		case AADD:
  1691  			oprangeset(AADDS, t)
  1692  			oprangeset(ASUB, t)
  1693  			oprangeset(ASUBS, t)
  1694  			oprangeset(AADDW, t)
  1695  			oprangeset(AADDSW, t)
  1696  			oprangeset(ASUBW, t)
  1697  			oprangeset(ASUBSW, t)
  1698  
  1699  		case AAND: /* logical immediate, logical shifted register */
  1700  			oprangeset(AANDS, t)
  1701  
  1702  			oprangeset(AANDSW, t)
  1703  			oprangeset(AANDW, t)
  1704  			oprangeset(AEOR, t)
  1705  			oprangeset(AEORW, t)
  1706  			oprangeset(AORR, t)
  1707  			oprangeset(AORRW, t)
  1708  
  1709  		case ABIC: /* only logical shifted register */
  1710  			oprangeset(ABICS, t)
  1711  
  1712  			oprangeset(ABICSW, t)
  1713  			oprangeset(ABICW, t)
  1714  			oprangeset(AEON, t)
  1715  			oprangeset(AEONW, t)
  1716  			oprangeset(AORN, t)
  1717  			oprangeset(AORNW, t)
  1718  
  1719  		case ANEG:
  1720  			oprangeset(ANEGS, t)
  1721  			oprangeset(ANEGSW, t)
  1722  			oprangeset(ANEGW, t)
  1723  
  1724  		case AADC: /* rn=Rd */
  1725  			oprangeset(AADCW, t)
  1726  
  1727  			oprangeset(AADCS, t)
  1728  			oprangeset(AADCSW, t)
  1729  			oprangeset(ASBC, t)
  1730  			oprangeset(ASBCW, t)
  1731  			oprangeset(ASBCS, t)
  1732  			oprangeset(ASBCSW, t)
  1733  
  1734  		case ANGC: /* rn=REGZERO */
  1735  			oprangeset(ANGCW, t)
  1736  
  1737  			oprangeset(ANGCS, t)
  1738  			oprangeset(ANGCSW, t)
  1739  
  1740  		case ACMP:
  1741  			oprangeset(ACMPW, t)
  1742  			oprangeset(ACMN, t)
  1743  			oprangeset(ACMNW, t)
  1744  
  1745  		case ATST:
  1746  			oprangeset(ATSTW, t)
  1747  
  1748  			/* register/register, and shifted */
  1749  		case AMVN:
  1750  			oprangeset(AMVNW, t)
  1751  
  1752  		case AMOVK:
  1753  			oprangeset(AMOVKW, t)
  1754  			oprangeset(AMOVN, t)
  1755  			oprangeset(AMOVNW, t)
  1756  			oprangeset(AMOVZ, t)
  1757  			oprangeset(AMOVZW, t)
  1758  
  1759  		case ABEQ:
  1760  			oprangeset(ABNE, t)
  1761  			oprangeset(ABCS, t)
  1762  			oprangeset(ABHS, t)
  1763  			oprangeset(ABCC, t)
  1764  			oprangeset(ABLO, t)
  1765  			oprangeset(ABMI, t)
  1766  			oprangeset(ABPL, t)
  1767  			oprangeset(ABVS, t)
  1768  			oprangeset(ABVC, t)
  1769  			oprangeset(ABHI, t)
  1770  			oprangeset(ABLS, t)
  1771  			oprangeset(ABGE, t)
  1772  			oprangeset(ABLT, t)
  1773  			oprangeset(ABGT, t)
  1774  			oprangeset(ABLE, t)
  1775  
  1776  		case ALSL:
  1777  			oprangeset(ALSLW, t)
  1778  			oprangeset(ALSR, t)
  1779  			oprangeset(ALSRW, t)
  1780  			oprangeset(AASR, t)
  1781  			oprangeset(AASRW, t)
  1782  			oprangeset(AROR, t)
  1783  			oprangeset(ARORW, t)
  1784  
  1785  		case ACLS:
  1786  			oprangeset(ACLSW, t)
  1787  			oprangeset(ACLZ, t)
  1788  			oprangeset(ACLZW, t)
  1789  			oprangeset(ARBIT, t)
  1790  			oprangeset(ARBITW, t)
  1791  			oprangeset(AREV, t)
  1792  			oprangeset(AREVW, t)
  1793  			oprangeset(AREV16, t)
  1794  			oprangeset(AREV16W, t)
  1795  			oprangeset(AREV32, t)
  1796  
  1797  		case ASDIV:
  1798  			oprangeset(ASDIVW, t)
  1799  			oprangeset(AUDIV, t)
  1800  			oprangeset(AUDIVW, t)
  1801  			oprangeset(ACRC32B, t)
  1802  			oprangeset(ACRC32CB, t)
  1803  			oprangeset(ACRC32CH, t)
  1804  			oprangeset(ACRC32CW, t)
  1805  			oprangeset(ACRC32CX, t)
  1806  			oprangeset(ACRC32H, t)
  1807  			oprangeset(ACRC32W, t)
  1808  			oprangeset(ACRC32X, t)
  1809  
  1810  		case AMADD:
  1811  			oprangeset(AMADDW, t)
  1812  			oprangeset(AMSUB, t)
  1813  			oprangeset(AMSUBW, t)
  1814  			oprangeset(ASMADDL, t)
  1815  			oprangeset(ASMSUBL, t)
  1816  			oprangeset(AUMADDL, t)
  1817  			oprangeset(AUMSUBL, t)
  1818  
  1819  		case AREM:
  1820  			oprangeset(AREMW, t)
  1821  			oprangeset(AUREM, t)
  1822  			oprangeset(AUREMW, t)
  1823  
  1824  		case AMUL:
  1825  			oprangeset(AMULW, t)
  1826  			oprangeset(AMNEG, t)
  1827  			oprangeset(AMNEGW, t)
  1828  			oprangeset(ASMNEGL, t)
  1829  			oprangeset(ASMULL, t)
  1830  			oprangeset(ASMULH, t)
  1831  			oprangeset(AUMNEGL, t)
  1832  			oprangeset(AUMULH, t)
  1833  			oprangeset(AUMULL, t)
  1834  
  1835  		case AMOVB:
  1836  			oprangeset(AMOVBU, t)
  1837  
  1838  		case AMOVH:
  1839  			oprangeset(AMOVHU, t)
  1840  
  1841  		case AMOVW:
  1842  			oprangeset(AMOVWU, t)
  1843  
  1844  		case ABFM:
  1845  			oprangeset(ABFMW, t)
  1846  			oprangeset(ASBFM, t)
  1847  			oprangeset(ASBFMW, t)
  1848  			oprangeset(AUBFM, t)
  1849  			oprangeset(AUBFMW, t)
  1850  
  1851  		case ABFI:
  1852  			oprangeset(ABFIW, t)
  1853  			oprangeset(ABFXIL, t)
  1854  			oprangeset(ABFXILW, t)
  1855  			oprangeset(ASBFIZ, t)
  1856  			oprangeset(ASBFIZW, t)
  1857  			oprangeset(ASBFX, t)
  1858  			oprangeset(ASBFXW, t)
  1859  			oprangeset(AUBFIZ, t)
  1860  			oprangeset(AUBFIZW, t)
  1861  			oprangeset(AUBFX, t)
  1862  			oprangeset(AUBFXW, t)
  1863  
  1864  		case AEXTR:
  1865  			oprangeset(AEXTRW, t)
  1866  
  1867  		case ASXTB:
  1868  			oprangeset(ASXTBW, t)
  1869  			oprangeset(ASXTH, t)
  1870  			oprangeset(ASXTHW, t)
  1871  			oprangeset(ASXTW, t)
  1872  			oprangeset(AUXTB, t)
  1873  			oprangeset(AUXTH, t)
  1874  			oprangeset(AUXTW, t)
  1875  			oprangeset(AUXTBW, t)
  1876  			oprangeset(AUXTHW, t)
  1877  
  1878  		case ACCMN:
  1879  			oprangeset(ACCMNW, t)
  1880  			oprangeset(ACCMP, t)
  1881  			oprangeset(ACCMPW, t)
  1882  
  1883  		case ACSEL:
  1884  			oprangeset(ACSELW, t)
  1885  			oprangeset(ACSINC, t)
  1886  			oprangeset(ACSINCW, t)
  1887  			oprangeset(ACSINV, t)
  1888  			oprangeset(ACSINVW, t)
  1889  			oprangeset(ACSNEG, t)
  1890  			oprangeset(ACSNEGW, t)
  1891  
  1892  			// aliases Rm=Rn, !cond
  1893  			oprangeset(ACINC, t)
  1894  
  1895  			oprangeset(ACINCW, t)
  1896  			oprangeset(ACINV, t)
  1897  			oprangeset(ACINVW, t)
  1898  			oprangeset(ACNEG, t)
  1899  			oprangeset(ACNEGW, t)
  1900  
  1901  			// aliases, Rm=Rn=REGZERO, !cond
  1902  		case ACSET:
  1903  			oprangeset(ACSETW, t)
  1904  
  1905  			oprangeset(ACSETM, t)
  1906  			oprangeset(ACSETMW, t)
  1907  
  1908  		case AMOVD,
  1909  			AMOVBU,
  1910  			AB,
  1911  			ABL,
  1912  			AWORD,
  1913  			ADWORD,
  1914  			obj.ARET,
  1915  			obj.ATEXT,
  1916  			ASTP,
  1917  			ALDP:
  1918  			break
  1919  
  1920  		case AERET:
  1921  			oprangeset(AWFE, t)
  1922  			oprangeset(AWFI, t)
  1923  			oprangeset(AYIELD, t)
  1924  			oprangeset(ASEV, t)
  1925  			oprangeset(ASEVL, t)
  1926  			oprangeset(ADRPS, t)
  1927  
  1928  		case ACBZ:
  1929  			oprangeset(ACBZW, t)
  1930  			oprangeset(ACBNZ, t)
  1931  			oprangeset(ACBNZW, t)
  1932  
  1933  		case ATBZ:
  1934  			oprangeset(ATBNZ, t)
  1935  
  1936  		case AADR, AADRP:
  1937  			break
  1938  
  1939  		case ACLREX:
  1940  			break
  1941  
  1942  		case ASVC:
  1943  			oprangeset(AHVC, t)
  1944  			oprangeset(AHLT, t)
  1945  			oprangeset(ASMC, t)
  1946  			oprangeset(ABRK, t)
  1947  			oprangeset(ADCPS1, t)
  1948  			oprangeset(ADCPS2, t)
  1949  			oprangeset(ADCPS3, t)
  1950  
  1951  		case AFADDS:
  1952  			oprangeset(AFADDD, t)
  1953  			oprangeset(AFSUBS, t)
  1954  			oprangeset(AFSUBD, t)
  1955  			oprangeset(AFMULS, t)
  1956  			oprangeset(AFMULD, t)
  1957  			oprangeset(AFNMULS, t)
  1958  			oprangeset(AFNMULD, t)
  1959  			oprangeset(AFDIVS, t)
  1960  			oprangeset(AFMAXD, t)
  1961  			oprangeset(AFMAXS, t)
  1962  			oprangeset(AFMIND, t)
  1963  			oprangeset(AFMINS, t)
  1964  			oprangeset(AFMAXNMD, t)
  1965  			oprangeset(AFMAXNMS, t)
  1966  			oprangeset(AFMINNMD, t)
  1967  			oprangeset(AFMINNMS, t)
  1968  			oprangeset(AFDIVD, t)
  1969  
  1970  		case AFCVTSD:
  1971  			oprangeset(AFCVTDS, t)
  1972  			oprangeset(AFABSD, t)
  1973  			oprangeset(AFABSS, t)
  1974  			oprangeset(AFNEGD, t)
  1975  			oprangeset(AFNEGS, t)
  1976  			oprangeset(AFSQRTD, t)
  1977  			oprangeset(AFSQRTS, t)
  1978  			oprangeset(AFRINTNS, t)
  1979  			oprangeset(AFRINTND, t)
  1980  			oprangeset(AFRINTPS, t)
  1981  			oprangeset(AFRINTPD, t)
  1982  			oprangeset(AFRINTMS, t)
  1983  			oprangeset(AFRINTMD, t)
  1984  			oprangeset(AFRINTZS, t)
  1985  			oprangeset(AFRINTZD, t)
  1986  			oprangeset(AFRINTAS, t)
  1987  			oprangeset(AFRINTAD, t)
  1988  			oprangeset(AFRINTXS, t)
  1989  			oprangeset(AFRINTXD, t)
  1990  			oprangeset(AFRINTIS, t)
  1991  			oprangeset(AFRINTID, t)
  1992  			oprangeset(AFCVTDH, t)
  1993  			oprangeset(AFCVTHS, t)
  1994  			oprangeset(AFCVTHD, t)
  1995  			oprangeset(AFCVTSH, t)
  1996  
  1997  		case AFCMPS:
  1998  			oprangeset(AFCMPD, t)
  1999  			oprangeset(AFCMPES, t)
  2000  			oprangeset(AFCMPED, t)
  2001  
  2002  		case AFCCMPS:
  2003  			oprangeset(AFCCMPD, t)
  2004  			oprangeset(AFCCMPES, t)
  2005  			oprangeset(AFCCMPED, t)
  2006  
  2007  		case AFCSELD:
  2008  			oprangeset(AFCSELS, t)
  2009  
  2010  		case AFMOVS, AFMOVD:
  2011  			break
  2012  
  2013  		case AFCVTZSD:
  2014  			oprangeset(AFCVTZSDW, t)
  2015  			oprangeset(AFCVTZSS, t)
  2016  			oprangeset(AFCVTZSSW, t)
  2017  			oprangeset(AFCVTZUD, t)
  2018  			oprangeset(AFCVTZUDW, t)
  2019  			oprangeset(AFCVTZUS, t)
  2020  			oprangeset(AFCVTZUSW, t)
  2021  
  2022  		case ASCVTFD:
  2023  			oprangeset(ASCVTFS, t)
  2024  			oprangeset(ASCVTFWD, t)
  2025  			oprangeset(ASCVTFWS, t)
  2026  			oprangeset(AUCVTFD, t)
  2027  			oprangeset(AUCVTFS, t)
  2028  			oprangeset(AUCVTFWD, t)
  2029  			oprangeset(AUCVTFWS, t)
  2030  
  2031  		case ASYS:
  2032  			oprangeset(AAT, t)
  2033  			oprangeset(ADC, t)
  2034  			oprangeset(AIC, t)
  2035  			oprangeset(ATLBI, t)
  2036  
  2037  		case ASYSL, AHINT:
  2038  			break
  2039  
  2040  		case ADMB:
  2041  			oprangeset(ADSB, t)
  2042  			oprangeset(AISB, t)
  2043  
  2044  		case AMRS, AMSR:
  2045  			break
  2046  
  2047  		case ALDAR:
  2048  			oprangeset(ALDARW, t)
  2049  			fallthrough
  2050  
  2051  		case ALDXR:
  2052  			oprangeset(ALDXRB, t)
  2053  			oprangeset(ALDXRH, t)
  2054  			oprangeset(ALDXRW, t)
  2055  
  2056  		case ALDAXR:
  2057  			oprangeset(ALDAXRB, t)
  2058  			oprangeset(ALDAXRH, t)
  2059  			oprangeset(ALDAXRW, t)
  2060  
  2061  		case ALDXP:
  2062  			oprangeset(ALDXPW, t)
  2063  
  2064  		case ASTLR:
  2065  			oprangeset(ASTLRW, t)
  2066  
  2067  		case ASTXR:
  2068  			oprangeset(ASTXRB, t)
  2069  			oprangeset(ASTXRH, t)
  2070  			oprangeset(ASTXRW, t)
  2071  
  2072  		case ASTLXR:
  2073  			oprangeset(ASTLXRB, t)
  2074  			oprangeset(ASTLXRH, t)
  2075  			oprangeset(ASTLXRW, t)
  2076  
  2077  		case ASTXP:
  2078  			oprangeset(ASTXPW, t)
  2079  
  2080  		case AVADDP:
  2081  			oprangeset(AVAND, t)
  2082  			oprangeset(AVCMEQ, t)
  2083  			oprangeset(AVORR, t)
  2084  			oprangeset(AVEOR, t)
  2085  
  2086  		case AVADD:
  2087  			oprangeset(AVSUB, t)
  2088  
  2089  		case AAESD:
  2090  			oprangeset(AAESE, t)
  2091  			oprangeset(AAESMC, t)
  2092  			oprangeset(AAESIMC, t)
  2093  			oprangeset(ASHA1SU1, t)
  2094  			oprangeset(ASHA256SU0, t)
  2095  
  2096  		case ASHA1C:
  2097  			oprangeset(ASHA1P, t)
  2098  			oprangeset(ASHA1M, t)
  2099  
  2100  		case ASHA256H:
  2101  			oprangeset(ASHA256H2, t)
  2102  
  2103  		case ASHA1SU0:
  2104  			oprangeset(ASHA256SU1, t)
  2105  
  2106  		case AVADDV:
  2107  			oprangeset(AVUADDLV, t)
  2108  
  2109  		case ASHA1H,
  2110  			AVMOV,
  2111  			AVLD1,
  2112  			AVREV32,
  2113  			AVST1,
  2114  			AVDUP,
  2115  			AVMOVS,
  2116  			AVMOVI:
  2117  			break
  2118  
  2119  		case obj.ANOP,
  2120  			obj.AUNDEF,
  2121  			obj.AFUNCDATA,
  2122  			obj.APCDATA,
  2123  			obj.ADUFFZERO,
  2124  			obj.ADUFFCOPY:
  2125  			break
  2126  		}
  2127  	}
  2128  }
  2129  
  2130  func (c *ctxt7) chipfloat7(e float64) int {
  2131  	ei := math.Float64bits(e)
  2132  	l := uint32(int32(ei))
  2133  	h := uint32(int32(ei >> 32))
  2134  
  2135  	if l != 0 || h&0xffff != 0 {
  2136  		return -1
  2137  	}
  2138  	h1 := h & 0x7fc00000
  2139  	if h1 != 0x40000000 && h1 != 0x3fc00000 {
  2140  		return -1
  2141  	}
  2142  	n := 0
  2143  
  2144  	// sign bit (a)
  2145  	if h&0x80000000 != 0 {
  2146  		n |= 1 << 7
  2147  	}
  2148  
  2149  	// exp sign bit (b)
  2150  	if h1 == 0x3fc00000 {
  2151  		n |= 1 << 6
  2152  	}
  2153  
  2154  	// rest of exp and mantissa (cd-efgh)
  2155  	n |= int((h >> 16) & 0x3f)
  2156  
  2157  	//print("match %.8lux %.8lux %d\n", l, h, n);
  2158  	return n
  2159  }
  2160  
  2161  /* form offset parameter to SYS; special register number */
  2162  func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
  2163  	return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
  2164  }
  2165  
  2166  func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
  2167  	return SYSARG5(0, op1, Cn, Cm, op2)
  2168  }
  2169  
  2170  func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
  2171  	o1 := uint32(0)
  2172  	o2 := uint32(0)
  2173  	o3 := uint32(0)
  2174  	o4 := uint32(0)
  2175  	o5 := uint32(0)
  2176  	if false { /*debug['P']*/
  2177  		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  2178  	}
  2179  	switch o.type_ {
  2180  	default:
  2181  		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  2182  
  2183  	case 0: /* pseudo ops */
  2184  		break
  2185  
  2186  	case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
  2187  		o1 = c.oprrr(p, p.As)
  2188  
  2189  		rf := int(p.From.Reg)
  2190  		rt := int(p.To.Reg)
  2191  		r := int(p.Reg)
  2192  		if p.To.Type == obj.TYPE_NONE {
  2193  			rt = REGZERO
  2194  		}
  2195  		if r == 0 {
  2196  			r = rt
  2197  		}
  2198  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  2199  
  2200  	case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
  2201  		o1 = c.opirr(p, p.As)
  2202  
  2203  		rt := int(p.To.Reg)
  2204  		if p.To.Type == obj.TYPE_NONE {
  2205  			if (o1 & Sbit) == 0 {
  2206  				c.ctxt.Diag("ineffective ZR destination\n%v", p)
  2207  			}
  2208  			rt = REGZERO
  2209  		}
  2210  
  2211  		r := int(p.Reg)
  2212  		if r == 0 {
  2213  			r = rt
  2214  		}
  2215  		v := int32(c.regoff(&p.From))
  2216  		o1 = c.oaddi(p, int32(o1), v, r, rt)
  2217  
  2218  	case 3: /* op R<<n[,R],R (shifted register) */
  2219  		o1 = c.oprrr(p, p.As)
  2220  
  2221  		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  2222  		rt := int(p.To.Reg)
  2223  		if p.To.Type == obj.TYPE_NONE {
  2224  			rt = REGZERO
  2225  		}
  2226  		r := int(p.Reg)
  2227  		if p.As == AMVN || p.As == AMVNW {
  2228  			r = REGZERO
  2229  		} else if r == 0 {
  2230  			r = rt
  2231  		}
  2232  		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  2233  
  2234  	case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R */
  2235  		o1 = c.opirr(p, p.As)
  2236  
  2237  		rt := int(p.To.Reg)
  2238  		r := int(o.param)
  2239  		if r == 0 {
  2240  			r = REGZERO
  2241  		} else if r == REGFROM {
  2242  			r = int(p.From.Reg)
  2243  		}
  2244  		if r == 0 {
  2245  			r = REGSP
  2246  		}
  2247  		v := int32(c.regoff(&p.From))
  2248  		if (v & 0xFFF000) != 0 {
  2249  			v >>= 12
  2250  			o1 |= 1 << 22 /* shift, by 12 */
  2251  		}
  2252  
  2253  		o1 |= ((uint32(v) & 0xFFF) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  2254  
  2255  	case 5: /* b s; bl s */
  2256  		o1 = c.opbra(p, p.As)
  2257  
  2258  		if p.To.Sym == nil {
  2259  			o1 |= uint32(c.brdist(p, 0, 26, 2))
  2260  			break
  2261  		}
  2262  
  2263  		rel := obj.Addrel(c.cursym)
  2264  		rel.Off = int32(c.pc)
  2265  		rel.Siz = 4
  2266  		rel.Sym = p.To.Sym
  2267  		rel.Add = p.To.Offset
  2268  		rel.Type = objabi.R_CALLARM64
  2269  
  2270  	case 6: /* b ,O(R); bl ,O(R) */
  2271  		o1 = c.opbrr(p, p.As)
  2272  
  2273  		o1 |= uint32(p.To.Reg&31) << 5
  2274  		rel := obj.Addrel(c.cursym)
  2275  		rel.Off = int32(c.pc)
  2276  		rel.Siz = 0
  2277  		rel.Type = objabi.R_CALLIND
  2278  
  2279  	case 7: /* beq s */
  2280  		o1 = c.opbra(p, p.As)
  2281  
  2282  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  2283  
  2284  	case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
  2285  		rt := int(p.To.Reg)
  2286  
  2287  		rf := int(p.Reg)
  2288  		if rf == 0 {
  2289  			rf = rt
  2290  		}
  2291  		v := int32(p.From.Offset)
  2292  		switch p.As {
  2293  		case AASR:
  2294  			o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
  2295  
  2296  		case AASRW:
  2297  			o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
  2298  
  2299  		case ALSL:
  2300  			o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
  2301  
  2302  		case ALSLW:
  2303  			o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
  2304  
  2305  		case ALSR:
  2306  			o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
  2307  
  2308  		case ALSRW:
  2309  			o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
  2310  
  2311  		case AROR:
  2312  			o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
  2313  
  2314  		case ARORW:
  2315  			o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
  2316  
  2317  		default:
  2318  			c.ctxt.Diag("bad shift $con\n%v", p)
  2319  			break
  2320  		}
  2321  
  2322  	case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
  2323  		o1 = c.oprrr(p, p.As)
  2324  
  2325  		r := int(p.Reg)
  2326  		if r == 0 {
  2327  			r = int(p.To.Reg)
  2328  		}
  2329  		o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
  2330  
  2331  	case 10: /* brk/hvc/.../svc [$con] */
  2332  		o1 = c.opimm(p, p.As)
  2333  
  2334  		if p.From.Type != obj.TYPE_NONE {
  2335  			o1 |= uint32((p.From.Offset & 0xffff) << 5)
  2336  		}
  2337  
  2338  	case 11: /* dword */
  2339  		c.aclass(&p.To)
  2340  
  2341  		o1 = uint32(c.instoffset)
  2342  		o2 = uint32(c.instoffset >> 32)
  2343  		if p.To.Sym != nil {
  2344  			rel := obj.Addrel(c.cursym)
  2345  			rel.Off = int32(c.pc)
  2346  			rel.Siz = 8
  2347  			rel.Sym = p.To.Sym
  2348  			rel.Add = p.To.Offset
  2349  			rel.Type = objabi.R_ADDR
  2350  			o2 = 0
  2351  			o1 = o2
  2352  		}
  2353  
  2354  	case 12: /* movT $vcon, reg */
  2355  		o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
  2356  
  2357  	case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
  2358  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  2359  
  2360  		if !(o1 != 0) {
  2361  			break
  2362  		}
  2363  		rt := int(p.To.Reg)
  2364  		if p.To.Type == obj.TYPE_NONE {
  2365  			rt = REGZERO
  2366  		}
  2367  		r := int(p.Reg)
  2368  		if r == 0 {
  2369  			r = rt
  2370  		}
  2371  		if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
  2372  			o2 = c.opxrrr(p, p.As, false)
  2373  			o2 |= REGTMP & 31 << 16
  2374  			o2 |= LSL0_64
  2375  		} else {
  2376  			o2 = c.oprrr(p, p.As)
  2377  			o2 |= REGTMP & 31 << 16 /* shift is 0 */
  2378  		}
  2379  
  2380  		o2 |= uint32(r&31) << 5
  2381  		o2 |= uint32(rt & 31)
  2382  
  2383  	case 14: /* word */
  2384  		if c.aclass(&p.To) == C_ADDR {
  2385  			c.ctxt.Diag("address constant needs DWORD\n%v", p)
  2386  		}
  2387  		o1 = uint32(c.instoffset)
  2388  		if p.To.Sym != nil {
  2389  			// This case happens with words generated
  2390  			// in the PC stream as part of the literal pool.
  2391  			rel := obj.Addrel(c.cursym)
  2392  
  2393  			rel.Off = int32(c.pc)
  2394  			rel.Siz = 4
  2395  			rel.Sym = p.To.Sym
  2396  			rel.Add = p.To.Offset
  2397  			rel.Type = objabi.R_ADDR
  2398  			o1 = 0
  2399  		}
  2400  
  2401  	case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub Rm,Ra,Rn,Rd */
  2402  		o1 = c.oprrr(p, p.As)
  2403  
  2404  		rf := int(p.From.Reg)
  2405  		rt := int(p.To.Reg)
  2406  		var r int
  2407  		var ra int
  2408  		if p.From3Type() == obj.TYPE_REG {
  2409  			r = int(p.GetFrom3().Reg)
  2410  			ra = int(p.Reg)
  2411  			if ra == 0 {
  2412  				ra = REGZERO
  2413  			}
  2414  		} else {
  2415  			r = int(p.Reg)
  2416  			if r == 0 {
  2417  				r = rt
  2418  			}
  2419  			ra = REGZERO
  2420  		}
  2421  
  2422  		o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  2423  
  2424  	case 16: /* XremY R[,R],R -> XdivY; XmsubY */
  2425  		o1 = c.oprrr(p, p.As)
  2426  
  2427  		rf := int(p.From.Reg)
  2428  		rt := int(p.To.Reg)
  2429  		r := int(p.Reg)
  2430  		if r == 0 {
  2431  			r = rt
  2432  		}
  2433  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
  2434  		o2 = c.oprrr(p, AMSUBW)
  2435  		o2 |= o1 & (1 << 31) /* same size */
  2436  		o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
  2437  
  2438  	case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
  2439  		o1 = c.oprrr(p, p.As)
  2440  
  2441  		rf := int(p.From.Reg)
  2442  		rt := int(p.To.Reg)
  2443  		r := int(p.Reg)
  2444  		if p.To.Type == obj.TYPE_NONE {
  2445  			rt = REGZERO
  2446  		}
  2447  		if r == 0 {
  2448  			r = REGZERO
  2449  		}
  2450  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  2451  
  2452  	case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
  2453  		o1 = c.oprrr(p, p.As)
  2454  
  2455  		cond := int(p.From.Reg)
  2456  		if cond < COND_EQ || cond > COND_NV {
  2457  			c.ctxt.Diag("invalid condition\n%v", p)
  2458  		} else {
  2459  			cond -= COND_EQ
  2460  		}
  2461  
  2462  		r := int(p.Reg)
  2463  		var rf int
  2464  		if r != 0 {
  2465  			if p.From3Type() == obj.TYPE_NONE {
  2466  				/* CINC/CINV/CNEG */
  2467  				rf = r
  2468  
  2469  				cond ^= 1
  2470  			} else {
  2471  				rf = int(p.GetFrom3().Reg) /* CSEL */
  2472  			}
  2473  		} else {
  2474  			/* CSET */
  2475  			if p.From3Type() != obj.TYPE_NONE {
  2476  				c.ctxt.Diag("invalid combination\n%v", p)
  2477  			}
  2478  			rf = REGZERO
  2479  			r = rf
  2480  			cond ^= 1
  2481  		}
  2482  
  2483  		rt := int(p.To.Reg)
  2484  		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
  2485  
  2486  	case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
  2487  		nzcv := int(p.To.Offset)
  2488  
  2489  		cond := int(p.From.Reg)
  2490  		if cond < COND_EQ || cond > COND_NV {
  2491  			c.ctxt.Diag("invalid condition\n%v", p)
  2492  		} else {
  2493  			cond -= COND_EQ
  2494  		}
  2495  		var rf int
  2496  		if p.GetFrom3().Type == obj.TYPE_REG {
  2497  			o1 = c.oprrr(p, p.As)
  2498  			rf = int(p.GetFrom3().Reg) /* Rm */
  2499  		} else {
  2500  			o1 = c.opirr(p, p.As)
  2501  			rf = int(p.GetFrom3().Offset & 0x1F)
  2502  		}
  2503  
  2504  		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
  2505  
  2506  	case 20: /* movT R,O(R) -> strT */
  2507  		v := int32(c.regoff(&p.To))
  2508  		sz := int32(1 << uint(movesize(p.As)))
  2509  
  2510  		r := int(p.To.Reg)
  2511  		if r == 0 {
  2512  			r = int(o.param)
  2513  		}
  2514  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  2515  			o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
  2516  		} else {
  2517  			v = int32(c.offsetshift(p, int64(v), int(o.a3)))
  2518  			o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
  2519  		}
  2520  
  2521  	case 21: /* movT O(R),R -> ldrT */
  2522  		v := int32(c.regoff(&p.From))
  2523  		sz := int32(1 << uint(movesize(p.As)))
  2524  
  2525  		r := int(p.From.Reg)
  2526  		if r == 0 {
  2527  			r = int(o.param)
  2528  		}
  2529  		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  2530  			o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
  2531  		} else {
  2532  			v = int32(c.offsetshift(p, int64(v), int(o.a1)))
  2533  			//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
  2534  			o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
  2535  		}
  2536  
  2537  	case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
  2538  		v := int32(p.From.Offset)
  2539  
  2540  		if v < -256 || v > 255 {
  2541  			c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  2542  		}
  2543  		o1 = c.opldrpp(p, p.As)
  2544  		if o.scond == C_XPOST {
  2545  			o1 |= 1 << 10
  2546  		} else {
  2547  			o1 |= 3 << 10
  2548  		}
  2549  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
  2550  
  2551  	case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
  2552  		v := int32(p.To.Offset)
  2553  
  2554  		if v < -256 || v > 255 {
  2555  			c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  2556  		}
  2557  		o1 = LD2STR(c.opldrpp(p, p.As))
  2558  		if o.scond == C_XPOST {
  2559  			o1 |= 1 << 10
  2560  		} else {
  2561  			o1 |= 3 << 10
  2562  		}
  2563  		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
  2564  
  2565  	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
  2566  		rf := int(p.From.Reg)
  2567  		rt := int(p.To.Reg)
  2568  		s := rf == REGSP || rt == REGSP
  2569  		if p.As == AMVN || p.As == AMVNW {
  2570  			if s {
  2571  				c.ctxt.Diag("illegal SP reference\n%v", p)
  2572  			}
  2573  			o1 = c.oprrr(p, p.As)
  2574  			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  2575  		} else if s {
  2576  			o1 = c.opirr(p, p.As)
  2577  			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  2578  		} else {
  2579  			o1 = c.oprrr(p, p.As)
  2580  			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  2581  		}
  2582  
  2583  	case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
  2584  		o1 = c.oprrr(p, p.As)
  2585  
  2586  		rf := int(p.From.Reg)
  2587  		if rf == C_NONE {
  2588  			rf = int(p.To.Reg)
  2589  		}
  2590  		rt := int(p.To.Reg)
  2591  		o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  2592  
  2593  	case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
  2594  		o1 = c.oprrr(p, p.As)
  2595  
  2596  		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  2597  		rt := int(p.To.Reg)
  2598  		o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
  2599  
  2600  	case 27: /* op Rm<<n[,Rn],Rd (extended register) */
  2601  
  2602  		if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
  2603  			amount := (p.From.Reg >> 5) & 7
  2604  			if amount > 4 {
  2605  				c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
  2606  			}
  2607  			o1 = c.opxrrr(p, p.As, true)
  2608  			o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  2609  		} else {
  2610  			o1 = c.opxrrr(p, p.As, false)
  2611  			o1 |= uint32(p.From.Reg&31) << 16
  2612  		}
  2613  		rt := int(p.To.Reg)
  2614  		if p.To.Type == obj.TYPE_NONE {
  2615  			rt = REGZERO
  2616  		}
  2617  		r := int(p.Reg)
  2618  		if r == 0 {
  2619  			r = rt
  2620  		}
  2621  		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  2622  
  2623  	case 28: /* logop $vcon, [R], R (64 bit literal) */
  2624  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  2625  
  2626  		if !(o1 != 0) {
  2627  			break
  2628  		}
  2629  		r := int(p.Reg)
  2630  		if r == 0 {
  2631  			r = int(p.To.Reg)
  2632  		}
  2633  		o2 = c.oprrr(p, p.As)
  2634  		o2 |= REGTMP & 31 << 16 /* shift is 0 */
  2635  		o2 |= uint32(r&31) << 5
  2636  		o2 |= uint32(p.To.Reg & 31)
  2637  
  2638  	case 29: /* op Rn, Rd */
  2639  		fc := c.aclass(&p.From)
  2640  		tc := c.aclass(&p.To)
  2641  		if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
  2642  			// FMOV Rx, Fy or FMOV Fy, Rx
  2643  			o1 = FPCVTI(0, 0, 0, 0, 6)
  2644  			if p.As == AFMOVD {
  2645  				o1 |= 1<<31 | 1<<22 // 64-bit
  2646  			}
  2647  			if fc == C_REG || fc == C_ZCON {
  2648  				o1 |= 1 << 16 // FMOV Rx, Fy
  2649  			}
  2650  		} else {
  2651  			o1 = c.oprrr(p, p.As)
  2652  		}
  2653  		o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
  2654  
  2655  	case 30: /* movT R,L(R) -> strT */
  2656  		// if offset L can be split into hi+lo, and both fit into instructions, do
  2657  		//	add $hi, R, Rtmp
  2658  		//	str R, lo(Rtmp)
  2659  		// otherwise, use constant pool
  2660  		//	mov $L, Rtmp (from constant pool)
  2661  		//	str R, (R+Rtmp)
  2662  		s := movesize(o.as)
  2663  		if s < 0 {
  2664  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  2665  		}
  2666  
  2667  		r := int(p.To.Reg)
  2668  		if r == 0 {
  2669  			r = int(o.param)
  2670  		}
  2671  
  2672  		v := int32(c.regoff(&p.To))
  2673  		var hi int32
  2674  		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  2675  			// negative or unaligned offset, use constant pool
  2676  			goto storeusepool
  2677  		}
  2678  
  2679  		hi = v - (v & (0xFFF << uint(s)))
  2680  		if hi&0xFFF != 0 {
  2681  			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  2682  		}
  2683  		if hi&^0xFFF000 != 0 {
  2684  			// hi doesn't fit into an ADD instruction
  2685  			goto storeusepool
  2686  		}
  2687  
  2688  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  2689  		o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
  2690  		break
  2691  
  2692  	storeusepool:
  2693  		if r == REGTMP || p.From.Reg == REGTMP {
  2694  			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  2695  		}
  2696  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  2697  		o2 = c.olsxrr(p, int32(c.opstrr(p, p.As)), int(p.From.Reg), r, REGTMP)
  2698  
  2699  	case 31: /* movT L(R), R -> ldrT */
  2700  		// if offset L can be split into hi+lo, and both fit into instructions, do
  2701  		//	add $hi, R, Rtmp
  2702  		//	ldr lo(Rtmp), R
  2703  		// otherwise, use constant pool
  2704  		//	mov $L, Rtmp (from constant pool)
  2705  		//	ldr (R+Rtmp), R
  2706  		s := movesize(o.as)
  2707  		if s < 0 {
  2708  			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  2709  		}
  2710  
  2711  		r := int(p.From.Reg)
  2712  		if r == 0 {
  2713  			r = int(o.param)
  2714  		}
  2715  
  2716  		v := int32(c.regoff(&p.From))
  2717  		var hi int32
  2718  		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  2719  			// negative or unaligned offset, use constant pool
  2720  			goto loadusepool
  2721  		}
  2722  
  2723  		hi = v - (v & (0xFFF << uint(s)))
  2724  		if (hi & 0xFFF) != 0 {
  2725  			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  2726  		}
  2727  		if hi&^0xFFF000 != 0 {
  2728  			// hi doesn't fit into an ADD instruction
  2729  			goto loadusepool
  2730  		}
  2731  
  2732  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  2733  		o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
  2734  		break
  2735  
  2736  	loadusepool:
  2737  		if r == REGTMP || p.From.Reg == REGTMP {
  2738  			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  2739  		}
  2740  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  2741  		o2 = c.olsxrr(p, int32(c.opldrr(p, p.As)), int(p.To.Reg), r, REGTMP)
  2742  
  2743  	case 32: /* mov $con, R -> movz/movn */
  2744  		o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
  2745  
  2746  	case 33: /* movk $uimm16 << pos */
  2747  		o1 = c.opirr(p, p.As)
  2748  
  2749  		d := p.From.Offset
  2750  		s := movcon(d)
  2751  		if s < 0 || s >= 4 {
  2752  			c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
  2753  		}
  2754  		if (o1&S64) == 0 && s >= 2 {
  2755  			c.ctxt.Diag("illegal bit position\n%v", p)
  2756  		}
  2757  		if ((d >> uint(s*16)) >> 16) != 0 {
  2758  			c.ctxt.Diag("requires uimm16\n%v", p)
  2759  		}
  2760  		rt := int(p.To.Reg)
  2761  
  2762  		o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
  2763  
  2764  	case 34: /* mov $lacon,R */
  2765  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  2766  
  2767  		if !(o1 != 0) {
  2768  			break
  2769  		}
  2770  		o2 = c.opxrrr(p, AADD, false)
  2771  		o2 |= REGTMP & 31 << 16
  2772  		o2 |= LSL0_64
  2773  		r := int(p.From.Reg)
  2774  		if r == 0 {
  2775  			r = int(o.param)
  2776  		}
  2777  		o2 |= uint32(r&31) << 5
  2778  		o2 |= uint32(p.To.Reg & 31)
  2779  
  2780  	case 35: /* mov SPR,R -> mrs */
  2781  		o1 = c.oprrr(p, AMRS)
  2782  
  2783  		v := uint32(0)
  2784  		for i := 0; i < len(systemreg); i++ {
  2785  			if systemreg[i].reg == p.From.Reg {
  2786  				v = systemreg[i].enc
  2787  				break
  2788  			}
  2789  		}
  2790  		if v == 0 {
  2791  			c.ctxt.Diag("illegal system register:\n%v", p)
  2792  		}
  2793  		if (o1 & uint32(v&^(3<<19))) != 0 {
  2794  			c.ctxt.Diag("MRS register value overlap\n%v", p)
  2795  		}
  2796  
  2797  		o1 |= v
  2798  		o1 |= uint32(p.To.Reg & 31)
  2799  
  2800  	case 36: /* mov R,SPR */
  2801  		o1 = c.oprrr(p, AMSR)
  2802  
  2803  		v := uint32(0)
  2804  		for i := 0; i < len(systemreg); i++ {
  2805  			if systemreg[i].reg == p.To.Reg {
  2806  				v = systemreg[i].enc
  2807  				break
  2808  			}
  2809  		}
  2810  		if v == 0 {
  2811  			c.ctxt.Diag("illegal system register:\n%v", p)
  2812  		}
  2813  		if (o1 & uint32(v&^(3<<19))) != 0 {
  2814  			c.ctxt.Diag("MSR register value overlap\n%v", p)
  2815  		}
  2816  
  2817  		o1 |= v
  2818  		o1 |= uint32(p.From.Reg & 31)
  2819  
  2820  	case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
  2821  		if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
  2822  			c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
  2823  		}
  2824  		o1 = c.opirr(p, AMSR)
  2825  		o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
  2826  		v := uint32(0)
  2827  		for i := 0; i < len(pstatefield); i++ {
  2828  			if pstatefield[i].reg == p.To.Reg {
  2829  				v = pstatefield[i].enc
  2830  				break
  2831  			}
  2832  		}
  2833  
  2834  		if v == 0 {
  2835  			c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
  2836  		}
  2837  		o1 |= v
  2838  
  2839  	case 38: /* clrex [$imm] */
  2840  		o1 = c.opimm(p, p.As)
  2841  
  2842  		if p.To.Type == obj.TYPE_NONE {
  2843  			o1 |= 0xF << 8
  2844  		} else {
  2845  			o1 |= uint32((p.To.Offset & 0xF) << 8)
  2846  		}
  2847  
  2848  	case 39: /* cbz R, rel */
  2849  		o1 = c.opirr(p, p.As)
  2850  
  2851  		o1 |= uint32(p.From.Reg & 31)
  2852  		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  2853  
  2854  	case 40: /* tbz */
  2855  		o1 = c.opirr(p, p.As)
  2856  
  2857  		v := int32(p.From.Offset)
  2858  		if v < 0 || v > 63 {
  2859  			c.ctxt.Diag("illegal bit number\n%v", p)
  2860  		}
  2861  		o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
  2862  		o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
  2863  		o1 |= uint32(p.Reg & 31)
  2864  
  2865  	case 41: /* eret, nop, others with no operands */
  2866  		o1 = c.op0(p, p.As)
  2867  
  2868  	case 42: /* bfm R,r,s,R */
  2869  		o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
  2870  
  2871  	case 43: /* bfm aliases */
  2872  		r := int(p.From.Offset)
  2873  
  2874  		s := int(p.GetFrom3().Offset)
  2875  		rf := int(p.Reg)
  2876  		rt := int(p.To.Reg)
  2877  		if rf == 0 {
  2878  			rf = rt
  2879  		}
  2880  		switch p.As {
  2881  		case ABFI:
  2882  			o1 = c.opbfm(p, ABFM, 64-r, s-1, rf, rt)
  2883  
  2884  		case ABFIW:
  2885  			o1 = c.opbfm(p, ABFMW, 32-r, s-1, rf, rt)
  2886  
  2887  		case ABFXIL:
  2888  			o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
  2889  
  2890  		case ABFXILW:
  2891  			o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
  2892  
  2893  		case ASBFIZ:
  2894  			o1 = c.opbfm(p, ASBFM, 64-r, s-1, rf, rt)
  2895  
  2896  		case ASBFIZW:
  2897  			o1 = c.opbfm(p, ASBFMW, 32-r, s-1, rf, rt)
  2898  
  2899  		case ASBFX:
  2900  			o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
  2901  
  2902  		case ASBFXW:
  2903  			o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
  2904  
  2905  		case AUBFIZ:
  2906  			o1 = c.opbfm(p, AUBFM, 64-r, s-1, rf, rt)
  2907  
  2908  		case AUBFIZW:
  2909  			o1 = c.opbfm(p, AUBFMW, 32-r, s-1, rf, rt)
  2910  
  2911  		case AUBFX:
  2912  			o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
  2913  
  2914  		case AUBFXW:
  2915  			o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
  2916  
  2917  		default:
  2918  			c.ctxt.Diag("bad bfm alias\n%v", p)
  2919  			break
  2920  		}
  2921  
  2922  	case 44: /* extr $b, Rn, Rm, Rd */
  2923  		o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
  2924  
  2925  	case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
  2926  		rf := int(p.From.Reg)
  2927  
  2928  		rt := int(p.To.Reg)
  2929  		as := p.As
  2930  		if rf == REGZERO {
  2931  			as = AMOVWU /* clearer in disassembly */
  2932  		}
  2933  		switch as {
  2934  		case AMOVB, ASXTB:
  2935  			o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
  2936  
  2937  		case AMOVH, ASXTH:
  2938  			o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
  2939  
  2940  		case AMOVW, ASXTW:
  2941  			o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
  2942  
  2943  		case AMOVBU, AUXTB:
  2944  			o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
  2945  
  2946  		case AMOVHU, AUXTH:
  2947  			o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
  2948  
  2949  		case AMOVWU:
  2950  			o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  2951  
  2952  		case AUXTW:
  2953  			o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
  2954  
  2955  		case ASXTBW:
  2956  			o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
  2957  
  2958  		case ASXTHW:
  2959  			o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
  2960  
  2961  		case AUXTBW:
  2962  			o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
  2963  
  2964  		case AUXTHW:
  2965  			o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
  2966  
  2967  		default:
  2968  			c.ctxt.Diag("bad sxt %v", as)
  2969  			break
  2970  		}
  2971  
  2972  	case 46: /* cls */
  2973  		o1 = c.opbit(p, p.As)
  2974  
  2975  		o1 |= uint32(p.From.Reg&31) << 5
  2976  		o1 |= uint32(p.To.Reg & 31)
  2977  
  2978  	case 50: /* sys/sysl */
  2979  		o1 = c.opirr(p, p.As)
  2980  
  2981  		if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
  2982  			c.ctxt.Diag("illegal SYS argument\n%v", p)
  2983  		}
  2984  		o1 |= uint32(p.From.Offset)
  2985  		if p.To.Type == obj.TYPE_REG {
  2986  			o1 |= uint32(p.To.Reg & 31)
  2987  		} else if p.Reg != 0 {
  2988  			o1 |= uint32(p.Reg & 31)
  2989  		} else {
  2990  			o1 |= 0x1F
  2991  		}
  2992  
  2993  	case 51: /* dmb */
  2994  		o1 = c.opirr(p, p.As)
  2995  
  2996  		if p.From.Type == obj.TYPE_CONST {
  2997  			o1 |= uint32((p.From.Offset & 0xF) << 8)
  2998  		}
  2999  
  3000  	case 52: /* hint */
  3001  		o1 = c.opirr(p, p.As)
  3002  
  3003  		o1 |= uint32((p.From.Offset & 0x7F) << 5)
  3004  
  3005  	case 53: /* and/or/eor/bic/... $bitcon, Rn, Rd */
  3006  		a := p.As
  3007  		rt := int(p.To.Reg)
  3008  		r := int(p.Reg)
  3009  		if r == 0 {
  3010  			r = rt
  3011  		}
  3012  		mode := 64
  3013  		v := uint64(p.From.Offset)
  3014  		switch p.As {
  3015  		case AANDW, AORRW, AEORW, AANDSW:
  3016  			mode = 32
  3017  		case ABIC, AORN, AEON, ABICS:
  3018  			v = ^v
  3019  		case ABICW, AORNW, AEONW, ABICSW:
  3020  			v = ^v
  3021  			mode = 32
  3022  		}
  3023  		o1 = c.opirr(p, a)
  3024  		o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
  3025  
  3026  	case 54: /* floating point arith */
  3027  		o1 = c.oprrr(p, p.As)
  3028  
  3029  		var rf int
  3030  		if p.From.Type == obj.TYPE_CONST {
  3031  			rf = c.chipfloat7(p.From.Val.(float64))
  3032  			if rf < 0 || true {
  3033  				c.ctxt.Diag("invalid floating-point immediate\n%v", p)
  3034  				rf = 0
  3035  			}
  3036  
  3037  			rf |= (1 << 3)
  3038  		} else {
  3039  			rf = int(p.From.Reg)
  3040  		}
  3041  		rt := int(p.To.Reg)
  3042  		r := int(p.Reg)
  3043  		if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
  3044  			r = rf
  3045  			rf = 0
  3046  		} else if r == 0 {
  3047  			r = rt
  3048  		}
  3049  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3050  
  3051  	case 56: /* floating point compare */
  3052  		o1 = c.oprrr(p, p.As)
  3053  
  3054  		var rf int
  3055  		if p.From.Type == obj.TYPE_FCONST {
  3056  			o1 |= 8 /* zero */
  3057  			rf = 0
  3058  		} else {
  3059  			rf = int(p.From.Reg)
  3060  		}
  3061  		rt := int(p.Reg)
  3062  		o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
  3063  
  3064  	case 57: /* floating point conditional compare */
  3065  		o1 = c.oprrr(p, p.As)
  3066  
  3067  		cond := int(p.From.Reg)
  3068  		if cond < COND_EQ || cond > COND_NV {
  3069  			c.ctxt.Diag("invalid condition\n%v", p)
  3070  		} else {
  3071  			cond -= COND_EQ
  3072  		}
  3073  
  3074  		nzcv := int(p.To.Offset)
  3075  		if nzcv&^0xF != 0 {
  3076  			c.ctxt.Diag("implausible condition\n%v", p)
  3077  		}
  3078  		rf := int(p.Reg)
  3079  		if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
  3080  			c.ctxt.Diag("illegal FCCMP\n%v", p)
  3081  			break
  3082  		}
  3083  		rt := int(p.GetFrom3().Reg)
  3084  		o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
  3085  
  3086  	case 58: /* ldar/ldxr/ldaxr */
  3087  		o1 = c.opload(p, p.As)
  3088  
  3089  		o1 |= 0x1F << 16
  3090  		o1 |= uint32(p.From.Reg&31) << 5
  3091  		if p.Reg != 0 {
  3092  			o1 |= uint32(p.Reg&31) << 10
  3093  		} else {
  3094  			o1 |= 0x1F << 10
  3095  		}
  3096  		o1 |= uint32(p.To.Reg & 31)
  3097  
  3098  	case 59: /* stxr/stlxr */
  3099  		o1 = c.opstore(p, p.As)
  3100  
  3101  		if p.RegTo2 != obj.REG_NONE {
  3102  			o1 |= uint32(p.RegTo2&31) << 16
  3103  		} else {
  3104  			o1 |= 0x1F << 16
  3105  		}
  3106  
  3107  		// TODO(aram): add support for STXP
  3108  		o1 |= uint32(p.To.Reg&31) << 5
  3109  
  3110  		o1 |= uint32(p.From.Reg & 31)
  3111  
  3112  	case 60: /* adrp label,r */
  3113  		d := c.brdist(p, 12, 21, 0)
  3114  
  3115  		o1 = ADR(1, uint32(d), uint32(p.To.Reg))
  3116  
  3117  	case 61: /* adr label, r */
  3118  		d := c.brdist(p, 0, 21, 0)
  3119  
  3120  		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
  3121  
  3122  	case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
  3123  		if p.Reg == REGTMP {
  3124  			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  3125  		}
  3126  		o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
  3127  
  3128  		rt := int(p.To.Reg)
  3129  		if p.To.Type == obj.TYPE_NONE {
  3130  			rt = REGZERO
  3131  		}
  3132  		r := int(p.Reg)
  3133  		if r == 0 {
  3134  			r = rt
  3135  		}
  3136  		if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
  3137  			o2 = c.opxrrr(p, p.As, false)
  3138  			o2 |= REGTMP & 31 << 16
  3139  			o2 |= LSL0_64
  3140  		} else {
  3141  			o2 = c.oprrr(p, p.As)
  3142  			o2 |= REGTMP & 31 << 16 /* shift is 0 */
  3143  		}
  3144  		o2 |= uint32(r&31) << 5
  3145  		o2 |= uint32(rt & 31)
  3146  
  3147  		/* reloc ops */
  3148  	case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
  3149  		o1 = ADR(1, 0, REGTMP)
  3150  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3151  		rel := obj.Addrel(c.cursym)
  3152  		rel.Off = int32(c.pc)
  3153  		rel.Siz = 8
  3154  		rel.Sym = p.To.Sym
  3155  		rel.Add = p.To.Offset
  3156  		rel.Type = objabi.R_ADDRARM64
  3157  		o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
  3158  
  3159  	case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
  3160  		o1 = ADR(1, 0, REGTMP)
  3161  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3162  		rel := obj.Addrel(c.cursym)
  3163  		rel.Off = int32(c.pc)
  3164  		rel.Siz = 8
  3165  		rel.Sym = p.From.Sym
  3166  		rel.Add = p.From.Offset
  3167  		rel.Type = objabi.R_ADDRARM64
  3168  		o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
  3169  
  3170  	case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
  3171  		v := int32(c.regoff(&p.From))
  3172  		r := int(p.From.Reg)
  3173  		if r == obj.REG_NONE {
  3174  			r = int(o.param)
  3175  		}
  3176  		if r == obj.REG_NONE {
  3177  			c.ctxt.Diag("invalid ldp source: %v\n", p)
  3178  		}
  3179  
  3180  		if v < -512 || v > 504 || v%8 != 0 {
  3181  			c.ctxt.Diag("invalid offset %v\n", p)
  3182  		}
  3183  		if o.scond == C_XPOST {
  3184  			o1 |= 1 << 23
  3185  		} else if o.scond == C_XPRE {
  3186  			o1 |= 3 << 23
  3187  		} else {
  3188  			o1 |= 2 << 23
  3189  		}
  3190  		o1 |= 1 << 22
  3191  		o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | (p.To.Offset&31)<<10 | int64(uint32(r&31)<<5) | int64(p.To.Reg&31))
  3192  
  3193  	case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
  3194  		r := int(p.To.Reg)
  3195  		if r == obj.REG_NONE {
  3196  			r = int(o.param)
  3197  		}
  3198  		if r == obj.REG_NONE {
  3199  			c.ctxt.Diag("invalid stp destination: %v\n", p)
  3200  		}
  3201  
  3202  		v := int32(c.regoff(&p.To))
  3203  		if v < -512 || v > 504 || v%8 != 0 {
  3204  			c.ctxt.Diag("invalid offset %v\n", p)
  3205  		}
  3206  
  3207  		if o.scond == C_XPOST {
  3208  			o1 |= 1 << 23
  3209  		} else if o.scond == C_XPRE {
  3210  			o1 |= 3 << 23
  3211  		} else {
  3212  			o1 |= 2 << 23
  3213  		}
  3214  		o1 |= uint32(int64(2<<30|5<<27|((uint32(v)/8)&0x7f)<<15) | (p.From.Offset&31)<<10 | int64(uint32(r&31)<<5) | int64(p.From.Reg&31))
  3215  
  3216  	case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
  3217  		if p.As == AMOVW {
  3218  			c.ctxt.Diag("invalid load of 32-bit address: %v", p)
  3219  		}
  3220  		o1 = ADR(1, 0, uint32(p.To.Reg))
  3221  		o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
  3222  		rel := obj.Addrel(c.cursym)
  3223  		rel.Off = int32(c.pc)
  3224  		rel.Siz = 8
  3225  		rel.Sym = p.From.Sym
  3226  		rel.Add = p.From.Offset
  3227  		rel.Type = objabi.R_ADDRARM64
  3228  
  3229  	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
  3230  		o1 = c.opirr(p, AMOVZ)
  3231  		o1 |= uint32(p.To.Reg & 31)
  3232  		rel := obj.Addrel(c.cursym)
  3233  		rel.Off = int32(c.pc)
  3234  		rel.Siz = 4
  3235  		rel.Sym = p.From.Sym
  3236  		rel.Type = objabi.R_ARM64_TLS_LE
  3237  		if p.From.Offset != 0 {
  3238  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  3239  		}
  3240  
  3241  	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
  3242  		o1 = ADR(1, 0, REGTMP)
  3243  		o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  3244  		rel := obj.Addrel(c.cursym)
  3245  		rel.Off = int32(c.pc)
  3246  		rel.Siz = 8
  3247  		rel.Sym = p.From.Sym
  3248  		rel.Add = 0
  3249  		rel.Type = objabi.R_ARM64_TLS_IE
  3250  		if p.From.Offset != 0 {
  3251  			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  3252  		}
  3253  
  3254  	case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
  3255  		o1 = ADR(1, 0, REGTMP)
  3256  		o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  3257  		rel := obj.Addrel(c.cursym)
  3258  		rel.Off = int32(c.pc)
  3259  		rel.Siz = 8
  3260  		rel.Sym = p.From.Sym
  3261  		rel.Add = 0
  3262  		rel.Type = objabi.R_ARM64_GOTPCREL
  3263  
  3264  	case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor Vm.<T>, Vn.<T>, Vd.<T> */
  3265  		af := int((p.From.Reg >> 5) & 15)
  3266  		af3 := int((p.Reg >> 5) & 15)
  3267  		at := int((p.To.Reg >> 5) & 15)
  3268  		if af != af3 || af != at {
  3269  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3270  		}
  3271  		o1 = c.oprrr(p, p.As)
  3272  		rf := int((p.From.Reg) & 31)
  3273  		rt := int((p.To.Reg) & 31)
  3274  		r := int((p.Reg) & 31)
  3275  
  3276  		Q := 0
  3277  		size := 0
  3278  		switch af {
  3279  		case ARNG_16B:
  3280  			Q = 1
  3281  			size = 0
  3282  		case ARNG_2D:
  3283  			Q = 1
  3284  			size = 3
  3285  		case ARNG_2S:
  3286  			Q = 0
  3287  			size = 2
  3288  		case ARNG_4H:
  3289  			Q = 0
  3290  			size = 1
  3291  		case ARNG_4S:
  3292  			Q = 1
  3293  			size = 2
  3294  		case ARNG_8B:
  3295  			Q = 0
  3296  			size = 0
  3297  		case ARNG_8H:
  3298  			Q = 1
  3299  			size = 1
  3300  		default:
  3301  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3302  		}
  3303  
  3304  		if (p.As == AVORR || p.As == AVAND || p.As == AVEOR) &&
  3305  			(af != ARNG_16B && af != ARNG_8B) {
  3306  			c.ctxt.Diag("invalid arrangement on op %v", p.As)
  3307  		} else if p.As == AVORR {
  3308  			size = 2
  3309  		} else if p.As == AVAND || p.As == AVEOR {
  3310  			size = 0
  3311  		}
  3312  
  3313  		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3314  
  3315  	case 73: /* vmov V.<T>[index], R */
  3316  		rf := int(p.From.Reg)
  3317  		rt := int(p.To.Reg)
  3318  		imm5 := 0
  3319  		o1 = 7<<25 | 0xf<<10
  3320  		switch (p.From.Reg >> 5) & 15 {
  3321  		case ARNG_B:
  3322  			imm5 |= 1
  3323  			imm5 |= int(p.From.Index) << 1
  3324  		case ARNG_H:
  3325  			imm5 |= 2
  3326  			imm5 |= int(p.From.Index) << 2
  3327  		case ARNG_S:
  3328  			imm5 |= 4
  3329  			imm5 |= int(p.From.Index) << 3
  3330  		case ARNG_D:
  3331  			imm5 |= 8
  3332  			imm5 |= int(p.From.Index) << 4
  3333  			o1 |= 1 << 30
  3334  		default:
  3335  			c.ctxt.Diag("invalid arrangement on op V.<T>[index], R: %v\n", p)
  3336  		}
  3337  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3338  
  3339  	case 74:
  3340  		//	add $O, R, Rtmp
  3341  		//	ldp (Rtmp), (R1, R2)
  3342  		r := int(p.From.Reg)
  3343  		if r == obj.REG_NONE {
  3344  			r = int(o.param)
  3345  		}
  3346  		if r == obj.REG_NONE {
  3347  			c.ctxt.Diag("invalid ldp source: %v\n", p)
  3348  		}
  3349  
  3350  		v := int32(c.regoff(&p.From))
  3351  		if v < 0 || v > 4095 {
  3352  			c.ctxt.Diag("offset out of range%v\n", p)
  3353  		}
  3354  
  3355  		if o.scond == C_XPOST {
  3356  			o2 |= 1 << 23
  3357  		} else if o.scond == C_XPRE {
  3358  			o2 |= 3 << 23
  3359  		} else {
  3360  			o2 |= 2 << 23
  3361  		}
  3362  
  3363  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  3364  		o2 |= 1 << 22
  3365  		o2 |= uint32(int64(2<<30|5<<27) | (p.To.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.To.Reg&31))
  3366  
  3367  	case 75:
  3368  		//	mov $L, Rtmp (from constant pool)
  3369  		//	add Rtmp, R, Rtmp
  3370  		//	ldp (Rtmp), (R1, R2)
  3371  		r := int(p.From.Reg)
  3372  		if r == obj.REG_NONE {
  3373  			r = int(o.param)
  3374  		}
  3375  		if r == obj.REG_NONE {
  3376  			c.ctxt.Diag("invalid ldp source: %v\n", p)
  3377  		}
  3378  
  3379  		if o.scond == C_XPOST {
  3380  			o3 |= 1 << 23
  3381  		} else if o.scond == C_XPRE {
  3382  			o3 |= 3 << 23
  3383  		} else {
  3384  			o3 |= 2 << 23
  3385  		}
  3386  
  3387  		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3388  		o2 = c.opxrrr(p, AADD, false)
  3389  		o2 |= (REGTMP & 31) << 16
  3390  		o2 |= uint32(r&31) << 5
  3391  		o2 |= uint32(REGTMP & 31)
  3392  		o3 |= 1 << 22
  3393  		o3 |= uint32(int64(2<<30|5<<27) | (p.To.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.To.Reg&31))
  3394  
  3395  	case 76:
  3396  		//	add $O, R, Rtmp
  3397  		//	stp (R1, R2), (Rtmp)
  3398  		r := int(p.To.Reg)
  3399  		if r == obj.REG_NONE {
  3400  			r = int(o.param)
  3401  		}
  3402  		if r == obj.REG_NONE {
  3403  			c.ctxt.Diag("invalid stp destination: %v\n", p)
  3404  		}
  3405  
  3406  		v := int32(c.regoff(&p.To))
  3407  		if v < 0 || v > 4095 {
  3408  			c.ctxt.Diag("offset out of range%v\n", p)
  3409  		}
  3410  		if o.scond == C_XPOST {
  3411  			o2 |= 1 << 23
  3412  		} else if o.scond == C_XPRE {
  3413  			o2 |= 3 << 23
  3414  		} else {
  3415  			o2 |= 2 << 23
  3416  		}
  3417  
  3418  		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  3419  		o2 |= uint32(int64(2<<30|5<<27) | (p.From.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.From.Reg&31))
  3420  
  3421  	case 77:
  3422  		//	mov $L, Rtmp (from constant pool)
  3423  		//	add Rtmp, R, Rtmp
  3424  		//	stp (R1, R2), (Rtmp)
  3425  		r := int(p.To.Reg)
  3426  		if r == obj.REG_NONE {
  3427  			r = int(o.param)
  3428  		}
  3429  		if r == obj.REG_NONE {
  3430  			c.ctxt.Diag("invalid stp destination: %v\n", p)
  3431  		}
  3432  
  3433  		if o.scond == C_XPOST {
  3434  			o3 |= 1 << 23
  3435  		} else if o.scond == C_XPRE {
  3436  			o3 |= 3 << 23
  3437  		} else {
  3438  			o3 |= 2 << 23
  3439  		}
  3440  		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  3441  		o2 = c.opxrrr(p, AADD, false)
  3442  		o2 |= REGTMP & 31 << 16
  3443  		o2 |= uint32(r&31) << 5
  3444  		o2 |= uint32(REGTMP & 31)
  3445  		o3 |= uint32(int64(2<<30|5<<27) | (p.From.Offset&31)<<10 | int64(uint32(REGTMP&31)<<5) | int64(p.From.Reg&31))
  3446  
  3447  	case 78: /* vmov R, V.<T>[index] */
  3448  		rf := int(p.From.Reg)
  3449  		rt := int(p.To.Reg)
  3450  		imm5 := 0
  3451  		o1 = 1<<30 | 7<<25 | 7<<10
  3452  		switch (p.To.Reg >> 5) & 15 {
  3453  		case ARNG_B:
  3454  			imm5 |= 1
  3455  			imm5 |= int(p.From.Index) << 1
  3456  		case ARNG_H:
  3457  			imm5 |= 2
  3458  			imm5 |= int(p.From.Index) << 2
  3459  		case ARNG_S:
  3460  			imm5 |= 4
  3461  			imm5 |= int(p.From.Index) << 3
  3462  		case ARNG_D:
  3463  			imm5 |= 8
  3464  			imm5 |= int(p.From.Index) << 4
  3465  		default:
  3466  			c.ctxt.Diag("invalid arrangement on op R, V.<T>[index]: %v\n", p)
  3467  		}
  3468  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3469  
  3470  	case 79: /* vdup Vn.<T>[index], Vd.<T> */
  3471  		rf := int(p.From.Reg)
  3472  		rt := int(p.To.Reg)
  3473  		o1 = 7<<25 | 1<<10
  3474  		var imm5, Q uint32
  3475  		switch (p.To.Reg >> 5) & 15 {
  3476  		case ARNG_16B:
  3477  			Q = 1
  3478  			imm5 = 1
  3479  			imm5 |= uint32(p.From.Index) << 1
  3480  		case ARNG_2D:
  3481  			Q = 1
  3482  			imm5 = 8
  3483  			imm5 |= uint32(p.From.Index) << 4
  3484  		case ARNG_2S:
  3485  			Q = 0
  3486  			imm5 = 4
  3487  			imm5 |= uint32(p.From.Index) << 3
  3488  		case ARNG_4H:
  3489  			Q = 0
  3490  			imm5 = 2
  3491  			imm5 |= uint32(p.From.Index) << 2
  3492  		case ARNG_4S:
  3493  			Q = 1
  3494  			imm5 = 4
  3495  			imm5 |= uint32(p.From.Index) << 3
  3496  		case ARNG_8B:
  3497  			Q = 0
  3498  			imm5 = 1
  3499  			imm5 |= uint32(p.From.Index) << 1
  3500  		case ARNG_8H:
  3501  			Q = 1
  3502  			imm5 = 2
  3503  			imm5 |= uint32(p.From.Index) << 2
  3504  		default:
  3505  			c.ctxt.Diag("invalid arrangement on VDUP Vn.<T>[index], Vd.<T>: %v\n", p)
  3506  		}
  3507  		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  3508  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3509  
  3510  	case 80: /* vmov V.<T>[index], Vn */
  3511  		rf := int(p.From.Reg)
  3512  		rt := int(p.To.Reg)
  3513  		imm5 := 0
  3514  		switch p.As {
  3515  		case AVMOV:
  3516  			o1 = 1<<30 | 15<<25 | 1<<10
  3517  			switch (p.From.Reg >> 5) & 15 {
  3518  			case ARNG_B:
  3519  				imm5 |= 1
  3520  				imm5 |= int(p.From.Index) << 1
  3521  			case ARNG_H:
  3522  				imm5 |= 2
  3523  				imm5 |= int(p.From.Index) << 2
  3524  			case ARNG_S:
  3525  				imm5 |= 4
  3526  				imm5 |= int(p.From.Index) << 3
  3527  			case ARNG_D:
  3528  				imm5 |= 8
  3529  				imm5 |= int(p.From.Index) << 4
  3530  			default:
  3531  				c.ctxt.Diag("invalid arrangement on op V.<T>[index], Vn: %v\n", p)
  3532  			}
  3533  		default:
  3534  			c.ctxt.Diag("unsupported op %v", p.As)
  3535  		}
  3536  		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3537  
  3538  	case 81: /* vld1 (Rn), [Vt1.<T>, Vt2.<T>, ...] */
  3539  		r := int(p.From.Reg)
  3540  		o1 = 3<<26 | 1<<22
  3541  		if o.scond == C_XPOST {
  3542  			o1 |= 1 << 23
  3543  			if p.From.Index == 0 {
  3544  				// immediate offset variant
  3545  				o1 |= 0x1f << 16
  3546  			} else {
  3547  				// register offset variant
  3548  				o1 |= uint32(p.From.Index&31) << 16
  3549  			}
  3550  		}
  3551  		o1 |= uint32(p.To.Offset)
  3552  		o1 |= uint32(r&31) << 5
  3553  
  3554  	case 82: /* vmov Rn, Vd.<T> */
  3555  		rf := int(p.From.Reg)
  3556  		rt := int(p.To.Reg)
  3557  		o1 = 7<<25 | 3<<10
  3558  		var imm5, Q uint32
  3559  		switch (p.To.Reg >> 5) & 15 {
  3560  		case ARNG_16B:
  3561  			Q = 1
  3562  			imm5 = 1
  3563  		case ARNG_2D:
  3564  			Q = 1
  3565  			imm5 = 8
  3566  		case ARNG_2S:
  3567  			Q = 0
  3568  			imm5 = 4
  3569  		case ARNG_4H:
  3570  			Q = 0
  3571  			imm5 = 2
  3572  		case ARNG_4S:
  3573  			Q = 1
  3574  			imm5 = 4
  3575  		case ARNG_8B:
  3576  			Q = 0
  3577  			imm5 = 1
  3578  		case ARNG_8H:
  3579  			Q = 1
  3580  			imm5 = 2
  3581  		default:
  3582  			c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p)
  3583  		}
  3584  		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  3585  		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3586  
  3587  	case 83: /* vmov Vn.<T>, Vd.<T> */
  3588  		af := int((p.From.Reg >> 5) & 15)
  3589  		at := int((p.To.Reg >> 5) & 15)
  3590  		if af != at {
  3591  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3592  		}
  3593  		o1 = c.oprrr(p, p.As)
  3594  		rf := int((p.From.Reg) & 31)
  3595  		rt := int((p.To.Reg) & 31)
  3596  
  3597  		Q := 0
  3598  		size := 0
  3599  		switch af {
  3600  		case ARNG_8B:
  3601  			Q = 0
  3602  			size = 0
  3603  		case ARNG_16B:
  3604  			Q = 1
  3605  			size = 0
  3606  		case ARNG_4H:
  3607  			Q = 0
  3608  			size = 1
  3609  		case ARNG_8H:
  3610  			Q = 1
  3611  			size = 1
  3612  		default:
  3613  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3614  		}
  3615  
  3616  		if (p.As == AVMOV) && (af != ARNG_16B && af != ARNG_8B) {
  3617  			c.ctxt.Diag("invalid arrangement on op %v", p.As)
  3618  		}
  3619  
  3620  		if p.As == AVMOV {
  3621  			o1 |= uint32(rf&31) << 16
  3622  		}
  3623  
  3624  		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
  3625  
  3626  	case 84: /* vst1 [Vt1.<T>, Vt2.<T>, ...], (Rn) */
  3627  		r := int(p.To.Reg)
  3628  		o1 = 3 << 26
  3629  		if o.scond == C_XPOST {
  3630  			o1 |= 1 << 23
  3631  			if p.To.Index == 0 {
  3632  				// immediate offset variant
  3633  				o1 |= 0x1f << 16
  3634  			} else {
  3635  				// register offset variant
  3636  				o1 |= uint32(p.To.Index&31) << 16
  3637  			}
  3638  		}
  3639  		o1 |= uint32(p.From.Offset)
  3640  		o1 |= uint32(r&31) << 5
  3641  
  3642  	case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
  3643  		af := int((p.From.Reg >> 5) & 15)
  3644  		o1 = c.oprrr(p, p.As)
  3645  		rf := int((p.From.Reg) & 31)
  3646  		rt := int((p.To.Reg) & 31)
  3647  		Q := 0
  3648  		size := 0
  3649  		switch af {
  3650  		case ARNG_8B:
  3651  			Q = 0
  3652  			size = 0
  3653  		case ARNG_16B:
  3654  			Q = 1
  3655  			size = 0
  3656  		case ARNG_4H:
  3657  			Q = 0
  3658  			size = 1
  3659  		case ARNG_8H:
  3660  			Q = 1
  3661  			size = 1
  3662  		case ARNG_4S:
  3663  			Q = 1
  3664  			size = 2
  3665  		default:
  3666  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3667  		}
  3668  		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
  3669  
  3670  	case 86: /* vmovi $imm8, Vd.<T>*/
  3671  		at := int((p.To.Reg >> 5) & 15)
  3672  		r := int(p.From.Offset)
  3673  		if r > 255 || r < 0 {
  3674  			c.ctxt.Diag("immediate constant out of range: %v\n", p)
  3675  		}
  3676  		rt := int((p.To.Reg) & 31)
  3677  		Q := 0
  3678  		switch at {
  3679  		case ARNG_8B:
  3680  			Q = 0
  3681  		case ARNG_16B:
  3682  			Q = 1
  3683  		default:
  3684  			c.ctxt.Diag("invalid arrangement: %v\n", p)
  3685  		}
  3686  		o1 = 0xf<<24 | 0xe<<12 | 1<<10
  3687  		o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
  3688  
  3689  	case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
  3690  		o1 = ADR(1, 0, REGTMP)
  3691  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3692  		rel := obj.Addrel(c.cursym)
  3693  		rel.Off = int32(c.pc)
  3694  		rel.Siz = 8
  3695  		rel.Sym = p.To.Sym
  3696  		rel.Add = p.To.Offset
  3697  		rel.Type = objabi.R_ADDRARM64
  3698  		o3 |= 2<<30 | 5<<27 | 2<<23 | uint32(p.From.Offset&31)<<10 | (REGTMP&31)<<5 | uint32(p.From.Reg&31)
  3699  
  3700  	case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
  3701  		o1 = ADR(1, 0, REGTMP)
  3702  		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3703  		rel := obj.Addrel(c.cursym)
  3704  		rel.Off = int32(c.pc)
  3705  		rel.Siz = 8
  3706  		rel.Sym = p.From.Sym
  3707  		rel.Add = p.From.Offset
  3708  		rel.Type = objabi.R_ADDRARM64
  3709  		o3 |= 2<<30 | 5<<27 | 2<<23 | 1<<22 | uint32(p.To.Offset&31)<<10 | (REGTMP&31)<<5 | uint32(p.To.Reg&31)
  3710  
  3711  	case 89: /* vadd/vsub Vm, Vn, Vd */
  3712  		switch p.As {
  3713  		case AVADD:
  3714  			o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  3715  
  3716  		case AVSUB:
  3717  			o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  3718  
  3719  		default:
  3720  			c.ctxt.Diag("bad opcode: %v\n", p)
  3721  			break
  3722  		}
  3723  
  3724  		rf := int(p.From.Reg)
  3725  		rt := int(p.To.Reg)
  3726  		r := int(p.Reg)
  3727  		if r == 0 {
  3728  			r = rt
  3729  		}
  3730  		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3731  
  3732  	// This is supposed to be something that stops execution.
  3733  	// It's not supposed to be reached, ever, but if it is, we'd
  3734  	// like to be able to tell how we got there. Assemble as
  3735  	// 0xbea71700 which is guaranteed to raise undefined instruction
  3736  	// exception.
  3737  	case 90:
  3738  		o1 = 0xbea71700
  3739  
  3740  		break
  3741  	}
  3742  
  3743  	out[0] = o1
  3744  	out[1] = o2
  3745  	out[2] = o3
  3746  	out[3] = o4
  3747  	out[4] = o5
  3748  	return
  3749  }
  3750  
  3751  /*
  3752   * basic Rm op Rn -> Rd (using shifted register with 0)
  3753   * also op Rn -> Rt
  3754   * also Rm*Rn op Ra -> Rd
  3755   * also Vm op Vn -> Vd
  3756   */
  3757  func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
  3758  	switch a {
  3759  	case AADC:
  3760  		return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  3761  
  3762  	case AADCW:
  3763  		return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  3764  
  3765  	case AADCS:
  3766  		return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  3767  
  3768  	case AADCSW:
  3769  		return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  3770  
  3771  	case ANGC, ASBC:
  3772  		return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  3773  
  3774  	case ANGCS, ASBCS:
  3775  		return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  3776  
  3777  	case ANGCW, ASBCW:
  3778  		return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  3779  
  3780  	case ANGCSW, ASBCSW:
  3781  		return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  3782  
  3783  	case AADD:
  3784  		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3785  
  3786  	case AADDW:
  3787  		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3788  
  3789  	case ACMN, AADDS:
  3790  		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3791  
  3792  	case ACMNW, AADDSW:
  3793  		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3794  
  3795  	case ASUB:
  3796  		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3797  
  3798  	case ASUBW:
  3799  		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3800  
  3801  	case ACMP, ASUBS:
  3802  		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3803  
  3804  	case ACMPW, ASUBSW:
  3805  		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  3806  
  3807  	case AAND:
  3808  		return S64 | 0<<29 | 0xA<<24
  3809  
  3810  	case AANDW:
  3811  		return S32 | 0<<29 | 0xA<<24
  3812  
  3813  	case AMOVD, AORR:
  3814  		return S64 | 1<<29 | 0xA<<24
  3815  
  3816  		//	case AMOVW:
  3817  	case AMOVWU, AORRW:
  3818  		return S32 | 1<<29 | 0xA<<24
  3819  
  3820  	case AEOR:
  3821  		return S64 | 2<<29 | 0xA<<24
  3822  
  3823  	case AEORW:
  3824  		return S32 | 2<<29 | 0xA<<24
  3825  
  3826  	case AANDS:
  3827  		return S64 | 3<<29 | 0xA<<24
  3828  
  3829  	case AANDSW:
  3830  		return S32 | 3<<29 | 0xA<<24
  3831  
  3832  	case ABIC:
  3833  		return S64 | 0<<29 | 0xA<<24 | 1<<21
  3834  
  3835  	case ABICW:
  3836  		return S32 | 0<<29 | 0xA<<24 | 1<<21
  3837  
  3838  	case ABICS:
  3839  		return S64 | 3<<29 | 0xA<<24 | 1<<21
  3840  
  3841  	case ABICSW:
  3842  		return S32 | 3<<29 | 0xA<<24 | 1<<21
  3843  
  3844  	case AEON:
  3845  		return S64 | 2<<29 | 0xA<<24 | 1<<21
  3846  
  3847  	case AEONW:
  3848  		return S32 | 2<<29 | 0xA<<24 | 1<<21
  3849  
  3850  	case AMVN, AORN:
  3851  		return S64 | 1<<29 | 0xA<<24 | 1<<21
  3852  
  3853  	case AMVNW, AORNW:
  3854  		return S32 | 1<<29 | 0xA<<24 | 1<<21
  3855  
  3856  	case AASR:
  3857  		return S64 | OPDP2(10) /* also ASRV */
  3858  
  3859  	case AASRW:
  3860  		return S32 | OPDP2(10)
  3861  
  3862  	case ALSL:
  3863  		return S64 | OPDP2(8)
  3864  
  3865  	case ALSLW:
  3866  		return S32 | OPDP2(8)
  3867  
  3868  	case ALSR:
  3869  		return S64 | OPDP2(9)
  3870  
  3871  	case ALSRW:
  3872  		return S32 | OPDP2(9)
  3873  
  3874  	case AROR:
  3875  		return S64 | OPDP2(11)
  3876  
  3877  	case ARORW:
  3878  		return S32 | OPDP2(11)
  3879  
  3880  	case ACCMN:
  3881  		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
  3882  
  3883  	case ACCMNW:
  3884  		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  3885  
  3886  	case ACCMP:
  3887  		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  3888  
  3889  	case ACCMPW:
  3890  		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  3891  
  3892  	case ACRC32B:
  3893  		return S32 | OPDP2(16)
  3894  
  3895  	case ACRC32H:
  3896  		return S32 | OPDP2(17)
  3897  
  3898  	case ACRC32W:
  3899  		return S32 | OPDP2(18)
  3900  
  3901  	case ACRC32X:
  3902  		return S64 | OPDP2(19)
  3903  
  3904  	case ACRC32CB:
  3905  		return S32 | OPDP2(20)
  3906  
  3907  	case ACRC32CH:
  3908  		return S32 | OPDP2(21)
  3909  
  3910  	case ACRC32CW:
  3911  		return S32 | OPDP2(22)
  3912  
  3913  	case ACRC32CX:
  3914  		return S64 | OPDP2(23)
  3915  
  3916  	case ACSEL:
  3917  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3918  
  3919  	case ACSELW:
  3920  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3921  
  3922  	case ACSET:
  3923  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3924  
  3925  	case ACSETW:
  3926  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3927  
  3928  	case ACSETM:
  3929  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3930  
  3931  	case ACSETMW:
  3932  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3933  
  3934  	case ACINC, ACSINC:
  3935  		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3936  
  3937  	case ACINCW, ACSINCW:
  3938  		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3939  
  3940  	case ACINV, ACSINV:
  3941  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3942  
  3943  	case ACINVW, ACSINVW:
  3944  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  3945  
  3946  	case ACNEG, ACSNEG:
  3947  		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3948  
  3949  	case ACNEGW, ACSNEGW:
  3950  		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  3951  
  3952  	case AMUL, AMADD:
  3953  		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  3954  
  3955  	case AMULW, AMADDW:
  3956  		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  3957  
  3958  	case AMNEG, AMSUB:
  3959  		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  3960  
  3961  	case AMNEGW, AMSUBW:
  3962  		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  3963  
  3964  	case AMRS:
  3965  		return SYSOP(1, 2, 0, 0, 0, 0, 0)
  3966  
  3967  	case AMSR:
  3968  		return SYSOP(0, 2, 0, 0, 0, 0, 0)
  3969  
  3970  	case ANEG:
  3971  		return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  3972  
  3973  	case ANEGW:
  3974  		return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  3975  
  3976  	case ANEGS:
  3977  		return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  3978  
  3979  	case ANEGSW:
  3980  		return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  3981  
  3982  	case AREM, ASDIV:
  3983  		return S64 | OPDP2(3)
  3984  
  3985  	case AREMW, ASDIVW:
  3986  		return S32 | OPDP2(3)
  3987  
  3988  	case ASMULL, ASMADDL:
  3989  		return OPDP3(1, 0, 1, 0)
  3990  
  3991  	case ASMNEGL, ASMSUBL:
  3992  		return OPDP3(1, 0, 1, 1)
  3993  
  3994  	case ASMULH:
  3995  		return OPDP3(1, 0, 2, 0)
  3996  
  3997  	case AUMULL, AUMADDL:
  3998  		return OPDP3(1, 0, 5, 0)
  3999  
  4000  	case AUMNEGL, AUMSUBL:
  4001  		return OPDP3(1, 0, 5, 1)
  4002  
  4003  	case AUMULH:
  4004  		return OPDP3(1, 0, 6, 0)
  4005  
  4006  	case AUREM, AUDIV:
  4007  		return S64 | OPDP2(2)
  4008  
  4009  	case AUREMW, AUDIVW:
  4010  		return S32 | OPDP2(2)
  4011  
  4012  	case AAESE:
  4013  		return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
  4014  
  4015  	case AAESD:
  4016  		return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
  4017  
  4018  	case AAESMC:
  4019  		return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
  4020  
  4021  	case AAESIMC:
  4022  		return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
  4023  
  4024  	case ASHA1C:
  4025  		return 0x5E<<24 | 0<<12
  4026  
  4027  	case ASHA1P:
  4028  		return 0x5E<<24 | 1<<12
  4029  
  4030  	case ASHA1M:
  4031  		return 0x5E<<24 | 2<<12
  4032  
  4033  	case ASHA1SU0:
  4034  		return 0x5E<<24 | 3<<12
  4035  
  4036  	case ASHA256H:
  4037  		return 0x5E<<24 | 4<<12
  4038  
  4039  	case ASHA256H2:
  4040  		return 0x5E<<24 | 5<<12
  4041  
  4042  	case ASHA256SU1:
  4043  		return 0x5E<<24 | 6<<12
  4044  
  4045  	case ASHA1H:
  4046  		return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
  4047  
  4048  	case ASHA1SU1:
  4049  		return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
  4050  
  4051  	case ASHA256SU0:
  4052  		return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
  4053  
  4054  	case AFCVTZSD:
  4055  		return FPCVTI(1, 0, 1, 3, 0)
  4056  
  4057  	case AFCVTZSDW:
  4058  		return FPCVTI(0, 0, 1, 3, 0)
  4059  
  4060  	case AFCVTZSS:
  4061  		return FPCVTI(1, 0, 0, 3, 0)
  4062  
  4063  	case AFCVTZSSW:
  4064  		return FPCVTI(0, 0, 0, 3, 0)
  4065  
  4066  	case AFCVTZUD:
  4067  		return FPCVTI(1, 0, 1, 3, 1)
  4068  
  4069  	case AFCVTZUDW:
  4070  		return FPCVTI(0, 0, 1, 3, 1)
  4071  
  4072  	case AFCVTZUS:
  4073  		return FPCVTI(1, 0, 0, 3, 1)
  4074  
  4075  	case AFCVTZUSW:
  4076  		return FPCVTI(0, 0, 0, 3, 1)
  4077  
  4078  	case ASCVTFD:
  4079  		return FPCVTI(1, 0, 1, 0, 2)
  4080  
  4081  	case ASCVTFS:
  4082  		return FPCVTI(1, 0, 0, 0, 2)
  4083  
  4084  	case ASCVTFWD:
  4085  		return FPCVTI(0, 0, 1, 0, 2)
  4086  
  4087  	case ASCVTFWS:
  4088  		return FPCVTI(0, 0, 0, 0, 2)
  4089  
  4090  	case AUCVTFD:
  4091  		return FPCVTI(1, 0, 1, 0, 3)
  4092  
  4093  	case AUCVTFS:
  4094  		return FPCVTI(1, 0, 0, 0, 3)
  4095  
  4096  	case AUCVTFWD:
  4097  		return FPCVTI(0, 0, 1, 0, 3)
  4098  
  4099  	case AUCVTFWS:
  4100  		return FPCVTI(0, 0, 0, 0, 3)
  4101  
  4102  	case AFADDS:
  4103  		return FPOP2S(0, 0, 0, 2)
  4104  
  4105  	case AFADDD:
  4106  		return FPOP2S(0, 0, 1, 2)
  4107  
  4108  	case AFSUBS:
  4109  		return FPOP2S(0, 0, 0, 3)
  4110  
  4111  	case AFSUBD:
  4112  		return FPOP2S(0, 0, 1, 3)
  4113  
  4114  	case AFMULS:
  4115  		return FPOP2S(0, 0, 0, 0)
  4116  
  4117  	case AFMULD:
  4118  		return FPOP2S(0, 0, 1, 0)
  4119  
  4120  	case AFDIVS:
  4121  		return FPOP2S(0, 0, 0, 1)
  4122  
  4123  	case AFDIVD:
  4124  		return FPOP2S(0, 0, 1, 1)
  4125  
  4126  	case AFMAXS:
  4127  		return FPOP2S(0, 0, 0, 4)
  4128  
  4129  	case AFMINS:
  4130  		return FPOP2S(0, 0, 0, 5)
  4131  
  4132  	case AFMAXD:
  4133  		return FPOP2S(0, 0, 1, 4)
  4134  
  4135  	case AFMIND:
  4136  		return FPOP2S(0, 0, 1, 5)
  4137  
  4138  	case AFMAXNMS:
  4139  		return FPOP2S(0, 0, 0, 6)
  4140  
  4141  	case AFMAXNMD:
  4142  		return FPOP2S(0, 0, 1, 6)
  4143  
  4144  	case AFMINNMS:
  4145  		return FPOP2S(0, 0, 0, 7)
  4146  
  4147  	case AFMINNMD:
  4148  		return FPOP2S(0, 0, 1, 7)
  4149  
  4150  	case AFNMULS:
  4151  		return FPOP2S(0, 0, 0, 8)
  4152  
  4153  	case AFNMULD:
  4154  		return FPOP2S(0, 0, 1, 8)
  4155  
  4156  	case AFCMPS:
  4157  		return FPCMP(0, 0, 0, 0, 0)
  4158  
  4159  	case AFCMPD:
  4160  		return FPCMP(0, 0, 1, 0, 0)
  4161  
  4162  	case AFCMPES:
  4163  		return FPCMP(0, 0, 0, 0, 16)
  4164  
  4165  	case AFCMPED:
  4166  		return FPCMP(0, 0, 1, 0, 16)
  4167  
  4168  	case AFCCMPS:
  4169  		return FPCCMP(0, 0, 0, 0)
  4170  
  4171  	case AFCCMPD:
  4172  		return FPCCMP(0, 0, 1, 0)
  4173  
  4174  	case AFCCMPES:
  4175  		return FPCCMP(0, 0, 0, 1)
  4176  
  4177  	case AFCCMPED:
  4178  		return FPCCMP(0, 0, 1, 1)
  4179  
  4180  	case AFCSELS:
  4181  		return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
  4182  
  4183  	case AFCSELD:
  4184  		return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
  4185  
  4186  	case AFMOVS:
  4187  		return FPOP1S(0, 0, 0, 0)
  4188  
  4189  	case AFABSS:
  4190  		return FPOP1S(0, 0, 0, 1)
  4191  
  4192  	case AFNEGS:
  4193  		return FPOP1S(0, 0, 0, 2)
  4194  
  4195  	case AFSQRTS:
  4196  		return FPOP1S(0, 0, 0, 3)
  4197  
  4198  	case AFCVTSD:
  4199  		return FPOP1S(0, 0, 0, 5)
  4200  
  4201  	case AFCVTSH:
  4202  		return FPOP1S(0, 0, 0, 7)
  4203  
  4204  	case AFRINTNS:
  4205  		return FPOP1S(0, 0, 0, 8)
  4206  
  4207  	case AFRINTPS:
  4208  		return FPOP1S(0, 0, 0, 9)
  4209  
  4210  	case AFRINTMS:
  4211  		return FPOP1S(0, 0, 0, 10)
  4212  
  4213  	case AFRINTZS:
  4214  		return FPOP1S(0, 0, 0, 11)
  4215  
  4216  	case AFRINTAS:
  4217  		return FPOP1S(0, 0, 0, 12)
  4218  
  4219  	case AFRINTXS:
  4220  		return FPOP1S(0, 0, 0, 14)
  4221  
  4222  	case AFRINTIS:
  4223  		return FPOP1S(0, 0, 0, 15)
  4224  
  4225  	case AFMOVD:
  4226  		return FPOP1S(0, 0, 1, 0)
  4227  
  4228  	case AFABSD:
  4229  		return FPOP1S(0, 0, 1, 1)
  4230  
  4231  	case AFNEGD:
  4232  		return FPOP1S(0, 0, 1, 2)
  4233  
  4234  	case AFSQRTD:
  4235  		return FPOP1S(0, 0, 1, 3)
  4236  
  4237  	case AFCVTDS:
  4238  		return FPOP1S(0, 0, 1, 4)
  4239  
  4240  	case AFCVTDH:
  4241  		return FPOP1S(0, 0, 1, 7)
  4242  
  4243  	case AFRINTND:
  4244  		return FPOP1S(0, 0, 1, 8)
  4245  
  4246  	case AFRINTPD:
  4247  		return FPOP1S(0, 0, 1, 9)
  4248  
  4249  	case AFRINTMD:
  4250  		return FPOP1S(0, 0, 1, 10)
  4251  
  4252  	case AFRINTZD:
  4253  		return FPOP1S(0, 0, 1, 11)
  4254  
  4255  	case AFRINTAD:
  4256  		return FPOP1S(0, 0, 1, 12)
  4257  
  4258  	case AFRINTXD:
  4259  		return FPOP1S(0, 0, 1, 14)
  4260  
  4261  	case AFRINTID:
  4262  		return FPOP1S(0, 0, 1, 15)
  4263  
  4264  	case AFCVTHS:
  4265  		return FPOP1S(0, 0, 3, 4)
  4266  
  4267  	case AFCVTHD:
  4268  		return FPOP1S(0, 0, 3, 5)
  4269  
  4270  	case AVADD:
  4271  		return 7<<25 | 1<<21 | 1<<15 | 1<<10
  4272  
  4273  	case AVADDP:
  4274  		return 7<<25 | 1<<21 | 1<<15 | 15<<10
  4275  
  4276  	case AVAND:
  4277  		return 7<<25 | 1<<21 | 7<<10
  4278  
  4279  	case AVCMEQ:
  4280  		return 1<<29 | 0x71<<21 | 0x23<<10
  4281  
  4282  	case AVEOR:
  4283  		return 1<<29 | 0x71<<21 | 7<<10
  4284  
  4285  	case AVORR:
  4286  		return 7<<25 | 5<<21 | 7<<10
  4287  
  4288  	case AVREV32:
  4289  		return 11<<26 | 2<<24 | 1<<21 | 1<<11
  4290  
  4291  	case AVMOV:
  4292  		return 7<<25 | 5<<21 | 7<<10
  4293  
  4294  	case AVADDV:
  4295  		return 7<<25 | 3<<20 | 3<<15 | 7<<11
  4296  
  4297  	case AVUADDLV:
  4298  		return 1<<29 | 7<<25 | 3<<20 | 7<<11
  4299  	}
  4300  
  4301  	c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
  4302  	return 0
  4303  }
  4304  
  4305  /*
  4306   * imm -> Rd
  4307   * imm op Rn -> Rd
  4308   */
  4309  func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
  4310  	switch a {
  4311  	/* op $addcon, Rn, Rd */
  4312  	case AMOVD, AADD:
  4313  		return S64 | 0<<30 | 0<<29 | 0x11<<24
  4314  
  4315  	case ACMN, AADDS:
  4316  		return S64 | 0<<30 | 1<<29 | 0x11<<24
  4317  
  4318  	case AMOVW, AADDW:
  4319  		return S32 | 0<<30 | 0<<29 | 0x11<<24
  4320  
  4321  	case ACMNW, AADDSW:
  4322  		return S32 | 0<<30 | 1<<29 | 0x11<<24
  4323  
  4324  	case ASUB:
  4325  		return S64 | 1<<30 | 0<<29 | 0x11<<24
  4326  
  4327  	case ACMP, ASUBS:
  4328  		return S64 | 1<<30 | 1<<29 | 0x11<<24
  4329  
  4330  	case ASUBW:
  4331  		return S32 | 1<<30 | 0<<29 | 0x11<<24
  4332  
  4333  	case ACMPW, ASUBSW:
  4334  		return S32 | 1<<30 | 1<<29 | 0x11<<24
  4335  
  4336  		/* op $imm(SB), Rd; op label, Rd */
  4337  	case AADR:
  4338  		return 0<<31 | 0x10<<24
  4339  
  4340  	case AADRP:
  4341  		return 1<<31 | 0x10<<24
  4342  
  4343  		/* op $bimm, Rn, Rd */
  4344  	case AAND, ABIC:
  4345  		return S64 | 0<<29 | 0x24<<23
  4346  
  4347  	case AANDW, ABICW:
  4348  		return S32 | 0<<29 | 0x24<<23 | 0<<22
  4349  
  4350  	case AORR, AORN:
  4351  		return S64 | 1<<29 | 0x24<<23
  4352  
  4353  	case AORRW, AORNW:
  4354  		return S32 | 1<<29 | 0x24<<23 | 0<<22
  4355  
  4356  	case AEOR, AEON:
  4357  		return S64 | 2<<29 | 0x24<<23
  4358  
  4359  	case AEORW, AEONW:
  4360  		return S32 | 2<<29 | 0x24<<23 | 0<<22
  4361  
  4362  	case AANDS, ABICS:
  4363  		return S64 | 3<<29 | 0x24<<23
  4364  
  4365  	case AANDSW, ABICSW:
  4366  		return S32 | 3<<29 | 0x24<<23 | 0<<22
  4367  
  4368  	case AASR:
  4369  		return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
  4370  
  4371  	case AASRW:
  4372  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  4373  
  4374  		/* op $width, $lsb, Rn, Rd */
  4375  	case ABFI:
  4376  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  4377  		/* alias of BFM */
  4378  
  4379  	case ABFIW:
  4380  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  4381  
  4382  		/* op $imms, $immr, Rn, Rd */
  4383  	case ABFM:
  4384  		return S64 | 1<<29 | 0x26<<23 | 1<<22
  4385  
  4386  	case ABFMW:
  4387  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  4388  
  4389  	case ASBFM:
  4390  		return S64 | 0<<29 | 0x26<<23 | 1<<22
  4391  
  4392  	case ASBFMW:
  4393  		return S32 | 0<<29 | 0x26<<23 | 0<<22
  4394  
  4395  	case AUBFM:
  4396  		return S64 | 2<<29 | 0x26<<23 | 1<<22
  4397  
  4398  	case AUBFMW:
  4399  		return S32 | 2<<29 | 0x26<<23 | 0<<22
  4400  
  4401  	case ABFXIL:
  4402  		return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
  4403  
  4404  	case ABFXILW:
  4405  		return S32 | 1<<29 | 0x26<<23 | 0<<22
  4406  
  4407  	case AEXTR:
  4408  		return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
  4409  
  4410  	case AEXTRW:
  4411  		return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
  4412  
  4413  	case ACBNZ:
  4414  		return S64 | 0x1A<<25 | 1<<24
  4415  
  4416  	case ACBNZW:
  4417  		return S32 | 0x1A<<25 | 1<<24
  4418  
  4419  	case ACBZ:
  4420  		return S64 | 0x1A<<25 | 0<<24
  4421  
  4422  	case ACBZW:
  4423  		return S32 | 0x1A<<25 | 0<<24
  4424  
  4425  	case ACCMN:
  4426  		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  4427  
  4428  	case ACCMNW:
  4429  		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  4430  
  4431  	case ACCMP:
  4432  		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  4433  
  4434  	case ACCMPW:
  4435  		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  4436  
  4437  	case AMOVK:
  4438  		return S64 | 3<<29 | 0x25<<23
  4439  
  4440  	case AMOVKW:
  4441  		return S32 | 3<<29 | 0x25<<23
  4442  
  4443  	case AMOVN:
  4444  		return S64 | 0<<29 | 0x25<<23
  4445  
  4446  	case AMOVNW:
  4447  		return S32 | 0<<29 | 0x25<<23
  4448  
  4449  	case AMOVZ:
  4450  		return S64 | 2<<29 | 0x25<<23
  4451  
  4452  	case AMOVZW:
  4453  		return S32 | 2<<29 | 0x25<<23
  4454  
  4455  	case AMSR:
  4456  		return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
  4457  
  4458  	case AAT,
  4459  		ADC,
  4460  		AIC,
  4461  		ATLBI,
  4462  		ASYS:
  4463  		return SYSOP(0, 1, 0, 0, 0, 0, 0)
  4464  
  4465  	case ASYSL:
  4466  		return SYSOP(1, 1, 0, 0, 0, 0, 0)
  4467  
  4468  	case ATBZ:
  4469  		return 0x36 << 24
  4470  
  4471  	case ATBNZ:
  4472  		return 0x37 << 24
  4473  
  4474  	case ADSB:
  4475  		return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
  4476  
  4477  	case ADMB:
  4478  		return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
  4479  
  4480  	case AISB:
  4481  		return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
  4482  
  4483  	case AHINT:
  4484  		return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
  4485  	}
  4486  
  4487  	c.ctxt.Diag("%v: bad irr %v", p, a)
  4488  	return 0
  4489  }
  4490  
  4491  func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
  4492  	switch a {
  4493  	case ACLS:
  4494  		return S64 | OPBIT(5)
  4495  
  4496  	case ACLSW:
  4497  		return S32 | OPBIT(5)
  4498  
  4499  	case ACLZ:
  4500  		return S64 | OPBIT(4)
  4501  
  4502  	case ACLZW:
  4503  		return S32 | OPBIT(4)
  4504  
  4505  	case ARBIT:
  4506  		return S64 | OPBIT(0)
  4507  
  4508  	case ARBITW:
  4509  		return S32 | OPBIT(0)
  4510  
  4511  	case AREV:
  4512  		return S64 | OPBIT(3)
  4513  
  4514  	case AREVW:
  4515  		return S32 | OPBIT(2)
  4516  
  4517  	case AREV16:
  4518  		return S64 | OPBIT(1)
  4519  
  4520  	case AREV16W:
  4521  		return S32 | OPBIT(1)
  4522  
  4523  	case AREV32:
  4524  		return S64 | OPBIT(2)
  4525  
  4526  	default:
  4527  		c.ctxt.Diag("bad bit op\n%v", p)
  4528  		return 0
  4529  	}
  4530  }
  4531  
  4532  /*
  4533   * add/subtract sign or zero-extended register
  4534   */
  4535  func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
  4536  	extension := uint32(0)
  4537  	if !extend {
  4538  		switch a {
  4539  		case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
  4540  			extension = LSL0_64
  4541  
  4542  		case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
  4543  			extension = LSL0_32
  4544  		}
  4545  	}
  4546  
  4547  	switch a {
  4548  	case AADD:
  4549  		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4550  
  4551  	case AADDW:
  4552  		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4553  
  4554  	case ACMN, AADDS:
  4555  		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4556  
  4557  	case ACMNW, AADDSW:
  4558  		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4559  
  4560  	case ASUB:
  4561  		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4562  
  4563  	case ASUBW:
  4564  		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4565  
  4566  	case ACMP, ASUBS:
  4567  		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4568  
  4569  	case ACMPW, ASUBSW:
  4570  		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  4571  	}
  4572  
  4573  	c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
  4574  	return 0
  4575  }
  4576  
  4577  func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
  4578  	switch a {
  4579  	case ASVC:
  4580  		return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
  4581  
  4582  	case AHVC:
  4583  		return 0xD4<<24 | 0<<21 | 2
  4584  
  4585  	case ASMC:
  4586  		return 0xD4<<24 | 0<<21 | 3
  4587  
  4588  	case ABRK:
  4589  		return 0xD4<<24 | 1<<21 | 0
  4590  
  4591  	case AHLT:
  4592  		return 0xD4<<24 | 2<<21 | 0
  4593  
  4594  	case ADCPS1:
  4595  		return 0xD4<<24 | 5<<21 | 1
  4596  
  4597  	case ADCPS2:
  4598  		return 0xD4<<24 | 5<<21 | 2
  4599  
  4600  	case ADCPS3:
  4601  		return 0xD4<<24 | 5<<21 | 3
  4602  
  4603  	case ACLREX:
  4604  		return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
  4605  	}
  4606  
  4607  	c.ctxt.Diag("%v: bad imm %v", p, a)
  4608  	return 0
  4609  }
  4610  
  4611  func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
  4612  	v := int64(0)
  4613  	t := int64(0)
  4614  	if p.Pcond != nil {
  4615  		v = (p.Pcond.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
  4616  		if (v & ((1 << uint(shift)) - 1)) != 0 {
  4617  			c.ctxt.Diag("misaligned label\n%v", p)
  4618  		}
  4619  		v >>= uint(shift)
  4620  		t = int64(1) << uint(flen-1)
  4621  		if v < -t || v >= t {
  4622  			c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, p.Pcond)
  4623  			panic("branch too far")
  4624  		}
  4625  	}
  4626  
  4627  	return v & ((t << 1) - 1)
  4628  }
  4629  
  4630  /*
  4631   * pc-relative branches
  4632   */
  4633  func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
  4634  	switch a {
  4635  	case ABEQ:
  4636  		return OPBcc(0x0)
  4637  
  4638  	case ABNE:
  4639  		return OPBcc(0x1)
  4640  
  4641  	case ABCS:
  4642  		return OPBcc(0x2)
  4643  
  4644  	case ABHS:
  4645  		return OPBcc(0x2)
  4646  
  4647  	case ABCC:
  4648  		return OPBcc(0x3)
  4649  
  4650  	case ABLO:
  4651  		return OPBcc(0x3)
  4652  
  4653  	case ABMI:
  4654  		return OPBcc(0x4)
  4655  
  4656  	case ABPL:
  4657  		return OPBcc(0x5)
  4658  
  4659  	case ABVS:
  4660  		return OPBcc(0x6)
  4661  
  4662  	case ABVC:
  4663  		return OPBcc(0x7)
  4664  
  4665  	case ABHI:
  4666  		return OPBcc(0x8)
  4667  
  4668  	case ABLS:
  4669  		return OPBcc(0x9)
  4670  
  4671  	case ABGE:
  4672  		return OPBcc(0xa)
  4673  
  4674  	case ABLT:
  4675  		return OPBcc(0xb)
  4676  
  4677  	case ABGT:
  4678  		return OPBcc(0xc)
  4679  
  4680  	case ABLE:
  4681  		return OPBcc(0xd) /* imm19<<5 | cond */
  4682  
  4683  	case AB:
  4684  		return 0<<31 | 5<<26 /* imm26 */
  4685  
  4686  	case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
  4687  		return 1<<31 | 5<<26
  4688  	}
  4689  
  4690  	c.ctxt.Diag("%v: bad bra %v", p, a)
  4691  	return 0
  4692  }
  4693  
  4694  func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
  4695  	switch a {
  4696  	case ABL:
  4697  		return OPBLR(1) /* BLR */
  4698  
  4699  	case AB:
  4700  		return OPBLR(0) /* BR */
  4701  
  4702  	case obj.ARET:
  4703  		return OPBLR(2) /* RET */
  4704  	}
  4705  
  4706  	c.ctxt.Diag("%v: bad brr %v", p, a)
  4707  	return 0
  4708  }
  4709  
  4710  func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
  4711  	switch a {
  4712  	case ADRPS:
  4713  		return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
  4714  
  4715  	case AERET:
  4716  		return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
  4717  
  4718  	// case ANOP:
  4719  	// 	return SYSHINT(0)
  4720  
  4721  	case AYIELD:
  4722  		return SYSHINT(1)
  4723  
  4724  	case AWFE:
  4725  		return SYSHINT(2)
  4726  
  4727  	case AWFI:
  4728  		return SYSHINT(3)
  4729  
  4730  	case ASEV:
  4731  		return SYSHINT(4)
  4732  
  4733  	case ASEVL:
  4734  		return SYSHINT(5)
  4735  	}
  4736  
  4737  	c.ctxt.Diag("%v: bad op0 %v", p, a)
  4738  	return 0
  4739  }
  4740  
  4741  /*
  4742   * register offset
  4743   */
  4744  func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
  4745  	switch a {
  4746  	case ALDAR:
  4747  		return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
  4748  
  4749  	case ALDARW:
  4750  		return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
  4751  
  4752  	case ALDARB:
  4753  		return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
  4754  
  4755  	case ALDARH:
  4756  		return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
  4757  
  4758  	case ALDAXP:
  4759  		return LDSTX(3, 0, 1, 1, 1)
  4760  
  4761  	case ALDAXPW:
  4762  		return LDSTX(2, 0, 1, 1, 1)
  4763  
  4764  	case ALDAXR:
  4765  		return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
  4766  
  4767  	case ALDAXRW:
  4768  		return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
  4769  
  4770  	case ALDAXRB:
  4771  		return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
  4772  
  4773  	case ALDAXRH:
  4774  		return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
  4775  
  4776  	case ALDXR:
  4777  		return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
  4778  
  4779  	case ALDXRB:
  4780  		return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
  4781  
  4782  	case ALDXRH:
  4783  		return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
  4784  
  4785  	case ALDXRW:
  4786  		return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
  4787  
  4788  	case ALDXP:
  4789  		return LDSTX(3, 0, 1, 1, 0)
  4790  
  4791  	case ALDXPW:
  4792  		return LDSTX(2, 0, 1, 1, 0)
  4793  
  4794  	case AMOVNP:
  4795  		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  4796  
  4797  	case AMOVNPW:
  4798  		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  4799  	}
  4800  
  4801  	c.ctxt.Diag("bad opload %v\n%v", a, p)
  4802  	return 0
  4803  }
  4804  
  4805  func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
  4806  	switch a {
  4807  	case ASTLR:
  4808  		return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
  4809  
  4810  	case ASTLRB:
  4811  		return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
  4812  
  4813  	case ASTLRH:
  4814  		return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
  4815  
  4816  	case ASTLP:
  4817  		return LDSTX(3, 0, 0, 1, 1)
  4818  
  4819  	case ASTLPW:
  4820  		return LDSTX(2, 0, 0, 1, 1)
  4821  
  4822  	case ASTLRW:
  4823  		return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
  4824  
  4825  	case ASTLXP:
  4826  		return LDSTX(2, 0, 0, 1, 1)
  4827  
  4828  	case ASTLXPW:
  4829  		return LDSTX(3, 0, 0, 1, 1)
  4830  
  4831  	case ASTLXR:
  4832  		return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
  4833  
  4834  	case ASTLXRB:
  4835  		return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
  4836  
  4837  	case ASTLXRH:
  4838  		return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
  4839  
  4840  	case ASTLXRW:
  4841  		return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
  4842  
  4843  	case ASTXR:
  4844  		return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
  4845  
  4846  	case ASTXRB:
  4847  		return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
  4848  
  4849  	case ASTXRH:
  4850  		return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
  4851  
  4852  	case ASTXP:
  4853  		return LDSTX(3, 0, 0, 1, 0)
  4854  
  4855  	case ASTXPW:
  4856  		return LDSTX(2, 0, 0, 1, 0)
  4857  
  4858  	case ASTXRW:
  4859  		return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
  4860  
  4861  	case AMOVNP:
  4862  		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  4863  
  4864  	case AMOVNPW:
  4865  		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  4866  	}
  4867  
  4868  	c.ctxt.Diag("bad opstore %v\n%v", a, p)
  4869  	return 0
  4870  }
  4871  
  4872  /*
  4873   * load/store register (unsigned immediate) C3.3.13
  4874   *	these produce 64-bit values (when there's an option)
  4875   */
  4876  func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  4877  	if v < 0 || v >= (1<<12) {
  4878  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  4879  	}
  4880  	o |= (v & 0xFFF) << 10
  4881  	o |= int32(b&31) << 5
  4882  	o |= int32(r & 31)
  4883  	return uint32(o)
  4884  }
  4885  
  4886  func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
  4887  	switch a {
  4888  	case AMOVD:
  4889  		return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
  4890  
  4891  	case AMOVW:
  4892  		return LDSTR12U(2, 0, 2)
  4893  
  4894  	case AMOVWU:
  4895  		return LDSTR12U(2, 0, 1)
  4896  
  4897  	case AMOVH:
  4898  		return LDSTR12U(1, 0, 2)
  4899  
  4900  	case AMOVHU:
  4901  		return LDSTR12U(1, 0, 1)
  4902  
  4903  	case AMOVB:
  4904  		return LDSTR12U(0, 0, 2)
  4905  
  4906  	case AMOVBU:
  4907  		return LDSTR12U(0, 0, 1)
  4908  
  4909  	case AFMOVS:
  4910  		return LDSTR12U(2, 1, 1)
  4911  
  4912  	case AFMOVD:
  4913  		return LDSTR12U(3, 1, 1)
  4914  
  4915  	case AVMOVS:
  4916  		return LDSTR12U(2, 1, 1)
  4917  	}
  4918  
  4919  	c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
  4920  	return 0
  4921  }
  4922  
  4923  func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
  4924  	return LD2STR(c.opldr12(p, a))
  4925  }
  4926  
  4927  /*
  4928   * load/store register (unscaled immediate) C3.3.12
  4929   */
  4930  func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  4931  	if v < -256 || v > 255 {
  4932  		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  4933  	}
  4934  	o |= (v & 0x1FF) << 12
  4935  	o |= int32(b&31) << 5
  4936  	o |= int32(r & 31)
  4937  	return uint32(o)
  4938  }
  4939  
  4940  func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
  4941  	switch a {
  4942  	case AMOVD:
  4943  		return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
  4944  
  4945  	case AMOVW:
  4946  		return LDSTR9S(2, 0, 2)
  4947  
  4948  	case AMOVWU:
  4949  		return LDSTR9S(2, 0, 1)
  4950  
  4951  	case AMOVH:
  4952  		return LDSTR9S(1, 0, 2)
  4953  
  4954  	case AMOVHU:
  4955  		return LDSTR9S(1, 0, 1)
  4956  
  4957  	case AMOVB:
  4958  		return LDSTR9S(0, 0, 2)
  4959  
  4960  	case AMOVBU:
  4961  		return LDSTR9S(0, 0, 1)
  4962  
  4963  	case AFMOVS:
  4964  		return LDSTR9S(2, 1, 1)
  4965  
  4966  	case AFMOVD:
  4967  		return LDSTR9S(3, 1, 1)
  4968  	}
  4969  
  4970  	c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
  4971  	return 0
  4972  }
  4973  
  4974  func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
  4975  	return LD2STR(c.opldr9(p, a))
  4976  }
  4977  
  4978  func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
  4979  	switch a {
  4980  	case AMOVD:
  4981  		return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
  4982  
  4983  	case AMOVW:
  4984  		return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  4985  
  4986  	case AMOVWU:
  4987  		return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  4988  
  4989  	case AMOVH:
  4990  		return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  4991  
  4992  	case AMOVHU:
  4993  		return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  4994  
  4995  	case AMOVB:
  4996  		return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  4997  
  4998  	case AMOVBU:
  4999  		return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  5000  
  5001  	case AVMOVS:
  5002  		return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
  5003  	}
  5004  
  5005  	c.ctxt.Diag("bad opldr %v\n%v", a, p)
  5006  	return 0
  5007  }
  5008  
  5009  // olsxrr attaches register operands to a load/store opcode supplied in o.
  5010  // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
  5011  func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
  5012  	o |= int32(r1&31) << 5
  5013  	o |= int32(r2&31) << 16
  5014  	o |= int32(r & 31)
  5015  	return uint32(o)
  5016  }
  5017  
  5018  // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  5019  // for load instruction with register offset.
  5020  func (c *ctxt7) opldrr(p *obj.Prog, a obj.As) uint32 {
  5021  	switch a {
  5022  	case AMOVD:
  5023  		return 0x1a<<10 | 0x3<<21 | 0x1f<<27
  5024  	case AMOVW:
  5025  		return 0x1a<<10 | 0x5<<21 | 0x17<<27
  5026  	case AMOVWU:
  5027  		return 0x1a<<10 | 0x3<<21 | 0x17<<27
  5028  	case AMOVH:
  5029  		return 0x1a<<10 | 0x5<<21 | 0x0f<<27
  5030  	case AMOVHU:
  5031  		return 0x1a<<10 | 0x3<<21 | 0x0f<<27
  5032  	case AMOVB:
  5033  		return 0x1a<<10 | 0x5<<21 | 0x07<<27
  5034  	case AMOVBU:
  5035  		return 0x1a<<10 | 0x3<<21 | 0x07<<27
  5036  	case AFMOVS:
  5037  		return 0x1a<<10 | 0x3<<21 | 0x17<<27 | 1<<26
  5038  	case AFMOVD:
  5039  		return 0x1a<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
  5040  	}
  5041  	c.ctxt.Diag("bad opldrr %v\n%v", a, p)
  5042  	return 0
  5043  }
  5044  
  5045  // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  5046  // for store instruction with register offset.
  5047  func (c *ctxt7) opstrr(p *obj.Prog, a obj.As) uint32 {
  5048  	switch a {
  5049  	case AMOVD:
  5050  		return 0x1a<<10 | 0x1<<21 | 0x1f<<27
  5051  	case AMOVW, AMOVWU:
  5052  		return 0x1a<<10 | 0x1<<21 | 0x17<<27
  5053  	case AMOVH, AMOVHU:
  5054  		return 0x1a<<10 | 0x1<<21 | 0x0f<<27
  5055  	case AMOVB, AMOVBU:
  5056  		return 0x1a<<10 | 0x1<<21 | 0x07<<27
  5057  	case AFMOVS:
  5058  		return 0x1a<<10 | 0x1<<21 | 0x17<<27 | 1<<26
  5059  	case AFMOVD:
  5060  		return 0x1a<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
  5061  	}
  5062  	c.ctxt.Diag("bad opstrr %v\n%v", a, p)
  5063  	return 0
  5064  }
  5065  
  5066  func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
  5067  	if (v & 0xFFF000) != 0 {
  5068  		if v&0xFFF != 0 {
  5069  			c.ctxt.Diag("%v misuses oaddi", p)
  5070  		}
  5071  		v >>= 12
  5072  		o1 |= 1 << 22
  5073  	}
  5074  
  5075  	o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
  5076  	return uint32(o1)
  5077  }
  5078  
  5079  /*
  5080   * load a a literal value into dr
  5081   */
  5082  func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
  5083  	var o1 int32
  5084  	if p.Pcond == nil { /* not in literal pool */
  5085  		c.aclass(a)
  5086  		c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
  5087  
  5088  		/* TODO: could be clever, and use general constant builder */
  5089  		o1 = int32(c.opirr(p, AADD))
  5090  
  5091  		v := int32(c.instoffset)
  5092  		if v != 0 && (v&0xFFF) == 0 {
  5093  			v >>= 12
  5094  			o1 |= 1 << 22 /* shift, by 12 */
  5095  		}
  5096  
  5097  		o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
  5098  	} else {
  5099  		fp := 0
  5100  		w := 0 /* default: 32 bit, unsigned */
  5101  		switch as {
  5102  		case AFMOVS:
  5103  			fp = 1
  5104  
  5105  		case AFMOVD:
  5106  			fp = 1
  5107  			w = 1 /* 64 bit simd&fp */
  5108  
  5109  		case AMOVD:
  5110  			if p.Pcond.As == ADWORD {
  5111  				w = 1 /* 64 bit */
  5112  			} else if p.Pcond.To.Offset < 0 {
  5113  				w = 2 /* sign extend */
  5114  			}
  5115  
  5116  		case AMOVB, AMOVH, AMOVW:
  5117  			w = 2 /* 32 bit, sign-extended to 64 */
  5118  			break
  5119  		}
  5120  
  5121  		v := int32(c.brdist(p, 0, 19, 2))
  5122  		o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
  5123  		o1 |= (v & 0x7FFFF) << 5
  5124  		o1 |= int32(dr & 31)
  5125  	}
  5126  
  5127  	return uint32(o1)
  5128  }
  5129  
  5130  // load a constant (MOVCON or BITCON) in a into rt
  5131  func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
  5132  	if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
  5133  		// or $bitcon, REGZERO, rt
  5134  		mode := 64
  5135  		var as1 obj.As
  5136  		switch as {
  5137  		case AMOVW:
  5138  			as1 = AORRW
  5139  			mode = 32
  5140  		case AMOVD:
  5141  			as1 = AORR
  5142  		}
  5143  		o1 = c.opirr(p, as1)
  5144  		o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  5145  		return o1
  5146  	}
  5147  
  5148  	r := 32
  5149  	if as == AMOVD {
  5150  		r = 64
  5151  	}
  5152  	d := a.Offset
  5153  	s := movcon(d)
  5154  	if s < 0 || s >= r {
  5155  		d = ^d
  5156  		s = movcon(d)
  5157  		if s < 0 || s >= r {
  5158  			c.ctxt.Diag("impossible move wide: %#x\n%v", uint64(a.Offset), p)
  5159  		}
  5160  		if as == AMOVD {
  5161  			o1 = c.opirr(p, AMOVN)
  5162  		} else {
  5163  			o1 = c.opirr(p, AMOVNW)
  5164  		}
  5165  	} else {
  5166  		if as == AMOVD {
  5167  			o1 = c.opirr(p, AMOVZ)
  5168  		} else {
  5169  			o1 = c.opirr(p, AMOVZW)
  5170  		}
  5171  	}
  5172  	o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
  5173  	return o1
  5174  }
  5175  
  5176  func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
  5177  	var b uint32
  5178  	o := c.opirr(p, a)
  5179  	if (o & (1 << 31)) == 0 {
  5180  		b = 32
  5181  	} else {
  5182  		b = 64
  5183  	}
  5184  	if r < 0 || uint32(r) >= b {
  5185  		c.ctxt.Diag("illegal bit number\n%v", p)
  5186  	}
  5187  	o |= (uint32(r) & 0x3F) << 16
  5188  	if s < 0 || uint32(s) >= b {
  5189  		c.ctxt.Diag("illegal bit number\n%v", p)
  5190  	}
  5191  	o |= (uint32(s) & 0x3F) << 10
  5192  	o |= (uint32(rf&31) << 5) | uint32(rt&31)
  5193  	return o
  5194  }
  5195  
  5196  func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
  5197  	var b uint32
  5198  	o := c.opirr(p, a)
  5199  	if (o & (1 << 31)) != 0 {
  5200  		b = 63
  5201  	} else {
  5202  		b = 31
  5203  	}
  5204  	if v < 0 || uint32(v) > b {
  5205  		c.ctxt.Diag("illegal bit number\n%v", p)
  5206  	}
  5207  	o |= uint32(v) << 10
  5208  	o |= uint32(rn&31) << 5
  5209  	o |= uint32(rm&31) << 16
  5210  	o |= uint32(rt & 31)
  5211  	return o
  5212  }
  5213  
  5214  /*
  5215   * size in log2(bytes)
  5216   */
  5217  func movesize(a obj.As) int {
  5218  	switch a {
  5219  	case AMOVD:
  5220  		return 3
  5221  
  5222  	case AMOVW, AMOVWU, AVMOVS:
  5223  		return 2
  5224  
  5225  	case AMOVH, AMOVHU:
  5226  		return 1
  5227  
  5228  	case AMOVB, AMOVBU:
  5229  		return 0
  5230  
  5231  	case AFMOVS:
  5232  		return 2
  5233  
  5234  	case AFMOVD:
  5235  		return 3
  5236  
  5237  	default:
  5238  		return -1
  5239  	}
  5240  }