github.com/euank/go@v0.0.0-20160829210321-495514729181/src/cmd/internal/obj/arm64/asm7.go (about)

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