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://bitbucket.org/plan9-from-bell-labs/9-cc/src/master/
3//
4// 	Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// 	Portions Copyright © 1995-1997 C H Forsyth ([email protected])
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 ([email protected])
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
31package arm64
32
33import (
34	"cmd/internal/obj"
35	"cmd/internal/objabi"
36	"fmt"
37	"log"
38	"math"
39	"sort"
40	"strings"
41)
42
43// ctxt7 holds state while assembling a single function.
44// Each function gets a fresh ctxt7.
45// This allows for multiple functions to be safely concurrently assembled.
46type ctxt7 struct {
47	ctxt       *obj.Link
48	newprog    obj.ProgAlloc
49	cursym     *obj.LSym
50	blitrl     *obj.Prog
51	elitrl     *obj.Prog
52	autosize   int32
53	extrasize  int32
54	instoffset int64
55	pc         int64
56	pool       struct {
57		start uint32
58		size  uint32
59	}
60}
61
62const (
63	funcAlign = 16
64)
65
66const (
67	REGFROM = 1
68)
69
70type Optab struct {
71	as    obj.As
72	a1    uint8 // Prog.From
73	a2    uint8 // 2nd source operand, Prog.Reg or Prog.RestArgs[XXX]
74	a3    uint8 // 3rd source operand, Prog.RestArgs[XXX]
75	a4    uint8 // Prog.To
76	a5    uint8 // 2nd destination operand, Prog.RegTo2 or Prog.RestArgs[XXX]
77	type_ int8
78	size_ int8 // the value of this field is not static, use the size() method to return the value
79	param int16
80	flag  int8
81	scond uint8
82}
83
84func IsAtomicInstruction(as obj.As) bool {
85	if _, ok := atomicLDADD[as]; ok {
86		return true
87	}
88	if _, ok := atomicSWP[as]; ok {
89		return true
90	}
91	return false
92}
93
94// known field values of an instruction.
95var atomicLDADD = map[obj.As]uint32{
96	ALDADDAD:  3<<30 | 0x1c5<<21 | 0x00<<10,
97	ALDADDAW:  2<<30 | 0x1c5<<21 | 0x00<<10,
98	ALDADDAH:  1<<30 | 0x1c5<<21 | 0x00<<10,
99	ALDADDAB:  0<<30 | 0x1c5<<21 | 0x00<<10,
100	ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
101	ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
102	ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
103	ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
104	ALDADDD:   3<<30 | 0x1c1<<21 | 0x00<<10,
105	ALDADDW:   2<<30 | 0x1c1<<21 | 0x00<<10,
106	ALDADDH:   1<<30 | 0x1c1<<21 | 0x00<<10,
107	ALDADDB:   0<<30 | 0x1c1<<21 | 0x00<<10,
108	ALDADDLD:  3<<30 | 0x1c3<<21 | 0x00<<10,
109	ALDADDLW:  2<<30 | 0x1c3<<21 | 0x00<<10,
110	ALDADDLH:  1<<30 | 0x1c3<<21 | 0x00<<10,
111	ALDADDLB:  0<<30 | 0x1c3<<21 | 0x00<<10,
112	ALDCLRAD:  3<<30 | 0x1c5<<21 | 0x04<<10,
113	ALDCLRAW:  2<<30 | 0x1c5<<21 | 0x04<<10,
114	ALDCLRAH:  1<<30 | 0x1c5<<21 | 0x04<<10,
115	ALDCLRAB:  0<<30 | 0x1c5<<21 | 0x04<<10,
116	ALDCLRALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
117	ALDCLRALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
118	ALDCLRALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
119	ALDCLRALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
120	ALDCLRD:   3<<30 | 0x1c1<<21 | 0x04<<10,
121	ALDCLRW:   2<<30 | 0x1c1<<21 | 0x04<<10,
122	ALDCLRH:   1<<30 | 0x1c1<<21 | 0x04<<10,
123	ALDCLRB:   0<<30 | 0x1c1<<21 | 0x04<<10,
124	ALDCLRLD:  3<<30 | 0x1c3<<21 | 0x04<<10,
125	ALDCLRLW:  2<<30 | 0x1c3<<21 | 0x04<<10,
126	ALDCLRLH:  1<<30 | 0x1c3<<21 | 0x04<<10,
127	ALDCLRLB:  0<<30 | 0x1c3<<21 | 0x04<<10,
128	ALDEORAD:  3<<30 | 0x1c5<<21 | 0x08<<10,
129	ALDEORAW:  2<<30 | 0x1c5<<21 | 0x08<<10,
130	ALDEORAH:  1<<30 | 0x1c5<<21 | 0x08<<10,
131	ALDEORAB:  0<<30 | 0x1c5<<21 | 0x08<<10,
132	ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
133	ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
134	ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
135	ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
136	ALDEORD:   3<<30 | 0x1c1<<21 | 0x08<<10,
137	ALDEORW:   2<<30 | 0x1c1<<21 | 0x08<<10,
138	ALDEORH:   1<<30 | 0x1c1<<21 | 0x08<<10,
139	ALDEORB:   0<<30 | 0x1c1<<21 | 0x08<<10,
140	ALDEORLD:  3<<30 | 0x1c3<<21 | 0x08<<10,
141	ALDEORLW:  2<<30 | 0x1c3<<21 | 0x08<<10,
142	ALDEORLH:  1<<30 | 0x1c3<<21 | 0x08<<10,
143	ALDEORLB:  0<<30 | 0x1c3<<21 | 0x08<<10,
144	ALDORAD:   3<<30 | 0x1c5<<21 | 0x0c<<10,
145	ALDORAW:   2<<30 | 0x1c5<<21 | 0x0c<<10,
146	ALDORAH:   1<<30 | 0x1c5<<21 | 0x0c<<10,
147	ALDORAB:   0<<30 | 0x1c5<<21 | 0x0c<<10,
148	ALDORALD:  3<<30 | 0x1c7<<21 | 0x0c<<10,
149	ALDORALW:  2<<30 | 0x1c7<<21 | 0x0c<<10,
150	ALDORALH:  1<<30 | 0x1c7<<21 | 0x0c<<10,
151	ALDORALB:  0<<30 | 0x1c7<<21 | 0x0c<<10,
152	ALDORD:    3<<30 | 0x1c1<<21 | 0x0c<<10,
153	ALDORW:    2<<30 | 0x1c1<<21 | 0x0c<<10,
154	ALDORH:    1<<30 | 0x1c1<<21 | 0x0c<<10,
155	ALDORB:    0<<30 | 0x1c1<<21 | 0x0c<<10,
156	ALDORLD:   3<<30 | 0x1c3<<21 | 0x0c<<10,
157	ALDORLW:   2<<30 | 0x1c3<<21 | 0x0c<<10,
158	ALDORLH:   1<<30 | 0x1c3<<21 | 0x0c<<10,
159	ALDORLB:   0<<30 | 0x1c3<<21 | 0x0c<<10,
160}
161
162var atomicSWP = map[obj.As]uint32{
163	ASWPAD:  3<<30 | 0x1c5<<21 | 0x20<<10,
164	ASWPAW:  2<<30 | 0x1c5<<21 | 0x20<<10,
165	ASWPAH:  1<<30 | 0x1c5<<21 | 0x20<<10,
166	ASWPAB:  0<<30 | 0x1c5<<21 | 0x20<<10,
167	ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10,
168	ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10,
169	ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10,
170	ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10,
171	ASWPD:   3<<30 | 0x1c1<<21 | 0x20<<10,
172	ASWPW:   2<<30 | 0x1c1<<21 | 0x20<<10,
173	ASWPH:   1<<30 | 0x1c1<<21 | 0x20<<10,
174	ASWPB:   0<<30 | 0x1c1<<21 | 0x20<<10,
175	ASWPLD:  3<<30 | 0x1c3<<21 | 0x20<<10,
176	ASWPLW:  2<<30 | 0x1c3<<21 | 0x20<<10,
177	ASWPLH:  1<<30 | 0x1c3<<21 | 0x20<<10,
178	ASWPLB:  0<<30 | 0x1c3<<21 | 0x20<<10,
179	ACASD:   3<<30 | 0x45<<21 | 0x1f<<10,
180	ACASW:   2<<30 | 0x45<<21 | 0x1f<<10,
181	ACASH:   1<<30 | 0x45<<21 | 0x1f<<10,
182	ACASB:   0<<30 | 0x45<<21 | 0x1f<<10,
183	ACASAD:  3<<30 | 0x47<<21 | 0x1f<<10,
184	ACASAW:  2<<30 | 0x47<<21 | 0x1f<<10,
185	ACASLD:  3<<30 | 0x45<<21 | 0x3f<<10,
186	ACASLW:  2<<30 | 0x45<<21 | 0x3f<<10,
187	ACASALD: 3<<30 | 0x47<<21 | 0x3f<<10,
188	ACASALW: 2<<30 | 0x47<<21 | 0x3f<<10,
189	ACASALH: 1<<30 | 0x47<<21 | 0x3f<<10,
190	ACASALB: 0<<30 | 0x47<<21 | 0x3f<<10,
191}
192var atomicCASP = map[obj.As]uint32{
193	ACASPD: 1<<30 | 0x41<<21 | 0x1f<<10,
194	ACASPW: 0<<30 | 0x41<<21 | 0x1f<<10,
195}
196
197var oprange [ALAST & obj.AMask][]Optab
198
199var xcmp [C_NCLASS][C_NCLASS]bool
200
201const (
202	S32     = 0 << 31
203	S64     = 1 << 31
204	Sbit    = 1 << 29
205	LSL0_32 = 2 << 13
206	LSL0_64 = 3 << 13
207)
208
209func OPDP2(x uint32) uint32 {
210	return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
211}
212
213func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
214	return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
215}
216
217func OPBcc(x uint32) uint32 {
218	return 0x2A<<25 | 0<<24 | 0<<4 | x&15
219}
220
221func OPBLR(x uint32) uint32 {
222	/* x=0, JMP; 1, CALL; 2, RET */
223	return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
224}
225
226func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
227	return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
228}
229
230func SYSHINT(x uint32) uint32 {
231	return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
232}
233
234func LDSTR(sz uint32, v uint32, opc uint32) uint32 {
235	return sz<<30 | 7<<27 | v<<26 | opc<<22
236}
237
238func LD2STR(o uint32) uint32 {
239	return o &^ (3 << 22)
240}
241
242func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
243	return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
244}
245
246func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
247	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
248}
249
250func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
251	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
252}
253
254func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
255	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
256}
257
258func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
259	return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
260}
261
262func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
263	return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
264}
265
266func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
267	return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
268}
269
270func ADR(p uint32, o uint32, rt uint32) uint32 {
271	return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
272}
273
274func OPBIT(x uint32) uint32 {
275	return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
276}
277
278func MOVCONST(d int64, s int, rt int) uint32 {
279	return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
280}
281
282const (
283	// Optab.flag
284	LFROM        = 1 << iota // p.From uses constant pool
285	LTO                      // p.To uses constant pool
286	NOTUSETMP                // p expands to multiple instructions, but does NOT use REGTMP
287	BRANCH14BITS             // branch instruction encodes 14 bits
288	BRANCH19BITS             // branch instruction encodes 19 bits
289)
290
291var optab = []Optab{
292	/* struct Optab:
293	OPCODE, from, prog->reg, from3, to, to2, type,size,param,flag,scond */
294	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, C_NONE, 0, 0, 0, 0, 0},
295
296	/* arithmetic operations */
297	{AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
298	{AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
299	{AADC, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
300	{AADC, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
301	{ANEG, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 25, 4, 0, 0, 0},
302	{ANEG, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 25, 4, 0, 0, 0},
303	{ANGC, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 17, 4, 0, 0, 0},
304	{ACMP, C_ZREG, C_ZREG, C_NONE, C_NONE, C_NONE, 1, 4, 0, 0, 0},
305	{AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, C_NONE, 2, 4, 0, 0, 0},
306	{AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, C_NONE, 2, 4, 0, 0, 0},
307	{ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, C_NONE, 2, 4, 0, 0, 0},
308	{AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0},
309	{AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0},
310	{ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0},
311	{AADD, C_BITCON, C_RSP, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0},
312	{AADD, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 62, 8, 0, 0, 0},
313	{ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0},
314	{AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, C_NONE, 48, 8, 0, NOTUSETMP, 0},
315	{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, C_NONE, 48, 8, 0, NOTUSETMP, 0},
316	{AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, C_NONE, 13, 12, 0, 0, 0},
317	{AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, C_NONE, 13, 12, 0, 0, 0},
318	{AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, C_NONE, 13, 16, 0, 0, 0},
319	{AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, C_NONE, 13, 16, 0, 0, 0},
320	{AADD, C_VCON, C_RSP, C_NONE, C_RSP, C_NONE, 13, 20, 0, 0, 0},
321	{AADD, C_VCON, C_NONE, C_NONE, C_RSP, C_NONE, 13, 20, 0, 0, 0},
322	{ACMP, C_MOVCON2, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 12, 0, 0, 0},
323	{ACMP, C_MOVCON3, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 16, 0, 0, 0},
324	{ACMP, C_VCON, C_ZREG, C_NONE, C_NONE, C_NONE, 13, 20, 0, 0, 0},
325	{AADD, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
326	{AADD, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
327	{AMVN, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
328	{ACMP, C_SHIFT, C_ZREG, C_NONE, C_NONE, C_NONE, 3, 4, 0, 0, 0},
329	{ANEG, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
330	{AADD, C_ZREG, C_RSP, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0},
331	{AADD, C_ZREG, C_NONE, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0},
332	{ACMP, C_ZREG, C_RSP, C_NONE, C_NONE, C_NONE, 27, 4, 0, 0, 0},
333	{AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0},
334	{AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, C_NONE, 27, 4, 0, 0, 0},
335	{ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, C_NONE, 27, 4, 0, 0, 0},
336	{AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
337	{AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
338	{AMUL, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 15, 4, 0, 0, 0},
339	{AMUL, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 15, 4, 0, 0, 0},
340	{AMADD, C_ZREG, C_ZREG, C_ZREG, C_ZREG, C_NONE, 15, 4, 0, 0, 0},
341	{AREM, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 16, 8, 0, 0, 0},
342	{AREM, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 16, 8, 0, 0, 0},
343	{ASDIV, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
344	{ASDIV, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
345
346	{AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0},
347	{AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0},
348	{AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, C_NONE, 15, 4, 0, 0, 0},
349	{AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, C_NONE, 56, 4, 0, 0, 0},
350	{AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, C_NONE, 56, 4, 0, 0, 0},
351	{AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0},
352	{AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0},
353	{AVADD, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 89, 4, 0, 0, 0},
354	{AVADD, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 89, 4, 0, 0, 0},
355	{AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, C_NONE, 85, 4, 0, 0, 0},
356
357	/* logical operations */
358	{AAND, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
359	{AAND, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
360	{AANDS, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
361	{AANDS, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 1, 4, 0, 0, 0},
362	{ATST, C_ZREG, C_ZREG, C_NONE, C_NONE, C_NONE, 1, 4, 0, 0, 0},
363	{AAND, C_MBCON, C_ZREG, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0},
364	{AAND, C_MBCON, C_NONE, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0},
365	{AANDS, C_MBCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0},
366	{AANDS, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0},
367	{ATST, C_MBCON, C_ZREG, C_NONE, C_NONE, C_NONE, 53, 4, 0, 0, 0},
368	{AAND, C_BITCON, C_ZREG, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0},
369	{AAND, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 53, 4, 0, 0, 0},
370	{AANDS, C_BITCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0},
371	{AANDS, C_BITCON, C_NONE, C_NONE, C_ZREG, C_NONE, 53, 4, 0, 0, 0},
372	{ATST, C_BITCON, C_ZREG, C_NONE, C_NONE, C_NONE, 53, 4, 0, 0, 0},
373	{AAND, C_MOVCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0},
374	{AAND, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0},
375	{AANDS, C_MOVCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0},
376	{AANDS, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 62, 8, 0, 0, 0},
377	{ATST, C_MOVCON, C_ZREG, C_NONE, C_NONE, C_NONE, 62, 8, 0, 0, 0},
378	{AAND, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0},
379	{AAND, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0},
380	{AAND, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0},
381	{AAND, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0},
382	{AAND, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0},
383	{AAND, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0},
384	{AANDS, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0},
385	{AANDS, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 12, 0, 0, 0},
386	{AANDS, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0},
387	{AANDS, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 16, 0, 0, 0},
388	{AANDS, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0},
389	{AANDS, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 28, 20, 0, 0, 0},
390	{ATST, C_MOVCON2, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 12, 0, 0, 0},
391	{ATST, C_MOVCON3, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 16, 0, 0, 0},
392	{ATST, C_VCON, C_ZREG, C_NONE, C_NONE, C_NONE, 28, 20, 0, 0, 0},
393	{AAND, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
394	{AAND, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
395	{AANDS, C_SHIFT, C_ZREG, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
396	{AANDS, C_SHIFT, C_NONE, C_NONE, C_ZREG, C_NONE, 3, 4, 0, 0, 0},
397	{ATST, C_SHIFT, C_ZREG, C_NONE, C_NONE, C_NONE, 3, 4, 0, 0, 0},
398	{AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, C_NONE, 24, 4, 0, 0, 0},
399	{AMOVD, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 24, 4, 0, 0, 0},
400	{AMVN, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 24, 4, 0, 0, 0},
401	{AMOVB, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVBU */
402	{AMOVH, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVHU */
403	{AMOVW, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0}, /* also MOVWU */
404	/* TODO: MVN C_SHIFT */
405
406	/* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
407	{AMOVW, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0},
408	{AMOVD, C_MBCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0},
409	{AMOVW, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0},
410	{AMOVD, C_MOVCON, C_NONE, C_NONE, C_ZREG, C_NONE, 32, 4, 0, 0, 0},
411	{AMOVW, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 32, 4, 0, 0, 0},
412	{AMOVD, C_BITCON, C_NONE, C_NONE, C_RSP, C_NONE, 32, 4, 0, 0, 0},
413	{AMOVW, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 8, 0, NOTUSETMP, 0},
414	{AMOVD, C_MOVCON2, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 8, 0, NOTUSETMP, 0},
415	{AMOVD, C_MOVCON3, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 12, 0, NOTUSETMP, 0},
416	{AMOVD, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 12, 16, 0, NOTUSETMP, 0},
417
418	{AMOVK, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 33, 4, 0, 0, 0},
419	{AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, C_NONE, 4, 4, REGFROM, 0, 0},
420	{AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, C_NONE, 4, 8, REGFROM, NOTUSETMP, 0},
421
422	/* load long effective stack address (load int32 offset and add) */
423	{AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, C_NONE, 34, 8, REGSP, LFROM, 0},
424
425	// Load a large constant into a vector register.
426	{AVMOVS, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
427	{AVMOVD, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
428	{AVMOVQ, C_ADDR, C_NONE, C_NONE, C_VREG, C_NONE, 65, 12, 0, 0, 0},
429
430	/* jump operations */
431	{AB, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0},
432	{ABL, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0},
433	{AB, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0},
434	{ABL, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 6, 4, 0, 0, 0},
435	{ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0},
436	{obj.ARET, C_NONE, C_NONE, C_NONE, C_ZREG, C_NONE, 6, 4, 0, 0, 0},
437	{obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 6, 4, 0, 0, 0},
438	{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 7, 4, 0, BRANCH19BITS, 0},
439	{ACBZ, C_ZREG, C_NONE, C_NONE, C_SBRA, C_NONE, 39, 4, 0, BRANCH19BITS, 0},
440	{ATBZ, C_VCON, C_ZREG, C_NONE, C_SBRA, C_NONE, 40, 4, 0, BRANCH14BITS, 0},
441	{AERET, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
442
443	// get a PC-relative address
444	{AADRP, C_SBRA, C_NONE, C_NONE, C_ZREG, C_NONE, 60, 4, 0, 0, 0},
445	{AADR, C_SBRA, C_NONE, C_NONE, C_ZREG, C_NONE, 61, 4, 0, 0, 0},
446
447	{ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, C_NONE, 38, 4, 0, 0, 0},
448	{ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
449	{ABFM, C_VCON, C_ZREG, C_VCON, C_ZREG, C_NONE, 42, 4, 0, 0, 0},
450	{ABFI, C_VCON, C_ZREG, C_VCON, C_ZREG, C_NONE, 43, 4, 0, 0, 0},
451	{AEXTR, C_VCON, C_ZREG, C_ZREG, C_ZREG, C_NONE, 44, 4, 0, 0, 0},
452	{ASXTB, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 45, 4, 0, 0, 0},
453	{ACLS, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 46, 4, 0, 0, 0},
454	{ALSL, C_VCON, C_ZREG, C_NONE, C_ZREG, C_NONE, 8, 4, 0, 0, 0},
455	{ALSL, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 8, 4, 0, 0, 0},
456	{ALSL, C_ZREG, C_NONE, C_NONE, C_ZREG, C_NONE, 9, 4, 0, 0, 0},
457	{ALSL, C_ZREG, C_ZREG, C_NONE, C_ZREG, C_NONE, 9, 4, 0, 0, 0},
458	{ASVC, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
459	{ASVC, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
460	{ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, C_NONE, 11, 8, 0, NOTUSETMP, 0},
461	{ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, C_NONE, 11, 8, 0, NOTUSETMP, 0},
462	{ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, C_NONE, 11, 8, 0, NOTUSETMP, 0},
463	{ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, C_NONE, 11, 8, 0, NOTUSETMP, 0},
464	{AWORD, C_NONE, C_NONE, C_NONE, C_LCON, C_NONE, 14, 4, 0, 0, 0},
465	{AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, C_NONE, 14, 4, 0, 0, 0},
466	{AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, C_NONE, 14, 4, 0, 0, 0},
467	{AMOVW, C_VCONADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 68, 8, 0, NOTUSETMP, 0},
468	{AMOVD, C_VCONADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 68, 8, 0, NOTUSETMP, 0},
469	{AMOVB, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
470	{AMOVH, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
471	{AMOVW, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
472	{AMOVD, C_ZREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
473	{AMOVB, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0},
474	{AMOVH, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0},
475	{AMOVW, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0},
476	{AMOVD, C_ADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 65, 12, 0, 0, 0},
477	{AMOVD, C_GOTADDR, C_NONE, C_NONE, C_ZREG, C_NONE, 71, 8, 0, 0, 0},
478	{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_ZREG, C_NONE, 69, 4, 0, 0, 0},
479	{AMOVD, C_TLS_IE, C_NONE, C_NONE, C_ZREG, C_NONE, 70, 8, 0, 0, 0},
480
481	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
482	{AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 65, 12, 0, 0, 0},
483	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 64, 12, 0, 0, 0},
484	{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 65, 12, 0, 0, 0},
485	{AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, C_NONE, 55, 4, 0, 0, 0},
486	{AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0},
487	{AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, C_NONE, 55, 4, 0, 0, 0},
488	{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 54, 4, 0, 0, 0},
489	{AFMOVS, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0},
490	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0},
491	{AFMOVD, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0},
492	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0},
493	{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_ZREG, C_NONE, 29, 4, 0, 0, 0},
494	{ASCVTFD, C_ZREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0},
495	{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 29, 4, 0, 0, 0},
496	{AVMOV, C_ELEM, C_NONE, C_NONE, C_ZREG, C_NONE, 73, 4, 0, 0, 0},
497	{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, C_NONE, 92, 4, 0, 0, 0},
498	{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, C_NONE, 80, 4, 0, 0, 0},
499	{AVMOV, C_ZREG, C_NONE, C_NONE, C_ARNG, C_NONE, 82, 4, 0, 0, 0},
500	{AVMOV, C_ZREG, C_NONE, C_NONE, C_ELEM, C_NONE, 78, 4, 0, 0, 0},
501	{AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 83, 4, 0, 0, 0},
502	{AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, C_NONE, 79, 4, 0, 0, 0},
503	{AVDUP, C_ELEM, C_NONE, C_NONE, C_VREG, C_NONE, 80, 4, 0, 0, 0},
504	{AVDUP, C_ZREG, C_NONE, C_NONE, C_ARNG, C_NONE, 82, 4, 0, 0, 0},
505	{AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, C_NONE, 86, 4, 0, 0, 0},
506	{AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0},
507	{AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, C_NONE, 94, 4, 0, 0, 0},
508	{AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, C_NONE, 100, 4, 0, 0, 0},
509	{AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, C_NONE, 95, 4, 0, 0, 0},
510	{AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 72, 4, 0, 0, 0},
511	{AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, C_NONE, 102, 4, 0, 0, 0},
512	{AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 102, 4, 0, 0, 0},
513	{AVUADDW, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 105, 4, 0, 0, 0},
514
515	/* conditional operations */
516	{ACSEL, C_COND, C_ZREG, C_ZREG, C_ZREG, C_NONE, 18, 4, 0, 0, 0},
517	{ACINC, C_COND, C_ZREG, C_NONE, C_ZREG, C_NONE, 18, 4, 0, 0, 0},
518	{ACSET, C_COND, C_NONE, C_NONE, C_ZREG, C_NONE, 18, 4, 0, 0, 0},
519	{AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, C_NONE, 18, 4, 0, 0, 0},
520	{ACCMN, C_COND, C_ZREG, C_ZREG, C_VCON, C_NONE, 19, 4, 0, 0, 0},
521	{ACCMN, C_COND, C_ZREG, C_VCON, C_VCON, C_NONE, 19, 4, 0, 0, 0},
522	{AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, C_NONE, 57, 4, 0, 0, 0},
523
524	/* scaled 12-bit unsigned displacement store */
525	{AMOVB, C_ZREG, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 20, 4, REGSP, 0, 0},
526	{AMOVB, C_ZREG, C_NONE, C_NONE, C_UOREG4K, C_NONE, 20, 4, 0, 0, 0},
527	{AMOVH, C_ZREG, C_NONE, C_NONE, C_UAUTO8K, C_NONE, 20, 4, REGSP, 0, 0},
528	{AMOVH, C_ZREG, C_NONE, C_NONE, C_UOREG8K, C_NONE, 20, 4, 0, 0, 0},
529	{AMOVW, C_ZREG, C_NONE, C_NONE, C_UAUTO16K, C_NONE, 20, 4, REGSP, 0, 0},
530	{AMOVW, C_ZREG, C_NONE, C_NONE, C_UOREG16K, C_NONE, 20, 4, 0, 0, 0},
531	{AMOVD, C_ZREG, C_NONE, C_NONE, C_UAUTO32K, C_NONE, 20, 4, REGSP, 0, 0},
532	{AMOVD, C_ZREG, C_NONE, C_NONE, C_UOREG32K, C_NONE, 20, 4, 0, 0, 0},
533
534	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, C_NONE, 20, 4, REGSP, 0, 0},
535	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, C_NONE, 20, 4, 0, 0, 0},
536	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, C_NONE, 20, 4, REGSP, 0, 0},
537	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, C_NONE, 20, 4, 0, 0, 0},
538	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_UAUTO64K, C_NONE, 20, 4, REGSP, 0, 0},
539	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_UOREG64K, C_NONE, 20, 4, 0, 0, 0},
540
541	/* unscaled 9-bit signed displacement store */
542	{AMOVB, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
543	{AMOVB, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
544	{AMOVH, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
545	{AMOVH, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
546	{AMOVW, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
547	{AMOVW, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
548	{AMOVD, C_ZREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
549	{AMOVD, C_ZREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
550
551	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
552	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
553	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
554	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
555	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSAUTO, C_NONE, 20, 4, REGSP, 0, 0},
556	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSOREG, C_NONE, 20, 4, 0, 0, 0},
557
558	/* scaled 12-bit unsigned displacement load */
559	{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
560	{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
561	{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
562	{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
563	{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
564	{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
565	{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
566	{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
567
568	{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
569	{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
570	{AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
571	{AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
572	{AFMOVQ, C_UAUTO64K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
573	{AFMOVQ, C_UOREG64K, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
574
575	/* unscaled 9-bit signed displacement load */
576	{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
577	{AMOVB, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
578	{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
579	{AMOVH, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
580	{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
581	{AMOVW, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
582	{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, REGSP, 0, 0},
583	{AMOVD, C_NSOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 21, 4, 0, 0, 0},
584
585	{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
586	{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
587	{AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
588	{AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
589	{AFMOVQ, C_NSAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, REGSP, 0, 0},
590	{AFMOVQ, C_NSOREG, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0, 0},
591
592	/* long displacement store */
593	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
594	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
595	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
596	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
597	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
598	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
599	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
600	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
601	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
602	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
603	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
604	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
605	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
606	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
607	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
608	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
609
610	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
611	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
612	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
613	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
614	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
615	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
616	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
617	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
618	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 30, 8, REGSP, 0, 0},
619	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 30, 8, REGSP, LTO, 0},
620	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 30, 8, 0, 0, 0},
621	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 30, 8, 0, LTO, 0},
622
623	/* long displacement load */
624	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0},
625	{AMOVB, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0},
626	{AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0},
627	{AMOVB, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0},
628	{AMOVH, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0},
629	{AMOVH, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0},
630	{AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0},
631	{AMOVH, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0},
632	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0},
633	{AMOVW, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0},
634	{AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0},
635	{AMOVW, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0},
636	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, 0, 0},
637	{AMOVD, C_LAUTOPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, REGSP, LFROM, 0},
638	{AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, 0, 0},
639	{AMOVD, C_LOREGPOOL, C_NONE, C_NONE, C_ZREG, C_NONE, 31, 8, 0, LFROM, 0},
640
641	{AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0},
642	{AFMOVS, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0},
643	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0},
644	{AFMOVS, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0},
645	{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0},
646	{AFMOVD, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0},
647	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0},
648	{AFMOVD, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0},
649	{AFMOVQ, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, 0, 0},
650	{AFMOVQ, C_LAUTOPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, REGSP, LFROM, 0},
651	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, 0, 0},
652	{AFMOVQ, C_LOREGPOOL, C_NONE, C_NONE, C_FREG, C_NONE, 31, 8, 0, LFROM, 0},
653
654	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
655	{AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST},
656	{AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST},
657	{AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST},
658	{AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPOST},
659	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST},
660	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST},
661	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPOST},
662
663	{AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE},
664	{AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE},
665	{AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE},
666	{AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 22, 4, 0, 0, C_XPRE},
667	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE},
668	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE},
669	{AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 22, 4, 0, 0, C_XPRE},
670
671	/* pre/post-indexed store (unscaled, signed 9-bit offset) */
672	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
673	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
674	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
675	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
676	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
677	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
678	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPOST},
679
680	{AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
681	{AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
682	{AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
683	{AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
684	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
685	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
686	{AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 23, 4, 0, 0, C_XPRE},
687
688	/* load with shifted or extended register offset */
689	{AMOVD, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0},
690	{AMOVW, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0},
691	{AMOVH, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0},
692	{AMOVB, C_ROFF, C_NONE, C_NONE, C_ZREG, C_NONE, 98, 4, 0, 0, 0},
693	{AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, C_NONE, 98, 4, 0, 0, 0},
694	{AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, C_NONE, 98, 4, 0, 0, 0},
695
696	/* store with extended register offset */
697	{AMOVD, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
698	{AMOVW, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
699	{AMOVH, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
700	{AMOVB, C_ZREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
701	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
702	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, C_NONE, 99, 4, 0, 0, 0},
703
704	/* pre/post-indexed/signed-offset load/store register pair
705	   (unscaled, signed 10-bit quad-aligned and long offset).
706	The pre/post-indexed format only supports OREG cases because
707	the RSP and pseudo registers are not allowed to be modified
708	in this way. */
709	{AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
710	{AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
711	{AFLDPQ, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
712	{AFLDPQ, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
713	{AFLDPQ, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0},
714	{AFLDPQ, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0},
715	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
716	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
717	{AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
718	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
719	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
720	{AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
721	{AFLDPQ, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
722	{AFLDPQ, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
723	{AFLDPQ, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0},
724	{AFLDPQ, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0},
725	{AFLDPQ, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0},
726
727	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, C_NONE, 67, 4, REGSP, 0, 0},
728	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, C_NONE, 67, 4, REGSP, 0, 0},
729	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
730	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
731	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0},
732	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0},
733	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, 0},
734	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, C_XPRE},
735	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, C_NONE, 67, 4, 0, 0, C_XPOST},
736	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, 0},
737	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, C_XPRE},
738	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, C_NONE, 67, 4, 0, 0, C_XPOST},
739	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0},
740	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0},
741	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0},
742	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0},
743	{AFSTPQ, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0},
744
745	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
746	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
747	{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
748	{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
749	{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0},
750	{ALDP, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0},
751	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
752	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
753	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
754	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
755	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
756	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
757	{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
758	{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
759	{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0},
760	{ALDP, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0},
761	{ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0},
762
763	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, C_NONE, 67, 4, REGSP, 0, 0},
764	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, C_NONE, 67, 4, REGSP, 0, 0},
765	{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
766	{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
767	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0},
768	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0},
769	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, 0},
770	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, C_XPRE},
771	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, C_NONE, 67, 4, 0, 0, C_XPOST},
772	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, 0},
773	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, C_XPRE},
774	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, C_NONE, 67, 4, 0, 0, C_XPOST},
775	{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0},
776	{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0},
777	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0},
778	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0},
779	{ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0},
780
781	// differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
782	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
783	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, REGSP, 0, 0},
784	{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
785	{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, REGSP, 0, 0},
786	{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, 0, 0},
787	{ALDPW, C_LAUTOPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, REGSP, LFROM, 0},
788	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
789	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
790	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
791	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, 0},
792	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPRE},
793	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, C_NONE, 66, 4, 0, 0, C_XPOST},
794	{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
795	{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, C_NONE, 74, 8, 0, 0, 0},
796	{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, 0, 0},
797	{ALDPW, C_LOREGPOOL, C_NONE, C_NONE, C_PAIR, C_NONE, 75, 12, 0, LFROM, 0},
798	{ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, C_NONE, 88, 12, 0, 0, 0},
799
800	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, C_NONE, 67, 4, REGSP, 0, 0},
801	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, C_NONE, 67, 4, REGSP, 0, 0},
802	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
803	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, C_NONE, 76, 8, REGSP, 0, 0},
804	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, C_NONE, 77, 12, REGSP, 0, 0},
805	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTOPOOL, C_NONE, 77, 12, REGSP, LTO, 0},
806	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, 0},
807	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, C_XPRE},
808	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, C_NONE, 67, 4, 0, 0, C_XPOST},
809	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, 0},
810	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, C_XPRE},
811	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, C_NONE, 67, 4, 0, 0, C_XPOST},
812	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, C_NONE, 76, 8, 0, 0, 0},
813	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, C_NONE, 76, 8, 0, 0, 0},
814	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, C_NONE, 77, 12, 0, 0, 0},
815	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREGPOOL, C_NONE, 77, 12, 0, LTO, 0},
816	{ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, C_NONE, 87, 12, 0, 0, 0},
817
818	{ASWPD, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 47, 4, 0, 0, 0},
819	{ASWPD, C_ZREG, C_NONE, C_NONE, C_ZAUTO, C_ZREG, 47, 4, REGSP, 0, 0},
820	{ACASPD, C_PAIR, C_NONE, C_NONE, C_ZOREG, C_PAIR, 106, 4, 0, 0, 0},
821	{ACASPD, C_PAIR, C_NONE, C_NONE, C_ZAUTO, C_PAIR, 106, 4, REGSP, 0, 0},
822	{ALDAR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0},
823	{ALDXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0},
824	{ALDAXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, C_NONE, 58, 4, 0, 0, 0},
825	{ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, C_NONE, 58, 4, 0, 0, 0},
826	{ASTLR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_NONE, 59, 4, 0, 0, 0},
827	{ASTXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0},
828	{ASTLXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0},
829	{ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, C_ZREG, 59, 4, 0, 0, 0},
830
831	/* VLD[1-4]/VST[1-4] */
832	{AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, 0},
833	{AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST},
834	{AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST},
835	{AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, 0},
836	{AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST},
837	{AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, C_NONE, 81, 4, 0, 0, C_XPOST},
838	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, C_XPOST},
839	{AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, C_XPOST},
840	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, C_NONE, 97, 4, 0, 0, 0},
841	{AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0},
842	{AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST},
843	{AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST},
844	{AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0},
845	{AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST},
846	{AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST},
847	{AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0},
848	{AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST},
849	{AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST},
850	{AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, C_NONE, 84, 4, 0, 0, 0},
851	{AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, C_NONE, 84, 4, 0, 0, C_XPOST},
852	{AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, C_NONE, 84, 4, 0, 0, C_XPOST},
853	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, C_NONE, 96, 4, 0, 0, C_XPOST},
854	{AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, C_NONE, 96, 4, 0, 0, C_XPOST},
855	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, C_NONE, 96, 4, 0, 0, 0},
856
857	/* special */
858	{AMOVD, C_SPR, C_NONE, C_NONE, C_ZREG, C_NONE, 35, 4, 0, 0, 0},
859	{AMRS, C_SPR, C_NONE, C_NONE, C_ZREG, C_NONE, 35, 4, 0, 0, 0},
860	{AMOVD, C_ZREG, C_NONE, C_NONE, C_SPR, C_NONE, 36, 4, 0, 0, 0},
861	{AMSR, C_ZREG, C_NONE, C_NONE, C_SPR, C_NONE, 36, 4, 0, 0, 0},
862	{AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, C_NONE, 37, 4, 0, 0, 0},
863	{AMSR, C_VCON, C_NONE, C_NONE, C_SPR, C_NONE, 37, 4, 0, 0, 0},
864	{AMSR, C_VCON, C_NONE, C_NONE, C_SPOP, C_NONE, 37, 4, 0, 0, 0},
865	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPOP, C_NONE, 91, 4, 0, 0, 0},
866	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, C_NONE, 91, 4, 0, 0, 0},
867	{ADMB, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
868	{AHINT, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
869	{ASYS, C_VCON, C_NONE, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
870	{ASYS, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 50, 4, 0, 0, 0},
871	{ASYSL, C_VCON, C_NONE, C_NONE, C_ZREG, C_NONE, 50, 4, 0, 0, 0},
872	{ATLBI, C_SPOP, C_NONE, C_NONE, C_NONE, C_NONE, 107, 4, 0, 0, 0},
873	{ATLBI, C_SPOP, C_NONE, C_NONE, C_ZREG, C_NONE, 107, 4, 0, 0, 0},
874
875	/* encryption instructions */
876	{AAESD, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 26, 4, 0, 0, 0}, // for compatibility with old code
877	{AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 26, 4, 0, 0, 0}, // recommend using the new one for better readability
878	{ASHA1C, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 49, 4, 0, 0, 0},
879	{ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, C_NONE, 49, 4, 0, 0, 0},
880	{ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 63, 4, 0, 0, 0},
881	{AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, C_NONE, 83, 4, 0, 0, 0},
882	{AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, C_NONE, 93, 4, 0, 0, 0},
883	{AVEOR3, C_ARNG, C_ARNG, C_ARNG, C_ARNG, C_NONE, 103, 4, 0, 0, 0},
884	{AVXAR, C_VCON, C_ARNG, C_ARNG, C_ARNG, C_NONE, 104, 4, 0, 0, 0},
885	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
886	{obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, C_NONE, 0, 0, 0, 0, 0},
887	{obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, C_NONE, 0, 0, 0, 0, 0},
888	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
889	{obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
890	{obj.ANOP, C_ZREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
891	{obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
892	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0},   // same as AB/ABL
893	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 5, 4, 0, 0, 0},   // same as AB/ABL
894	{obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},    // align code
895	{obj.APCALIGNMAX, C_LCON, C_NONE, C_NONE, C_LCON, C_NONE, 0, 0, 0, 0, 0}, // align code, conditional
896}
897
898// Valid pstate field values, and value to use in instruction.
899// Doesn't include special registers.
900var pstatefield = []struct {
901	opd SpecialOperand
902	enc uint32
903}{
904	{SPOP_DAIFSet, 3<<16 | 4<<12 | 6<<5},
905	{SPOP_DAIFClr, 3<<16 | 4<<12 | 7<<5},
906}
907
908var prfopfield = map[SpecialOperand]uint32{
909	SPOP_PLDL1KEEP: 0,
910	SPOP_PLDL1STRM: 1,
911	SPOP_PLDL2KEEP: 2,
912	SPOP_PLDL2STRM: 3,
913	SPOP_PLDL3KEEP: 4,
914	SPOP_PLDL3STRM: 5,
915	SPOP_PLIL1KEEP: 8,
916	SPOP_PLIL1STRM: 9,
917	SPOP_PLIL2KEEP: 10,
918	SPOP_PLIL2STRM: 11,
919	SPOP_PLIL3KEEP: 12,
920	SPOP_PLIL3STRM: 13,
921	SPOP_PSTL1KEEP: 16,
922	SPOP_PSTL1STRM: 17,
923	SPOP_PSTL2KEEP: 18,
924	SPOP_PSTL2STRM: 19,
925	SPOP_PSTL3KEEP: 20,
926	SPOP_PSTL3STRM: 21,
927}
928
929// sysInstFields helps convert SYS alias instructions to SYS instructions.
930// For example, the format of TLBI is: TLBI <tlbi_op>{, <Xt>}.
931// It's equivalent to: SYS #<op1>, C8, <Cm>, #<op2>{, <Xt>}.
932// The field hasOperand2 indicates whether Xt is required. It helps to check
933// some combinations that may be undefined, such as TLBI VMALLE1IS, R0.
934var sysInstFields = map[SpecialOperand]struct {
935	op1         uint8
936	cn          uint8
937	cm          uint8
938	op2         uint8
939	hasOperand2 bool
940}{
941	// TLBI
942	SPOP_VMALLE1IS:    {0, 8, 3, 0, false},
943	SPOP_VAE1IS:       {0, 8, 3, 1, true},
944	SPOP_ASIDE1IS:     {0, 8, 3, 2, true},
945	SPOP_VAAE1IS:      {0, 8, 3, 3, true},
946	SPOP_VALE1IS:      {0, 8, 3, 5, true},
947	SPOP_VAALE1IS:     {0, 8, 3, 7, true},
948	SPOP_VMALLE1:      {0, 8, 7, 0, false},
949	SPOP_VAE1:         {0, 8, 7, 1, true},
950	SPOP_ASIDE1:       {0, 8, 7, 2, true},
951	SPOP_VAAE1:        {0, 8, 7, 3, true},
952	SPOP_VALE1:        {0, 8, 7, 5, true},
953	SPOP_VAALE1:       {0, 8, 7, 7, true},
954	SPOP_IPAS2E1IS:    {4, 8, 0, 1, true},
955	SPOP_IPAS2LE1IS:   {4, 8, 0, 5, true},
956	SPOP_ALLE2IS:      {4, 8, 3, 0, false},
957	SPOP_VAE2IS:       {4, 8, 3, 1, true},
958	SPOP_ALLE1IS:      {4, 8, 3, 4, false},
959	SPOP_VALE2IS:      {4, 8, 3, 5, true},
960	SPOP_VMALLS12E1IS: {4, 8, 3, 6, false},
961	SPOP_IPAS2E1:      {4, 8, 4, 1, true},
962	SPOP_IPAS2LE1:     {4, 8, 4, 5, true},
963	SPOP_ALLE2:        {4, 8, 7, 0, false},
964	SPOP_VAE2:         {4, 8, 7, 1, true},
965	SPOP_ALLE1:        {4, 8, 7, 4, false},
966	SPOP_VALE2:        {4, 8, 7, 5, true},
967	SPOP_VMALLS12E1:   {4, 8, 7, 6, false},
968	SPOP_ALLE3IS:      {6, 8, 3, 0, false},
969	SPOP_VAE3IS:       {6, 8, 3, 1, true},
970	SPOP_VALE3IS:      {6, 8, 3, 5, true},
971	SPOP_ALLE3:        {6, 8, 7, 0, false},
972	SPOP_VAE3:         {6, 8, 7, 1, true},
973	SPOP_VALE3:        {6, 8, 7, 5, true},
974	SPOP_VMALLE1OS:    {0, 8, 1, 0, false},
975	SPOP_VAE1OS:       {0, 8, 1, 1, true},
976	SPOP_ASIDE1OS:     {0, 8, 1, 2, true},
977	SPOP_VAAE1OS:      {0, 8, 1, 3, true},
978	SPOP_VALE1OS:      {0, 8, 1, 5, true},
979	SPOP_VAALE1OS:     {0, 8, 1, 7, true},
980	SPOP_RVAE1IS:      {0, 8, 2, 1, true},
981	SPOP_RVAAE1IS:     {0, 8, 2, 3, true},
982	SPOP_RVALE1IS:     {0, 8, 2, 5, true},
983	SPOP_RVAALE1IS:    {0, 8, 2, 7, true},
984	SPOP_RVAE1OS:      {0, 8, 5, 1, true},
985	SPOP_RVAAE1OS:     {0, 8, 5, 3, true},
986	SPOP_RVALE1OS:     {0, 8, 5, 5, true},
987	SPOP_RVAALE1OS:    {0, 8, 5, 7, true},
988	SPOP_RVAE1:        {0, 8, 6, 1, true},
989	SPOP_RVAAE1:       {0, 8, 6, 3, true},
990	SPOP_RVALE1:       {0, 8, 6, 5, true},
991	SPOP_RVAALE1:      {0, 8, 6, 7, true},
992	SPOP_RIPAS2E1IS:   {4, 8, 0, 2, true},
993	SPOP_RIPAS2LE1IS:  {4, 8, 0, 6, true},
994	SPOP_ALLE2OS:      {4, 8, 1, 0, false},
995	SPOP_VAE2OS:       {4, 8, 1, 1, true},
996	SPOP_ALLE1OS:      {4, 8, 1, 4, false},
997	SPOP_VALE2OS:      {4, 8, 1, 5, true},
998	SPOP_VMALLS12E1OS: {4, 8, 1, 6, false},
999	SPOP_RVAE2IS:      {4, 8, 2, 1, true},
1000	SPOP_RVALE2IS:     {4, 8, 2, 5, true},
1001	SPOP_IPAS2E1OS:    {4, 8, 4, 0, true},
1002	SPOP_RIPAS2E1:     {4, 8, 4, 2, true},
1003	SPOP_RIPAS2E1OS:   {4, 8, 4, 3, true},
1004	SPOP_IPAS2LE1OS:   {4, 8, 4, 4, true},
1005	SPOP_RIPAS2LE1:    {4, 8, 4, 6, true},
1006	SPOP_RIPAS2LE1OS:  {4, 8, 4, 7, true},
1007	SPOP_RVAE2OS:      {4, 8, 5, 1, true},
1008	SPOP_RVALE2OS:     {4, 8, 5, 5, true},
1009	SPOP_RVAE2:        {4, 8, 6, 1, true},
1010	SPOP_RVALE2:       {4, 8, 6, 5, true},
1011	SPOP_ALLE3OS:      {6, 8, 1, 0, false},
1012	SPOP_VAE3OS:       {6, 8, 1, 1, true},
1013	SPOP_VALE3OS:      {6, 8, 1, 5, true},
1014	SPOP_RVAE3IS:      {6, 8, 2, 1, true},
1015	SPOP_RVALE3IS:     {6, 8, 2, 5, true},
1016	SPOP_RVAE3OS:      {6, 8, 5, 1, true},
1017	SPOP_RVALE3OS:     {6, 8, 5, 5, true},
1018	SPOP_RVAE3:        {6, 8, 6, 1, true},
1019	SPOP_RVALE3:       {6, 8, 6, 5, true},
1020	// DC
1021	SPOP_IVAC:    {0, 7, 6, 1, true},
1022	SPOP_ISW:     {0, 7, 6, 2, true},
1023	SPOP_CSW:     {0, 7, 10, 2, true},
1024	SPOP_CISW:    {0, 7, 14, 2, true},
1025	SPOP_ZVA:     {3, 7, 4, 1, true},
1026	SPOP_CVAC:    {3, 7, 10, 1, true},
1027	SPOP_CVAU:    {3, 7, 11, 1, true},
1028	SPOP_CIVAC:   {3, 7, 14, 1, true},
1029	SPOP_IGVAC:   {0, 7, 6, 3, true},
1030	SPOP_IGSW:    {0, 7, 6, 4, true},
1031	SPOP_IGDVAC:  {0, 7, 6, 5, true},
1032	SPOP_IGDSW:   {0, 7, 6, 6, true},
1033	SPOP_CGSW:    {0, 7, 10, 4, true},
1034	SPOP_CGDSW:   {0, 7, 10, 6, true},
1035	SPOP_CIGSW:   {0, 7, 14, 4, true},
1036	SPOP_CIGDSW:  {0, 7, 14, 6, true},
1037	SPOP_GVA:     {3, 7, 4, 3, true},
1038	SPOP_GZVA:    {3, 7, 4, 4, true},
1039	SPOP_CGVAC:   {3, 7, 10, 3, true},
1040	SPOP_CGDVAC:  {3, 7, 10, 5, true},
1041	SPOP_CGVAP:   {3, 7, 12, 3, true},
1042	SPOP_CGDVAP:  {3, 7, 12, 5, true},
1043	SPOP_CGVADP:  {3, 7, 13, 3, true},
1044	SPOP_CGDVADP: {3, 7, 13, 5, true},
1045	SPOP_CIGVAC:  {3, 7, 14, 3, true},
1046	SPOP_CIGDVAC: {3, 7, 14, 5, true},
1047	SPOP_CVAP:    {3, 7, 12, 1, true},
1048	SPOP_CVADP:   {3, 7, 13, 1, true},
1049}
1050
1051// Used for padding NOOP instruction
1052const OP_NOOP = 0xd503201f
1053
1054// pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
1055// reporting an error if alignedValue is not a power of two or is out of range.
1056func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
1057	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
1058		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
1059	}
1060	return int(-pc & (alignedValue - 1))
1061}
1062
1063// size returns the size of the sequence of machine instructions when p is encoded with o.
1064// Usually it just returns o.size directly, in some cases it checks whether the optimization
1065// conditions are met, and if so returns the size of the optimized instruction sequence.
1066// These optimizations need to be synchronized with the asmout function.
1067func (o *Optab) size(ctxt *obj.Link, p *obj.Prog) int {
1068	// Optimize adrp+add+ld/st to adrp+ld/st(offset).
1069	sz := movesize(p.As)
1070	if sz != -1 {
1071		// Relocations R_AARCH64_LDST{64,32,16,8}_ABS_LO12_NC can only generate 8-byte, 4-byte,
1072		// 2-byte and 1-byte aligned addresses, so the address of load/store must be aligned.
1073		// Also symbols with prefix of "go:string." are Go strings, which will go into
1074		// the symbol table, their addresses are not necessary aligned, rule this out.
1075		align := int64(1 << sz)
1076		if o.a1 == C_ADDR && p.From.Offset%align == 0 && !strings.HasPrefix(p.From.Sym.Name, "go:string.") ||
1077			o.a4 == C_ADDR && p.To.Offset%align == 0 && !strings.HasPrefix(p.To.Sym.Name, "go:string.") {
1078			return 8
1079		}
1080	}
1081	return int(o.size_)
1082}
1083
1084func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
1085	if ctxt.Retpoline {
1086		ctxt.Diag("-spectre=ret not supported on arm64")
1087		ctxt.Retpoline = false // don't keep printing
1088	}
1089
1090	p := cursym.Func().Text
1091	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
1092		return
1093	}
1094
1095	if oprange[AAND&obj.AMask] == nil {
1096		ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
1097	}
1098
1099	c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
1100	p.To.Offset &= 0xffffffff // extrasize is no longer needed
1101
1102	bflag := 1
1103	pc := int64(0)
1104	p.Pc = pc
1105	var m int
1106	var o *Optab
1107	for p = p.Link; p != nil; p = p.Link {
1108		p.Pc = pc
1109		o = c.oplook(p)
1110		m = o.size(c.ctxt, p)
1111		if m == 0 {
1112			switch p.As {
1113			case obj.APCALIGN, obj.APCALIGNMAX:
1114				m = obj.AlignmentPadding(int32(pc), p, ctxt, cursym)
1115				break
1116			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1117				continue
1118			default:
1119				c.ctxt.Diag("zero-width instruction\n%v", p)
1120			}
1121		}
1122		pc += int64(m)
1123
1124		if o.flag&LFROM != 0 {
1125			c.addpool(p, &p.From)
1126		}
1127		if o.flag&LTO != 0 {
1128			c.addpool(p, &p.To)
1129		}
1130		if c.blitrl != nil {
1131			c.checkpool(p)
1132		}
1133	}
1134
1135	c.cursym.Size = pc
1136
1137	/*
1138	 * if any procedure is large enough to
1139	 * generate a large SBRA branch, then
1140	 * generate extra passes putting branches
1141	 * around jmps to fix. this is rare.
1142	 */
1143	for bflag != 0 {
1144		bflag = 0
1145		pc = 0
1146		for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
1147			p.Pc = pc
1148			o = c.oplook(p)
1149
1150			/* very large branches */
1151			if (o.flag&BRANCH14BITS != 0 || o.flag&BRANCH19BITS != 0) && p.To.Target() != nil {
1152				otxt := p.To.Target().Pc - pc
1153				var toofar bool
1154				if o.flag&BRANCH14BITS != 0 { // branch instruction encodes 14 bits
1155					toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
1156				} else if o.flag&BRANCH19BITS != 0 { // branch instruction encodes 19 bits
1157					toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
1158				}
1159				if toofar {
1160					q := c.newprog()
1161					q.Link = p.Link
1162					p.Link = q
1163					q.As = AB
1164					q.To.Type = obj.TYPE_BRANCH
1165					q.To.SetTarget(p.To.Target())
1166					p.To.SetTarget(q)
1167					q = c.newprog()
1168					q.Link = p.Link
1169					p.Link = q
1170					q.As = AB
1171					q.To.Type = obj.TYPE_BRANCH
1172					q.To.SetTarget(q.Link.Link)
1173					bflag = 1
1174				}
1175			}
1176			m = o.size(c.ctxt, p)
1177
1178			if m == 0 {
1179				switch p.As {
1180				case obj.APCALIGN, obj.APCALIGNMAX:
1181					m = obj.AlignmentPaddingLength(int32(pc), p, ctxt)
1182					break
1183				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1184					continue
1185				default:
1186					c.ctxt.Diag("zero-width instruction\n%v", p)
1187				}
1188			}
1189
1190			pc += int64(m)
1191		}
1192	}
1193
1194	pc += -pc & (funcAlign - 1)
1195	c.cursym.Size = pc
1196
1197	/*
1198	 * lay out the code, emitting code and data relocations.
1199	 */
1200	c.cursym.Grow(c.cursym.Size)
1201	bp := c.cursym.P
1202	psz := int32(0)
1203	var i int
1204	var out [6]uint32
1205	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
1206		c.pc = p.Pc
1207		o = c.oplook(p)
1208		sz := o.size(c.ctxt, p)
1209		if sz > 4*len(out) {
1210			log.Fatalf("out array in span7 is too small, need at least %d for %v", sz/4, p)
1211		}
1212		if p.As == obj.APCALIGN || p.As == obj.APCALIGNMAX {
1213			v := obj.AlignmentPaddingLength(int32(p.Pc), p, c.ctxt)
1214			for i = 0; i < int(v/4); i++ {
1215				// emit ANOOP instruction by the padding size
1216				c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
1217				bp = bp[4:]
1218				psz += 4
1219			}
1220		} else {
1221			c.asmout(p, o, out[:])
1222			for i = 0; i < sz/4; i++ {
1223				c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
1224				bp = bp[4:]
1225				psz += 4
1226			}
1227		}
1228	}
1229
1230	// Mark nonpreemptible instruction sequences.
1231	// We use REGTMP as a scratch register during call injection,
1232	// so instruction sequences that use REGTMP are unsafe to
1233	// preempt asynchronously.
1234	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
1235
1236	// Now that we know byte offsets, we can generate jump table entries.
1237	for _, jt := range cursym.Func().JumpTables {
1238		for i, p := range jt.Targets {
1239			// The ith jumptable entry points to the p.Pc'th
1240			// byte in the function symbol s.
1241			// TODO: try using relative PCs.
1242			jt.Sym.WriteAddr(ctxt, int64(i)*8, 8, cursym, p.Pc)
1243		}
1244	}
1245}
1246
1247// isUnsafePoint returns whether p is an unsafe point.
1248func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
1249	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
1250	// preemption sequence clobbers REGTMP.
1251	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP ||
1252		p.From.Type == obj.TYPE_REGREG && p.From.Offset == REGTMP ||
1253		p.To.Type == obj.TYPE_REGREG && p.To.Offset == REGTMP
1254}
1255
1256// isRestartable returns whether p is a multi-instruction sequence that,
1257// if preempted, can be restarted.
1258func (c *ctxt7) isRestartable(p *obj.Prog) bool {
1259	if c.isUnsafePoint(p) {
1260		return false
1261	}
1262	// If p is a multi-instruction sequence with uses REGTMP inserted by
1263	// the assembler in order to materialize a large constant/offset, we
1264	// can restart p (at the start of the instruction sequence), recompute
1265	// the content of REGTMP, upon async preemption. Currently, all cases
1266	// of assembler-inserted REGTMP fall into this category.
1267	// If p doesn't use REGTMP, it can be simply preempted, so we don't
1268	// mark it.
1269	o := c.oplook(p)
1270	return o.size(c.ctxt, p) > 4 && o.flag&NOTUSETMP == 0
1271}
1272
1273/*
1274 * when the first reference to the literal pool threatens
1275 * to go out of range of a 1Mb PC-relative offset
1276 * drop the pool now.
1277 */
1278func (c *ctxt7) checkpool(p *obj.Prog) {
1279	// If the pool is going to go out of range or p is the last instruction of the function,
1280	// flush the pool.
1281	if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) || p.Link == nil {
1282		c.flushpool(p)
1283	}
1284}
1285
1286func (c *ctxt7) flushpool(p *obj.Prog) {
1287	// Needs to insert a branch before flushing the pool.
1288	// We don't need the jump if following an unconditional branch.
1289	// TODO: other unconditional operations.
1290	if !(p.As == AB || p.As == obj.ARET || p.As == AERET) {
1291		if c.ctxt.Debugvlog {
1292			fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
1293		}
1294		q := c.newprog()
1295		if p.Link == nil {
1296			// If p is the last instruction of the function, insert an UNDEF instruction in case the
1297			// execution fall through to the pool.
1298			q.As = obj.AUNDEF
1299		} else {
1300			// Else insert a branch to the next instruction of p.
1301			q.As = AB
1302			q.To.Type = obj.TYPE_BRANCH
1303			q.To.SetTarget(p.Link)
1304		}
1305		q.Link = c.blitrl
1306		q.Pos = p.Pos
1307		c.blitrl = q
1308	}
1309
1310	// The line number for constant pool entries doesn't really matter.
1311	// We set it to the line number of the preceding instruction so that
1312	// there are no deltas to encode in the pc-line tables.
1313	for q := c.blitrl; q != nil; q = q.Link {
1314		q.Pos = p.Pos
1315	}
1316
1317	c.elitrl.Link = p.Link
1318	p.Link = c.blitrl
1319
1320	c.blitrl = nil /* BUG: should refer back to values until out-of-range */
1321	c.elitrl = nil
1322	c.pool.size = 0
1323	c.pool.start = 0
1324}
1325
1326/*
1327 * MOVD foo(SB), R is actually
1328 *   MOVD addr, REGTMP
1329 *   MOVD REGTMP, R
1330 * where addr is the address of the DWORD containing the address of foo.
1331 *
1332 * TODO: hash
1333 */
1334func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
1335	cls := c.aclass(a)
1336	lit := c.instoffset
1337	t := c.newprog()
1338	t.As = AWORD
1339	sz := 4
1340
1341	if a.Type == obj.TYPE_CONST {
1342		if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
1343			// out of range -0x80000000 ~ 0xffffffff, must store 64-bit.
1344			t.As = ADWORD
1345			sz = 8
1346		} // else store 32-bit
1347	} else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) {
1348		// conservative: don't know if we want signed or unsigned extension.
1349		// in case of ambiguity, store 64-bit
1350		t.As = ADWORD
1351		sz = 8
1352	}
1353
1354	t.To.Type = obj.TYPE_CONST
1355	t.To.Offset = lit
1356
1357	for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
1358		if q.To == t.To {
1359			p.Pool = q
1360			return
1361		}
1362	}
1363
1364	if c.blitrl == nil {
1365		c.blitrl = t
1366		c.pool.start = uint32(p.Pc)
1367	} else {
1368		c.elitrl.Link = t
1369	}
1370	c.elitrl = t
1371	if t.As == ADWORD {
1372		// make DWORD 8-byte aligned, this is not required by ISA,
1373		// just to avoid performance penalties when loading from
1374		// the constant pool across a cache line.
1375		c.pool.size = roundUp(c.pool.size, 8)
1376	}
1377	c.pool.size += uint32(sz)
1378	p.Pool = t
1379}
1380
1381// roundUp rounds up x to "to".
1382func roundUp(x, to uint32) uint32 {
1383	if to == 0 || to&(to-1) != 0 {
1384		log.Fatalf("rounded up to a value that is not a power of 2: %d\n", to)
1385	}
1386	return (x + to - 1) &^ (to - 1)
1387}
1388
1389// splitImm24uScaled splits an immediate into a scaled 12 bit unsigned lo value
1390// and an unscaled shifted 12 bit unsigned hi value. These are typically used
1391// by adding or subtracting the hi value and using the lo value as the offset
1392// for a load or store.
1393func splitImm24uScaled(v int32, shift int) (int32, int32, error) {
1394	if v < 0 {
1395		return 0, 0, fmt.Errorf("%d is not a 24 bit unsigned immediate", v)
1396	}
1397	if v > 0xfff000+0xfff<<shift {
1398		return 0, 0, fmt.Errorf("%d is too large for a scaled 24 bit unsigned immediate", v)
1399	}
1400	if v&((1<<shift)-1) != 0 {
1401		return 0, 0, fmt.Errorf("%d is not a multiple of %d", v, 1<<shift)
1402	}
1403	lo := (v >> shift) & 0xfff
1404	hi := v - (lo << shift)
1405	if hi > 0xfff000 {
1406		hi = 0xfff000
1407		lo = (v - hi) >> shift
1408	}
1409	if hi & ^0xfff000 != 0 {
1410		panic(fmt.Sprintf("bad split for %x with shift %v (%x, %x)", v, shift, hi, lo))
1411	}
1412	return hi, lo, nil
1413}
1414
1415func (c *ctxt7) regoff(a *obj.Addr) int32 {
1416	c.instoffset = 0
1417	c.aclass(a)
1418	return int32(c.instoffset)
1419}
1420
1421func isSTLXRop(op obj.As) bool {
1422	switch op {
1423	case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
1424		ASTXR, ASTXRW, ASTXRB, ASTXRH:
1425		return true
1426	}
1427	return false
1428}
1429
1430func isSTXPop(op obj.As) bool {
1431	switch op {
1432	case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
1433		return true
1434	}
1435	return false
1436}
1437
1438func isANDop(op obj.As) bool {
1439	switch op {
1440	case AAND, AORR, AEOR, AANDS, ATST,
1441		ABIC, AEON, AORN, ABICS:
1442		return true
1443	}
1444	return false
1445}
1446
1447func isANDWop(op obj.As) bool {
1448	switch op {
1449	case AANDW, AORRW, AEORW, AANDSW, ATSTW,
1450		ABICW, AEONW, AORNW, ABICSW:
1451		return true
1452	}
1453	return false
1454}
1455
1456func isADDop(op obj.As) bool {
1457	switch op {
1458	case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
1459		return true
1460	}
1461	return false
1462}
1463
1464func isADDWop(op obj.As) bool {
1465	switch op {
1466	case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
1467		return true
1468	}
1469	return false
1470}
1471
1472func isADDSop(op obj.As) bool {
1473	switch op {
1474	case AADDS, AADDSW, ASUBS, ASUBSW:
1475		return true
1476	}
1477	return false
1478}
1479
1480func isNEGop(op obj.As) bool {
1481	switch op {
1482	case ANEG, ANEGW, ANEGS, ANEGSW:
1483		return true
1484	}
1485	return false
1486}
1487
1488func isLoadStorePairOp(op obj.As) bool {
1489	switch op {
1490	case AFLDPQ, AFSTPQ, ALDP, ASTP, ALDPW, ASTPW:
1491		return true
1492	}
1493	return false
1494}
1495
1496func isMOVop(op obj.As) bool {
1497	switch op {
1498	case AMOVB, AMOVBU, AMOVH, AMOVHU, AMOVW, AMOVWU, AMOVD, AFMOVS, AFMOVD, AFMOVQ:
1499		return true
1500	}
1501	return false
1502}
1503
1504func isRegShiftOrExt(a *obj.Addr) bool {
1505	return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
1506}
1507
1508// Maximum PC-relative displacement.
1509// The actual limit is ±2²⁰, but we are conservative
1510// to avoid needing to recompute the literal pool flush points
1511// as span-dependent jumps are enlarged.
1512const maxPCDisp = 512 * 1024
1513
1514// ispcdisp reports whether v is a valid PC-relative displacement.
1515func ispcdisp(v int32) bool {
1516	return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
1517}
1518
1519func isaddcon(v int64) bool {
1520	/* uimm12 or uimm24? */
1521	if v < 0 {
1522		return false
1523	}
1524	if (v & 0xFFF) == 0 {
1525		v >>= 12
1526	}
1527	return v <= 0xFFF
1528}
1529
1530func isaddcon2(v int64) bool {
1531	return 0 <= v && v <= 0xFFFFFF
1532}
1533
1534// isbitcon reports whether a constant can be encoded into a logical instruction.
1535// bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
1536// which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
1537// special cases: 0 and -1 are not bitcon.
1538// this function needs to run against virtually all the constants, so it needs to be fast.
1539// for this reason, bitcon testing and bitcon encoding are separate functions.
1540func isbitcon(x uint64) bool {
1541	if x == 1<<64-1 || x == 0 {
1542		return false
1543	}
1544	// determine the period and sign-extend a unit to 64 bits
1545	switch {
1546	case x != x>>32|x<<32:
1547		// period is 64
1548		// nothing to do
1549	case x != x>>16|x<<48:
1550		// period is 32
1551		x = uint64(int64(int32(x)))
1552	case x != x>>8|x<<56:
1553		// period is 16
1554		x = uint64(int64(int16(x)))
1555	case x != x>>4|x<<60:
1556		// period is 8
1557		x = uint64(int64(int8(x)))
1558	default:
1559		// period is 4 or 2, always true
1560		// 0001, 0010, 0100, 1000 -- 0001 rotate
1561		// 0011, 0110, 1100, 1001 -- 0011 rotate
1562		// 0111, 1011, 1101, 1110 -- 0111 rotate
1563		// 0101, 1010             -- 01   rotate, repeat
1564		return true
1565	}
1566	return sequenceOfOnes(x) || sequenceOfOnes(^x)
1567}
1568
1569// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros.
1570func sequenceOfOnes(x uint64) bool {
1571	y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
1572	y += x
1573	return (y-1)&y == 0
1574}
1575
1576// bitconEncode returns the encoding of a bitcon used in logical instructions
1577// x is known to be a bitcon
1578// a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
1579// by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
1580// it is encoded in logical instructions with 3 bitfields
1581// N (1 bit) : R (6 bits) : S (6 bits), where
1582// N=1           -- period=64
1583// N=0, S=0xxxxx -- period=32
1584// N=0, S=10xxxx -- period=16
1585// N=0, S=110xxx -- period=8
1586// N=0, S=1110xx -- period=4
1587// N=0, S=11110x -- period=2
1588// R is the shift amount, low bits of S = n-1
1589func bitconEncode(x uint64, mode int) uint32 {
1590	if mode == 32 {
1591		x &= 0xffffffff
1592		x = x<<32 | x
1593	}
1594	var period uint32
1595	// determine the period and sign-extend a unit to 64 bits
1596	switch {
1597	case x != x>>32|x<<32:
1598		period = 64
1599	case x != x>>16|x<<48:
1600		period = 32
1601		x = uint64(int64(int32(x)))
1602	case x != x>>8|x<<56:
1603		period = 16
1604		x = uint64(int64(int16(x)))
1605	case x != x>>4|x<<60:
1606		period = 8
1607		x = uint64(int64(int8(x)))
1608	case x != x>>2|x<<62:
1609		period = 4
1610		x = uint64(int64(x<<60) >> 60)
1611	default:
1612		period = 2
1613		x = uint64(int64(x<<62) >> 62)
1614	}
1615	neg := false
1616	if int64(x) < 0 {
1617		x = ^x
1618		neg = true
1619	}
1620	y := x & -x // lowest set bit of x.
1621	s := log2(y)
1622	n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
1623	if neg {
1624		// ^x is a sequence of n ones left shifted by s bits
1625		// adjust n, s for x
1626		s = n + s
1627		n = period - n
1628	}
1629
1630	N := uint32(0)
1631	if mode == 64 && period == 64 {
1632		N = 1
1633	}
1634	R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
1635	S := (n - 1) | 63&^(period<<1-1)                  // low bits = #ones - 1, high bits encodes period
1636	return N<<22 | R<<16 | S<<10
1637}
1638
1639func log2(x uint64) uint32 {
1640	if x == 0 {
1641		panic("log2 of 0")
1642	}
1643	n := uint32(0)
1644	if x >= 1<<32 {
1645		x >>= 32
1646		n += 32
1647	}
1648	if x >= 1<<16 {
1649		x >>= 16
1650		n += 16
1651	}
1652	if x >= 1<<8 {
1653		x >>= 8
1654		n += 8
1655	}
1656	if x >= 1<<4 {
1657		x >>= 4
1658		n += 4
1659	}
1660	if x >= 1<<2 {
1661		x >>= 2
1662		n += 2
1663	}
1664	if x >= 1<<1 {
1665		x >>= 1
1666		n += 1
1667	}
1668	return n
1669}
1670
1671func autoclass(l int64) int {
1672	if l == 0 {
1673		return C_ZAUTO
1674	}
1675
1676	if l < 0 {
1677		if l >= -256 && (l&15) == 0 {
1678			return C_NSAUTO_16
1679		}
1680		if l >= -256 && (l&7) == 0 {
1681			return C_NSAUTO_8
1682		}
1683		if l >= -256 && (l&3) == 0 {
1684			return C_NSAUTO_4
1685		}
1686		if l >= -256 {
1687			return C_NSAUTO
1688		}
1689		if l >= -512 && (l&15) == 0 {
1690			return C_NPAUTO_16
1691		}
1692		if l >= -512 && (l&7) == 0 {
1693			return C_NPAUTO
1694		}
1695		if l >= -1024 && (l&15) == 0 {
1696			return C_NQAUTO_16
1697		}
1698		if l >= -4095 {
1699			return C_NAUTO4K
1700		}
1701		return C_LAUTO
1702	}
1703
1704	if l <= 255 {
1705		if (l & 15) == 0 {
1706			return C_PSAUTO_16
1707		}
1708		if (l & 7) == 0 {
1709			return C_PSAUTO_8
1710		}
1711		if (l & 3) == 0 {
1712			return C_PSAUTO_4
1713		}
1714		return C_PSAUTO
1715	}
1716	if l <= 504 {
1717		if l&15 == 0 {
1718			return C_PPAUTO_16
1719		}
1720		if l&7 == 0 {
1721			return C_PPAUTO
1722		}
1723	}
1724	if l <= 1008 {
1725		if l&15 == 0 {
1726			return C_PQAUTO_16
1727		}
1728	}
1729	if l <= 4095 {
1730		if l&15 == 0 {
1731			return C_UAUTO4K_16
1732		}
1733		if l&7 == 0 {
1734			return C_UAUTO4K_8
1735		}
1736		if l&3 == 0 {
1737			return C_UAUTO4K_4
1738		}
1739		if l&1 == 0 {
1740			return C_UAUTO4K_2
1741		}
1742		return C_UAUTO4K
1743	}
1744	if l <= 8190 {
1745		if l&15 == 0 {
1746			return C_UAUTO8K_16
1747		}
1748		if l&7 == 0 {
1749			return C_UAUTO8K_8
1750		}
1751		if l&3 == 0 {
1752			return C_UAUTO8K_4
1753		}
1754		if l&1 == 0 {
1755			return C_UAUTO8K
1756		}
1757	}
1758	if l <= 16380 {
1759		if l&15 == 0 {
1760			return C_UAUTO16K_16
1761		}
1762		if l&7 == 0 {
1763			return C_UAUTO16K_8
1764		}
1765		if l&3 == 0 {
1766			return C_UAUTO16K
1767		}
1768	}
1769	if l <= 32760 {
1770		if l&15 == 0 {
1771			return C_UAUTO32K_16
1772		}
1773		if l&7 == 0 {
1774			return C_UAUTO32K
1775		}
1776	}
1777	if l <= 65520 && (l&15) == 0 {
1778		return C_UAUTO64K
1779	}
1780	return C_LAUTO
1781}
1782
1783func oregclass(l int64) int {
1784	return autoclass(l) - C_ZAUTO + C_ZOREG
1785}
1786
1787/*
1788 * given an offset v and a class c (see above)
1789 * return the offset value to use in the instruction,
1790 * scaled if necessary
1791 */
1792func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
1793	s := 0
1794	if cls >= C_SEXT1 && cls <= C_SEXT16 {
1795		s = cls - C_SEXT1
1796	} else {
1797		switch cls {
1798		case C_UAUTO4K, C_UOREG4K, C_ZOREG:
1799			s = 0
1800		case C_UAUTO8K, C_UOREG8K:
1801			s = 1
1802		case C_UAUTO16K, C_UOREG16K:
1803			s = 2
1804		case C_UAUTO32K, C_UOREG32K:
1805			s = 3
1806		case C_UAUTO64K, C_UOREG64K:
1807			s = 4
1808		default:
1809			c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
1810		}
1811	}
1812	vs := v >> uint(s)
1813	if vs<<uint(s) != v {
1814		c.ctxt.Diag("odd offset: %d\n%v", v, p)
1815	}
1816	return vs
1817}
1818
1819/*
1820 * if v contains a single 16-bit value aligned
1821 * on a 16-bit field, and thus suitable for movk/movn,
1822 * return the field index 0 to 3; otherwise return -1.
1823 */
1824func movcon(v int64) int {
1825	for s := 0; s < 64; s += 16 {
1826		if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
1827			return s / 16
1828		}
1829	}
1830	return -1
1831}
1832
1833func rclass(r int16) int {
1834	switch {
1835	case REG_R0 <= r && r <= REG_R30: // not 31
1836		return C_REG
1837	case r == REGZERO:
1838		return C_ZREG
1839	case REG_F0 <= r && r <= REG_F31:
1840		return C_FREG
1841	case REG_V0 <= r && r <= REG_V31:
1842		return C_VREG
1843	case r == REGSP:
1844		return C_RSP
1845	case r >= REG_ARNG && r < REG_ELEM:
1846		return C_ARNG
1847	case r >= REG_ELEM && r < REG_ELEM_END:
1848		return C_ELEM
1849	case r >= REG_UXTB && r < REG_SPECIAL,
1850		r >= REG_LSL && r < REG_ARNG:
1851		return C_EXTREG
1852	case r >= REG_SPECIAL:
1853		return C_SPR
1854	}
1855	return C_GOK
1856}
1857
1858// con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
1859// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
1860func (c *ctxt7) con32class(a *obj.Addr) int {
1861	v := uint32(a.Offset)
1862	// For 32-bit instruction with constant, rewrite
1863	// the high 32-bit to be a repetition of the low
1864	// 32-bit, so that the BITCON test can be shared
1865	// for both 32-bit and 64-bit. 32-bit ops will
1866	// zero the high 32-bit of the destination register
1867	// anyway.
1868	vbitcon := uint64(v)<<32 | uint64(v)
1869	if v == 0 {
1870		return C_ZCON
1871	}
1872	if isaddcon(int64(v)) {
1873		if v <= 0xFFF {
1874			if isbitcon(vbitcon) {
1875				return C_ABCON0
1876			}
1877			return C_ADDCON0
1878		}
1879		if isbitcon(vbitcon) {
1880			return C_ABCON
1881		}
1882		if movcon(int64(v)) >= 0 {
1883			return C_AMCON
1884		}
1885		if movcon(int64(^v)) >= 0 {
1886			return C_AMCON
1887		}
1888		return C_ADDCON
1889	}
1890
1891	t := movcon(int64(v))
1892	if t >= 0 {
1893		if isbitcon(vbitcon) {
1894			return C_MBCON
1895		}
1896		return C_MOVCON
1897	}
1898
1899	t = movcon(int64(^v))
1900	if t >= 0 {
1901		if isbitcon(vbitcon) {
1902			return C_MBCON
1903		}
1904		return C_MOVCON
1905	}
1906
1907	if isbitcon(vbitcon) {
1908		return C_BITCON
1909	}
1910
1911	if 0 <= v && v <= 0xffffff {
1912		return C_ADDCON2
1913	}
1914	return C_LCON
1915}
1916
1917// con64class reclassifies the constant of C_VCON and C_LCON class.
1918func (c *ctxt7) con64class(a *obj.Addr) int {
1919	zeroCount := 0
1920	negCount := 0
1921	for i := uint(0); i < 4; i++ {
1922		immh := uint32(a.Offset >> (i * 16) & 0xffff)
1923		if immh == 0 {
1924			zeroCount++
1925		} else if immh == 0xffff {
1926			negCount++
1927		}
1928	}
1929	if zeroCount >= 3 || negCount >= 3 {
1930		return C_MOVCON
1931	} else if zeroCount == 2 || negCount == 2 {
1932		return C_MOVCON2
1933	} else if zeroCount == 1 || negCount == 1 {
1934		return C_MOVCON3
1935	} else {
1936		return C_VCON
1937	}
1938}
1939
1940// loadStoreClass reclassifies a load or store operation based on its offset.
1941func (c *ctxt7) loadStoreClass(p *obj.Prog, lsc int, v int64) int {
1942	// Avoid reclassification of pre/post-indexed loads and stores.
1943	if p.Scond == C_XPRE || p.Scond == C_XPOST {
1944		return lsc
1945	}
1946	if cmp(C_NSAUTO, lsc) || cmp(C_NSOREG, lsc) {
1947		return lsc
1948	}
1949
1950	needsPool := true
1951	if v >= -4095 && v <= 4095 {
1952		needsPool = false
1953	}
1954
1955	switch p.As {
1956	case AMOVB, AMOVBU:
1957		if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) {
1958			return lsc
1959		}
1960		if v >= 0 && v <= 0xffffff {
1961			needsPool = false
1962		}
1963	case AMOVH, AMOVHU:
1964		if cmp(C_UAUTO8K, lsc) || cmp(C_UOREG8K, lsc) {
1965			return lsc
1966		}
1967		if v >= 0 && v <= 0xfff000+0xfff<<1 && v&1 == 0 {
1968			needsPool = false
1969		}
1970	case AMOVW, AMOVWU, AFMOVS:
1971		if cmp(C_UAUTO16K, lsc) || cmp(C_UOREG16K, lsc) {
1972			return lsc
1973		}
1974		if v >= 0 && v <= 0xfff000+0xfff<<2 && v&3 == 0 {
1975			needsPool = false
1976		}
1977	case AMOVD, AFMOVD:
1978		if cmp(C_UAUTO32K, lsc) || cmp(C_UOREG32K, lsc) {
1979			return lsc
1980		}
1981		if v >= 0 && v <= 0xfff000+0xfff<<3 && v&7 == 0 {
1982			needsPool = false
1983		}
1984	case AFMOVQ:
1985		if cmp(C_UAUTO64K, lsc) || cmp(C_UOREG64K, lsc) {
1986			return lsc
1987		}
1988		if v >= 0 && v <= 0xfff000+0xfff<<4 && v&15 == 0 {
1989			needsPool = false
1990		}
1991	}
1992	if needsPool && cmp(C_LAUTO, lsc) {
1993		return C_LAUTOPOOL
1994	}
1995	if needsPool && cmp(C_LOREG, lsc) {
1996		return C_LOREGPOOL
1997	}
1998	return lsc
1999}
2000
2001// loadStorePairClass reclassifies a load or store pair operation based on its offset.
2002func (c *ctxt7) loadStorePairClass(p *obj.Prog, lsc int, v int64) int {
2003	// Avoid reclassification of pre/post-indexed loads and stores.
2004	if p.Scond == C_XPRE || p.Scond == C_XPOST {
2005		return lsc
2006	}
2007
2008	if cmp(C_NAUTO4K, lsc) || cmp(C_NOREG4K, lsc) {
2009		return lsc
2010	}
2011	if cmp(C_UAUTO4K, lsc) || cmp(C_UOREG4K, lsc) {
2012		return lsc
2013	}
2014
2015	needsPool := true
2016	if v >= 0 && v <= 0xffffff {
2017		needsPool = false
2018	}
2019	if needsPool && cmp(C_LAUTO, lsc) {
2020		return C_LAUTOPOOL
2021	}
2022	if needsPool && cmp(C_LOREG, lsc) {
2023		return C_LOREGPOOL
2024	}
2025	return lsc
2026}
2027
2028func (c *ctxt7) aclass(a *obj.Addr) int {
2029	switch a.Type {
2030	case obj.TYPE_NONE:
2031		return C_NONE
2032
2033	case obj.TYPE_REG:
2034		return rclass(a.Reg)
2035
2036	case obj.TYPE_REGREG:
2037		return C_PAIR
2038
2039	case obj.TYPE_SHIFT:
2040		return C_SHIFT
2041
2042	case obj.TYPE_REGLIST:
2043		return C_LIST
2044
2045	case obj.TYPE_MEM:
2046		// The base register should be an integer register.
2047		if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
2048			break
2049		}
2050		switch a.Name {
2051		case obj.NAME_EXTERN, obj.NAME_STATIC:
2052			if a.Sym == nil {
2053				break
2054			}
2055			c.instoffset = a.Offset
2056			if a.Sym != nil { // use relocation
2057				if a.Sym.Type == objabi.STLSBSS {
2058					if c.ctxt.Flag_shared {
2059						return C_TLS_IE
2060					} else {
2061						return C_TLS_LE
2062					}
2063				}
2064				return C_ADDR
2065			}
2066			return C_LEXT
2067
2068		case obj.NAME_GOTREF:
2069			return C_GOTADDR
2070
2071		case obj.NAME_AUTO:
2072			if a.Reg == REGSP {
2073				// unset base register for better printing, since
2074				// a.Offset is still relative to pseudo-SP.
2075				a.Reg = obj.REG_NONE
2076			}
2077			// The frame top 8 or 16 bytes are for FP
2078			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
2079			return autoclass(c.instoffset)
2080
2081		case obj.NAME_PARAM:
2082			if a.Reg == REGSP {
2083				// unset base register for better printing, since
2084				// a.Offset is still relative to pseudo-FP.
2085				a.Reg = obj.REG_NONE
2086			}
2087			c.instoffset = int64(c.autosize) + a.Offset + 8
2088			return autoclass(c.instoffset)
2089
2090		case obj.NAME_NONE:
2091			if a.Index != 0 {
2092				if a.Offset != 0 {
2093					if isRegShiftOrExt(a) {
2094						// extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
2095						return C_ROFF
2096					}
2097					return C_GOK
2098				}
2099				// register offset, (Rn)(Rm)
2100				return C_ROFF
2101			}
2102			c.instoffset = a.Offset
2103			return oregclass(c.instoffset)
2104		}
2105		return C_GOK
2106
2107	case obj.TYPE_FCONST:
2108		return C_FCON
2109
2110	case obj.TYPE_TEXTSIZE:
2111		return C_TEXTSIZE
2112
2113	case obj.TYPE_CONST, obj.TYPE_ADDR:
2114		switch a.Name {
2115		case obj.NAME_NONE:
2116			c.instoffset = a.Offset
2117			if a.Reg != 0 && a.Reg != REGZERO {
2118				break
2119			}
2120			v := c.instoffset
2121			if v == 0 {
2122				return C_ZCON
2123			}
2124			if isaddcon(v) {
2125				if v <= 0xFFF {
2126					if isbitcon(uint64(v)) {
2127						return C_ABCON0
2128					}
2129					return C_ADDCON0
2130				}
2131				if isbitcon(uint64(v)) {
2132					return C_ABCON
2133				}
2134				if movcon(v) >= 0 {
2135					return C_AMCON
2136				}
2137				if movcon(^v) >= 0 {
2138					return C_AMCON
2139				}
2140				return C_ADDCON
2141			}
2142
2143			t := movcon(v)
2144			if t >= 0 {
2145				if isbitcon(uint64(v)) {
2146					return C_MBCON
2147				}
2148				return C_MOVCON
2149			}
2150
2151			t = movcon(^v)
2152			if t >= 0 {
2153				if isbitcon(uint64(v)) {
2154					return C_MBCON
2155				}
2156				return C_MOVCON
2157			}
2158
2159			if isbitcon(uint64(v)) {
2160				return C_BITCON
2161			}
2162
2163			if 0 <= v && v <= 0xffffff {
2164				return C_ADDCON2
2165			}
2166
2167			if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
2168				return C_LCON
2169			}
2170			return C_VCON
2171
2172		case obj.NAME_EXTERN, obj.NAME_STATIC:
2173			if a.Sym == nil {
2174				return C_GOK
2175			}
2176			if a.Sym.Type == objabi.STLSBSS {
2177				c.ctxt.Diag("taking address of TLS variable is not supported")
2178			}
2179			c.instoffset = a.Offset
2180			return C_VCONADDR
2181
2182		case obj.NAME_AUTO:
2183			if a.Reg == REGSP {
2184				// unset base register for better printing, since
2185				// a.Offset is still relative to pseudo-SP.
2186				a.Reg = obj.REG_NONE
2187			}
2188			// The frame top 8 or 16 bytes are for FP
2189			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
2190
2191		case obj.NAME_PARAM:
2192			if a.Reg == REGSP {
2193				// unset base register for better printing, since
2194				// a.Offset is still relative to pseudo-FP.
2195				a.Reg = obj.REG_NONE
2196			}
2197			c.instoffset = int64(c.autosize) + a.Offset + 8
2198		default:
2199			return C_GOK
2200		}
2201		cf := c.instoffset
2202		if isaddcon(cf) || isaddcon(-cf) {
2203			return C_AACON
2204		}
2205		if isaddcon2(cf) {
2206			return C_AACON2
2207		}
2208
2209		return C_LACON
2210
2211	case obj.TYPE_BRANCH:
2212		return C_SBRA
2213
2214	case obj.TYPE_SPECIAL:
2215		opd := SpecialOperand(a.Offset)
2216		if SPOP_EQ <= opd && opd <= SPOP_NV {
2217			return C_COND
2218		}
2219		return C_SPOP
2220	}
2221	return C_GOK
2222}
2223
2224func (c *ctxt7) oplook(p *obj.Prog) *Optab {
2225	a1 := int(p.Optab)
2226	if a1 != 0 {
2227		return &optab[a1-1]
2228	}
2229	a1 = int(p.From.Class)
2230	if a1 == 0 {
2231		a1 = c.aclass(&p.From)
2232		// do not break C_ADDCON2 when S bit is set
2233		if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a1 == C_ADDCON2 {
2234			a1 = C_LCON
2235		}
2236		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
2237			if p.As == AMOVW || isADDWop(p.As) || isANDWop(p.As) {
2238				// For 32-bit instruction with constant, we need to
2239				// treat its offset value as 32 bits to classify it.
2240				a1 = c.con32class(&p.From)
2241				// do not break C_ADDCON2 when S bit is set
2242				if (p.As == AADDSW || p.As == ASUBSW) && a1 == C_ADDCON2 {
2243					a1 = C_LCON
2244				}
2245			}
2246			if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a1 == C_LCON || a1 == C_VCON) {
2247				// more specific classification of 64-bit integers
2248				a1 = c.con64class(&p.From)
2249			}
2250		}
2251		if p.From.Type == obj.TYPE_MEM {
2252			if isMOVop(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) {
2253				// More specific classification of large offset loads and stores.
2254				a1 = c.loadStoreClass(p, a1, c.instoffset)
2255			}
2256			if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a1) || cmp(C_LOREG, a1)) {
2257				// More specific classification of large offset loads and stores.
2258				a1 = c.loadStorePairClass(p, a1, c.instoffset)
2259			}
2260		}
2261		p.From.Class = int8(a1)
2262	}
2263
2264	a2 := C_NONE
2265	if p.Reg != 0 {
2266		a2 = rclass(p.Reg)
2267	}
2268
2269	a3 := C_NONE
2270	if p.GetFrom3() != nil {
2271		a3 = int(p.GetFrom3().Class)
2272		if a3 == 0 {
2273			a3 = c.aclass(p.GetFrom3())
2274			p.GetFrom3().Class = int8(a3)
2275		}
2276	}
2277
2278	a4 := int(p.To.Class)
2279	if a4 == 0 {
2280		a4 = c.aclass(&p.To)
2281		if p.To.Type == obj.TYPE_MEM {
2282			if isMOVop(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) {
2283				// More specific classification of large offset loads and stores.
2284				a4 = c.loadStoreClass(p, a4, c.instoffset)
2285			}
2286			if isLoadStorePairOp(p.As) && (cmp(C_LAUTO, a4) || cmp(C_LOREG, a4)) {
2287				// More specific classification of large offset loads and stores.
2288				a4 = c.loadStorePairClass(p, a4, c.instoffset)
2289			}
2290		}
2291		p.To.Class = int8(a4)
2292	}
2293
2294	a5 := C_NONE
2295	if p.RegTo2 != 0 {
2296		a5 = rclass(p.RegTo2)
2297	} else if p.GetTo2() != nil {
2298		a5 = int(p.GetTo2().Class)
2299		if a5 == 0 {
2300			a5 = c.aclass(p.GetTo2())
2301			p.GetTo2().Class = int8(a5)
2302		}
2303	}
2304
2305	if false {
2306		fmt.Printf("oplook %v %d %d %d %d %d\n", p.As, a1, a2, a3, a4, a5)
2307		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
2308	}
2309
2310	ops := oprange[p.As&obj.AMask]
2311	c1 := &xcmp[a1]
2312	c2 := &xcmp[a2]
2313	c3 := &xcmp[a3]
2314	c4 := &xcmp[a4]
2315	c5 := &xcmp[a5]
2316	for i := range ops {
2317		op := &ops[i]
2318		if c1[op.a1] && c2[op.a2] && c3[op.a3] && c4[op.a4] && c5[op.a5] && p.Scond == op.scond {
2319			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
2320			return op
2321		}
2322	}
2323
2324	c.ctxt.Diag("illegal combination: %v %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), DRconv(a5), p.From.Type, p.To.Type)
2325	// Turn illegal instruction into an UNDEF, avoid crashing in asmout
2326	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
2327}
2328
2329func cmp(a int, b int) bool {
2330	if a == b {
2331		return true
2332	}
2333	switch a {
2334	case C_RSP:
2335		if b == C_REG {
2336			return true
2337		}
2338
2339	case C_ZREG:
2340		if b == C_REG {
2341			return true
2342		}
2343
2344	case C_ADDCON0:
2345		if b == C_ZCON || b == C_ABCON0 {
2346			return true
2347		}
2348
2349	case C_ADDCON:
2350		if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
2351			return true
2352		}
2353
2354	case C_MBCON:
2355		if b == C_ABCON0 {
2356			return true
2357		}
2358
2359	case C_BITCON:
2360		if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
2361			return true
2362		}
2363
2364	case C_MOVCON:
2365		if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON {
2366			return true
2367		}
2368
2369	case C_ADDCON2:
2370		if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
2371			return true
2372		}
2373
2374	case C_LCON:
2375		if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
2376			return true
2377		}
2378
2379	case C_MOVCON2:
2380		return cmp(C_LCON, b)
2381
2382	case C_VCON:
2383		return cmp(C_LCON, b)
2384
2385	case C_LACON:
2386		if b == C_AACON || b == C_AACON2 {
2387			return true
2388		}
2389
2390	case C_SEXT2:
2391		if b == C_SEXT1 {
2392			return true
2393		}
2394
2395	case C_SEXT4:
2396		if b == C_SEXT1 || b == C_SEXT2 {
2397			return true
2398		}
2399
2400	case C_SEXT8:
2401		if b >= C_SEXT1 && b <= C_SEXT4 {
2402			return true
2403		}
2404
2405	case C_SEXT16:
2406		if b >= C_SEXT1 && b <= C_SEXT8 {
2407			return true
2408		}
2409
2410	case C_LEXT:
2411		if b >= C_SEXT1 && b <= C_SEXT16 {
2412			return true
2413		}
2414
2415	case C_NSAUTO_8:
2416		if b == C_NSAUTO_16 {
2417			return true
2418		}
2419
2420	case C_NSAUTO_4:
2421		if b == C_NSAUTO_16 || b == C_NSAUTO_8 {
2422			return true
2423		}
2424
2425	case C_NSAUTO:
2426		switch b {
2427		case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16:
2428			return true
2429		}
2430
2431	case C_NPAUTO_16:
2432		switch b {
2433		case C_NSAUTO_16:
2434			return true
2435		}
2436
2437	case C_NPAUTO:
2438		switch b {
2439		case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16:
2440			return true
2441		}
2442
2443	case C_NQAUTO_16:
2444		switch b {
2445		case C_NSAUTO_16, C_NPAUTO_16:
2446			return true
2447		}
2448
2449	case C_NAUTO4K:
2450		switch b {
2451		case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16,
2452			C_NPAUTO, C_NQAUTO_16:
2453			return true
2454		}
2455
2456	case C_PSAUTO_16:
2457		if b == C_ZAUTO {
2458			return true
2459		}
2460
2461	case C_PSAUTO_8:
2462		if b == C_ZAUTO || b == C_PSAUTO_16 {
2463			return true
2464		}
2465
2466	case C_PSAUTO_4:
2467		switch b {
2468		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8:
2469			return true
2470		}
2471
2472	case C_PSAUTO:
2473		switch b {
2474		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4:
2475			return true
2476		}
2477
2478	case C_PPAUTO_16:
2479		switch b {
2480		case C_ZAUTO, C_PSAUTO_16:
2481			return true
2482		}
2483
2484	case C_PPAUTO:
2485		switch b {
2486		case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16:
2487			return true
2488		}
2489
2490	case C_PQAUTO_16:
2491		switch b {
2492		case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16:
2493			return true
2494		}
2495
2496	case C_UAUTO4K:
2497		switch b {
2498		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2499			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2500			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16:
2501			return true
2502		}
2503
2504	case C_UAUTO8K:
2505		switch b {
2506		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2507			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2508			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2509			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16:
2510			return true
2511		}
2512
2513	case C_UAUTO16K:
2514		switch b {
2515		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2516			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2517			C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2518			C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
2519			C_UAUTO16K_8, C_UAUTO16K_16:
2520			return true
2521		}
2522
2523	case C_UAUTO32K:
2524		switch b {
2525		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2526			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2527			C_UAUTO4K_8, C_UAUTO4K_16,
2528			C_UAUTO8K_8, C_UAUTO8K_16,
2529			C_UAUTO16K_8, C_UAUTO16K_16,
2530			C_UAUTO32K_16:
2531			return true
2532		}
2533
2534	case C_UAUTO64K:
2535		switch b {
2536		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2537			C_PPAUTO_16, C_PQAUTO_16, C_UAUTO4K_16, C_UAUTO8K_16, C_UAUTO16K_16,
2538			C_UAUTO32K_16:
2539			return true
2540		}
2541
2542	case C_LAUTO:
2543		switch b {
2544		case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16, C_NPAUTO_16, C_NPAUTO, C_NQAUTO_16, C_NAUTO4K,
2545			C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2546			C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2547			C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2548			C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
2549			C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K_16,
2550			C_UAUTO32K, C_UAUTO32K_16,
2551			C_UAUTO64K:
2552			return true
2553		}
2554
2555	case C_NSOREG_8:
2556		if b == C_NSOREG_16 {
2557			return true
2558		}
2559
2560	case C_NSOREG_4:
2561		if b == C_NSOREG_8 || b == C_NSOREG_16 {
2562			return true
2563		}
2564
2565	case C_NSOREG:
2566		switch b {
2567		case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16:
2568			return true
2569		}
2570
2571	case C_NPOREG_16:
2572		switch b {
2573		case C_NSOREG_16:
2574			return true
2575		}
2576
2577	case C_NPOREG:
2578		switch b {
2579		case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16:
2580			return true
2581		}
2582
2583	case C_NQOREG_16:
2584		switch b {
2585		case C_NSOREG_16, C_NPOREG_16:
2586			return true
2587		}
2588
2589	case C_NOREG4K:
2590		switch b {
2591		case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16:
2592			return true
2593		}
2594
2595	case C_PSOREG_16:
2596		if b == C_ZOREG {
2597			return true
2598		}
2599
2600	case C_PSOREG_8:
2601		if b == C_ZOREG || b == C_PSOREG_16 {
2602			return true
2603		}
2604
2605	case C_PSOREG_4:
2606		switch b {
2607		case C_ZOREG, C_PSOREG_16, C_PSOREG_8:
2608			return true
2609		}
2610
2611	case C_PSOREG:
2612		switch b {
2613		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4:
2614			return true
2615		}
2616
2617	case C_PPOREG_16:
2618		switch b {
2619		case C_ZOREG, C_PSOREG_16:
2620			return true
2621		}
2622
2623	case C_PPOREG:
2624		switch b {
2625		case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16:
2626			return true
2627		}
2628
2629	case C_PQOREG_16:
2630		switch b {
2631		case C_ZOREG, C_PSOREG_16, C_PPOREG_16:
2632			return true
2633		}
2634
2635	case C_UOREG4K:
2636		switch b {
2637		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2638			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2639			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16:
2640			return true
2641		}
2642
2643	case C_UOREG8K:
2644		switch b {
2645		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2646			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2647			C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2648			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16:
2649			return true
2650		}
2651
2652	case C_UOREG16K:
2653		switch b {
2654		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2655			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2656			C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2657			C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
2658			C_UOREG16K_8, C_UOREG16K_16:
2659			return true
2660		}
2661
2662	case C_UOREG32K:
2663		switch b {
2664		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2665			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2666			C_UOREG4K_8, C_UOREG4K_16,
2667			C_UOREG8K_8, C_UOREG8K_16,
2668			C_UOREG16K_8, C_UOREG16K_16,
2669			C_UOREG32K_16:
2670			return true
2671		}
2672
2673	case C_UOREG64K:
2674		switch b {
2675		case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2676			C_PPOREG_16, C_PQOREG_16, C_UOREG4K_16, C_UOREG8K_16, C_UOREG16K_16,
2677			C_UOREG32K_16:
2678			return true
2679		}
2680
2681	case C_LOREG:
2682		switch b {
2683		case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NSOREG_16, C_NPOREG, C_NPOREG_16, C_NQOREG_16, C_NOREG4K,
2684			C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2685			C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2686			C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2687			C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
2688			C_UOREG16K, C_UOREG16K_8, C_UOREG16K_16,
2689			C_UOREG32K, C_UOREG32K_16,
2690			C_UOREG64K:
2691			return true
2692		}
2693
2694	case C_LBRA:
2695		if b == C_SBRA {
2696			return true
2697		}
2698	}
2699
2700	return false
2701}
2702
2703type ocmp []Optab
2704
2705func (x ocmp) Len() int {
2706	return len(x)
2707}
2708
2709func (x ocmp) Swap(i, j int) {
2710	x[i], x[j] = x[j], x[i]
2711}
2712
2713func (x ocmp) Less(i, j int) bool {
2714	p1 := &x[i]
2715	p2 := &x[j]
2716	if p1.as != p2.as {
2717		return p1.as < p2.as
2718	}
2719	if p1.a1 != p2.a1 {
2720		return p1.a1 < p2.a1
2721	}
2722	if p1.a2 != p2.a2 {
2723		return p1.a2 < p2.a2
2724	}
2725	if p1.a3 != p2.a3 {
2726		return p1.a3 < p2.a3
2727	}
2728	if p1.a4 != p2.a4 {
2729		return p1.a4 < p2.a4
2730	}
2731	if p1.scond != p2.scond {
2732		return p1.scond < p2.scond
2733	}
2734	return false
2735}
2736
2737func oprangeset(a obj.As, t []Optab) {
2738	oprange[a&obj.AMask] = t
2739}
2740
2741func buildop(ctxt *obj.Link) {
2742	if oprange[AAND&obj.AMask] != nil {
2743		// Already initialized; stop now.
2744		// This happens in the cmd/asm tests,
2745		// each of which re-initializes the arch.
2746		return
2747	}
2748
2749	for i := 0; i < C_GOK; i++ {
2750		for j := 0; j < C_GOK; j++ {
2751			if cmp(j, i) {
2752				xcmp[i][j] = true
2753			}
2754		}
2755	}
2756
2757	sort.Sort(ocmp(optab))
2758	for i := 0; i < len(optab); i++ {
2759		as, start := optab[i].as, i
2760		for ; i < len(optab)-1; i++ {
2761			if optab[i+1].as != as {
2762				break
2763			}
2764		}
2765		t := optab[start : i+1]
2766		oprangeset(as, t)
2767		switch as {
2768		default:
2769			ctxt.Diag("unknown op in build: %v", as)
2770			ctxt.DiagFlush()
2771			log.Fatalf("bad code")
2772
2773		case AADD:
2774			oprangeset(AADDS, t)
2775			oprangeset(ASUB, t)
2776			oprangeset(ASUBS, t)
2777			oprangeset(AADDW, t)
2778			oprangeset(AADDSW, t)
2779			oprangeset(ASUBW, t)
2780			oprangeset(ASUBSW, t)
2781
2782		case AAND: /* logical immediate, logical shifted register */
2783			oprangeset(AANDW, t)
2784			oprangeset(AEOR, t)
2785			oprangeset(AEORW, t)
2786			oprangeset(AORR, t)
2787			oprangeset(AORRW, t)
2788			oprangeset(ABIC, t)
2789			oprangeset(ABICW, t)
2790			oprangeset(AEON, t)
2791			oprangeset(AEONW, t)
2792			oprangeset(AORN, t)
2793			oprangeset(AORNW, t)
2794
2795		case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
2796			oprangeset(AANDSW, t)
2797			oprangeset(ABICS, t)
2798			oprangeset(ABICSW, t)
2799
2800		case ANEG:
2801			oprangeset(ANEGS, t)
2802			oprangeset(ANEGSW, t)
2803			oprangeset(ANEGW, t)
2804
2805		case AADC: /* rn=Rd */
2806			oprangeset(AADCW, t)
2807
2808			oprangeset(AADCS, t)
2809			oprangeset(AADCSW, t)
2810			oprangeset(ASBC, t)
2811			oprangeset(ASBCW, t)
2812			oprangeset(ASBCS, t)
2813			oprangeset(ASBCSW, t)
2814
2815		case ANGC: /* rn=REGZERO */
2816			oprangeset(ANGCW, t)
2817
2818			oprangeset(ANGCS, t)
2819			oprangeset(ANGCSW, t)
2820
2821		case ACMP:
2822			oprangeset(ACMPW, t)
2823			oprangeset(ACMN, t)
2824			oprangeset(ACMNW, t)
2825
2826		case ATST:
2827			oprangeset(ATSTW, t)
2828
2829			/* register/register, and shifted */
2830		case AMVN:
2831			oprangeset(AMVNW, t)
2832
2833		case AMOVK:
2834			oprangeset(AMOVKW, t)
2835			oprangeset(AMOVN, t)
2836			oprangeset(AMOVNW, t)
2837			oprangeset(AMOVZ, t)
2838			oprangeset(AMOVZW, t)
2839
2840		case ASWPD:
2841			for i := range atomicLDADD {
2842				oprangeset(i, t)
2843			}
2844			for i := range atomicSWP {
2845				if i == ASWPD {
2846					continue
2847				}
2848				oprangeset(i, t)
2849			}
2850
2851		case ACASPD:
2852			oprangeset(ACASPW, t)
2853		case ABEQ:
2854			oprangeset(ABNE, t)
2855			oprangeset(ABCS, t)
2856			oprangeset(ABHS, t)
2857			oprangeset(ABCC, t)
2858			oprangeset(ABLO, t)
2859			oprangeset(ABMI, t)
2860			oprangeset(ABPL, t)
2861			oprangeset(ABVS, t)
2862			oprangeset(ABVC, t)
2863			oprangeset(ABHI, t)
2864			oprangeset(ABLS, t)
2865			oprangeset(ABGE, t)
2866			oprangeset(ABLT, t)
2867			oprangeset(ABGT, t)
2868			oprangeset(ABLE, t)
2869
2870		case ALSL:
2871			oprangeset(ALSLW, t)
2872			oprangeset(ALSR, t)
2873			oprangeset(ALSRW, t)
2874			oprangeset(AASR, t)
2875			oprangeset(AASRW, t)
2876			oprangeset(AROR, t)
2877			oprangeset(ARORW, t)
2878
2879		case ACLS:
2880			oprangeset(ACLSW, t)
2881			oprangeset(ACLZ, t)
2882			oprangeset(ACLZW, t)
2883			oprangeset(ARBIT, t)
2884			oprangeset(ARBITW, t)
2885			oprangeset(AREV, t)
2886			oprangeset(AREVW, t)
2887			oprangeset(AREV16, t)
2888			oprangeset(AREV16W, t)
2889			oprangeset(AREV32, t)
2890
2891		case ASDIV:
2892			oprangeset(ASDIVW, t)
2893			oprangeset(AUDIV, t)
2894			oprangeset(AUDIVW, t)
2895			oprangeset(ACRC32B, t)
2896			oprangeset(ACRC32CB, t)
2897			oprangeset(ACRC32CH, t)
2898			oprangeset(ACRC32CW, t)
2899			oprangeset(ACRC32CX, t)
2900			oprangeset(ACRC32H, t)
2901			oprangeset(ACRC32W, t)
2902			oprangeset(ACRC32X, t)
2903
2904		case AMADD:
2905			oprangeset(AMADDW, t)
2906			oprangeset(AMSUB, t)
2907			oprangeset(AMSUBW, t)
2908			oprangeset(ASMADDL, t)
2909			oprangeset(ASMSUBL, t)
2910			oprangeset(AUMADDL, t)
2911			oprangeset(AUMSUBL, t)
2912
2913		case AREM:
2914			oprangeset(AREMW, t)
2915			oprangeset(AUREM, t)
2916			oprangeset(AUREMW, t)
2917
2918		case AMUL:
2919			oprangeset(AMULW, t)
2920			oprangeset(AMNEG, t)
2921			oprangeset(AMNEGW, t)
2922			oprangeset(ASMNEGL, t)
2923			oprangeset(ASMULL, t)
2924			oprangeset(ASMULH, t)
2925			oprangeset(AUMNEGL, t)
2926			oprangeset(AUMULH, t)
2927			oprangeset(AUMULL, t)
2928
2929		case AMOVB:
2930			oprangeset(AMOVBU, t)
2931
2932		case AMOVH:
2933			oprangeset(AMOVHU, t)
2934
2935		case AMOVW:
2936			oprangeset(AMOVWU, t)
2937
2938		case ABFM:
2939			oprangeset(ABFMW, t)
2940			oprangeset(ASBFM, t)
2941			oprangeset(ASBFMW, t)
2942			oprangeset(AUBFM, t)
2943			oprangeset(AUBFMW, t)
2944
2945		case ABFI:
2946			oprangeset(ABFIW, t)
2947			oprangeset(ABFXIL, t)
2948			oprangeset(ABFXILW, t)
2949			oprangeset(ASBFIZ, t)
2950			oprangeset(ASBFIZW, t)
2951			oprangeset(ASBFX, t)
2952			oprangeset(ASBFXW, t)
2953			oprangeset(AUBFIZ, t)
2954			oprangeset(AUBFIZW, t)
2955			oprangeset(AUBFX, t)
2956			oprangeset(AUBFXW, t)
2957
2958		case AEXTR:
2959			oprangeset(AEXTRW, t)
2960
2961		case ASXTB:
2962			oprangeset(ASXTBW, t)
2963			oprangeset(ASXTH, t)
2964			oprangeset(ASXTHW, t)
2965			oprangeset(ASXTW, t)
2966			oprangeset(AUXTB, t)
2967			oprangeset(AUXTH, t)
2968			oprangeset(AUXTW, t)
2969			oprangeset(AUXTBW, t)
2970			oprangeset(AUXTHW, t)
2971
2972		case ACCMN:
2973			oprangeset(ACCMNW, t)
2974			oprangeset(ACCMP, t)
2975			oprangeset(ACCMPW, t)
2976
2977		case ACSEL:
2978			oprangeset(ACSELW, t)
2979			oprangeset(ACSINC, t)
2980			oprangeset(ACSINCW, t)
2981			oprangeset(ACSINV, t)
2982			oprangeset(ACSINVW, t)
2983			oprangeset(ACSNEG, t)
2984			oprangeset(ACSNEGW, t)
2985
2986		case ACINC:
2987			// aliases Rm=Rn, !cond
2988			oprangeset(ACINCW, t)
2989			oprangeset(ACINV, t)
2990			oprangeset(ACINVW, t)
2991			oprangeset(ACNEG, t)
2992			oprangeset(ACNEGW, t)
2993
2994			// aliases, Rm=Rn=REGZERO, !cond
2995		case ACSET:
2996			oprangeset(ACSETW, t)
2997
2998			oprangeset(ACSETM, t)
2999			oprangeset(ACSETMW, t)
3000
3001		case AMOVD,
3002			AB,
3003			ABL,
3004			AWORD,
3005			ADWORD,
3006			obj.ARET,
3007			obj.ATEXT:
3008			break
3009
3010		case AFLDPQ:
3011			break
3012		case AFSTPQ:
3013			break
3014		case ALDP:
3015			oprangeset(AFLDPD, t)
3016
3017		case ASTP:
3018			oprangeset(AFSTPD, t)
3019
3020		case ASTPW:
3021			oprangeset(AFSTPS, t)
3022
3023		case ALDPW:
3024			oprangeset(ALDPSW, t)
3025			oprangeset(AFLDPS, t)
3026
3027		case AERET:
3028			oprangeset(AWFE, t)
3029			oprangeset(AWFI, t)
3030			oprangeset(AYIELD, t)
3031			oprangeset(ASEV, t)
3032			oprangeset(ASEVL, t)
3033			oprangeset(ANOOP, t)
3034			oprangeset(ADRPS, t)
3035
3036		case ACBZ:
3037			oprangeset(ACBZW, t)
3038			oprangeset(ACBNZ, t)
3039			oprangeset(ACBNZW, t)
3040
3041		case ATBZ:
3042			oprangeset(ATBNZ, t)
3043
3044		case AADR, AADRP:
3045			break
3046
3047		case ACLREX:
3048			break
3049
3050		case ASVC:
3051			oprangeset(AHVC, t)
3052			oprangeset(AHLT, t)
3053			oprangeset(ASMC, t)
3054			oprangeset(ABRK, t)
3055			oprangeset(ADCPS1, t)
3056			oprangeset(ADCPS2, t)
3057			oprangeset(ADCPS3, t)
3058
3059		case AFADDS:
3060			oprangeset(AFADDD, t)
3061			oprangeset(AFSUBS, t)
3062			oprangeset(AFSUBD, t)
3063			oprangeset(AFMULS, t)
3064			oprangeset(AFMULD, t)
3065			oprangeset(AFNMULS, t)
3066			oprangeset(AFNMULD, t)
3067			oprangeset(AFDIVS, t)
3068			oprangeset(AFMAXD, t)
3069			oprangeset(AFMAXS, t)
3070			oprangeset(AFMIND, t)
3071			oprangeset(AFMINS, t)
3072			oprangeset(AFMAXNMD, t)
3073			oprangeset(AFMAXNMS, t)
3074			oprangeset(AFMINNMD, t)
3075			oprangeset(AFMINNMS, t)
3076			oprangeset(AFDIVD, t)
3077
3078		case AFMSUBD:
3079			oprangeset(AFMSUBS, t)
3080			oprangeset(AFMADDS, t)
3081			oprangeset(AFMADDD, t)
3082			oprangeset(AFNMSUBS, t)
3083			oprangeset(AFNMSUBD, t)
3084			oprangeset(AFNMADDS, t)
3085			oprangeset(AFNMADDD, t)
3086
3087		case AFCVTSD:
3088			oprangeset(AFCVTDS, t)
3089			oprangeset(AFABSD, t)
3090			oprangeset(AFABSS, t)
3091			oprangeset(AFNEGD, t)
3092			oprangeset(AFNEGS, t)
3093			oprangeset(AFSQRTD, t)
3094			oprangeset(AFSQRTS, t)
3095			oprangeset(AFRINTNS, t)
3096			oprangeset(AFRINTND, t)
3097			oprangeset(AFRINTPS, t)
3098			oprangeset(AFRINTPD, t)
3099			oprangeset(AFRINTMS, t)
3100			oprangeset(AFRINTMD, t)
3101			oprangeset(AFRINTZS, t)
3102			oprangeset(AFRINTZD, t)
3103			oprangeset(AFRINTAS, t)
3104			oprangeset(AFRINTAD, t)
3105			oprangeset(AFRINTXS, t)
3106			oprangeset(AFRINTXD, t)
3107			oprangeset(AFRINTIS, t)
3108			oprangeset(AFRINTID, t)
3109			oprangeset(AFCVTDH, t)
3110			oprangeset(AFCVTHS, t)
3111			oprangeset(AFCVTHD, t)
3112			oprangeset(AFCVTSH, t)
3113
3114		case AFCMPS:
3115			oprangeset(AFCMPD, t)
3116			oprangeset(AFCMPES, t)
3117			oprangeset(AFCMPED, t)
3118
3119		case AFCCMPS:
3120			oprangeset(AFCCMPD, t)
3121			oprangeset(AFCCMPES, t)
3122			oprangeset(AFCCMPED, t)
3123
3124		case AFCSELD:
3125			oprangeset(AFCSELS, t)
3126
3127		case AFMOVQ, AFMOVD, AFMOVS,
3128			AVMOVQ, AVMOVD, AVMOVS:
3129			break
3130
3131		case AFCVTZSD:
3132			oprangeset(AFCVTZSDW, t)
3133			oprangeset(AFCVTZSS, t)
3134			oprangeset(AFCVTZSSW, t)
3135			oprangeset(AFCVTZUD, t)
3136			oprangeset(AFCVTZUDW, t)
3137			oprangeset(AFCVTZUS, t)
3138			oprangeset(AFCVTZUSW, t)
3139
3140		case ASCVTFD:
3141			oprangeset(ASCVTFS, t)
3142			oprangeset(ASCVTFWD, t)
3143			oprangeset(ASCVTFWS, t)
3144			oprangeset(AUCVTFD, t)
3145			oprangeset(AUCVTFS, t)
3146			oprangeset(AUCVTFWD, t)
3147			oprangeset(AUCVTFWS, t)
3148
3149		case ASYS:
3150			oprangeset(AAT, t)
3151			oprangeset(AIC, t)
3152
3153		case ATLBI:
3154			oprangeset(ADC, t)
3155
3156		case ASYSL, AHINT:
3157			break
3158
3159		case ADMB:
3160			oprangeset(ADSB, t)
3161			oprangeset(AISB, t)
3162
3163		case AMRS, AMSR:
3164			break
3165
3166		case ALDAR:
3167			oprangeset(ALDARW, t)
3168			oprangeset(ALDARB, t)
3169			oprangeset(ALDARH, t)
3170			fallthrough
3171
3172		case ALDXR:
3173			oprangeset(ALDXRB, t)
3174			oprangeset(ALDXRH, t)
3175			oprangeset(ALDXRW, t)
3176
3177		case ALDAXR:
3178			oprangeset(ALDAXRB, t)
3179			oprangeset(ALDAXRH, t)
3180			oprangeset(ALDAXRW, t)
3181
3182		case ALDXP:
3183			oprangeset(ALDXPW, t)
3184			oprangeset(ALDAXP, t)
3185			oprangeset(ALDAXPW, t)
3186
3187		case ASTLR:
3188			oprangeset(ASTLRB, t)
3189			oprangeset(ASTLRH, t)
3190			oprangeset(ASTLRW, t)
3191
3192		case ASTXR:
3193			oprangeset(ASTXRB, t)
3194			oprangeset(ASTXRH, t)
3195			oprangeset(ASTXRW, t)
3196
3197		case ASTLXR:
3198			oprangeset(ASTLXRB, t)
3199			oprangeset(ASTLXRH, t)
3200			oprangeset(ASTLXRW, t)
3201
3202		case ASTXP:
3203			oprangeset(ASTLXP, t)
3204			oprangeset(ASTLXPW, t)
3205			oprangeset(ASTXPW, t)
3206
3207		case AVADDP:
3208			oprangeset(AVAND, t)
3209			oprangeset(AVCMEQ, t)
3210			oprangeset(AVORR, t)
3211			oprangeset(AVEOR, t)
3212			oprangeset(AVBSL, t)
3213			oprangeset(AVBIT, t)
3214			oprangeset(AVCMTST, t)
3215			oprangeset(AVUMAX, t)
3216			oprangeset(AVUMIN, t)
3217			oprangeset(AVUZP1, t)
3218			oprangeset(AVUZP2, t)
3219			oprangeset(AVBIF, t)
3220
3221		case AVADD:
3222			oprangeset(AVSUB, t)
3223			oprangeset(AVRAX1, t)
3224
3225		case AAESD:
3226			oprangeset(AAESE, t)
3227			oprangeset(AAESMC, t)
3228			oprangeset(AAESIMC, t)
3229			oprangeset(ASHA1SU1, t)
3230			oprangeset(ASHA256SU0, t)
3231			oprangeset(ASHA512SU0, t)
3232			oprangeset(ASHA1H, t)
3233
3234		case ASHA1C:
3235			oprangeset(ASHA1P, t)
3236			oprangeset(ASHA1M, t)
3237			oprangeset(ASHA256H, t)
3238			oprangeset(ASHA256H2, t)
3239			oprangeset(ASHA512H, t)
3240			oprangeset(ASHA512H2, t)
3241
3242		case ASHA1SU0:
3243			oprangeset(ASHA256SU1, t)
3244			oprangeset(ASHA512SU1, t)
3245
3246		case AVADDV:
3247			oprangeset(AVUADDLV, t)
3248
3249		case AVFMLA:
3250			oprangeset(AVFMLS, t)
3251
3252		case AVPMULL:
3253			oprangeset(AVPMULL2, t)
3254
3255		case AVUSHR:
3256			oprangeset(AVSHL, t)
3257			oprangeset(AVSRI, t)
3258			oprangeset(AVSLI, t)
3259			oprangeset(AVUSRA, t)
3260
3261		case AVREV32:
3262			oprangeset(AVCNT, t)
3263			oprangeset(AVRBIT, t)
3264			oprangeset(AVREV64, t)
3265			oprangeset(AVREV16, t)
3266
3267		case AVZIP1:
3268			oprangeset(AVZIP2, t)
3269			oprangeset(AVTRN1, t)
3270			oprangeset(AVTRN2, t)
3271
3272		case AVUXTL:
3273			oprangeset(AVUXTL2, t)
3274
3275		case AVUSHLL:
3276			oprangeset(AVUSHLL2, t)
3277
3278		case AVLD1R:
3279			oprangeset(AVLD2, t)
3280			oprangeset(AVLD2R, t)
3281			oprangeset(AVLD3, t)
3282			oprangeset(AVLD3R, t)
3283			oprangeset(AVLD4, t)
3284			oprangeset(AVLD4R, t)
3285
3286		case AVEOR3:
3287			oprangeset(AVBCAX, t)
3288
3289		case AVUADDW:
3290			oprangeset(AVUADDW2, t)
3291
3292		case AVTBL:
3293			oprangeset(AVTBX, t)
3294
3295		case AVCNT,
3296			AVMOV,
3297			AVLD1,
3298			AVST1,
3299			AVST2,
3300			AVST3,
3301			AVST4,
3302			AVDUP,
3303			AVMOVI,
3304			APRFM,
3305			AVEXT,
3306			AVXAR:
3307			break
3308
3309		case obj.ANOP,
3310			obj.AUNDEF,
3311			obj.AFUNCDATA,
3312			obj.APCALIGN,
3313			obj.APCALIGNMAX,
3314			obj.APCDATA,
3315			obj.ADUFFZERO,
3316			obj.ADUFFCOPY:
3317			break
3318		}
3319	}
3320}
3321
3322// chipfloat7() checks if the immediate constants available in  FMOVS/FMOVD instructions.
3323// For details of the range of constants available, see
3324// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
3325func (c *ctxt7) chipfloat7(e float64) int {
3326	ei := math.Float64bits(e)
3327	l := uint32(int32(ei))
3328	h := uint32(int32(ei >> 32))
3329
3330	if l != 0 || h&0xffff != 0 {
3331		return -1
3332	}
3333	h1 := h & 0x7fc00000
3334	if h1 != 0x40000000 && h1 != 0x3fc00000 {
3335		return -1
3336	}
3337	n := 0
3338
3339	// sign bit (a)
3340	if h&0x80000000 != 0 {
3341		n |= 1 << 7
3342	}
3343
3344	// exp sign bit (b)
3345	if h1 == 0x3fc00000 {
3346		n |= 1 << 6
3347	}
3348
3349	// rest of exp and mantissa (cd-efgh)
3350	n |= int((h >> 16) & 0x3f)
3351
3352	//print("match %.8lux %.8lux %d\n", l, h, n);
3353	return n
3354}
3355
3356/* form offset parameter to SYS; special register number */
3357func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
3358	return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
3359}
3360
3361func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
3362	return SYSARG5(0, op1, Cn, Cm, op2)
3363}
3364
3365// checkUnpredictable checks if the source and transfer registers are the same register.
3366// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
3367func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
3368	if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
3369		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3370	}
3371	if isload && rt1 == rt2 {
3372		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3373	}
3374}
3375
3376/* checkindex checks if index >= 0 && index <= maxindex */
3377func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
3378	if index < 0 || index > maxindex {
3379		c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
3380	}
3381}
3382
3383/* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
3384func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
3385	var offset, list, n, expect int64
3386	switch as {
3387	case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3388		offset = p.From.Offset
3389		list = p.To.Offset
3390	case AVST1, AVST2, AVST3, AVST4:
3391		offset = p.To.Offset
3392		list = p.From.Offset
3393	default:
3394		c.ctxt.Diag("invalid operation on op %v", p.As)
3395	}
3396	opcode := (list >> 12) & 15
3397	q := (list >> 30) & 1
3398	size := (list >> 10) & 3
3399	if offset == 0 {
3400		return
3401	}
3402	switch opcode {
3403	case 0x7:
3404		n = 1 // one register
3405	case 0xa:
3406		n = 2 // two registers
3407	case 0x6:
3408		n = 3 // three registers
3409	case 0x2:
3410		n = 4 // four registers
3411	default:
3412		c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
3413	}
3414
3415	switch as {
3416	case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3417		if offset != n*(1<<uint(size)) {
3418			c.ctxt.Diag("invalid post-increment offset: %v", p)
3419		}
3420	default:
3421		if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
3422			c.ctxt.Diag("invalid post-increment offset: %v", p)
3423		}
3424	}
3425
3426	switch as {
3427	case AVLD1, AVST1:
3428		return
3429	case AVLD1R:
3430		expect = 1
3431	case AVLD2, AVST2, AVLD2R:
3432		expect = 2
3433	case AVLD3, AVST3, AVLD3R:
3434		expect = 3
3435	case AVLD4, AVST4, AVLD4R:
3436		expect = 4
3437	}
3438
3439	if expect != n {
3440		c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
3441	}
3442}
3443
3444/* checkShiftAmount checks whether the index shift amount is valid */
3445/* for load with register offset instructions */
3446func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
3447	var amount int16
3448	amount = (a.Index >> 5) & 7
3449	switch p.As {
3450	case AMOVB, AMOVBU:
3451		if amount != 0 {
3452			c.ctxt.Diag("invalid index shift amount: %v", p)
3453		}
3454	case AMOVH, AMOVHU:
3455		if amount != 1 && amount != 0 {
3456			c.ctxt.Diag("invalid index shift amount: %v", p)
3457		}
3458	case AMOVW, AMOVWU, AFMOVS:
3459		if amount != 2 && amount != 0 {
3460			c.ctxt.Diag("invalid index shift amount: %v", p)
3461		}
3462	case AMOVD, AFMOVD:
3463		if amount != 3 && amount != 0 {
3464			c.ctxt.Diag("invalid index shift amount: %v", p)
3465		}
3466	default:
3467		panic("invalid operation")
3468	}
3469}
3470
3471func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3472	var os [5]uint32
3473	o1 := uint32(0)
3474	o2 := uint32(0)
3475	o3 := uint32(0)
3476	o4 := uint32(0)
3477	o5 := uint32(0)
3478	if false { /*debug['P']*/
3479		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
3480	}
3481	switch o.type_ {
3482	default:
3483		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
3484
3485	case 0: /* pseudo ops */
3486		break
3487
3488	case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
3489		o1 = c.oprrr(p, p.As)
3490
3491		rf := int(p.From.Reg)
3492		rt := int(p.To.Reg)
3493		r := int(p.Reg)
3494		if p.To.Type == obj.TYPE_NONE {
3495			rt = REGZERO
3496		}
3497		if r == obj.REG_NONE {
3498			r = rt
3499		}
3500		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3501
3502	case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
3503		if p.To.Reg == REG_RSP && isADDSop(p.As) {
3504			c.ctxt.Diag("illegal destination register: %v\n", p)
3505		}
3506		o1 = c.opirr(p, p.As)
3507
3508		rt, r := p.To.Reg, p.Reg
3509		if p.To.Type == obj.TYPE_NONE {
3510			if (o1 & Sbit) == 0 {
3511				c.ctxt.Diag("ineffective ZR destination\n%v", p)
3512			}
3513			rt = REGZERO
3514		}
3515		if r == obj.REG_NONE {
3516			r = rt
3517		}
3518		v := c.regoff(&p.From)
3519		o1 = c.oaddi(p, p.As, v, rt, r)
3520
3521	case 3: /* op R<<n[,R],R (shifted register) */
3522		o1 = c.oprrr(p, p.As)
3523
3524		amount := (p.From.Offset >> 10) & 63
3525		is64bit := o1 & (1 << 31)
3526		if is64bit == 0 && amount >= 32 {
3527			c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
3528		}
3529		shift := (p.From.Offset >> 22) & 3
3530		if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) {
3531			c.ctxt.Diag("unsupported shift operator: %v", p)
3532		}
3533		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
3534		rt := int(p.To.Reg)
3535		if p.To.Type == obj.TYPE_NONE {
3536			rt = REGZERO
3537		}
3538		r := int(p.Reg)
3539		if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) {
3540			r = REGZERO
3541		} else if r == obj.REG_NONE {
3542			r = rt
3543		}
3544		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3545
3546	case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
3547		rt, r := p.To.Reg, o.param
3548		if r == obj.REG_NONE {
3549			r = REGZERO
3550		} else if r == REGFROM {
3551			r = p.From.Reg
3552		}
3553		if r == obj.REG_NONE {
3554			r = REGSP
3555		}
3556
3557		v := c.regoff(&p.From)
3558		a := AADD
3559		if v < 0 {
3560			a = ASUB
3561			v = -v
3562		}
3563
3564		if o.size(c.ctxt, p) == 8 {
3565			// NOTE: this case does not use REGTMP. If it ever does,
3566			// remove the NOTUSETMP flag in optab.
3567			o1 = c.oaddi(p, a, v&0xfff000, rt, r)
3568			o2 = c.oaddi(p, a, v&0x000fff, rt, rt)
3569			break
3570		}
3571
3572		o1 = c.oaddi(p, a, v, rt, r)
3573
3574	case 5: /* b s; bl s */
3575		o1 = c.opbra(p, p.As)
3576
3577		if p.To.Sym == nil {
3578			o1 |= uint32(c.brdist(p, 0, 26, 2))
3579			break
3580		}
3581
3582		rel := obj.Addrel(c.cursym)
3583		rel.Off = int32(c.pc)
3584		rel.Siz = 4
3585		rel.Sym = p.To.Sym
3586		rel.Add = p.To.Offset
3587		rel.Type = objabi.R_CALLARM64
3588
3589	case 6: /* b ,O(R); bl ,O(R) */
3590		o1 = c.opbrr(p, p.As)
3591		o1 |= uint32(p.To.Reg&31) << 5
3592		if p.As == obj.ACALL {
3593			rel := obj.Addrel(c.cursym)
3594			rel.Off = int32(c.pc)
3595			rel.Siz = 0
3596			rel.Type = objabi.R_CALLIND
3597		}
3598
3599	case 7: /* beq s */
3600		o1 = c.opbra(p, p.As)
3601
3602		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
3603
3604	case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
3605		rt, rf := p.To.Reg, p.Reg
3606		if rf == obj.REG_NONE {
3607			rf = rt
3608		}
3609		v := p.From.Offset
3610		switch p.As {
3611		case AASR:
3612			o1 = c.opbfm(p, ASBFM, v, 63, rf, rt)
3613
3614		case AASRW:
3615			o1 = c.opbfm(p, ASBFMW, v, 31, rf, rt)
3616
3617		case ALSL:
3618			o1 = c.opbfm(p, AUBFM, (64-v)&63, 63-v, rf, rt)
3619
3620		case ALSLW:
3621			o1 = c.opbfm(p, AUBFMW, (32-v)&31, 31-v, rf, rt)
3622
3623		case ALSR:
3624			o1 = c.opbfm(p, AUBFM, v, 63, rf, rt)
3625
3626		case ALSRW:
3627			o1 = c.opbfm(p, AUBFMW, v, 31, rf, rt)
3628
3629		case AROR:
3630			o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
3631
3632		case ARORW:
3633			o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
3634
3635		default:
3636			c.ctxt.Diag("bad shift $con\n%v", p)
3637			break
3638		}
3639
3640	case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
3641		o1 = c.oprrr(p, p.As)
3642
3643		r := int(p.Reg)
3644		if r == obj.REG_NONE {
3645			r = int(p.To.Reg)
3646		}
3647		o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
3648
3649	case 10: /* brk/hvc/.../svc [$con] */
3650		o1 = c.opimm(p, p.As)
3651
3652		if p.From.Type != obj.TYPE_NONE {
3653			o1 |= uint32((p.From.Offset & 0xffff) << 5)
3654		}
3655
3656	case 11: /* dword */
3657		c.aclass(&p.To)
3658
3659		o1 = uint32(c.instoffset)
3660		o2 = uint32(c.instoffset >> 32)
3661		if p.To.Sym != nil {
3662			rel := obj.Addrel(c.cursym)
3663			rel.Off = int32(c.pc)
3664			rel.Siz = 8
3665			rel.Sym = p.To.Sym
3666			rel.Add = p.To.Offset
3667			rel.Type = objabi.R_ADDR
3668			o2 = 0
3669			o1 = o2
3670		}
3671
3672	case 12: /* movT $vcon, reg */
3673		// NOTE: this case does not use REGTMP. If it ever does,
3674		// remove the NOTUSETMP flag in optab.
3675		num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
3676		if num == 0 {
3677			c.ctxt.Diag("invalid constant: %v", p)
3678		}
3679		o1 = os[0]
3680		o2 = os[1]
3681		o3 = os[2]
3682		o4 = os[3]
3683
3684	case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
3685		if p.Reg == REGTMP {
3686			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
3687		}
3688		if p.To.Reg == REG_RSP && isADDSop(p.As) {
3689			c.ctxt.Diag("illegal destination register: %v\n", p)
3690		}
3691		o := uint32(0)
3692		num := uint8(0)
3693		cls := int(p.From.Class)
3694		if isADDWop(p.As) {
3695			if !cmp(C_LCON, cls) {
3696				c.ctxt.Diag("illegal combination: %v", p)
3697			}
3698			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3699		} else {
3700			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3701		}
3702		if num == 0 {
3703			c.ctxt.Diag("invalid constant: %v", p)
3704		}
3705
3706		rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP)
3707		if p.To.Type == obj.TYPE_NONE {
3708			rt = REGZERO
3709		}
3710		if r == obj.REG_NONE {
3711			r = rt
3712		}
3713		if p.To.Type != obj.TYPE_NONE && (rt == REGSP || r == REGSP) {
3714			o = c.opxrrr(p, p.As, rt, r, rf, false)
3715			o |= LSL0_64
3716		} else {
3717			o = c.oprrr(p, p.As)
3718			o |= uint32(rf&31) << 16 /* shift is 0 */
3719			o |= uint32(r&31) << 5
3720			o |= uint32(rt & 31)
3721		}
3722
3723		os[num] = o
3724		o1 = os[0]
3725		o2 = os[1]
3726		o3 = os[2]
3727		o4 = os[3]
3728		o5 = os[4]
3729
3730	case 14: /* word */
3731		if c.aclass(&p.To) == C_ADDR {
3732			c.ctxt.Diag("address constant needs DWORD\n%v", p)
3733		}
3734		o1 = uint32(c.instoffset)
3735		if p.To.Sym != nil {
3736			// This case happens with words generated
3737			// in the PC stream as part of the literal pool.
3738			rel := obj.Addrel(c.cursym)
3739
3740			rel.Off = int32(c.pc)
3741			rel.Siz = 4
3742			rel.Sym = p.To.Sym
3743			rel.Add = p.To.Offset
3744			rel.Type = objabi.R_ADDR
3745			o1 = 0
3746		}
3747
3748	case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
3749		o1 = c.oprrr(p, p.As)
3750
3751		rf := int(p.From.Reg)
3752		rt := int(p.To.Reg)
3753		var r int
3754		var ra int
3755		if p.From3Type() == obj.TYPE_REG {
3756			r = int(p.GetFrom3().Reg)
3757			ra = int(p.Reg)
3758			if ra == obj.REG_NONE {
3759				ra = REGZERO
3760			}
3761		} else {
3762			r = int(p.Reg)
3763			if r == obj.REG_NONE {
3764				r = rt
3765			}
3766			ra = REGZERO
3767		}
3768
3769		o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
3770
3771	case 16: /* XremY R[,R],R -> XdivY; XmsubY */
3772		o1 = c.oprrr(p, p.As)
3773
3774		rf := int(p.From.Reg)
3775		rt := int(p.To.Reg)
3776		r := int(p.Reg)
3777		if r == obj.REG_NONE {
3778			r = rt
3779		}
3780		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
3781		o2 = c.oprrr(p, AMSUBW)
3782		o2 |= o1 & (1 << 31) /* same size */
3783		o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
3784
3785	case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
3786		o1 = c.oprrr(p, p.As)
3787
3788		rf := int(p.From.Reg)
3789		rt := int(p.To.Reg)
3790		r := int(p.Reg)
3791		if p.To.Type == obj.TYPE_NONE {
3792			rt = REGZERO
3793		}
3794		if r == obj.REG_NONE {
3795			r = REGZERO
3796		}
3797		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3798
3799	case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
3800		o1 = c.oprrr(p, p.As)
3801
3802		cond := SpecialOperand(p.From.Offset)
3803		if cond < SPOP_EQ || cond > SPOP_NV || (cond == SPOP_AL || cond == SPOP_NV) && p.From3Type() == obj.TYPE_NONE {
3804			c.ctxt.Diag("invalid condition: %v", p)
3805		} else {
3806			cond -= SPOP_EQ
3807		}
3808
3809		r := int(p.Reg)
3810		var rf int = r
3811		if p.From3Type() == obj.TYPE_NONE {
3812			/* CINC/CINV/CNEG or CSET/CSETM*/
3813			if r == obj.REG_NONE {
3814				/* CSET/CSETM */
3815				rf = REGZERO
3816				r = rf
3817			}
3818			cond ^= 1
3819		} else {
3820			rf = int(p.GetFrom3().Reg) /* CSEL */
3821		}
3822
3823		rt := int(p.To.Reg)
3824		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
3825
3826	case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
3827		nzcv := int(p.To.Offset)
3828
3829		cond := SpecialOperand(p.From.Offset)
3830		if cond < SPOP_EQ || cond > SPOP_NV {
3831			c.ctxt.Diag("invalid condition\n%v", p)
3832		} else {
3833			cond -= SPOP_EQ
3834		}
3835		var rf int
3836		if p.GetFrom3().Type == obj.TYPE_REG {
3837			o1 = c.oprrr(p, p.As)
3838			rf = int(p.GetFrom3().Reg) /* Rm */
3839		} else {
3840			o1 = c.opirr(p, p.As)
3841			rf = int(p.GetFrom3().Offset & 0x1F)
3842		}
3843
3844		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
3845
3846	case 20: /* movT R,O(R) -> strT */
3847		v := c.regoff(&p.To)
3848		sz := int32(1 << uint(movesize(p.As)))
3849
3850		rt, rf := p.To.Reg, p.From.Reg
3851		if rt == obj.REG_NONE {
3852			rt = o.param
3853		}
3854		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3855			o1 = c.olsr9s(p, c.opstr(p, p.As), v, rt, rf)
3856		} else {
3857			v = int32(c.offsetshift(p, int64(v), int(o.a4)))
3858			o1 = c.olsr12u(p, c.opstr(p, p.As), v, rt, rf)
3859		}
3860
3861	case 21: /* movT O(R),R -> ldrT */
3862		v := c.regoff(&p.From)
3863		sz := int32(1 << uint(movesize(p.As)))
3864
3865		rt, rf := p.To.Reg, p.From.Reg
3866		if rf == obj.REG_NONE {
3867			rf = o.param
3868		}
3869		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3870			o1 = c.olsr9s(p, c.opldr(p, p.As), v, rf, rt)
3871		} else {
3872			v = int32(c.offsetshift(p, int64(v), int(o.a1)))
3873			o1 = c.olsr12u(p, c.opldr(p, p.As), v, rf, rt)
3874		}
3875
3876	case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
3877		if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
3878			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3879		}
3880
3881		v := int32(p.From.Offset)
3882
3883		if v < -256 || v > 255 {
3884			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3885		}
3886		o1 = c.opldr(p, p.As)
3887		if o.scond == C_XPOST {
3888			o1 |= 1 << 10
3889		} else {
3890			o1 |= 3 << 10
3891		}
3892		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
3893
3894	case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
3895		if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
3896			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3897		}
3898
3899		v := int32(p.To.Offset)
3900
3901		if v < -256 || v > 255 {
3902			c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3903		}
3904		o1 = c.opstr(p, p.As)
3905		if o.scond == C_XPOST {
3906			o1 |= 1 << 10
3907		} else {
3908			o1 |= 3 << 10
3909		}
3910		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
3911
3912	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
3913		rf := int(p.From.Reg)
3914		rt := int(p.To.Reg)
3915		if rf == REGSP || rt == REGSP {
3916			if p.As == AMVN || p.As == AMVNW {
3917				c.ctxt.Diag("illegal SP reference\n%v", p)
3918			}
3919			o1 = c.opirr(p, p.As)
3920			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
3921		} else {
3922			o1 = c.oprrr(p, p.As)
3923			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3924		}
3925
3926	case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
3927		o1 = c.oprrr(p, p.As)
3928
3929		rf := int(p.From.Reg)
3930		if rf == C_NONE {
3931			rf = int(p.To.Reg)
3932		}
3933		rt := int(p.To.Reg)
3934		o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3935
3936	case 26: /* op Vn, Vd; op Vn.<T>, Vd.<T> */
3937		o1 = c.oprrr(p, p.As)
3938		cf := c.aclass(&p.From)
3939		af := (p.From.Reg >> 5) & 15
3940		at := (p.To.Reg >> 5) & 15
3941		var sz int16
3942		switch p.As {
3943		case AAESD, AAESE, AAESIMC, AAESMC:
3944			sz = ARNG_16B
3945		case ASHA1SU1, ASHA256SU0:
3946			sz = ARNG_4S
3947		case ASHA512SU0:
3948			sz = ARNG_2D
3949		}
3950
3951		if cf == C_ARNG {
3952			if p.As == ASHA1H {
3953				c.ctxt.Diag("invalid operands: %v", p)
3954			} else {
3955				if af != sz || af != at {
3956					c.ctxt.Diag("invalid arrangement: %v", p)
3957				}
3958			}
3959		}
3960		o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
3961
3962	case 27: /* op Rm<<n[,Rn],Rd (extended register) */
3963		if p.To.Reg == REG_RSP && isADDSop(p.As) {
3964			c.ctxt.Diag("illegal destination register: %v\n", p)
3965		}
3966		rt, r, rf := p.To.Reg, p.Reg, p.From.Reg
3967		if p.To.Type == obj.TYPE_NONE {
3968			rt = REGZERO
3969		}
3970		if r == obj.REG_NONE {
3971			r = rt
3972		}
3973		if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 ||
3974			(p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) {
3975			amount := (p.From.Reg >> 5) & 7
3976			if amount > 4 {
3977				c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
3978			}
3979			o1 = c.opxrrr(p, p.As, rt, r, obj.REG_NONE, true)
3980			o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
3981		} else {
3982			o1 = c.opxrrr(p, p.As, rt, r, rf, false)
3983		}
3984
3985	case 28: /* logop $vcon, [R], R (64 bit literal) */
3986		if p.Reg == REGTMP {
3987			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
3988		}
3989		o := uint32(0)
3990		num := uint8(0)
3991		cls := int(p.From.Class)
3992		if isANDWop(p.As) {
3993			if !cmp(C_LCON, cls) {
3994				c.ctxt.Diag("illegal combination: %v", p)
3995			}
3996			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3997		} else {
3998			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3999		}
4000
4001		if num == 0 {
4002			c.ctxt.Diag("invalid constant: %v", p)
4003		}
4004		rt := int(p.To.Reg)
4005		if p.To.Type == obj.TYPE_NONE {
4006			rt = REGZERO
4007		}
4008		r := int(p.Reg)
4009		if r == obj.REG_NONE {
4010			r = rt
4011		}
4012		o = c.oprrr(p, p.As)
4013		o |= REGTMP & 31 << 16 /* shift is 0 */
4014		o |= uint32(r&31) << 5
4015		o |= uint32(rt & 31)
4016
4017		os[num] = o
4018		o1 = os[0]
4019		o2 = os[1]
4020		o3 = os[2]
4021		o4 = os[3]
4022		o5 = os[4]
4023
4024	case 29: /* op Rn, Rd */
4025		fc := c.aclass(&p.From)
4026		tc := c.aclass(&p.To)
4027		if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZREG || tc == C_REG || tc == C_ZREG) {
4028			// FMOV Rx, Fy or FMOV Fy, Rx
4029			o1 = FPCVTI(0, 0, 0, 0, 6)
4030			if p.As == AFMOVD {
4031				o1 |= 1<<31 | 1<<22 // 64-bit
4032			}
4033			if fc == C_REG || fc == C_ZREG {
4034				o1 |= 1 << 16 // FMOV Rx, Fy
4035			}
4036		} else {
4037			o1 = c.oprrr(p, p.As)
4038		}
4039		o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
4040
4041	case 30: /* movT R,L(R) -> strT */
4042		// If offset L fits in a 12 bit unsigned immediate:
4043		//	add $L, R, Rtmp  or  sub $L, R, Rtmp
4044		//	str R, (Rtmp)
4045		// Otherwise, if offset L can be split into hi+lo, and both fit into instructions:
4046		//	add $hi, R, Rtmp
4047		//	str R, lo(Rtmp)
4048		// Otherwise, use constant pool:
4049		//	mov $L, Rtmp (from constant pool)
4050		//	str R, (R+Rtmp)
4051		s := movesize(o.as)
4052		if s < 0 {
4053			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
4054		}
4055
4056		r := p.To.Reg
4057		if r == obj.REG_NONE {
4058			r = o.param
4059		}
4060
4061		v := c.regoff(&p.To)
4062		if v >= -256 && v <= 256 {
4063			c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate store)", p, v)
4064		}
4065		if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 {
4066			c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate store)", p, v)
4067		}
4068
4069		// Handle smaller unaligned and negative offsets via addition or subtraction.
4070		if v >= -4095 && v <= 4095 {
4071			o1 = c.oaddi12(p, v, REGTMP, int16(r))
4072			o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg)
4073			break
4074		}
4075
4076		hi, lo, err := splitImm24uScaled(v, s)
4077		if err != nil {
4078			goto storeusepool
4079		}
4080		if p.Pool != nil {
4081			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
4082		}
4083		o1 = c.oaddi(p, AADD, hi, REGTMP, r)
4084		o2 = c.olsr12u(p, c.opstr(p, p.As), lo, REGTMP, p.From.Reg)
4085		break
4086
4087	storeusepool:
4088		if p.Pool == nil {
4089			c.ctxt.Diag("%v: constant is not in pool", p)
4090		}
4091		if r == REGTMP || p.From.Reg == REGTMP {
4092			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
4093		}
4094		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
4095		o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), int(r), REGTMP)
4096
4097	case 31: /* movT L(R), R -> ldrT */
4098		// If offset L fits in a 12 bit unsigned immediate:
4099		//	add $L, R, Rtmp  or  sub $L, R, Rtmp
4100		//	ldr R, (Rtmp)
4101		// Otherwise, if offset L can be split into hi+lo, and both fit into instructions:
4102		//	add $hi, R, Rtmp
4103		//	ldr lo(Rtmp), R
4104		// Otherwise, use constant pool:
4105		//	mov $L, Rtmp (from constant pool)
4106		//	ldr (R+Rtmp), R
4107		s := movesize(o.as)
4108		if s < 0 {
4109			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
4110		}
4111
4112		r := p.From.Reg
4113		if r == obj.REG_NONE {
4114			r = o.param
4115		}
4116
4117		v := c.regoff(&p.From)
4118		if v >= -256 && v <= 256 {
4119			c.ctxt.Diag("%v: bad type for offset %d (should be 9 bit signed immediate load)", p, v)
4120		}
4121		if v >= 0 && v <= 4095 && v&((1<<int32(s))-1) == 0 {
4122			c.ctxt.Diag("%v: bad type for offset %d (should be 12 bit unsigned immediate load)", p, v)
4123		}
4124
4125		// Handle smaller unaligned and negative offsets via addition or subtraction.
4126		if v >= -4095 && v <= 4095 {
4127			o1 = c.oaddi12(p, v, REGTMP, int16(r))
4128			o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg)
4129			break
4130		}
4131
4132		hi, lo, err := splitImm24uScaled(v, s)
4133		if err != nil {
4134			goto loadusepool
4135		}
4136		if p.Pool != nil {
4137			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
4138		}
4139		o1 = c.oaddi(p, AADD, hi, REGTMP, r)
4140		o2 = c.olsr12u(p, c.opldr(p, p.As), lo, REGTMP, p.To.Reg)
4141		break
4142
4143	loadusepool:
4144		if p.Pool == nil {
4145			c.ctxt.Diag("%v: constant is not in pool", p)
4146		}
4147		if r == REGTMP || p.From.Reg == REGTMP {
4148			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
4149		}
4150		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4151		o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), int(r), REGTMP)
4152
4153	case 32: /* mov $con, R -> movz/movn */
4154		o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
4155
4156	case 33: /* movk $uimm16 << pos */
4157		o1 = c.opirr(p, p.As)
4158
4159		d := p.From.Offset
4160		if d == 0 {
4161			c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p)
4162		}
4163		s := movcon(d)
4164		if s < 0 || s >= 4 {
4165			c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
4166		}
4167		if (o1&S64) == 0 && s >= 2 {
4168			c.ctxt.Diag("illegal bit position\n%v", p)
4169		}
4170		if ((uint64(d) >> uint(s*16)) >> 16) != 0 {
4171			c.ctxt.Diag("requires uimm16\n%v", p)
4172		}
4173		rt := int(p.To.Reg)
4174
4175		o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
4176
4177	case 34: /* mov $lacon,R */
4178		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4179		rt, r, rf := p.To.Reg, p.From.Reg, int16(REGTMP)
4180		if r == obj.REG_NONE {
4181			r = o.param
4182		}
4183		o2 = c.opxrrr(p, AADD, rt, r, rf, false)
4184		o2 |= LSL0_64
4185
4186	case 35: /* mov SPR,R -> mrs */
4187		o1 = c.oprrr(p, AMRS)
4188
4189		// SysRegEnc function returns the system register encoding and accessFlags.
4190		_, v, accessFlags := SysRegEnc(p.From.Reg)
4191		if v == 0 {
4192			c.ctxt.Diag("illegal system register:\n%v", p)
4193		}
4194		if (o1 & (v &^ (3 << 19))) != 0 {
4195			c.ctxt.Diag("MRS register value overlap\n%v", p)
4196		}
4197		if accessFlags&SR_READ == 0 {
4198			c.ctxt.Diag("system register is not readable: %v", p)
4199		}
4200
4201		o1 |= v
4202		o1 |= uint32(p.To.Reg & 31)
4203
4204	case 36: /* mov R,SPR */
4205		o1 = c.oprrr(p, AMSR)
4206
4207		// SysRegEnc function returns the system register encoding and accessFlags.
4208		_, v, accessFlags := SysRegEnc(p.To.Reg)
4209		if v == 0 {
4210			c.ctxt.Diag("illegal system register:\n%v", p)
4211		}
4212		if (o1 & (v &^ (3 << 19))) != 0 {
4213			c.ctxt.Diag("MSR register value overlap\n%v", p)
4214		}
4215		if accessFlags&SR_WRITE == 0 {
4216			c.ctxt.Diag("system register is not writable: %v", p)
4217		}
4218
4219		o1 |= v
4220		o1 |= uint32(p.From.Reg & 31)
4221
4222	case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
4223		if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
4224			c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
4225		}
4226		o1 = c.opirr(p, AMSR)
4227		o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
4228		v := uint32(0)
4229		// PSTATEfield can be special registers and special operands.
4230		if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SPSel {
4231			v = 0<<16 | 4<<12 | 5<<5
4232		} else if p.To.Type == obj.TYPE_SPECIAL {
4233			opd := SpecialOperand(p.To.Offset)
4234			for _, pf := range pstatefield {
4235				if pf.opd == opd {
4236					v = pf.enc
4237					break
4238				}
4239			}
4240		}
4241
4242		if v == 0 {
4243			c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
4244		}
4245		o1 |= v
4246
4247	case 38: /* clrex [$imm] */
4248		o1 = c.opimm(p, p.As)
4249
4250		if p.To.Type == obj.TYPE_NONE {
4251			o1 |= 0xF << 8
4252		} else {
4253			o1 |= uint32((p.To.Offset & 0xF) << 8)
4254		}
4255
4256	case 39: /* cbz R, rel */
4257		o1 = c.opirr(p, p.As)
4258
4259		o1 |= uint32(p.From.Reg & 31)
4260		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
4261
4262	case 40: /* tbz */
4263		o1 = c.opirr(p, p.As)
4264
4265		v := int32(p.From.Offset)
4266		if v < 0 || v > 63 {
4267			c.ctxt.Diag("illegal bit number\n%v", p)
4268		}
4269		o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
4270		o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
4271		o1 |= uint32(p.Reg & 31)
4272
4273	case 41: /* eret, nop, others with no operands */
4274		o1 = c.op0(p, p.As)
4275
4276	case 42: /* bfm R,r,s,R */
4277		o1 = c.opbfm(p, p.As, p.From.Offset, p.GetFrom3().Offset, p.Reg, p.To.Reg)
4278
4279	case 43: /* bfm aliases */
4280		rt, rf := p.To.Reg, p.Reg
4281		if rf == obj.REG_NONE {
4282			rf = rt
4283		}
4284		r, s := p.From.Offset, p.GetFrom3().Offset
4285		switch p.As {
4286		case ABFI:
4287			if r != 0 {
4288				r = 64 - r
4289			}
4290			o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
4291
4292		case ABFIW:
4293			if r != 0 {
4294				r = 32 - r
4295			}
4296			o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
4297
4298		case ABFXIL:
4299			o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
4300
4301		case ABFXILW:
4302			o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
4303
4304		case ASBFIZ:
4305			if r != 0 {
4306				r = 64 - r
4307			}
4308			o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
4309
4310		case ASBFIZW:
4311			if r != 0 {
4312				r = 32 - r
4313			}
4314			o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
4315
4316		case ASBFX:
4317			o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
4318
4319		case ASBFXW:
4320			o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
4321
4322		case AUBFIZ:
4323			if r != 0 {
4324				r = 64 - r
4325			}
4326			o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
4327
4328		case AUBFIZW:
4329			if r != 0 {
4330				r = 32 - r
4331			}
4332			o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
4333
4334		case AUBFX:
4335			o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
4336
4337		case AUBFXW:
4338			o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
4339
4340		default:
4341			c.ctxt.Diag("bad bfm alias\n%v", p)
4342			break
4343		}
4344
4345	case 44: /* extr $b, Rn, Rm, Rd */
4346		o1 = c.opextr(p, p.As, p.From.Offset, p.GetFrom3().Reg, p.Reg, p.To.Reg)
4347
4348	case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
4349		as := p.As
4350		rt, rf := p.To.Reg, p.From.Reg
4351		if rf == REGZERO {
4352			as = AMOVWU /* clearer in disassembly */
4353		}
4354		switch as {
4355		case AMOVB, ASXTB:
4356			o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
4357
4358		case AMOVH, ASXTH:
4359			o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
4360
4361		case AMOVW, ASXTW:
4362			o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
4363
4364		case AMOVBU, AUXTB:
4365			o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
4366
4367		case AMOVHU, AUXTH:
4368			o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
4369
4370		case AMOVWU:
4371			o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
4372
4373		case AUXTW:
4374			o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
4375
4376		case ASXTBW:
4377			o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
4378
4379		case ASXTHW:
4380			o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
4381
4382		case AUXTBW:
4383			o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
4384
4385		case AUXTHW:
4386			o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
4387
4388		default:
4389			c.ctxt.Diag("bad sxt %v", as)
4390			break
4391		}
4392
4393	case 46: /* cls */
4394		o1 = c.opbit(p, p.As)
4395
4396		o1 |= uint32(p.From.Reg&31) << 5
4397		o1 |= uint32(p.To.Reg & 31)
4398
4399	case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt
4400		rs := p.From.Reg
4401		rt := p.RegTo2
4402		rb := p.To.Reg
4403
4404		// rt can't be sp.
4405		if rt == REG_RSP {
4406			c.ctxt.Diag("illegal destination register: %v\n", p)
4407		}
4408
4409		o1 = atomicLDADD[p.As] | atomicSWP[p.As]
4410		o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
4411
4412	case 48: /* ADD $C_ADDCON2, Rm, Rd */
4413		// NOTE: this case does not use REGTMP. If it ever does,
4414		// remove the NOTUSETMP flag in optab.
4415		op := c.opirr(p, p.As)
4416		if op&Sbit != 0 {
4417			c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
4418		}
4419		rt, r := p.To.Reg, p.Reg
4420		if r == obj.REG_NONE {
4421			r = rt
4422		}
4423		o1 = c.oaddi(p, p.As, c.regoff(&p.From)&0x000fff, rt, r)
4424		o2 = c.oaddi(p, p.As, c.regoff(&p.From)&0xfff000, rt, rt)
4425
4426	case 49: /* op Vm.<T>, Vn, Vd */
4427		o1 = c.oprrr(p, p.As)
4428		cf := c.aclass(&p.From)
4429		af := (p.From.Reg >> 5) & 15
4430		sz := ARNG_4S
4431		if p.As == ASHA512H || p.As == ASHA512H2 {
4432			sz = ARNG_2D
4433		}
4434		if cf == C_ARNG && af != int16(sz) {
4435			c.ctxt.Diag("invalid arrangement: %v", p)
4436		}
4437		o1 |= uint32(p.From.Reg&31)<<16 | uint32(p.Reg&31)<<5 | uint32(p.To.Reg&31)
4438
4439	case 50: /* sys/sysl */
4440		o1 = c.opirr(p, p.As)
4441
4442		if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
4443			c.ctxt.Diag("illegal SYS argument\n%v", p)
4444		}
4445		o1 |= uint32(p.From.Offset)
4446		if p.To.Type == obj.TYPE_REG {
4447			o1 |= uint32(p.To.Reg & 31)
4448		} else {
4449			o1 |= 0x1F
4450		}
4451
4452	case 51: /* dmb */
4453		o1 = c.opirr(p, p.As)
4454
4455		if p.From.Type == obj.TYPE_CONST {
4456			o1 |= uint32((p.From.Offset & 0xF) << 8)
4457		}
4458
4459	case 52: /* hint */
4460		o1 = c.opirr(p, p.As)
4461
4462		o1 |= uint32((p.From.Offset & 0x7F) << 5)
4463
4464	case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
4465		a := p.As
4466		rt := int(p.To.Reg)
4467		if p.To.Type == obj.TYPE_NONE {
4468			rt = REGZERO
4469		}
4470		r := int(p.Reg)
4471		if r == obj.REG_NONE {
4472			r = rt
4473		}
4474		if r == REG_RSP {
4475			c.ctxt.Diag("illegal source register: %v", p)
4476			break
4477		}
4478		mode := 64
4479		v := uint64(p.From.Offset)
4480		switch p.As {
4481		case AANDW, AORRW, AEORW, AANDSW, ATSTW:
4482			mode = 32
4483		case ABIC, AORN, AEON, ABICS:
4484			v = ^v
4485		case ABICW, AORNW, AEONW, ABICSW:
4486			v = ^v
4487			mode = 32
4488		}
4489		o1 = c.opirr(p, a)
4490		o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
4491
4492	case 54: /* floating point arith */
4493		o1 = c.oprrr(p, p.As)
4494		rf := int(p.From.Reg)
4495		rt := int(p.To.Reg)
4496		r := int(p.Reg)
4497		if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
4498			r = rf
4499			rf = 0
4500		} else if r == obj.REG_NONE {
4501			r = rt
4502		}
4503		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4504
4505	case 55: /* floating-point constant */
4506		var rf int
4507		o1 = 0xf<<25 | 1<<21 | 1<<12
4508		rf = c.chipfloat7(p.From.Val.(float64))
4509		if rf < 0 {
4510			c.ctxt.Diag("invalid floating-point immediate\n%v", p)
4511		}
4512		if p.As == AFMOVD {
4513			o1 |= 1 << 22
4514		}
4515		o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
4516
4517	case 56: /* floating point compare */
4518		o1 = c.oprrr(p, p.As)
4519
4520		var rf int
4521		if p.From.Type == obj.TYPE_FCONST {
4522			o1 |= 8 /* zero */
4523			rf = 0
4524		} else {
4525			rf = int(p.From.Reg)
4526		}
4527		rt := int(p.Reg)
4528		o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
4529
4530	case 57: /* floating point conditional compare */
4531		o1 = c.oprrr(p, p.As)
4532
4533		cond := SpecialOperand(p.From.Offset)
4534		if cond < SPOP_EQ || cond > SPOP_NV {
4535			c.ctxt.Diag("invalid condition\n%v", p)
4536		} else {
4537			cond -= SPOP_EQ
4538		}
4539
4540		nzcv := int(p.To.Offset)
4541		if nzcv&^0xF != 0 {
4542			c.ctxt.Diag("implausible condition\n%v", p)
4543		}
4544		rf := int(p.Reg)
4545		if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
4546			c.ctxt.Diag("illegal FCCMP\n%v", p)
4547			break
4548		}
4549		rt := int(p.GetFrom3().Reg)
4550		o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
4551
4552	case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
4553		o1 = c.opload(p, p.As)
4554
4555		o1 |= 0x1F << 16
4556		o1 |= uint32(p.From.Reg&31) << 5
4557		if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
4558			if int(p.To.Reg) == int(p.To.Offset) {
4559				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4560			}
4561			o1 |= uint32(p.To.Offset&31) << 10
4562		} else {
4563			o1 |= 0x1F << 10
4564		}
4565		o1 |= uint32(p.To.Reg & 31)
4566
4567	case 59: /* stxr/stlxr/stxp/stlxp */
4568		s := p.RegTo2
4569		n := p.To.Reg
4570		t := p.From.Reg
4571		if isSTLXRop(p.As) {
4572			if s == t || (s == n && n != REGSP) {
4573				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4574			}
4575		} else if isSTXPop(p.As) {
4576			t2 := int16(p.From.Offset)
4577			if (s == t || s == t2) || (s == n && n != REGSP) {
4578				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4579			}
4580		}
4581		if s == REG_RSP {
4582			c.ctxt.Diag("illegal destination register: %v\n", p)
4583		}
4584		o1 = c.opstore(p, p.As)
4585
4586		if p.RegTo2 != obj.REG_NONE {
4587			o1 |= uint32(p.RegTo2&31) << 16
4588		} else {
4589			o1 |= 0x1F << 16
4590		}
4591		if isSTXPop(p.As) {
4592			o1 |= uint32(p.From.Offset&31) << 10
4593		}
4594		o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
4595
4596	case 60: /* adrp label,r */
4597		d := c.brdist(p, 12, 21, 0)
4598
4599		o1 = ADR(1, uint32(d), uint32(p.To.Reg))
4600
4601	case 61: /* adr label, r */
4602		d := c.brdist(p, 0, 21, 0)
4603
4604		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
4605
4606	case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
4607		if p.Reg == REGTMP {
4608			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
4609		}
4610		if p.To.Reg == REG_RSP && isADDSop(p.As) {
4611			c.ctxt.Diag("illegal destination register: %v\n", p)
4612		}
4613		lsl0 := LSL0_64
4614		if isADDWop(p.As) || isANDWop(p.As) {
4615			o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
4616			lsl0 = LSL0_32
4617		} else {
4618			o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
4619		}
4620
4621		rt, r, rf := p.To.Reg, p.Reg, int16(REGTMP)
4622		if p.To.Type == obj.TYPE_NONE {
4623			rt = REGZERO
4624		}
4625		if r == obj.REG_NONE {
4626			r = rt
4627		}
4628		if rt == REGSP || r == REGSP {
4629			o2 = c.opxrrr(p, p.As, rt, r, rf, false)
4630			o2 |= uint32(lsl0)
4631		} else {
4632			o2 = c.oprrr(p, p.As)
4633			o2 |= uint32(rf&31) << 16 /* shift is 0 */
4634			o2 |= uint32(r&31) << 5
4635			o2 |= uint32(rt & 31)
4636		}
4637
4638	case 63: /* op Vm.<t>, Vn.<T>, Vd.<T> */
4639		o1 |= c.oprrr(p, p.As)
4640		af := (p.From.Reg >> 5) & 15
4641		at := (p.To.Reg >> 5) & 15
4642		ar := (p.Reg >> 5) & 15
4643		sz := ARNG_4S
4644		if p.As == ASHA512SU1 {
4645			sz = ARNG_2D
4646		}
4647		if af != at || af != ar || af != int16(sz) {
4648			c.ctxt.Diag("invalid arrangement: %v", p)
4649		}
4650		o1 |= uint32(p.From.Reg&31)<<16 | uint32(p.Reg&31)<<5 | uint32(p.To.Reg&31)
4651
4652	/* reloc ops */
4653	case 64: /* movT R,addr -> adrp + movT R, (REGTMP) */
4654		if p.From.Reg == REGTMP {
4655			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
4656		}
4657		o1 = ADR(1, 0, REGTMP)
4658		rel := obj.Addrel(c.cursym)
4659		rel.Off = int32(c.pc)
4660		rel.Siz = 8
4661		rel.Sym = p.To.Sym
4662		rel.Add = p.To.Offset
4663		// For unaligned access, fall back to adrp + add + movT R, (REGTMP).
4664		if o.size(c.ctxt, p) != 8 {
4665			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4666			o3 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg)
4667			rel.Type = objabi.R_ADDRARM64
4668			break
4669		}
4670		o2 = c.olsr12u(p, c.opstr(p, p.As), 0, REGTMP, p.From.Reg)
4671		rel.Type = c.addrRelocType(p)
4672
4673	case 65: /* movT addr,R -> adrp + movT (REGTMP), R */
4674		o1 = ADR(1, 0, REGTMP)
4675		rel := obj.Addrel(c.cursym)
4676		rel.Off = int32(c.pc)
4677		rel.Siz = 8
4678		rel.Sym = p.From.Sym
4679		rel.Add = p.From.Offset
4680		// For unaligned access, fall back to adrp + add + movT (REGTMP), R.
4681		if o.size(c.ctxt, p) != 8 {
4682			o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4683			o3 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg)
4684			rel.Type = objabi.R_ADDRARM64
4685			break
4686		}
4687		o2 = c.olsr12u(p, c.opldr(p, p.As), 0, REGTMP, p.To.Reg)
4688		rel.Type = c.addrRelocType(p)
4689
4690	case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
4691		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
4692		if rf == obj.REG_NONE {
4693			rf = o.param
4694		}
4695		if rf == obj.REG_NONE {
4696			c.ctxt.Diag("invalid ldp source: %v\n", p)
4697		}
4698		v := c.regoff(&p.From)
4699		o1 = c.opldpstp(p, o, v, rf, rt1, rt2, 1)
4700
4701	case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
4702		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
4703		if rt == obj.REG_NONE {
4704			rt = o.param
4705		}
4706		if rt == obj.REG_NONE {
4707			c.ctxt.Diag("invalid stp destination: %v\n", p)
4708		}
4709		v := c.regoff(&p.To)
4710		o1 = c.opldpstp(p, o, v, rt, rf1, rf2, 0)
4711
4712	case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
4713		// NOTE: this case does not use REGTMP. If it ever does,
4714		// remove the NOTUSETMP flag in optab.
4715		if p.As == AMOVW {
4716			c.ctxt.Diag("invalid load of 32-bit address: %v", p)
4717		}
4718		o1 = ADR(1, 0, uint32(p.To.Reg))
4719		o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
4720		rel := obj.Addrel(c.cursym)
4721		rel.Off = int32(c.pc)
4722		rel.Siz = 8
4723		rel.Sym = p.From.Sym
4724		rel.Add = p.From.Offset
4725		rel.Type = objabi.R_ADDRARM64
4726
4727	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
4728		o1 = c.opirr(p, AMOVZ)
4729		o1 |= uint32(p.To.Reg & 31)
4730		rel := obj.Addrel(c.cursym)
4731		rel.Off = int32(c.pc)
4732		rel.Siz = 4
4733		rel.Sym = p.From.Sym
4734		rel.Type = objabi.R_ARM64_TLS_LE
4735		if p.From.Offset != 0 {
4736			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4737		}
4738
4739	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
4740		o1 = ADR(1, 0, REGTMP)
4741		o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg)
4742		rel := obj.Addrel(c.cursym)
4743		rel.Off = int32(c.pc)
4744		rel.Siz = 8
4745		rel.Sym = p.From.Sym
4746		rel.Add = 0
4747		rel.Type = objabi.R_ARM64_TLS_IE
4748		if p.From.Offset != 0 {
4749			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4750		}
4751
4752	case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
4753		o1 = ADR(1, 0, REGTMP)
4754		o2 = c.olsr12u(p, c.opldr(p, AMOVD), 0, REGTMP, p.To.Reg)
4755		rel := obj.Addrel(c.cursym)
4756		rel.Off = int32(c.pc)
4757		rel.Siz = 8
4758		rel.Sym = p.From.Sym
4759		rel.Add = 0
4760		rel.Type = objabi.R_ARM64_GOTPCREL
4761
4762	case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2/vrax1 Vm.<T>, Vn.<T>, Vd.<T> */
4763		af := int((p.From.Reg >> 5) & 15)
4764		af3 := int((p.Reg >> 5) & 15)
4765		at := int((p.To.Reg >> 5) & 15)
4766		if af != af3 || af != at {
4767			c.ctxt.Diag("operand mismatch: %v", p)
4768			break
4769		}
4770		o1 = c.oprrr(p, p.As)
4771		rf := int((p.From.Reg) & 31)
4772		rt := int((p.To.Reg) & 31)
4773		r := int((p.Reg) & 31)
4774
4775		Q := 0
4776		size := 0
4777		switch af {
4778		case ARNG_16B:
4779			Q = 1
4780			size = 0
4781		case ARNG_2D:
4782			Q = 1
4783			size = 3
4784		case ARNG_2S:
4785			Q = 0
4786			size = 2
4787		case ARNG_4H:
4788			Q = 0
4789			size = 1
4790		case ARNG_4S:
4791			Q = 1
4792			size = 2
4793		case ARNG_8B:
4794			Q = 0
4795			size = 0
4796		case ARNG_8H:
4797			Q = 1
4798			size = 1
4799		default:
4800			c.ctxt.Diag("invalid arrangement: %v", p)
4801		}
4802
4803		switch p.As {
4804		case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
4805			if af != ARNG_16B && af != ARNG_8B {
4806				c.ctxt.Diag("invalid arrangement: %v", p)
4807			}
4808		case AVFMLA, AVFMLS:
4809			if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
4810				c.ctxt.Diag("invalid arrangement: %v", p)
4811			}
4812		case AVUMAX, AVUMIN:
4813			if af == ARNG_2D {
4814				c.ctxt.Diag("invalid arrangement: %v", p)
4815			}
4816		}
4817		switch p.As {
4818		case AVAND, AVEOR:
4819			size = 0
4820		case AVBSL:
4821			size = 1
4822		case AVORR, AVBIT, AVBIF:
4823			size = 2
4824		case AVFMLA, AVFMLS:
4825			if af == ARNG_2D {
4826				size = 1
4827			} else {
4828				size = 0
4829			}
4830		case AVRAX1:
4831			if af != ARNG_2D {
4832				c.ctxt.Diag("invalid arrangement: %v", p)
4833			}
4834			size = 0
4835			Q = 0
4836		}
4837
4838		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4839
4840	case 73: /* vmov V.<T>[index], R */
4841		rf := int(p.From.Reg)
4842		rt := int(p.To.Reg)
4843		imm5 := 0
4844		o1 = 7<<25 | 0xf<<10
4845		index := int(p.From.Index)
4846		switch (p.From.Reg >> 5) & 15 {
4847		case ARNG_B:
4848			c.checkindex(p, index, 15)
4849			imm5 |= 1
4850			imm5 |= index << 1
4851		case ARNG_H:
4852			c.checkindex(p, index, 7)
4853			imm5 |= 2
4854			imm5 |= index << 2
4855		case ARNG_S:
4856			c.checkindex(p, index, 3)
4857			imm5 |= 4
4858			imm5 |= index << 3
4859		case ARNG_D:
4860			c.checkindex(p, index, 1)
4861			imm5 |= 8
4862			imm5 |= index << 4
4863			o1 |= 1 << 30
4864		default:
4865			c.ctxt.Diag("invalid arrangement: %v", p)
4866		}
4867		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4868
4869	case 74:
4870		//	add $O, R, Rtmp or sub $O, R, Rtmp
4871		//	ldp (Rtmp), (R1, R2)
4872		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
4873		if rf == obj.REG_NONE {
4874			rf = o.param
4875		}
4876		if rf == obj.REG_NONE {
4877			c.ctxt.Diag("invalid ldp source: %v", p)
4878		}
4879		v := c.regoff(&p.From)
4880		o1 = c.oaddi12(p, v, REGTMP, rf)
4881		o2 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
4882
4883	case 75:
4884		// If offset L fits in a 24 bit unsigned immediate:
4885		//	add $lo, R, Rtmp
4886		//	add $hi, Rtmp, Rtmp
4887		//	ldr (Rtmp), R
4888		// Otherwise, use constant pool:
4889		//	mov $L, Rtmp (from constant pool)
4890		//	add Rtmp, R, Rtmp
4891		//	ldp (Rtmp), (R1, R2)
4892		rf, rt1, rt2 := p.From.Reg, p.To.Reg, int16(p.To.Offset)
4893		if rf == REGTMP {
4894			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
4895		}
4896		if rf == obj.REG_NONE {
4897			rf = o.param
4898		}
4899		if rf == obj.REG_NONE {
4900			c.ctxt.Diag("invalid ldp source: %v", p)
4901		}
4902
4903		v := c.regoff(&p.From)
4904		if v >= -4095 && v <= 4095 {
4905			c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+ldp)", p, v)
4906		}
4907
4908		hi, lo, err := splitImm24uScaled(v, 0)
4909		if err != nil {
4910			goto loadpairusepool
4911		}
4912		if p.Pool != nil {
4913			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
4914		}
4915		o1 = c.oaddi(p, AADD, lo, REGTMP, int16(rf))
4916		o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP)
4917		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
4918		break
4919
4920	loadpairusepool:
4921		if p.Pool == nil {
4922			c.ctxt.Diag("%v: constant is not in pool", p)
4923		}
4924		if rf == REGTMP || p.From.Reg == REGTMP {
4925			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
4926		}
4927		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4928		o2 = c.opxrrr(p, AADD, REGTMP, rf, REGTMP, false)
4929		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
4930
4931	case 76:
4932		//	add $O, R, Rtmp or sub $O, R, Rtmp
4933		//	stp (R1, R2), (Rtmp)
4934		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
4935		if rf1 == REGTMP || rf2 == REGTMP {
4936			c.ctxt.Diag("cannot use REGTMP as source: %v", p)
4937		}
4938		if rt == obj.REG_NONE {
4939			rt = o.param
4940		}
4941		if rt == obj.REG_NONE {
4942			c.ctxt.Diag("invalid stp destination: %v", p)
4943		}
4944		v := c.regoff(&p.To)
4945		o1 = c.oaddi12(p, v, REGTMP, rt)
4946		o2 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
4947
4948	case 77:
4949		// If offset L fits in a 24 bit unsigned immediate:
4950		//	add $lo, R, Rtmp
4951		//	add $hi, Rtmp, Rtmp
4952		//	stp (R1, R2), (Rtmp)
4953		// Otherwise, use constant pool:
4954		//	mov $L, Rtmp (from constant pool)
4955		//	add Rtmp, R, Rtmp
4956		//	stp (R1, R2), (Rtmp)
4957		rt, rf1, rf2 := p.To.Reg, p.From.Reg, int16(p.From.Offset)
4958		if rt == REGTMP || rf1 == REGTMP || rf2 == REGTMP {
4959			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
4960		}
4961		if rt == obj.REG_NONE {
4962			rt = o.param
4963		}
4964		if rt == obj.REG_NONE {
4965			c.ctxt.Diag("invalid stp destination: %v", p)
4966		}
4967
4968		v := c.regoff(&p.To)
4969		if v >= -4095 && v <= 4095 {
4970			c.ctxt.Diag("%v: bad type for offset %d (should be add/sub+stp)", p, v)
4971		}
4972
4973		hi, lo, err := splitImm24uScaled(v, 0)
4974		if err != nil {
4975			goto storepairusepool
4976		}
4977		if p.Pool != nil {
4978			c.ctxt.Diag("%v: unused constant in pool (%v)\n", p, v)
4979		}
4980		o1 = c.oaddi(p, AADD, lo, REGTMP, int16(rt))
4981		o2 = c.oaddi(p, AADD, hi, REGTMP, REGTMP)
4982		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
4983		break
4984
4985	storepairusepool:
4986		if p.Pool == nil {
4987			c.ctxt.Diag("%v: constant is not in pool", p)
4988		}
4989		if rt == REGTMP || p.From.Reg == REGTMP {
4990			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
4991		}
4992		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
4993		o2 = c.opxrrr(p, AADD, REGTMP, rt, REGTMP, false)
4994		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
4995
4996	case 78: /* vmov R, V.<T>[index] */
4997		rf := int(p.From.Reg)
4998		rt := int(p.To.Reg)
4999		imm5 := 0
5000		o1 = 1<<30 | 7<<25 | 7<<10
5001		index := int(p.To.Index)
5002		switch (p.To.Reg >> 5) & 15 {
5003		case ARNG_B:
5004			c.checkindex(p, index, 15)
5005			imm5 |= 1
5006			imm5 |= index << 1
5007		case ARNG_H:
5008			c.checkindex(p, index, 7)
5009			imm5 |= 2
5010			imm5 |= index << 2
5011		case ARNG_S:
5012			c.checkindex(p, index, 3)
5013			imm5 |= 4
5014			imm5 |= index << 3
5015		case ARNG_D:
5016			c.checkindex(p, index, 1)
5017			imm5 |= 8
5018			imm5 |= index << 4
5019		default:
5020			c.ctxt.Diag("invalid arrangement: %v", p)
5021		}
5022		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
5023
5024	case 79: /* vdup Vn.<T>[index], Vd.<T> */
5025		rf := int(p.From.Reg)
5026		rt := int(p.To.Reg)
5027		o1 = 7<<25 | 1<<10
5028		var imm5, Q int
5029		index := int(p.From.Index)
5030		switch (p.To.Reg >> 5) & 15 {
5031		case ARNG_16B:
5032			c.checkindex(p, index, 15)
5033			Q = 1
5034			imm5 = 1
5035			imm5 |= index << 1
5036		case ARNG_2D:
5037			c.checkindex(p, index, 1)
5038			Q = 1
5039			imm5 = 8
5040			imm5 |= index << 4
5041		case ARNG_2S:
5042			c.checkindex(p, index, 3)
5043			Q = 0
5044			imm5 = 4
5045			imm5 |= index << 3
5046		case ARNG_4H:
5047			c.checkindex(p, index, 7)
5048			Q = 0
5049			imm5 = 2
5050			imm5 |= index << 2
5051		case ARNG_4S:
5052			c.checkindex(p, index, 3)
5053			Q = 1
5054			imm5 = 4
5055			imm5 |= index << 3
5056		case ARNG_8B:
5057			c.checkindex(p, index, 15)
5058			Q = 0
5059			imm5 = 1
5060			imm5 |= index << 1
5061		case ARNG_8H:
5062			c.checkindex(p, index, 7)
5063			Q = 1
5064			imm5 = 2
5065			imm5 |= index << 2
5066		default:
5067			c.ctxt.Diag("invalid arrangement: %v", p)
5068		}
5069		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
5070		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
5071
5072	case 80: /* vmov/vdup V.<T>[index], Vn */
5073		rf := int(p.From.Reg)
5074		rt := int(p.To.Reg)
5075		imm5 := 0
5076		index := int(p.From.Index)
5077		switch p.As {
5078		case AVMOV, AVDUP:
5079			o1 = 1<<30 | 15<<25 | 1<<10
5080			switch (p.From.Reg >> 5) & 15 {
5081			case ARNG_B:
5082				c.checkindex(p, index, 15)
5083				imm5 |= 1
5084				imm5 |= index << 1
5085			case ARNG_H:
5086				c.checkindex(p, index, 7)
5087				imm5 |= 2
5088				imm5 |= index << 2
5089			case ARNG_S:
5090				c.checkindex(p, index, 3)
5091				imm5 |= 4
5092				imm5 |= index << 3
5093			case ARNG_D:
5094				c.checkindex(p, index, 1)
5095				imm5 |= 8
5096				imm5 |= index << 4
5097			default:
5098				c.ctxt.Diag("invalid arrangement: %v", p)
5099			}
5100		default:
5101			c.ctxt.Diag("unsupported op %v", p.As)
5102		}
5103		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
5104
5105	case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
5106		c.checkoffset(p, p.As)
5107		r := int(p.From.Reg)
5108		o1 = c.oprrr(p, p.As)
5109		if o.scond == C_XPOST {
5110			o1 |= 1 << 23
5111			if p.From.Index == 0 {
5112				// immediate offset variant
5113				o1 |= 0x1f << 16
5114			} else {
5115				// register offset variant
5116				if isRegShiftOrExt(&p.From) {
5117					c.ctxt.Diag("invalid extended register op: %v\n", p)
5118				}
5119				o1 |= uint32(p.From.Index&0x1f) << 16
5120			}
5121		}
5122		o1 |= uint32(p.To.Offset)
5123		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
5124		// add opcode(bit 12-15) for vld1, mask it off if it's not vld1
5125		o1 = c.maskOpvldvst(p, o1)
5126		o1 |= uint32(r&31) << 5
5127
5128	case 82: /* vmov/vdup Rn, Vd.<T> */
5129		rf := int(p.From.Reg)
5130		rt := int(p.To.Reg)
5131		o1 = 7<<25 | 3<<10
5132		var imm5, Q uint32
5133		switch (p.To.Reg >> 5) & 15 {
5134		case ARNG_16B:
5135			Q = 1
5136			imm5 = 1
5137		case ARNG_2D:
5138			Q = 1
5139			imm5 = 8
5140		case ARNG_2S:
5141			Q = 0
5142			imm5 = 4
5143		case ARNG_4H:
5144			Q = 0
5145			imm5 = 2
5146		case ARNG_4S:
5147			Q = 1
5148			imm5 = 4
5149		case ARNG_8B:
5150			Q = 0
5151			imm5 = 1
5152		case ARNG_8H:
5153			Q = 1
5154			imm5 = 2
5155		default:
5156			c.ctxt.Diag("invalid arrangement: %v\n", p)
5157		}
5158		o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
5159		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
5160
5161	case 83: /* vmov Vn.<T>, Vd.<T> */
5162		af := int((p.From.Reg >> 5) & 15)
5163		at := int((p.To.Reg >> 5) & 15)
5164		if af != at {
5165			c.ctxt.Diag("invalid arrangement: %v\n", p)
5166		}
5167		o1 = c.oprrr(p, p.As)
5168		rf := int((p.From.Reg) & 31)
5169		rt := int((p.To.Reg) & 31)
5170
5171		var Q, size uint32
5172		switch af {
5173		case ARNG_8B:
5174			Q = 0
5175			size = 0
5176		case ARNG_16B:
5177			Q = 1
5178			size = 0
5179		case ARNG_4H:
5180			Q = 0
5181			size = 1
5182		case ARNG_8H:
5183			Q = 1
5184			size = 1
5185		case ARNG_2S:
5186			Q = 0
5187			size = 2
5188		case ARNG_4S:
5189			Q = 1
5190			size = 2
5191		default:
5192			c.ctxt.Diag("invalid arrangement: %v\n", p)
5193		}
5194
5195		if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
5196			c.ctxt.Diag("invalid arrangement: %v", p)
5197		}
5198
5199		if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
5200			c.ctxt.Diag("invalid arrangement: %v", p)
5201		}
5202
5203		if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
5204			c.ctxt.Diag("invalid arrangement: %v", p)
5205		}
5206
5207		if p.As == AVMOV {
5208			o1 |= uint32(rf&31) << 16
5209		}
5210
5211		if p.As == AVRBIT {
5212			size = 1
5213		}
5214
5215		o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
5216
5217	case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
5218		c.checkoffset(p, p.As)
5219		r := int(p.To.Reg)
5220		o1 = 3 << 26
5221		if o.scond == C_XPOST {
5222			o1 |= 1 << 23
5223			if p.To.Index == 0 {
5224				// immediate offset variant
5225				o1 |= 0x1f << 16
5226			} else {
5227				// register offset variant
5228				if isRegShiftOrExt(&p.To) {
5229					c.ctxt.Diag("invalid extended register: %v\n", p)
5230				}
5231				o1 |= uint32(p.To.Index&31) << 16
5232			}
5233		}
5234		o1 |= uint32(p.From.Offset)
5235		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
5236		// add opcode(bit 12-15) for vst1, mask it off if it's not vst1
5237		o1 = c.maskOpvldvst(p, o1)
5238		o1 |= uint32(r&31) << 5
5239
5240	case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
5241		af := int((p.From.Reg >> 5) & 15)
5242		o1 = c.oprrr(p, p.As)
5243		rf := int((p.From.Reg) & 31)
5244		rt := int((p.To.Reg) & 31)
5245		Q := 0
5246		size := 0
5247		switch af {
5248		case ARNG_8B:
5249			Q = 0
5250			size = 0
5251		case ARNG_16B:
5252			Q = 1
5253			size = 0
5254		case ARNG_4H:
5255			Q = 0
5256			size = 1
5257		case ARNG_8H:
5258			Q = 1
5259			size = 1
5260		case ARNG_4S:
5261			Q = 1
5262			size = 2
5263		default:
5264			c.ctxt.Diag("invalid arrangement: %v\n", p)
5265		}
5266		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
5267
5268	case 86: /* vmovi $imm8, Vd.<T>*/
5269		at := int((p.To.Reg >> 5) & 15)
5270		r := int(p.From.Offset)
5271		if r > 255 || r < 0 {
5272			c.ctxt.Diag("immediate constant out of range: %v\n", p)
5273		}
5274		rt := int((p.To.Reg) & 31)
5275		Q := 0
5276		switch at {
5277		case ARNG_8B:
5278			Q = 0
5279		case ARNG_16B:
5280			Q = 1
5281		default:
5282			c.ctxt.Diag("invalid arrangement: %v\n", p)
5283		}
5284		o1 = 0xf<<24 | 0xe<<12 | 1<<10
5285		o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
5286
5287	case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
5288		rf1, rf2 := p.From.Reg, int16(p.From.Offset)
5289		if rf1 == REGTMP || rf2 == REGTMP {
5290			c.ctxt.Diag("cannot use REGTMP as source: %v", p)
5291		}
5292		o1 = ADR(1, 0, REGTMP)
5293		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
5294		rel := obj.Addrel(c.cursym)
5295		rel.Off = int32(c.pc)
5296		rel.Siz = 8
5297		rel.Sym = p.To.Sym
5298		rel.Add = p.To.Offset
5299		rel.Type = objabi.R_ADDRARM64
5300		o3 = c.opldpstp(p, o, 0, REGTMP, rf1, rf2, 0)
5301
5302	case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
5303		rt1, rt2 := p.To.Reg, int16(p.To.Offset)
5304		o1 = ADR(1, 0, REGTMP)
5305		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
5306		rel := obj.Addrel(c.cursym)
5307		rel.Off = int32(c.pc)
5308		rel.Siz = 8
5309		rel.Sym = p.From.Sym
5310		rel.Add = p.From.Offset
5311		rel.Type = objabi.R_ADDRARM64
5312		o3 = c.opldpstp(p, o, 0, REGTMP, rt1, rt2, 1)
5313
5314	case 89: /* vadd/vsub Vm, Vn, Vd */
5315		switch p.As {
5316		case AVADD:
5317			o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5318
5319		case AVSUB:
5320			o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5321
5322		default:
5323			c.ctxt.Diag("bad opcode: %v\n", p)
5324			break
5325		}
5326
5327		rf := int(p.From.Reg)
5328		rt := int(p.To.Reg)
5329		r := int(p.Reg)
5330		if r == obj.REG_NONE {
5331			r = rt
5332		}
5333		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5334
5335	// This is supposed to be something that stops execution.
5336	// It's not supposed to be reached, ever, but if it is, we'd
5337	// like to be able to tell how we got there. Assemble as
5338	// 0xbea71700 which is guaranteed to raise undefined instruction
5339	// exception.
5340	case 90:
5341		o1 = 0xbea71700
5342
5343	case 91: /* prfm imm(Rn), <prfop | $imm5> */
5344		imm := uint32(p.From.Offset)
5345		r := p.From.Reg
5346		var v uint32
5347		var ok bool
5348		if p.To.Type == obj.TYPE_CONST {
5349			v = uint32(p.To.Offset)
5350			ok = v <= 31
5351		} else {
5352			v, ok = prfopfield[SpecialOperand(p.To.Offset)]
5353		}
5354		if !ok {
5355			c.ctxt.Diag("illegal prefetch operation:\n%v", p)
5356		}
5357
5358		o1 = c.opirr(p, p.As)
5359		o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
5360
5361	case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
5362		rf := int(p.From.Reg)
5363		rt := int(p.To.Reg)
5364		imm4 := 0
5365		imm5 := 0
5366		o1 = 3<<29 | 7<<25 | 1<<10
5367		index1 := int(p.To.Index)
5368		index2 := int(p.From.Index)
5369		if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
5370			c.ctxt.Diag("operand mismatch: %v", p)
5371		}
5372		switch (p.To.Reg >> 5) & 15 {
5373		case ARNG_B:
5374			c.checkindex(p, index1, 15)
5375			c.checkindex(p, index2, 15)
5376			imm5 |= 1
5377			imm5 |= index1 << 1
5378			imm4 |= index2
5379		case ARNG_H:
5380			c.checkindex(p, index1, 7)
5381			c.checkindex(p, index2, 7)
5382			imm5 |= 2
5383			imm5 |= index1 << 2
5384			imm4 |= index2 << 1
5385		case ARNG_S:
5386			c.checkindex(p, index1, 3)
5387			c.checkindex(p, index2, 3)
5388			imm5 |= 4
5389			imm5 |= index1 << 3
5390			imm4 |= index2 << 2
5391		case ARNG_D:
5392			c.checkindex(p, index1, 1)
5393			c.checkindex(p, index2, 1)
5394			imm5 |= 8
5395			imm5 |= index1 << 4
5396			imm4 |= index2 << 3
5397		default:
5398			c.ctxt.Diag("invalid arrangement: %v", p)
5399		}
5400		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5401
5402	case 93: /* vpmull{2} Vm.<Tb>, Vn.<Tb>, Vd.<Ta> */
5403		af := uint8((p.From.Reg >> 5) & 15)
5404		at := uint8((p.To.Reg >> 5) & 15)
5405		a := uint8((p.Reg >> 5) & 15)
5406		if af != a {
5407			c.ctxt.Diag("invalid arrangement: %v", p)
5408		}
5409
5410		var Q, size uint32
5411		if p.As == AVPMULL2 {
5412			Q = 1
5413		}
5414		switch pack(Q, at, af) {
5415		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5416			size = 0
5417		case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D):
5418			size = 3
5419		default:
5420			c.ctxt.Diag("operand mismatch: %v\n", p)
5421		}
5422
5423		o1 = c.oprrr(p, p.As)
5424		rf := int((p.From.Reg) & 31)
5425		rt := int((p.To.Reg) & 31)
5426		r := int((p.Reg) & 31)
5427		o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5428
5429	case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
5430		af := int(((p.GetFrom3().Reg) >> 5) & 15)
5431		at := int((p.To.Reg >> 5) & 15)
5432		a := int((p.Reg >> 5) & 15)
5433		index := int(p.From.Offset)
5434
5435		if af != a || af != at {
5436			c.ctxt.Diag("invalid arrangement: %v", p)
5437			break
5438		}
5439
5440		var Q uint32
5441		var b int
5442		if af == ARNG_8B {
5443			Q = 0
5444			b = 7
5445		} else if af == ARNG_16B {
5446			Q = 1
5447			b = 15
5448		} else {
5449			c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
5450			break
5451		}
5452
5453		if index < 0 || index > b {
5454			c.ctxt.Diag("illegal offset: %v", p)
5455		}
5456
5457		o1 = c.opirr(p, p.As)
5458		rf := int((p.GetFrom3().Reg) & 31)
5459		rt := int((p.To.Reg) & 31)
5460		r := int((p.Reg) & 31)
5461
5462		o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5463
5464	case 95: /* vushr/vshl/vsri/vsli/vusra $shift, Vn.<T>, Vd.<T> */
5465		at := int((p.To.Reg >> 5) & 15)
5466		af := int((p.Reg >> 5) & 15)
5467		shift := int(p.From.Offset)
5468
5469		if af != at {
5470			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5471		}
5472
5473		var Q uint32
5474		var imax, esize int
5475
5476		switch af {
5477		case ARNG_8B, ARNG_4H, ARNG_2S:
5478			Q = 0
5479		case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
5480			Q = 1
5481		default:
5482			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5483		}
5484
5485		switch af {
5486		case ARNG_8B, ARNG_16B:
5487			imax = 15
5488			esize = 8
5489		case ARNG_4H, ARNG_8H:
5490			imax = 31
5491			esize = 16
5492		case ARNG_2S, ARNG_4S:
5493			imax = 63
5494			esize = 32
5495		case ARNG_2D:
5496			imax = 127
5497			esize = 64
5498		}
5499
5500		imm := 0
5501		switch p.As {
5502		case AVUSHR, AVSRI, AVUSRA:
5503			imm = esize*2 - shift
5504			if imm < esize || imm > imax {
5505				c.ctxt.Diag("shift out of range: %v", p)
5506			}
5507		case AVSHL, AVSLI:
5508			imm = esize + shift
5509			if imm > imax {
5510				c.ctxt.Diag("shift out of range: %v", p)
5511			}
5512		default:
5513			c.ctxt.Diag("invalid instruction %v\n", p)
5514		}
5515
5516		o1 = c.opirr(p, p.As)
5517		rt := int((p.To.Reg) & 31)
5518		rf := int((p.Reg) & 31)
5519
5520		o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
5521
5522	case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
5523		af := int((p.From.Reg >> 5) & 15)
5524		rt := int((p.From.Reg) & 31)
5525		rf := int((p.To.Reg) & 31)
5526		r := int(p.To.Index & 31)
5527		index := int(p.From.Index)
5528		offset := c.regoff(&p.To)
5529
5530		if o.scond == C_XPOST {
5531			if (p.To.Index != 0) && (offset != 0) {
5532				c.ctxt.Diag("invalid offset: %v", p)
5533			}
5534			if p.To.Index == 0 && offset == 0 {
5535				c.ctxt.Diag("invalid offset: %v", p)
5536			}
5537		}
5538
5539		if offset != 0 {
5540			r = 31
5541		}
5542
5543		var Q, S, size int
5544		var opcode uint32
5545		switch af {
5546		case ARNG_B:
5547			c.checkindex(p, index, 15)
5548			if o.scond == C_XPOST && offset != 0 && offset != 1 {
5549				c.ctxt.Diag("invalid offset: %v", p)
5550			}
5551			Q = index >> 3
5552			S = (index >> 2) & 1
5553			size = index & 3
5554			opcode = 0
5555		case ARNG_H:
5556			c.checkindex(p, index, 7)
5557			if o.scond == C_XPOST && offset != 0 && offset != 2 {
5558				c.ctxt.Diag("invalid offset: %v", p)
5559			}
5560			Q = index >> 2
5561			S = (index >> 1) & 1
5562			size = (index & 1) << 1
5563			opcode = 2
5564		case ARNG_S:
5565			c.checkindex(p, index, 3)
5566			if o.scond == C_XPOST && offset != 0 && offset != 4 {
5567				c.ctxt.Diag("invalid offset: %v", p)
5568			}
5569			Q = index >> 1
5570			S = index & 1
5571			size = 0
5572			opcode = 4
5573		case ARNG_D:
5574			c.checkindex(p, index, 1)
5575			if o.scond == C_XPOST && offset != 0 && offset != 8 {
5576				c.ctxt.Diag("invalid offset: %v", p)
5577			}
5578			Q = index
5579			S = 0
5580			size = 1
5581			opcode = 4
5582		default:
5583			c.ctxt.Diag("invalid arrangement: %v", p)
5584		}
5585
5586		if o.scond == C_XPOST {
5587			o1 |= 27 << 23
5588		} else {
5589			o1 |= 26 << 23
5590		}
5591
5592		o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
5593
5594	case 97: /* vld1 offset(Rn), vt.<T>[index] */
5595		at := int((p.To.Reg >> 5) & 15)
5596		rt := int((p.To.Reg) & 31)
5597		rf := int((p.From.Reg) & 31)
5598		r := int(p.From.Index & 31)
5599		index := int(p.To.Index)
5600		offset := c.regoff(&p.From)
5601
5602		if o.scond == C_XPOST {
5603			if (p.From.Index != 0) && (offset != 0) {
5604				c.ctxt.Diag("invalid offset: %v", p)
5605			}
5606			if p.From.Index == 0 && offset == 0 {
5607				c.ctxt.Diag("invalid offset: %v", p)
5608			}
5609		}
5610
5611		if offset != 0 {
5612			r = 31
5613		}
5614
5615		Q := 0
5616		S := 0
5617		size := 0
5618		var opcode uint32
5619		switch at {
5620		case ARNG_B:
5621			c.checkindex(p, index, 15)
5622			if o.scond == C_XPOST && offset != 0 && offset != 1 {
5623				c.ctxt.Diag("invalid offset: %v", p)
5624			}
5625			Q = index >> 3
5626			S = (index >> 2) & 1
5627			size = index & 3
5628			opcode = 0
5629		case ARNG_H:
5630			c.checkindex(p, index, 7)
5631			if o.scond == C_XPOST && offset != 0 && offset != 2 {
5632				c.ctxt.Diag("invalid offset: %v", p)
5633			}
5634			Q = index >> 2
5635			S = (index >> 1) & 1
5636			size = (index & 1) << 1
5637			opcode = 2
5638		case ARNG_S:
5639			c.checkindex(p, index, 3)
5640			if o.scond == C_XPOST && offset != 0 && offset != 4 {
5641				c.ctxt.Diag("invalid offset: %v", p)
5642			}
5643			Q = index >> 1
5644			S = index & 1
5645			size = 0
5646			opcode = 4
5647		case ARNG_D:
5648			c.checkindex(p, index, 1)
5649			if o.scond == C_XPOST && offset != 0 && offset != 8 {
5650				c.ctxt.Diag("invalid offset: %v", p)
5651			}
5652			Q = index
5653			S = 0
5654			size = 1
5655			opcode = 4
5656		default:
5657			c.ctxt.Diag("invalid arrangement: %v", p)
5658		}
5659
5660		if o.scond == C_XPOST {
5661			o1 |= 110 << 21
5662		} else {
5663			o1 |= 106 << 21
5664		}
5665
5666		o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
5667
5668	case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
5669		if isRegShiftOrExt(&p.From) {
5670			// extended or shifted offset register.
5671			c.checkShiftAmount(p, &p.From)
5672
5673			o1 = c.opldrr(p, p.As, true)
5674			o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
5675		} else {
5676			// (Rn)(Rm), no extension or shift.
5677			o1 = c.opldrr(p, p.As, false)
5678			o1 |= uint32(p.From.Index&31) << 16
5679		}
5680		o1 |= uint32(p.From.Reg&31) << 5
5681		rt := int(p.To.Reg)
5682		o1 |= uint32(rt & 31)
5683
5684	case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
5685		if isRegShiftOrExt(&p.To) {
5686			// extended or shifted offset register.
5687			c.checkShiftAmount(p, &p.To)
5688
5689			o1 = c.opstrr(p, p.As, true)
5690			o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
5691		} else {
5692			// (Rn)(Rm), no extension or shift.
5693			o1 = c.opstrr(p, p.As, false)
5694			o1 |= uint32(p.To.Index&31) << 16
5695		}
5696		o1 |= uint32(p.To.Reg&31) << 5
5697		rf := int(p.From.Reg)
5698		o1 |= uint32(rf & 31)
5699
5700	case 100: /* VTBL/VTBX Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
5701		af := int((p.From.Reg >> 5) & 15)
5702		at := int((p.To.Reg >> 5) & 15)
5703		if af != at {
5704			c.ctxt.Diag("invalid arrangement: %v\n", p)
5705		}
5706		var q, len uint32
5707		switch af {
5708		case ARNG_8B:
5709			q = 0
5710		case ARNG_16B:
5711			q = 1
5712		default:
5713			c.ctxt.Diag("invalid arrangement: %v", p)
5714		}
5715		rf := int(p.From.Reg)
5716		rt := int(p.To.Reg)
5717		offset := int(p.GetFrom3().Offset)
5718		opcode := (offset >> 12) & 15
5719		switch opcode {
5720		case 0x7:
5721			len = 0 // one register
5722		case 0xa:
5723			len = 1 // two register
5724		case 0x6:
5725			len = 2 // three registers
5726		case 0x2:
5727			len = 3 // four registers
5728		default:
5729			c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
5730		}
5731		var op uint32
5732		switch p.As {
5733		case AVTBL:
5734			op = 0
5735		case AVTBX:
5736			op = 1
5737		}
5738		o1 = q<<30 | 0xe<<24 | len<<13 | op<<12
5739		o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
5740
5741	case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
5742		o1 = c.opirr(p, p.As)
5743		rf := p.Reg
5744		af := uint8((p.Reg >> 5) & 15)
5745		at := uint8((p.To.Reg >> 5) & 15)
5746		shift := int(p.From.Offset)
5747		if p.As == AVUXTL || p.As == AVUXTL2 {
5748			rf = p.From.Reg
5749			af = uint8((p.From.Reg >> 5) & 15)
5750			shift = 0
5751		}
5752
5753		Q := (o1 >> 30) & 1
5754		var immh, width uint8
5755		switch pack(Q, af, at) {
5756		case pack(0, ARNG_8B, ARNG_8H):
5757			immh, width = 1, 8
5758		case pack(1, ARNG_16B, ARNG_8H):
5759			immh, width = 1, 8
5760		case pack(0, ARNG_4H, ARNG_4S):
5761			immh, width = 2, 16
5762		case pack(1, ARNG_8H, ARNG_4S):
5763			immh, width = 2, 16
5764		case pack(0, ARNG_2S, ARNG_2D):
5765			immh, width = 4, 32
5766		case pack(1, ARNG_4S, ARNG_2D):
5767			immh, width = 4, 32
5768		default:
5769			c.ctxt.Diag("operand mismatch: %v\n", p)
5770		}
5771		if !(0 <= shift && shift <= int(width-1)) {
5772			c.ctxt.Diag("shift amount out of range: %v\n", p)
5773		}
5774		o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
5775
5776	case 103: /* VEOR3/VBCAX Va.B16, Vm.B16, Vn.B16, Vd.B16 */
5777		ta := (p.From.Reg >> 5) & 15
5778		tm := (p.Reg >> 5) & 15
5779		td := (p.To.Reg >> 5) & 15
5780		tn := ((p.GetFrom3().Reg) >> 5) & 15
5781
5782		if ta != tm || ta != tn || ta != td || ta != ARNG_16B {
5783			c.ctxt.Diag("invalid arrangement: %v", p)
5784			break
5785		}
5786
5787		o1 = c.oprrr(p, p.As)
5788		ra := int(p.From.Reg)
5789		rm := int(p.Reg)
5790		rn := int(p.GetFrom3().Reg)
5791		rd := int(p.To.Reg)
5792		o1 |= uint32(rm&31)<<16 | uint32(ra&31)<<10 | uint32(rn&31)<<5 | uint32(rd)&31
5793
5794	case 104: /* vxar $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
5795		af := ((p.GetFrom3().Reg) >> 5) & 15
5796		at := (p.To.Reg >> 5) & 15
5797		a := (p.Reg >> 5) & 15
5798		index := int(p.From.Offset)
5799
5800		if af != a || af != at {
5801			c.ctxt.Diag("invalid arrangement: %v", p)
5802			break
5803		}
5804
5805		if af != ARNG_2D {
5806			c.ctxt.Diag("invalid arrangement, should be D2: %v", p)
5807			break
5808		}
5809
5810		if index < 0 || index > 63 {
5811			c.ctxt.Diag("illegal offset: %v", p)
5812		}
5813
5814		o1 = c.opirr(p, p.As)
5815		rf := (p.GetFrom3().Reg) & 31
5816		rt := (p.To.Reg) & 31
5817		r := (p.Reg) & 31
5818
5819		o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
5820
5821	case 105: /* vuaddw{2} Vm.<Tb>, Vn.<Ta>, Vd.<Ta> */
5822		af := uint8((p.From.Reg >> 5) & 15)
5823		at := uint8((p.To.Reg >> 5) & 15)
5824		a := uint8((p.Reg >> 5) & 15)
5825		if at != a {
5826			c.ctxt.Diag("invalid arrangement: %v", p)
5827			break
5828		}
5829
5830		var Q, size uint32
5831		if p.As == AVUADDW2 {
5832			Q = 1
5833		}
5834		switch pack(Q, at, af) {
5835		case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5836			size = 0
5837		case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H):
5838			size = 1
5839		case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S):
5840			size = 2
5841		default:
5842			c.ctxt.Diag("operand mismatch: %v\n", p)
5843		}
5844
5845		o1 = c.oprrr(p, p.As)
5846		rf := int((p.From.Reg) & 31)
5847		rt := int((p.To.Reg) & 31)
5848		r := int((p.Reg) & 31)
5849		o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5850
5851	case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1)
5852		rs := p.From.Reg
5853		rt := p.GetTo2().Reg
5854		rb := p.To.Reg
5855		rs1 := int16(p.From.Offset)
5856		rt1 := int16(p.GetTo2().Offset)
5857
5858		enc, ok := atomicCASP[p.As]
5859		if !ok {
5860			c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p)
5861		}
5862		// for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1
5863		switch {
5864		case rs&1 != 0:
5865			c.ctxt.Diag("source register pair must start from even register: %v\n", p)
5866			break
5867		case rt&1 != 0:
5868			c.ctxt.Diag("destination register pair must start from even register: %v\n", p)
5869			break
5870		case rs != rs1-1:
5871			c.ctxt.Diag("source register pair must be contiguous: %v\n", p)
5872			break
5873		case rt != rt1-1:
5874			c.ctxt.Diag("destination register pair must be contiguous: %v\n", p)
5875			break
5876		}
5877		// rt can't be sp.
5878		if rt == REG_RSP {
5879			c.ctxt.Diag("illegal destination register: %v\n", p)
5880		}
5881		o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
5882
5883	case 107: /* tlbi, dc */
5884		op, ok := sysInstFields[SpecialOperand(p.From.Offset)]
5885		if !ok || (p.As == ATLBI && op.cn != 8) || (p.As == ADC && op.cn != 7) {
5886			c.ctxt.Diag("illegal argument: %v\n", p)
5887			break
5888		}
5889		o1 = c.opirr(p, p.As)
5890		if op.hasOperand2 {
5891			if p.To.Reg == obj.REG_NONE {
5892				c.ctxt.Diag("missing register at operand 2: %v\n", p)
5893			}
5894			o1 |= uint32(p.To.Reg & 0x1F)
5895		} else {
5896			if p.To.Reg != obj.REG_NONE || p.Reg != obj.REG_NONE {
5897				c.ctxt.Diag("extraneous register at operand 2: %v\n", p)
5898			}
5899			o1 |= uint32(0x1F)
5900		}
5901		o1 |= uint32(SYSARG4(int(op.op1), int(op.cn), int(op.cm), int(op.op2)))
5902	}
5903	out[0] = o1
5904	out[1] = o2
5905	out[2] = o3
5906	out[3] = o4
5907	out[4] = o5
5908}
5909
5910func (c *ctxt7) addrRelocType(p *obj.Prog) objabi.RelocType {
5911	switch movesize(p.As) {
5912	case 0:
5913		return objabi.R_ARM64_PCREL_LDST8
5914	case 1:
5915		return objabi.R_ARM64_PCREL_LDST16
5916	case 2:
5917		return objabi.R_ARM64_PCREL_LDST32
5918	case 3:
5919		return objabi.R_ARM64_PCREL_LDST64
5920	default:
5921		c.ctxt.Diag("use R_ADDRARM64 relocation type for: %v\n", p)
5922	}
5923	return -1
5924}
5925
5926/*
5927 * basic Rm op Rn -> Rd (using shifted register with 0)
5928 * also op Rn -> Rt
5929 * also Rm*Rn op Ra -> Rd
5930 * also Vm op Vn -> Vd
5931 */
5932func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
5933	switch a {
5934	case AADC:
5935		return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5936
5937	case AADCW:
5938		return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5939
5940	case AADCS:
5941		return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5942
5943	case AADCSW:
5944		return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5945
5946	case ANGC, ASBC:
5947		return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5948
5949	case ANGCS, ASBCS:
5950		return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5951
5952	case ANGCW, ASBCW:
5953		return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5954
5955	case ANGCSW, ASBCSW:
5956		return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5957
5958	case AADD:
5959		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5960
5961	case AADDW:
5962		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5963
5964	case ACMN, AADDS:
5965		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5966
5967	case ACMNW, AADDSW:
5968		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5969
5970	case ASUB:
5971		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5972
5973	case ASUBW:
5974		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5975
5976	case ACMP, ASUBS:
5977		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5978
5979	case ACMPW, ASUBSW:
5980		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5981
5982	case AAND:
5983		return S64 | 0<<29 | 0xA<<24
5984
5985	case AANDW:
5986		return S32 | 0<<29 | 0xA<<24
5987
5988	case AMOVD, AORR:
5989		return S64 | 1<<29 | 0xA<<24
5990
5991		//	case AMOVW:
5992	case AMOVWU, AORRW:
5993		return S32 | 1<<29 | 0xA<<24
5994
5995	case AEOR:
5996		return S64 | 2<<29 | 0xA<<24
5997
5998	case AEORW:
5999		return S32 | 2<<29 | 0xA<<24
6000
6001	case AANDS, ATST:
6002		return S64 | 3<<29 | 0xA<<24
6003
6004	case AANDSW, ATSTW:
6005		return S32 | 3<<29 | 0xA<<24
6006
6007	case ABIC:
6008		return S64 | 0<<29 | 0xA<<24 | 1<<21
6009
6010	case ABICW:
6011		return S32 | 0<<29 | 0xA<<24 | 1<<21
6012
6013	case ABICS:
6014		return S64 | 3<<29 | 0xA<<24 | 1<<21
6015
6016	case ABICSW:
6017		return S32 | 3<<29 | 0xA<<24 | 1<<21
6018
6019	case AEON:
6020		return S64 | 2<<29 | 0xA<<24 | 1<<21
6021
6022	case AEONW:
6023		return S32 | 2<<29 | 0xA<<24 | 1<<21
6024
6025	case AMVN, AORN:
6026		return S64 | 1<<29 | 0xA<<24 | 1<<21
6027
6028	case AMVNW, AORNW:
6029		return S32 | 1<<29 | 0xA<<24 | 1<<21
6030
6031	case AASR:
6032		return S64 | OPDP2(10) /* also ASRV */
6033
6034	case AASRW:
6035		return S32 | OPDP2(10)
6036
6037	case ALSL:
6038		return S64 | OPDP2(8)
6039
6040	case ALSLW:
6041		return S32 | OPDP2(8)
6042
6043	case ALSR:
6044		return S64 | OPDP2(9)
6045
6046	case ALSRW:
6047		return S32 | OPDP2(9)
6048
6049	case AROR:
6050		return S64 | OPDP2(11)
6051
6052	case ARORW:
6053		return S32 | OPDP2(11)
6054
6055	case ACCMN:
6056		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
6057
6058	case ACCMNW:
6059		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
6060
6061	case ACCMP:
6062		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6063
6064	case ACCMPW:
6065		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
6066
6067	case ACRC32B:
6068		return S32 | OPDP2(16)
6069
6070	case ACRC32H:
6071		return S32 | OPDP2(17)
6072
6073	case ACRC32W:
6074		return S32 | OPDP2(18)
6075
6076	case ACRC32X:
6077		return S64 | OPDP2(19)
6078
6079	case ACRC32CB:
6080		return S32 | OPDP2(20)
6081
6082	case ACRC32CH:
6083		return S32 | OPDP2(21)
6084
6085	case ACRC32CW:
6086		return S32 | OPDP2(22)
6087
6088	case ACRC32CX:
6089		return S64 | OPDP2(23)
6090
6091	case ACSEL:
6092		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6093
6094	case ACSELW:
6095		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6096
6097	case ACSET:
6098		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6099
6100	case ACSETW:
6101		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6102
6103	case ACSETM:
6104		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6105
6106	case ACSETMW:
6107		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6108
6109	case ACINC, ACSINC:
6110		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6111
6112	case ACINCW, ACSINCW:
6113		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6114
6115	case ACINV, ACSINV:
6116		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6117
6118	case ACINVW, ACSINVW:
6119		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
6120
6121	case ACNEG, ACSNEG:
6122		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6123
6124	case ACNEGW, ACSNEGW:
6125		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
6126
6127	case AMUL, AMADD:
6128		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
6129
6130	case AMULW, AMADDW:
6131		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
6132
6133	case AMNEG, AMSUB:
6134		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
6135
6136	case AMNEGW, AMSUBW:
6137		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
6138
6139	case AMRS:
6140		return SYSOP(1, 2, 0, 0, 0, 0, 0)
6141
6142	case AMSR:
6143		return SYSOP(0, 2, 0, 0, 0, 0, 0)
6144
6145	case ANEG:
6146		return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
6147
6148	case ANEGW:
6149		return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
6150
6151	case ANEGS:
6152		return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
6153
6154	case ANEGSW:
6155		return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
6156
6157	case AREM, ASDIV:
6158		return S64 | OPDP2(3)
6159
6160	case AREMW, ASDIVW:
6161		return S32 | OPDP2(3)
6162
6163	case ASMULL, ASMADDL:
6164		return OPDP3(1, 0, 1, 0)
6165
6166	case ASMNEGL, ASMSUBL:
6167		return OPDP3(1, 0, 1, 1)
6168
6169	case ASMULH:
6170		return OPDP3(1, 0, 2, 0)
6171
6172	case AUMULL, AUMADDL:
6173		return OPDP3(1, 0, 5, 0)
6174
6175	case AUMNEGL, AUMSUBL:
6176		return OPDP3(1, 0, 5, 1)
6177
6178	case AUMULH:
6179		return OPDP3(1, 0, 6, 0)
6180
6181	case AUREM, AUDIV:
6182		return S64 | OPDP2(2)
6183
6184	case AUREMW, AUDIVW:
6185		return S32 | OPDP2(2)
6186
6187	case AAESE:
6188		return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
6189
6190	case AAESD:
6191		return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
6192
6193	case AAESMC:
6194		return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
6195
6196	case AAESIMC:
6197		return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
6198
6199	case ASHA1C:
6200		return 0x5E<<24 | 0<<12
6201
6202	case ASHA1P:
6203		return 0x5E<<24 | 1<<12
6204
6205	case ASHA1M:
6206		return 0x5E<<24 | 2<<12
6207
6208	case ASHA1SU0:
6209		return 0x5E<<24 | 3<<12
6210
6211	case ASHA256H:
6212		return 0x5E<<24 | 4<<12
6213
6214	case ASHA256H2:
6215		return 0x5E<<24 | 5<<12
6216
6217	case ASHA256SU1:
6218		return 0x5E<<24 | 6<<12
6219
6220	case ASHA1H:
6221		return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
6222
6223	case ASHA1SU1:
6224		return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
6225
6226	case ASHA256SU0:
6227		return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
6228
6229	case ASHA512H:
6230		return 0xCE<<24 | 3<<21 | 8<<12
6231
6232	case ASHA512H2:
6233		return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
6234
6235	case ASHA512SU1:
6236		return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
6237
6238	case ASHA512SU0:
6239		return 0xCE<<24 | 3<<22 | 8<<12
6240
6241	case AFCVTZSD:
6242		return FPCVTI(1, 0, 1, 3, 0)
6243
6244	case AFCVTZSDW:
6245		return FPCVTI(0, 0, 1, 3, 0)
6246
6247	case AFCVTZSS:
6248		return FPCVTI(1, 0, 0, 3, 0)
6249
6250	case AFCVTZSSW:
6251		return FPCVTI(0, 0, 0, 3, 0)
6252
6253	case AFCVTZUD:
6254		return FPCVTI(1, 0, 1, 3, 1)
6255
6256	case AFCVTZUDW:
6257		return FPCVTI(0, 0, 1, 3, 1)
6258
6259	case AFCVTZUS:
6260		return FPCVTI(1, 0, 0, 3, 1)
6261
6262	case AFCVTZUSW:
6263		return FPCVTI(0, 0, 0, 3, 1)
6264
6265	case ASCVTFD:
6266		return FPCVTI(1, 0, 1, 0, 2)
6267
6268	case ASCVTFS:
6269		return FPCVTI(1, 0, 0, 0, 2)
6270
6271	case ASCVTFWD:
6272		return FPCVTI(0, 0, 1, 0, 2)
6273
6274	case ASCVTFWS:
6275		return FPCVTI(0, 0, 0, 0, 2)
6276
6277	case AUCVTFD:
6278		return FPCVTI(1, 0, 1, 0, 3)
6279
6280	case AUCVTFS:
6281		return FPCVTI(1, 0, 0, 0, 3)
6282
6283	case AUCVTFWD:
6284		return FPCVTI(0, 0, 1, 0, 3)
6285
6286	case AUCVTFWS:
6287		return FPCVTI(0, 0, 0, 0, 3)
6288
6289	case AFADDS:
6290		return FPOP2S(0, 0, 0, 2)
6291
6292	case AFADDD:
6293		return FPOP2S(0, 0, 1, 2)
6294
6295	case AFSUBS:
6296		return FPOP2S(0, 0, 0, 3)
6297
6298	case AFSUBD:
6299		return FPOP2S(0, 0, 1, 3)
6300
6301	case AFMADDD:
6302		return FPOP3S(0, 0, 1, 0, 0)
6303
6304	case AFMADDS:
6305		return FPOP3S(0, 0, 0, 0, 0)
6306
6307	case AFMSUBD:
6308		return FPOP3S(0, 0, 1, 0, 1)
6309
6310	case AFMSUBS:
6311		return FPOP3S(0, 0, 0, 0, 1)
6312
6313	case AFNMADDD:
6314		return FPOP3S(0, 0, 1, 1, 0)
6315
6316	case AFNMADDS:
6317		return FPOP3S(0, 0, 0, 1, 0)
6318
6319	case AFNMSUBD:
6320		return FPOP3S(0, 0, 1, 1, 1)
6321
6322	case AFNMSUBS:
6323		return FPOP3S(0, 0, 0, 1, 1)
6324
6325	case AFMULS:
6326		return FPOP2S(0, 0, 0, 0)
6327
6328	case AFMULD:
6329		return FPOP2S(0, 0, 1, 0)
6330
6331	case AFDIVS:
6332		return FPOP2S(0, 0, 0, 1)
6333
6334	case AFDIVD:
6335		return FPOP2S(0, 0, 1, 1)
6336
6337	case AFMAXS:
6338		return FPOP2S(0, 0, 0, 4)
6339
6340	case AFMINS:
6341		return FPOP2S(0, 0, 0, 5)
6342
6343	case AFMAXD:
6344		return FPOP2S(0, 0, 1, 4)
6345
6346	case AFMIND:
6347		return FPOP2S(0, 0, 1, 5)
6348
6349	case AFMAXNMS:
6350		return FPOP2S(0, 0, 0, 6)
6351
6352	case AFMAXNMD:
6353		return FPOP2S(0, 0, 1, 6)
6354
6355	case AFMINNMS:
6356		return FPOP2S(0, 0, 0, 7)
6357
6358	case AFMINNMD:
6359		return FPOP2S(0, 0, 1, 7)
6360
6361	case AFNMULS:
6362		return FPOP2S(0, 0, 0, 8)
6363
6364	case AFNMULD:
6365		return FPOP2S(0, 0, 1, 8)
6366
6367	case AFCMPS:
6368		return FPCMP(0, 0, 0, 0, 0)
6369
6370	case AFCMPD:
6371		return FPCMP(0, 0, 1, 0, 0)
6372
6373	case AFCMPES:
6374		return FPCMP(0, 0, 0, 0, 16)
6375
6376	case AFCMPED:
6377		return FPCMP(0, 0, 1, 0, 16)
6378
6379	case AFCCMPS:
6380		return FPCCMP(0, 0, 0, 0)
6381
6382	case AFCCMPD:
6383		return FPCCMP(0, 0, 1, 0)
6384
6385	case AFCCMPES:
6386		return FPCCMP(0, 0, 0, 1)
6387
6388	case AFCCMPED:
6389		return FPCCMP(0, 0, 1, 1)
6390
6391	case AFCSELS:
6392		return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
6393
6394	case AFCSELD:
6395		return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
6396
6397	case AFMOVS:
6398		return FPOP1S(0, 0, 0, 0)
6399
6400	case AFABSS:
6401		return FPOP1S(0, 0, 0, 1)
6402
6403	case AFNEGS:
6404		return FPOP1S(0, 0, 0, 2)
6405
6406	case AFSQRTS:
6407		return FPOP1S(0, 0, 0, 3)
6408
6409	case AFCVTSD:
6410		return FPOP1S(0, 0, 0, 5)
6411
6412	case AFCVTSH:
6413		return FPOP1S(0, 0, 0, 7)
6414
6415	case AFRINTNS:
6416		return FPOP1S(0, 0, 0, 8)
6417
6418	case AFRINTPS:
6419		return FPOP1S(0, 0, 0, 9)
6420
6421	case AFRINTMS:
6422		return FPOP1S(0, 0, 0, 10)
6423
6424	case AFRINTZS:
6425		return FPOP1S(0, 0, 0, 11)
6426
6427	case AFRINTAS:
6428		return FPOP1S(0, 0, 0, 12)
6429
6430	case AFRINTXS:
6431		return FPOP1S(0, 0, 0, 14)
6432
6433	case AFRINTIS:
6434		return FPOP1S(0, 0, 0, 15)
6435
6436	case AFMOVD:
6437		return FPOP1S(0, 0, 1, 0)
6438
6439	case AFABSD:
6440		return FPOP1S(0, 0, 1, 1)
6441
6442	case AFNEGD:
6443		return FPOP1S(0, 0, 1, 2)
6444
6445	case AFSQRTD:
6446		return FPOP1S(0, 0, 1, 3)
6447
6448	case AFCVTDS:
6449		return FPOP1S(0, 0, 1, 4)
6450
6451	case AFCVTDH:
6452		return FPOP1S(0, 0, 1, 7)
6453
6454	case AFRINTND:
6455		return FPOP1S(0, 0, 1, 8)
6456
6457	case AFRINTPD:
6458		return FPOP1S(0, 0, 1, 9)
6459
6460	case AFRINTMD:
6461		return FPOP1S(0, 0, 1, 10)
6462
6463	case AFRINTZD:
6464		return FPOP1S(0, 0, 1, 11)
6465
6466	case AFRINTAD:
6467		return FPOP1S(0, 0, 1, 12)
6468
6469	case AFRINTXD:
6470		return FPOP1S(0, 0, 1, 14)
6471
6472	case AFRINTID:
6473		return FPOP1S(0, 0, 1, 15)
6474
6475	case AFCVTHS:
6476		return FPOP1S(0, 0, 3, 4)
6477
6478	case AFCVTHD:
6479		return FPOP1S(0, 0, 3, 5)
6480
6481	case AVADD:
6482		return 7<<25 | 1<<21 | 1<<15 | 1<<10
6483
6484	case AVSUB:
6485		return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
6486
6487	case AVADDP:
6488		return 7<<25 | 1<<21 | 1<<15 | 15<<10
6489
6490	case AVAND:
6491		return 7<<25 | 1<<21 | 7<<10
6492
6493	case AVBCAX:
6494		return 0xCE<<24 | 1<<21
6495
6496	case AVCMEQ:
6497		return 1<<29 | 0x71<<21 | 0x23<<10
6498
6499	case AVCNT:
6500		return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
6501
6502	case AVZIP1:
6503		return 0xE<<24 | 3<<12 | 2<<10
6504
6505	case AVZIP2:
6506		return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
6507
6508	case AVEOR:
6509		return 1<<29 | 0x71<<21 | 7<<10
6510
6511	case AVEOR3:
6512		return 0xCE << 24
6513
6514	case AVORR:
6515		return 7<<25 | 5<<21 | 7<<10
6516
6517	case AVREV16:
6518		return 3<<26 | 2<<24 | 1<<21 | 3<<11
6519
6520	case AVRAX1:
6521		return 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
6522
6523	case AVREV32:
6524		return 11<<26 | 2<<24 | 1<<21 | 1<<11
6525
6526	case AVREV64:
6527		return 3<<26 | 2<<24 | 1<<21 | 1<<11
6528
6529	case AVMOV:
6530		return 7<<25 | 5<<21 | 7<<10
6531
6532	case AVADDV:
6533		return 7<<25 | 3<<20 | 3<<15 | 7<<11
6534
6535	case AVUADDLV:
6536		return 1<<29 | 7<<25 | 3<<20 | 7<<11
6537
6538	case AVFMLA:
6539		return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
6540
6541	case AVFMLS:
6542		return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
6543
6544	case AVPMULL, AVPMULL2:
6545		return 0xE<<24 | 1<<21 | 0x38<<10
6546
6547	case AVRBIT:
6548		return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
6549
6550	case AVLD1, AVLD2, AVLD3, AVLD4:
6551		return 3<<26 | 1<<22
6552
6553	case AVLD1R, AVLD3R:
6554		return 0xD<<24 | 1<<22
6555
6556	case AVLD2R, AVLD4R:
6557		return 0xD<<24 | 3<<21
6558
6559	case AVBIF:
6560		return 1<<29 | 7<<25 | 7<<21 | 7<<10
6561
6562	case AVBIT:
6563		return 1<<29 | 0x75<<21 | 7<<10
6564
6565	case AVBSL:
6566		return 1<<29 | 0x73<<21 | 7<<10
6567
6568	case AVCMTST:
6569		return 0xE<<24 | 1<<21 | 0x23<<10
6570
6571	case AVUMAX:
6572		return 1<<29 | 7<<25 | 1<<21 | 0x19<<10
6573
6574	case AVUMIN:
6575		return 1<<29 | 7<<25 | 1<<21 | 0x1b<<10
6576
6577	case AVUZP1:
6578		return 7<<25 | 3<<11
6579
6580	case AVUZP2:
6581		return 7<<25 | 1<<14 | 3<<11
6582
6583	case AVUADDW, AVUADDW2:
6584		return 0x17<<25 | 1<<21 | 1<<12
6585
6586	case AVTRN1:
6587		return 7<<25 | 5<<11
6588
6589	case AVTRN2:
6590		return 7<<25 | 1<<14 | 5<<11
6591	}
6592
6593	c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
6594	return 0
6595}
6596
6597/*
6598 * imm -> Rd
6599 * imm op Rn -> Rd
6600 */
6601func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
6602	switch a {
6603	/* op $addcon, Rn, Rd */
6604	case AMOVD, AADD:
6605		return S64 | 0<<30 | 0<<29 | 0x11<<24
6606
6607	case ACMN, AADDS:
6608		return S64 | 0<<30 | 1<<29 | 0x11<<24
6609
6610	case AMOVW, AADDW:
6611		return S32 | 0<<30 | 0<<29 | 0x11<<24
6612
6613	case ACMNW, AADDSW:
6614		return S32 | 0<<30 | 1<<29 | 0x11<<24
6615
6616	case ASUB:
6617		return S64 | 1<<30 | 0<<29 | 0x11<<24
6618
6619	case ACMP, ASUBS:
6620		return S64 | 1<<30 | 1<<29 | 0x11<<24
6621
6622	case ASUBW:
6623		return S32 | 1<<30 | 0<<29 | 0x11<<24
6624
6625	case ACMPW, ASUBSW:
6626		return S32 | 1<<30 | 1<<29 | 0x11<<24
6627
6628		/* op $imm(SB), Rd; op label, Rd */
6629	case AADR:
6630		return 0<<31 | 0x10<<24
6631
6632	case AADRP:
6633		return 1<<31 | 0x10<<24
6634
6635		/* op $bimm, Rn, Rd */
6636	case AAND, ABIC:
6637		return S64 | 0<<29 | 0x24<<23
6638
6639	case AANDW, ABICW:
6640		return S32 | 0<<29 | 0x24<<23 | 0<<22
6641
6642	case AORR, AORN:
6643		return S64 | 1<<29 | 0x24<<23
6644
6645	case AORRW, AORNW:
6646		return S32 | 1<<29 | 0x24<<23 | 0<<22
6647
6648	case AEOR, AEON:
6649		return S64 | 2<<29 | 0x24<<23
6650
6651	case AEORW, AEONW:
6652		return S32 | 2<<29 | 0x24<<23 | 0<<22
6653
6654	case AANDS, ABICS, ATST:
6655		return S64 | 3<<29 | 0x24<<23
6656
6657	case AANDSW, ABICSW, ATSTW:
6658		return S32 | 3<<29 | 0x24<<23 | 0<<22
6659
6660	case AASR:
6661		return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
6662
6663	case AASRW:
6664		return S32 | 0<<29 | 0x26<<23 | 0<<22
6665
6666		/* op $width, $lsb, Rn, Rd */
6667	case ABFI:
6668		return S64 | 2<<29 | 0x26<<23 | 1<<22
6669		/* alias of BFM */
6670
6671	case ABFIW:
6672		return S32 | 2<<29 | 0x26<<23 | 0<<22
6673
6674		/* op $imms, $immr, Rn, Rd */
6675	case ABFM:
6676		return S64 | 1<<29 | 0x26<<23 | 1<<22
6677
6678	case ABFMW:
6679		return S32 | 1<<29 | 0x26<<23 | 0<<22
6680
6681	case ASBFM:
6682		return S64 | 0<<29 | 0x26<<23 | 1<<22
6683
6684	case ASBFMW:
6685		return S32 | 0<<29 | 0x26<<23 | 0<<22
6686
6687	case AUBFM:
6688		return S64 | 2<<29 | 0x26<<23 | 1<<22
6689
6690	case AUBFMW:
6691		return S32 | 2<<29 | 0x26<<23 | 0<<22
6692
6693	case ABFXIL:
6694		return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
6695
6696	case ABFXILW:
6697		return S32 | 1<<29 | 0x26<<23 | 0<<22
6698
6699	case AEXTR:
6700		return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
6701
6702	case AEXTRW:
6703		return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
6704
6705	case ACBNZ:
6706		return S64 | 0x1A<<25 | 1<<24
6707
6708	case ACBNZW:
6709		return S32 | 0x1A<<25 | 1<<24
6710
6711	case ACBZ:
6712		return S64 | 0x1A<<25 | 0<<24
6713
6714	case ACBZW:
6715		return S32 | 0x1A<<25 | 0<<24
6716
6717	case ACCMN:
6718		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6719
6720	case ACCMNW:
6721		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6722
6723	case ACCMP:
6724		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6725
6726	case ACCMPW:
6727		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6728
6729	case AMOVK:
6730		return S64 | 3<<29 | 0x25<<23
6731
6732	case AMOVKW:
6733		return S32 | 3<<29 | 0x25<<23
6734
6735	case AMOVN:
6736		return S64 | 0<<29 | 0x25<<23
6737
6738	case AMOVNW:
6739		return S32 | 0<<29 | 0x25<<23
6740
6741	case AMOVZ:
6742		return S64 | 2<<29 | 0x25<<23
6743
6744	case AMOVZW:
6745		return S32 | 2<<29 | 0x25<<23
6746
6747	case AMSR:
6748		return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
6749
6750	case AAT,
6751		ADC,
6752		AIC,
6753		ATLBI,
6754		ASYS:
6755		return SYSOP(0, 1, 0, 0, 0, 0, 0)
6756
6757	case ASYSL:
6758		return SYSOP(1, 1, 0, 0, 0, 0, 0)
6759
6760	case ATBZ:
6761		return 0x36 << 24
6762
6763	case ATBNZ:
6764		return 0x37 << 24
6765
6766	case ADSB:
6767		return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
6768
6769	case ADMB:
6770		return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
6771
6772	case AISB:
6773		return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
6774
6775	case AHINT:
6776		return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
6777
6778	case AVEXT:
6779		return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
6780
6781	case AVUSHR:
6782		return 0x5E<<23 | 1<<10
6783
6784	case AVSHL:
6785		return 0x1E<<23 | 21<<10
6786
6787	case AVSRI:
6788		return 0x5E<<23 | 17<<10
6789
6790	case AVSLI:
6791		return 0x5E<<23 | 21<<10
6792
6793	case AVUSHLL, AVUXTL:
6794		return 1<<29 | 15<<24 | 0x29<<10
6795
6796	case AVUSHLL2, AVUXTL2:
6797		return 3<<29 | 15<<24 | 0x29<<10
6798
6799	case AVXAR:
6800		return 0xCE<<24 | 1<<23
6801
6802	case AVUSRA:
6803		return 1<<29 | 15<<24 | 5<<10
6804
6805	case APRFM:
6806		return 0xf9<<24 | 2<<22
6807	}
6808
6809	c.ctxt.Diag("%v: bad irr %v", p, a)
6810	return 0
6811}
6812
6813func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
6814	switch a {
6815	case ACLS:
6816		return S64 | OPBIT(5)
6817
6818	case ACLSW:
6819		return S32 | OPBIT(5)
6820
6821	case ACLZ:
6822		return S64 | OPBIT(4)
6823
6824	case ACLZW:
6825		return S32 | OPBIT(4)
6826
6827	case ARBIT:
6828		return S64 | OPBIT(0)
6829
6830	case ARBITW:
6831		return S32 | OPBIT(0)
6832
6833	case AREV:
6834		return S64 | OPBIT(3)
6835
6836	case AREVW:
6837		return S32 | OPBIT(2)
6838
6839	case AREV16:
6840		return S64 | OPBIT(1)
6841
6842	case AREV16W:
6843		return S32 | OPBIT(1)
6844
6845	case AREV32:
6846		return S64 | OPBIT(2)
6847
6848	default:
6849		c.ctxt.Diag("bad bit op\n%v", p)
6850		return 0
6851	}
6852}
6853
6854/*
6855 * add/subtract sign or zero-extended register
6856 */
6857func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, rd, rn, rm int16, extend bool) uint32 {
6858	extension := uint32(0)
6859	if !extend {
6860		if isADDop(a) {
6861			extension = LSL0_64
6862		}
6863		if isADDWop(a) {
6864			extension = LSL0_32
6865		}
6866	}
6867
6868	var op uint32
6869
6870	switch a {
6871	case AADD:
6872		op = S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6873
6874	case AADDW:
6875		op = S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6876
6877	case ACMN, AADDS:
6878		op = S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6879
6880	case ACMNW, AADDSW:
6881		op = S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6882
6883	case ASUB:
6884		op = S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6885
6886	case ASUBW:
6887		op = S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6888
6889	case ACMP, ASUBS:
6890		op = S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6891
6892	case ACMPW, ASUBSW:
6893		op = S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6894
6895	default:
6896		c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
6897		return 0
6898	}
6899
6900	op |= uint32(rm&0x1f)<<16 | uint32(rn&0x1f)<<5 | uint32(rd&0x1f)
6901
6902	return op
6903}
6904
6905func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
6906	switch a {
6907	case ASVC:
6908		return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
6909
6910	case AHVC:
6911		return 0xD4<<24 | 0<<21 | 2
6912
6913	case ASMC:
6914		return 0xD4<<24 | 0<<21 | 3
6915
6916	case ABRK:
6917		return 0xD4<<24 | 1<<21 | 0
6918
6919	case AHLT:
6920		return 0xD4<<24 | 2<<21 | 0
6921
6922	case ADCPS1:
6923		return 0xD4<<24 | 5<<21 | 1
6924
6925	case ADCPS2:
6926		return 0xD4<<24 | 5<<21 | 2
6927
6928	case ADCPS3:
6929		return 0xD4<<24 | 5<<21 | 3
6930
6931	case ACLREX:
6932		return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
6933	}
6934
6935	c.ctxt.Diag("%v: bad imm %v", p, a)
6936	return 0
6937}
6938
6939func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
6940	v := int64(0)
6941	t := int64(0)
6942	var q *obj.Prog
6943	if p.To.Type == obj.TYPE_BRANCH {
6944		q = p.To.Target()
6945	} else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp
6946		q = p.From.Target()
6947	}
6948	if q == nil {
6949		// TODO: don't use brdist for this case, as it isn't a branch.
6950		// (Calls from omovlit, and maybe adr/adrp opcodes as well.)
6951		q = p.Pool
6952	}
6953	if q != nil {
6954		v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
6955		if (v & ((1 << uint(shift)) - 1)) != 0 {
6956			c.ctxt.Diag("misaligned label\n%v", p)
6957		}
6958		v >>= uint(shift)
6959		t = int64(1) << uint(flen-1)
6960		if v < -t || v >= t {
6961			c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
6962			panic("branch too far")
6963		}
6964	}
6965
6966	return v & ((t << 1) - 1)
6967}
6968
6969/*
6970 * pc-relative branches
6971 */
6972func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
6973	switch a {
6974	case ABEQ:
6975		return OPBcc(0x0)
6976
6977	case ABNE:
6978		return OPBcc(0x1)
6979
6980	case ABCS:
6981		return OPBcc(0x2)
6982
6983	case ABHS:
6984		return OPBcc(0x2)
6985
6986	case ABCC:
6987		return OPBcc(0x3)
6988
6989	case ABLO:
6990		return OPBcc(0x3)
6991
6992	case ABMI:
6993		return OPBcc(0x4)
6994
6995	case ABPL:
6996		return OPBcc(0x5)
6997
6998	case ABVS:
6999		return OPBcc(0x6)
7000
7001	case ABVC:
7002		return OPBcc(0x7)
7003
7004	case ABHI:
7005		return OPBcc(0x8)
7006
7007	case ABLS:
7008		return OPBcc(0x9)
7009
7010	case ABGE:
7011		return OPBcc(0xa)
7012
7013	case ABLT:
7014		return OPBcc(0xb)
7015
7016	case ABGT:
7017		return OPBcc(0xc)
7018
7019	case ABLE:
7020		return OPBcc(0xd) /* imm19<<5 | cond */
7021
7022	case AB:
7023		return 0<<31 | 5<<26 /* imm26 */
7024
7025	case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
7026		return 1<<31 | 5<<26
7027	}
7028
7029	c.ctxt.Diag("%v: bad bra %v", p, a)
7030	return 0
7031}
7032
7033func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
7034	switch a {
7035	case ABL:
7036		return OPBLR(1) /* BLR */
7037
7038	case AB:
7039		return OPBLR(0) /* BR */
7040
7041	case obj.ARET:
7042		return OPBLR(2) /* RET */
7043	}
7044
7045	c.ctxt.Diag("%v: bad brr %v", p, a)
7046	return 0
7047}
7048
7049func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
7050	switch a {
7051	case ADRPS:
7052		return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
7053
7054	case AERET:
7055		return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
7056
7057	case ANOOP:
7058		return SYSHINT(0)
7059
7060	case AYIELD:
7061		return SYSHINT(1)
7062
7063	case AWFE:
7064		return SYSHINT(2)
7065
7066	case AWFI:
7067		return SYSHINT(3)
7068
7069	case ASEV:
7070		return SYSHINT(4)
7071
7072	case ASEVL:
7073		return SYSHINT(5)
7074	}
7075
7076	c.ctxt.Diag("%v: bad op0 %v", p, a)
7077	return 0
7078}
7079
7080/*
7081 * register offset
7082 */
7083func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
7084	switch a {
7085	case ALDAR:
7086		return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
7087
7088	case ALDARW:
7089		return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
7090
7091	case ALDARB:
7092		return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
7093
7094	case ALDARH:
7095		return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
7096
7097	case ALDAXP:
7098		return LDSTX(3, 0, 1, 1, 1)
7099
7100	case ALDAXPW:
7101		return LDSTX(2, 0, 1, 1, 1)
7102
7103	case ALDAXR:
7104		return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
7105
7106	case ALDAXRW:
7107		return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
7108
7109	case ALDAXRB:
7110		return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
7111
7112	case ALDAXRH:
7113		return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
7114
7115	case ALDXR:
7116		return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
7117
7118	case ALDXRB:
7119		return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
7120
7121	case ALDXRH:
7122		return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
7123
7124	case ALDXRW:
7125		return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
7126
7127	case ALDXP:
7128		return LDSTX(3, 0, 1, 1, 0)
7129
7130	case ALDXPW:
7131		return LDSTX(2, 0, 1, 1, 0)
7132	}
7133
7134	c.ctxt.Diag("bad opload %v\n%v", a, p)
7135	return 0
7136}
7137
7138func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
7139	switch a {
7140	case ASTLR:
7141		return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
7142
7143	case ASTLRB:
7144		return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
7145
7146	case ASTLRH:
7147		return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
7148
7149	case ASTLRW:
7150		return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
7151
7152	case ASTLXP:
7153		return LDSTX(3, 0, 0, 1, 1)
7154
7155	case ASTLXPW:
7156		return LDSTX(2, 0, 0, 1, 1)
7157
7158	case ASTLXR:
7159		return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
7160
7161	case ASTLXRB:
7162		return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
7163
7164	case ASTLXRH:
7165		return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
7166
7167	case ASTLXRW:
7168		return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
7169
7170	case ASTXR:
7171		return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
7172
7173	case ASTXRB:
7174		return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
7175
7176	case ASTXRH:
7177		return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
7178
7179	case ASTXP:
7180		return LDSTX(3, 0, 0, 1, 0)
7181
7182	case ASTXPW:
7183		return LDSTX(2, 0, 0, 1, 0)
7184
7185	case ASTXRW:
7186		return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
7187	}
7188
7189	c.ctxt.Diag("bad opstore %v\n%v", a, p)
7190	return 0
7191}
7192
7193/*
7194 * load/store register (scaled 12-bit unsigned immediate) C3.3.13
7195 *	these produce 64-bit values (when there's an option)
7196 */
7197func (c *ctxt7) olsr12u(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 {
7198	if v < 0 || v >= (1<<12) {
7199		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
7200	}
7201	o |= uint32(v&0xFFF) << 10
7202	o |= uint32(rn&31) << 5
7203	o |= uint32(rt & 31)
7204	o |= 1 << 24
7205	return o
7206}
7207
7208/*
7209 * load/store register (unscaled 9-bit signed immediate) C3.3.12
7210 */
7211func (c *ctxt7) olsr9s(p *obj.Prog, o uint32, v int32, rn, rt int16) uint32 {
7212	if v < -256 || v > 255 {
7213		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
7214	}
7215	o |= uint32((v & 0x1FF) << 12)
7216	o |= uint32(rn&31) << 5
7217	o |= uint32(rt & 31)
7218	return o
7219}
7220
7221// store(immediate)
7222// scaled 12-bit unsigned immediate offset.
7223// unscaled 9-bit signed immediate offset.
7224// pre/post-indexed store.
7225// and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
7226func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 {
7227	enc := c.opldr(p, a)
7228	switch p.As {
7229	case AFMOVQ:
7230		enc = enc &^ (1 << 22)
7231	default:
7232		enc = LD2STR(enc)
7233	}
7234	return enc
7235}
7236
7237// load(immediate)
7238// scaled 12-bit unsigned immediate offset.
7239// unscaled 9-bit signed immediate offset.
7240// pre/post-indexed load.
7241// and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
7242func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 {
7243	switch a {
7244	case AMOVD:
7245		return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
7246
7247	case AMOVW:
7248		return LDSTR(2, 0, 2)
7249
7250	case AMOVWU:
7251		return LDSTR(2, 0, 1)
7252
7253	case AMOVH:
7254		return LDSTR(1, 0, 2)
7255
7256	case AMOVHU:
7257		return LDSTR(1, 0, 1)
7258
7259	case AMOVB:
7260		return LDSTR(0, 0, 2)
7261
7262	case AMOVBU:
7263		return LDSTR(0, 0, 1)
7264
7265	case AFMOVS, AVMOVS:
7266		return LDSTR(2, 1, 1)
7267
7268	case AFMOVD, AVMOVD:
7269		return LDSTR(3, 1, 1)
7270
7271	case AFMOVQ, AVMOVQ:
7272		return LDSTR(0, 1, 3)
7273	}
7274
7275	c.ctxt.Diag("bad opldr %v\n%v", a, p)
7276	return 0
7277}
7278
7279// olsxrr attaches register operands to a load/store opcode supplied in o.
7280// The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
7281func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
7282	o |= int32(r1&31) << 5
7283	o |= int32(r2&31) << 16
7284	o |= int32(r & 31)
7285	return uint32(o)
7286}
7287
7288// opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
7289// for load instruction with register offset.
7290// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
7291func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
7292	OptionS := uint32(0x1a)
7293	if extension {
7294		OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
7295	}
7296	switch a {
7297	case AMOVD:
7298		return OptionS<<10 | 0x3<<21 | 0x1f<<27
7299	case AMOVW:
7300		return OptionS<<10 | 0x5<<21 | 0x17<<27
7301	case AMOVWU:
7302		return OptionS<<10 | 0x3<<21 | 0x17<<27
7303	case AMOVH:
7304		return OptionS<<10 | 0x5<<21 | 0x0f<<27
7305	case AMOVHU:
7306		return OptionS<<10 | 0x3<<21 | 0x0f<<27
7307	case AMOVB:
7308		return OptionS<<10 | 0x5<<21 | 0x07<<27
7309	case AMOVBU:
7310		return OptionS<<10 | 0x3<<21 | 0x07<<27
7311	case AFMOVS:
7312		return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
7313	case AFMOVD:
7314		return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
7315	}
7316	c.ctxt.Diag("bad opldrr %v\n%v", a, p)
7317	return 0
7318}
7319
7320// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
7321// for store instruction with register offset.
7322// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
7323func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
7324	OptionS := uint32(0x1a)
7325	if extension {
7326		OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
7327	}
7328	switch a {
7329	case AMOVD:
7330		return OptionS<<10 | 0x1<<21 | 0x1f<<27
7331	case AMOVW, AMOVWU:
7332		return OptionS<<10 | 0x1<<21 | 0x17<<27
7333	case AMOVH, AMOVHU:
7334		return OptionS<<10 | 0x1<<21 | 0x0f<<27
7335	case AMOVB, AMOVBU:
7336		return OptionS<<10 | 0x1<<21 | 0x07<<27
7337	case AFMOVS:
7338		return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
7339	case AFMOVD:
7340		return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
7341	}
7342	c.ctxt.Diag("bad opstrr %v\n%v", a, p)
7343	return 0
7344}
7345
7346func (c *ctxt7) oaddi(p *obj.Prog, a obj.As, v int32, rd, rn int16) uint32 {
7347	op := c.opirr(p, a)
7348
7349	if (v & 0xFFF000) != 0 {
7350		if v&0xFFF != 0 {
7351			c.ctxt.Diag("%v misuses oaddi", p)
7352		}
7353		v >>= 12
7354		op |= 1 << 22
7355	}
7356
7357	op |= (uint32(v&0xFFF) << 10) | (uint32(rn&31) << 5) | uint32(rd&31)
7358
7359	return op
7360}
7361
7362func (c *ctxt7) oaddi12(p *obj.Prog, v int32, rd, rn int16) uint32 {
7363	if v < -4095 || v > 4095 {
7364		c.ctxt.Diag("%v is not a 12 bit immediate: %v", v, p)
7365		return 0
7366	}
7367	a := AADD
7368	if v < 0 {
7369		a = ASUB
7370		v = -v
7371	}
7372	return c.oaddi(p, a, v, rd, rn)
7373}
7374
7375/*
7376 * load a literal value into dr
7377 */
7378func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
7379	var o1 int32
7380	if p.Pool == nil { /* not in literal pool */
7381		c.aclass(a)
7382		c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
7383
7384		/* TODO: could be clever, and use general constant builder */
7385		o1 = int32(c.opirr(p, AADD))
7386
7387		v := int32(c.instoffset)
7388		if v != 0 && (v&0xFFF) == 0 {
7389			v >>= 12
7390			o1 |= 1 << 22 /* shift, by 12 */
7391		}
7392
7393		o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
7394	} else {
7395		fp, w := 0, 0
7396		switch as {
7397		case AFMOVS, AVMOVS:
7398			fp = 1
7399			w = 0 /* 32-bit SIMD/FP */
7400
7401		case AFMOVD, AVMOVD:
7402			fp = 1
7403			w = 1 /* 64-bit SIMD/FP */
7404
7405		case AVMOVQ:
7406			fp = 1
7407			w = 2 /* 128-bit SIMD/FP */
7408
7409		case AMOVD:
7410			if p.Pool.As == ADWORD {
7411				w = 1 /* 64-bit */
7412			} else if p.Pool.To.Offset < 0 {
7413				w = 2 /* 32-bit, sign-extended to 64-bit */
7414			} else if p.Pool.To.Offset >= 0 {
7415				w = 0 /* 32-bit, zero-extended to 64-bit */
7416			} else {
7417				c.ctxt.Diag("invalid operand %v in %v", a, p)
7418			}
7419
7420		case AMOVBU, AMOVHU, AMOVWU:
7421			w = 0 /* 32-bit, zero-extended to 64-bit */
7422
7423		case AMOVB, AMOVH, AMOVW:
7424			w = 2 /* 32-bit, sign-extended to 64-bit */
7425
7426		default:
7427			c.ctxt.Diag("invalid operation %v in %v", as, p)
7428		}
7429
7430		v := int32(c.brdist(p, 0, 19, 2))
7431		o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
7432		o1 |= (v & 0x7FFFF) << 5
7433		o1 |= int32(dr & 31)
7434	}
7435
7436	return uint32(o1)
7437}
7438
7439// load a constant (MOVCON or BITCON) in a into rt
7440func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
7441	if cls := int(a.Class); (cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0) && rt != REGZERO {
7442		// or $bitcon, REGZERO, rt. rt can't be ZR.
7443		mode := 64
7444		var as1 obj.As
7445		switch as {
7446		case AMOVW:
7447			as1 = AORRW
7448			mode = 32
7449		case AMOVD:
7450			as1 = AORR
7451		}
7452		o1 = c.opirr(p, as1)
7453		o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
7454		return o1
7455	}
7456
7457	if as == AMOVW {
7458		d := uint32(a.Offset)
7459		s := movcon(int64(d))
7460		if s < 0 || 16*s >= 32 {
7461			d = ^d
7462			s = movcon(int64(d))
7463			if s < 0 || 16*s >= 32 {
7464				c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
7465			}
7466			o1 = c.opirr(p, AMOVNW)
7467		} else {
7468			o1 = c.opirr(p, AMOVZW)
7469		}
7470		o1 |= MOVCONST(int64(d), s, rt)
7471	}
7472	if as == AMOVD {
7473		d := a.Offset
7474		s := movcon(d)
7475		if s < 0 || 16*s >= 64 {
7476			d = ^d
7477			s = movcon(d)
7478			if s < 0 || 16*s >= 64 {
7479				c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
7480			}
7481			o1 = c.opirr(p, AMOVN)
7482		} else {
7483			o1 = c.opirr(p, AMOVZ)
7484		}
7485		o1 |= MOVCONST(d, s, rt)
7486	}
7487	return o1
7488}
7489
7490// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
7491// put the instruction sequence in os and return the number of instructions.
7492func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
7493	switch as {
7494	case AMOVW:
7495		d := uint32(a.Offset)
7496		// use MOVZW and MOVKW to load a constant to rt
7497		os[0] = c.opirr(p, AMOVZW)
7498		os[0] |= MOVCONST(int64(d), 0, rt)
7499		os[1] = c.opirr(p, AMOVKW)
7500		os[1] |= MOVCONST(int64(d), 1, rt)
7501		return 2
7502
7503	case AMOVD:
7504		d := a.Offset
7505		dn := ^d
7506		var immh [4]uint64
7507		var i int
7508		zeroCount := int(0)
7509		negCount := int(0)
7510		for i = 0; i < 4; i++ {
7511			immh[i] = uint64((d >> uint(i*16)) & 0xffff)
7512			if immh[i] == 0 {
7513				zeroCount++
7514			} else if immh[i] == 0xffff {
7515				negCount++
7516			}
7517		}
7518
7519		if zeroCount == 4 || negCount == 4 {
7520			c.ctxt.Diag("the immediate should be MOVCON: %v", p)
7521		}
7522		switch {
7523		case zeroCount == 3:
7524			// one MOVZ
7525			for i = 0; i < 4; i++ {
7526				if immh[i] != 0 {
7527					os[0] = c.opirr(p, AMOVZ)
7528					os[0] |= MOVCONST(d, i, rt)
7529					break
7530				}
7531			}
7532			return 1
7533
7534		case negCount == 3:
7535			// one MOVN
7536			for i = 0; i < 4; i++ {
7537				if immh[i] != 0xffff {
7538					os[0] = c.opirr(p, AMOVN)
7539					os[0] |= MOVCONST(dn, i, rt)
7540					break
7541				}
7542			}
7543			return 1
7544
7545		case zeroCount == 2:
7546			// one MOVZ and one MOVK
7547			for i = 0; i < 4; i++ {
7548				if immh[i] != 0 {
7549					os[0] = c.opirr(p, AMOVZ)
7550					os[0] |= MOVCONST(d, i, rt)
7551					i++
7552					break
7553				}
7554			}
7555			for ; i < 4; i++ {
7556				if immh[i] != 0 {
7557					os[1] = c.opirr(p, AMOVK)
7558					os[1] |= MOVCONST(d, i, rt)
7559				}
7560			}
7561			return 2
7562
7563		case negCount == 2:
7564			// one MOVN and one MOVK
7565			for i = 0; i < 4; i++ {
7566				if immh[i] != 0xffff {
7567					os[0] = c.opirr(p, AMOVN)
7568					os[0] |= MOVCONST(dn, i, rt)
7569					i++
7570					break
7571				}
7572			}
7573			for ; i < 4; i++ {
7574				if immh[i] != 0xffff {
7575					os[1] = c.opirr(p, AMOVK)
7576					os[1] |= MOVCONST(d, i, rt)
7577				}
7578			}
7579			return 2
7580
7581		case zeroCount == 1:
7582			// one MOVZ and two MOVKs
7583			for i = 0; i < 4; i++ {
7584				if immh[i] != 0 {
7585					os[0] = c.opirr(p, AMOVZ)
7586					os[0] |= MOVCONST(d, i, rt)
7587					i++
7588					break
7589				}
7590			}
7591
7592			for j := 1; i < 4; i++ {
7593				if immh[i] != 0 {
7594					os[j] = c.opirr(p, AMOVK)
7595					os[j] |= MOVCONST(d, i, rt)
7596					j++
7597				}
7598			}
7599			return 3
7600
7601		case negCount == 1:
7602			// one MOVN and two MOVKs
7603			for i = 0; i < 4; i++ {
7604				if immh[i] != 0xffff {
7605					os[0] = c.opirr(p, AMOVN)
7606					os[0] |= MOVCONST(dn, i, rt)
7607					i++
7608					break
7609				}
7610			}
7611
7612			for j := 1; i < 4; i++ {
7613				if immh[i] != 0xffff {
7614					os[j] = c.opirr(p, AMOVK)
7615					os[j] |= MOVCONST(d, i, rt)
7616					j++
7617				}
7618			}
7619			return 3
7620
7621		default:
7622			// one MOVZ and 3 MOVKs
7623			os[0] = c.opirr(p, AMOVZ)
7624			os[0] |= MOVCONST(d, 0, rt)
7625			for i = 1; i < 4; i++ {
7626				os[i] = c.opirr(p, AMOVK)
7627				os[i] |= MOVCONST(d, i, rt)
7628			}
7629			return 4
7630		}
7631	default:
7632		return 0
7633	}
7634}
7635
7636func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r, s int64, rf, rt int16) uint32 {
7637	var b uint32
7638	o := c.opirr(p, a)
7639	if (o & (1 << 31)) == 0 {
7640		b = 32
7641	} else {
7642		b = 64
7643	}
7644	if r < 0 || uint32(r) >= b {
7645		c.ctxt.Diag("illegal bit number\n%v", p)
7646	}
7647	o |= (uint32(r) & 0x3F) << 16
7648	if s < 0 || uint32(s) >= b {
7649		c.ctxt.Diag("illegal bit number\n%v", p)
7650	}
7651	o |= (uint32(s) & 0x3F) << 10
7652	o |= (uint32(rf&31) << 5) | uint32(rt&31)
7653	return o
7654}
7655
7656func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int64, rn, rm, rt int16) uint32 {
7657	var b uint32
7658	o := c.opirr(p, a)
7659	if (o & (1 << 31)) != 0 {
7660		b = 63
7661	} else {
7662		b = 31
7663	}
7664	if v < 0 || uint32(v) > b {
7665		c.ctxt.Diag("illegal bit number\n%v", p)
7666	}
7667	o |= uint32(v) << 10
7668	o |= uint32(rn&31) << 5
7669	o |= uint32(rm&31) << 16
7670	o |= uint32(rt & 31)
7671	return o
7672}
7673
7674/* generate instruction encoding for ldp and stp series */
7675func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh int16, ldp uint32) uint32 {
7676	wback := false
7677	if o.scond == C_XPOST || o.scond == C_XPRE {
7678		wback = true
7679	}
7680	switch p.As {
7681	case ALDP, ALDPW, ALDPSW:
7682		c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7683	case ASTP, ASTPW:
7684		if wback {
7685			c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
7686		}
7687	case AFLDPD, AFLDPQ, AFLDPS:
7688		c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7689	}
7690	var ret uint32
7691	// check offset
7692	switch p.As {
7693	case AFLDPQ, AFSTPQ:
7694		if vo < -1024 || vo > 1008 || vo%16 != 0 {
7695			c.ctxt.Diag("invalid offset %v\n", p)
7696		}
7697		vo /= 16
7698		ret = 2<<30 | 1<<26
7699	case AFLDPD, AFSTPD:
7700		if vo < -512 || vo > 504 || vo%8 != 0 {
7701			c.ctxt.Diag("invalid offset %v\n", p)
7702		}
7703		vo /= 8
7704		ret = 1<<30 | 1<<26
7705	case AFLDPS, AFSTPS:
7706		if vo < -256 || vo > 252 || vo%4 != 0 {
7707			c.ctxt.Diag("invalid offset %v\n", p)
7708		}
7709		vo /= 4
7710		ret = 1 << 26
7711	case ALDP, ASTP:
7712		if vo < -512 || vo > 504 || vo%8 != 0 {
7713			c.ctxt.Diag("invalid offset %v\n", p)
7714		}
7715		vo /= 8
7716		ret = 2 << 30
7717	case ALDPW, ASTPW:
7718		if vo < -256 || vo > 252 || vo%4 != 0 {
7719			c.ctxt.Diag("invalid offset %v\n", p)
7720		}
7721		vo /= 4
7722		ret = 0
7723	case ALDPSW:
7724		if vo < -256 || vo > 252 || vo%4 != 0 {
7725			c.ctxt.Diag("invalid offset %v\n", p)
7726		}
7727		vo /= 4
7728		ret = 1 << 30
7729	default:
7730		c.ctxt.Diag("invalid instruction %v\n", p)
7731	}
7732	// check register pair
7733	switch p.As {
7734	case AFLDPQ, AFLDPD, AFLDPS, AFSTPQ, AFSTPD, AFSTPS:
7735		if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
7736			c.ctxt.Diag("invalid register pair %v\n", p)
7737		}
7738	case ALDP, ALDPW, ALDPSW:
7739		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
7740			c.ctxt.Diag("invalid register pair %v\n", p)
7741		}
7742	case ASTP, ASTPW:
7743		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
7744			c.ctxt.Diag("invalid register pair %v\n", p)
7745		}
7746	}
7747	// other conditional flag bits
7748	switch o.scond {
7749	case C_XPOST:
7750		ret |= 1 << 23
7751	case C_XPRE:
7752		ret |= 3 << 23
7753	default:
7754		ret |= 2 << 23
7755	}
7756	ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | uint32(rh&31)<<10 | uint32(rbase&31)<<5 | uint32(rl&31)
7757	return ret
7758}
7759
7760func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
7761	if p.As == AVLD1 || p.As == AVST1 {
7762		return o1
7763	}
7764
7765	o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
7766	switch p.As {
7767	case AVLD1R, AVLD2R:
7768		o1 |= 0xC << 12
7769	case AVLD3R, AVLD4R:
7770		o1 |= 0xE << 12
7771	case AVLD2, AVST2:
7772		o1 |= 8 << 12
7773	case AVLD3, AVST3:
7774		o1 |= 4 << 12
7775	case AVLD4, AVST4:
7776	default:
7777		c.ctxt.Diag("unsupported instruction:%v\n", p.As)
7778	}
7779	return o1
7780}
7781
7782/*
7783 * size in log2(bytes)
7784 */
7785func movesize(a obj.As) int {
7786	switch a {
7787	case AFMOVQ:
7788		return 4
7789
7790	case AMOVD, AFMOVD:
7791		return 3
7792
7793	case AMOVW, AMOVWU, AFMOVS:
7794		return 2
7795
7796	case AMOVH, AMOVHU:
7797		return 1
7798
7799	case AMOVB, AMOVBU:
7800		return 0
7801
7802	default:
7803		return -1
7804	}
7805}
7806
7807// rm is the Rm register value, o is the extension, amount is the left shift value.
7808func roff(rm int16, o uint32, amount int16) uint32 {
7809	return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
7810}
7811
7812// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
7813func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 {
7814	var num, rm int16
7815	num = (r >> 5) & 7
7816	rm = r & 31
7817	switch {
7818	case REG_UXTB <= r && r < REG_UXTH:
7819		return roff(rm, 0, num)
7820	case REG_UXTH <= r && r < REG_UXTW:
7821		return roff(rm, 1, num)
7822	case REG_UXTW <= r && r < REG_UXTX:
7823		if a.Type == obj.TYPE_MEM {
7824			if num == 0 {
7825				// According to the arm64 specification, for instructions MOVB, MOVBU and FMOVB,
7826				// the extension amount must be 0, encoded in "S" as 0 if omitted, or as 1 if present.
7827				// But in Go, we don't distinguish between Rn.UXTW and Rn.UXTW<<0, so we encode it as
7828				// that does not present. This makes no difference to the function of the instruction.
7829				// This is also true for extensions LSL, SXTW and SXTX.
7830				return roff(rm, 2, 2)
7831			} else {
7832				return roff(rm, 2, 6)
7833			}
7834		} else {
7835			return roff(rm, 2, num)
7836		}
7837	case REG_UXTX <= r && r < REG_SXTB:
7838		return roff(rm, 3, num)
7839	case REG_SXTB <= r && r < REG_SXTH:
7840		return roff(rm, 4, num)
7841	case REG_SXTH <= r && r < REG_SXTW:
7842		return roff(rm, 5, num)
7843	case REG_SXTW <= r && r < REG_SXTX:
7844		if a.Type == obj.TYPE_MEM {
7845			if num == 0 {
7846				return roff(rm, 6, 2)
7847			} else {
7848				return roff(rm, 6, 6)
7849			}
7850		} else {
7851			return roff(rm, 6, num)
7852		}
7853	case REG_SXTX <= r && r < REG_SPECIAL:
7854		if a.Type == obj.TYPE_MEM {
7855			if num == 0 {
7856				return roff(rm, 7, 2)
7857			} else {
7858				return roff(rm, 7, 6)
7859			}
7860		} else {
7861			return roff(rm, 7, num)
7862		}
7863	case REG_LSL <= r && r < REG_ARNG:
7864		if a.Type == obj.TYPE_MEM { // (R1)(R2<<1)
7865			if num == 0 {
7866				return roff(rm, 3, 2)
7867			} else {
7868				return roff(rm, 3, 6)
7869			}
7870		} else if isADDWop(p.As) {
7871			return roff(rm, 2, num)
7872		}
7873		return roff(rm, 3, num)
7874	default:
7875		c.ctxt.Diag("unsupported register extension type.")
7876	}
7877
7878	return 0
7879}
7880
7881// pack returns the encoding of the "Q" field and two arrangement specifiers.
7882func pack(q uint32, arngA, arngB uint8) uint32 {
7883	return uint32(q)<<16 | uint32(arngA)<<8 | uint32(arngB)
7884}
7885