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