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