github.com/aloncn/graphics-go@v0.0.1/src/cmd/internal/obj/arm64/asm7.go (about)

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