github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/cmd/internal/obj/arm64/asm7.go (about)

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