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