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