github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/cmd/internal/obj/arm64/asm7.go (about)

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