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