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