github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/internal/obj/arm64/asm7.go (about)

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