github.com/StingNevermore/go@v0.0.0-20180120041312-3810f5bfed72/src/cmd/internal/obj/arm64/asm7.go (about)

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