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