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