Home | History | Annotate | Download | only in arm64
      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 (a] 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 (a] 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 }
   4159