github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/cmd/internal/obj/arm64/asm7.go (about)

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