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