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