podman

Форк
0
7140 строк · 172.8 Кб
1
// cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
2
// https://code.google.com/p/ken-cc/source/browse/
3
//
4
// 	Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5
// 	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6
// 	Portions Copyright © 1997-1999 Vita Nuova Limited
7
// 	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8
// 	Portions Copyright © 2004,2006 Bruce Ellis
9
// 	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10
// 	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11
// 	Portions Copyright © 2009 The Go Authors. All rights reserved.
12
//
13
// Permission is hereby granted, free of charge, to any person obtaining a copy
14
// of this software and associated documentation files (the "Software"), to deal
15
// in the Software without restriction, including without limitation the rights
16
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
// copies of the Software, and to permit persons to whom the Software is
18
// furnished to do so, subject to the following conditions:
19
//
20
// The above copyright notice and this permission notice shall be included in
21
// all copies or substantial portions of the Software.
22
//
23
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29
// THE SOFTWARE.
30

31
package arm64
32

33
import (
34
	"github.com/twitchyliquid64/golang-asm/obj"
35
	"github.com/twitchyliquid64/golang-asm/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.
45
type 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

61
const (
62
	funcAlign = 16
63
)
64

65
const (
66
	REGFROM = 1
67
)
68

69
type 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

82
func IsAtomicInstruction(as obj.As) bool {
83
	_, ok := atomicInstructions[as]
84
	return ok
85
}
86

87
// known field values of an instruction.
88
var 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

171
var oprange [ALAST & obj.AMask][]Optab
172

173
var xcmp [C_NCLASS][C_NCLASS]bool
174

175
const (
176
	S32     = 0 << 31
177
	S64     = 1 << 31
178
	Sbit    = 1 << 29
179
	LSL0_32 = 2 << 13
180
	LSL0_64 = 3 << 13
181
)
182

183
func OPDP2(x uint32) uint32 {
184
	return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
185
}
186

187
func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
188
	return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
189
}
190

191
func OPBcc(x uint32) uint32 {
192
	return 0x2A<<25 | 0<<24 | 0<<4 | x&15
193
}
194

195
func 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

200
func 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

204
func SYSHINT(x uint32) uint32 {
205
	return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
206
}
207

208
func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 {
209
	return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22
210
}
211

212
func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
213
	return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
214
}
215

216
func LD2STR(o uint32) uint32 {
217
	return o &^ (3 << 22)
218
}
219

220
func 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

224
func 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

228
func 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

232
func 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

236
func 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

240
func 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

244
func 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

248
func 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

252
func OPBIT(x uint32) uint32 {
253
	return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
254
}
255

256
func 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

260
const (
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

267
var 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, NOTUSETMP, 0},
291
	{AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 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_RSP, 4, 4, REGFROM, 0, 0},
395
	{AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0},
396

397
	/* load long effective stack address (load int32 offset and add) */
398
	{AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0},
399

400
	// Move a large constant to a Vn.
401
	{AFMOVQ, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
402
	{AFMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
403
	{AFMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
404

405
	/* jump operations */
406
	{AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
407
	{ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
408
	{AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
409
	{ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
410
	{ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
411
	{ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
412
	{obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
413
	{obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
414
	{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
415
	{ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
416
	{ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0},
417
	{AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
418

419
	// get a PC-relative address
420
	{AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0},
421
	{AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0},
422

423
	{ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
424
	{ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
425
	{ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0},
426
	{ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0},
427
	{AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0},
428
	{ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
429
	{ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0},
430
	{ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0},
431
	{ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0},
432
	{ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0},
433
	{ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
434
	{ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
435
	{ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
436
	{ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0},
437
	{ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0},
438
	{ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0},
439
	{ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0},
440
	{AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
441
	{AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
442
	{AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
443
	{AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
444
	{AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
445
	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
446
	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
447
	{AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
448
	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
449
	{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
450
	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
451
	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
452
	{AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
453
	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
454
	{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
455
	{AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0},
456
	{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0},
457
	{AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0},
458

459
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
460
	{AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
461
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
462
	{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
463
	{AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
464
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
465
	{AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
466
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
467
	{AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
468
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
469
	{AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
470
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
471
	{AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
472
	{ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
473
	{AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
474
	{AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
475
	{AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
476
	{AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
477
	{AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
478
	{AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
479
	{AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
480
	{AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
481
	{AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
482
	{AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
483
	{AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
484
	{AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
485
	{AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
486
	{AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
487
	{AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
488
	{AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
489

490
	/* conditional operations */
491
	{ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0},
492
	{ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0},
493
	{ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0},
494
	{AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
495
	{ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0},
496
	{ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
497
	{AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
498

499
	/* scaled 12-bit unsigned displacement store */
500
	{AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
501
	{AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
502
	{AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
503
	{AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
504
	{AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
505
	{AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
506
	{AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
507
	{AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
508
	{AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
509
	{AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
510

511
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
512
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
513
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
514
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
515

516
	/* unscaled 9-bit signed displacement store */
517
	{AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
518
	{AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
519
	{AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
520
	{AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
521
	{AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
522
	{AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
523
	{AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
524
	{AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
525
	{AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
526
	{AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
527

528
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
529
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
530
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
531
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
532

533
	/* scaled 12-bit unsigned displacement load */
534
	{AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
535
	{AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
536
	{AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
537
	{AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
538
	{AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
539
	{AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
540
	{AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
541
	{AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
542
	{AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
543
	{AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
544

545
	{AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
546
	{AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
547
	{AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
548
	{AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
549

550
	/* unscaled 9-bit signed displacement load */
551
	{AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
552
	{AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
553
	{AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
554
	{AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
555
	{AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
556
	{AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
557
	{AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
558
	{AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
559
	{AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
560
	{AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
561

562
	{AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
563
	{AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
564
	{AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
565
	{AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
566

567
	/* long displacement store */
568
	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
569
	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
570
	{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
571
	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
572
	{AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
573
	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
574
	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
575
	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
576
	{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
577
	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
578

579
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
580
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
581
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
582
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
583

584
	/* long displacement load */
585
	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
586
	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
587
	{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
588
	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
589
	{AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
590
	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
591
	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
592
	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
593
	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
594
	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
595

596
	{AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
597
	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
598
	{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
599
	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
600

601
	/* pre/post-indexed load (unscaled, signed 9-bit offset) */
602
	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
603
	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
604
	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
605
	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
606
	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
607
	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
608
	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
609

610
	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
611
	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
612
	{AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
613
	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
614
	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
615
	{AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
616
	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
617

618
	/* pre/post-indexed store (unscaled, signed 9-bit offset) */
619
	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
620
	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
621
	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
622
	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
623
	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
624
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
625
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
626

627
	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
628
	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
629
	{AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
630
	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
631
	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
632
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
633
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
634

635
	/* load with shifted or extended register offset */
636
	{AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
637
	{AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
638
	{AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
639
	{AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
640
	{AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
641
	{AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
642
	{AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
643

644
	/* store with extended register offset */
645
	{AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
646
	{AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
647
	{AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
648
	{AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
649
	{AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
650
	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
651

652
	/* pre/post-indexed/signed-offset load/store register pair
653
	   (unscaled, signed 10-bit quad-aligned and long offset) */
654
	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
655
	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
656
	{ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
657
	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
658
	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
659
	{ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
660
	{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
661
	{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
662
	{ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
663
	{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
664
	{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
665
	{ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
666
	{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
667
	{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
668
	{ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
669
	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
670
	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
671
	{ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
672
	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
673
	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
674
	{ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
675
	{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
676
	{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
677
	{ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
678
	{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
679
	{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
680
	{ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
681
	{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
682
	{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
683
	{ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
684
	{ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
685

686
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
687
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
688
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
689
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
690
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
691
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
692
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
693
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
694
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
695
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
696
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
697
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
698
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
699
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
700
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
701
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
702
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
703
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
704
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
705
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
706
	{ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
707
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
708
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
709
	{ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
710
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
711
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
712
	{ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
713
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
714
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
715
	{ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
716
	{ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
717

718
	// differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
719
	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
720
	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
721
	{ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
722
	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
723
	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
724
	{ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
725
	{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
726
	{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
727
	{ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
728
	{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
729
	{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
730
	{ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
731
	{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
732
	{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
733
	{ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
734
	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
735
	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
736
	{ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
737
	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
738
	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
739
	{ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
740
	{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
741
	{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
742
	{ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
743
	{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
744
	{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
745
	{ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
746
	{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
747
	{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
748
	{ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
749
	{ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
750

751
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
752
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
753
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
754
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
755
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
756
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
757
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
758
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
759
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
760
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
761
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
762
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
763
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
764
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
765
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
766
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
767
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
768
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
769
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
770
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
771
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
772
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
773
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
774
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
775
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
776
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
777
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
778
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
779
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
780
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
781
	{ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
782

783
	{ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0},     // RegTo2=C_REG
784
	{ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG
785
	{ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
786
	{ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
787
	{ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
788
	{ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
789
	{ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_NONE
790
	{ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},  // RegTo2=C_REG
791
	{ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
792
	{ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
793

794
	/* VLD[1-4]/VST[1-4] */
795
	{AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
796
	{AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
797
	{AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
798
	{AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
799
	{AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
800
	{AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
801
	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
802
	{AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
803
	{AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
804
	{AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
805
	{AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
806
	{AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
807
	{AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
808
	{AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
809
	{AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
810
	{AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
811
	{AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
812
	{AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
813
	{AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
814
	{AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
815
	{AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
816
	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
817
	{AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
818
	{AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
819

820
	/* special */
821
	{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
822
	{AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
823
	{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
824
	{AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
825
	{AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
826
	{AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
827
	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0},
828
	{APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
829
	{ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
830
	{AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
831
	{ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
832
	{ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0},
833
	{ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0},
834

835
	/* encryption instructions */
836
	{AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
837
	{AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
838
	{ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
839
	{ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
840
	{ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0},
841
	{ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0},
842
	{ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
843
	{AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
844
	{AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0},
845

846
	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
847
	{obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
848
	{obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
849
	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
850
	{obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
851
	{obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
852
	{obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
853
	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
854
	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
855
	{obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},  // align code
856

857
	{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
858
}
859

860
/*
861
 * valid pstate field values, and value to use in instruction
862
 */
863
var pstatefield = []struct {
864
	reg int16
865
	enc uint32
866
}{
867
	{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
868
	{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
869
	{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
870
}
871

872
var prfopfield = []struct {
873
	reg int16
874
	enc uint32
875
}{
876
	{REG_PLDL1KEEP, 0},
877
	{REG_PLDL1STRM, 1},
878
	{REG_PLDL2KEEP, 2},
879
	{REG_PLDL2STRM, 3},
880
	{REG_PLDL3KEEP, 4},
881
	{REG_PLDL3STRM, 5},
882
	{REG_PLIL1KEEP, 8},
883
	{REG_PLIL1STRM, 9},
884
	{REG_PLIL2KEEP, 10},
885
	{REG_PLIL2STRM, 11},
886
	{REG_PLIL3KEEP, 12},
887
	{REG_PLIL3STRM, 13},
888
	{REG_PSTL1KEEP, 16},
889
	{REG_PSTL1STRM, 17},
890
	{REG_PSTL2KEEP, 18},
891
	{REG_PSTL2STRM, 19},
892
	{REG_PSTL3KEEP, 20},
893
	{REG_PSTL3STRM, 21},
894
}
895

896
// Used for padinng NOOP instruction
897
const OP_NOOP = 0xd503201f
898

899
// align code to a certain length by padding bytes.
900
func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int {
901
	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
902
		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
903
	}
904
	return int(-pc & (alignedValue - 1))
905
}
906

907
func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
908
	if ctxt.Retpoline {
909
		ctxt.Diag("-spectre=ret not supported on arm64")
910
		ctxt.Retpoline = false // don't keep printing
911
	}
912

913
	p := cursym.Func.Text
914
	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
915
		return
916
	}
917

918
	if oprange[AAND&obj.AMask] == nil {
919
		ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
920
	}
921

922
	c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
923
	p.To.Offset &= 0xffffffff // extrasize is no longer needed
924

925
	bflag := 1
926
	pc := int64(0)
927
	p.Pc = pc
928
	var m int
929
	var o *Optab
930
	for p = p.Link; p != nil; p = p.Link {
931
		if p.As == ADWORD && (pc&7) != 0 {
932
			pc += 4
933
		}
934
		p.Pc = pc
935
		o = c.oplook(p)
936
		m = int(o.size)
937
		if m == 0 {
938
			switch p.As {
939
			case obj.APCALIGN:
940
				alignedValue := p.From.Offset
941
				m = pcAlignPadLength(pc, alignedValue, ctxt)
942
				// Update the current text symbol alignment value.
943
				if int32(alignedValue) > cursym.Func.Align {
944
					cursym.Func.Align = int32(alignedValue)
945
				}
946
				break
947
			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
948
				continue
949
			default:
950
				c.ctxt.Diag("zero-width instruction\n%v", p)
951
			}
952
		}
953
		switch o.flag & (LFROM | LTO) {
954
		case LFROM:
955
			c.addpool(p, &p.From)
956

957
		case LTO:
958
			c.addpool(p, &p.To)
959
			break
960
		}
961

962
		if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
963
			c.checkpool(p, 0)
964
		}
965
		pc += int64(m)
966
		if c.blitrl != nil {
967
			c.checkpool(p, 1)
968
		}
969
	}
970

971
	c.cursym.Size = pc
972

973
	/*
974
	 * if any procedure is large enough to
975
	 * generate a large SBRA branch, then
976
	 * generate extra passes putting branches
977
	 * around jmps to fix. this is rare.
978
	 */
979
	for bflag != 0 {
980
		bflag = 0
981
		pc = 0
982
		for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
983
			if p.As == ADWORD && (pc&7) != 0 {
984
				pc += 4
985
			}
986
			p.Pc = pc
987
			o = c.oplook(p)
988

989
			/* very large branches */
990
			if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.To.Target() != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
991
				otxt := p.To.Target().Pc - pc
992
				var toofar bool
993
				switch o.type_ {
994
				case 7, 39: // branch instruction encodes 19 bits
995
					toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
996
				case 40: // branch instruction encodes 14 bits
997
					toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
998
				}
999
				if toofar {
1000
					q := c.newprog()
1001
					q.Link = p.Link
1002
					p.Link = q
1003
					q.As = AB
1004
					q.To.Type = obj.TYPE_BRANCH
1005
					q.To.SetTarget(p.To.Target())
1006
					p.To.SetTarget(q)
1007
					q = c.newprog()
1008
					q.Link = p.Link
1009
					p.Link = q
1010
					q.As = AB
1011
					q.To.Type = obj.TYPE_BRANCH
1012
					q.To.SetTarget(q.Link.Link)
1013
					bflag = 1
1014
				}
1015
			}
1016
			m = int(o.size)
1017

1018
			if m == 0 {
1019
				switch p.As {
1020
				case obj.APCALIGN:
1021
					alignedValue := p.From.Offset
1022
					m = pcAlignPadLength(pc, alignedValue, ctxt)
1023
					break
1024
				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1025
					continue
1026
				default:
1027
					c.ctxt.Diag("zero-width instruction\n%v", p)
1028
				}
1029
			}
1030

1031
			pc += int64(m)
1032
		}
1033
	}
1034

1035
	pc += -pc & (funcAlign - 1)
1036
	c.cursym.Size = pc
1037

1038
	/*
1039
	 * lay out the code, emitting code and data relocations.
1040
	 */
1041
	c.cursym.Grow(c.cursym.Size)
1042
	bp := c.cursym.P
1043
	psz := int32(0)
1044
	var i int
1045
	var out [6]uint32
1046
	for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
1047
		c.pc = p.Pc
1048
		o = c.oplook(p)
1049

1050
		// need to align DWORDs on 8-byte boundary. The ISA doesn't
1051
		// require it, but the various 64-bit loads we generate assume it.
1052
		if o.as == ADWORD && psz%8 != 0 {
1053
			bp[3] = 0
1054
			bp[2] = bp[3]
1055
			bp[1] = bp[2]
1056
			bp[0] = bp[1]
1057
			bp = bp[4:]
1058
			psz += 4
1059
		}
1060

1061
		if int(o.size) > 4*len(out) {
1062
			log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
1063
		}
1064
		if p.As == obj.APCALIGN {
1065
			alignedValue := p.From.Offset
1066
			v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt)
1067
			for i = 0; i < int(v/4); i++ {
1068
				// emit ANOOP instruction by the padding size
1069
				c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
1070
				bp = bp[4:]
1071
				psz += 4
1072
			}
1073
		} else {
1074
			c.asmout(p, o, out[:])
1075
			for i = 0; i < int(o.size/4); i++ {
1076
				c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
1077
				bp = bp[4:]
1078
				psz += 4
1079
			}
1080
		}
1081
	}
1082

1083
	// Mark nonpreemptible instruction sequences.
1084
	// We use REGTMP as a scratch register during call injection,
1085
	// so instruction sequences that use REGTMP are unsafe to
1086
	// preempt asynchronously.
1087
	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
1088
}
1089

1090
// isUnsafePoint returns whether p is an unsafe point.
1091
func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
1092
	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
1093
	// preemption sequence clobbers REGTMP.
1094
	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
1095
}
1096

1097
// isRestartable returns whether p is a multi-instruction sequence that,
1098
// if preempted, can be restarted.
1099
func (c *ctxt7) isRestartable(p *obj.Prog) bool {
1100
	if c.isUnsafePoint(p) {
1101
		return false
1102
	}
1103
	// If p is a multi-instruction sequence with uses REGTMP inserted by
1104
	// the assembler in order to materialize a large constant/offset, we
1105
	// can restart p (at the start of the instruction sequence), recompute
1106
	// the content of REGTMP, upon async preemption. Currently, all cases
1107
	// of assembler-inserted REGTMP fall into this category.
1108
	// If p doesn't use REGTMP, it can be simply preempted, so we don't
1109
	// mark it.
1110
	o := c.oplook(p)
1111
	return o.size > 4 && o.flag&NOTUSETMP == 0
1112
}
1113

1114
/*
1115
 * when the first reference to the literal pool threatens
1116
 * to go out of range of a 1Mb PC-relative offset
1117
 * drop the pool now, and branch round it.
1118
 */
1119
func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
1120
	if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
1121
		c.flushpool(p, skip)
1122
	} else if p.Link == nil {
1123
		c.flushpool(p, 2)
1124
	}
1125
}
1126

1127
func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
1128
	if c.blitrl != nil {
1129
		if skip != 0 {
1130
			if c.ctxt.Debugvlog && skip == 1 {
1131
				fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
1132
			}
1133
			q := c.newprog()
1134
			q.As = AB
1135
			q.To.Type = obj.TYPE_BRANCH
1136
			q.To.SetTarget(p.Link)
1137
			q.Link = c.blitrl
1138
			q.Pos = p.Pos
1139
			c.blitrl = q
1140
		} else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
1141
			return
1142
		}
1143

1144
		// The line number for constant pool entries doesn't really matter.
1145
		// We set it to the line number of the preceding instruction so that
1146
		// there are no deltas to encode in the pc-line tables.
1147
		for q := c.blitrl; q != nil; q = q.Link {
1148
			q.Pos = p.Pos
1149
		}
1150

1151
		c.elitrl.Link = p.Link
1152
		p.Link = c.blitrl
1153

1154
		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
1155
		c.elitrl = nil
1156
		c.pool.size = 0
1157
		c.pool.start = 0
1158
	}
1159
}
1160

1161
/*
1162
 * MOVD foo(SB), R is actually
1163
 *   MOVD addr, REGTMP
1164
 *   MOVD REGTMP, R
1165
 * where addr is the address of the DWORD containing the address of foo.
1166
 *
1167
 * TODO: hash
1168
 */
1169
func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
1170
	cls := c.aclass(a)
1171
	lit := c.instoffset
1172
	t := c.newprog()
1173
	t.As = AWORD
1174
	sz := 4
1175

1176
	if a.Type == obj.TYPE_CONST {
1177
		if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
1178
			// out of range -0x80000000 ~ 0xffffffff, must store 64-bit
1179
			t.As = ADWORD
1180
			sz = 8
1181
		} // else store 32-bit
1182
	} 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)) {
1183
		// conservative: don't know if we want signed or unsigned extension.
1184
		// in case of ambiguity, store 64-bit
1185
		t.As = ADWORD
1186
		sz = 8
1187
	}
1188

1189
	switch cls {
1190
	// TODO(aram): remove.
1191
	default:
1192
		if a.Name != obj.NAME_EXTERN {
1193
			fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p)
1194
		}
1195

1196
		t.To.Offset = a.Offset
1197
		t.To.Sym = a.Sym
1198
		t.To.Type = a.Type
1199
		t.To.Name = a.Name
1200

1201
	/* This is here because MOV uint12<<12, R is disabled in optab.
1202
	Because of this, we need to load the constant from memory. */
1203
	case C_ADDCON:
1204
		fallthrough
1205

1206
	case C_ZAUTO,
1207
		C_PSAUTO,
1208
		C_PSAUTO_8,
1209
		C_PSAUTO_4,
1210
		C_PPAUTO,
1211
		C_UAUTO4K_8,
1212
		C_UAUTO4K_4,
1213
		C_UAUTO4K_2,
1214
		C_UAUTO4K,
1215
		C_UAUTO8K_8,
1216
		C_UAUTO8K_4,
1217
		C_UAUTO8K,
1218
		C_UAUTO16K_8,
1219
		C_UAUTO16K,
1220
		C_UAUTO32K,
1221
		C_NSAUTO_8,
1222
		C_NSAUTO_4,
1223
		C_NSAUTO,
1224
		C_NPAUTO,
1225
		C_NAUTO4K,
1226
		C_LAUTO,
1227
		C_PPOREG,
1228
		C_PSOREG,
1229
		C_PSOREG_4,
1230
		C_PSOREG_8,
1231
		C_UOREG4K_8,
1232
		C_UOREG4K_4,
1233
		C_UOREG4K_2,
1234
		C_UOREG4K,
1235
		C_UOREG8K_8,
1236
		C_UOREG8K_4,
1237
		C_UOREG8K,
1238
		C_UOREG16K_8,
1239
		C_UOREG16K,
1240
		C_UOREG32K,
1241
		C_NSOREG_8,
1242
		C_NSOREG_4,
1243
		C_NSOREG,
1244
		C_NPOREG,
1245
		C_NOREG4K,
1246
		C_LOREG,
1247
		C_LACON,
1248
		C_ADDCON2,
1249
		C_LCON,
1250
		C_VCON:
1251
		if a.Name == obj.NAME_EXTERN {
1252
			fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p)
1253
		}
1254

1255
		t.To.Type = obj.TYPE_CONST
1256
		t.To.Offset = lit
1257
		break
1258
	}
1259

1260
	for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
1261
		if q.To == t.To {
1262
			p.Pool = q
1263
			return
1264
		}
1265
	}
1266

1267
	q := c.newprog()
1268
	*q = *t
1269
	q.Pc = int64(c.pool.size)
1270
	if c.blitrl == nil {
1271
		c.blitrl = q
1272
		c.pool.start = uint32(p.Pc)
1273
	} else {
1274
		c.elitrl.Link = q
1275
	}
1276
	c.elitrl = q
1277
	c.pool.size = -c.pool.size & (funcAlign - 1)
1278
	c.pool.size += uint32(sz)
1279
	p.Pool = q
1280
}
1281

1282
func (c *ctxt7) regoff(a *obj.Addr) uint32 {
1283
	c.instoffset = 0
1284
	c.aclass(a)
1285
	return uint32(c.instoffset)
1286
}
1287

1288
func isSTLXRop(op obj.As) bool {
1289
	switch op {
1290
	case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
1291
		ASTXR, ASTXRW, ASTXRB, ASTXRH:
1292
		return true
1293
	}
1294
	return false
1295
}
1296

1297
func isSTXPop(op obj.As) bool {
1298
	switch op {
1299
	case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
1300
		return true
1301
	}
1302
	return false
1303
}
1304

1305
func isANDop(op obj.As) bool {
1306
	switch op {
1307
	case AAND, AORR, AEOR, AANDS, ATST,
1308
		ABIC, AEON, AORN, ABICS:
1309
		return true
1310
	}
1311
	return false
1312
}
1313

1314
func isANDWop(op obj.As) bool {
1315
	switch op {
1316
	case AANDW, AORRW, AEORW, AANDSW, ATSTW,
1317
		ABICW, AEONW, AORNW, ABICSW:
1318
		return true
1319
	}
1320
	return false
1321
}
1322

1323
func isADDop(op obj.As) bool {
1324
	switch op {
1325
	case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
1326
		return true
1327
	}
1328
	return false
1329
}
1330

1331
func isADDWop(op obj.As) bool {
1332
	switch op {
1333
	case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
1334
		return true
1335
	}
1336
	return false
1337
}
1338

1339
func isRegShiftOrExt(a *obj.Addr) bool {
1340
	return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
1341
}
1342

1343
// Maximum PC-relative displacement.
1344
// The actual limit is ±2²⁰, but we are conservative
1345
// to avoid needing to recompute the literal pool flush points
1346
// as span-dependent jumps are enlarged.
1347
const maxPCDisp = 512 * 1024
1348

1349
// ispcdisp reports whether v is a valid PC-relative displacement.
1350
func ispcdisp(v int32) bool {
1351
	return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
1352
}
1353

1354
func isaddcon(v int64) bool {
1355
	/* uimm12 or uimm24? */
1356
	if v < 0 {
1357
		return false
1358
	}
1359
	if (v & 0xFFF) == 0 {
1360
		v >>= 12
1361
	}
1362
	return v <= 0xFFF
1363
}
1364

1365
func isaddcon2(v int64) bool {
1366
	return 0 <= v && v <= 0xFFFFFF
1367
}
1368

1369
// isbitcon reports whether a constant can be encoded into a logical instruction.
1370
// bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
1371
// which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
1372
// special cases: 0 and -1 are not bitcon.
1373
// this function needs to run against virtually all the constants, so it needs to be fast.
1374
// for this reason, bitcon testing and bitcon encoding are separate functions.
1375
func isbitcon(x uint64) bool {
1376
	if x == 1<<64-1 || x == 0 {
1377
		return false
1378
	}
1379
	// determine the period and sign-extend a unit to 64 bits
1380
	switch {
1381
	case x != x>>32|x<<32:
1382
		// period is 64
1383
		// nothing to do
1384
	case x != x>>16|x<<48:
1385
		// period is 32
1386
		x = uint64(int64(int32(x)))
1387
	case x != x>>8|x<<56:
1388
		// period is 16
1389
		x = uint64(int64(int16(x)))
1390
	case x != x>>4|x<<60:
1391
		// period is 8
1392
		x = uint64(int64(int8(x)))
1393
	default:
1394
		// period is 4 or 2, always true
1395
		// 0001, 0010, 0100, 1000 -- 0001 rotate
1396
		// 0011, 0110, 1100, 1001 -- 0011 rotate
1397
		// 0111, 1011, 1101, 1110 -- 0111 rotate
1398
		// 0101, 1010             -- 01   rotate, repeat
1399
		return true
1400
	}
1401
	return sequenceOfOnes(x) || sequenceOfOnes(^x)
1402
}
1403

1404
// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
1405
func sequenceOfOnes(x uint64) bool {
1406
	y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
1407
	y += x
1408
	return (y-1)&y == 0
1409
}
1410

1411
// bitconEncode returns the encoding of a bitcon used in logical instructions
1412
// x is known to be a bitcon
1413
// a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
1414
// by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
1415
// it is encoded in logical instructions with 3 bitfields
1416
// N (1 bit) : R (6 bits) : S (6 bits), where
1417
// N=1           -- period=64
1418
// N=0, S=0xxxxx -- period=32
1419
// N=0, S=10xxxx -- period=16
1420
// N=0, S=110xxx -- period=8
1421
// N=0, S=1110xx -- period=4
1422
// N=0, S=11110x -- period=2
1423
// R is the shift amount, low bits of S = n-1
1424
func bitconEncode(x uint64, mode int) uint32 {
1425
	var period uint32
1426
	// determine the period and sign-extend a unit to 64 bits
1427
	switch {
1428
	case x != x>>32|x<<32:
1429
		period = 64
1430
	case x != x>>16|x<<48:
1431
		period = 32
1432
		x = uint64(int64(int32(x)))
1433
	case x != x>>8|x<<56:
1434
		period = 16
1435
		x = uint64(int64(int16(x)))
1436
	case x != x>>4|x<<60:
1437
		period = 8
1438
		x = uint64(int64(int8(x)))
1439
	case x != x>>2|x<<62:
1440
		period = 4
1441
		x = uint64(int64(x<<60) >> 60)
1442
	default:
1443
		period = 2
1444
		x = uint64(int64(x<<62) >> 62)
1445
	}
1446
	neg := false
1447
	if int64(x) < 0 {
1448
		x = ^x
1449
		neg = true
1450
	}
1451
	y := x & -x // lowest set bit of x.
1452
	s := log2(y)
1453
	n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
1454
	if neg {
1455
		// ^x is a sequence of n ones left shifted by s bits
1456
		// adjust n, s for x
1457
		s = n + s
1458
		n = period - n
1459
	}
1460

1461
	N := uint32(0)
1462
	if mode == 64 && period == 64 {
1463
		N = 1
1464
	}
1465
	R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
1466
	S := (n - 1) | 63&^(period<<1-1)                  // low bits = #ones - 1, high bits encodes period
1467
	return N<<22 | R<<16 | S<<10
1468
}
1469

1470
func log2(x uint64) uint32 {
1471
	if x == 0 {
1472
		panic("log2 of 0")
1473
	}
1474
	n := uint32(0)
1475
	if x >= 1<<32 {
1476
		x >>= 32
1477
		n += 32
1478
	}
1479
	if x >= 1<<16 {
1480
		x >>= 16
1481
		n += 16
1482
	}
1483
	if x >= 1<<8 {
1484
		x >>= 8
1485
		n += 8
1486
	}
1487
	if x >= 1<<4 {
1488
		x >>= 4
1489
		n += 4
1490
	}
1491
	if x >= 1<<2 {
1492
		x >>= 2
1493
		n += 2
1494
	}
1495
	if x >= 1<<1 {
1496
		x >>= 1
1497
		n += 1
1498
	}
1499
	return n
1500
}
1501

1502
func autoclass(l int64) int {
1503
	if l == 0 {
1504
		return C_ZAUTO
1505
	}
1506

1507
	if l < 0 {
1508
		if l >= -256 && (l&7) == 0 {
1509
			return C_NSAUTO_8
1510
		}
1511
		if l >= -256 && (l&3) == 0 {
1512
			return C_NSAUTO_4
1513
		}
1514
		if l >= -256 {
1515
			return C_NSAUTO
1516
		}
1517
		if l >= -512 && (l&7) == 0 {
1518
			return C_NPAUTO
1519
		}
1520
		if l >= -4095 {
1521
			return C_NAUTO4K
1522
		}
1523
		return C_LAUTO
1524
	}
1525

1526
	if l <= 255 {
1527
		if (l & 7) == 0 {
1528
			return C_PSAUTO_8
1529
		}
1530
		if (l & 3) == 0 {
1531
			return C_PSAUTO_4
1532
		}
1533
		return C_PSAUTO
1534
	}
1535
	if l <= 504 && l&7 == 0 {
1536
		return C_PPAUTO
1537
	}
1538
	if l <= 4095 {
1539
		if l&7 == 0 {
1540
			return C_UAUTO4K_8
1541
		}
1542
		if l&3 == 0 {
1543
			return C_UAUTO4K_4
1544
		}
1545
		if l&1 == 0 {
1546
			return C_UAUTO4K_2
1547
		}
1548
		return C_UAUTO4K
1549
	}
1550
	if l <= 8190 {
1551
		if l&7 == 0 {
1552
			return C_UAUTO8K_8
1553
		}
1554
		if l&3 == 0 {
1555
			return C_UAUTO8K_4
1556
		}
1557
		if l&1 == 0 {
1558
			return C_UAUTO8K
1559
		}
1560
	}
1561
	if l <= 16380 {
1562
		if l&7 == 0 {
1563
			return C_UAUTO16K_8
1564
		}
1565
		if l&3 == 0 {
1566
			return C_UAUTO16K
1567
		}
1568
	}
1569
	if l <= 32760 && (l&7) == 0 {
1570
		return C_UAUTO32K
1571
	}
1572
	return C_LAUTO
1573
}
1574

1575
func oregclass(l int64) int {
1576
	return autoclass(l) - C_ZAUTO + C_ZOREG
1577
}
1578

1579
/*
1580
 * given an offset v and a class c (see above)
1581
 * return the offset value to use in the instruction,
1582
 * scaled if necessary
1583
 */
1584
func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
1585
	s := 0
1586
	if cls >= C_SEXT1 && cls <= C_SEXT16 {
1587
		s = cls - C_SEXT1
1588
	} else {
1589
		switch cls {
1590
		case C_UAUTO4K, C_UOREG4K, C_ZOREG:
1591
			s = 0
1592
		case C_UAUTO8K, C_UOREG8K:
1593
			s = 1
1594
		case C_UAUTO16K, C_UOREG16K:
1595
			s = 2
1596
		case C_UAUTO32K, C_UOREG32K:
1597
			s = 3
1598
		default:
1599
			c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
1600
		}
1601
	}
1602
	vs := v >> uint(s)
1603
	if vs<<uint(s) != v {
1604
		c.ctxt.Diag("odd offset: %d\n%v", v, p)
1605
	}
1606
	return vs
1607
}
1608

1609
/*
1610
 * if v contains a single 16-bit value aligned
1611
 * on a 16-bit field, and thus suitable for movk/movn,
1612
 * return the field index 0 to 3; otherwise return -1
1613
 */
1614
func movcon(v int64) int {
1615
	for s := 0; s < 64; s += 16 {
1616
		if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
1617
			return s / 16
1618
		}
1619
	}
1620
	return -1
1621
}
1622

1623
func rclass(r int16) int {
1624
	switch {
1625
	case REG_R0 <= r && r <= REG_R30: // not 31
1626
		return C_REG
1627
	case r == REGZERO:
1628
		return C_ZCON
1629
	case REG_F0 <= r && r <= REG_F31:
1630
		return C_FREG
1631
	case REG_V0 <= r && r <= REG_V31:
1632
		return C_VREG
1633
	case COND_EQ <= r && r <= COND_NV:
1634
		return C_COND
1635
	case r == REGSP:
1636
		return C_RSP
1637
	case r >= REG_ARNG && r < REG_ELEM:
1638
		return C_ARNG
1639
	case r >= REG_ELEM && r < REG_ELEM_END:
1640
		return C_ELEM
1641
	case r >= REG_UXTB && r < REG_SPECIAL:
1642
		return C_EXTREG
1643
	case r >= REG_SPECIAL:
1644
		return C_SPR
1645
	}
1646
	return C_GOK
1647
}
1648

1649
// con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
1650
// but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
1651
func (c *ctxt7) con32class(a *obj.Addr) int {
1652
	v := uint32(a.Offset)
1653
	if v == 0 {
1654
		return C_ZCON
1655
	}
1656
	if isaddcon(int64(v)) {
1657
		if v <= 0xFFF {
1658
			if isbitcon(uint64(a.Offset)) {
1659
				return C_ABCON0
1660
			}
1661
			return C_ADDCON0
1662
		}
1663
		if isbitcon(uint64(a.Offset)) {
1664
			return C_ABCON
1665
		}
1666
		if movcon(int64(v)) >= 0 {
1667
			return C_AMCON
1668
		}
1669
		if movcon(int64(^v)) >= 0 {
1670
			return C_AMCON
1671
		}
1672
		return C_ADDCON
1673
	}
1674

1675
	t := movcon(int64(v))
1676
	if t >= 0 {
1677
		if isbitcon(uint64(a.Offset)) {
1678
			return C_MBCON
1679
		}
1680
		return C_MOVCON
1681
	}
1682

1683
	t = movcon(int64(^v))
1684
	if t >= 0 {
1685
		if isbitcon(uint64(a.Offset)) {
1686
			return C_MBCON
1687
		}
1688
		return C_MOVCON
1689
	}
1690

1691
	if isbitcon(uint64(a.Offset)) {
1692
		return C_BITCON
1693
	}
1694

1695
	if 0 <= v && v <= 0xffffff {
1696
		return C_ADDCON2
1697
	}
1698
	return C_LCON
1699
}
1700

1701
// con64class reclassifies the constant of C_VCON and C_LCON class.
1702
func (c *ctxt7) con64class(a *obj.Addr) int {
1703
	zeroCount := 0
1704
	negCount := 0
1705
	for i := uint(0); i < 4; i++ {
1706
		immh := uint32(a.Offset >> (i * 16) & 0xffff)
1707
		if immh == 0 {
1708
			zeroCount++
1709
		} else if immh == 0xffff {
1710
			negCount++
1711
		}
1712
	}
1713
	if zeroCount >= 3 || negCount >= 3 {
1714
		return C_MOVCON
1715
	} else if zeroCount == 2 || negCount == 2 {
1716
		return C_MOVCON2
1717
	} else if zeroCount == 1 || negCount == 1 {
1718
		return C_MOVCON3
1719
	} else {
1720
		return C_VCON
1721
	}
1722
}
1723

1724
func (c *ctxt7) aclass(a *obj.Addr) int {
1725
	switch a.Type {
1726
	case obj.TYPE_NONE:
1727
		return C_NONE
1728

1729
	case obj.TYPE_REG:
1730
		return rclass(a.Reg)
1731

1732
	case obj.TYPE_REGREG:
1733
		return C_PAIR
1734

1735
	case obj.TYPE_SHIFT:
1736
		return C_SHIFT
1737

1738
	case obj.TYPE_REGLIST:
1739
		return C_LIST
1740

1741
	case obj.TYPE_MEM:
1742
		// The base register should be an integer register.
1743
		if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
1744
			break
1745
		}
1746
		switch a.Name {
1747
		case obj.NAME_EXTERN, obj.NAME_STATIC:
1748
			if a.Sym == nil {
1749
				break
1750
			}
1751
			c.instoffset = a.Offset
1752
			if a.Sym != nil { // use relocation
1753
				if a.Sym.Type == objabi.STLSBSS {
1754
					if c.ctxt.Flag_shared {
1755
						return C_TLS_IE
1756
					} else {
1757
						return C_TLS_LE
1758
					}
1759
				}
1760
				return C_ADDR
1761
			}
1762
			return C_LEXT
1763

1764
		case obj.NAME_GOTREF:
1765
			return C_GOTADDR
1766

1767
		case obj.NAME_AUTO:
1768
			if a.Reg == REGSP {
1769
				// unset base register for better printing, since
1770
				// a.Offset is still relative to pseudo-SP.
1771
				a.Reg = obj.REG_NONE
1772
			}
1773
			// The frame top 8 or 16 bytes are for FP
1774
			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
1775
			return autoclass(c.instoffset)
1776

1777
		case obj.NAME_PARAM:
1778
			if a.Reg == REGSP {
1779
				// unset base register for better printing, since
1780
				// a.Offset is still relative to pseudo-FP.
1781
				a.Reg = obj.REG_NONE
1782
			}
1783
			c.instoffset = int64(c.autosize) + a.Offset + 8
1784
			return autoclass(c.instoffset)
1785

1786
		case obj.NAME_NONE:
1787
			if a.Index != 0 {
1788
				if a.Offset != 0 {
1789
					if isRegShiftOrExt(a) {
1790
						// extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
1791
						return C_ROFF
1792
					}
1793
					return C_GOK
1794
				}
1795
				// register offset, (Rn)(Rm)
1796
				return C_ROFF
1797
			}
1798
			c.instoffset = a.Offset
1799
			return oregclass(c.instoffset)
1800
		}
1801
		return C_GOK
1802

1803
	case obj.TYPE_FCONST:
1804
		return C_FCON
1805

1806
	case obj.TYPE_TEXTSIZE:
1807
		return C_TEXTSIZE
1808

1809
	case obj.TYPE_CONST, obj.TYPE_ADDR:
1810
		switch a.Name {
1811
		case obj.NAME_NONE:
1812
			c.instoffset = a.Offset
1813
			if a.Reg != 0 && a.Reg != REGZERO {
1814
				break
1815
			}
1816
			v := c.instoffset
1817
			if v == 0 {
1818
				return C_ZCON
1819
			}
1820
			if isaddcon(v) {
1821
				if v <= 0xFFF {
1822
					if isbitcon(uint64(v)) {
1823
						return C_ABCON0
1824
					}
1825
					return C_ADDCON0
1826
				}
1827
				if isbitcon(uint64(v)) {
1828
					return C_ABCON
1829
				}
1830
				if movcon(v) >= 0 {
1831
					return C_AMCON
1832
				}
1833
				if movcon(^v) >= 0 {
1834
					return C_AMCON
1835
				}
1836
				return C_ADDCON
1837
			}
1838

1839
			t := movcon(v)
1840
			if t >= 0 {
1841
				if isbitcon(uint64(v)) {
1842
					return C_MBCON
1843
				}
1844
				return C_MOVCON
1845
			}
1846

1847
			t = movcon(^v)
1848
			if t >= 0 {
1849
				if isbitcon(uint64(v)) {
1850
					return C_MBCON
1851
				}
1852
				return C_MOVCON
1853
			}
1854

1855
			if isbitcon(uint64(v)) {
1856
				return C_BITCON
1857
			}
1858

1859
			if 0 <= v && v <= 0xffffff {
1860
				return C_ADDCON2
1861
			}
1862

1863
			if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
1864
				return C_LCON
1865
			}
1866
			return C_VCON
1867

1868
		case obj.NAME_EXTERN, obj.NAME_STATIC:
1869
			if a.Sym == nil {
1870
				return C_GOK
1871
			}
1872
			if a.Sym.Type == objabi.STLSBSS {
1873
				c.ctxt.Diag("taking address of TLS variable is not supported")
1874
			}
1875
			c.instoffset = a.Offset
1876
			return C_VCONADDR
1877

1878
		case obj.NAME_AUTO:
1879
			if a.Reg == REGSP {
1880
				// unset base register for better printing, since
1881
				// a.Offset is still relative to pseudo-SP.
1882
				a.Reg = obj.REG_NONE
1883
			}
1884
			// The frame top 8 or 16 bytes are for FP
1885
			c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
1886

1887
		case obj.NAME_PARAM:
1888
			if a.Reg == REGSP {
1889
				// unset base register for better printing, since
1890
				// a.Offset is still relative to pseudo-FP.
1891
				a.Reg = obj.REG_NONE
1892
			}
1893
			c.instoffset = int64(c.autosize) + a.Offset + 8
1894
		default:
1895
			return C_GOK
1896
		}
1897
		cf := c.instoffset
1898
		if isaddcon(cf) || isaddcon(-cf) {
1899
			return C_AACON
1900
		}
1901
		if isaddcon2(cf) {
1902
			return C_AACON2
1903
		}
1904

1905
		return C_LACON
1906

1907
	case obj.TYPE_BRANCH:
1908
		return C_SBRA
1909
	}
1910

1911
	return C_GOK
1912
}
1913

1914
func oclass(a *obj.Addr) int {
1915
	return int(a.Class) - 1
1916
}
1917

1918
func (c *ctxt7) oplook(p *obj.Prog) *Optab {
1919
	a1 := int(p.Optab)
1920
	if a1 != 0 {
1921
		return &optab[a1-1]
1922
	}
1923
	a1 = int(p.From.Class)
1924
	if a1 == 0 {
1925
		a0 := c.aclass(&p.From)
1926
		// do not break C_ADDCON2 when S bit is set
1927
		if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
1928
			a0 = C_LCON
1929
		}
1930
		a1 = a0 + 1
1931
		p.From.Class = int8(a1)
1932
		// more specific classification of 32-bit integers
1933
		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
1934
			if p.As == AMOVW || isADDWop(p.As) {
1935
				ra0 := c.con32class(&p.From)
1936
				// do not break C_ADDCON2 when S bit is set
1937
				if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
1938
					ra0 = C_LCON
1939
				}
1940
				a1 = ra0 + 1
1941
				p.From.Class = int8(a1)
1942
			}
1943
			if isANDWop(p.As) && a0 != C_BITCON {
1944
				// For 32-bit logical instruction with constant,
1945
				// the BITCON test is special in that it looks at
1946
				// the 64-bit which has the high 32-bit as a copy
1947
				// of the low 32-bit. We have handled that and
1948
				// don't pass it to con32class.
1949
				a1 = c.con32class(&p.From) + 1
1950
				p.From.Class = int8(a1)
1951
			}
1952
			if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
1953
				a1 = c.con64class(&p.From) + 1
1954
				p.From.Class = int8(a1)
1955
			}
1956
		}
1957
	}
1958

1959
	a1--
1960
	a3 := C_NONE + 1
1961
	if p.GetFrom3() != nil {
1962
		a3 = int(p.GetFrom3().Class)
1963
		if a3 == 0 {
1964
			a3 = c.aclass(p.GetFrom3()) + 1
1965
			p.GetFrom3().Class = int8(a3)
1966
		}
1967
	}
1968

1969
	a3--
1970
	a4 := int(p.To.Class)
1971
	if a4 == 0 {
1972
		a4 = c.aclass(&p.To) + 1
1973
		p.To.Class = int8(a4)
1974
	}
1975

1976
	a4--
1977
	a2 := C_NONE
1978
	if p.Reg != 0 {
1979
		a2 = rclass(p.Reg)
1980
	}
1981

1982
	if false {
1983
		fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
1984
		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
1985
	}
1986

1987
	ops := oprange[p.As&obj.AMask]
1988
	c1 := &xcmp[a1]
1989
	c2 := &xcmp[a2]
1990
	c3 := &xcmp[a3]
1991
	c4 := &xcmp[a4]
1992
	c5 := &xcmp[p.Scond>>5]
1993
	for i := range ops {
1994
		op := &ops[i]
1995
		if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
1996
			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
1997
			return op
1998
		}
1999
	}
2000

2001
	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)
2002
	// Turn illegal instruction into an UNDEF, avoid crashing in asmout
2003
	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
2004
}
2005

2006
func cmp(a int, b int) bool {
2007
	if a == b {
2008
		return true
2009
	}
2010
	switch a {
2011
	case C_RSP:
2012
		if b == C_REG {
2013
			return true
2014
		}
2015

2016
	case C_REG:
2017
		if b == C_ZCON {
2018
			return true
2019
		}
2020

2021
	case C_ADDCON0:
2022
		if b == C_ZCON || b == C_ABCON0 {
2023
			return true
2024
		}
2025

2026
	case C_ADDCON:
2027
		if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
2028
			return true
2029
		}
2030

2031
	case C_BITCON:
2032
		if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
2033
			return true
2034
		}
2035

2036
	case C_MOVCON:
2037
		if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
2038
			return true
2039
		}
2040

2041
	case C_ADDCON2:
2042
		if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
2043
			return true
2044
		}
2045

2046
	case C_LCON:
2047
		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 {
2048
			return true
2049
		}
2050

2051
	case C_MOVCON2:
2052
		return cmp(C_LCON, b)
2053

2054
	case C_VCON:
2055
		return cmp(C_LCON, b)
2056

2057
	case C_LACON:
2058
		if b == C_AACON || b == C_AACON2 {
2059
			return true
2060
		}
2061

2062
	case C_SEXT2:
2063
		if b == C_SEXT1 {
2064
			return true
2065
		}
2066

2067
	case C_SEXT4:
2068
		if b == C_SEXT1 || b == C_SEXT2 {
2069
			return true
2070
		}
2071

2072
	case C_SEXT8:
2073
		if b >= C_SEXT1 && b <= C_SEXT4 {
2074
			return true
2075
		}
2076

2077
	case C_SEXT16:
2078
		if b >= C_SEXT1 && b <= C_SEXT8 {
2079
			return true
2080
		}
2081

2082
	case C_LEXT:
2083
		if b >= C_SEXT1 && b <= C_SEXT16 {
2084
			return true
2085
		}
2086

2087
	case C_NSAUTO_4:
2088
		if b == C_NSAUTO_8 {
2089
			return true
2090
		}
2091

2092
	case C_NSAUTO:
2093
		switch b {
2094
		case C_NSAUTO_4, C_NSAUTO_8:
2095
			return true
2096
		}
2097

2098
	case C_NPAUTO:
2099
		switch b {
2100
		case C_NSAUTO_8:
2101
			return true
2102
		}
2103

2104
	case C_NAUTO4K:
2105
		switch b {
2106
		case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO:
2107
			return true
2108
		}
2109

2110
	case C_PSAUTO_8:
2111
		if b == C_ZAUTO {
2112
			return true
2113
		}
2114

2115
	case C_PSAUTO_4:
2116
		switch b {
2117
		case C_ZAUTO, C_PSAUTO_8:
2118
			return true
2119
		}
2120

2121
	case C_PSAUTO:
2122
		switch b {
2123
		case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4:
2124
			return true
2125
		}
2126

2127
	case C_PPAUTO:
2128
		switch b {
2129
		case C_ZAUTO, C_PSAUTO_8:
2130
			return true
2131
		}
2132

2133
	case C_UAUTO4K:
2134
		switch b {
2135
		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
2136
			C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
2137
			return true
2138
		}
2139

2140
	case C_UAUTO8K:
2141
		switch b {
2142
		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
2143
			C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
2144
			return true
2145
		}
2146

2147
	case C_UAUTO16K:
2148
		switch b {
2149
		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
2150
			C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
2151
			return true
2152
		}
2153

2154
	case C_UAUTO32K:
2155
		switch b {
2156
		case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
2157
			C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
2158
			return true
2159
		}
2160

2161
	case C_LAUTO:
2162
		switch b {
2163
		case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO,
2164
			C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
2165
			C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
2166
			C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
2167
			C_UAUTO16K, C_UAUTO16K_8,
2168
			C_UAUTO32K:
2169
			return true
2170
		}
2171

2172
	case C_NSOREG_4:
2173
		if b == C_NSOREG_8 {
2174
			return true
2175
		}
2176

2177
	case C_NSOREG:
2178
		switch b {
2179
		case C_NSOREG_4, C_NSOREG_8:
2180
			return true
2181
		}
2182

2183
	case C_NPOREG:
2184
		switch b {
2185
		case C_NSOREG_8:
2186
			return true
2187
		}
2188

2189
	case C_NOREG4K:
2190
		switch b {
2191
		case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG:
2192
			return true
2193
		}
2194

2195
	case C_PSOREG_4:
2196
		switch b {
2197
		case C_ZOREG, C_PSOREG_8:
2198
			return true
2199
		}
2200

2201
	case C_PSOREG:
2202
		switch b {
2203
		case C_ZOREG, C_PSOREG_8, C_PSOREG_4:
2204
			return true
2205
		}
2206

2207
	case C_PPOREG:
2208
		switch b {
2209
		case C_ZOREG, C_PSOREG_8:
2210
			return true
2211
		}
2212

2213
	case C_UOREG4K:
2214
		switch b {
2215
		case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
2216
			C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8:
2217
			return true
2218
		}
2219

2220
	case C_UOREG8K:
2221
		switch b {
2222
		case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
2223
			C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
2224
			C_UOREG8K_4, C_UOREG8K_8:
2225
			return true
2226
		}
2227

2228
	case C_UOREG16K:
2229
		switch b {
2230
		case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
2231
			C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4,
2232
			C_UOREG8K_8, C_UOREG16K_8:
2233
			return true
2234
		}
2235

2236
	case C_UOREG32K:
2237
		switch b {
2238
		case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
2239
			C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8:
2240
			return true
2241
		}
2242

2243
	case C_LOREG:
2244
		switch b {
2245
		case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG,
2246
			C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG,
2247
			C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
2248
			C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8,
2249
			C_UOREG16K, C_UOREG16K_8,
2250
			C_UOREG32K:
2251
			return true
2252
		}
2253

2254
	case C_LBRA:
2255
		if b == C_SBRA {
2256
			return true
2257
		}
2258
	}
2259

2260
	return false
2261
}
2262

2263
type ocmp []Optab
2264

2265
func (x ocmp) Len() int {
2266
	return len(x)
2267
}
2268

2269
func (x ocmp) Swap(i, j int) {
2270
	x[i], x[j] = x[j], x[i]
2271
}
2272

2273
func (x ocmp) Less(i, j int) bool {
2274
	p1 := &x[i]
2275
	p2 := &x[j]
2276
	if p1.as != p2.as {
2277
		return p1.as < p2.as
2278
	}
2279
	if p1.a1 != p2.a1 {
2280
		return p1.a1 < p2.a1
2281
	}
2282
	if p1.a2 != p2.a2 {
2283
		return p1.a2 < p2.a2
2284
	}
2285
	if p1.a3 != p2.a3 {
2286
		return p1.a3 < p2.a3
2287
	}
2288
	if p1.a4 != p2.a4 {
2289
		return p1.a4 < p2.a4
2290
	}
2291
	if p1.scond != p2.scond {
2292
		return p1.scond < p2.scond
2293
	}
2294
	return false
2295
}
2296

2297
func oprangeset(a obj.As, t []Optab) {
2298
	oprange[a&obj.AMask] = t
2299
}
2300

2301
func buildop(ctxt *obj.Link) {
2302
	if oprange[AAND&obj.AMask] != nil {
2303
		// Already initialized; stop now.
2304
		// This happens in the cmd/asm tests,
2305
		// each of which re-initializes the arch.
2306
		return
2307
	}
2308

2309
	var n int
2310
	for i := 0; i < C_GOK; i++ {
2311
		for n = 0; n < C_GOK; n++ {
2312
			if cmp(n, i) {
2313
				xcmp[i][n] = true
2314
			}
2315
		}
2316
	}
2317
	for n = 0; optab[n].as != obj.AXXX; n++ {
2318
	}
2319
	sort.Sort(ocmp(optab[:n]))
2320
	for i := 0; i < n; i++ {
2321
		r := optab[i].as
2322
		start := i
2323
		for optab[i].as == r {
2324
			i++
2325
		}
2326
		t := optab[start:i]
2327
		i--
2328
		oprangeset(r, t)
2329
		switch r {
2330
		default:
2331
			ctxt.Diag("unknown op in build: %v", r)
2332
			ctxt.DiagFlush()
2333
			log.Fatalf("bad code")
2334

2335
		case AADD:
2336
			oprangeset(AADDS, t)
2337
			oprangeset(ASUB, t)
2338
			oprangeset(ASUBS, t)
2339
			oprangeset(AADDW, t)
2340
			oprangeset(AADDSW, t)
2341
			oprangeset(ASUBW, t)
2342
			oprangeset(ASUBSW, t)
2343

2344
		case AAND: /* logical immediate, logical shifted register */
2345
			oprangeset(AANDW, t)
2346
			oprangeset(AEOR, t)
2347
			oprangeset(AEORW, t)
2348
			oprangeset(AORR, t)
2349
			oprangeset(AORRW, t)
2350
			oprangeset(ABIC, t)
2351
			oprangeset(ABICW, t)
2352
			oprangeset(AEON, t)
2353
			oprangeset(AEONW, t)
2354
			oprangeset(AORN, t)
2355
			oprangeset(AORNW, t)
2356

2357
		case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
2358
			oprangeset(AANDSW, t)
2359
			oprangeset(ABICS, t)
2360
			oprangeset(ABICSW, t)
2361

2362
		case ANEG:
2363
			oprangeset(ANEGS, t)
2364
			oprangeset(ANEGSW, t)
2365
			oprangeset(ANEGW, t)
2366

2367
		case AADC: /* rn=Rd */
2368
			oprangeset(AADCW, t)
2369

2370
			oprangeset(AADCS, t)
2371
			oprangeset(AADCSW, t)
2372
			oprangeset(ASBC, t)
2373
			oprangeset(ASBCW, t)
2374
			oprangeset(ASBCS, t)
2375
			oprangeset(ASBCSW, t)
2376

2377
		case ANGC: /* rn=REGZERO */
2378
			oprangeset(ANGCW, t)
2379

2380
			oprangeset(ANGCS, t)
2381
			oprangeset(ANGCSW, t)
2382

2383
		case ACMP:
2384
			oprangeset(ACMPW, t)
2385
			oprangeset(ACMN, t)
2386
			oprangeset(ACMNW, t)
2387

2388
		case ATST:
2389
			oprangeset(ATSTW, t)
2390

2391
			/* register/register, and shifted */
2392
		case AMVN:
2393
			oprangeset(AMVNW, t)
2394

2395
		case AMOVK:
2396
			oprangeset(AMOVKW, t)
2397
			oprangeset(AMOVN, t)
2398
			oprangeset(AMOVNW, t)
2399
			oprangeset(AMOVZ, t)
2400
			oprangeset(AMOVZW, t)
2401

2402
		case ASWPD:
2403
			for i := range atomicInstructions {
2404
				oprangeset(i, t)
2405
			}
2406

2407
		case ABEQ:
2408
			oprangeset(ABNE, t)
2409
			oprangeset(ABCS, t)
2410
			oprangeset(ABHS, t)
2411
			oprangeset(ABCC, t)
2412
			oprangeset(ABLO, t)
2413
			oprangeset(ABMI, t)
2414
			oprangeset(ABPL, t)
2415
			oprangeset(ABVS, t)
2416
			oprangeset(ABVC, t)
2417
			oprangeset(ABHI, t)
2418
			oprangeset(ABLS, t)
2419
			oprangeset(ABGE, t)
2420
			oprangeset(ABLT, t)
2421
			oprangeset(ABGT, t)
2422
			oprangeset(ABLE, t)
2423

2424
		case ALSL:
2425
			oprangeset(ALSLW, t)
2426
			oprangeset(ALSR, t)
2427
			oprangeset(ALSRW, t)
2428
			oprangeset(AASR, t)
2429
			oprangeset(AASRW, t)
2430
			oprangeset(AROR, t)
2431
			oprangeset(ARORW, t)
2432

2433
		case ACLS:
2434
			oprangeset(ACLSW, t)
2435
			oprangeset(ACLZ, t)
2436
			oprangeset(ACLZW, t)
2437
			oprangeset(ARBIT, t)
2438
			oprangeset(ARBITW, t)
2439
			oprangeset(AREV, t)
2440
			oprangeset(AREVW, t)
2441
			oprangeset(AREV16, t)
2442
			oprangeset(AREV16W, t)
2443
			oprangeset(AREV32, t)
2444

2445
		case ASDIV:
2446
			oprangeset(ASDIVW, t)
2447
			oprangeset(AUDIV, t)
2448
			oprangeset(AUDIVW, t)
2449
			oprangeset(ACRC32B, t)
2450
			oprangeset(ACRC32CB, t)
2451
			oprangeset(ACRC32CH, t)
2452
			oprangeset(ACRC32CW, t)
2453
			oprangeset(ACRC32CX, t)
2454
			oprangeset(ACRC32H, t)
2455
			oprangeset(ACRC32W, t)
2456
			oprangeset(ACRC32X, t)
2457

2458
		case AMADD:
2459
			oprangeset(AMADDW, t)
2460
			oprangeset(AMSUB, t)
2461
			oprangeset(AMSUBW, t)
2462
			oprangeset(ASMADDL, t)
2463
			oprangeset(ASMSUBL, t)
2464
			oprangeset(AUMADDL, t)
2465
			oprangeset(AUMSUBL, t)
2466

2467
		case AREM:
2468
			oprangeset(AREMW, t)
2469
			oprangeset(AUREM, t)
2470
			oprangeset(AUREMW, t)
2471

2472
		case AMUL:
2473
			oprangeset(AMULW, t)
2474
			oprangeset(AMNEG, t)
2475
			oprangeset(AMNEGW, t)
2476
			oprangeset(ASMNEGL, t)
2477
			oprangeset(ASMULL, t)
2478
			oprangeset(ASMULH, t)
2479
			oprangeset(AUMNEGL, t)
2480
			oprangeset(AUMULH, t)
2481
			oprangeset(AUMULL, t)
2482

2483
		case AMOVB:
2484
			oprangeset(AMOVBU, t)
2485

2486
		case AMOVH:
2487
			oprangeset(AMOVHU, t)
2488

2489
		case AMOVW:
2490
			oprangeset(AMOVWU, t)
2491

2492
		case ABFM:
2493
			oprangeset(ABFMW, t)
2494
			oprangeset(ASBFM, t)
2495
			oprangeset(ASBFMW, t)
2496
			oprangeset(AUBFM, t)
2497
			oprangeset(AUBFMW, t)
2498

2499
		case ABFI:
2500
			oprangeset(ABFIW, t)
2501
			oprangeset(ABFXIL, t)
2502
			oprangeset(ABFXILW, t)
2503
			oprangeset(ASBFIZ, t)
2504
			oprangeset(ASBFIZW, t)
2505
			oprangeset(ASBFX, t)
2506
			oprangeset(ASBFXW, t)
2507
			oprangeset(AUBFIZ, t)
2508
			oprangeset(AUBFIZW, t)
2509
			oprangeset(AUBFX, t)
2510
			oprangeset(AUBFXW, t)
2511

2512
		case AEXTR:
2513
			oprangeset(AEXTRW, t)
2514

2515
		case ASXTB:
2516
			oprangeset(ASXTBW, t)
2517
			oprangeset(ASXTH, t)
2518
			oprangeset(ASXTHW, t)
2519
			oprangeset(ASXTW, t)
2520
			oprangeset(AUXTB, t)
2521
			oprangeset(AUXTH, t)
2522
			oprangeset(AUXTW, t)
2523
			oprangeset(AUXTBW, t)
2524
			oprangeset(AUXTHW, t)
2525

2526
		case ACCMN:
2527
			oprangeset(ACCMNW, t)
2528
			oprangeset(ACCMP, t)
2529
			oprangeset(ACCMPW, t)
2530

2531
		case ACSEL:
2532
			oprangeset(ACSELW, t)
2533
			oprangeset(ACSINC, t)
2534
			oprangeset(ACSINCW, t)
2535
			oprangeset(ACSINV, t)
2536
			oprangeset(ACSINVW, t)
2537
			oprangeset(ACSNEG, t)
2538
			oprangeset(ACSNEGW, t)
2539

2540
		case ACINC:
2541
			// aliases Rm=Rn, !cond
2542
			oprangeset(ACINCW, t)
2543
			oprangeset(ACINV, t)
2544
			oprangeset(ACINVW, t)
2545
			oprangeset(ACNEG, t)
2546
			oprangeset(ACNEGW, t)
2547

2548
			// aliases, Rm=Rn=REGZERO, !cond
2549
		case ACSET:
2550
			oprangeset(ACSETW, t)
2551

2552
			oprangeset(ACSETM, t)
2553
			oprangeset(ACSETMW, t)
2554

2555
		case AMOVD,
2556
			AMOVBU,
2557
			AB,
2558
			ABL,
2559
			AWORD,
2560
			ADWORD,
2561
			obj.ARET,
2562
			obj.ATEXT:
2563
			break
2564

2565
		case ALDP:
2566
			oprangeset(AFLDPD, t)
2567

2568
		case ASTP:
2569
			oprangeset(AFSTPD, t)
2570

2571
		case ASTPW:
2572
			oprangeset(AFSTPS, t)
2573

2574
		case ALDPW:
2575
			oprangeset(ALDPSW, t)
2576
			oprangeset(AFLDPS, t)
2577

2578
		case AERET:
2579
			oprangeset(AWFE, t)
2580
			oprangeset(AWFI, t)
2581
			oprangeset(AYIELD, t)
2582
			oprangeset(ASEV, t)
2583
			oprangeset(ASEVL, t)
2584
			oprangeset(ANOOP, t)
2585
			oprangeset(ADRPS, t)
2586

2587
		case ACBZ:
2588
			oprangeset(ACBZW, t)
2589
			oprangeset(ACBNZ, t)
2590
			oprangeset(ACBNZW, t)
2591

2592
		case ATBZ:
2593
			oprangeset(ATBNZ, t)
2594

2595
		case AADR, AADRP:
2596
			break
2597

2598
		case ACLREX:
2599
			break
2600

2601
		case ASVC:
2602
			oprangeset(AHVC, t)
2603
			oprangeset(AHLT, t)
2604
			oprangeset(ASMC, t)
2605
			oprangeset(ABRK, t)
2606
			oprangeset(ADCPS1, t)
2607
			oprangeset(ADCPS2, t)
2608
			oprangeset(ADCPS3, t)
2609

2610
		case AFADDS:
2611
			oprangeset(AFADDD, t)
2612
			oprangeset(AFSUBS, t)
2613
			oprangeset(AFSUBD, t)
2614
			oprangeset(AFMULS, t)
2615
			oprangeset(AFMULD, t)
2616
			oprangeset(AFNMULS, t)
2617
			oprangeset(AFNMULD, t)
2618
			oprangeset(AFDIVS, t)
2619
			oprangeset(AFMAXD, t)
2620
			oprangeset(AFMAXS, t)
2621
			oprangeset(AFMIND, t)
2622
			oprangeset(AFMINS, t)
2623
			oprangeset(AFMAXNMD, t)
2624
			oprangeset(AFMAXNMS, t)
2625
			oprangeset(AFMINNMD, t)
2626
			oprangeset(AFMINNMS, t)
2627
			oprangeset(AFDIVD, t)
2628

2629
		case AFMSUBD:
2630
			oprangeset(AFMSUBS, t)
2631
			oprangeset(AFMADDS, t)
2632
			oprangeset(AFMADDD, t)
2633
			oprangeset(AFNMSUBS, t)
2634
			oprangeset(AFNMSUBD, t)
2635
			oprangeset(AFNMADDS, t)
2636
			oprangeset(AFNMADDD, t)
2637

2638
		case AFCVTSD:
2639
			oprangeset(AFCVTDS, t)
2640
			oprangeset(AFABSD, t)
2641
			oprangeset(AFABSS, t)
2642
			oprangeset(AFNEGD, t)
2643
			oprangeset(AFNEGS, t)
2644
			oprangeset(AFSQRTD, t)
2645
			oprangeset(AFSQRTS, t)
2646
			oprangeset(AFRINTNS, t)
2647
			oprangeset(AFRINTND, t)
2648
			oprangeset(AFRINTPS, t)
2649
			oprangeset(AFRINTPD, t)
2650
			oprangeset(AFRINTMS, t)
2651
			oprangeset(AFRINTMD, t)
2652
			oprangeset(AFRINTZS, t)
2653
			oprangeset(AFRINTZD, t)
2654
			oprangeset(AFRINTAS, t)
2655
			oprangeset(AFRINTAD, t)
2656
			oprangeset(AFRINTXS, t)
2657
			oprangeset(AFRINTXD, t)
2658
			oprangeset(AFRINTIS, t)
2659
			oprangeset(AFRINTID, t)
2660
			oprangeset(AFCVTDH, t)
2661
			oprangeset(AFCVTHS, t)
2662
			oprangeset(AFCVTHD, t)
2663
			oprangeset(AFCVTSH, t)
2664

2665
		case AFCMPS:
2666
			oprangeset(AFCMPD, t)
2667
			oprangeset(AFCMPES, t)
2668
			oprangeset(AFCMPED, t)
2669

2670
		case AFCCMPS:
2671
			oprangeset(AFCCMPD, t)
2672
			oprangeset(AFCCMPES, t)
2673
			oprangeset(AFCCMPED, t)
2674

2675
		case AFCSELD:
2676
			oprangeset(AFCSELS, t)
2677

2678
		case AFMOVS, AFMOVD, AFMOVQ:
2679
			break
2680

2681
		case AFCVTZSD:
2682
			oprangeset(AFCVTZSDW, t)
2683
			oprangeset(AFCVTZSS, t)
2684
			oprangeset(AFCVTZSSW, t)
2685
			oprangeset(AFCVTZUD, t)
2686
			oprangeset(AFCVTZUDW, t)
2687
			oprangeset(AFCVTZUS, t)
2688
			oprangeset(AFCVTZUSW, t)
2689

2690
		case ASCVTFD:
2691
			oprangeset(ASCVTFS, t)
2692
			oprangeset(ASCVTFWD, t)
2693
			oprangeset(ASCVTFWS, t)
2694
			oprangeset(AUCVTFD, t)
2695
			oprangeset(AUCVTFS, t)
2696
			oprangeset(AUCVTFWD, t)
2697
			oprangeset(AUCVTFWS, t)
2698

2699
		case ASYS:
2700
			oprangeset(AAT, t)
2701
			oprangeset(ADC, t)
2702
			oprangeset(AIC, t)
2703
			oprangeset(ATLBI, t)
2704

2705
		case ASYSL, AHINT:
2706
			break
2707

2708
		case ADMB:
2709
			oprangeset(ADSB, t)
2710
			oprangeset(AISB, t)
2711

2712
		case AMRS, AMSR:
2713
			break
2714

2715
		case ALDAR:
2716
			oprangeset(ALDARW, t)
2717
			oprangeset(ALDARB, t)
2718
			oprangeset(ALDARH, t)
2719
			fallthrough
2720

2721
		case ALDXR:
2722
			oprangeset(ALDXRB, t)
2723
			oprangeset(ALDXRH, t)
2724
			oprangeset(ALDXRW, t)
2725

2726
		case ALDAXR:
2727
			oprangeset(ALDAXRB, t)
2728
			oprangeset(ALDAXRH, t)
2729
			oprangeset(ALDAXRW, t)
2730

2731
		case ALDXP:
2732
			oprangeset(ALDXPW, t)
2733
			oprangeset(ALDAXP, t)
2734
			oprangeset(ALDAXPW, t)
2735

2736
		case ASTLR:
2737
			oprangeset(ASTLRB, t)
2738
			oprangeset(ASTLRH, t)
2739
			oprangeset(ASTLRW, t)
2740

2741
		case ASTXR:
2742
			oprangeset(ASTXRB, t)
2743
			oprangeset(ASTXRH, t)
2744
			oprangeset(ASTXRW, t)
2745

2746
		case ASTLXR:
2747
			oprangeset(ASTLXRB, t)
2748
			oprangeset(ASTLXRH, t)
2749
			oprangeset(ASTLXRW, t)
2750

2751
		case ASTXP:
2752
			oprangeset(ASTLXP, t)
2753
			oprangeset(ASTLXPW, t)
2754
			oprangeset(ASTXPW, t)
2755

2756
		case AVADDP:
2757
			oprangeset(AVAND, t)
2758
			oprangeset(AVCMEQ, t)
2759
			oprangeset(AVORR, t)
2760
			oprangeset(AVEOR, t)
2761
			oprangeset(AVBSL, t)
2762
			oprangeset(AVBIT, t)
2763
			oprangeset(AVCMTST, t)
2764
			oprangeset(AVUZP1, t)
2765
			oprangeset(AVUZP2, t)
2766
			oprangeset(AVBIF, t)
2767

2768
		case AVADD:
2769
			oprangeset(AVSUB, t)
2770

2771
		case AAESD:
2772
			oprangeset(AAESE, t)
2773
			oprangeset(AAESMC, t)
2774
			oprangeset(AAESIMC, t)
2775
			oprangeset(ASHA1SU1, t)
2776
			oprangeset(ASHA256SU0, t)
2777
			oprangeset(ASHA512SU0, t)
2778

2779
		case ASHA1C:
2780
			oprangeset(ASHA1P, t)
2781
			oprangeset(ASHA1M, t)
2782

2783
		case ASHA256H:
2784
			oprangeset(ASHA256H2, t)
2785
			oprangeset(ASHA512H, t)
2786
			oprangeset(ASHA512H2, t)
2787

2788
		case ASHA1SU0:
2789
			oprangeset(ASHA256SU1, t)
2790
			oprangeset(ASHA512SU1, t)
2791

2792
		case AVADDV:
2793
			oprangeset(AVUADDLV, t)
2794

2795
		case AVFMLA:
2796
			oprangeset(AVFMLS, t)
2797

2798
		case AVPMULL:
2799
			oprangeset(AVPMULL2, t)
2800

2801
		case AVUSHR:
2802
			oprangeset(AVSHL, t)
2803
			oprangeset(AVSRI, t)
2804

2805
		case AVREV32:
2806
			oprangeset(AVCNT, t)
2807
			oprangeset(AVRBIT, t)
2808
			oprangeset(AVREV64, t)
2809
			oprangeset(AVREV16, t)
2810

2811
		case AVZIP1:
2812
			oprangeset(AVZIP2, t)
2813

2814
		case AVUXTL:
2815
			oprangeset(AVUXTL2, t)
2816

2817
		case AVUSHLL:
2818
			oprangeset(AVUSHLL2, t)
2819

2820
		case AVLD1R:
2821
			oprangeset(AVLD2, t)
2822
			oprangeset(AVLD2R, t)
2823
			oprangeset(AVLD3, t)
2824
			oprangeset(AVLD3R, t)
2825
			oprangeset(AVLD4, t)
2826
			oprangeset(AVLD4R, t)
2827

2828
		case ASHA1H,
2829
			AVCNT,
2830
			AVMOV,
2831
			AVLD1,
2832
			AVST1,
2833
			AVST2,
2834
			AVST3,
2835
			AVST4,
2836
			AVTBL,
2837
			AVDUP,
2838
			AVMOVI,
2839
			APRFM,
2840
			AVEXT:
2841
			break
2842

2843
		case obj.ANOP,
2844
			obj.AUNDEF,
2845
			obj.AFUNCDATA,
2846
			obj.APCALIGN,
2847
			obj.APCDATA,
2848
			obj.ADUFFZERO,
2849
			obj.ADUFFCOPY:
2850
			break
2851
		}
2852
	}
2853
}
2854

2855
// chipfloat7() checks if the immediate constants available in  FMOVS/FMOVD instructions.
2856
// For details of the range of constants available, see
2857
// http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
2858
func (c *ctxt7) chipfloat7(e float64) int {
2859
	ei := math.Float64bits(e)
2860
	l := uint32(int32(ei))
2861
	h := uint32(int32(ei >> 32))
2862

2863
	if l != 0 || h&0xffff != 0 {
2864
		return -1
2865
	}
2866
	h1 := h & 0x7fc00000
2867
	if h1 != 0x40000000 && h1 != 0x3fc00000 {
2868
		return -1
2869
	}
2870
	n := 0
2871

2872
	// sign bit (a)
2873
	if h&0x80000000 != 0 {
2874
		n |= 1 << 7
2875
	}
2876

2877
	// exp sign bit (b)
2878
	if h1 == 0x3fc00000 {
2879
		n |= 1 << 6
2880
	}
2881

2882
	// rest of exp and mantissa (cd-efgh)
2883
	n |= int((h >> 16) & 0x3f)
2884

2885
	//print("match %.8lux %.8lux %d\n", l, h, n);
2886
	return n
2887
}
2888

2889
/* form offset parameter to SYS; special register number */
2890
func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
2891
	return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
2892
}
2893

2894
func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
2895
	return SYSARG5(0, op1, Cn, Cm, op2)
2896
}
2897

2898
// checkUnpredictable checks if the sourse and transfer registers are the same register.
2899
// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
2900
func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
2901
	if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
2902
		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
2903
	}
2904
	if isload && rt1 == rt2 {
2905
		c.ctxt.Diag("constrained unpredictable behavior: %v", p)
2906
	}
2907
}
2908

2909
/* checkindex checks if index >= 0 && index <= maxindex */
2910
func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
2911
	if index < 0 || index > maxindex {
2912
		c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
2913
	}
2914
}
2915

2916
/* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
2917
func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
2918
	var offset, list, n, expect int64
2919
	switch as {
2920
	case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
2921
		offset = p.From.Offset
2922
		list = p.To.Offset
2923
	case AVST1, AVST2, AVST3, AVST4:
2924
		offset = p.To.Offset
2925
		list = p.From.Offset
2926
	default:
2927
		c.ctxt.Diag("invalid operation on op %v", p.As)
2928
	}
2929
	opcode := (list >> 12) & 15
2930
	q := (list >> 30) & 1
2931
	size := (list >> 10) & 3
2932
	if offset == 0 {
2933
		return
2934
	}
2935
	switch opcode {
2936
	case 0x7:
2937
		n = 1 // one register
2938
	case 0xa:
2939
		n = 2 // two registers
2940
	case 0x6:
2941
		n = 3 // three registers
2942
	case 0x2:
2943
		n = 4 // four registers
2944
	default:
2945
		c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
2946
	}
2947

2948
	switch as {
2949
	case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
2950
		if offset != n*(1<<uint(size)) {
2951
			c.ctxt.Diag("invalid post-increment offset: %v", p)
2952
		}
2953
	default:
2954
		if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
2955
			c.ctxt.Diag("invalid post-increment offset: %v", p)
2956
		}
2957
	}
2958

2959
	switch as {
2960
	case AVLD1, AVST1:
2961
		return
2962
	case AVLD1R:
2963
		expect = 1
2964
	case AVLD2, AVST2, AVLD2R:
2965
		expect = 2
2966
	case AVLD3, AVST3, AVLD3R:
2967
		expect = 3
2968
	case AVLD4, AVST4, AVLD4R:
2969
		expect = 4
2970
	}
2971

2972
	if expect != n {
2973
		c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
2974
	}
2975
}
2976

2977
/* checkShiftAmount checks whether the index shift amount is valid */
2978
/* for load with register offset instructions */
2979
func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
2980
	var amount int16
2981
	amount = (a.Index >> 5) & 7
2982
	switch p.As {
2983
	case AMOVB, AMOVBU:
2984
		if amount != 0 {
2985
			c.ctxt.Diag("invalid index shift amount: %v", p)
2986
		}
2987
	case AMOVH, AMOVHU:
2988
		if amount != 1 && amount != 0 {
2989
			c.ctxt.Diag("invalid index shift amount: %v", p)
2990
		}
2991
	case AMOVW, AMOVWU, AFMOVS:
2992
		if amount != 2 && amount != 0 {
2993
			c.ctxt.Diag("invalid index shift amount: %v", p)
2994
		}
2995
	case AMOVD, AFMOVD:
2996
		if amount != 3 && amount != 0 {
2997
			c.ctxt.Diag("invalid index shift amount: %v", p)
2998
		}
2999
	default:
3000
		panic("invalid operation")
3001
	}
3002
}
3003

3004
func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3005
	var os [5]uint32
3006
	o1 := uint32(0)
3007
	o2 := uint32(0)
3008
	o3 := uint32(0)
3009
	o4 := uint32(0)
3010
	o5 := uint32(0)
3011
	if false { /*debug['P']*/
3012
		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
3013
	}
3014
	switch o.type_ {
3015
	default:
3016
		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
3017

3018
	case 0: /* pseudo ops */
3019
		break
3020

3021
	case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
3022
		o1 = c.oprrr(p, p.As)
3023

3024
		rf := int(p.From.Reg)
3025
		rt := int(p.To.Reg)
3026
		r := int(p.Reg)
3027
		if p.To.Type == obj.TYPE_NONE {
3028
			rt = REGZERO
3029
		}
3030
		if r == 0 {
3031
			r = rt
3032
		}
3033
		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3034

3035
	case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
3036
		o1 = c.opirr(p, p.As)
3037

3038
		rt := int(p.To.Reg)
3039
		if p.To.Type == obj.TYPE_NONE {
3040
			if (o1 & Sbit) == 0 {
3041
				c.ctxt.Diag("ineffective ZR destination\n%v", p)
3042
			}
3043
			rt = REGZERO
3044
		}
3045

3046
		r := int(p.Reg)
3047
		if r == 0 {
3048
			r = rt
3049
		}
3050
		v := int32(c.regoff(&p.From))
3051
		o1 = c.oaddi(p, int32(o1), v, r, rt)
3052

3053
	case 3: /* op R<<n[,R],R (shifted register) */
3054
		o1 = c.oprrr(p, p.As)
3055

3056
		amount := (p.From.Offset >> 10) & 63
3057
		is64bit := o1 & (1 << 31)
3058
		if is64bit == 0 && amount >= 32 {
3059
			c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
3060
		}
3061
		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
3062
		rt := int(p.To.Reg)
3063
		if p.To.Type == obj.TYPE_NONE {
3064
			rt = REGZERO
3065
		}
3066
		r := int(p.Reg)
3067
		if p.As == AMVN || p.As == AMVNW {
3068
			r = REGZERO
3069
		} else if r == 0 {
3070
			r = rt
3071
		}
3072
		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3073

3074
	case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
3075
		rt := int(p.To.Reg)
3076
		r := int(o.param)
3077

3078
		if r == 0 {
3079
			r = REGZERO
3080
		} else if r == REGFROM {
3081
			r = int(p.From.Reg)
3082
		}
3083
		if r == 0 {
3084
			r = REGSP
3085
		}
3086

3087
		v := int32(c.regoff(&p.From))
3088
		var op int32
3089
		if v < 0 {
3090
			v = -v
3091
			op = int32(c.opirr(p, ASUB))
3092
		} else {
3093
			op = int32(c.opirr(p, AADD))
3094
		}
3095

3096
		if int(o.size) == 8 {
3097
			o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP)
3098
			o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt)
3099
			break
3100
		}
3101

3102
		o1 = c.oaddi(p, op, v, r, rt)
3103

3104
	case 5: /* b s; bl s */
3105
		o1 = c.opbra(p, p.As)
3106

3107
		if p.To.Sym == nil {
3108
			o1 |= uint32(c.brdist(p, 0, 26, 2))
3109
			break
3110
		}
3111

3112
		rel := obj.Addrel(c.cursym)
3113
		rel.Off = int32(c.pc)
3114
		rel.Siz = 4
3115
		rel.Sym = p.To.Sym
3116
		rel.Add = p.To.Offset
3117
		rel.Type = objabi.R_CALLARM64
3118

3119
	case 6: /* b ,O(R); bl ,O(R) */
3120
		o1 = c.opbrr(p, p.As)
3121

3122
		o1 |= uint32(p.To.Reg&31) << 5
3123
		rel := obj.Addrel(c.cursym)
3124
		rel.Off = int32(c.pc)
3125
		rel.Siz = 0
3126
		rel.Type = objabi.R_CALLIND
3127

3128
	case 7: /* beq s */
3129
		o1 = c.opbra(p, p.As)
3130

3131
		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
3132

3133
	case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
3134
		rt := int(p.To.Reg)
3135

3136
		rf := int(p.Reg)
3137
		if rf == 0 {
3138
			rf = rt
3139
		}
3140
		v := int32(p.From.Offset)
3141
		switch p.As {
3142
		case AASR:
3143
			o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
3144

3145
		case AASRW:
3146
			o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
3147

3148
		case ALSL:
3149
			o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
3150

3151
		case ALSLW:
3152
			o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
3153

3154
		case ALSR:
3155
			o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
3156

3157
		case ALSRW:
3158
			o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
3159

3160
		case AROR:
3161
			o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
3162

3163
		case ARORW:
3164
			o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
3165

3166
		default:
3167
			c.ctxt.Diag("bad shift $con\n%v", p)
3168
			break
3169
		}
3170

3171
	case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
3172
		o1 = c.oprrr(p, p.As)
3173

3174
		r := int(p.Reg)
3175
		if r == 0 {
3176
			r = int(p.To.Reg)
3177
		}
3178
		o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
3179

3180
	case 10: /* brk/hvc/.../svc [$con] */
3181
		o1 = c.opimm(p, p.As)
3182

3183
		if p.From.Type != obj.TYPE_NONE {
3184
			o1 |= uint32((p.From.Offset & 0xffff) << 5)
3185
		}
3186

3187
	case 11: /* dword */
3188
		c.aclass(&p.To)
3189

3190
		o1 = uint32(c.instoffset)
3191
		o2 = uint32(c.instoffset >> 32)
3192
		if p.To.Sym != nil {
3193
			rel := obj.Addrel(c.cursym)
3194
			rel.Off = int32(c.pc)
3195
			rel.Siz = 8
3196
			rel.Sym = p.To.Sym
3197
			rel.Add = p.To.Offset
3198
			rel.Type = objabi.R_ADDR
3199
			o2 = 0
3200
			o1 = o2
3201
		}
3202

3203
	case 12: /* movT $vcon, reg */
3204
		// NOTE: this case does not use REGTMP. If it ever does,
3205
		// remove the NOTUSETMP flag in optab.
3206
		num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
3207
		if num == 0 {
3208
			c.ctxt.Diag("invalid constant: %v", p)
3209
		}
3210
		o1 = os[0]
3211
		o2 = os[1]
3212
		o3 = os[2]
3213
		o4 = os[3]
3214

3215
	case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
3216
		o := uint32(0)
3217
		num := uint8(0)
3218
		cls := oclass(&p.From)
3219
		if isADDWop(p.As) {
3220
			if !cmp(C_LCON, cls) {
3221
				c.ctxt.Diag("illegal combination: %v", p)
3222
			}
3223
			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3224
		} else {
3225
			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3226
		}
3227
		if num == 0 {
3228
			c.ctxt.Diag("invalid constant: %v", p)
3229
		}
3230
		rt := int(p.To.Reg)
3231
		if p.To.Type == obj.TYPE_NONE {
3232
			rt = REGZERO
3233
		}
3234
		r := int(p.Reg)
3235
		if r == 0 {
3236
			r = rt
3237
		}
3238
		if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
3239
			o = c.opxrrr(p, p.As, false)
3240
			o |= REGTMP & 31 << 16
3241
			o |= LSL0_64
3242
		} else {
3243
			o = c.oprrr(p, p.As)
3244
			o |= REGTMP & 31 << 16 /* shift is 0 */
3245
		}
3246

3247
		o |= uint32(r&31) << 5
3248
		o |= uint32(rt & 31)
3249

3250
		os[num] = o
3251
		o1 = os[0]
3252
		o2 = os[1]
3253
		o3 = os[2]
3254
		o4 = os[3]
3255
		o5 = os[4]
3256

3257
	case 14: /* word */
3258
		if c.aclass(&p.To) == C_ADDR {
3259
			c.ctxt.Diag("address constant needs DWORD\n%v", p)
3260
		}
3261
		o1 = uint32(c.instoffset)
3262
		if p.To.Sym != nil {
3263
			// This case happens with words generated
3264
			// in the PC stream as part of the literal pool.
3265
			rel := obj.Addrel(c.cursym)
3266

3267
			rel.Off = int32(c.pc)
3268
			rel.Siz = 4
3269
			rel.Sym = p.To.Sym
3270
			rel.Add = p.To.Offset
3271
			rel.Type = objabi.R_ADDR
3272
			o1 = 0
3273
		}
3274

3275
	case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
3276
		o1 = c.oprrr(p, p.As)
3277

3278
		rf := int(p.From.Reg)
3279
		rt := int(p.To.Reg)
3280
		var r int
3281
		var ra int
3282
		if p.From3Type() == obj.TYPE_REG {
3283
			r = int(p.GetFrom3().Reg)
3284
			ra = int(p.Reg)
3285
			if ra == 0 {
3286
				ra = REGZERO
3287
			}
3288
		} else {
3289
			r = int(p.Reg)
3290
			if r == 0 {
3291
				r = rt
3292
			}
3293
			ra = REGZERO
3294
		}
3295

3296
		o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
3297

3298
	case 16: /* XremY R[,R],R -> XdivY; XmsubY */
3299
		o1 = c.oprrr(p, p.As)
3300

3301
		rf := int(p.From.Reg)
3302
		rt := int(p.To.Reg)
3303
		r := int(p.Reg)
3304
		if r == 0 {
3305
			r = rt
3306
		}
3307
		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
3308
		o2 = c.oprrr(p, AMSUBW)
3309
		o2 |= o1 & (1 << 31) /* same size */
3310
		o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
3311

3312
	case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
3313
		o1 = c.oprrr(p, p.As)
3314

3315
		rf := int(p.From.Reg)
3316
		rt := int(p.To.Reg)
3317
		r := int(p.Reg)
3318
		if p.To.Type == obj.TYPE_NONE {
3319
			rt = REGZERO
3320
		}
3321
		if r == 0 {
3322
			r = REGZERO
3323
		}
3324
		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3325

3326
	case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
3327
		o1 = c.oprrr(p, p.As)
3328

3329
		cond := int(p.From.Reg)
3330
		if cond < COND_EQ || cond > COND_NV {
3331
			c.ctxt.Diag("invalid condition: %v", p)
3332
		} else {
3333
			cond -= COND_EQ
3334
		}
3335

3336
		r := int(p.Reg)
3337
		var rf int
3338
		if r != 0 {
3339
			if p.From3Type() == obj.TYPE_NONE {
3340
				/* CINC/CINV/CNEG */
3341
				rf = r
3342
				cond ^= 1
3343
			} else {
3344
				rf = int(p.GetFrom3().Reg) /* CSEL */
3345
			}
3346
		} else {
3347
			/* CSET */
3348
			rf = REGZERO
3349
			r = rf
3350
			cond ^= 1
3351
		}
3352

3353
		rt := int(p.To.Reg)
3354
		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
3355

3356
	case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
3357
		nzcv := int(p.To.Offset)
3358

3359
		cond := int(p.From.Reg)
3360
		if cond < COND_EQ || cond > COND_NV {
3361
			c.ctxt.Diag("invalid condition\n%v", p)
3362
		} else {
3363
			cond -= COND_EQ
3364
		}
3365
		var rf int
3366
		if p.GetFrom3().Type == obj.TYPE_REG {
3367
			o1 = c.oprrr(p, p.As)
3368
			rf = int(p.GetFrom3().Reg) /* Rm */
3369
		} else {
3370
			o1 = c.opirr(p, p.As)
3371
			rf = int(p.GetFrom3().Offset & 0x1F)
3372
		}
3373

3374
		o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
3375

3376
	case 20: /* movT R,O(R) -> strT */
3377
		v := int32(c.regoff(&p.To))
3378
		sz := int32(1 << uint(movesize(p.As)))
3379

3380
		r := int(p.To.Reg)
3381
		if r == 0 {
3382
			r = int(o.param)
3383
		}
3384
		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3385
			o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
3386
		} else {
3387
			v = int32(c.offsetshift(p, int64(v), int(o.a4)))
3388
			o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
3389
		}
3390

3391
	case 21: /* movT O(R),R -> ldrT */
3392
		v := int32(c.regoff(&p.From))
3393
		sz := int32(1 << uint(movesize(p.As)))
3394

3395
		r := int(p.From.Reg)
3396
		if r == 0 {
3397
			r = int(o.param)
3398
		}
3399
		if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3400
			o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
3401
		} else {
3402
			v = int32(c.offsetshift(p, int64(v), int(o.a1)))
3403
			//print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
3404
			o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
3405
		}
3406

3407
	case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
3408
		if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
3409
			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3410
		}
3411

3412
		v := int32(p.From.Offset)
3413

3414
		if v < -256 || v > 255 {
3415
			c.ctxt.Diag("offset out of range [-255,254]: %v", p)
3416
		}
3417
		o1 = c.opldrpp(p, p.As)
3418
		if o.scond == C_XPOST {
3419
			o1 |= 1 << 10
3420
		} else {
3421
			o1 |= 3 << 10
3422
		}
3423
		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
3424

3425
	case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
3426
		if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
3427
			c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3428
		}
3429

3430
		v := int32(p.To.Offset)
3431

3432
		if v < -256 || v > 255 {
3433
			c.ctxt.Diag("offset out of range [-255,254]: %v", p)
3434
		}
3435
		o1 = LD2STR(c.opldrpp(p, p.As))
3436
		if o.scond == C_XPOST {
3437
			o1 |= 1 << 10
3438
		} else {
3439
			o1 |= 3 << 10
3440
		}
3441
		o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
3442

3443
	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
3444
		rf := int(p.From.Reg)
3445
		rt := int(p.To.Reg)
3446
		s := rf == REGSP || rt == REGSP
3447
		if p.As == AMVN || p.As == AMVNW {
3448
			if s {
3449
				c.ctxt.Diag("illegal SP reference\n%v", p)
3450
			}
3451
			o1 = c.oprrr(p, p.As)
3452
			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3453
		} else if s {
3454
			o1 = c.opirr(p, p.As)
3455
			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
3456
		} else {
3457
			o1 = c.oprrr(p, p.As)
3458
			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3459
		}
3460

3461
	case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
3462
		o1 = c.oprrr(p, p.As)
3463

3464
		rf := int(p.From.Reg)
3465
		if rf == C_NONE {
3466
			rf = int(p.To.Reg)
3467
		}
3468
		rt := int(p.To.Reg)
3469
		o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3470

3471
	case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
3472
		o1 = c.oprrr(p, p.As)
3473

3474
		o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
3475
		rt := int(p.To.Reg)
3476
		o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
3477

3478
	case 27: /* op Rm<<n[,Rn],Rd (extended register) */
3479
		if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
3480
			amount := (p.From.Reg >> 5) & 7
3481
			if amount > 4 {
3482
				c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
3483
			}
3484
			o1 = c.opxrrr(p, p.As, true)
3485
			o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
3486
		} else {
3487
			o1 = c.opxrrr(p, p.As, false)
3488
			o1 |= uint32(p.From.Reg&31) << 16
3489
		}
3490
		rt := int(p.To.Reg)
3491
		if p.To.Type == obj.TYPE_NONE {
3492
			rt = REGZERO
3493
		}
3494
		r := int(p.Reg)
3495
		if r == 0 {
3496
			r = rt
3497
		}
3498
		o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3499

3500
	case 28: /* logop $vcon, [R], R (64 bit literal) */
3501
		o := uint32(0)
3502
		num := uint8(0)
3503
		cls := oclass(&p.From)
3504
		if isANDWop(p.As) {
3505
			if !cmp(C_LCON, cls) {
3506
				c.ctxt.Diag("illegal combination: %v", p)
3507
			}
3508
			num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3509
		} else {
3510
			num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3511
		}
3512

3513
		if num == 0 {
3514
			c.ctxt.Diag("invalid constant: %v", p)
3515
		}
3516
		rt := int(p.To.Reg)
3517
		if p.To.Type == obj.TYPE_NONE {
3518
			rt = REGZERO
3519
		}
3520
		r := int(p.Reg)
3521
		if r == 0 {
3522
			r = rt
3523
		}
3524
		o = c.oprrr(p, p.As)
3525
		o |= REGTMP & 31 << 16 /* shift is 0 */
3526
		o |= uint32(r&31) << 5
3527
		o |= uint32(rt & 31)
3528

3529
		os[num] = o
3530
		o1 = os[0]
3531
		o2 = os[1]
3532
		o3 = os[2]
3533
		o4 = os[3]
3534
		o5 = os[4]
3535

3536
	case 29: /* op Rn, Rd */
3537
		fc := c.aclass(&p.From)
3538
		tc := c.aclass(&p.To)
3539
		if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
3540
			// FMOV Rx, Fy or FMOV Fy, Rx
3541
			o1 = FPCVTI(0, 0, 0, 0, 6)
3542
			if p.As == AFMOVD {
3543
				o1 |= 1<<31 | 1<<22 // 64-bit
3544
			}
3545
			if fc == C_REG || fc == C_ZCON {
3546
				o1 |= 1 << 16 // FMOV Rx, Fy
3547
			}
3548
		} else {
3549
			o1 = c.oprrr(p, p.As)
3550
		}
3551
		o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
3552

3553
	case 30: /* movT R,L(R) -> strT */
3554
		// if offset L can be split into hi+lo, and both fit into instructions, do
3555
		//	add $hi, R, Rtmp
3556
		//	str R, lo(Rtmp)
3557
		// otherwise, use constant pool
3558
		//	mov $L, Rtmp (from constant pool)
3559
		//	str R, (R+Rtmp)
3560
		s := movesize(o.as)
3561
		if s < 0 {
3562
			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3563
		}
3564

3565
		r := int(p.To.Reg)
3566
		if r == 0 {
3567
			r = int(o.param)
3568
		}
3569

3570
		v := int32(c.regoff(&p.To))
3571
		var hi int32
3572
		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3573
			// negative or unaligned offset, use constant pool
3574
			goto storeusepool
3575
		}
3576

3577
		hi = v - (v & (0xFFF << uint(s)))
3578
		if hi&0xFFF != 0 {
3579
			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
3580
		}
3581
		if hi&^0xFFF000 != 0 {
3582
			// hi doesn't fit into an ADD instruction
3583
			goto storeusepool
3584
		}
3585

3586
		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
3587
		o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
3588
		break
3589

3590
	storeusepool:
3591
		if r == REGTMP || p.From.Reg == REGTMP {
3592
			c.ctxt.Diag("REGTMP used in large offset store: %v", p)
3593
		}
3594
		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
3595
		o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
3596

3597
	case 31: /* movT L(R), R -> ldrT */
3598
		// if offset L can be split into hi+lo, and both fit into instructions, do
3599
		//	add $hi, R, Rtmp
3600
		//	ldr lo(Rtmp), R
3601
		// otherwise, use constant pool
3602
		//	mov $L, Rtmp (from constant pool)
3603
		//	ldr (R+Rtmp), R
3604
		s := movesize(o.as)
3605
		if s < 0 {
3606
			c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3607
		}
3608

3609
		r := int(p.From.Reg)
3610
		if r == 0 {
3611
			r = int(o.param)
3612
		}
3613

3614
		v := int32(c.regoff(&p.From))
3615
		var hi int32
3616
		if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3617
			// negative or unaligned offset, use constant pool
3618
			goto loadusepool
3619
		}
3620

3621
		hi = v - (v & (0xFFF << uint(s)))
3622
		if (hi & 0xFFF) != 0 {
3623
			c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
3624
		}
3625
		if hi&^0xFFF000 != 0 {
3626
			// hi doesn't fit into an ADD instruction
3627
			goto loadusepool
3628
		}
3629

3630
		o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
3631
		o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
3632
		break
3633

3634
	loadusepool:
3635
		if r == REGTMP || p.From.Reg == REGTMP {
3636
			c.ctxt.Diag("REGTMP used in large offset load: %v", p)
3637
		}
3638
		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
3639
		o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
3640

3641
	case 32: /* mov $con, R -> movz/movn */
3642
		o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
3643

3644
	case 33: /* movk $uimm16 << pos */
3645
		o1 = c.opirr(p, p.As)
3646

3647
		d := p.From.Offset
3648
		s := movcon(d)
3649
		if s < 0 || s >= 4 {
3650
			c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
3651
		}
3652
		if (o1&S64) == 0 && s >= 2 {
3653
			c.ctxt.Diag("illegal bit position\n%v", p)
3654
		}
3655
		if ((d >> uint(s*16)) >> 16) != 0 {
3656
			c.ctxt.Diag("requires uimm16\n%v", p)
3657
		}
3658
		rt := int(p.To.Reg)
3659

3660
		o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
3661

3662
	case 34: /* mov $lacon,R */
3663
		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
3664

3665
		if o1 == 0 {
3666
			break
3667
		}
3668
		o2 = c.opxrrr(p, AADD, false)
3669
		o2 |= REGTMP & 31 << 16
3670
		o2 |= LSL0_64
3671
		r := int(p.From.Reg)
3672
		if r == 0 {
3673
			r = int(o.param)
3674
		}
3675
		o2 |= uint32(r&31) << 5
3676
		o2 |= uint32(p.To.Reg & 31)
3677

3678
	case 35: /* mov SPR,R -> mrs */
3679
		o1 = c.oprrr(p, AMRS)
3680

3681
		// SysRegEnc function returns the system register encoding and accessFlags.
3682
		_, v, accessFlags := SysRegEnc(p.From.Reg)
3683
		if v == 0 {
3684
			c.ctxt.Diag("illegal system register:\n%v", p)
3685
		}
3686
		if (o1 & (v &^ (3 << 19))) != 0 {
3687
			c.ctxt.Diag("MRS register value overlap\n%v", p)
3688
		}
3689
		if accessFlags&SR_READ == 0 {
3690
			c.ctxt.Diag("system register is not readable: %v", p)
3691
		}
3692

3693
		o1 |= v
3694
		o1 |= uint32(p.To.Reg & 31)
3695

3696
	case 36: /* mov R,SPR */
3697
		o1 = c.oprrr(p, AMSR)
3698

3699
		// SysRegEnc function returns the system register encoding and accessFlags.
3700
		_, v, accessFlags := SysRegEnc(p.To.Reg)
3701
		if v == 0 {
3702
			c.ctxt.Diag("illegal system register:\n%v", p)
3703
		}
3704
		if (o1 & (v &^ (3 << 19))) != 0 {
3705
			c.ctxt.Diag("MSR register value overlap\n%v", p)
3706
		}
3707
		if accessFlags&SR_WRITE == 0 {
3708
			c.ctxt.Diag("system register is not writable: %v", p)
3709
		}
3710

3711
		o1 |= v
3712
		o1 |= uint32(p.From.Reg & 31)
3713

3714
	case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
3715
		if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
3716
			c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
3717
		}
3718
		o1 = c.opirr(p, AMSR)
3719
		o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
3720
		v := uint32(0)
3721
		for i := 0; i < len(pstatefield); i++ {
3722
			if pstatefield[i].reg == p.To.Reg {
3723
				v = pstatefield[i].enc
3724
				break
3725
			}
3726
		}
3727

3728
		if v == 0 {
3729
			c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
3730
		}
3731
		o1 |= v
3732

3733
	case 38: /* clrex [$imm] */
3734
		o1 = c.opimm(p, p.As)
3735

3736
		if p.To.Type == obj.TYPE_NONE {
3737
			o1 |= 0xF << 8
3738
		} else {
3739
			o1 |= uint32((p.To.Offset & 0xF) << 8)
3740
		}
3741

3742
	case 39: /* cbz R, rel */
3743
		o1 = c.opirr(p, p.As)
3744

3745
		o1 |= uint32(p.From.Reg & 31)
3746
		o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
3747

3748
	case 40: /* tbz */
3749
		o1 = c.opirr(p, p.As)
3750

3751
		v := int32(p.From.Offset)
3752
		if v < 0 || v > 63 {
3753
			c.ctxt.Diag("illegal bit number\n%v", p)
3754
		}
3755
		o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
3756
		o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
3757
		o1 |= uint32(p.Reg & 31)
3758

3759
	case 41: /* eret, nop, others with no operands */
3760
		o1 = c.op0(p, p.As)
3761

3762
	case 42: /* bfm R,r,s,R */
3763
		o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
3764

3765
	case 43: /* bfm aliases */
3766
		r := int(p.From.Offset)
3767
		s := int(p.GetFrom3().Offset)
3768
		rf := int(p.Reg)
3769
		rt := int(p.To.Reg)
3770
		if rf == 0 {
3771
			rf = rt
3772
		}
3773
		switch p.As {
3774
		case ABFI:
3775
			if r != 0 {
3776
				r = 64 - r
3777
			}
3778
			o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
3779

3780
		case ABFIW:
3781
			if r != 0 {
3782
				r = 32 - r
3783
			}
3784
			o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
3785

3786
		case ABFXIL:
3787
			o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
3788

3789
		case ABFXILW:
3790
			o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
3791

3792
		case ASBFIZ:
3793
			if r != 0 {
3794
				r = 64 - r
3795
			}
3796
			o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
3797

3798
		case ASBFIZW:
3799
			if r != 0 {
3800
				r = 32 - r
3801
			}
3802
			o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
3803

3804
		case ASBFX:
3805
			o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
3806

3807
		case ASBFXW:
3808
			o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
3809

3810
		case AUBFIZ:
3811
			if r != 0 {
3812
				r = 64 - r
3813
			}
3814
			o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
3815

3816
		case AUBFIZW:
3817
			if r != 0 {
3818
				r = 32 - r
3819
			}
3820
			o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
3821

3822
		case AUBFX:
3823
			o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
3824

3825
		case AUBFXW:
3826
			o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
3827

3828
		default:
3829
			c.ctxt.Diag("bad bfm alias\n%v", p)
3830
			break
3831
		}
3832

3833
	case 44: /* extr $b, Rn, Rm, Rd */
3834
		o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
3835

3836
	case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
3837
		rf := int(p.From.Reg)
3838

3839
		rt := int(p.To.Reg)
3840
		as := p.As
3841
		if rf == REGZERO {
3842
			as = AMOVWU /* clearer in disassembly */
3843
		}
3844
		switch as {
3845
		case AMOVB, ASXTB:
3846
			o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
3847

3848
		case AMOVH, ASXTH:
3849
			o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
3850

3851
		case AMOVW, ASXTW:
3852
			o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
3853

3854
		case AMOVBU, AUXTB:
3855
			o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
3856

3857
		case AMOVHU, AUXTH:
3858
			o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
3859

3860
		case AMOVWU:
3861
			o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3862

3863
		case AUXTW:
3864
			o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
3865

3866
		case ASXTBW:
3867
			o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
3868

3869
		case ASXTHW:
3870
			o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
3871

3872
		case AUXTBW:
3873
			o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
3874

3875
		case AUXTHW:
3876
			o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
3877

3878
		default:
3879
			c.ctxt.Diag("bad sxt %v", as)
3880
			break
3881
		}
3882

3883
	case 46: /* cls */
3884
		o1 = c.opbit(p, p.As)
3885

3886
		o1 |= uint32(p.From.Reg&31) << 5
3887
		o1 |= uint32(p.To.Reg & 31)
3888

3889
	case 47: /* SWPx/LDADDx/LDANDx/LDEORx/LDORx Rs, (Rb), Rt */
3890
		rs := p.From.Reg
3891
		rt := p.RegTo2
3892
		rb := p.To.Reg
3893

3894
		fields := atomicInstructions[p.As]
3895
		// rt can't be sp. rt can't be r31 when field A is 0, A bit is the 23rd bit.
3896
		if rt == REG_RSP || (rt == REGZERO && (fields&(1<<23) == 0)) {
3897
			c.ctxt.Diag("illegal destination register: %v\n", p)
3898
		}
3899
		o1 |= fields | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
3900

3901
	case 48: /* ADD $C_ADDCON2, Rm, Rd */
3902
		// NOTE: this case does not use REGTMP. If it ever does,
3903
		// remove the NOTUSETMP flag in optab.
3904
		op := c.opirr(p, p.As)
3905
		if op&Sbit != 0 {
3906
			c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
3907
		}
3908
		rt := int(p.To.Reg)
3909
		r := int(p.Reg)
3910
		if r == 0 {
3911
			r = rt
3912
		}
3913
		o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
3914
		o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
3915

3916
	case 50: /* sys/sysl */
3917
		o1 = c.opirr(p, p.As)
3918

3919
		if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
3920
			c.ctxt.Diag("illegal SYS argument\n%v", p)
3921
		}
3922
		o1 |= uint32(p.From.Offset)
3923
		if p.To.Type == obj.TYPE_REG {
3924
			o1 |= uint32(p.To.Reg & 31)
3925
		} else if p.Reg != 0 {
3926
			o1 |= uint32(p.Reg & 31)
3927
		} else {
3928
			o1 |= 0x1F
3929
		}
3930

3931
	case 51: /* dmb */
3932
		o1 = c.opirr(p, p.As)
3933

3934
		if p.From.Type == obj.TYPE_CONST {
3935
			o1 |= uint32((p.From.Offset & 0xF) << 8)
3936
		}
3937

3938
	case 52: /* hint */
3939
		o1 = c.opirr(p, p.As)
3940

3941
		o1 |= uint32((p.From.Offset & 0x7F) << 5)
3942

3943
	case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
3944
		a := p.As
3945
		rt := int(p.To.Reg)
3946
		if p.To.Type == obj.TYPE_NONE {
3947
			rt = REGZERO
3948
		}
3949
		r := int(p.Reg)
3950
		if r == 0 {
3951
			r = rt
3952
		}
3953
		mode := 64
3954
		v := uint64(p.From.Offset)
3955
		switch p.As {
3956
		case AANDW, AORRW, AEORW, AANDSW, ATSTW:
3957
			mode = 32
3958
		case ABIC, AORN, AEON, ABICS:
3959
			v = ^v
3960
		case ABICW, AORNW, AEONW, ABICSW:
3961
			v = ^v
3962
			mode = 32
3963
		}
3964
		o1 = c.opirr(p, a)
3965
		o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
3966

3967
	case 54: /* floating point arith */
3968
		o1 = c.oprrr(p, p.As)
3969
		rf := int(p.From.Reg)
3970
		rt := int(p.To.Reg)
3971
		r := int(p.Reg)
3972
		if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
3973
			r = rf
3974
			rf = 0
3975
		} else if r == 0 {
3976
			r = rt
3977
		}
3978
		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3979

3980
	case 55: /* floating-point constant */
3981
		var rf int
3982
		o1 = 0xf<<25 | 1<<21 | 1<<12
3983
		rf = c.chipfloat7(p.From.Val.(float64))
3984
		if rf < 0 {
3985
			c.ctxt.Diag("invalid floating-point immediate\n%v", p)
3986
		}
3987
		if p.As == AFMOVD {
3988
			o1 |= 1 << 22
3989
		}
3990
		o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
3991

3992
	case 56: /* floating point compare */
3993
		o1 = c.oprrr(p, p.As)
3994

3995
		var rf int
3996
		if p.From.Type == obj.TYPE_FCONST {
3997
			o1 |= 8 /* zero */
3998
			rf = 0
3999
		} else {
4000
			rf = int(p.From.Reg)
4001
		}
4002
		rt := int(p.Reg)
4003
		o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
4004

4005
	case 57: /* floating point conditional compare */
4006
		o1 = c.oprrr(p, p.As)
4007

4008
		cond := int(p.From.Reg)
4009
		if cond < COND_EQ || cond > COND_NV {
4010
			c.ctxt.Diag("invalid condition\n%v", p)
4011
		} else {
4012
			cond -= COND_EQ
4013
		}
4014

4015
		nzcv := int(p.To.Offset)
4016
		if nzcv&^0xF != 0 {
4017
			c.ctxt.Diag("implausible condition\n%v", p)
4018
		}
4019
		rf := int(p.Reg)
4020
		if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
4021
			c.ctxt.Diag("illegal FCCMP\n%v", p)
4022
			break
4023
		}
4024
		rt := int(p.GetFrom3().Reg)
4025
		o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
4026

4027
	case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
4028
		o1 = c.opload(p, p.As)
4029

4030
		o1 |= 0x1F << 16
4031
		o1 |= uint32(p.From.Reg&31) << 5
4032
		if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
4033
			if int(p.To.Reg) == int(p.To.Offset) {
4034
				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4035
			}
4036
			o1 |= uint32(p.To.Offset&31) << 10
4037
		} else {
4038
			o1 |= 0x1F << 10
4039
		}
4040
		o1 |= uint32(p.To.Reg & 31)
4041

4042
	case 59: /* stxr/stlxr/stxp/stlxp */
4043
		s := p.RegTo2
4044
		n := p.To.Reg
4045
		t := p.From.Reg
4046
		if isSTLXRop(p.As) {
4047
			if s == t || (s == n && n != REGSP) {
4048
				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4049
			}
4050
		} else if isSTXPop(p.As) {
4051
			t2 := int16(p.From.Offset)
4052
			if (s == t || s == t2) || (s == n && n != REGSP) {
4053
				c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4054
			}
4055
		}
4056
		if s == REG_RSP {
4057
			c.ctxt.Diag("illegal destination register: %v\n", p)
4058
		}
4059
		o1 = c.opstore(p, p.As)
4060

4061
		if p.RegTo2 != obj.REG_NONE {
4062
			o1 |= uint32(p.RegTo2&31) << 16
4063
		} else {
4064
			o1 |= 0x1F << 16
4065
		}
4066
		if isSTXPop(p.As) {
4067
			o1 |= uint32(p.From.Offset&31) << 10
4068
		}
4069
		o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
4070

4071
	case 60: /* adrp label,r */
4072
		d := c.brdist(p, 12, 21, 0)
4073

4074
		o1 = ADR(1, uint32(d), uint32(p.To.Reg))
4075

4076
	case 61: /* adr label, r */
4077
		d := c.brdist(p, 0, 21, 0)
4078

4079
		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
4080

4081
	case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
4082
		if p.Reg == REGTMP {
4083
			c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
4084
		}
4085
		if isADDWop(p.As) || isANDWop(p.As) {
4086
			o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
4087
		} else {
4088
			o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
4089
		}
4090

4091
		rt := int(p.To.Reg)
4092
		if p.To.Type == obj.TYPE_NONE {
4093
			rt = REGZERO
4094
		}
4095
		r := int(p.Reg)
4096
		if r == 0 {
4097
			r = rt
4098
		}
4099
		if p.To.Reg == REGSP || r == REGSP {
4100
			o2 = c.opxrrr(p, p.As, false)
4101
			o2 |= REGTMP & 31 << 16
4102
			o2 |= LSL0_64
4103
		} else {
4104
			o2 = c.oprrr(p, p.As)
4105
			o2 |= REGTMP & 31 << 16 /* shift is 0 */
4106
		}
4107
		o2 |= uint32(r&31) << 5
4108
		o2 |= uint32(rt & 31)
4109

4110
		/* reloc ops */
4111
	case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
4112
		o1 = ADR(1, 0, REGTMP)
4113
		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4114
		rel := obj.Addrel(c.cursym)
4115
		rel.Off = int32(c.pc)
4116
		rel.Siz = 8
4117
		rel.Sym = p.To.Sym
4118
		rel.Add = p.To.Offset
4119
		rel.Type = objabi.R_ADDRARM64
4120
		o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
4121

4122
	case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
4123
		o1 = ADR(1, 0, REGTMP)
4124
		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4125
		rel := obj.Addrel(c.cursym)
4126
		rel.Off = int32(c.pc)
4127
		rel.Siz = 8
4128
		rel.Sym = p.From.Sym
4129
		rel.Add = p.From.Offset
4130
		rel.Type = objabi.R_ADDRARM64
4131
		o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
4132

4133
	case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
4134
		v := int32(c.regoff(&p.From))
4135
		r := int(p.From.Reg)
4136
		if r == obj.REG_NONE {
4137
			r = int(o.param)
4138
		}
4139
		if r == obj.REG_NONE {
4140
			c.ctxt.Diag("invalid ldp source: %v\n", p)
4141
		}
4142
		o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4143

4144
	case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
4145
		r := int(p.To.Reg)
4146
		if r == obj.REG_NONE {
4147
			r = int(o.param)
4148
		}
4149
		if r == obj.REG_NONE {
4150
			c.ctxt.Diag("invalid stp destination: %v\n", p)
4151
		}
4152
		v := int32(c.regoff(&p.To))
4153
		o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4154

4155
	case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
4156
		// NOTE: this case does not use REGTMP. If it ever does,
4157
		// remove the NOTUSETMP flag in optab.
4158
		if p.As == AMOVW {
4159
			c.ctxt.Diag("invalid load of 32-bit address: %v", p)
4160
		}
4161
		o1 = ADR(1, 0, uint32(p.To.Reg))
4162
		o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
4163
		rel := obj.Addrel(c.cursym)
4164
		rel.Off = int32(c.pc)
4165
		rel.Siz = 8
4166
		rel.Sym = p.From.Sym
4167
		rel.Add = p.From.Offset
4168
		rel.Type = objabi.R_ADDRARM64
4169

4170
	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
4171
		o1 = c.opirr(p, AMOVZ)
4172
		o1 |= uint32(p.To.Reg & 31)
4173
		rel := obj.Addrel(c.cursym)
4174
		rel.Off = int32(c.pc)
4175
		rel.Siz = 4
4176
		rel.Sym = p.From.Sym
4177
		rel.Type = objabi.R_ARM64_TLS_LE
4178
		if p.From.Offset != 0 {
4179
			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4180
		}
4181

4182
	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
4183
		o1 = ADR(1, 0, REGTMP)
4184
		o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
4185
		rel := obj.Addrel(c.cursym)
4186
		rel.Off = int32(c.pc)
4187
		rel.Siz = 8
4188
		rel.Sym = p.From.Sym
4189
		rel.Add = 0
4190
		rel.Type = objabi.R_ARM64_TLS_IE
4191
		if p.From.Offset != 0 {
4192
			c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4193
		}
4194

4195
	case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
4196
		o1 = ADR(1, 0, REGTMP)
4197
		o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
4198
		rel := obj.Addrel(c.cursym)
4199
		rel.Off = int32(c.pc)
4200
		rel.Siz = 8
4201
		rel.Sym = p.From.Sym
4202
		rel.Add = 0
4203
		rel.Type = objabi.R_ARM64_GOTPCREL
4204

4205
	case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2 Vm.<T>, Vn.<T>, Vd.<T> */
4206
		af := int((p.From.Reg >> 5) & 15)
4207
		af3 := int((p.Reg >> 5) & 15)
4208
		at := int((p.To.Reg >> 5) & 15)
4209
		if af != af3 || af != at {
4210
			c.ctxt.Diag("operand mismatch: %v", p)
4211
			break
4212
		}
4213
		o1 = c.oprrr(p, p.As)
4214
		rf := int((p.From.Reg) & 31)
4215
		rt := int((p.To.Reg) & 31)
4216
		r := int((p.Reg) & 31)
4217

4218
		Q := 0
4219
		size := 0
4220
		switch af {
4221
		case ARNG_16B:
4222
			Q = 1
4223
			size = 0
4224
		case ARNG_2D:
4225
			Q = 1
4226
			size = 3
4227
		case ARNG_2S:
4228
			Q = 0
4229
			size = 2
4230
		case ARNG_4H:
4231
			Q = 0
4232
			size = 1
4233
		case ARNG_4S:
4234
			Q = 1
4235
			size = 2
4236
		case ARNG_8B:
4237
			Q = 0
4238
			size = 0
4239
		case ARNG_8H:
4240
			Q = 1
4241
			size = 1
4242
		default:
4243
			c.ctxt.Diag("invalid arrangement: %v", p)
4244
		}
4245

4246
		switch p.As {
4247
		case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
4248
			if af != ARNG_16B && af != ARNG_8B {
4249
				c.ctxt.Diag("invalid arrangement: %v", p)
4250
			}
4251
		case AVFMLA, AVFMLS:
4252
			if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
4253
				c.ctxt.Diag("invalid arrangement: %v", p)
4254
			}
4255
		}
4256
		switch p.As {
4257
		case AVAND, AVEOR:
4258
			size = 0
4259
		case AVBSL:
4260
			size = 1
4261
		case AVORR, AVBIT, AVBIF:
4262
			size = 2
4263
		case AVFMLA, AVFMLS:
4264
			if af == ARNG_2D {
4265
				size = 1
4266
			} else {
4267
				size = 0
4268
			}
4269
		}
4270

4271
		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4272

4273
	case 73: /* vmov V.<T>[index], R */
4274
		rf := int(p.From.Reg)
4275
		rt := int(p.To.Reg)
4276
		imm5 := 0
4277
		o1 = 7<<25 | 0xf<<10
4278
		index := int(p.From.Index)
4279
		switch (p.From.Reg >> 5) & 15 {
4280
		case ARNG_B:
4281
			c.checkindex(p, index, 15)
4282
			imm5 |= 1
4283
			imm5 |= index << 1
4284
		case ARNG_H:
4285
			c.checkindex(p, index, 7)
4286
			imm5 |= 2
4287
			imm5 |= index << 2
4288
		case ARNG_S:
4289
			c.checkindex(p, index, 3)
4290
			imm5 |= 4
4291
			imm5 |= index << 3
4292
		case ARNG_D:
4293
			c.checkindex(p, index, 1)
4294
			imm5 |= 8
4295
			imm5 |= index << 4
4296
			o1 |= 1 << 30
4297
		default:
4298
			c.ctxt.Diag("invalid arrangement: %v", p)
4299
		}
4300
		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4301

4302
	case 74:
4303
		//	add $O, R, Rtmp or sub $O, R, Rtmp
4304
		//	ldp (Rtmp), (R1, R2)
4305
		r := int(p.From.Reg)
4306
		if r == obj.REG_NONE {
4307
			r = int(o.param)
4308
		}
4309
		if r == obj.REG_NONE {
4310
			c.ctxt.Diag("invalid ldp source: %v", p)
4311
		}
4312
		v := int32(c.regoff(&p.From))
4313

4314
		if v > 0 {
4315
			if v > 4095 {
4316
				c.ctxt.Diag("offset out of range: %v", p)
4317
			}
4318
			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4319
		}
4320
		if v < 0 {
4321
			if v < -4095 {
4322
				c.ctxt.Diag("offset out of range: %v", p)
4323
			}
4324
			o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4325
		}
4326
		o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4327

4328
	case 75:
4329
		//	mov $L, Rtmp (from constant pool)
4330
		//	add Rtmp, R, Rtmp
4331
		//	ldp (Rtmp), (R1, R2)
4332
		r := int(p.From.Reg)
4333
		if r == obj.REG_NONE {
4334
			r = int(o.param)
4335
		}
4336
		if r == obj.REG_NONE {
4337
			c.ctxt.Diag("invalid ldp source: %v", p)
4338
		}
4339
		o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4340
		o2 = c.opxrrr(p, AADD, false)
4341
		o2 |= (REGTMP & 31) << 16
4342
		o2 |= uint32(r&31) << 5
4343
		o2 |= uint32(REGTMP & 31)
4344
		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4345

4346
	case 76:
4347
		//	add $O, R, Rtmp or sub $O, R, Rtmp
4348
		//	stp (R1, R2), (Rtmp)
4349
		r := int(p.To.Reg)
4350
		if r == obj.REG_NONE {
4351
			r = int(o.param)
4352
		}
4353
		if r == obj.REG_NONE {
4354
			c.ctxt.Diag("invalid stp destination: %v", p)
4355
		}
4356
		v := int32(c.regoff(&p.To))
4357
		if v > 0 {
4358
			if v > 4095 {
4359
				c.ctxt.Diag("offset out of range: %v", p)
4360
			}
4361
			o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4362
		}
4363
		if v < 0 {
4364
			if v < -4095 {
4365
				c.ctxt.Diag("offset out of range: %v", p)
4366
			}
4367
			o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4368
		}
4369
		o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4370

4371
	case 77:
4372
		//	mov $L, Rtmp (from constant pool)
4373
		//	add Rtmp, R, Rtmp
4374
		//	stp (R1, R2), (Rtmp)
4375
		r := int(p.To.Reg)
4376
		if r == obj.REG_NONE {
4377
			r = int(o.param)
4378
		}
4379
		if r == obj.REG_NONE {
4380
			c.ctxt.Diag("invalid stp destination: %v", p)
4381
		}
4382
		o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
4383
		o2 = c.opxrrr(p, AADD, false)
4384
		o2 |= REGTMP & 31 << 16
4385
		o2 |= uint32(r&31) << 5
4386
		o2 |= uint32(REGTMP & 31)
4387
		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4388

4389
	case 78: /* vmov R, V.<T>[index] */
4390
		rf := int(p.From.Reg)
4391
		rt := int(p.To.Reg)
4392
		imm5 := 0
4393
		o1 = 1<<30 | 7<<25 | 7<<10
4394
		index := int(p.To.Index)
4395
		switch (p.To.Reg >> 5) & 15 {
4396
		case ARNG_B:
4397
			c.checkindex(p, index, 15)
4398
			imm5 |= 1
4399
			imm5 |= index << 1
4400
		case ARNG_H:
4401
			c.checkindex(p, index, 7)
4402
			imm5 |= 2
4403
			imm5 |= index << 2
4404
		case ARNG_S:
4405
			c.checkindex(p, index, 3)
4406
			imm5 |= 4
4407
			imm5 |= index << 3
4408
		case ARNG_D:
4409
			c.checkindex(p, index, 1)
4410
			imm5 |= 8
4411
			imm5 |= index << 4
4412
		default:
4413
			c.ctxt.Diag("invalid arrangement: %v", p)
4414
		}
4415
		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4416

4417
	case 79: /* vdup Vn.<T>[index], Vd.<T> */
4418
		rf := int(p.From.Reg)
4419
		rt := int(p.To.Reg)
4420
		o1 = 7<<25 | 1<<10
4421
		var imm5, Q int
4422
		index := int(p.From.Index)
4423
		switch (p.To.Reg >> 5) & 15 {
4424
		case ARNG_16B:
4425
			c.checkindex(p, index, 15)
4426
			Q = 1
4427
			imm5 = 1
4428
			imm5 |= index << 1
4429
		case ARNG_2D:
4430
			c.checkindex(p, index, 1)
4431
			Q = 1
4432
			imm5 = 8
4433
			imm5 |= index << 4
4434
		case ARNG_2S:
4435
			c.checkindex(p, index, 3)
4436
			Q = 0
4437
			imm5 = 4
4438
			imm5 |= index << 3
4439
		case ARNG_4H:
4440
			c.checkindex(p, index, 7)
4441
			Q = 0
4442
			imm5 = 2
4443
			imm5 |= index << 2
4444
		case ARNG_4S:
4445
			c.checkindex(p, index, 3)
4446
			Q = 1
4447
			imm5 = 4
4448
			imm5 |= index << 3
4449
		case ARNG_8B:
4450
			c.checkindex(p, index, 15)
4451
			Q = 0
4452
			imm5 = 1
4453
			imm5 |= index << 1
4454
		case ARNG_8H:
4455
			c.checkindex(p, index, 7)
4456
			Q = 1
4457
			imm5 = 2
4458
			imm5 |= index << 2
4459
		default:
4460
			c.ctxt.Diag("invalid arrangement: %v", p)
4461
		}
4462
		o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
4463
		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4464

4465
	case 80: /* vmov V.<T>[index], Vn */
4466
		rf := int(p.From.Reg)
4467
		rt := int(p.To.Reg)
4468
		imm5 := 0
4469
		index := int(p.From.Index)
4470
		switch p.As {
4471
		case AVMOV:
4472
			o1 = 1<<30 | 15<<25 | 1<<10
4473
			switch (p.From.Reg >> 5) & 15 {
4474
			case ARNG_B:
4475
				c.checkindex(p, index, 15)
4476
				imm5 |= 1
4477
				imm5 |= index << 1
4478
			case ARNG_H:
4479
				c.checkindex(p, index, 7)
4480
				imm5 |= 2
4481
				imm5 |= index << 2
4482
			case ARNG_S:
4483
				c.checkindex(p, index, 3)
4484
				imm5 |= 4
4485
				imm5 |= index << 3
4486
			case ARNG_D:
4487
				c.checkindex(p, index, 1)
4488
				imm5 |= 8
4489
				imm5 |= index << 4
4490
			default:
4491
				c.ctxt.Diag("invalid arrangement: %v", p)
4492
			}
4493
		default:
4494
			c.ctxt.Diag("unsupported op %v", p.As)
4495
		}
4496
		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4497

4498
	case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
4499
		c.checkoffset(p, p.As)
4500
		r := int(p.From.Reg)
4501
		o1 = c.oprrr(p, p.As)
4502
		if o.scond == C_XPOST {
4503
			o1 |= 1 << 23
4504
			if p.From.Index == 0 {
4505
				// immediate offset variant
4506
				o1 |= 0x1f << 16
4507
			} else {
4508
				// register offset variant
4509
				if isRegShiftOrExt(&p.From) {
4510
					c.ctxt.Diag("invalid extended register op: %v\n", p)
4511
				}
4512
				o1 |= uint32(p.From.Index&0x1f) << 16
4513
			}
4514
		}
4515
		o1 |= uint32(p.To.Offset)
4516
		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
4517
		// add opcode(bit 12-15) for vld1, mask it off if it's not vld1
4518
		o1 = c.maskOpvldvst(p, o1)
4519
		o1 |= uint32(r&31) << 5
4520

4521
	case 82: /* vmov Rn, Vd.<T> */
4522
		rf := int(p.From.Reg)
4523
		rt := int(p.To.Reg)
4524
		o1 = 7<<25 | 3<<10
4525
		var imm5, Q uint32
4526
		switch (p.To.Reg >> 5) & 15 {
4527
		case ARNG_16B:
4528
			Q = 1
4529
			imm5 = 1
4530
		case ARNG_2D:
4531
			Q = 1
4532
			imm5 = 8
4533
		case ARNG_2S:
4534
			Q = 0
4535
			imm5 = 4
4536
		case ARNG_4H:
4537
			Q = 0
4538
			imm5 = 2
4539
		case ARNG_4S:
4540
			Q = 1
4541
			imm5 = 4
4542
		case ARNG_8B:
4543
			Q = 0
4544
			imm5 = 1
4545
		case ARNG_8H:
4546
			Q = 1
4547
			imm5 = 2
4548
		default:
4549
			c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p)
4550
		}
4551
		o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
4552
		o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4553

4554
	case 83: /* vmov Vn.<T>, Vd.<T> */
4555
		af := int((p.From.Reg >> 5) & 15)
4556
		at := int((p.To.Reg >> 5) & 15)
4557
		if af != at {
4558
			c.ctxt.Diag("invalid arrangement: %v\n", p)
4559
		}
4560
		o1 = c.oprrr(p, p.As)
4561
		rf := int((p.From.Reg) & 31)
4562
		rt := int((p.To.Reg) & 31)
4563

4564
		var Q, size uint32
4565
		switch af {
4566
		case ARNG_8B:
4567
			Q = 0
4568
			size = 0
4569
		case ARNG_16B:
4570
			Q = 1
4571
			size = 0
4572
		case ARNG_4H:
4573
			Q = 0
4574
			size = 1
4575
		case ARNG_8H:
4576
			Q = 1
4577
			size = 1
4578
		case ARNG_2S:
4579
			Q = 0
4580
			size = 2
4581
		case ARNG_4S:
4582
			Q = 1
4583
			size = 2
4584
		default:
4585
			c.ctxt.Diag("invalid arrangement: %v\n", p)
4586
		}
4587

4588
		if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
4589
			c.ctxt.Diag("invalid arrangement: %v", p)
4590
		}
4591

4592
		if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
4593
			c.ctxt.Diag("invalid arrangement: %v", p)
4594
		}
4595

4596
		if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
4597
			c.ctxt.Diag("invalid arrangement: %v", p)
4598
		}
4599

4600
		if p.As == AVMOV {
4601
			o1 |= uint32(rf&31) << 16
4602
		}
4603

4604
		if p.As == AVRBIT {
4605
			size = 1
4606
		}
4607

4608
		o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
4609

4610
	case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
4611
		c.checkoffset(p, p.As)
4612
		r := int(p.To.Reg)
4613
		o1 = 3 << 26
4614
		if o.scond == C_XPOST {
4615
			o1 |= 1 << 23
4616
			if p.To.Index == 0 {
4617
				// immediate offset variant
4618
				o1 |= 0x1f << 16
4619
			} else {
4620
				// register offset variant
4621
				if isRegShiftOrExt(&p.To) {
4622
					c.ctxt.Diag("invalid extended register: %v\n", p)
4623
				}
4624
				o1 |= uint32(p.To.Index&31) << 16
4625
			}
4626
		}
4627
		o1 |= uint32(p.From.Offset)
4628
		// cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
4629
		// add opcode(bit 12-15) for vst1, mask it off if it's not vst1
4630
		o1 = c.maskOpvldvst(p, o1)
4631
		o1 |= uint32(r&31) << 5
4632

4633
	case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
4634
		af := int((p.From.Reg >> 5) & 15)
4635
		o1 = c.oprrr(p, p.As)
4636
		rf := int((p.From.Reg) & 31)
4637
		rt := int((p.To.Reg) & 31)
4638
		Q := 0
4639
		size := 0
4640
		switch af {
4641
		case ARNG_8B:
4642
			Q = 0
4643
			size = 0
4644
		case ARNG_16B:
4645
			Q = 1
4646
			size = 0
4647
		case ARNG_4H:
4648
			Q = 0
4649
			size = 1
4650
		case ARNG_8H:
4651
			Q = 1
4652
			size = 1
4653
		case ARNG_4S:
4654
			Q = 1
4655
			size = 2
4656
		default:
4657
			c.ctxt.Diag("invalid arrangement: %v\n", p)
4658
		}
4659
		o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
4660

4661
	case 86: /* vmovi $imm8, Vd.<T>*/
4662
		at := int((p.To.Reg >> 5) & 15)
4663
		r := int(p.From.Offset)
4664
		if r > 255 || r < 0 {
4665
			c.ctxt.Diag("immediate constant out of range: %v\n", p)
4666
		}
4667
		rt := int((p.To.Reg) & 31)
4668
		Q := 0
4669
		switch at {
4670
		case ARNG_8B:
4671
			Q = 0
4672
		case ARNG_16B:
4673
			Q = 1
4674
		default:
4675
			c.ctxt.Diag("invalid arrangement: %v\n", p)
4676
		}
4677
		o1 = 0xf<<24 | 0xe<<12 | 1<<10
4678
		o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
4679

4680
	case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
4681
		o1 = ADR(1, 0, REGTMP)
4682
		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4683
		rel := obj.Addrel(c.cursym)
4684
		rel.Off = int32(c.pc)
4685
		rel.Siz = 8
4686
		rel.Sym = p.To.Sym
4687
		rel.Add = p.To.Offset
4688
		rel.Type = objabi.R_ADDRARM64
4689
		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4690

4691
	case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
4692
		o1 = ADR(1, 0, REGTMP)
4693
		o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4694
		rel := obj.Addrel(c.cursym)
4695
		rel.Off = int32(c.pc)
4696
		rel.Siz = 8
4697
		rel.Sym = p.From.Sym
4698
		rel.Add = p.From.Offset
4699
		rel.Type = objabi.R_ADDRARM64
4700
		o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4701

4702
	case 89: /* vadd/vsub Vm, Vn, Vd */
4703
		switch p.As {
4704
		case AVADD:
4705
			o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
4706

4707
		case AVSUB:
4708
			o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
4709

4710
		default:
4711
			c.ctxt.Diag("bad opcode: %v\n", p)
4712
			break
4713
		}
4714

4715
		rf := int(p.From.Reg)
4716
		rt := int(p.To.Reg)
4717
		r := int(p.Reg)
4718
		if r == 0 {
4719
			r = rt
4720
		}
4721
		o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4722

4723
	// This is supposed to be something that stops execution.
4724
	// It's not supposed to be reached, ever, but if it is, we'd
4725
	// like to be able to tell how we got there. Assemble as
4726
	// 0xbea71700 which is guaranteed to raise undefined instruction
4727
	// exception.
4728
	case 90:
4729
		o1 = 0xbea71700
4730

4731
	case 91: /* prfm imm(Rn), <prfop | $imm5> */
4732
		imm := uint32(p.From.Offset)
4733
		r := p.From.Reg
4734
		v := uint32(0xff)
4735
		if p.To.Type == obj.TYPE_CONST {
4736
			v = uint32(p.To.Offset)
4737
			if v > 31 {
4738
				c.ctxt.Diag("illegal prefetch operation\n%v", p)
4739
			}
4740
		} else {
4741
			for i := 0; i < len(prfopfield); i++ {
4742
				if prfopfield[i].reg == p.To.Reg {
4743
					v = prfopfield[i].enc
4744
					break
4745
				}
4746
			}
4747
			if v == 0xff {
4748
				c.ctxt.Diag("illegal prefetch operation:\n%v", p)
4749
			}
4750
		}
4751

4752
		o1 = c.opldrpp(p, p.As)
4753
		o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
4754

4755
	case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
4756
		rf := int(p.From.Reg)
4757
		rt := int(p.To.Reg)
4758
		imm4 := 0
4759
		imm5 := 0
4760
		o1 = 3<<29 | 7<<25 | 1<<10
4761
		index1 := int(p.To.Index)
4762
		index2 := int(p.From.Index)
4763
		if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
4764
			c.ctxt.Diag("operand mismatch: %v", p)
4765
		}
4766
		switch (p.To.Reg >> 5) & 15 {
4767
		case ARNG_B:
4768
			c.checkindex(p, index1, 15)
4769
			c.checkindex(p, index2, 15)
4770
			imm5 |= 1
4771
			imm5 |= index1 << 1
4772
			imm4 |= index2
4773
		case ARNG_H:
4774
			c.checkindex(p, index1, 7)
4775
			c.checkindex(p, index2, 7)
4776
			imm5 |= 2
4777
			imm5 |= index1 << 2
4778
			imm4 |= index2 << 1
4779
		case ARNG_S:
4780
			c.checkindex(p, index1, 3)
4781
			c.checkindex(p, index2, 3)
4782
			imm5 |= 4
4783
			imm5 |= index1 << 3
4784
			imm4 |= index2 << 2
4785
		case ARNG_D:
4786
			c.checkindex(p, index1, 1)
4787
			c.checkindex(p, index2, 1)
4788
			imm5 |= 8
4789
			imm5 |= index1 << 4
4790
			imm4 |= index2 << 3
4791
		default:
4792
			c.ctxt.Diag("invalid arrangement: %v", p)
4793
		}
4794
		o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
4795

4796
	case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */
4797
		af := int((p.From.Reg >> 5) & 15)
4798
		at := int((p.To.Reg >> 5) & 15)
4799
		a := int((p.Reg >> 5) & 15)
4800

4801
		var Q, size uint32
4802
		if p.As == AVPMULL {
4803
			Q = 0
4804
		} else {
4805
			Q = 1
4806
		}
4807

4808
		var fArng int
4809
		switch at {
4810
		case ARNG_8H:
4811
			if Q == 0 {
4812
				fArng = ARNG_8B
4813
			} else {
4814
				fArng = ARNG_16B
4815
			}
4816
			size = 0
4817
		case ARNG_1Q:
4818
			if Q == 0 {
4819
				fArng = ARNG_1D
4820
			} else {
4821
				fArng = ARNG_2D
4822
			}
4823
			size = 3
4824
		default:
4825
			c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p)
4826
		}
4827

4828
		if af != a || af != fArng {
4829
			c.ctxt.Diag("invalid arrangement: %v", p)
4830
		}
4831

4832
		o1 = c.oprrr(p, p.As)
4833
		rf := int((p.From.Reg) & 31)
4834
		rt := int((p.To.Reg) & 31)
4835
		r := int((p.Reg) & 31)
4836

4837
		o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4838

4839
	case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
4840
		af := int(((p.GetFrom3().Reg) >> 5) & 15)
4841
		at := int((p.To.Reg >> 5) & 15)
4842
		a := int((p.Reg >> 5) & 15)
4843
		index := int(p.From.Offset)
4844

4845
		if af != a || af != at {
4846
			c.ctxt.Diag("invalid arrangement: %v", p)
4847
			break
4848
		}
4849

4850
		var Q uint32
4851
		var b int
4852
		if af == ARNG_8B {
4853
			Q = 0
4854
			b = 7
4855
		} else if af == ARNG_16B {
4856
			Q = 1
4857
			b = 15
4858
		} else {
4859
			c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
4860
			break
4861
		}
4862

4863
		if index < 0 || index > b {
4864
			c.ctxt.Diag("illegal offset: %v", p)
4865
		}
4866

4867
		o1 = c.opirr(p, p.As)
4868
		rf := int((p.GetFrom3().Reg) & 31)
4869
		rt := int((p.To.Reg) & 31)
4870
		r := int((p.Reg) & 31)
4871

4872
		o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
4873

4874
	case 95: /* vushr $shift, Vn.<T>, Vd.<T> */
4875
		at := int((p.To.Reg >> 5) & 15)
4876
		af := int((p.Reg >> 5) & 15)
4877
		shift := int(p.From.Offset)
4878

4879
		if af != at {
4880
			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
4881
		}
4882

4883
		var Q uint32
4884
		var imax, esize int
4885

4886
		switch af {
4887
		case ARNG_8B, ARNG_4H, ARNG_2S:
4888
			Q = 0
4889
		case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
4890
			Q = 1
4891
		default:
4892
			c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
4893
		}
4894

4895
		switch af {
4896
		case ARNG_8B, ARNG_16B:
4897
			imax = 15
4898
			esize = 8
4899
		case ARNG_4H, ARNG_8H:
4900
			imax = 31
4901
			esize = 16
4902
		case ARNG_2S, ARNG_4S:
4903
			imax = 63
4904
			esize = 32
4905
		case ARNG_2D:
4906
			imax = 127
4907
			esize = 64
4908
		}
4909

4910
		imm := 0
4911

4912
		switch p.As {
4913
		case AVUSHR, AVSRI:
4914
			imm = esize*2 - shift
4915
			if imm < esize || imm > imax {
4916
				c.ctxt.Diag("shift out of range: %v", p)
4917
			}
4918
		case AVSHL:
4919
			imm = esize + shift
4920
			if imm > imax {
4921
				c.ctxt.Diag("shift out of range: %v", p)
4922
			}
4923
		default:
4924
			c.ctxt.Diag("invalid instruction %v\n", p)
4925
		}
4926

4927
		o1 = c.opirr(p, p.As)
4928
		rt := int((p.To.Reg) & 31)
4929
		rf := int((p.Reg) & 31)
4930

4931
		o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4932

4933
	case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
4934
		af := int((p.From.Reg >> 5) & 15)
4935
		rt := int((p.From.Reg) & 31)
4936
		rf := int((p.To.Reg) & 31)
4937
		r := int(p.To.Index & 31)
4938
		index := int(p.From.Index)
4939
		offset := int32(c.regoff(&p.To))
4940

4941
		if o.scond == C_XPOST {
4942
			if (p.To.Index != 0) && (offset != 0) {
4943
				c.ctxt.Diag("invalid offset: %v", p)
4944
			}
4945
			if p.To.Index == 0 && offset == 0 {
4946
				c.ctxt.Diag("invalid offset: %v", p)
4947
			}
4948
		}
4949

4950
		if offset != 0 {
4951
			r = 31
4952
		}
4953

4954
		var Q, S, size int
4955
		var opcode uint32
4956
		switch af {
4957
		case ARNG_B:
4958
			c.checkindex(p, index, 15)
4959
			if o.scond == C_XPOST && offset != 0 && offset != 1 {
4960
				c.ctxt.Diag("invalid offset: %v", p)
4961
			}
4962
			Q = index >> 3
4963
			S = (index >> 2) & 1
4964
			size = index & 3
4965
			opcode = 0
4966
		case ARNG_H:
4967
			c.checkindex(p, index, 7)
4968
			if o.scond == C_XPOST && offset != 0 && offset != 2 {
4969
				c.ctxt.Diag("invalid offset: %v", p)
4970
			}
4971
			Q = index >> 2
4972
			S = (index >> 1) & 1
4973
			size = (index & 1) << 1
4974
			opcode = 2
4975
		case ARNG_S:
4976
			c.checkindex(p, index, 3)
4977
			if o.scond == C_XPOST && offset != 0 && offset != 4 {
4978
				c.ctxt.Diag("invalid offset: %v", p)
4979
			}
4980
			Q = index >> 1
4981
			S = index & 1
4982
			size = 0
4983
			opcode = 4
4984
		case ARNG_D:
4985
			c.checkindex(p, index, 1)
4986
			if o.scond == C_XPOST && offset != 0 && offset != 8 {
4987
				c.ctxt.Diag("invalid offset: %v", p)
4988
			}
4989
			Q = index
4990
			S = 0
4991
			size = 1
4992
			opcode = 4
4993
		default:
4994
			c.ctxt.Diag("invalid arrangement: %v", p)
4995
		}
4996

4997
		if o.scond == C_XPOST {
4998
			o1 |= 27 << 23
4999
		} else {
5000
			o1 |= 26 << 23
5001
		}
5002

5003
		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)
5004

5005
	case 97: /* vld1 offset(Rn), vt.<T>[index] */
5006
		at := int((p.To.Reg >> 5) & 15)
5007
		rt := int((p.To.Reg) & 31)
5008
		rf := int((p.From.Reg) & 31)
5009
		r := int(p.From.Index & 31)
5010
		index := int(p.To.Index)
5011
		offset := int32(c.regoff(&p.From))
5012

5013
		if o.scond == C_XPOST {
5014
			if (p.From.Index != 0) && (offset != 0) {
5015
				c.ctxt.Diag("invalid offset: %v", p)
5016
			}
5017
			if p.From.Index == 0 && offset == 0 {
5018
				c.ctxt.Diag("invalid offset: %v", p)
5019
			}
5020
		}
5021

5022
		if offset != 0 {
5023
			r = 31
5024
		}
5025

5026
		Q := 0
5027
		S := 0
5028
		size := 0
5029
		var opcode uint32
5030
		switch at {
5031
		case ARNG_B:
5032
			c.checkindex(p, index, 15)
5033
			if o.scond == C_XPOST && offset != 0 && offset != 1 {
5034
				c.ctxt.Diag("invalid offset: %v", p)
5035
			}
5036
			Q = index >> 3
5037
			S = (index >> 2) & 1
5038
			size = index & 3
5039
			opcode = 0
5040
		case ARNG_H:
5041
			c.checkindex(p, index, 7)
5042
			if o.scond == C_XPOST && offset != 0 && offset != 2 {
5043
				c.ctxt.Diag("invalid offset: %v", p)
5044
			}
5045
			Q = index >> 2
5046
			S = (index >> 1) & 1
5047
			size = (index & 1) << 1
5048
			opcode = 2
5049
		case ARNG_S:
5050
			c.checkindex(p, index, 3)
5051
			if o.scond == C_XPOST && offset != 0 && offset != 4 {
5052
				c.ctxt.Diag("invalid offset: %v", p)
5053
			}
5054
			Q = index >> 1
5055
			S = index & 1
5056
			size = 0
5057
			opcode = 4
5058
		case ARNG_D:
5059
			c.checkindex(p, index, 1)
5060
			if o.scond == C_XPOST && offset != 0 && offset != 8 {
5061
				c.ctxt.Diag("invalid offset: %v", p)
5062
			}
5063
			Q = index
5064
			S = 0
5065
			size = 1
5066
			opcode = 4
5067
		default:
5068
			c.ctxt.Diag("invalid arrangement: %v", p)
5069
		}
5070

5071
		if o.scond == C_XPOST {
5072
			o1 |= 110 << 21
5073
		} else {
5074
			o1 |= 106 << 21
5075
		}
5076

5077
		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)
5078

5079
	case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
5080
		if isRegShiftOrExt(&p.From) {
5081
			// extended or shifted offset register.
5082
			c.checkShiftAmount(p, &p.From)
5083

5084
			o1 = c.opldrr(p, p.As, true)
5085
			o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
5086
		} else {
5087
			// (Rn)(Rm), no extension or shift.
5088
			o1 = c.opldrr(p, p.As, false)
5089
			o1 |= uint32(p.From.Index&31) << 16
5090
		}
5091
		o1 |= uint32(p.From.Reg&31) << 5
5092
		rt := int(p.To.Reg)
5093
		o1 |= uint32(rt & 31)
5094

5095
	case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
5096
		if isRegShiftOrExt(&p.To) {
5097
			// extended or shifted offset register.
5098
			c.checkShiftAmount(p, &p.To)
5099

5100
			o1 = c.opstrr(p, p.As, true)
5101
			o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
5102
		} else {
5103
			// (Rn)(Rm), no extension or shift.
5104
			o1 = c.opstrr(p, p.As, false)
5105
			o1 |= uint32(p.To.Index&31) << 16
5106
		}
5107
		o1 |= uint32(p.To.Reg&31) << 5
5108
		rf := int(p.From.Reg)
5109
		o1 |= uint32(rf & 31)
5110

5111
	case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
5112
		af := int((p.From.Reg >> 5) & 15)
5113
		at := int((p.To.Reg >> 5) & 15)
5114
		if af != at {
5115
			c.ctxt.Diag("invalid arrangement: %v\n", p)
5116
		}
5117
		var q, len uint32
5118
		switch af {
5119
		case ARNG_8B:
5120
			q = 0
5121
		case ARNG_16B:
5122
			q = 1
5123
		default:
5124
			c.ctxt.Diag("invalid arrangement: %v", p)
5125
		}
5126
		rf := int(p.From.Reg)
5127
		rt := int(p.To.Reg)
5128
		offset := int(p.GetFrom3().Offset)
5129
		opcode := (offset >> 12) & 15
5130
		switch opcode {
5131
		case 0x7:
5132
			len = 0 // one register
5133
		case 0xa:
5134
			len = 1 // two register
5135
		case 0x6:
5136
			len = 2 // three registers
5137
		case 0x2:
5138
			len = 3 // four registers
5139
		default:
5140
			c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
5141
		}
5142
		o1 = q<<30 | 0xe<<24 | len<<13
5143
		o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
5144

5145
	case 101: // FOMVQ/FMOVD $vcon, Vd -> load from constant pool.
5146
		o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
5147

5148
	case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
5149
		o1 = c.opirr(p, p.As)
5150
		rf := p.Reg
5151
		af := uint8((p.Reg >> 5) & 15)
5152
		at := uint8((p.To.Reg >> 5) & 15)
5153
		shift := int(p.From.Offset)
5154
		if p.As == AVUXTL || p.As == AVUXTL2 {
5155
			rf = p.From.Reg
5156
			af = uint8((p.From.Reg >> 5) & 15)
5157
			shift = 0
5158
		}
5159

5160
		pack := func(q, x, y uint8) uint32 {
5161
			return uint32(q)<<16 | uint32(x)<<8 | uint32(y)
5162
		}
5163

5164
		var Q uint8 = uint8(o1>>30) & 1
5165
		var immh, width uint8
5166
		switch pack(Q, af, at) {
5167
		case pack(0, ARNG_8B, ARNG_8H):
5168
			immh, width = 1, 8
5169
		case pack(1, ARNG_16B, ARNG_8H):
5170
			immh, width = 1, 8
5171
		case pack(0, ARNG_4H, ARNG_4S):
5172
			immh, width = 2, 16
5173
		case pack(1, ARNG_8H, ARNG_4S):
5174
			immh, width = 2, 16
5175
		case pack(0, ARNG_2S, ARNG_2D):
5176
			immh, width = 4, 32
5177
		case pack(1, ARNG_4S, ARNG_2D):
5178
			immh, width = 4, 32
5179
		default:
5180
			c.ctxt.Diag("operand mismatch: %v\n", p)
5181
		}
5182
		if !(0 <= shift && shift <= int(width-1)) {
5183
			c.ctxt.Diag("shift amount out of range: %v\n", p)
5184
		}
5185
		o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
5186
	}
5187
	out[0] = o1
5188
	out[1] = o2
5189
	out[2] = o3
5190
	out[3] = o4
5191
	out[4] = o5
5192
}
5193

5194
/*
5195
 * basic Rm op Rn -> Rd (using shifted register with 0)
5196
 * also op Rn -> Rt
5197
 * also Rm*Rn op Ra -> Rd
5198
 * also Vm op Vn -> Vd
5199
 */
5200
func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
5201
	switch a {
5202
	case AADC:
5203
		return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5204

5205
	case AADCW:
5206
		return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5207

5208
	case AADCS:
5209
		return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5210

5211
	case AADCSW:
5212
		return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5213

5214
	case ANGC, ASBC:
5215
		return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5216

5217
	case ANGCS, ASBCS:
5218
		return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5219

5220
	case ANGCW, ASBCW:
5221
		return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5222

5223
	case ANGCSW, ASBCSW:
5224
		return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5225

5226
	case AADD:
5227
		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5228

5229
	case AADDW:
5230
		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5231

5232
	case ACMN, AADDS:
5233
		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5234

5235
	case ACMNW, AADDSW:
5236
		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5237

5238
	case ASUB:
5239
		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5240

5241
	case ASUBW:
5242
		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5243

5244
	case ACMP, ASUBS:
5245
		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5246

5247
	case ACMPW, ASUBSW:
5248
		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5249

5250
	case AAND:
5251
		return S64 | 0<<29 | 0xA<<24
5252

5253
	case AANDW:
5254
		return S32 | 0<<29 | 0xA<<24
5255

5256
	case AMOVD, AORR:
5257
		return S64 | 1<<29 | 0xA<<24
5258

5259
		//	case AMOVW:
5260
	case AMOVWU, AORRW:
5261
		return S32 | 1<<29 | 0xA<<24
5262

5263
	case AEOR:
5264
		return S64 | 2<<29 | 0xA<<24
5265

5266
	case AEORW:
5267
		return S32 | 2<<29 | 0xA<<24
5268

5269
	case AANDS, ATST:
5270
		return S64 | 3<<29 | 0xA<<24
5271

5272
	case AANDSW, ATSTW:
5273
		return S32 | 3<<29 | 0xA<<24
5274

5275
	case ABIC:
5276
		return S64 | 0<<29 | 0xA<<24 | 1<<21
5277

5278
	case ABICW:
5279
		return S32 | 0<<29 | 0xA<<24 | 1<<21
5280

5281
	case ABICS:
5282
		return S64 | 3<<29 | 0xA<<24 | 1<<21
5283

5284
	case ABICSW:
5285
		return S32 | 3<<29 | 0xA<<24 | 1<<21
5286

5287
	case AEON:
5288
		return S64 | 2<<29 | 0xA<<24 | 1<<21
5289

5290
	case AEONW:
5291
		return S32 | 2<<29 | 0xA<<24 | 1<<21
5292

5293
	case AMVN, AORN:
5294
		return S64 | 1<<29 | 0xA<<24 | 1<<21
5295

5296
	case AMVNW, AORNW:
5297
		return S32 | 1<<29 | 0xA<<24 | 1<<21
5298

5299
	case AASR:
5300
		return S64 | OPDP2(10) /* also ASRV */
5301

5302
	case AASRW:
5303
		return S32 | OPDP2(10)
5304

5305
	case ALSL:
5306
		return S64 | OPDP2(8)
5307

5308
	case ALSLW:
5309
		return S32 | OPDP2(8)
5310

5311
	case ALSR:
5312
		return S64 | OPDP2(9)
5313

5314
	case ALSRW:
5315
		return S32 | OPDP2(9)
5316

5317
	case AROR:
5318
		return S64 | OPDP2(11)
5319

5320
	case ARORW:
5321
		return S32 | OPDP2(11)
5322

5323
	case ACCMN:
5324
		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
5325

5326
	case ACCMNW:
5327
		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5328

5329
	case ACCMP:
5330
		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
5331

5332
	case ACCMPW:
5333
		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5334

5335
	case ACRC32B:
5336
		return S32 | OPDP2(16)
5337

5338
	case ACRC32H:
5339
		return S32 | OPDP2(17)
5340

5341
	case ACRC32W:
5342
		return S32 | OPDP2(18)
5343

5344
	case ACRC32X:
5345
		return S64 | OPDP2(19)
5346

5347
	case ACRC32CB:
5348
		return S32 | OPDP2(20)
5349

5350
	case ACRC32CH:
5351
		return S32 | OPDP2(21)
5352

5353
	case ACRC32CW:
5354
		return S32 | OPDP2(22)
5355

5356
	case ACRC32CX:
5357
		return S64 | OPDP2(23)
5358

5359
	case ACSEL:
5360
		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5361

5362
	case ACSELW:
5363
		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5364

5365
	case ACSET:
5366
		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5367

5368
	case ACSETW:
5369
		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5370

5371
	case ACSETM:
5372
		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5373

5374
	case ACSETMW:
5375
		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5376

5377
	case ACINC, ACSINC:
5378
		return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5379

5380
	case ACINCW, ACSINCW:
5381
		return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5382

5383
	case ACINV, ACSINV:
5384
		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5385

5386
	case ACINVW, ACSINVW:
5387
		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5388

5389
	case ACNEG, ACSNEG:
5390
		return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5391

5392
	case ACNEGW, ACSNEGW:
5393
		return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5394

5395
	case AMUL, AMADD:
5396
		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5397

5398
	case AMULW, AMADDW:
5399
		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5400

5401
	case AMNEG, AMSUB:
5402
		return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5403

5404
	case AMNEGW, AMSUBW:
5405
		return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5406

5407
	case AMRS:
5408
		return SYSOP(1, 2, 0, 0, 0, 0, 0)
5409

5410
	case AMSR:
5411
		return SYSOP(0, 2, 0, 0, 0, 0, 0)
5412

5413
	case ANEG:
5414
		return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5415

5416
	case ANEGW:
5417
		return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5418

5419
	case ANEGS:
5420
		return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5421

5422
	case ANEGSW:
5423
		return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5424

5425
	case AREM, ASDIV:
5426
		return S64 | OPDP2(3)
5427

5428
	case AREMW, ASDIVW:
5429
		return S32 | OPDP2(3)
5430

5431
	case ASMULL, ASMADDL:
5432
		return OPDP3(1, 0, 1, 0)
5433

5434
	case ASMNEGL, ASMSUBL:
5435
		return OPDP3(1, 0, 1, 1)
5436

5437
	case ASMULH:
5438
		return OPDP3(1, 0, 2, 0)
5439

5440
	case AUMULL, AUMADDL:
5441
		return OPDP3(1, 0, 5, 0)
5442

5443
	case AUMNEGL, AUMSUBL:
5444
		return OPDP3(1, 0, 5, 1)
5445

5446
	case AUMULH:
5447
		return OPDP3(1, 0, 6, 0)
5448

5449
	case AUREM, AUDIV:
5450
		return S64 | OPDP2(2)
5451

5452
	case AUREMW, AUDIVW:
5453
		return S32 | OPDP2(2)
5454

5455
	case AAESE:
5456
		return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
5457

5458
	case AAESD:
5459
		return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
5460

5461
	case AAESMC:
5462
		return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
5463

5464
	case AAESIMC:
5465
		return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
5466

5467
	case ASHA1C:
5468
		return 0x5E<<24 | 0<<12
5469

5470
	case ASHA1P:
5471
		return 0x5E<<24 | 1<<12
5472

5473
	case ASHA1M:
5474
		return 0x5E<<24 | 2<<12
5475

5476
	case ASHA1SU0:
5477
		return 0x5E<<24 | 3<<12
5478

5479
	case ASHA256H:
5480
		return 0x5E<<24 | 4<<12
5481

5482
	case ASHA256H2:
5483
		return 0x5E<<24 | 5<<12
5484

5485
	case ASHA256SU1:
5486
		return 0x5E<<24 | 6<<12
5487

5488
	case ASHA1H:
5489
		return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
5490

5491
	case ASHA1SU1:
5492
		return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
5493

5494
	case ASHA256SU0:
5495
		return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
5496

5497
	case ASHA512H:
5498
		return 0xCE<<24 | 3<<21 | 8<<12
5499

5500
	case ASHA512H2:
5501
		return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
5502

5503
	case ASHA512SU1:
5504
		return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
5505

5506
	case ASHA512SU0:
5507
		return 0xCE<<24 | 3<<22 | 8<<12
5508

5509
	case AFCVTZSD:
5510
		return FPCVTI(1, 0, 1, 3, 0)
5511

5512
	case AFCVTZSDW:
5513
		return FPCVTI(0, 0, 1, 3, 0)
5514

5515
	case AFCVTZSS:
5516
		return FPCVTI(1, 0, 0, 3, 0)
5517

5518
	case AFCVTZSSW:
5519
		return FPCVTI(0, 0, 0, 3, 0)
5520

5521
	case AFCVTZUD:
5522
		return FPCVTI(1, 0, 1, 3, 1)
5523

5524
	case AFCVTZUDW:
5525
		return FPCVTI(0, 0, 1, 3, 1)
5526

5527
	case AFCVTZUS:
5528
		return FPCVTI(1, 0, 0, 3, 1)
5529

5530
	case AFCVTZUSW:
5531
		return FPCVTI(0, 0, 0, 3, 1)
5532

5533
	case ASCVTFD:
5534
		return FPCVTI(1, 0, 1, 0, 2)
5535

5536
	case ASCVTFS:
5537
		return FPCVTI(1, 0, 0, 0, 2)
5538

5539
	case ASCVTFWD:
5540
		return FPCVTI(0, 0, 1, 0, 2)
5541

5542
	case ASCVTFWS:
5543
		return FPCVTI(0, 0, 0, 0, 2)
5544

5545
	case AUCVTFD:
5546
		return FPCVTI(1, 0, 1, 0, 3)
5547

5548
	case AUCVTFS:
5549
		return FPCVTI(1, 0, 0, 0, 3)
5550

5551
	case AUCVTFWD:
5552
		return FPCVTI(0, 0, 1, 0, 3)
5553

5554
	case AUCVTFWS:
5555
		return FPCVTI(0, 0, 0, 0, 3)
5556

5557
	case AFADDS:
5558
		return FPOP2S(0, 0, 0, 2)
5559

5560
	case AFADDD:
5561
		return FPOP2S(0, 0, 1, 2)
5562

5563
	case AFSUBS:
5564
		return FPOP2S(0, 0, 0, 3)
5565

5566
	case AFSUBD:
5567
		return FPOP2S(0, 0, 1, 3)
5568

5569
	case AFMADDD:
5570
		return FPOP3S(0, 0, 1, 0, 0)
5571

5572
	case AFMADDS:
5573
		return FPOP3S(0, 0, 0, 0, 0)
5574

5575
	case AFMSUBD:
5576
		return FPOP3S(0, 0, 1, 0, 1)
5577

5578
	case AFMSUBS:
5579
		return FPOP3S(0, 0, 0, 0, 1)
5580

5581
	case AFNMADDD:
5582
		return FPOP3S(0, 0, 1, 1, 0)
5583

5584
	case AFNMADDS:
5585
		return FPOP3S(0, 0, 0, 1, 0)
5586

5587
	case AFNMSUBD:
5588
		return FPOP3S(0, 0, 1, 1, 1)
5589

5590
	case AFNMSUBS:
5591
		return FPOP3S(0, 0, 0, 1, 1)
5592

5593
	case AFMULS:
5594
		return FPOP2S(0, 0, 0, 0)
5595

5596
	case AFMULD:
5597
		return FPOP2S(0, 0, 1, 0)
5598

5599
	case AFDIVS:
5600
		return FPOP2S(0, 0, 0, 1)
5601

5602
	case AFDIVD:
5603
		return FPOP2S(0, 0, 1, 1)
5604

5605
	case AFMAXS:
5606
		return FPOP2S(0, 0, 0, 4)
5607

5608
	case AFMINS:
5609
		return FPOP2S(0, 0, 0, 5)
5610

5611
	case AFMAXD:
5612
		return FPOP2S(0, 0, 1, 4)
5613

5614
	case AFMIND:
5615
		return FPOP2S(0, 0, 1, 5)
5616

5617
	case AFMAXNMS:
5618
		return FPOP2S(0, 0, 0, 6)
5619

5620
	case AFMAXNMD:
5621
		return FPOP2S(0, 0, 1, 6)
5622

5623
	case AFMINNMS:
5624
		return FPOP2S(0, 0, 0, 7)
5625

5626
	case AFMINNMD:
5627
		return FPOP2S(0, 0, 1, 7)
5628

5629
	case AFNMULS:
5630
		return FPOP2S(0, 0, 0, 8)
5631

5632
	case AFNMULD:
5633
		return FPOP2S(0, 0, 1, 8)
5634

5635
	case AFCMPS:
5636
		return FPCMP(0, 0, 0, 0, 0)
5637

5638
	case AFCMPD:
5639
		return FPCMP(0, 0, 1, 0, 0)
5640

5641
	case AFCMPES:
5642
		return FPCMP(0, 0, 0, 0, 16)
5643

5644
	case AFCMPED:
5645
		return FPCMP(0, 0, 1, 0, 16)
5646

5647
	case AFCCMPS:
5648
		return FPCCMP(0, 0, 0, 0)
5649

5650
	case AFCCMPD:
5651
		return FPCCMP(0, 0, 1, 0)
5652

5653
	case AFCCMPES:
5654
		return FPCCMP(0, 0, 0, 1)
5655

5656
	case AFCCMPED:
5657
		return FPCCMP(0, 0, 1, 1)
5658

5659
	case AFCSELS:
5660
		return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
5661

5662
	case AFCSELD:
5663
		return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
5664

5665
	case AFMOVS:
5666
		return FPOP1S(0, 0, 0, 0)
5667

5668
	case AFABSS:
5669
		return FPOP1S(0, 0, 0, 1)
5670

5671
	case AFNEGS:
5672
		return FPOP1S(0, 0, 0, 2)
5673

5674
	case AFSQRTS:
5675
		return FPOP1S(0, 0, 0, 3)
5676

5677
	case AFCVTSD:
5678
		return FPOP1S(0, 0, 0, 5)
5679

5680
	case AFCVTSH:
5681
		return FPOP1S(0, 0, 0, 7)
5682

5683
	case AFRINTNS:
5684
		return FPOP1S(0, 0, 0, 8)
5685

5686
	case AFRINTPS:
5687
		return FPOP1S(0, 0, 0, 9)
5688

5689
	case AFRINTMS:
5690
		return FPOP1S(0, 0, 0, 10)
5691

5692
	case AFRINTZS:
5693
		return FPOP1S(0, 0, 0, 11)
5694

5695
	case AFRINTAS:
5696
		return FPOP1S(0, 0, 0, 12)
5697

5698
	case AFRINTXS:
5699
		return FPOP1S(0, 0, 0, 14)
5700

5701
	case AFRINTIS:
5702
		return FPOP1S(0, 0, 0, 15)
5703

5704
	case AFMOVD:
5705
		return FPOP1S(0, 0, 1, 0)
5706

5707
	case AFABSD:
5708
		return FPOP1S(0, 0, 1, 1)
5709

5710
	case AFNEGD:
5711
		return FPOP1S(0, 0, 1, 2)
5712

5713
	case AFSQRTD:
5714
		return FPOP1S(0, 0, 1, 3)
5715

5716
	case AFCVTDS:
5717
		return FPOP1S(0, 0, 1, 4)
5718

5719
	case AFCVTDH:
5720
		return FPOP1S(0, 0, 1, 7)
5721

5722
	case AFRINTND:
5723
		return FPOP1S(0, 0, 1, 8)
5724

5725
	case AFRINTPD:
5726
		return FPOP1S(0, 0, 1, 9)
5727

5728
	case AFRINTMD:
5729
		return FPOP1S(0, 0, 1, 10)
5730

5731
	case AFRINTZD:
5732
		return FPOP1S(0, 0, 1, 11)
5733

5734
	case AFRINTAD:
5735
		return FPOP1S(0, 0, 1, 12)
5736

5737
	case AFRINTXD:
5738
		return FPOP1S(0, 0, 1, 14)
5739

5740
	case AFRINTID:
5741
		return FPOP1S(0, 0, 1, 15)
5742

5743
	case AFCVTHS:
5744
		return FPOP1S(0, 0, 3, 4)
5745

5746
	case AFCVTHD:
5747
		return FPOP1S(0, 0, 3, 5)
5748

5749
	case AVADD:
5750
		return 7<<25 | 1<<21 | 1<<15 | 1<<10
5751

5752
	case AVSUB:
5753
		return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
5754

5755
	case AVADDP:
5756
		return 7<<25 | 1<<21 | 1<<15 | 15<<10
5757

5758
	case AVAND:
5759
		return 7<<25 | 1<<21 | 7<<10
5760

5761
	case AVCMEQ:
5762
		return 1<<29 | 0x71<<21 | 0x23<<10
5763

5764
	case AVCNT:
5765
		return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
5766

5767
	case AVZIP1:
5768
		return 0xE<<24 | 3<<12 | 2<<10
5769

5770
	case AVZIP2:
5771
		return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
5772

5773
	case AVEOR:
5774
		return 1<<29 | 0x71<<21 | 7<<10
5775

5776
	case AVORR:
5777
		return 7<<25 | 5<<21 | 7<<10
5778

5779
	case AVREV16:
5780
		return 3<<26 | 2<<24 | 1<<21 | 3<<11
5781

5782
	case AVREV32:
5783
		return 11<<26 | 2<<24 | 1<<21 | 1<<11
5784

5785
	case AVREV64:
5786
		return 3<<26 | 2<<24 | 1<<21 | 1<<11
5787

5788
	case AVMOV:
5789
		return 7<<25 | 5<<21 | 7<<10
5790

5791
	case AVADDV:
5792
		return 7<<25 | 3<<20 | 3<<15 | 7<<11
5793

5794
	case AVUADDLV:
5795
		return 1<<29 | 7<<25 | 3<<20 | 7<<11
5796

5797
	case AVFMLA:
5798
		return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
5799

5800
	case AVFMLS:
5801
		return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
5802

5803
	case AVPMULL, AVPMULL2:
5804
		return 0xE<<24 | 1<<21 | 0x38<<10
5805

5806
	case AVRBIT:
5807
		return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
5808

5809
	case AVLD1, AVLD2, AVLD3, AVLD4:
5810
		return 3<<26 | 1<<22
5811

5812
	case AVLD1R, AVLD3R:
5813
		return 0xD<<24 | 1<<22
5814

5815
	case AVLD2R, AVLD4R:
5816
		return 0xD<<24 | 3<<21
5817

5818
	case AVBIF:
5819
		return 1<<29 | 7<<25 | 7<<21 | 7<<10
5820

5821
	case AVBIT:
5822
		return 1<<29 | 0x75<<21 | 7<<10
5823

5824
	case AVBSL:
5825
		return 1<<29 | 0x73<<21 | 7<<10
5826

5827
	case AVCMTST:
5828
		return 0xE<<24 | 1<<21 | 0x23<<10
5829

5830
	case AVUZP1:
5831
		return 7<<25 | 3<<11
5832

5833
	case AVUZP2:
5834
		return 7<<25 | 1<<14 | 3<<11
5835
	}
5836

5837
	c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
5838
	return 0
5839
}
5840

5841
/*
5842
 * imm -> Rd
5843
 * imm op Rn -> Rd
5844
 */
5845
func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
5846
	switch a {
5847
	/* op $addcon, Rn, Rd */
5848
	case AMOVD, AADD:
5849
		return S64 | 0<<30 | 0<<29 | 0x11<<24
5850

5851
	case ACMN, AADDS:
5852
		return S64 | 0<<30 | 1<<29 | 0x11<<24
5853

5854
	case AMOVW, AADDW:
5855
		return S32 | 0<<30 | 0<<29 | 0x11<<24
5856

5857
	case ACMNW, AADDSW:
5858
		return S32 | 0<<30 | 1<<29 | 0x11<<24
5859

5860
	case ASUB:
5861
		return S64 | 1<<30 | 0<<29 | 0x11<<24
5862

5863
	case ACMP, ASUBS:
5864
		return S64 | 1<<30 | 1<<29 | 0x11<<24
5865

5866
	case ASUBW:
5867
		return S32 | 1<<30 | 0<<29 | 0x11<<24
5868

5869
	case ACMPW, ASUBSW:
5870
		return S32 | 1<<30 | 1<<29 | 0x11<<24
5871

5872
		/* op $imm(SB), Rd; op label, Rd */
5873
	case AADR:
5874
		return 0<<31 | 0x10<<24
5875

5876
	case AADRP:
5877
		return 1<<31 | 0x10<<24
5878

5879
		/* op $bimm, Rn, Rd */
5880
	case AAND, ABIC:
5881
		return S64 | 0<<29 | 0x24<<23
5882

5883
	case AANDW, ABICW:
5884
		return S32 | 0<<29 | 0x24<<23 | 0<<22
5885

5886
	case AORR, AORN:
5887
		return S64 | 1<<29 | 0x24<<23
5888

5889
	case AORRW, AORNW:
5890
		return S32 | 1<<29 | 0x24<<23 | 0<<22
5891

5892
	case AEOR, AEON:
5893
		return S64 | 2<<29 | 0x24<<23
5894

5895
	case AEORW, AEONW:
5896
		return S32 | 2<<29 | 0x24<<23 | 0<<22
5897

5898
	case AANDS, ABICS, ATST:
5899
		return S64 | 3<<29 | 0x24<<23
5900

5901
	case AANDSW, ABICSW, ATSTW:
5902
		return S32 | 3<<29 | 0x24<<23 | 0<<22
5903

5904
	case AASR:
5905
		return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
5906

5907
	case AASRW:
5908
		return S32 | 0<<29 | 0x26<<23 | 0<<22
5909

5910
		/* op $width, $lsb, Rn, Rd */
5911
	case ABFI:
5912
		return S64 | 2<<29 | 0x26<<23 | 1<<22
5913
		/* alias of BFM */
5914

5915
	case ABFIW:
5916
		return S32 | 2<<29 | 0x26<<23 | 0<<22
5917

5918
		/* op $imms, $immr, Rn, Rd */
5919
	case ABFM:
5920
		return S64 | 1<<29 | 0x26<<23 | 1<<22
5921

5922
	case ABFMW:
5923
		return S32 | 1<<29 | 0x26<<23 | 0<<22
5924

5925
	case ASBFM:
5926
		return S64 | 0<<29 | 0x26<<23 | 1<<22
5927

5928
	case ASBFMW:
5929
		return S32 | 0<<29 | 0x26<<23 | 0<<22
5930

5931
	case AUBFM:
5932
		return S64 | 2<<29 | 0x26<<23 | 1<<22
5933

5934
	case AUBFMW:
5935
		return S32 | 2<<29 | 0x26<<23 | 0<<22
5936

5937
	case ABFXIL:
5938
		return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
5939

5940
	case ABFXILW:
5941
		return S32 | 1<<29 | 0x26<<23 | 0<<22
5942

5943
	case AEXTR:
5944
		return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
5945

5946
	case AEXTRW:
5947
		return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
5948

5949
	case ACBNZ:
5950
		return S64 | 0x1A<<25 | 1<<24
5951

5952
	case ACBNZW:
5953
		return S32 | 0x1A<<25 | 1<<24
5954

5955
	case ACBZ:
5956
		return S64 | 0x1A<<25 | 0<<24
5957

5958
	case ACBZW:
5959
		return S32 | 0x1A<<25 | 0<<24
5960

5961
	case ACCMN:
5962
		return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
5963

5964
	case ACCMNW:
5965
		return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
5966

5967
	case ACCMP:
5968
		return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
5969

5970
	case ACCMPW:
5971
		return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
5972

5973
	case AMOVK:
5974
		return S64 | 3<<29 | 0x25<<23
5975

5976
	case AMOVKW:
5977
		return S32 | 3<<29 | 0x25<<23
5978

5979
	case AMOVN:
5980
		return S64 | 0<<29 | 0x25<<23
5981

5982
	case AMOVNW:
5983
		return S32 | 0<<29 | 0x25<<23
5984

5985
	case AMOVZ:
5986
		return S64 | 2<<29 | 0x25<<23
5987

5988
	case AMOVZW:
5989
		return S32 | 2<<29 | 0x25<<23
5990

5991
	case AMSR:
5992
		return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
5993

5994
	case AAT,
5995
		ADC,
5996
		AIC,
5997
		ATLBI,
5998
		ASYS:
5999
		return SYSOP(0, 1, 0, 0, 0, 0, 0)
6000

6001
	case ASYSL:
6002
		return SYSOP(1, 1, 0, 0, 0, 0, 0)
6003

6004
	case ATBZ:
6005
		return 0x36 << 24
6006

6007
	case ATBNZ:
6008
		return 0x37 << 24
6009

6010
	case ADSB:
6011
		return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
6012

6013
	case ADMB:
6014
		return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
6015

6016
	case AISB:
6017
		return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
6018

6019
	case AHINT:
6020
		return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
6021

6022
	case AVEXT:
6023
		return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
6024

6025
	case AVUSHR:
6026
		return 0x5E<<23 | 1<<10
6027

6028
	case AVSHL:
6029
		return 0x1E<<23 | 21<<10
6030

6031
	case AVSRI:
6032
		return 0x5E<<23 | 17<<10
6033

6034
	case AVUSHLL, AVUXTL:
6035
		return 1<<29 | 15<<24 | 0x29<<10
6036

6037
	case AVUSHLL2, AVUXTL2:
6038
		return 3<<29 | 15<<24 | 0x29<<10
6039
	}
6040

6041
	c.ctxt.Diag("%v: bad irr %v", p, a)
6042
	return 0
6043
}
6044

6045
func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
6046
	switch a {
6047
	case ACLS:
6048
		return S64 | OPBIT(5)
6049

6050
	case ACLSW:
6051
		return S32 | OPBIT(5)
6052

6053
	case ACLZ:
6054
		return S64 | OPBIT(4)
6055

6056
	case ACLZW:
6057
		return S32 | OPBIT(4)
6058

6059
	case ARBIT:
6060
		return S64 | OPBIT(0)
6061

6062
	case ARBITW:
6063
		return S32 | OPBIT(0)
6064

6065
	case AREV:
6066
		return S64 | OPBIT(3)
6067

6068
	case AREVW:
6069
		return S32 | OPBIT(2)
6070

6071
	case AREV16:
6072
		return S64 | OPBIT(1)
6073

6074
	case AREV16W:
6075
		return S32 | OPBIT(1)
6076

6077
	case AREV32:
6078
		return S64 | OPBIT(2)
6079

6080
	default:
6081
		c.ctxt.Diag("bad bit op\n%v", p)
6082
		return 0
6083
	}
6084
}
6085

6086
/*
6087
 * add/subtract sign or zero-extended register
6088
 */
6089
func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
6090
	extension := uint32(0)
6091
	if !extend {
6092
		switch a {
6093
		case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
6094
			extension = LSL0_64
6095

6096
		case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
6097
			extension = LSL0_32
6098
		}
6099
	}
6100

6101
	switch a {
6102
	case AADD:
6103
		return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6104

6105
	case AADDW:
6106
		return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6107

6108
	case ACMN, AADDS:
6109
		return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6110

6111
	case ACMNW, AADDSW:
6112
		return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6113

6114
	case ASUB:
6115
		return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6116

6117
	case ASUBW:
6118
		return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6119

6120
	case ACMP, ASUBS:
6121
		return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6122

6123
	case ACMPW, ASUBSW:
6124
		return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6125
	}
6126

6127
	c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
6128
	return 0
6129
}
6130

6131
func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
6132
	switch a {
6133
	case ASVC:
6134
		return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
6135

6136
	case AHVC:
6137
		return 0xD4<<24 | 0<<21 | 2
6138

6139
	case ASMC:
6140
		return 0xD4<<24 | 0<<21 | 3
6141

6142
	case ABRK:
6143
		return 0xD4<<24 | 1<<21 | 0
6144

6145
	case AHLT:
6146
		return 0xD4<<24 | 2<<21 | 0
6147

6148
	case ADCPS1:
6149
		return 0xD4<<24 | 5<<21 | 1
6150

6151
	case ADCPS2:
6152
		return 0xD4<<24 | 5<<21 | 2
6153

6154
	case ADCPS3:
6155
		return 0xD4<<24 | 5<<21 | 3
6156

6157
	case ACLREX:
6158
		return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
6159
	}
6160

6161
	c.ctxt.Diag("%v: bad imm %v", p, a)
6162
	return 0
6163
}
6164

6165
func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
6166
	v := int64(0)
6167
	t := int64(0)
6168
	q := p.To.Target()
6169
	if q == nil {
6170
		// TODO: don't use brdist for this case, as it isn't a branch.
6171
		// (Calls from omovlit, and maybe adr/adrp opcodes as well.)
6172
		q = p.Pool
6173
	}
6174
	if q != nil {
6175
		v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
6176
		if (v & ((1 << uint(shift)) - 1)) != 0 {
6177
			c.ctxt.Diag("misaligned label\n%v", p)
6178
		}
6179
		v >>= uint(shift)
6180
		t = int64(1) << uint(flen-1)
6181
		if v < -t || v >= t {
6182
			c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
6183
			panic("branch too far")
6184
		}
6185
	}
6186

6187
	return v & ((t << 1) - 1)
6188
}
6189

6190
/*
6191
 * pc-relative branches
6192
 */
6193
func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
6194
	switch a {
6195
	case ABEQ:
6196
		return OPBcc(0x0)
6197

6198
	case ABNE:
6199
		return OPBcc(0x1)
6200

6201
	case ABCS:
6202
		return OPBcc(0x2)
6203

6204
	case ABHS:
6205
		return OPBcc(0x2)
6206

6207
	case ABCC:
6208
		return OPBcc(0x3)
6209

6210
	case ABLO:
6211
		return OPBcc(0x3)
6212

6213
	case ABMI:
6214
		return OPBcc(0x4)
6215

6216
	case ABPL:
6217
		return OPBcc(0x5)
6218

6219
	case ABVS:
6220
		return OPBcc(0x6)
6221

6222
	case ABVC:
6223
		return OPBcc(0x7)
6224

6225
	case ABHI:
6226
		return OPBcc(0x8)
6227

6228
	case ABLS:
6229
		return OPBcc(0x9)
6230

6231
	case ABGE:
6232
		return OPBcc(0xa)
6233

6234
	case ABLT:
6235
		return OPBcc(0xb)
6236

6237
	case ABGT:
6238
		return OPBcc(0xc)
6239

6240
	case ABLE:
6241
		return OPBcc(0xd) /* imm19<<5 | cond */
6242

6243
	case AB:
6244
		return 0<<31 | 5<<26 /* imm26 */
6245

6246
	case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
6247
		return 1<<31 | 5<<26
6248
	}
6249

6250
	c.ctxt.Diag("%v: bad bra %v", p, a)
6251
	return 0
6252
}
6253

6254
func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
6255
	switch a {
6256
	case ABL:
6257
		return OPBLR(1) /* BLR */
6258

6259
	case AB:
6260
		return OPBLR(0) /* BR */
6261

6262
	case obj.ARET:
6263
		return OPBLR(2) /* RET */
6264
	}
6265

6266
	c.ctxt.Diag("%v: bad brr %v", p, a)
6267
	return 0
6268
}
6269

6270
func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
6271
	switch a {
6272
	case ADRPS:
6273
		return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
6274

6275
	case AERET:
6276
		return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
6277

6278
	case ANOOP:
6279
		return SYSHINT(0)
6280

6281
	case AYIELD:
6282
		return SYSHINT(1)
6283

6284
	case AWFE:
6285
		return SYSHINT(2)
6286

6287
	case AWFI:
6288
		return SYSHINT(3)
6289

6290
	case ASEV:
6291
		return SYSHINT(4)
6292

6293
	case ASEVL:
6294
		return SYSHINT(5)
6295
	}
6296

6297
	c.ctxt.Diag("%v: bad op0 %v", p, a)
6298
	return 0
6299
}
6300

6301
/*
6302
 * register offset
6303
 */
6304
func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
6305
	switch a {
6306
	case ALDAR:
6307
		return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
6308

6309
	case ALDARW:
6310
		return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
6311

6312
	case ALDARB:
6313
		return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
6314

6315
	case ALDARH:
6316
		return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
6317

6318
	case ALDAXP:
6319
		return LDSTX(3, 0, 1, 1, 1)
6320

6321
	case ALDAXPW:
6322
		return LDSTX(2, 0, 1, 1, 1)
6323

6324
	case ALDAXR:
6325
		return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
6326

6327
	case ALDAXRW:
6328
		return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
6329

6330
	case ALDAXRB:
6331
		return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
6332

6333
	case ALDAXRH:
6334
		return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
6335

6336
	case ALDXR:
6337
		return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
6338

6339
	case ALDXRB:
6340
		return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
6341

6342
	case ALDXRH:
6343
		return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
6344

6345
	case ALDXRW:
6346
		return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
6347

6348
	case ALDXP:
6349
		return LDSTX(3, 0, 1, 1, 0)
6350

6351
	case ALDXPW:
6352
		return LDSTX(2, 0, 1, 1, 0)
6353

6354
	case AMOVNP:
6355
		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6356

6357
	case AMOVNPW:
6358
		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6359
	}
6360

6361
	c.ctxt.Diag("bad opload %v\n%v", a, p)
6362
	return 0
6363
}
6364

6365
func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
6366
	switch a {
6367
	case ASTLR:
6368
		return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
6369

6370
	case ASTLRB:
6371
		return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
6372

6373
	case ASTLRH:
6374
		return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
6375

6376
	case ASTLP:
6377
		return LDSTX(3, 0, 0, 1, 1)
6378

6379
	case ASTLPW:
6380
		return LDSTX(2, 0, 0, 1, 1)
6381

6382
	case ASTLRW:
6383
		return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
6384

6385
	case ASTLXP:
6386
		return LDSTX(3, 0, 0, 1, 1)
6387

6388
	case ASTLXPW:
6389
		return LDSTX(2, 0, 0, 1, 1)
6390

6391
	case ASTLXR:
6392
		return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
6393

6394
	case ASTLXRB:
6395
		return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
6396

6397
	case ASTLXRH:
6398
		return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
6399

6400
	case ASTLXRW:
6401
		return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
6402

6403
	case ASTXR:
6404
		return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
6405

6406
	case ASTXRB:
6407
		return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
6408

6409
	case ASTXRH:
6410
		return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
6411

6412
	case ASTXP:
6413
		return LDSTX(3, 0, 0, 1, 0)
6414

6415
	case ASTXPW:
6416
		return LDSTX(2, 0, 0, 1, 0)
6417

6418
	case ASTXRW:
6419
		return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
6420

6421
	case AMOVNP:
6422
		return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6423

6424
	case AMOVNPW:
6425
		return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6426
	}
6427

6428
	c.ctxt.Diag("bad opstore %v\n%v", a, p)
6429
	return 0
6430
}
6431

6432
/*
6433
 * load/store register (unsigned immediate) C3.3.13
6434
 *	these produce 64-bit values (when there's an option)
6435
 */
6436
func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
6437
	if v < 0 || v >= (1<<12) {
6438
		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
6439
	}
6440
	o |= (v & 0xFFF) << 10
6441
	o |= int32(b&31) << 5
6442
	o |= int32(r & 31)
6443
	return uint32(o)
6444
}
6445

6446
func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
6447
	switch a {
6448
	case AMOVD:
6449
		return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
6450

6451
	case AMOVW:
6452
		return LDSTR12U(2, 0, 2)
6453

6454
	case AMOVWU:
6455
		return LDSTR12U(2, 0, 1)
6456

6457
	case AMOVH:
6458
		return LDSTR12U(1, 0, 2)
6459

6460
	case AMOVHU:
6461
		return LDSTR12U(1, 0, 1)
6462

6463
	case AMOVB:
6464
		return LDSTR12U(0, 0, 2)
6465

6466
	case AMOVBU:
6467
		return LDSTR12U(0, 0, 1)
6468

6469
	case AFMOVS:
6470
		return LDSTR12U(2, 1, 1)
6471

6472
	case AFMOVD:
6473
		return LDSTR12U(3, 1, 1)
6474
	}
6475

6476
	c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
6477
	return 0
6478
}
6479

6480
func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
6481
	return LD2STR(c.opldr12(p, a))
6482
}
6483

6484
/*
6485
 * load/store register (unscaled immediate) C3.3.12
6486
 */
6487
func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
6488
	if v < -256 || v > 255 {
6489
		c.ctxt.Diag("offset out of range: %d\n%v", v, p)
6490
	}
6491
	o |= (v & 0x1FF) << 12
6492
	o |= int32(b&31) << 5
6493
	o |= int32(r & 31)
6494
	return uint32(o)
6495
}
6496

6497
func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
6498
	switch a {
6499
	case AMOVD:
6500
		return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
6501

6502
	case AMOVW:
6503
		return LDSTR9S(2, 0, 2)
6504

6505
	case AMOVWU:
6506
		return LDSTR9S(2, 0, 1)
6507

6508
	case AMOVH:
6509
		return LDSTR9S(1, 0, 2)
6510

6511
	case AMOVHU:
6512
		return LDSTR9S(1, 0, 1)
6513

6514
	case AMOVB:
6515
		return LDSTR9S(0, 0, 2)
6516

6517
	case AMOVBU:
6518
		return LDSTR9S(0, 0, 1)
6519

6520
	case AFMOVS:
6521
		return LDSTR9S(2, 1, 1)
6522

6523
	case AFMOVD:
6524
		return LDSTR9S(3, 1, 1)
6525
	}
6526

6527
	c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
6528
	return 0
6529
}
6530

6531
func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
6532
	return LD2STR(c.opldr9(p, a))
6533
}
6534

6535
func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
6536
	switch a {
6537
	case AMOVD:
6538
		return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
6539

6540
	case AMOVW:
6541
		return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
6542

6543
	case AMOVWU:
6544
		return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
6545

6546
	case AMOVH:
6547
		return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
6548

6549
	case AMOVHU:
6550
		return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
6551

6552
	case AMOVB:
6553
		return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
6554

6555
	case AMOVBU:
6556
		return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
6557

6558
	case AFMOVS:
6559
		return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
6560

6561
	case AFMOVD:
6562
		return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
6563

6564
	case APRFM:
6565
		return 0xf9<<24 | 2<<22
6566

6567
	}
6568

6569
	c.ctxt.Diag("bad opldr %v\n%v", a, p)
6570
	return 0
6571
}
6572

6573
// olsxrr attaches register operands to a load/store opcode supplied in o.
6574
// The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
6575
func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
6576
	o |= int32(r1&31) << 5
6577
	o |= int32(r2&31) << 16
6578
	o |= int32(r & 31)
6579
	return uint32(o)
6580
}
6581

6582
// opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
6583
// for load instruction with register offset.
6584
// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
6585
func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
6586
	OptionS := uint32(0x1a)
6587
	if extension {
6588
		OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
6589
	}
6590
	switch a {
6591
	case AMOVD:
6592
		return OptionS<<10 | 0x3<<21 | 0x1f<<27
6593
	case AMOVW:
6594
		return OptionS<<10 | 0x5<<21 | 0x17<<27
6595
	case AMOVWU:
6596
		return OptionS<<10 | 0x3<<21 | 0x17<<27
6597
	case AMOVH:
6598
		return OptionS<<10 | 0x5<<21 | 0x0f<<27
6599
	case AMOVHU:
6600
		return OptionS<<10 | 0x3<<21 | 0x0f<<27
6601
	case AMOVB:
6602
		return OptionS<<10 | 0x5<<21 | 0x07<<27
6603
	case AMOVBU:
6604
		return OptionS<<10 | 0x3<<21 | 0x07<<27
6605
	case AFMOVS:
6606
		return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
6607
	case AFMOVD:
6608
		return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
6609
	}
6610
	c.ctxt.Diag("bad opldrr %v\n%v", a, p)
6611
	return 0
6612
}
6613

6614
// opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
6615
// for store instruction with register offset.
6616
// The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
6617
func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
6618
	OptionS := uint32(0x1a)
6619
	if extension {
6620
		OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
6621
	}
6622
	switch a {
6623
	case AMOVD:
6624
		return OptionS<<10 | 0x1<<21 | 0x1f<<27
6625
	case AMOVW, AMOVWU:
6626
		return OptionS<<10 | 0x1<<21 | 0x17<<27
6627
	case AMOVH, AMOVHU:
6628
		return OptionS<<10 | 0x1<<21 | 0x0f<<27
6629
	case AMOVB, AMOVBU:
6630
		return OptionS<<10 | 0x1<<21 | 0x07<<27
6631
	case AFMOVS:
6632
		return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
6633
	case AFMOVD:
6634
		return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
6635
	}
6636
	c.ctxt.Diag("bad opstrr %v\n%v", a, p)
6637
	return 0
6638
}
6639

6640
func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
6641
	if (v & 0xFFF000) != 0 {
6642
		if v&0xFFF != 0 {
6643
			c.ctxt.Diag("%v misuses oaddi", p)
6644
		}
6645
		v >>= 12
6646
		o1 |= 1 << 22
6647
	}
6648

6649
	o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
6650
	return uint32(o1)
6651
}
6652

6653
/*
6654
 * load a literal value into dr
6655
 */
6656
func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
6657
	var o1 int32
6658
	if p.Pool == nil { /* not in literal pool */
6659
		c.aclass(a)
6660
		c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
6661

6662
		/* TODO: could be clever, and use general constant builder */
6663
		o1 = int32(c.opirr(p, AADD))
6664

6665
		v := int32(c.instoffset)
6666
		if v != 0 && (v&0xFFF) == 0 {
6667
			v >>= 12
6668
			o1 |= 1 << 22 /* shift, by 12 */
6669
		}
6670

6671
		o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
6672
	} else {
6673
		fp, w := 0, 0
6674
		switch as {
6675
		case AFMOVS:
6676
			fp = 1
6677
			w = 0 /* 32-bit SIMD/FP */
6678

6679
		case AFMOVD:
6680
			fp = 1
6681
			w = 1 /* 64-bit SIMD/FP */
6682

6683
		case AFMOVQ:
6684
			fp = 1
6685
			w = 2 /* 128-bit SIMD/FP */
6686

6687
		case AMOVD:
6688
			if p.Pool.As == ADWORD {
6689
				w = 1 /* 64-bit */
6690
			} else if p.Pool.To.Offset < 0 {
6691
				w = 2 /* 32-bit, sign-extended to 64-bit */
6692
			} else if p.Pool.To.Offset >= 0 {
6693
				w = 0 /* 32-bit, zero-extended to 64-bit */
6694
			} else {
6695
				c.ctxt.Diag("invalid operand %v in %v", a, p)
6696
			}
6697

6698
		case AMOVBU, AMOVHU, AMOVWU:
6699
			w = 0 /* 32-bit, zero-extended to 64-bit */
6700

6701
		case AMOVB, AMOVH, AMOVW:
6702
			w = 2 /* 32-bit, sign-extended to 64-bit */
6703

6704
		default:
6705
			c.ctxt.Diag("invalid operation %v in %v", as, p)
6706
		}
6707

6708
		v := int32(c.brdist(p, 0, 19, 2))
6709
		o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
6710
		o1 |= (v & 0x7FFFF) << 5
6711
		o1 |= int32(dr & 31)
6712
	}
6713

6714
	return uint32(o1)
6715
}
6716

6717
// load a constant (MOVCON or BITCON) in a into rt
6718
func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
6719
	if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
6720
		// or $bitcon, REGZERO, rt
6721
		mode := 64
6722
		var as1 obj.As
6723
		switch as {
6724
		case AMOVW:
6725
			as1 = AORRW
6726
			mode = 32
6727
		case AMOVD:
6728
			as1 = AORR
6729
		}
6730
		o1 = c.opirr(p, as1)
6731
		o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
6732
		return o1
6733
	}
6734

6735
	if as == AMOVW {
6736
		d := uint32(a.Offset)
6737
		s := movcon(int64(d))
6738
		if s < 0 || 16*s >= 32 {
6739
			d = ^d
6740
			s = movcon(int64(d))
6741
			if s < 0 || 16*s >= 32 {
6742
				c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
6743
			}
6744
			o1 = c.opirr(p, AMOVNW)
6745
		} else {
6746
			o1 = c.opirr(p, AMOVZW)
6747
		}
6748
		o1 |= MOVCONST(int64(d), s, rt)
6749
	}
6750
	if as == AMOVD {
6751
		d := a.Offset
6752
		s := movcon(d)
6753
		if s < 0 || 16*s >= 64 {
6754
			d = ^d
6755
			s = movcon(d)
6756
			if s < 0 || 16*s >= 64 {
6757
				c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
6758
			}
6759
			o1 = c.opirr(p, AMOVN)
6760
		} else {
6761
			o1 = c.opirr(p, AMOVZ)
6762
		}
6763
		o1 |= MOVCONST(d, s, rt)
6764
	}
6765
	return o1
6766
}
6767

6768
// load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
6769
// put the instruction sequence in os and return the number of instructions.
6770
func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
6771
	switch as {
6772
	case AMOVW:
6773
		d := uint32(a.Offset)
6774
		// use MOVZW and MOVKW to load a constant to rt
6775
		os[0] = c.opirr(p, AMOVZW)
6776
		os[0] |= MOVCONST(int64(d), 0, rt)
6777
		os[1] = c.opirr(p, AMOVKW)
6778
		os[1] |= MOVCONST(int64(d), 1, rt)
6779
		return 2
6780

6781
	case AMOVD:
6782
		d := a.Offset
6783
		dn := ^d
6784
		var immh [4]uint64
6785
		var i int
6786
		zeroCount := int(0)
6787
		negCount := int(0)
6788
		for i = 0; i < 4; i++ {
6789
			immh[i] = uint64((d >> uint(i*16)) & 0xffff)
6790
			if immh[i] == 0 {
6791
				zeroCount++
6792
			} else if immh[i] == 0xffff {
6793
				negCount++
6794
			}
6795
		}
6796

6797
		if zeroCount == 4 || negCount == 4 {
6798
			c.ctxt.Diag("the immediate should be MOVCON: %v", p)
6799
		}
6800
		switch {
6801
		case zeroCount == 3:
6802
			// one MOVZ
6803
			for i = 0; i < 4; i++ {
6804
				if immh[i] != 0 {
6805
					os[0] = c.opirr(p, AMOVZ)
6806
					os[0] |= MOVCONST(d, i, rt)
6807
					break
6808
				}
6809
			}
6810
			return 1
6811

6812
		case negCount == 3:
6813
			// one MOVN
6814
			for i = 0; i < 4; i++ {
6815
				if immh[i] != 0xffff {
6816
					os[0] = c.opirr(p, AMOVN)
6817
					os[0] |= MOVCONST(dn, i, rt)
6818
					break
6819
				}
6820
			}
6821
			return 1
6822

6823
		case zeroCount == 2:
6824
			// one MOVZ and one MOVK
6825
			for i = 0; i < 4; i++ {
6826
				if immh[i] != 0 {
6827
					os[0] = c.opirr(p, AMOVZ)
6828
					os[0] |= MOVCONST(d, i, rt)
6829
					i++
6830
					break
6831
				}
6832
			}
6833
			for ; i < 4; i++ {
6834
				if immh[i] != 0 {
6835
					os[1] = c.opirr(p, AMOVK)
6836
					os[1] |= MOVCONST(d, i, rt)
6837
				}
6838
			}
6839
			return 2
6840

6841
		case negCount == 2:
6842
			// one MOVN and one MOVK
6843
			for i = 0; i < 4; i++ {
6844
				if immh[i] != 0xffff {
6845
					os[0] = c.opirr(p, AMOVN)
6846
					os[0] |= MOVCONST(dn, i, rt)
6847
					i++
6848
					break
6849
				}
6850
			}
6851
			for ; i < 4; i++ {
6852
				if immh[i] != 0xffff {
6853
					os[1] = c.opirr(p, AMOVK)
6854
					os[1] |= MOVCONST(d, i, rt)
6855
				}
6856
			}
6857
			return 2
6858

6859
		case zeroCount == 1:
6860
			// one MOVZ and two MOVKs
6861
			for i = 0; i < 4; i++ {
6862
				if immh[i] != 0 {
6863
					os[0] = c.opirr(p, AMOVZ)
6864
					os[0] |= MOVCONST(d, i, rt)
6865
					i++
6866
					break
6867
				}
6868
			}
6869

6870
			for j := 1; i < 4; i++ {
6871
				if immh[i] != 0 {
6872
					os[j] = c.opirr(p, AMOVK)
6873
					os[j] |= MOVCONST(d, i, rt)
6874
					j++
6875
				}
6876
			}
6877
			return 3
6878

6879
		case negCount == 1:
6880
			// one MOVN and two MOVKs
6881
			for i = 0; i < 4; i++ {
6882
				if immh[i] != 0xffff {
6883
					os[0] = c.opirr(p, AMOVN)
6884
					os[0] |= MOVCONST(dn, i, rt)
6885
					i++
6886
					break
6887
				}
6888
			}
6889

6890
			for j := 1; i < 4; i++ {
6891
				if immh[i] != 0xffff {
6892
					os[j] = c.opirr(p, AMOVK)
6893
					os[j] |= MOVCONST(d, i, rt)
6894
					j++
6895
				}
6896
			}
6897
			return 3
6898

6899
		default:
6900
			// one MOVZ and 3 MOVKs
6901
			os[0] = c.opirr(p, AMOVZ)
6902
			os[0] |= MOVCONST(d, 0, rt)
6903
			for i = 1; i < 4; i++ {
6904
				os[i] = c.opirr(p, AMOVK)
6905
				os[i] |= MOVCONST(d, i, rt)
6906
			}
6907
			return 4
6908
		}
6909
	default:
6910
		return 0
6911
	}
6912
}
6913

6914
func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
6915
	var b uint32
6916
	o := c.opirr(p, a)
6917
	if (o & (1 << 31)) == 0 {
6918
		b = 32
6919
	} else {
6920
		b = 64
6921
	}
6922
	if r < 0 || uint32(r) >= b {
6923
		c.ctxt.Diag("illegal bit number\n%v", p)
6924
	}
6925
	o |= (uint32(r) & 0x3F) << 16
6926
	if s < 0 || uint32(s) >= b {
6927
		c.ctxt.Diag("illegal bit number\n%v", p)
6928
	}
6929
	o |= (uint32(s) & 0x3F) << 10
6930
	o |= (uint32(rf&31) << 5) | uint32(rt&31)
6931
	return o
6932
}
6933

6934
func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
6935
	var b uint32
6936
	o := c.opirr(p, a)
6937
	if (o & (1 << 31)) != 0 {
6938
		b = 63
6939
	} else {
6940
		b = 31
6941
	}
6942
	if v < 0 || uint32(v) > b {
6943
		c.ctxt.Diag("illegal bit number\n%v", p)
6944
	}
6945
	o |= uint32(v) << 10
6946
	o |= uint32(rn&31) << 5
6947
	o |= uint32(rm&31) << 16
6948
	o |= uint32(rt & 31)
6949
	return o
6950
}
6951

6952
/* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
6953
func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
6954
	wback := false
6955
	if o.scond == C_XPOST || o.scond == C_XPRE {
6956
		wback = true
6957
	}
6958
	switch p.As {
6959
	case ALDP, ALDPW, ALDPSW:
6960
		c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
6961
	case ASTP, ASTPW:
6962
		if wback == true {
6963
			c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
6964
		}
6965
	case AFLDPD, AFLDPS:
6966
		c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
6967
	}
6968
	var ret uint32
6969
	// check offset
6970
	switch p.As {
6971
	case AFLDPD, AFSTPD:
6972
		if vo < -512 || vo > 504 || vo%8 != 0 {
6973
			c.ctxt.Diag("invalid offset %v\n", p)
6974
		}
6975
		vo /= 8
6976
		ret = 1<<30 | 1<<26
6977
	case ALDP, ASTP:
6978
		if vo < -512 || vo > 504 || vo%8 != 0 {
6979
			c.ctxt.Diag("invalid offset %v\n", p)
6980
		}
6981
		vo /= 8
6982
		ret = 2 << 30
6983
	case AFLDPS, AFSTPS:
6984
		if vo < -256 || vo > 252 || vo%4 != 0 {
6985
			c.ctxt.Diag("invalid offset %v\n", p)
6986
		}
6987
		vo /= 4
6988
		ret = 1 << 26
6989
	case ALDPW, ASTPW:
6990
		if vo < -256 || vo > 252 || vo%4 != 0 {
6991
			c.ctxt.Diag("invalid offset %v\n", p)
6992
		}
6993
		vo /= 4
6994
		ret = 0
6995
	case ALDPSW:
6996
		if vo < -256 || vo > 252 || vo%4 != 0 {
6997
			c.ctxt.Diag("invalid offset %v\n", p)
6998
		}
6999
		vo /= 4
7000
		ret = 1 << 30
7001
	default:
7002
		c.ctxt.Diag("invalid instruction %v\n", p)
7003
	}
7004
	// check register pair
7005
	switch p.As {
7006
	case AFLDPD, AFLDPS, AFSTPD, AFSTPS:
7007
		if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
7008
			c.ctxt.Diag("invalid register pair %v\n", p)
7009
		}
7010
	case ALDP, ALDPW, ALDPSW:
7011
		if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
7012
			c.ctxt.Diag("invalid register pair %v\n", p)
7013
		}
7014
	case ASTP, ASTPW:
7015
		if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
7016
			c.ctxt.Diag("invalid register pair %v\n", p)
7017
		}
7018
	}
7019
	// other conditional flag bits
7020
	switch o.scond {
7021
	case C_XPOST:
7022
		ret |= 1 << 23
7023
	case C_XPRE:
7024
		ret |= 3 << 23
7025
	default:
7026
		ret |= 2 << 23
7027
	}
7028
	ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
7029
	return ret
7030
}
7031

7032
func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
7033
	if p.As == AVLD1 || p.As == AVST1 {
7034
		return o1
7035
	}
7036

7037
	o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
7038
	switch p.As {
7039
	case AVLD1R, AVLD2R:
7040
		o1 |= 0xC << 12
7041
	case AVLD3R, AVLD4R:
7042
		o1 |= 0xE << 12
7043
	case AVLD2, AVST2:
7044
		o1 |= 8 << 12
7045
	case AVLD3, AVST3:
7046
		o1 |= 4 << 12
7047
	case AVLD4, AVST4:
7048
	default:
7049
		c.ctxt.Diag("unsupported instruction:%v\n", p.As)
7050
	}
7051
	return o1
7052
}
7053

7054
/*
7055
 * size in log2(bytes)
7056
 */
7057
func movesize(a obj.As) int {
7058
	switch a {
7059
	case AMOVD:
7060
		return 3
7061

7062
	case AMOVW, AMOVWU:
7063
		return 2
7064

7065
	case AMOVH, AMOVHU:
7066
		return 1
7067

7068
	case AMOVB, AMOVBU:
7069
		return 0
7070

7071
	case AFMOVS:
7072
		return 2
7073

7074
	case AFMOVD:
7075
		return 3
7076

7077
	default:
7078
		return -1
7079
	}
7080
}
7081

7082
// rm is the Rm register value, o is the extension, amount is the left shift value.
7083
func roff(rm int16, o uint32, amount int16) uint32 {
7084
	return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
7085
}
7086

7087
// encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
7088
func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
7089
	var num, rm int16
7090
	num = (r >> 5) & 7
7091
	rm = r & 31
7092
	switch {
7093
	case REG_UXTB <= r && r < REG_UXTH:
7094
		return roff(rm, 0, num)
7095
	case REG_UXTH <= r && r < REG_UXTW:
7096
		return roff(rm, 1, num)
7097
	case REG_UXTW <= r && r < REG_UXTX:
7098
		if a.Type == obj.TYPE_MEM {
7099
			if num == 0 {
7100
				return roff(rm, 2, 2)
7101
			} else {
7102
				return roff(rm, 2, 6)
7103
			}
7104
		} else {
7105
			return roff(rm, 2, num)
7106
		}
7107
	case REG_UXTX <= r && r < REG_SXTB:
7108
		return roff(rm, 3, num)
7109
	case REG_SXTB <= r && r < REG_SXTH:
7110
		return roff(rm, 4, num)
7111
	case REG_SXTH <= r && r < REG_SXTW:
7112
		return roff(rm, 5, num)
7113
	case REG_SXTW <= r && r < REG_SXTX:
7114
		if a.Type == obj.TYPE_MEM {
7115
			if num == 0 {
7116
				return roff(rm, 6, 2)
7117
			} else {
7118
				return roff(rm, 6, 6)
7119
			}
7120
		} else {
7121
			return roff(rm, 6, num)
7122
		}
7123
	case REG_SXTX <= r && r < REG_SPECIAL:
7124
		if a.Type == obj.TYPE_MEM {
7125
			if num == 0 {
7126
				return roff(rm, 7, 2)
7127
			} else {
7128
				return roff(rm, 7, 6)
7129
			}
7130
		} else {
7131
			return roff(rm, 7, num)
7132
		}
7133
	case REG_LSL <= r && r < (REG_LSL+1<<8):
7134
		return roff(rm, 3, 6)
7135
	default:
7136
		c.ctxt.Diag("unsupported register extension type.")
7137
	}
7138

7139
	return 0
7140
}
7141

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.