github.com/jonasi/go@v0.0.0-20150930005915-e78e654c1de0/src/cmd/internal/obj/arm64/asm7.go (about)

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