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/
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.
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:
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
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
43 // ctxt7 holds state while assembling a single function.
44 // Each function gets a fresh ctxt7.
45 // This allows for multiple functions to be safely concurrently assembled.
77 size_ int8 // the value of this field is not static, use the size() method to return the value
83 func IsAtomicInstruction(as obj.As) bool {
84 if _, ok := atomicLDADD[as]; ok {
87 if _, ok := atomicSWP[as]; ok {
93 // known field values of an instruction.
94 var atomicLDADD = map[obj.As]uint32{
95 ALDADDAD: 3<<30 | 0x1c5<<21 | 0x00<<10,
96 ALDADDAW: 2<<30 | 0x1c5<<21 | 0x00<<10,
97 ALDADDAH: 1<<30 | 0x1c5<<21 | 0x00<<10,
98 ALDADDAB: 0<<30 | 0x1c5<<21 | 0x00<<10,
99 ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
100 ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
101 ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
102 ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
103 ALDADDD: 3<<30 | 0x1c1<<21 | 0x00<<10,
104 ALDADDW: 2<<30 | 0x1c1<<21 | 0x00<<10,
105 ALDADDH: 1<<30 | 0x1c1<<21 | 0x00<<10,
106 ALDADDB: 0<<30 | 0x1c1<<21 | 0x00<<10,
107 ALDADDLD: 3<<30 | 0x1c3<<21 | 0x00<<10,
108 ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10,
109 ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10,
110 ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10,
111 ALDCLRAD: 3<<30 | 0x1c5<<21 | 0x04<<10,
112 ALDCLRAW: 2<<30 | 0x1c5<<21 | 0x04<<10,
113 ALDCLRAH: 1<<30 | 0x1c5<<21 | 0x04<<10,
114 ALDCLRAB: 0<<30 | 0x1c5<<21 | 0x04<<10,
115 ALDCLRALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
116 ALDCLRALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
117 ALDCLRALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
118 ALDCLRALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
119 ALDCLRD: 3<<30 | 0x1c1<<21 | 0x04<<10,
120 ALDCLRW: 2<<30 | 0x1c1<<21 | 0x04<<10,
121 ALDCLRH: 1<<30 | 0x1c1<<21 | 0x04<<10,
122 ALDCLRB: 0<<30 | 0x1c1<<21 | 0x04<<10,
123 ALDCLRLD: 3<<30 | 0x1c3<<21 | 0x04<<10,
124 ALDCLRLW: 2<<30 | 0x1c3<<21 | 0x04<<10,
125 ALDCLRLH: 1<<30 | 0x1c3<<21 | 0x04<<10,
126 ALDCLRLB: 0<<30 | 0x1c3<<21 | 0x04<<10,
127 ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10,
128 ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10,
129 ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10,
130 ALDEORAB: 0<<30 | 0x1c5<<21 | 0x08<<10,
131 ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
132 ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
133 ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
134 ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
135 ALDEORD: 3<<30 | 0x1c1<<21 | 0x08<<10,
136 ALDEORW: 2<<30 | 0x1c1<<21 | 0x08<<10,
137 ALDEORH: 1<<30 | 0x1c1<<21 | 0x08<<10,
138 ALDEORB: 0<<30 | 0x1c1<<21 | 0x08<<10,
139 ALDEORLD: 3<<30 | 0x1c3<<21 | 0x08<<10,
140 ALDEORLW: 2<<30 | 0x1c3<<21 | 0x08<<10,
141 ALDEORLH: 1<<30 | 0x1c3<<21 | 0x08<<10,
142 ALDEORLB: 0<<30 | 0x1c3<<21 | 0x08<<10,
143 ALDORAD: 3<<30 | 0x1c5<<21 | 0x0c<<10,
144 ALDORAW: 2<<30 | 0x1c5<<21 | 0x0c<<10,
145 ALDORAH: 1<<30 | 0x1c5<<21 | 0x0c<<10,
146 ALDORAB: 0<<30 | 0x1c5<<21 | 0x0c<<10,
147 ALDORALD: 3<<30 | 0x1c7<<21 | 0x0c<<10,
148 ALDORALW: 2<<30 | 0x1c7<<21 | 0x0c<<10,
149 ALDORALH: 1<<30 | 0x1c7<<21 | 0x0c<<10,
150 ALDORALB: 0<<30 | 0x1c7<<21 | 0x0c<<10,
151 ALDORD: 3<<30 | 0x1c1<<21 | 0x0c<<10,
152 ALDORW: 2<<30 | 0x1c1<<21 | 0x0c<<10,
153 ALDORH: 1<<30 | 0x1c1<<21 | 0x0c<<10,
154 ALDORB: 0<<30 | 0x1c1<<21 | 0x0c<<10,
155 ALDORLD: 3<<30 | 0x1c3<<21 | 0x0c<<10,
156 ALDORLW: 2<<30 | 0x1c3<<21 | 0x0c<<10,
157 ALDORLH: 1<<30 | 0x1c3<<21 | 0x0c<<10,
158 ALDORLB: 0<<30 | 0x1c3<<21 | 0x0c<<10,
161 var atomicSWP = map[obj.As]uint32{
162 ASWPAD: 3<<30 | 0x1c5<<21 | 0x20<<10,
163 ASWPAW: 2<<30 | 0x1c5<<21 | 0x20<<10,
164 ASWPAH: 1<<30 | 0x1c5<<21 | 0x20<<10,
165 ASWPAB: 0<<30 | 0x1c5<<21 | 0x20<<10,
166 ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10,
167 ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10,
168 ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10,
169 ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10,
170 ASWPD: 3<<30 | 0x1c1<<21 | 0x20<<10,
171 ASWPW: 2<<30 | 0x1c1<<21 | 0x20<<10,
172 ASWPH: 1<<30 | 0x1c1<<21 | 0x20<<10,
173 ASWPB: 0<<30 | 0x1c1<<21 | 0x20<<10,
174 ASWPLD: 3<<30 | 0x1c3<<21 | 0x20<<10,
175 ASWPLW: 2<<30 | 0x1c3<<21 | 0x20<<10,
176 ASWPLH: 1<<30 | 0x1c3<<21 | 0x20<<10,
177 ASWPLB: 0<<30 | 0x1c3<<21 | 0x20<<10,
178 ACASD: 3<<30 | 0x45<<21 | 0x1f<<10,
179 ACASW: 2<<30 | 0x45<<21 | 0x1f<<10,
180 ACASH: 1<<30 | 0x45<<21 | 0x1f<<10,
181 ACASB: 0<<30 | 0x45<<21 | 0x1f<<10,
182 ACASAD: 3<<30 | 0x47<<21 | 0x1f<<10,
183 ACASAW: 2<<30 | 0x47<<21 | 0x1f<<10,
184 ACASLD: 3<<30 | 0x45<<21 | 0x3f<<10,
185 ACASLW: 2<<30 | 0x45<<21 | 0x3f<<10,
186 ACASALD: 3<<30 | 0x47<<21 | 0x3f<<10,
187 ACASALW: 2<<30 | 0x47<<21 | 0x3f<<10,
188 ACASALH: 1<<30 | 0x47<<21 | 0x3f<<10,
189 ACASALB: 0<<30 | 0x47<<21 | 0x3f<<10,
191 var atomicCASP = map[obj.As]uint32{
192 ACASPD: 1<<30 | 0x41<<21 | 0x1f<<10,
193 ACASPW: 0<<30 | 0x41<<21 | 0x1f<<10,
196 var oprange [ALAST & obj.AMask][]Optab
198 var xcmp [C_NCLASS][C_NCLASS]bool
208 func OPDP2(x uint32) uint32 {
209 return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
212 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
213 return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
216 func OPBcc(x uint32) uint32 {
217 return 0x2A<<25 | 0<<24 | 0<<4 | x&15
220 func OPBLR(x uint32) uint32 {
221 /* x=0, JMP; 1, CALL; 2, RET */
222 return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
225 func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
226 return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
229 func SYSHINT(x uint32) uint32 {
230 return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
233 func LDSTR(sz uint32, v uint32, opc uint32) uint32 {
234 return sz<<30 | 7<<27 | v<<26 | opc<<22
237 func LD2STR(o uint32) uint32 {
238 return o &^ (3 << 22)
241 func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
242 return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
245 func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
246 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
249 func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
250 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
253 func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
254 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
257 func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
258 return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
261 func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
262 return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
265 func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
266 return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
269 func ADR(p uint32, o uint32, rt uint32) uint32 {
270 return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
273 func OPBIT(x uint32) uint32 {
274 return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
277 func MOVCONST(d int64, s int, rt int) uint32 {
278 return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
283 LFROM = 1 << iota // p.From uses constant pool
284 LFROM128 // p.From3<<64+p.From forms a 128-bit constant in literal pool
285 LTO // p.To uses constant pool
286 NOTUSETMP // p expands to multiple instructions, but does NOT use REGTMP
287 BRANCH14BITS // branch instruction encodes 14 bits
288 BRANCH19BITS // branch instruction encodes 19 bits
293 OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */
294 {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
296 /* arithmetic operations */
297 {AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
298 {AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
299 {AADC, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
300 {AADC, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
301 {ANEG, C_ZREG, C_NONE, C_NONE, C_ZREG, 25, 4, 0, 0, 0},
302 {ANEG, C_NONE, C_NONE, C_NONE, C_ZREG, 25, 4, 0, 0, 0},
303 {ANGC, C_ZREG, C_NONE, C_NONE, C_ZREG, 17, 4, 0, 0, 0},
304 {ACMP, C_ZREG, C_ZREG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
305 {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0},
306 {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0},
307 {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0},
308 {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
309 {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
310 {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
311 {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
312 {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
313 {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
314 {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
315 {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
316 {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
317 {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
318 {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
319 {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
320 {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
321 {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
322 {ACMP, C_MOVCON2, C_ZREG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
323 {ACMP, C_MOVCON3, C_ZREG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
324 {ACMP, C_VCON, C_ZREG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
325 {AADD, C_SHIFT, C_ZREG, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
326 {AADD, C_SHIFT, C_NONE, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
327 {AMVN, C_SHIFT, C_NONE, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
328 {ACMP, C_SHIFT, C_ZREG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
329 {ANEG, C_SHIFT, C_NONE, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
330 {AADD, C_ZREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
331 {AADD, C_ZREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
332 {ACMP, C_ZREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
333 {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
334 {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
335 {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
336 {AADD, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
337 {AADD, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
338 {AMUL, C_ZREG, C_ZREG, C_NONE, C_ZREG, 15, 4, 0, 0, 0},
339 {AMUL, C_ZREG, C_NONE, C_NONE, C_ZREG, 15, 4, 0, 0, 0},
340 {AMADD, C_ZREG, C_ZREG, C_ZREG, C_ZREG, 15, 4, 0, 0, 0},
341 {AREM, C_ZREG, C_ZREG, C_NONE, C_ZREG, 16, 8, 0, 0, 0},
342 {AREM, C_ZREG, C_NONE, C_NONE, C_ZREG, 16, 8, 0, 0, 0},
343 {ASDIV, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
344 {ASDIV, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
346 {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
347 {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
348 {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0},
349 {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
350 {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
351 {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
352 {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
353 {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
354 {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0},
355 {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0},
357 /* logical operations */
358 {AAND, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
359 {AAND, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
360 {AANDS, C_ZREG, C_ZREG, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
361 {AANDS, C_ZREG, C_NONE, C_NONE, C_ZREG, 1, 4, 0, 0, 0},
362 {ATST, C_ZREG, C_ZREG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
363 {AAND, C_MBCON, C_ZREG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
364 {AAND, C_MBCON, C_NONE, C_NONE, C_RSP, 53, 4, 0, 0, 0},
365 {AANDS, C_MBCON, C_ZREG, C_NONE, C_ZREG, 53, 4, 0, 0, 0},
366 {AANDS, C_MBCON, C_NONE, C_NONE, C_ZREG, 53, 4, 0, 0, 0},
367 {ATST, C_MBCON, C_ZREG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
368 {AAND, C_BITCON, C_ZREG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
369 {AAND, C_BITCON, C_NONE, C_NONE, C_RSP, 53, 4, 0, 0, 0},
370 {AANDS, C_BITCON, C_ZREG, C_NONE, C_ZREG, 53, 4, 0, 0, 0},
371 {AANDS, C_BITCON, C_NONE, C_NONE, C_ZREG, 53, 4, 0, 0, 0},
372 {ATST, C_BITCON, C_ZREG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
373 {AAND, C_MOVCON, C_ZREG, C_NONE, C_ZREG, 62, 8, 0, 0, 0},
374 {AAND, C_MOVCON, C_NONE, C_NONE, C_ZREG, 62, 8, 0, 0, 0},
375 {AANDS, C_MOVCON, C_ZREG, C_NONE, C_ZREG, 62, 8, 0, 0, 0},
376 {AANDS, C_MOVCON, C_NONE, C_NONE, C_ZREG, 62, 8, 0, 0, 0},
377 {ATST, C_MOVCON, C_ZREG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
378 {AAND, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, 28, 12, 0, 0, 0},
379 {AAND, C_MOVCON2, C_NONE, C_NONE, C_ZREG, 28, 12, 0, 0, 0},
380 {AAND, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, 28, 16, 0, 0, 0},
381 {AAND, C_MOVCON3, C_NONE, C_NONE, C_ZREG, 28, 16, 0, 0, 0},
382 {AAND, C_VCON, C_ZREG, C_NONE, C_ZREG, 28, 20, 0, 0, 0},
383 {AAND, C_VCON, C_NONE, C_NONE, C_ZREG, 28, 20, 0, 0, 0},
384 {AANDS, C_MOVCON2, C_ZREG, C_NONE, C_ZREG, 28, 12, 0, 0, 0},
385 {AANDS, C_MOVCON2, C_NONE, C_NONE, C_ZREG, 28, 12, 0, 0, 0},
386 {AANDS, C_MOVCON3, C_ZREG, C_NONE, C_ZREG, 28, 16, 0, 0, 0},
387 {AANDS, C_MOVCON3, C_NONE, C_NONE, C_ZREG, 28, 16, 0, 0, 0},
388 {AANDS, C_VCON, C_ZREG, C_NONE, C_ZREG, 28, 20, 0, 0, 0},
389 {AANDS, C_VCON, C_NONE, C_NONE, C_ZREG, 28, 20, 0, 0, 0},
390 {ATST, C_MOVCON2, C_ZREG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
391 {ATST, C_MOVCON3, C_ZREG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
392 {ATST, C_VCON, C_ZREG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
393 {AAND, C_SHIFT, C_ZREG, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
394 {AAND, C_SHIFT, C_NONE, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
395 {AANDS, C_SHIFT, C_ZREG, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
396 {AANDS, C_SHIFT, C_NONE, C_NONE, C_ZREG, 3, 4, 0, 0, 0},
397 {ATST, C_SHIFT, C_ZREG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
398 {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0},
399 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ZREG, 24, 4, 0, 0, 0},
400 {AMVN, C_ZREG, C_NONE, C_NONE, C_ZREG, 24, 4, 0, 0, 0},
401 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ZREG, 45, 4, 0, 0, 0}, /* also MOVBU */
402 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ZREG, 45, 4, 0, 0, 0}, /* also MOVHU */
403 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ZREG, 45, 4, 0, 0, 0}, /* also MOVWU */
404 /* TODO: MVN C_SHIFT */
406 /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
407 {AMOVW, C_MBCON, C_NONE, C_NONE, C_ZREG, 32, 4, 0, 0, 0},
408 {AMOVD, C_MBCON, C_NONE, C_NONE, C_ZREG, 32, 4, 0, 0, 0},
409 {AMOVW, C_MOVCON, C_NONE, C_NONE, C_ZREG, 32, 4, 0, 0, 0},
410 {AMOVD, C_MOVCON, C_NONE, C_NONE, C_ZREG, 32, 4, 0, 0, 0},
411 {AMOVW, C_BITCON, C_NONE, C_NONE, C_RSP, 32, 4, 0, 0, 0},
412 {AMOVD, C_BITCON, C_NONE, C_NONE, C_RSP, 32, 4, 0, 0, 0},
413 {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_ZREG, 12, 8, 0, NOTUSETMP, 0},
414 {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_ZREG, 12, 8, 0, NOTUSETMP, 0},
415 {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_ZREG, 12, 12, 0, NOTUSETMP, 0},
416 {AMOVD, C_VCON, C_NONE, C_NONE, C_ZREG, 12, 16, 0, NOTUSETMP, 0},
418 {AMOVK, C_VCON, C_NONE, C_NONE, C_ZREG, 33, 4, 0, 0, 0},
419 {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0},
420 {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, NOTUSETMP, 0},
422 /* load long effective stack address (load int32 offset and add) */
423 {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0},
425 // Move a large constant to a vector register.
426 {AVMOVQ, C_VCON, C_NONE, C_VCON, C_VREG, 101, 4, 0, LFROM128, 0},
427 {AVMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
428 {AVMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
430 /* jump operations */
431 {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
432 {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
433 {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
434 {ABL, C_NONE, C_NONE, C_NONE, C_ZREG, 6, 4, 0, 0, 0},
435 {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
436 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZREG, 6, 4, 0, 0, 0},
437 {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
438 {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, BRANCH19BITS, 0},
439 {ACBZ, C_ZREG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, BRANCH19BITS, 0},
440 {ATBZ, C_VCON, C_ZREG, C_NONE, C_SBRA, 40, 4, 0, BRANCH14BITS, 0},
441 {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
443 // get a PC-relative address
444 {AADRP, C_SBRA, C_NONE, C_NONE, C_ZREG, 60, 4, 0, 0, 0},
445 {AADR, C_SBRA, C_NONE, C_NONE, C_ZREG, 61, 4, 0, 0, 0},
447 {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
448 {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
449 {ABFM, C_VCON, C_ZREG, C_VCON, C_ZREG, 42, 4, 0, 0, 0},
450 {ABFI, C_VCON, C_ZREG, C_VCON, C_ZREG, 43, 4, 0, 0, 0},
451 {AEXTR, C_VCON, C_ZREG, C_ZREG, C_ZREG, 44, 4, 0, 0, 0},
452 {ASXTB, C_ZREG, C_NONE, C_NONE, C_ZREG, 45, 4, 0, 0, 0},
453 {ACLS, C_ZREG, C_NONE, C_NONE, C_ZREG, 46, 4, 0, 0, 0},
454 {ALSL, C_VCON, C_ZREG, C_NONE, C_ZREG, 8, 4, 0, 0, 0},
455 {ALSL, C_VCON, C_NONE, C_NONE, C_ZREG, 8, 4, 0, 0, 0},
456 {ALSL, C_ZREG, C_NONE, C_NONE, C_ZREG, 9, 4, 0, 0, 0},
457 {ALSL, C_ZREG, C_ZREG, C_NONE, C_ZREG, 9, 4, 0, 0, 0},
458 {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
459 {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
460 {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0},
461 {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0},
462 {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0},
463 {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0},
464 {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
465 {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
466 {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
467 {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_ZREG, 68, 8, 0, NOTUSETMP, 0},
468 {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_ZREG, 68, 8, 0, NOTUSETMP, 0},
469 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
470 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
471 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
472 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
473 {AMOVB, C_ADDR, C_NONE, C_NONE, C_ZREG, 65, 12, 0, 0, 0},
474 {AMOVH, C_ADDR, C_NONE, C_NONE, C_ZREG, 65, 12, 0, 0, 0},
475 {AMOVW, C_ADDR, C_NONE, C_NONE, C_ZREG, 65, 12, 0, 0, 0},
476 {AMOVD, C_ADDR, C_NONE, C_NONE, C_ZREG, 65, 12, 0, 0, 0},
477 {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_ZREG, 71, 8, 0, 0, 0},
478 {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_ZREG, 69, 4, 0, 0, 0},
479 {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_ZREG, 70, 8, 0, 0, 0},
481 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
482 {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
483 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
484 {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
485 {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
486 {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
487 {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
488 {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
489 {AFMOVS, C_ZREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
490 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ZREG, 29, 4, 0, 0, 0},
491 {AFMOVD, C_ZREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
492 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ZREG, 29, 4, 0, 0, 0},
493 {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_ZREG, 29, 4, 0, 0, 0},
494 {ASCVTFD, C_ZREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
495 {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
496 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ZREG, 73, 4, 0, 0, 0},
497 {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
498 {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
499 {AVMOV, C_ZREG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
500 {AVMOV, C_ZREG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
501 {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
502 {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
503 {AVDUP, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
504 {AVDUP, C_ZREG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
505 {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
506 {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
507 {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
508 {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
509 {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
510 {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
511 {AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
512 {AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
513 {AVUADDW, C_ARNG, C_ARNG, C_NONE, C_ARNG, 105, 4, 0, 0, 0},
515 /* conditional operations */
516 {ACSEL, C_COND, C_ZREG, C_ZREG, C_ZREG, 18, 4, 0, 0, 0},
517 {ACINC, C_COND, C_ZREG, C_NONE, C_ZREG, 18, 4, 0, 0, 0},
518 {ACSET, C_COND, C_NONE, C_NONE, C_ZREG, 18, 4, 0, 0, 0},
519 {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
520 {ACCMN, C_COND, C_ZREG, C_ZREG, C_VCON, 19, 4, 0, 0, 0},
521 {ACCMN, C_COND, C_ZREG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
522 {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
524 /* scaled 12-bit unsigned displacement store */
525 {AMOVB, C_ZREG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
526 {AMOVB, C_ZREG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
527 {AMOVH, C_ZREG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
528 {AMOVH, C_ZREG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
529 {AMOVW, C_ZREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
530 {AMOVW, C_ZREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
531 {AMOVD, C_ZREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
532 {AMOVD, C_ZREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
534 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
535 {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
536 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
537 {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
538 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_UAUTO64K, 20, 4, REGSP, 0, 0},
539 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_UOREG64K, 20, 4, 0, 0, 0},
541 /* unscaled 9-bit signed displacement store */
542 {AMOVB, C_ZREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
543 {AMOVB, C_ZREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
544 {AMOVH, C_ZREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
545 {AMOVH, C_ZREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
546 {AMOVW, C_ZREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
547 {AMOVW, C_ZREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
548 {AMOVD, C_ZREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
549 {AMOVD, C_ZREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
551 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
552 {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
553 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
554 {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
555 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
556 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
558 /* scaled 12-bit unsigned displacement load */
559 {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
560 {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
561 {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
562 {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
563 {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
564 {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
565 {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
566 {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
568 {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
569 {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
570 {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
571 {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
572 {AFMOVQ, C_UAUTO64K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
573 {AFMOVQ, C_UOREG64K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
575 /* unscaled 9-bit signed displacement load */
576 {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
577 {AMOVB, C_NSOREG, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
578 {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
579 {AMOVH, C_NSOREG, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
580 {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
581 {AMOVW, C_NSOREG, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
582 {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_ZREG, 21, 4, REGSP, 0, 0},
583 {AMOVD, C_NSOREG, C_NONE, C_NONE, C_ZREG, 21, 4, 0, 0, 0},
585 {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
586 {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
587 {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
588 {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
589 {AFMOVQ, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
590 {AFMOVQ, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
592 /* long displacement store */
593 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
594 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
595 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
596 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
597 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
598 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
599 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
600 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
602 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
603 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
604 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
605 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
606 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
607 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
609 /* long displacement load */
610 {AMOVB, C_LAUTO, C_NONE, C_NONE, C_ZREG, 31, 8, REGSP, LFROM, 0},
611 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, 31, 8, 0, LFROM, 0},
612 {AMOVH, C_LAUTO, C_NONE, C_NONE, C_ZREG, 31, 8, REGSP, LFROM, 0},
613 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, 31, 8, 0, LFROM, 0},
614 {AMOVW, C_LAUTO, C_NONE, C_NONE, C_ZREG, 31, 8, REGSP, LFROM, 0},
615 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, 31, 8, 0, LFROM, 0},
616 {AMOVD, C_LAUTO, C_NONE, C_NONE, C_ZREG, 31, 8, REGSP, LFROM, 0},
617 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, 31, 8, 0, LFROM, 0},
619 {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
620 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
621 {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
622 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
623 {AFMOVQ, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
624 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
626 /* pre/post-indexed load (unscaled, signed 9-bit offset) */
627 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPOST},
628 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPOST},
629 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPOST},
630 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPOST},
631 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
632 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
633 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
635 {AMOVD, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPRE},
636 {AMOVW, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPRE},
637 {AMOVH, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPRE},
638 {AMOVB, C_LOREG, C_NONE, C_NONE, C_ZREG, 22, 4, 0, 0, C_XPRE},
639 {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
640 {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
641 {AFMOVQ, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
643 /* pre/post-indexed store (unscaled, signed 9-bit offset) */
644 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
645 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
646 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
647 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
648 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
649 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
650 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
652 {AMOVD, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
653 {AMOVW, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
654 {AMOVH, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
655 {AMOVB, C_ZREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
656 {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
657 {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
658 {AFMOVQ, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
660 /* load with shifted or extended register offset */
661 {AMOVD, C_ROFF, C_NONE, C_NONE, C_ZREG, 98, 4, 0, 0, 0},
662 {AMOVW, C_ROFF, C_NONE, C_NONE, C_ZREG, 98, 4, 0, 0, 0},
663 {AMOVH, C_ROFF, C_NONE, C_NONE, C_ZREG, 98, 4, 0, 0, 0},
664 {AMOVB, C_ROFF, C_NONE, C_NONE, C_ZREG, 98, 4, 0, 0, 0},
665 {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
666 {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
668 /* store with extended register offset */
669 {AMOVD, C_ZREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
670 {AMOVW, C_ZREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
671 {AMOVH, C_ZREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
672 {AMOVB, C_ZREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
673 {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
674 {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
676 /* pre/post-indexed/signed-offset load/store register pair
677 (unscaled, signed 10-bit quad-aligned and long offset).
678 The pre/post-indexed format only supports OREG cases because
679 the RSP and pseudo registers are not allowed to be modified
681 {AFLDPQ, C_NQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
682 {AFLDPQ, C_PQAUTO_16, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
683 {AFLDPQ, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
684 {AFLDPQ, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
685 {AFLDPQ, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
686 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
687 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
688 {AFLDPQ, C_NQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
689 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
690 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
691 {AFLDPQ, C_PQOREG_16, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
692 {AFLDPQ, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
693 {AFLDPQ, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
694 {AFLDPQ, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
695 {AFLDPQ, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
697 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQAUTO_16, 67, 4, REGSP, 0, 0},
698 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQAUTO_16, 67, 4, REGSP, 0, 0},
699 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
700 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
701 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
702 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, 0},
703 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, C_XPRE},
704 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NQOREG_16, 67, 4, 0, 0, C_XPOST},
705 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, 0},
706 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, C_XPRE},
707 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_PQOREG_16, 67, 4, 0, 0, C_XPOST},
708 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
709 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
710 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
711 {AFSTPQ, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
713 {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
714 {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
715 {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
716 {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
717 {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
718 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
719 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
720 {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
721 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
722 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
723 {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
724 {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
725 {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
726 {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
727 {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
729 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
730 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
731 {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
732 {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
733 {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
734 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
735 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
736 {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
737 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
738 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
739 {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
740 {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
741 {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
742 {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
743 {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
745 // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
746 {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
747 {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
748 {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
749 {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
750 {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
751 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
752 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
753 {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
754 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
755 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
756 {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
757 {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
758 {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
759 {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
760 {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
762 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
763 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
764 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
765 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 8, REGSP, 0, 0},
766 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
767 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
768 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
769 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
770 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
771 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
772 {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
773 {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
774 {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
775 {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
776 {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
778 {ASWPD, C_ZREG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG
779 {ASWPD, C_ZREG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG
780 {ACASPD, C_PAIR, C_NONE, C_NONE, C_ZOREG, 106, 4, 0, 0, 0}, // RegTo2=C_REGREG
781 {ACASPD, C_PAIR, C_NONE, C_NONE, C_ZAUTO, 106, 4, REGSP, 0, 0}, // RegTo2=C_REGREG
782 {ALDAR, C_ZOREG, C_NONE, C_NONE, C_ZREG, 58, 4, 0, 0, 0},
783 {ALDXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, 58, 4, 0, 0, 0},
784 {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_ZREG, 58, 4, 0, 0, 0},
785 {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
786 {ASTLR, C_ZREG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE
787 {ASTXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
788 {ASTLXR, C_ZREG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
789 {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
791 /* VLD[1-4]/VST[1-4] */
792 {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
793 {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
794 {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
795 {AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
796 {AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
797 {AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
798 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
799 {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
800 {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
801 {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
802 {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
803 {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
804 {AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
805 {AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
806 {AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
807 {AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
808 {AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
809 {AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
810 {AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
811 {AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
812 {AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
813 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
814 {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
815 {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
818 {AMOVD, C_SPR, C_NONE, C_NONE, C_ZREG, 35, 4, 0, 0, 0},
819 {AMRS, C_SPR, C_NONE, C_NONE, C_ZREG, 35, 4, 0, 0, 0},
820 {AMOVD, C_ZREG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
821 {AMSR, C_ZREG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
822 {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
823 {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
824 {AMSR, C_VCON, C_NONE, C_NONE, C_SPOP, 37, 4, 0, 0, 0},
825 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPOP, 91, 4, 0, 0, 0},
826 {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
827 {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
828 {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
829 {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
830 {ASYS, C_VCON, C_NONE, C_NONE, C_ZREG, 50, 4, 0, 0, 0},
831 {ASYSL, C_VCON, C_NONE, C_NONE, C_ZREG, 50, 4, 0, 0, 0},
832 {ATLBI, C_SPOP, C_NONE, C_NONE, C_NONE, 107, 4, 0, 0, 0},
833 {ATLBI, C_SPOP, C_NONE, C_NONE, C_ZREG, 107, 4, 0, 0, 0},
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_ZREG, 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 {AVEOR3, C_ARNG, C_ARNG, C_ARNG, C_ARNG, 103, 4, 0, 0, 0},
846 {AVXAR, C_VCON, C_ARNG, C_ARNG, C_ARNG, 104, 4, 0, 0, 0},
848 {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
849 {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
850 {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
851 {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
852 {obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
853 {obj.ANOP, C_ZREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
854 {obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
855 {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
856 {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
857 {obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // align code
859 {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
862 // Valid pstate field values, and value to use in instruction.
863 // Doesn't include special registers.
864 var pstatefield = []struct {
868 {SPOP_DAIFSet, 3<<16 | 4<<12 | 6<<5},
869 {SPOP_DAIFClr, 3<<16 | 4<<12 | 7<<5},
872 var prfopfield = map[SpecialOperand]uint32{
893 // sysInstFields helps convert SYS alias instructions to SYS instructions.
894 // For example, the format of TLBI is: TLBI <tlbi_op>{, <Xt>}.
895 // It's equivalent to: SYS #<op1>, C8, <Cm>, #<op2>{, <Xt>}.
896 // The field hasOperand2 indicates whether Xt is required. It helps to check
897 // some combinations that may be undefined, such as TLBI VMALLE1IS, R0.
898 var sysInstFields = map[SpecialOperand]struct {
906 SPOP_VMALLE1IS: {0, 8, 3, 0, false},
907 SPOP_VAE1IS: {0, 8, 3, 1, true},
908 SPOP_ASIDE1IS: {0, 8, 3, 2, true},
909 SPOP_VAAE1IS: {0, 8, 3, 3, true},
910 SPOP_VALE1IS: {0, 8, 3, 5, true},
911 SPOP_VAALE1IS: {0, 8, 3, 7, true},
912 SPOP_VMALLE1: {0, 8, 7, 0, false},
913 SPOP_VAE1: {0, 8, 7, 1, true},
914 SPOP_ASIDE1: {0, 8, 7, 2, true},
915 SPOP_VAAE1: {0, 8, 7, 3, true},
916 SPOP_VALE1: {0, 8, 7, 5, true},
917 SPOP_VAALE1: {0, 8, 7, 7, true},
918 SPOP_IPAS2E1IS: {4, 8, 0, 1, true},
919 SPOP_IPAS2LE1IS: {4, 8, 0, 5, true},
920 SPOP_ALLE2IS: {4, 8, 3, 0, false},
921 SPOP_VAE2IS: {4, 8, 3, 1, true},
922 SPOP_ALLE1IS: {4, 8, 3, 4, false},
923 SPOP_VALE2IS: {4, 8, 3, 5, true},
924 SPOP_VMALLS12E1IS: {4, 8, 3, 6, false},
925 SPOP_IPAS2E1: {4, 8, 4, 1, true},
926 SPOP_IPAS2LE1: {4, 8, 4, 5, true},
927 SPOP_ALLE2: {4, 8, 7, 0, false},
928 SPOP_VAE2: {4, 8, 7, 1, true},
929 SPOP_ALLE1: {4, 8, 7, 4, false},
930 SPOP_VALE2: {4, 8, 7, 5, true},
931 SPOP_VMALLS12E1: {4, 8, 7, 6, false},
932 SPOP_ALLE3IS: {6, 8, 3, 0, false},
933 SPOP_VAE3IS: {6, 8, 3, 1, true},
934 SPOP_VALE3IS: {6, 8, 3, 5, true},
935 SPOP_ALLE3: {6, 8, 7, 0, false},
936 SPOP_VAE3: {6, 8, 7, 1, true},
937 SPOP_VALE3: {6, 8, 7, 5, true},
938 SPOP_VMALLE1OS: {0, 8, 1, 0, false},
939 SPOP_VAE1OS: {0, 8, 1, 1, true},
940 SPOP_ASIDE1OS: {0, 8, 1, 2, true},
941 SPOP_VAAE1OS: {0, 8, 1, 3, true},
942 SPOP_VALE1OS: {0, 8, 1, 5, true},
943 SPOP_VAALE1OS: {0, 8, 1, 7, true},
944 SPOP_RVAE1IS: {0, 8, 2, 1, true},
945 SPOP_RVAAE1IS: {0, 8, 2, 3, true},
946 SPOP_RVALE1IS: {0, 8, 2, 5, true},
947 SPOP_RVAALE1IS: {0, 8, 2, 7, true},
948 SPOP_RVAE1OS: {0, 8, 5, 1, true},
949 SPOP_RVAAE1OS: {0, 8, 5, 3, true},
950 SPOP_RVALE1OS: {0, 8, 5, 5, true},
951 SPOP_RVAALE1OS: {0, 8, 5, 7, true},
952 SPOP_RVAE1: {0, 8, 6, 1, true},
953 SPOP_RVAAE1: {0, 8, 6, 3, true},
954 SPOP_RVALE1: {0, 8, 6, 5, true},
955 SPOP_RVAALE1: {0, 8, 6, 7, true},
956 SPOP_RIPAS2E1IS: {4, 8, 0, 2, true},
957 SPOP_RIPAS2LE1IS: {4, 8, 0, 6, true},
958 SPOP_ALLE2OS: {4, 8, 1, 0, false},
959 SPOP_VAE2OS: {4, 8, 1, 1, true},
960 SPOP_ALLE1OS: {4, 8, 1, 4, false},
961 SPOP_VALE2OS: {4, 8, 1, 5, true},
962 SPOP_VMALLS12E1OS: {4, 8, 1, 6, false},
963 SPOP_RVAE2IS: {4, 8, 2, 1, true},
964 SPOP_RVALE2IS: {4, 8, 2, 5, true},
965 SPOP_IPAS2E1OS: {4, 8, 4, 0, true},
966 SPOP_RIPAS2E1: {4, 8, 4, 2, true},
967 SPOP_RIPAS2E1OS: {4, 8, 4, 3, true},
968 SPOP_IPAS2LE1OS: {4, 8, 4, 4, true},
969 SPOP_RIPAS2LE1: {4, 8, 4, 6, true},
970 SPOP_RIPAS2LE1OS: {4, 8, 4, 7, true},
971 SPOP_RVAE2OS: {4, 8, 5, 1, true},
972 SPOP_RVALE2OS: {4, 8, 5, 5, true},
973 SPOP_RVAE2: {4, 8, 6, 1, true},
974 SPOP_RVALE2: {4, 8, 6, 5, true},
975 SPOP_ALLE3OS: {6, 8, 1, 0, false},
976 SPOP_VAE3OS: {6, 8, 1, 1, true},
977 SPOP_VALE3OS: {6, 8, 1, 5, true},
978 SPOP_RVAE3IS: {6, 8, 2, 1, true},
979 SPOP_RVALE3IS: {6, 8, 2, 5, true},
980 SPOP_RVAE3OS: {6, 8, 5, 1, true},
981 SPOP_RVALE3OS: {6, 8, 5, 5, true},
982 SPOP_RVAE3: {6, 8, 6, 1, true},
983 SPOP_RVALE3: {6, 8, 6, 5, true},
985 SPOP_IVAC: {0, 7, 6, 1, true},
986 SPOP_ISW: {0, 7, 6, 2, true},
987 SPOP_CSW: {0, 7, 10, 2, true},
988 SPOP_CISW: {0, 7, 14, 2, true},
989 SPOP_ZVA: {3, 7, 4, 1, true},
990 SPOP_CVAC: {3, 7, 10, 1, true},
991 SPOP_CVAU: {3, 7, 11, 1, true},
992 SPOP_CIVAC: {3, 7, 14, 1, true},
993 SPOP_IGVAC: {0, 7, 6, 3, true},
994 SPOP_IGSW: {0, 7, 6, 4, true},
995 SPOP_IGDVAC: {0, 7, 6, 5, true},
996 SPOP_IGDSW: {0, 7, 6, 6, true},
997 SPOP_CGSW: {0, 7, 10, 4, true},
998 SPOP_CGDSW: {0, 7, 10, 6, true},
999 SPOP_CIGSW: {0, 7, 14, 4, true},
1000 SPOP_CIGDSW: {0, 7, 14, 6, true},
1001 SPOP_GVA: {3, 7, 4, 3, true},
1002 SPOP_GZVA: {3, 7, 4, 4, true},
1003 SPOP_CGVAC: {3, 7, 10, 3, true},
1004 SPOP_CGDVAC: {3, 7, 10, 5, true},
1005 SPOP_CGVAP: {3, 7, 12, 3, true},
1006 SPOP_CGDVAP: {3, 7, 12, 5, true},
1007 SPOP_CGVADP: {3, 7, 13, 3, true},
1008 SPOP_CGDVADP: {3, 7, 13, 5, true},
1009 SPOP_CIGVAC: {3, 7, 14, 3, true},
1010 SPOP_CIGDVAC: {3, 7, 14, 5, true},
1011 SPOP_CVAP: {3, 7, 12, 1, true},
1012 SPOP_CVADP: {3, 7, 13, 1, true},
1015 // Used for padding NOOP instruction
1016 const OP_NOOP = 0xd503201f
1018 // align code to a certain length by padding bytes.
1019 func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int {
1020 if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
1021 ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
1023 return int(-pc & (alignedValue - 1))
1026 // size returns the size of the sequence of machine instructions when p is encoded with o.
1027 // Usually it just returns o.size directly, in some cases it checks whether the optimization
1028 // conditions are met, and if so returns the size of the optimized instruction sequence.
1029 // These optimizations need to be synchronized with the asmout function.
1030 func (o *Optab) size(ctxt *obj.Link, p *obj.Prog) int {
1031 // Optimize adrp+add+ld/st to adrp+ld/st(offset).
1032 sz := movesize(p.As)
1034 // Relocations R_AARCH64_LDST{64,32,16,8}_ABS_LO12_NC can only generate 8-byte, 4-byte,
1035 // 2-byte and 1-byte aligned addresses, so the address of load/store must be aligned.
1036 // Also symbols with prefix of "go:string." are Go strings, which will go into
1037 // the symbol table, their addresses are not necessary aligned, rule this out.
1038 align := int64(1 << sz)
1039 if o.a1 == C_ADDR && p.From.Offset%align == 0 && !strings.HasPrefix(p.From.Sym.Name, "go:string.") ||
1040 o.a4 == C_ADDR && p.To.Offset%align == 0 && !strings.HasPrefix(p.To.Sym.Name, "go:string.") {
1047 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
1049 ctxt.Diag("-spectre=ret not supported on arm64")
1050 ctxt.Retpoline = false // don't keep printing
1053 p := cursym.Func().Text
1054 if p == nil || p.Link == nil { // handle external functions and ELF section symbols
1058 if oprange[AAND&obj.AMask] == nil {
1059 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
1062 c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
1063 p.To.Offset &= 0xffffffff // extrasize is no longer needed
1070 for p = p.Link; p != nil; p = p.Link {
1073 m = o.size(c.ctxt, p)
1077 alignedValue := p.From.Offset
1078 m = pcAlignPadLength(pc, alignedValue, ctxt)
1079 // Update the current text symbol alignment value.
1080 if int32(alignedValue) > cursym.Func().Align {
1081 cursym.Func().Align = int32(alignedValue)
1084 case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1087 c.ctxt.Diag("zero-width instruction\n%v", p)
1092 if o.flag&LFROM != 0 {
1093 c.addpool(p, &p.From)
1095 if o.flag&LFROM128 != 0 {
1096 c.addpool128(p, &p.From, p.GetFrom3())
1098 if o.flag<O != 0 {
1101 if c.blitrl != nil {
1109 * if any procedure is large enough to
1110 * generate a large SBRA branch, then
1111 * generate extra passes putting branches
1112 * around jmps to fix. this is rare.
1117 for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
1121 /* very large branches */
1122 if (o.flag&BRANCH14BITS != 0 || o.flag&BRANCH19BITS != 0) && p.To.Target() != nil {
1123 otxt := p.To.Target().Pc - pc
1125 if o.flag&BRANCH14BITS != 0 { // branch instruction encodes 14 bits
1126 toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
1127 } else if o.flag&BRANCH19BITS != 0 { // branch instruction encodes 19 bits
1128 toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
1135 q.To.Type = obj.TYPE_BRANCH
1136 q.To.SetTarget(p.To.Target())
1142 q.To.Type = obj.TYPE_BRANCH
1143 q.To.SetTarget(q.Link.Link)
1147 m = o.size(c.ctxt, p)
1152 alignedValue := p.From.Offset
1153 m = pcAlignPadLength(pc, alignedValue, ctxt)
1155 case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1158 c.ctxt.Diag("zero-width instruction\n%v", p)
1166 pc += -pc & (funcAlign - 1)
1170 * lay out the code, emitting code and data relocations.
1172 c.cursym.Grow(c.cursym.Size)
1177 for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
1180 sz := o.size(c.ctxt, p)
1181 if sz > 4*len(out) {
1182 log.Fatalf("out array in span7 is too small, need at least %d for %v", sz/4, p)
1184 if p.As == obj.APCALIGN {
1185 alignedValue := p.From.Offset
1186 v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt)
1187 for i = 0; i < int(v/4); i++ {
1188 // emit ANOOP instruction by the padding size
1189 c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
1194 c.asmout(p, o, out[:])
1195 for i = 0; i < sz/4; i++ {
1196 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
1203 // Mark nonpreemptible instruction sequences.
1204 // We use REGTMP as a scratch register during call injection,
1205 // so instruction sequences that use REGTMP are unsafe to
1206 // preempt asynchronously.
1207 obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
1209 // Now that we know byte offsets, we can generate jump table entries.
1210 for _, jt := range cursym.Func().JumpTables {
1211 for i, p := range jt.Targets {
1212 // The ith jumptable entry points to the p.Pc'th
1213 // byte in the function symbol s.
1214 // TODO: try using relative PCs.
1215 jt.Sym.WriteAddr(ctxt, int64(i)*8, 8, cursym, p.Pc)
1220 // isUnsafePoint returns whether p is an unsafe point.
1221 func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
1222 // If p explicitly uses REGTMP, it's unsafe to preempt, because the
1223 // preemption sequence clobbers REGTMP.
1224 return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP ||
1225 p.From.Type == obj.TYPE_REGREG && p.From.Offset == REGTMP ||
1226 p.To.Type == obj.TYPE_REGREG && p.To.Offset == REGTMP
1229 // isRestartable returns whether p is a multi-instruction sequence that,
1230 // if preempted, can be restarted.
1231 func (c *ctxt7) isRestartable(p *obj.Prog) bool {
1232 if c.isUnsafePoint(p) {
1235 // If p is a multi-instruction sequence with uses REGTMP inserted by
1236 // the assembler in order to materialize a large constant/offset, we
1237 // can restart p (at the start of the instruction sequence), recompute
1238 // the content of REGTMP, upon async preemption. Currently, all cases
1239 // of assembler-inserted REGTMP fall into this category.
1240 // If p doesn't use REGTMP, it can be simply preempted, so we don't
1243 return o.size(c.ctxt, p) > 4 && o.flag&NOTUSETMP == 0
1247 * when the first reference to the literal pool threatens
1248 * to go out of range of a 1Mb PC-relative offset
1249 * drop the pool now.
1251 func (c *ctxt7) checkpool(p *obj.Prog) {
1252 // If the pool is going to go out of range or p is the last instruction of the function,
1254 if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) || p.Link == nil {
1259 func (c *ctxt7) flushpool(p *obj.Prog) {
1260 // Needs to insert a branch before flushing the pool.
1261 // We don't need the jump if following an unconditional branch.
1262 // TODO: other unconditional operations.
1263 if !(p.As == AB || p.As == obj.ARET || p.As == AERET) {
1264 if c.ctxt.Debugvlog {
1265 fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
1269 // If p is the last instruction of the function, insert an UNDEF instruction in case the
1270 // exection fall through to the pool.
1273 // Else insert a branch to the next instruction of p.
1275 q.To.Type = obj.TYPE_BRANCH
1276 q.To.SetTarget(p.Link)
1283 // The line number for constant pool entries doesn't really matter.
1284 // We set it to the line number of the preceding instruction so that
1285 // there are no deltas to encode in the pc-line tables.
1286 for q := c.blitrl; q != nil; q = q.Link {
1290 c.elitrl.Link = p.Link
1293 c.blitrl = nil /* BUG: should refer back to values until out-of-range */
1299 // addpool128 adds a 128-bit constant to literal pool by two consecutive DWORD
1300 // instructions, the 128-bit constant is formed by ah.Offset<<64+al.Offset.
1301 func (c *ctxt7) addpool128(p *obj.Prog, al, ah *obj.Addr) {
1304 q.To.Type = obj.TYPE_CONST
1305 q.To.Offset = al.Offset // q.Pc is lower than t.Pc, so al.Offset is stored in q.
1309 t.To.Type = obj.TYPE_CONST
1310 t.To.Offset = ah.Offset
1314 if c.blitrl == nil {
1316 c.pool.start = uint32(p.Pc)
1322 c.pool.size = roundUp(c.pool.size, 16)
1328 * MOVD foo(SB), R is actually
1331 * where addr is the address of the DWORD containing the address of foo.
1335 func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
1342 if a.Type == obj.TYPE_CONST {
1343 if (lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit))) || p.As == AVMOVQ || p.As == AVMOVD {
1344 // out of range -0x80000000 ~ 0xffffffff or VMOVQ or VMOVD operand, must store 64-bit.
1347 } // else store 32-bit
1348 } 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)) {
1349 // conservative: don't know if we want signed or unsigned extension.
1350 // in case of ambiguity, store 64-bit
1355 t.To.Type = obj.TYPE_CONST
1358 for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
1365 if c.blitrl == nil {
1367 c.pool.start = uint32(p.Pc)
1373 // make DWORD 8-byte aligned, this is not required by ISA,
1374 // just to avoid performance penalties when loading from
1375 // the constant pool across a cache line.
1376 c.pool.size = roundUp(c.pool.size, 8)
1378 c.pool.size += uint32(sz)
1382 // roundUp rounds up x to "to".
1383 func roundUp(x, to uint32) uint32 {
1384 if to == 0 || to&(to-1) != 0 {
1385 log.Fatalf("rounded up to a value that is not a power of 2: %d\n", to)
1387 return (x + to - 1) &^ (to - 1)
1390 func (c *ctxt7) regoff(a *obj.Addr) uint32 {
1393 return uint32(c.instoffset)
1396 func isSTLXRop(op obj.As) bool {
1398 case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
1399 ASTXR, ASTXRW, ASTXRB, ASTXRH:
1405 func isSTXPop(op obj.As) bool {
1407 case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
1413 func isANDop(op obj.As) bool {
1415 case AAND, AORR, AEOR, AANDS, ATST,
1416 ABIC, AEON, AORN, ABICS:
1422 func isANDWop(op obj.As) bool {
1424 case AANDW, AORRW, AEORW, AANDSW, ATSTW,
1425 ABICW, AEONW, AORNW, ABICSW:
1431 func isADDop(op obj.As) bool {
1433 case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
1439 func isADDWop(op obj.As) bool {
1441 case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
1447 func isADDSop(op obj.As) bool {
1449 case AADDS, AADDSW, ASUBS, ASUBSW:
1455 func isNEGop(op obj.As) bool {
1457 case ANEG, ANEGW, ANEGS, ANEGSW:
1463 func isRegShiftOrExt(a *obj.Addr) bool {
1464 return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0
1467 // Maximum PC-relative displacement.
1468 // The actual limit is ±2²⁰, but we are conservative
1469 // to avoid needing to recompute the literal pool flush points
1470 // as span-dependent jumps are enlarged.
1471 const maxPCDisp = 512 * 1024
1473 // ispcdisp reports whether v is a valid PC-relative displacement.
1474 func ispcdisp(v int32) bool {
1475 return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
1478 func isaddcon(v int64) bool {
1479 /* uimm12 or uimm24? */
1483 if (v & 0xFFF) == 0 {
1489 func isaddcon2(v int64) bool {
1490 return 0 <= v && v <= 0xFFFFFF
1493 // isbitcon reports whether a constant can be encoded into a logical instruction.
1494 // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
1495 // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
1496 // special cases: 0 and -1 are not bitcon.
1497 // this function needs to run against virtually all the constants, so it needs to be fast.
1498 // for this reason, bitcon testing and bitcon encoding are separate functions.
1499 func isbitcon(x uint64) bool {
1500 if x == 1<<64-1 || x == 0 {
1503 // determine the period and sign-extend a unit to 64 bits
1505 case x != x>>32|x<<32:
1508 case x != x>>16|x<<48:
1510 x = uint64(int64(int32(x)))
1511 case x != x>>8|x<<56:
1513 x = uint64(int64(int16(x)))
1514 case x != x>>4|x<<60:
1516 x = uint64(int64(int8(x)))
1518 // period is 4 or 2, always true
1519 // 0001, 0010, 0100, 1000 -- 0001 rotate
1520 // 0011, 0110, 1100, 1001 -- 0011 rotate
1521 // 0111, 1011, 1101, 1110 -- 0111 rotate
1522 // 0101, 1010 -- 01 rotate, repeat
1525 return sequenceOfOnes(x) || sequenceOfOnes(^x)
1528 // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros.
1529 func sequenceOfOnes(x uint64) bool {
1530 y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
1535 // bitconEncode returns the encoding of a bitcon used in logical instructions
1536 // x is known to be a bitcon
1537 // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
1538 // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
1539 // it is encoded in logical instructions with 3 bitfields
1540 // N (1 bit) : R (6 bits) : S (6 bits), where
1542 // N=0, S=0xxxxx -- period=32
1543 // N=0, S=10xxxx -- period=16
1544 // N=0, S=110xxx -- period=8
1545 // N=0, S=1110xx -- period=4
1546 // N=0, S=11110x -- period=2
1547 // R is the shift amount, low bits of S = n-1
1548 func bitconEncode(x uint64, mode int) uint32 {
1554 // determine the period and sign-extend a unit to 64 bits
1556 case x != x>>32|x<<32:
1558 case x != x>>16|x<<48:
1560 x = uint64(int64(int32(x)))
1561 case x != x>>8|x<<56:
1563 x = uint64(int64(int16(x)))
1564 case x != x>>4|x<<60:
1566 x = uint64(int64(int8(x)))
1567 case x != x>>2|x<<62:
1569 x = uint64(int64(x<<60) >> 60)
1572 x = uint64(int64(x<<62) >> 62)
1579 y := x & -x // lowest set bit of x.
1581 n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
1583 // ^x is a sequence of n ones left shifted by s bits
1584 // adjust n, s for x
1590 if mode == 64 && period == 64 {
1593 R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
1594 S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period
1595 return N<<22 | R<<16 | S<<10
1598 func log2(x uint64) uint32 {
1630 func autoclass(l int64) int {
1636 if l >= -256 && (l&15) == 0 {
1639 if l >= -256 && (l&7) == 0 {
1642 if l >= -256 && (l&3) == 0 {
1648 if l >= -512 && (l&15) == 0 {
1651 if l >= -512 && (l&7) == 0 {
1654 if l >= -1024 && (l&15) == 0 {
1719 return C_UAUTO16K_16
1730 return C_UAUTO32K_16
1736 if l <= 65520 && (l&15) == 0 {
1742 func oregclass(l int64) int {
1743 return autoclass(l) - C_ZAUTO + C_ZOREG
1747 * given an offset v and a class c (see above)
1748 * return the offset value to use in the instruction,
1749 * scaled if necessary
1751 func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
1753 if cls >= C_SEXT1 && cls <= C_SEXT16 {
1757 case C_UAUTO4K, C_UOREG4K, C_ZOREG:
1759 case C_UAUTO8K, C_UOREG8K:
1761 case C_UAUTO16K, C_UOREG16K:
1763 case C_UAUTO32K, C_UOREG32K:
1765 case C_UAUTO64K, C_UOREG64K:
1768 c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
1772 if vs<<uint(s) != v {
1773 c.ctxt.Diag("odd offset: %d\n%v", v, p)
1779 * if v contains a single 16-bit value aligned
1780 * on a 16-bit field, and thus suitable for movk/movn,
1781 * return the field index 0 to 3; otherwise return -1.
1783 func movcon(v int64) int {
1784 for s := 0; s < 64; s += 16 {
1785 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
1792 func rclass(r int16) int {
1794 case REG_R0 <= r && r <= REG_R30: // not 31
1798 case REG_F0 <= r && r <= REG_F31:
1800 case REG_V0 <= r && r <= REG_V31:
1804 case r >= REG_ARNG && r < REG_ELEM:
1806 case r >= REG_ELEM && r < REG_ELEM_END:
1808 case r >= REG_UXTB && r < REG_SPECIAL,
1809 r >= REG_LSL && r < REG_ARNG:
1811 case r >= REG_SPECIAL:
1817 // con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
1818 // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
1819 func (c *ctxt7) con32class(a *obj.Addr) int {
1820 v := uint32(a.Offset)
1821 // For 32-bit instruction with constant, rewrite
1822 // the high 32-bit to be a repetition of the low
1823 // 32-bit, so that the BITCON test can be shared
1824 // for both 32-bit and 64-bit. 32-bit ops will
1825 // zero the high 32-bit of the destination register
1827 vbitcon := uint64(v)<<32 | uint64(v)
1831 if isaddcon(int64(v)) {
1833 if isbitcon(vbitcon) {
1838 if isbitcon(vbitcon) {
1841 if movcon(int64(v)) >= 0 {
1844 if movcon(int64(^v)) >= 0 {
1850 t := movcon(int64(v))
1852 if isbitcon(vbitcon) {
1858 t = movcon(int64(^v))
1860 if isbitcon(vbitcon) {
1866 if isbitcon(vbitcon) {
1870 if 0 <= v && v <= 0xffffff {
1876 // con64class reclassifies the constant of C_VCON and C_LCON class.
1877 func (c *ctxt7) con64class(a *obj.Addr) int {
1880 for i := uint(0); i < 4; i++ {
1881 immh := uint32(a.Offset >> (i * 16) & 0xffff)
1884 } else if immh == 0xffff {
1888 if zeroCount >= 3 || negCount >= 3 {
1890 } else if zeroCount == 2 || negCount == 2 {
1892 } else if zeroCount == 1 || negCount == 1 {
1899 func (c *ctxt7) aclass(a *obj.Addr) int {
1905 return rclass(a.Reg)
1907 case obj.TYPE_REGREG:
1910 case obj.TYPE_SHIFT:
1913 case obj.TYPE_REGLIST:
1917 // The base register should be an integer register.
1918 if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
1922 case obj.NAME_EXTERN, obj.NAME_STATIC:
1926 c.instoffset = a.Offset
1927 if a.Sym != nil { // use relocation
1928 if a.Sym.Type == objabi.STLSBSS {
1929 if c.ctxt.Flag_shared {
1939 case obj.NAME_GOTREF:
1944 // unset base register for better printing, since
1945 // a.Offset is still relative to pseudo-SP.
1946 a.Reg = obj.REG_NONE
1948 // The frame top 8 or 16 bytes are for FP
1949 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
1950 return autoclass(c.instoffset)
1952 case obj.NAME_PARAM:
1954 // unset base register for better printing, since
1955 // a.Offset is still relative to pseudo-FP.
1956 a.Reg = obj.REG_NONE
1958 c.instoffset = int64(c.autosize) + a.Offset + 8
1959 return autoclass(c.instoffset)
1964 if isRegShiftOrExt(a) {
1965 // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
1970 // register offset, (Rn)(Rm)
1973 c.instoffset = a.Offset
1974 return oregclass(c.instoffset)
1978 case obj.TYPE_FCONST:
1981 case obj.TYPE_TEXTSIZE:
1984 case obj.TYPE_CONST, obj.TYPE_ADDR:
1987 c.instoffset = a.Offset
1988 if a.Reg != 0 && a.Reg != REGZERO {
1997 if isbitcon(uint64(v)) {
2002 if isbitcon(uint64(v)) {
2008 if movcon(^v) >= 0 {
2016 if isbitcon(uint64(v)) {
2024 if isbitcon(uint64(v)) {
2030 if isbitcon(uint64(v)) {
2034 if 0 <= v && v <= 0xffffff {
2038 if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
2043 case obj.NAME_EXTERN, obj.NAME_STATIC:
2047 if a.Sym.Type == objabi.STLSBSS {
2048 c.ctxt.Diag("taking address of TLS variable is not supported")
2050 c.instoffset = a.Offset
2055 // unset base register for better printing, since
2056 // a.Offset is still relative to pseudo-SP.
2057 a.Reg = obj.REG_NONE
2059 // The frame top 8 or 16 bytes are for FP
2060 c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
2062 case obj.NAME_PARAM:
2064 // unset base register for better printing, since
2065 // a.Offset is still relative to pseudo-FP.
2066 a.Reg = obj.REG_NONE
2068 c.instoffset = int64(c.autosize) + a.Offset + 8
2073 if isaddcon(cf) || isaddcon(-cf) {
2082 case obj.TYPE_BRANCH:
2085 case obj.TYPE_SPECIAL:
2086 opd := SpecialOperand(a.Offset)
2087 if SPOP_EQ <= opd && opd <= SPOP_NV {
2095 func oclass(a *obj.Addr) int {
2096 return int(a.Class) - 1
2099 func (c *ctxt7) oplook(p *obj.Prog) *Optab {
2104 a1 = int(p.From.Class)
2106 a0 := c.aclass(&p.From)
2107 // do not break C_ADDCON2 when S bit is set
2108 if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
2112 p.From.Class = int8(a1)
2113 if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
2114 if p.As == AMOVW || isADDWop(p.As) || isANDWop(p.As) {
2115 // For 32-bit instruction with constant, we need to
2116 // treat its offset value as 32 bits to classify it.
2117 ra0 := c.con32class(&p.From)
2118 // do not break C_ADDCON2 when S bit is set
2119 if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
2123 p.From.Class = int8(a1)
2125 if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
2126 // more specific classification of 64-bit integers
2127 a1 = c.con64class(&p.From) + 1
2128 p.From.Class = int8(a1)
2135 if p.GetFrom3() != nil && p.RestArgs[0].Pos == 0 {
2136 a3 = int(p.GetFrom3().Class)
2138 a3 = c.aclass(p.GetFrom3()) + 1
2139 p.GetFrom3().Class = int8(a3)
2144 a4 := int(p.To.Class)
2146 a4 = c.aclass(&p.To) + 1
2147 p.To.Class = int8(a4)
2157 fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
2158 fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
2161 ops := oprange[p.As&obj.AMask]
2166 c5 := &xcmp[p.Scond>>5]
2167 for i := range ops {
2169 if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
2170 p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
2175 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)
2176 // Turn illegal instruction into an UNDEF, avoid crashing in asmout
2177 return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
2180 func cmp(a int, b int) bool {
2196 if b == C_ZCON || b == C_ABCON0 {
2201 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
2211 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
2216 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON {
2221 if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
2226 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 {
2231 return cmp(C_LCON, b)
2234 return cmp(C_LCON, b)
2237 if b == C_AACON || b == C_AACON2 {
2247 if b == C_SEXT1 || b == C_SEXT2 {
2252 if b >= C_SEXT1 && b <= C_SEXT4 {
2257 if b >= C_SEXT1 && b <= C_SEXT8 {
2262 if b >= C_SEXT1 && b <= C_SEXT16 {
2267 if b == C_NSAUTO_16 {
2272 if b == C_NSAUTO_16 || b == C_NSAUTO_8 {
2278 case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16:
2290 case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16:
2296 case C_NSAUTO_16, C_NPAUTO_16:
2302 case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16,
2303 C_NPAUTO, C_NQAUTO_16:
2313 if b == C_ZAUTO || b == C_PSAUTO_16 {
2319 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8:
2325 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4:
2331 case C_ZAUTO, C_PSAUTO_16:
2337 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16:
2343 case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16:
2349 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2350 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2351 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16:
2357 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2358 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2359 C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2360 C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16:
2366 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2367 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2368 C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2369 C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
2370 C_UAUTO16K_8, C_UAUTO16K_16:
2376 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2377 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2378 C_UAUTO4K_8, C_UAUTO4K_16,
2379 C_UAUTO8K_8, C_UAUTO8K_16,
2380 C_UAUTO16K_8, C_UAUTO16K_16,
2387 case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2388 C_PPAUTO_16, C_PQAUTO_16, C_UAUTO4K_16, C_UAUTO8K_16, C_UAUTO16K_16,
2395 case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16, C_NPAUTO_16, C_NPAUTO, C_NQAUTO_16, C_NAUTO4K,
2396 C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PSAUTO_16,
2397 C_PPAUTO, C_PPAUTO_16, C_PQAUTO_16,
2398 C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO4K_16,
2399 C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO8K_16,
2400 C_UAUTO16K, C_UAUTO16K_8, C_UAUTO16K_16,
2401 C_UAUTO32K, C_UAUTO32K_16,
2407 if b == C_NSOREG_16 {
2412 if b == C_NSOREG_8 || b == C_NSOREG_16 {
2418 case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16:
2430 case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16:
2436 case C_NSOREG_16, C_NPOREG_16:
2442 case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16:
2452 if b == C_ZOREG || b == C_PSOREG_16 {
2458 case C_ZOREG, C_PSOREG_16, C_PSOREG_8:
2464 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4:
2470 case C_ZOREG, C_PSOREG_16:
2476 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16:
2482 case C_ZOREG, C_PSOREG_16, C_PPOREG_16:
2488 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2489 C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2490 C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16:
2496 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2497 C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2498 C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2499 C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16:
2505 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2506 C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2507 C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2508 C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
2509 C_UOREG16K_8, C_UOREG16K_16:
2515 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2516 C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2517 C_UOREG4K_8, C_UOREG4K_16,
2518 C_UOREG8K_8, C_UOREG8K_16,
2519 C_UOREG16K_8, C_UOREG16K_16,
2526 case C_ZOREG, C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2527 C_PPOREG_16, C_PQOREG_16, C_UOREG4K_16, C_UOREG8K_16, C_UOREG16K_16,
2534 case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NSOREG_16, C_NPOREG, C_NPOREG_16, C_NQOREG_16, C_NOREG4K,
2535 C_PSOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG_16,
2536 C_PPOREG, C_PPOREG_16, C_PQOREG_16,
2537 C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8, C_UOREG4K_16,
2538 C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8, C_UOREG8K_16,
2539 C_UOREG16K, C_UOREG16K_8, C_UOREG16K_16,
2540 C_UOREG32K, C_UOREG32K_16,
2556 func (x ocmp) Len() int {
2560 func (x ocmp) Swap(i, j int) {
2561 x[i], x[j] = x[j], x[i]
2564 func (x ocmp) Less(i, j int) bool {
2568 return p1.as < p2.as
2571 return p1.a1 < p2.a1
2574 return p1.a2 < p2.a2
2577 return p1.a3 < p2.a3
2580 return p1.a4 < p2.a4
2582 if p1.scond != p2.scond {
2583 return p1.scond < p2.scond
2588 func oprangeset(a obj.As, t []Optab) {
2589 oprange[a&obj.AMask] = t
2592 func buildop(ctxt *obj.Link) {
2593 if oprange[AAND&obj.AMask] != nil {
2594 // Already initialized; stop now.
2595 // This happens in the cmd/asm tests,
2596 // each of which re-initializes the arch.
2601 for i := 0; i < C_GOK; i++ {
2602 for n = 0; n < C_GOK; n++ {
2608 for n = 0; optab[n].as != obj.AXXX; n++ {
2610 sort.Sort(ocmp(optab[:n]))
2611 for i := 0; i < n; i++ {
2614 for optab[i].as == r {
2622 ctxt.Diag("unknown op in build: %v", r)
2624 log.Fatalf("bad code")
2627 oprangeset(AADDS, t)
2629 oprangeset(ASUBS, t)
2630 oprangeset(AADDW, t)
2631 oprangeset(AADDSW, t)
2632 oprangeset(ASUBW, t)
2633 oprangeset(ASUBSW, t)
2635 case AAND: /* logical immediate, logical shifted register */
2636 oprangeset(AANDW, t)
2638 oprangeset(AEORW, t)
2640 oprangeset(AORRW, t)
2642 oprangeset(ABICW, t)
2644 oprangeset(AEONW, t)
2646 oprangeset(AORNW, t)
2648 case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
2649 oprangeset(AANDSW, t)
2650 oprangeset(ABICS, t)
2651 oprangeset(ABICSW, t)
2654 oprangeset(ANEGS, t)
2655 oprangeset(ANEGSW, t)
2656 oprangeset(ANEGW, t)
2658 case AADC: /* rn=Rd */
2659 oprangeset(AADCW, t)
2661 oprangeset(AADCS, t)
2662 oprangeset(AADCSW, t)
2664 oprangeset(ASBCW, t)
2665 oprangeset(ASBCS, t)
2666 oprangeset(ASBCSW, t)
2668 case ANGC: /* rn=REGZERO */
2669 oprangeset(ANGCW, t)
2671 oprangeset(ANGCS, t)
2672 oprangeset(ANGCSW, t)
2675 oprangeset(ACMPW, t)
2677 oprangeset(ACMNW, t)
2680 oprangeset(ATSTW, t)
2682 /* register/register, and shifted */
2684 oprangeset(AMVNW, t)
2687 oprangeset(AMOVKW, t)
2688 oprangeset(AMOVN, t)
2689 oprangeset(AMOVNW, t)
2690 oprangeset(AMOVZ, t)
2691 oprangeset(AMOVZW, t)
2694 for i := range atomicLDADD {
2697 for i := range atomicSWP {
2705 oprangeset(ACASPW, t)
2724 oprangeset(ALSLW, t)
2726 oprangeset(ALSRW, t)
2728 oprangeset(AASRW, t)
2730 oprangeset(ARORW, t)
2733 oprangeset(ACLSW, t)
2735 oprangeset(ACLZW, t)
2736 oprangeset(ARBIT, t)
2737 oprangeset(ARBITW, t)
2739 oprangeset(AREVW, t)
2740 oprangeset(AREV16, t)
2741 oprangeset(AREV16W, t)
2742 oprangeset(AREV32, t)
2745 oprangeset(ASDIVW, t)
2746 oprangeset(AUDIV, t)
2747 oprangeset(AUDIVW, t)
2748 oprangeset(ACRC32B, t)
2749 oprangeset(ACRC32CB, t)
2750 oprangeset(ACRC32CH, t)
2751 oprangeset(ACRC32CW, t)
2752 oprangeset(ACRC32CX, t)
2753 oprangeset(ACRC32H, t)
2754 oprangeset(ACRC32W, t)
2755 oprangeset(ACRC32X, t)
2758 oprangeset(AMADDW, t)
2759 oprangeset(AMSUB, t)
2760 oprangeset(AMSUBW, t)
2761 oprangeset(ASMADDL, t)
2762 oprangeset(ASMSUBL, t)
2763 oprangeset(AUMADDL, t)
2764 oprangeset(AUMSUBL, t)
2767 oprangeset(AREMW, t)
2768 oprangeset(AUREM, t)
2769 oprangeset(AUREMW, t)
2772 oprangeset(AMULW, t)
2773 oprangeset(AMNEG, t)
2774 oprangeset(AMNEGW, t)
2775 oprangeset(ASMNEGL, t)
2776 oprangeset(ASMULL, t)
2777 oprangeset(ASMULH, t)
2778 oprangeset(AUMNEGL, t)
2779 oprangeset(AUMULH, t)
2780 oprangeset(AUMULL, t)
2783 oprangeset(AMOVBU, t)
2786 oprangeset(AMOVHU, t)
2789 oprangeset(AMOVWU, t)
2792 oprangeset(ABFMW, t)
2793 oprangeset(ASBFM, t)
2794 oprangeset(ASBFMW, t)
2795 oprangeset(AUBFM, t)
2796 oprangeset(AUBFMW, t)
2799 oprangeset(ABFIW, t)
2800 oprangeset(ABFXIL, t)
2801 oprangeset(ABFXILW, t)
2802 oprangeset(ASBFIZ, t)
2803 oprangeset(ASBFIZW, t)
2804 oprangeset(ASBFX, t)
2805 oprangeset(ASBFXW, t)
2806 oprangeset(AUBFIZ, t)
2807 oprangeset(AUBFIZW, t)
2808 oprangeset(AUBFX, t)
2809 oprangeset(AUBFXW, t)
2812 oprangeset(AEXTRW, t)
2815 oprangeset(ASXTBW, t)
2816 oprangeset(ASXTH, t)
2817 oprangeset(ASXTHW, t)
2818 oprangeset(ASXTW, t)
2819 oprangeset(AUXTB, t)
2820 oprangeset(AUXTH, t)
2821 oprangeset(AUXTW, t)
2822 oprangeset(AUXTBW, t)
2823 oprangeset(AUXTHW, t)
2826 oprangeset(ACCMNW, t)
2827 oprangeset(ACCMP, t)
2828 oprangeset(ACCMPW, t)
2831 oprangeset(ACSELW, t)
2832 oprangeset(ACSINC, t)
2833 oprangeset(ACSINCW, t)
2834 oprangeset(ACSINV, t)
2835 oprangeset(ACSINVW, t)
2836 oprangeset(ACSNEG, t)
2837 oprangeset(ACSNEGW, t)
2840 // aliases Rm=Rn, !cond
2841 oprangeset(ACINCW, t)
2842 oprangeset(ACINV, t)
2843 oprangeset(ACINVW, t)
2844 oprangeset(ACNEG, t)
2845 oprangeset(ACNEGW, t)
2847 // aliases, Rm=Rn=REGZERO, !cond
2849 oprangeset(ACSETW, t)
2851 oprangeset(ACSETM, t)
2852 oprangeset(ACSETMW, t)
2868 oprangeset(AFLDPD, t)
2871 oprangeset(AFSTPD, t)
2874 oprangeset(AFSTPS, t)
2877 oprangeset(ALDPSW, t)
2878 oprangeset(AFLDPS, t)
2883 oprangeset(AYIELD, t)
2885 oprangeset(ASEVL, t)
2886 oprangeset(ANOOP, t)
2887 oprangeset(ADRPS, t)
2890 oprangeset(ACBZW, t)
2891 oprangeset(ACBNZ, t)
2892 oprangeset(ACBNZW, t)
2895 oprangeset(ATBNZ, t)
2908 oprangeset(ADCPS1, t)
2909 oprangeset(ADCPS2, t)
2910 oprangeset(ADCPS3, t)
2913 oprangeset(AFADDD, t)
2914 oprangeset(AFSUBS, t)
2915 oprangeset(AFSUBD, t)
2916 oprangeset(AFMULS, t)
2917 oprangeset(AFMULD, t)
2918 oprangeset(AFNMULS, t)
2919 oprangeset(AFNMULD, t)
2920 oprangeset(AFDIVS, t)
2921 oprangeset(AFMAXD, t)
2922 oprangeset(AFMAXS, t)
2923 oprangeset(AFMIND, t)
2924 oprangeset(AFMINS, t)
2925 oprangeset(AFMAXNMD, t)
2926 oprangeset(AFMAXNMS, t)
2927 oprangeset(AFMINNMD, t)
2928 oprangeset(AFMINNMS, t)
2929 oprangeset(AFDIVD, t)
2932 oprangeset(AFMSUBS, t)
2933 oprangeset(AFMADDS, t)
2934 oprangeset(AFMADDD, t)
2935 oprangeset(AFNMSUBS, t)
2936 oprangeset(AFNMSUBD, t)
2937 oprangeset(AFNMADDS, t)
2938 oprangeset(AFNMADDD, t)
2941 oprangeset(AFCVTDS, t)
2942 oprangeset(AFABSD, t)
2943 oprangeset(AFABSS, t)
2944 oprangeset(AFNEGD, t)
2945 oprangeset(AFNEGS, t)
2946 oprangeset(AFSQRTD, t)
2947 oprangeset(AFSQRTS, t)
2948 oprangeset(AFRINTNS, t)
2949 oprangeset(AFRINTND, t)
2950 oprangeset(AFRINTPS, t)
2951 oprangeset(AFRINTPD, t)
2952 oprangeset(AFRINTMS, t)
2953 oprangeset(AFRINTMD, t)
2954 oprangeset(AFRINTZS, t)
2955 oprangeset(AFRINTZD, t)
2956 oprangeset(AFRINTAS, t)
2957 oprangeset(AFRINTAD, t)
2958 oprangeset(AFRINTXS, t)
2959 oprangeset(AFRINTXD, t)
2960 oprangeset(AFRINTIS, t)
2961 oprangeset(AFRINTID, t)
2962 oprangeset(AFCVTDH, t)
2963 oprangeset(AFCVTHS, t)
2964 oprangeset(AFCVTHD, t)
2965 oprangeset(AFCVTSH, t)
2968 oprangeset(AFCMPD, t)
2969 oprangeset(AFCMPES, t)
2970 oprangeset(AFCMPED, t)
2973 oprangeset(AFCCMPD, t)
2974 oprangeset(AFCCMPES, t)
2975 oprangeset(AFCCMPED, t)
2978 oprangeset(AFCSELS, t)
2980 case AFMOVQ, AFMOVD, AFMOVS,
2981 AVMOVQ, AVMOVD, AVMOVS:
2985 oprangeset(AFCVTZSDW, t)
2986 oprangeset(AFCVTZSS, t)
2987 oprangeset(AFCVTZSSW, t)
2988 oprangeset(AFCVTZUD, t)
2989 oprangeset(AFCVTZUDW, t)
2990 oprangeset(AFCVTZUS, t)
2991 oprangeset(AFCVTZUSW, t)
2994 oprangeset(ASCVTFS, t)
2995 oprangeset(ASCVTFWD, t)
2996 oprangeset(ASCVTFWS, t)
2997 oprangeset(AUCVTFD, t)
2998 oprangeset(AUCVTFS, t)
2999 oprangeset(AUCVTFWD, t)
3000 oprangeset(AUCVTFWS, t)
3020 oprangeset(ALDARW, t)
3021 oprangeset(ALDARB, t)
3022 oprangeset(ALDARH, t)
3026 oprangeset(ALDXRB, t)
3027 oprangeset(ALDXRH, t)
3028 oprangeset(ALDXRW, t)
3031 oprangeset(ALDAXRB, t)
3032 oprangeset(ALDAXRH, t)
3033 oprangeset(ALDAXRW, t)
3036 oprangeset(ALDXPW, t)
3037 oprangeset(ALDAXP, t)
3038 oprangeset(ALDAXPW, t)
3041 oprangeset(ASTLRB, t)
3042 oprangeset(ASTLRH, t)
3043 oprangeset(ASTLRW, t)
3046 oprangeset(ASTXRB, t)
3047 oprangeset(ASTXRH, t)
3048 oprangeset(ASTXRW, t)
3051 oprangeset(ASTLXRB, t)
3052 oprangeset(ASTLXRH, t)
3053 oprangeset(ASTLXRW, t)
3056 oprangeset(ASTLXP, t)
3057 oprangeset(ASTLXPW, t)
3058 oprangeset(ASTXPW, t)
3061 oprangeset(AVAND, t)
3062 oprangeset(AVCMEQ, t)
3063 oprangeset(AVORR, t)
3064 oprangeset(AVEOR, t)
3065 oprangeset(AVBSL, t)
3066 oprangeset(AVBIT, t)
3067 oprangeset(AVCMTST, t)
3068 oprangeset(AVUMAX, t)
3069 oprangeset(AVUMIN, t)
3070 oprangeset(AVUZP1, t)
3071 oprangeset(AVUZP2, t)
3072 oprangeset(AVBIF, t)
3075 oprangeset(AVSUB, t)
3076 oprangeset(AVRAX1, t)
3079 oprangeset(AAESE, t)
3080 oprangeset(AAESMC, t)
3081 oprangeset(AAESIMC, t)
3082 oprangeset(ASHA1SU1, t)
3083 oprangeset(ASHA256SU0, t)
3084 oprangeset(ASHA512SU0, t)
3087 oprangeset(ASHA1P, t)
3088 oprangeset(ASHA1M, t)
3091 oprangeset(ASHA256H2, t)
3092 oprangeset(ASHA512H, t)
3093 oprangeset(ASHA512H2, t)
3096 oprangeset(ASHA256SU1, t)
3097 oprangeset(ASHA512SU1, t)
3100 oprangeset(AVUADDLV, t)
3103 oprangeset(AVFMLS, t)
3106 oprangeset(AVPMULL2, t)
3109 oprangeset(AVSHL, t)
3110 oprangeset(AVSRI, t)
3111 oprangeset(AVSLI, t)
3112 oprangeset(AVUSRA, t)
3115 oprangeset(AVCNT, t)
3116 oprangeset(AVRBIT, t)
3117 oprangeset(AVREV64, t)
3118 oprangeset(AVREV16, t)
3121 oprangeset(AVZIP2, t)
3122 oprangeset(AVTRN1, t)
3123 oprangeset(AVTRN2, t)
3126 oprangeset(AVUXTL2, t)
3129 oprangeset(AVUSHLL2, t)
3132 oprangeset(AVLD2, t)
3133 oprangeset(AVLD2R, t)
3134 oprangeset(AVLD3, t)
3135 oprangeset(AVLD3R, t)
3136 oprangeset(AVLD4, t)
3137 oprangeset(AVLD4R, t)
3140 oprangeset(AVBCAX, t)
3143 oprangeset(AVUADDW2, t)
3146 oprangeset(AVTBX, t)
3175 // chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions.
3176 // For details of the range of constants available, see
3177 // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
3178 func (c *ctxt7) chipfloat7(e float64) int {
3179 ei := math.Float64bits(e)
3180 l := uint32(int32(ei))
3181 h := uint32(int32(ei >> 32))
3183 if l != 0 || h&0xffff != 0 {
3186 h1 := h & 0x7fc00000
3187 if h1 != 0x40000000 && h1 != 0x3fc00000 {
3193 if h&0x80000000 != 0 {
3198 if h1 == 0x3fc00000 {
3202 // rest of exp and mantissa (cd-efgh)
3203 n |= int((h >> 16) & 0x3f)
3205 //print("match %.8lux %.8lux %d\n", l, h, n);
3209 /* form offset parameter to SYS; special register number */
3210 func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
3211 return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
3214 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
3215 return SYSARG5(0, op1, Cn, Cm, op2)
3218 // checkUnpredictable checks if the source and transfer registers are the same register.
3219 // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
3220 func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
3221 if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
3222 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3224 if isload && rt1 == rt2 {
3225 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3229 /* checkindex checks if index >= 0 && index <= maxindex */
3230 func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
3231 if index < 0 || index > maxindex {
3232 c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
3236 /* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
3237 func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
3238 var offset, list, n, expect int64
3240 case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3241 offset = p.From.Offset
3243 case AVST1, AVST2, AVST3, AVST4:
3244 offset = p.To.Offset
3245 list = p.From.Offset
3247 c.ctxt.Diag("invalid operation on op %v", p.As)
3249 opcode := (list >> 12) & 15
3250 q := (list >> 30) & 1
3251 size := (list >> 10) & 3
3257 n = 1 // one register
3259 n = 2 // two registers
3261 n = 3 // three registers
3263 n = 4 // four registers
3265 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
3269 case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3270 if offset != n*(1<<uint(size)) {
3271 c.ctxt.Diag("invalid post-increment offset: %v", p)
3274 if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
3275 c.ctxt.Diag("invalid post-increment offset: %v", p)
3284 case AVLD2, AVST2, AVLD2R:
3286 case AVLD3, AVST3, AVLD3R:
3288 case AVLD4, AVST4, AVLD4R:
3293 c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
3297 /* checkShiftAmount checks whether the index shift amount is valid */
3298 /* for load with register offset instructions */
3299 func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
3301 amount = (a.Index >> 5) & 7
3305 c.ctxt.Diag("invalid index shift amount: %v", p)
3308 if amount != 1 && amount != 0 {
3309 c.ctxt.Diag("invalid index shift amount: %v", p)
3311 case AMOVW, AMOVWU, AFMOVS:
3312 if amount != 2 && amount != 0 {
3313 c.ctxt.Diag("invalid index shift amount: %v", p)
3316 if amount != 3 && amount != 0 {
3317 c.ctxt.Diag("invalid index shift amount: %v", p)
3320 panic("invalid operation")
3324 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3331 if false { /*debug['P']*/
3332 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
3336 c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
3338 case 0: /* pseudo ops */
3341 case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
3342 o1 = c.oprrr(p, p.As)
3344 rf := int(p.From.Reg)
3347 if p.To.Type == obj.TYPE_NONE {
3353 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3355 case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
3356 if p.To.Reg == REG_RSP && isADDSop(p.As) {
3357 c.ctxt.Diag("illegal destination register: %v\n", p)
3359 o1 = c.opirr(p, p.As)
3362 if p.To.Type == obj.TYPE_NONE {
3363 if (o1 & Sbit) == 0 {
3364 c.ctxt.Diag("ineffective ZR destination\n%v", p)
3373 v := int32(c.regoff(&p.From))
3374 o1 = c.oaddi(p, int32(o1), v, r, rt)
3376 case 3: /* op R<<n[,R],R (shifted register) */
3377 o1 = c.oprrr(p, p.As)
3379 amount := (p.From.Offset >> 10) & 63
3380 is64bit := o1 & (1 << 31)
3381 if is64bit == 0 && amount >= 32 {
3382 c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
3384 shift := (p.From.Offset >> 22) & 3
3385 if (shift > 2 || shift < 0) && (isADDop(p.As) || isADDWop(p.As) || isNEGop(p.As)) {
3386 c.ctxt.Diag("unsupported shift operator: %v", p)
3388 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
3390 if p.To.Type == obj.TYPE_NONE {
3394 if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) {
3399 o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3401 case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
3407 } else if r == REGFROM {
3414 v := int32(c.regoff(&p.From))
3418 op = int32(c.opirr(p, ASUB))
3420 op = int32(c.opirr(p, AADD))
3423 if int(o.size(c.ctxt, p)) == 8 {
3424 // NOTE: this case does not use REGTMP. If it ever does,
3425 // remove the NOTUSETMP flag in optab.
3426 o1 = c.oaddi(p, op, v&0xfff000, r, rt)
3427 o2 = c.oaddi(p, op, v&0x000fff, rt, rt)
3431 o1 = c.oaddi(p, op, v, r, rt)
3433 case 5: /* b s; bl s */
3434 o1 = c.opbra(p, p.As)
3436 if p.To.Sym == nil {
3437 o1 |= uint32(c.brdist(p, 0, 26, 2))
3441 rel := obj.Addrel(c.cursym)
3442 rel.Off = int32(c.pc)
3445 rel.Add = p.To.Offset
3446 rel.Type = objabi.R_CALLARM64
3448 case 6: /* b ,O(R); bl ,O(R) */
3449 o1 = c.opbrr(p, p.As)
3450 o1 |= uint32(p.To.Reg&31) << 5
3451 if p.As == obj.ACALL {
3452 rel := obj.Addrel(c.cursym)
3453 rel.Off = int32(c.pc)
3455 rel.Type = objabi.R_CALLIND
3459 o1 = c.opbra(p, p.As)
3461 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
3463 case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
3470 v := int32(p.From.Offset)
3473 o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
3476 o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
3479 o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
3482 o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
3485 o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
3488 o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
3491 o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
3494 o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
3497 c.ctxt.Diag("bad shift $con\n%v", p)
3501 case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
3502 o1 = c.oprrr(p, p.As)
3508 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
3510 case 10: /* brk/hvc/.../svc [$con] */
3511 o1 = c.opimm(p, p.As)
3513 if p.From.Type != obj.TYPE_NONE {
3514 o1 |= uint32((p.From.Offset & 0xffff) << 5)
3517 case 11: /* dword */
3520 o1 = uint32(c.instoffset)
3521 o2 = uint32(c.instoffset >> 32)
3522 if p.To.Sym != nil {
3523 rel := obj.Addrel(c.cursym)
3524 rel.Off = int32(c.pc)
3527 rel.Add = p.To.Offset
3528 rel.Type = objabi.R_ADDR
3533 case 12: /* movT $vcon, reg */
3534 // NOTE: this case does not use REGTMP. If it ever does,
3535 // remove the NOTUSETMP flag in optab.
3536 num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
3538 c.ctxt.Diag("invalid constant: %v", p)
3545 case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
3546 if p.Reg == REGTMP {
3547 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
3549 if p.To.Reg == REG_RSP && isADDSop(p.As) {
3550 c.ctxt.Diag("illegal destination register: %v\n", p)
3554 cls := oclass(&p.From)
3556 if !cmp(C_LCON, cls) {
3557 c.ctxt.Diag("illegal combination: %v", p)
3559 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3561 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3564 c.ctxt.Diag("invalid constant: %v", p)
3567 if p.To.Type == obj.TYPE_NONE {
3574 if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
3575 o = c.opxrrr(p, p.As, false)
3576 o |= REGTMP & 31 << 16
3579 o = c.oprrr(p, p.As)
3580 o |= REGTMP & 31 << 16 /* shift is 0 */
3583 o |= uint32(r&31) << 5
3584 o |= uint32(rt & 31)
3594 if c.aclass(&p.To) == C_ADDR {
3595 c.ctxt.Diag("address constant needs DWORD\n%v", p)
3597 o1 = uint32(c.instoffset)
3598 if p.To.Sym != nil {
3599 // This case happens with words generated
3600 // in the PC stream as part of the literal pool.
3601 rel := obj.Addrel(c.cursym)
3603 rel.Off = int32(c.pc)
3606 rel.Add = p.To.Offset
3607 rel.Type = objabi.R_ADDR
3611 case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
3612 o1 = c.oprrr(p, p.As)
3614 rf := int(p.From.Reg)
3618 if p.From3Type() == obj.TYPE_REG {
3619 r = int(p.GetFrom3().Reg)
3632 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
3634 case 16: /* XremY R[,R],R -> XdivY; XmsubY */
3635 o1 = c.oprrr(p, p.As)
3637 rf := int(p.From.Reg)
3643 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
3644 o2 = c.oprrr(p, AMSUBW)
3645 o2 |= o1 & (1 << 31) /* same size */
3646 o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
3648 case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
3649 o1 = c.oprrr(p, p.As)
3651 rf := int(p.From.Reg)
3654 if p.To.Type == obj.TYPE_NONE {
3660 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3662 case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
3663 o1 = c.oprrr(p, p.As)
3665 cond := SpecialOperand(p.From.Offset)
3666 if cond < SPOP_EQ || cond > SPOP_NV || (cond == SPOP_AL || cond == SPOP_NV) && p.From3Type() == obj.TYPE_NONE {
3667 c.ctxt.Diag("invalid condition: %v", p)
3674 if p.From3Type() == obj.TYPE_NONE {
3675 /* CINC/CINV/CNEG or CSET/CSETM*/
3683 rf = int(p.GetFrom3().Reg) /* CSEL */
3687 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
3689 case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
3690 nzcv := int(p.To.Offset)
3692 cond := SpecialOperand(p.From.Offset)
3693 if cond < SPOP_EQ || cond > SPOP_NV {
3694 c.ctxt.Diag("invalid condition\n%v", p)
3699 if p.GetFrom3().Type == obj.TYPE_REG {
3700 o1 = c.oprrr(p, p.As)
3701 rf = int(p.GetFrom3().Reg) /* Rm */
3703 o1 = c.opirr(p, p.As)
3704 rf = int(p.GetFrom3().Offset & 0x1F)
3707 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
3709 case 20: /* movT R,O(R) -> strT */
3710 v := int32(c.regoff(&p.To))
3711 sz := int32(1 << uint(movesize(p.As)))
3717 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3718 o1 = c.olsr9s(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
3720 v = int32(c.offsetshift(p, int64(v), int(o.a4)))
3721 o1 = c.olsr12u(p, int32(c.opstr(p, p.As)), v, r, int(p.From.Reg))
3724 case 21: /* movT O(R),R -> ldrT */
3725 v := int32(c.regoff(&p.From))
3726 sz := int32(1 << uint(movesize(p.As)))
3728 r := int(p.From.Reg)
3732 if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
3733 o1 = c.olsr9s(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
3735 v = int32(c.offsetshift(p, int64(v), int(o.a1)))
3736 //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
3737 o1 = c.olsr12u(p, int32(c.opldr(p, p.As)), v, r, int(p.To.Reg))
3740 case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
3741 if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
3742 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3745 v := int32(p.From.Offset)
3747 if v < -256 || v > 255 {
3748 c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3750 o1 = c.opldr(p, p.As)
3751 if o.scond == C_XPOST {
3756 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
3758 case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
3759 if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
3760 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3763 v := int32(p.To.Offset)
3765 if v < -256 || v > 255 {
3766 c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3768 o1 = c.opstr(p, p.As)
3769 if o.scond == C_XPOST {
3774 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
3776 case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
3777 rf := int(p.From.Reg)
3779 s := rf == REGSP || rt == REGSP
3780 if p.As == AMVN || p.As == AMVNW {
3782 c.ctxt.Diag("illegal SP reference\n%v", p)
3784 o1 = c.oprrr(p, p.As)
3785 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3787 o1 = c.opirr(p, p.As)
3788 o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
3790 o1 = c.oprrr(p, p.As)
3791 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3794 case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
3795 o1 = c.oprrr(p, p.As)
3797 rf := int(p.From.Reg)
3802 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3804 case 27: /* op Rm<<n[,Rn],Rd (extended register) */
3805 if p.To.Reg == REG_RSP && isADDSop(p.As) {
3806 c.ctxt.Diag("illegal destination register: %v\n", p)
3808 if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 ||
3809 (p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) {
3810 amount := (p.From.Reg >> 5) & 7
3812 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
3814 o1 = c.opxrrr(p, p.As, true)
3815 o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
3817 o1 = c.opxrrr(p, p.As, false)
3818 o1 |= uint32(p.From.Reg&31) << 16
3821 if p.To.Type == obj.TYPE_NONE {
3828 o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3830 case 28: /* logop $vcon, [R], R (64 bit literal) */
3831 if p.Reg == REGTMP {
3832 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
3836 cls := oclass(&p.From)
3838 if !cmp(C_LCON, cls) {
3839 c.ctxt.Diag("illegal combination: %v", p)
3841 num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3843 num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3847 c.ctxt.Diag("invalid constant: %v", p)
3850 if p.To.Type == obj.TYPE_NONE {
3857 o = c.oprrr(p, p.As)
3858 o |= REGTMP & 31 << 16 /* shift is 0 */
3859 o |= uint32(r&31) << 5
3860 o |= uint32(rt & 31)
3869 case 29: /* op Rn, Rd */
3870 fc := c.aclass(&p.From)
3871 tc := c.aclass(&p.To)
3872 if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZREG || tc == C_REG) {
3873 // FMOV Rx, Fy or FMOV Fy, Rx
3874 o1 = FPCVTI(0, 0, 0, 0, 6)
3876 o1 |= 1<<31 | 1<<22 // 64-bit
3878 if fc == C_REG || fc == C_ZREG {
3879 o1 |= 1 << 16 // FMOV Rx, Fy
3882 o1 = c.oprrr(p, p.As)
3884 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
3886 case 30: /* movT R,L(R) -> strT */
3887 // if offset L can be split into hi+lo, and both fit into instructions, do
3890 // otherwise, use constant pool
3891 // mov $L, Rtmp (from constant pool)
3895 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3903 v := int32(c.regoff(&p.To))
3905 if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3906 // negative or unaligned offset, use constant pool
3910 hi = v - (v & (0xFFF << uint(s)))
3912 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
3914 if hi&^0xFFF000 != 0 {
3915 // hi doesn't fit into an ADD instruction
3919 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
3920 o2 = c.olsr12u(p, int32(c.opstr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
3924 if r == REGTMP || p.From.Reg == REGTMP {
3925 c.ctxt.Diag("REGTMP used in large offset store: %v", p)
3927 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
3928 o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
3930 case 31: /* movT L(R), R -> ldrT */
3931 // if offset L can be split into hi+lo, and both fit into instructions, do
3934 // otherwise, use constant pool
3935 // mov $L, Rtmp (from constant pool)
3939 c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3942 r := int(p.From.Reg)
3947 v := int32(c.regoff(&p.From))
3949 if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3950 // negative or unaligned offset, use constant pool
3954 hi = v - (v & (0xFFF << uint(s)))
3955 if (hi & 0xFFF) != 0 {
3956 c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
3958 if hi&^0xFFF000 != 0 {
3959 // hi doesn't fit into an ADD instruction
3963 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
3964 o2 = c.olsr12u(p, int32(c.opldr(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
3968 if r == REGTMP || p.From.Reg == REGTMP {
3969 c.ctxt.Diag("REGTMP used in large offset load: %v", p)
3971 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
3972 o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
3974 case 32: /* mov $con, R -> movz/movn */
3975 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
3977 case 33: /* movk $uimm16 << pos */
3978 o1 = c.opirr(p, p.As)
3982 c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p)
3985 if s < 0 || s >= 4 {
3986 c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
3988 if (o1&S64) == 0 && s >= 2 {
3989 c.ctxt.Diag("illegal bit position\n%v", p)
3991 if ((uint64(d) >> uint(s*16)) >> 16) != 0 {
3992 c.ctxt.Diag("requires uimm16\n%v", p)
3996 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
3998 case 34: /* mov $lacon,R */
3999 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4004 o2 = c.opxrrr(p, AADD, false)
4005 o2 |= REGTMP & 31 << 16
4007 r := int(p.From.Reg)
4011 o2 |= uint32(r&31) << 5
4012 o2 |= uint32(p.To.Reg & 31)
4014 case 35: /* mov SPR,R -> mrs */
4015 o1 = c.oprrr(p, AMRS)
4017 // SysRegEnc function returns the system register encoding and accessFlags.
4018 _, v, accessFlags := SysRegEnc(p.From.Reg)
4020 c.ctxt.Diag("illegal system register:\n%v", p)
4022 if (o1 & (v &^ (3 << 19))) != 0 {
4023 c.ctxt.Diag("MRS register value overlap\n%v", p)
4025 if accessFlags&SR_READ == 0 {
4026 c.ctxt.Diag("system register is not readable: %v", p)
4030 o1 |= uint32(p.To.Reg & 31)
4032 case 36: /* mov R,SPR */
4033 o1 = c.oprrr(p, AMSR)
4035 // SysRegEnc function returns the system register encoding and accessFlags.
4036 _, v, accessFlags := SysRegEnc(p.To.Reg)
4038 c.ctxt.Diag("illegal system register:\n%v", p)
4040 if (o1 & (v &^ (3 << 19))) != 0 {
4041 c.ctxt.Diag("MSR register value overlap\n%v", p)
4043 if accessFlags&SR_WRITE == 0 {
4044 c.ctxt.Diag("system register is not writable: %v", p)
4048 o1 |= uint32(p.From.Reg & 31)
4050 case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
4051 if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
4052 c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
4054 o1 = c.opirr(p, AMSR)
4055 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
4057 // PSTATEfield can be special registers and special operands.
4058 if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SPSel {
4059 v = 0<<16 | 4<<12 | 5<<5
4060 } else if p.To.Type == obj.TYPE_SPECIAL {
4061 opd := SpecialOperand(p.To.Offset)
4062 for _, pf := range pstatefield {
4071 c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
4075 case 38: /* clrex [$imm] */
4076 o1 = c.opimm(p, p.As)
4078 if p.To.Type == obj.TYPE_NONE {
4081 o1 |= uint32((p.To.Offset & 0xF) << 8)
4084 case 39: /* cbz R, rel */
4085 o1 = c.opirr(p, p.As)
4087 o1 |= uint32(p.From.Reg & 31)
4088 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
4091 o1 = c.opirr(p, p.As)
4093 v := int32(p.From.Offset)
4094 if v < 0 || v > 63 {
4095 c.ctxt.Diag("illegal bit number\n%v", p)
4097 o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
4098 o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
4099 o1 |= uint32(p.Reg & 31)
4101 case 41: /* eret, nop, others with no operands */
4104 case 42: /* bfm R,r,s,R */
4105 o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
4107 case 43: /* bfm aliases */
4108 r := int(p.From.Offset)
4109 s := int(p.GetFrom3().Offset)
4120 o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
4126 o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
4129 o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
4132 o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
4138 o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
4144 o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
4147 o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
4150 o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
4156 o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
4162 o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
4165 o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
4168 o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
4171 c.ctxt.Diag("bad bfm alias\n%v", p)
4175 case 44: /* extr $b, Rn, Rm, Rd */
4176 o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
4178 case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
4179 rf := int(p.From.Reg)
4184 as = AMOVWU /* clearer in disassembly */
4188 o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
4191 o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
4194 o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
4197 o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
4200 o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
4203 o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
4206 o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
4209 o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
4212 o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
4215 o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
4218 o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
4221 c.ctxt.Diag("bad sxt %v", as)
4226 o1 = c.opbit(p, p.As)
4228 o1 |= uint32(p.From.Reg&31) << 5
4229 o1 |= uint32(p.To.Reg & 31)
4231 case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt
4238 c.ctxt.Diag("illegal destination register: %v\n", p)
4240 if enc, ok := atomicLDADD[p.As]; ok {
4241 // for LDADDx-like instructions, rt can't be r31 when field.enc A is 0, A bit is the 23rd bit.
4242 if (rt == REGZERO) && (enc&(1<<23) == 0) {
4243 c.ctxt.Diag("illegal destination register: %v\n", p)
4246 } else if enc, ok := atomicSWP[p.As]; ok {
4249 c.ctxt.Diag("invalid atomic instructions: %v\n", p)
4251 o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
4253 case 48: /* ADD $C_ADDCON2, Rm, Rd */
4254 // NOTE: this case does not use REGTMP. If it ever does,
4255 // remove the NOTUSETMP flag in optab.
4256 op := c.opirr(p, p.As)
4258 c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
4265 o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
4266 o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
4268 case 50: /* sys/sysl */
4269 o1 = c.opirr(p, p.As)
4271 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
4272 c.ctxt.Diag("illegal SYS argument\n%v", p)
4274 o1 |= uint32(p.From.Offset)
4275 if p.To.Type == obj.TYPE_REG {
4276 o1 |= uint32(p.To.Reg & 31)
4282 o1 = c.opirr(p, p.As)
4284 if p.From.Type == obj.TYPE_CONST {
4285 o1 |= uint32((p.From.Offset & 0xF) << 8)
4289 o1 = c.opirr(p, p.As)
4291 o1 |= uint32((p.From.Offset & 0x7F) << 5)
4293 case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
4296 if p.To.Type == obj.TYPE_NONE {
4304 c.ctxt.Diag("illegal source register: %v", p)
4308 v := uint64(p.From.Offset)
4310 case AANDW, AORRW, AEORW, AANDSW, ATSTW:
4312 case ABIC, AORN, AEON, ABICS:
4314 case ABICW, AORNW, AEONW, ABICSW:
4319 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
4321 case 54: /* floating point arith */
4322 o1 = c.oprrr(p, p.As)
4323 rf := int(p.From.Reg)
4326 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
4332 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4334 case 55: /* floating-point constant */
4336 o1 = 0xf<<25 | 1<<21 | 1<<12
4337 rf = c.chipfloat7(p.From.Val.(float64))
4339 c.ctxt.Diag("invalid floating-point immediate\n%v", p)
4344 o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
4346 case 56: /* floating point compare */
4347 o1 = c.oprrr(p, p.As)
4350 if p.From.Type == obj.TYPE_FCONST {
4354 rf = int(p.From.Reg)
4357 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
4359 case 57: /* floating point conditional compare */
4360 o1 = c.oprrr(p, p.As)
4362 cond := SpecialOperand(p.From.Offset)
4363 if cond < SPOP_EQ || cond > SPOP_NV {
4364 c.ctxt.Diag("invalid condition\n%v", p)
4369 nzcv := int(p.To.Offset)
4371 c.ctxt.Diag("implausible condition\n%v", p)
4374 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
4375 c.ctxt.Diag("illegal FCCMP\n%v", p)
4378 rt := int(p.GetFrom3().Reg)
4379 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
4381 case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
4382 o1 = c.opload(p, p.As)
4385 o1 |= uint32(p.From.Reg&31) << 5
4386 if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
4387 if int(p.To.Reg) == int(p.To.Offset) {
4388 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4390 o1 |= uint32(p.To.Offset&31) << 10
4394 o1 |= uint32(p.To.Reg & 31)
4396 case 59: /* stxr/stlxr/stxp/stlxp */
4400 if isSTLXRop(p.As) {
4401 if s == t || (s == n && n != REGSP) {
4402 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4404 } else if isSTXPop(p.As) {
4405 t2 := int16(p.From.Offset)
4406 if (s == t || s == t2) || (s == n && n != REGSP) {
4407 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4411 c.ctxt.Diag("illegal destination register: %v\n", p)
4413 o1 = c.opstore(p, p.As)
4415 if p.RegTo2 != obj.REG_NONE {
4416 o1 |= uint32(p.RegTo2&31) << 16
4421 o1 |= uint32(p.From.Offset&31) << 10
4423 o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
4425 case 60: /* adrp label,r */
4426 d := c.brdist(p, 12, 21, 0)
4428 o1 = ADR(1, uint32(d), uint32(p.To.Reg))
4430 case 61: /* adr label, r */
4431 d := c.brdist(p, 0, 21, 0)
4433 o1 = ADR(0, uint32(d), uint32(p.To.Reg))
4435 case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
4436 if p.Reg == REGTMP {
4437 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
4439 if p.To.Reg == REG_RSP && isADDSop(p.As) {
4440 c.ctxt.Diag("illegal destination register: %v\n", p)
4443 if isADDWop(p.As) || isANDWop(p.As) {
4444 o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
4447 o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
4451 if p.To.Type == obj.TYPE_NONE {
4458 if p.To.Reg == REGSP || r == REGSP {
4459 o2 = c.opxrrr(p, p.As, false)
4460 o2 |= REGTMP & 31 << 16
4463 o2 = c.oprrr(p, p.As)
4464 o2 |= REGTMP & 31 << 16 /* shift is 0 */
4466 o2 |= uint32(r&31) << 5
4467 o2 |= uint32(rt & 31)
4470 case 64: /* movT R,addr -> adrp + movT R, (REGTMP) */
4471 if p.From.Reg == REGTMP {
4472 c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
4474 o1 = ADR(1, 0, REGTMP)
4475 rel := obj.Addrel(c.cursym)
4476 rel.Off = int32(c.pc)
4479 rel.Add = p.To.Offset
4480 // For unaligned access, fall back to adrp + add + movT R, (REGTMP).
4481 if o.size(c.ctxt, p) != 8 {
4482 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4483 o3 = c.olsr12u(p, int32(c.opstr(p, p.As)), 0, REGTMP, int(p.From.Reg))
4484 rel.Type = objabi.R_ADDRARM64
4487 o2 = c.olsr12u(p, int32(c.opstr(p, p.As)), 0, REGTMP, int(p.From.Reg))
4488 rel.Type = c.addrRelocType(p)
4490 case 65: /* movT addr,R -> adrp + movT (REGTMP), R */
4491 o1 = ADR(1, 0, REGTMP)
4492 rel := obj.Addrel(c.cursym)
4493 rel.Off = int32(c.pc)
4495 rel.Sym = p.From.Sym
4496 rel.Add = p.From.Offset
4497 // For unaligned access, fall back to adrp + add + movT (REGTMP), R.
4498 if o.size(c.ctxt, p) != 8 {
4499 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
4500 o3 = c.olsr12u(p, int32(c.opldr(p, p.As)), 0, REGTMP, int(p.To.Reg))
4501 rel.Type = objabi.R_ADDRARM64
4504 o2 = c.olsr12u(p, int32(c.opldr(p, p.As)), 0, REGTMP, int(p.To.Reg))
4505 rel.Type = c.addrRelocType(p)
4507 case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
4508 v := int32(c.regoff(&p.From))
4509 r := int(p.From.Reg)
4510 if r == obj.REG_NONE {
4513 if r == obj.REG_NONE {
4514 c.ctxt.Diag("invalid ldp source: %v\n", p)
4516 o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4518 case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
4520 if r == obj.REG_NONE {
4523 if r == obj.REG_NONE {
4524 c.ctxt.Diag("invalid stp destination: %v\n", p)
4526 v := int32(c.regoff(&p.To))
4527 o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4529 case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
4530 // NOTE: this case does not use REGTMP. If it ever does,
4531 // remove the NOTUSETMP flag in optab.
4533 c.ctxt.Diag("invalid load of 32-bit address: %v", p)
4535 o1 = ADR(1, 0, uint32(p.To.Reg))
4536 o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
4537 rel := obj.Addrel(c.cursym)
4538 rel.Off = int32(c.pc)
4540 rel.Sym = p.From.Sym
4541 rel.Add = p.From.Offset
4542 rel.Type = objabi.R_ADDRARM64
4544 case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
4545 o1 = c.opirr(p, AMOVZ)
4546 o1 |= uint32(p.To.Reg & 31)
4547 rel := obj.Addrel(c.cursym)
4548 rel.Off = int32(c.pc)
4550 rel.Sym = p.From.Sym
4551 rel.Type = objabi.R_ARM64_TLS_LE
4552 if p.From.Offset != 0 {
4553 c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4556 case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
4557 o1 = ADR(1, 0, REGTMP)
4558 o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
4559 rel := obj.Addrel(c.cursym)
4560 rel.Off = int32(c.pc)
4562 rel.Sym = p.From.Sym
4564 rel.Type = objabi.R_ARM64_TLS_IE
4565 if p.From.Offset != 0 {
4566 c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4569 case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
4570 o1 = ADR(1, 0, REGTMP)
4571 o2 = c.olsr12u(p, int32(c.opldr(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
4572 rel := obj.Addrel(c.cursym)
4573 rel.Off = int32(c.pc)
4575 rel.Sym = p.From.Sym
4577 rel.Type = objabi.R_ARM64_GOTPCREL
4579 case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2/vrax1 Vm.<T>, Vn.<T>, Vd.<T> */
4580 af := int((p.From.Reg >> 5) & 15)
4581 af3 := int((p.Reg >> 5) & 15)
4582 at := int((p.To.Reg >> 5) & 15)
4583 if af != af3 || af != at {
4584 c.ctxt.Diag("operand mismatch: %v", p)
4587 o1 = c.oprrr(p, p.As)
4588 rf := int((p.From.Reg) & 31)
4589 rt := int((p.To.Reg) & 31)
4590 r := int((p.Reg) & 31)
4617 c.ctxt.Diag("invalid arrangement: %v", p)
4621 case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
4622 if af != ARNG_16B && af != ARNG_8B {
4623 c.ctxt.Diag("invalid arrangement: %v", p)
4625 case AVFMLA, AVFMLS:
4626 if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
4627 c.ctxt.Diag("invalid arrangement: %v", p)
4629 case AVUMAX, AVUMIN:
4631 c.ctxt.Diag("invalid arrangement: %v", p)
4639 case AVORR, AVBIT, AVBIF:
4641 case AVFMLA, AVFMLS:
4649 c.ctxt.Diag("invalid arrangement: %v", p)
4655 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4657 case 73: /* vmov V.<T>[index], R */
4658 rf := int(p.From.Reg)
4661 o1 = 7<<25 | 0xf<<10
4662 index := int(p.From.Index)
4663 switch (p.From.Reg >> 5) & 15 {
4665 c.checkindex(p, index, 15)
4669 c.checkindex(p, index, 7)
4673 c.checkindex(p, index, 3)
4677 c.checkindex(p, index, 1)
4682 c.ctxt.Diag("invalid arrangement: %v", p)
4684 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4687 // add $O, R, Rtmp or sub $O, R, Rtmp
4688 // ldp (Rtmp), (R1, R2)
4689 r := int(p.From.Reg)
4690 if r == obj.REG_NONE {
4693 if r == obj.REG_NONE {
4694 c.ctxt.Diag("invalid ldp source: %v", p)
4696 v := int32(c.regoff(&p.From))
4700 c.ctxt.Diag("offset out of range: %v", p)
4702 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4706 c.ctxt.Diag("offset out of range: %v", p)
4708 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4710 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4713 // mov $L, Rtmp (from constant pool)
4714 // add Rtmp, R, Rtmp
4715 // ldp (Rtmp), (R1, R2)
4716 r := int(p.From.Reg)
4718 c.ctxt.Diag("REGTMP used in large offset load: %v", p)
4720 if r == obj.REG_NONE {
4723 if r == obj.REG_NONE {
4724 c.ctxt.Diag("invalid ldp source: %v", p)
4726 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4727 o2 = c.opxrrr(p, AADD, false)
4728 o2 |= (REGTMP & 31) << 16
4729 o2 |= uint32(r&31) << 5
4730 o2 |= uint32(REGTMP & 31)
4731 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4734 // add $O, R, Rtmp or sub $O, R, Rtmp
4735 // stp (R1, R2), (Rtmp)
4736 if p.From.Reg == REGTMP || p.From.Offset == REGTMP {
4737 c.ctxt.Diag("cannot use REGTMP as source: %v", p)
4740 if r == obj.REG_NONE {
4743 if r == obj.REG_NONE {
4744 c.ctxt.Diag("invalid stp destination: %v", p)
4746 v := int32(c.regoff(&p.To))
4749 c.ctxt.Diag("offset out of range: %v", p)
4751 o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4755 c.ctxt.Diag("offset out of range: %v", p)
4757 o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4759 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4762 // mov $L, Rtmp (from constant pool)
4763 // add Rtmp, R, Rtmp
4764 // stp (R1, R2), (Rtmp)
4766 if r == REGTMP || p.From.Reg == REGTMP || p.From.Offset == REGTMP {
4767 c.ctxt.Diag("REGTMP used in large offset store: %v", p)
4769 if r == obj.REG_NONE {
4772 if r == obj.REG_NONE {
4773 c.ctxt.Diag("invalid stp destination: %v", p)
4775 o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
4776 o2 = c.opxrrr(p, AADD, false)
4777 o2 |= REGTMP & 31 << 16
4778 o2 |= uint32(r&31) << 5
4779 o2 |= uint32(REGTMP & 31)
4780 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4782 case 78: /* vmov R, V.<T>[index] */
4783 rf := int(p.From.Reg)
4786 o1 = 1<<30 | 7<<25 | 7<<10
4787 index := int(p.To.Index)
4788 switch (p.To.Reg >> 5) & 15 {
4790 c.checkindex(p, index, 15)
4794 c.checkindex(p, index, 7)
4798 c.checkindex(p, index, 3)
4802 c.checkindex(p, index, 1)
4806 c.ctxt.Diag("invalid arrangement: %v", p)
4808 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4810 case 79: /* vdup Vn.<T>[index], Vd.<T> */
4811 rf := int(p.From.Reg)
4815 index := int(p.From.Index)
4816 switch (p.To.Reg >> 5) & 15 {
4818 c.checkindex(p, index, 15)
4823 c.checkindex(p, index, 1)
4828 c.checkindex(p, index, 3)
4833 c.checkindex(p, index, 7)
4838 c.checkindex(p, index, 3)
4843 c.checkindex(p, index, 15)
4848 c.checkindex(p, index, 7)
4853 c.ctxt.Diag("invalid arrangement: %v", p)
4855 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
4856 o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4858 case 80: /* vmov/vdup V.<T>[index], Vn */
4859 rf := int(p.From.Reg)
4862 index := int(p.From.Index)
4865 o1 = 1<<30 | 15<<25 | 1<<10
4866 switch (p.From.Reg >> 5) & 15 {
4868 c.checkindex(p, index, 15)
4872 c.checkindex(p, index, 7)
4876 c.checkindex(p, index, 3)
4880 c.checkindex(p, index, 1)
4884 c.ctxt.Diag("invalid arrangement: %v", p)
4887 c.ctxt.Diag("unsupported op %v", p.As)
4889 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4891 case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
4892 c.checkoffset(p, p.As)
4893 r := int(p.From.Reg)
4894 o1 = c.oprrr(p, p.As)
4895 if o.scond == C_XPOST {
4897 if p.From.Index == 0 {
4898 // immediate offset variant
4901 // register offset variant
4902 if isRegShiftOrExt(&p.From) {
4903 c.ctxt.Diag("invalid extended register op: %v\n", p)
4905 o1 |= uint32(p.From.Index&0x1f) << 16
4908 o1 |= uint32(p.To.Offset)
4909 // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
4910 // add opcode(bit 12-15) for vld1, mask it off if it's not vld1
4911 o1 = c.maskOpvldvst(p, o1)
4912 o1 |= uint32(r&31) << 5
4914 case 82: /* vmov/vdup Rn, Vd.<T> */
4915 rf := int(p.From.Reg)
4919 switch (p.To.Reg >> 5) & 15 {
4942 c.ctxt.Diag("invalid arrangement: %v\n", p)
4944 o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
4945 o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4947 case 83: /* vmov Vn.<T>, Vd.<T> */
4948 af := int((p.From.Reg >> 5) & 15)
4949 at := int((p.To.Reg >> 5) & 15)
4951 c.ctxt.Diag("invalid arrangement: %v\n", p)
4953 o1 = c.oprrr(p, p.As)
4954 rf := int((p.From.Reg) & 31)
4955 rt := int((p.To.Reg) & 31)
4978 c.ctxt.Diag("invalid arrangement: %v\n", p)
4981 if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
4982 c.ctxt.Diag("invalid arrangement: %v", p)
4985 if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
4986 c.ctxt.Diag("invalid arrangement: %v", p)
4989 if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
4990 c.ctxt.Diag("invalid arrangement: %v", p)
4994 o1 |= uint32(rf&31) << 16
5001 o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
5003 case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
5004 c.checkoffset(p, p.As)
5007 if o.scond == C_XPOST {
5009 if p.To.Index == 0 {
5010 // immediate offset variant
5013 // register offset variant
5014 if isRegShiftOrExt(&p.To) {
5015 c.ctxt.Diag("invalid extended register: %v\n", p)
5017 o1 |= uint32(p.To.Index&31) << 16
5020 o1 |= uint32(p.From.Offset)
5021 // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
5022 // add opcode(bit 12-15) for vst1, mask it off if it's not vst1
5023 o1 = c.maskOpvldvst(p, o1)
5024 o1 |= uint32(r&31) << 5
5026 case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
5027 af := int((p.From.Reg >> 5) & 15)
5028 o1 = c.oprrr(p, p.As)
5029 rf := int((p.From.Reg) & 31)
5030 rt := int((p.To.Reg) & 31)
5050 c.ctxt.Diag("invalid arrangement: %v\n", p)
5052 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
5054 case 86: /* vmovi $imm8, Vd.<T>*/
5055 at := int((p.To.Reg >> 5) & 15)
5056 r := int(p.From.Offset)
5057 if r > 255 || r < 0 {
5058 c.ctxt.Diag("immediate constant out of range: %v\n", p)
5060 rt := int((p.To.Reg) & 31)
5068 c.ctxt.Diag("invalid arrangement: %v\n", p)
5070 o1 = 0xf<<24 | 0xe<<12 | 1<<10
5071 o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
5073 case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
5074 if p.From.Reg == REGTMP || p.From.Offset == REGTMP {
5075 c.ctxt.Diag("cannot use REGTMP as source: %v", p)
5077 o1 = ADR(1, 0, REGTMP)
5078 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
5079 rel := obj.Addrel(c.cursym)
5080 rel.Off = int32(c.pc)
5083 rel.Add = p.To.Offset
5084 rel.Type = objabi.R_ADDRARM64
5085 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
5087 case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
5088 o1 = ADR(1, 0, REGTMP)
5089 o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
5090 rel := obj.Addrel(c.cursym)
5091 rel.Off = int32(c.pc)
5093 rel.Sym = p.From.Sym
5094 rel.Add = p.From.Offset
5095 rel.Type = objabi.R_ADDRARM64
5096 o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
5098 case 89: /* vadd/vsub Vm, Vn, Vd */
5101 o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5104 o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5107 c.ctxt.Diag("bad opcode: %v\n", p)
5111 rf := int(p.From.Reg)
5117 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5119 // This is supposed to be something that stops execution.
5120 // It's not supposed to be reached, ever, but if it is, we'd
5121 // like to be able to tell how we got there. Assemble as
5122 // 0xbea71700 which is guaranteed to raise undefined instruction
5127 case 91: /* prfm imm(Rn), <prfop | $imm5> */
5128 imm := uint32(p.From.Offset)
5132 if p.To.Type == obj.TYPE_CONST {
5133 v = uint32(p.To.Offset)
5136 v, ok = prfopfield[SpecialOperand(p.To.Offset)]
5139 c.ctxt.Diag("illegal prefetch operation:\n%v", p)
5142 o1 = c.opirr(p, p.As)
5143 o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
5145 case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
5146 rf := int(p.From.Reg)
5150 o1 = 3<<29 | 7<<25 | 1<<10
5151 index1 := int(p.To.Index)
5152 index2 := int(p.From.Index)
5153 if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
5154 c.ctxt.Diag("operand mismatch: %v", p)
5156 switch (p.To.Reg >> 5) & 15 {
5158 c.checkindex(p, index1, 15)
5159 c.checkindex(p, index2, 15)
5164 c.checkindex(p, index1, 7)
5165 c.checkindex(p, index2, 7)
5170 c.checkindex(p, index1, 3)
5171 c.checkindex(p, index2, 3)
5176 c.checkindex(p, index1, 1)
5177 c.checkindex(p, index2, 1)
5182 c.ctxt.Diag("invalid arrangement: %v", p)
5184 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5186 case 93: /* vpmull{2} Vm.<Tb>, Vn.<Tb>, Vd.<Ta> */
5187 af := uint8((p.From.Reg >> 5) & 15)
5188 at := uint8((p.To.Reg >> 5) & 15)
5189 a := uint8((p.Reg >> 5) & 15)
5191 c.ctxt.Diag("invalid arrangement: %v", p)
5195 if p.As == AVPMULL2 {
5198 switch pack(Q, at, af) {
5199 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5201 case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D):
5204 c.ctxt.Diag("operand mismatch: %v\n", p)
5207 o1 = c.oprrr(p, p.As)
5208 rf := int((p.From.Reg) & 31)
5209 rt := int((p.To.Reg) & 31)
5210 r := int((p.Reg) & 31)
5211 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5213 case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
5214 af := int(((p.GetFrom3().Reg) >> 5) & 15)
5215 at := int((p.To.Reg >> 5) & 15)
5216 a := int((p.Reg >> 5) & 15)
5217 index := int(p.From.Offset)
5219 if af != a || af != at {
5220 c.ctxt.Diag("invalid arrangement: %v", p)
5229 } else if af == ARNG_16B {
5233 c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
5237 if index < 0 || index > b {
5238 c.ctxt.Diag("illegal offset: %v", p)
5241 o1 = c.opirr(p, p.As)
5242 rf := int((p.GetFrom3().Reg) & 31)
5243 rt := int((p.To.Reg) & 31)
5244 r := int((p.Reg) & 31)
5246 o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5248 case 95: /* vushr/vshl/vsri/vsli/vusra $shift, Vn.<T>, Vd.<T> */
5249 at := int((p.To.Reg >> 5) & 15)
5250 af := int((p.Reg >> 5) & 15)
5251 shift := int(p.From.Offset)
5254 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5261 case ARNG_8B, ARNG_4H, ARNG_2S:
5263 case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
5266 c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5270 case ARNG_8B, ARNG_16B:
5273 case ARNG_4H, ARNG_8H:
5276 case ARNG_2S, ARNG_4S:
5286 case AVUSHR, AVSRI, AVUSRA:
5287 imm = esize*2 - shift
5288 if imm < esize || imm > imax {
5289 c.ctxt.Diag("shift out of range: %v", p)
5294 c.ctxt.Diag("shift out of range: %v", p)
5297 c.ctxt.Diag("invalid instruction %v\n", p)
5300 o1 = c.opirr(p, p.As)
5301 rt := int((p.To.Reg) & 31)
5302 rf := int((p.Reg) & 31)
5304 o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
5306 case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
5307 af := int((p.From.Reg >> 5) & 15)
5308 rt := int((p.From.Reg) & 31)
5309 rf := int((p.To.Reg) & 31)
5310 r := int(p.To.Index & 31)
5311 index := int(p.From.Index)
5312 offset := int32(c.regoff(&p.To))
5314 if o.scond == C_XPOST {
5315 if (p.To.Index != 0) && (offset != 0) {
5316 c.ctxt.Diag("invalid offset: %v", p)
5318 if p.To.Index == 0 && offset == 0 {
5319 c.ctxt.Diag("invalid offset: %v", p)
5331 c.checkindex(p, index, 15)
5332 if o.scond == C_XPOST && offset != 0 && offset != 1 {
5333 c.ctxt.Diag("invalid offset: %v", p)
5336 S = (index >> 2) & 1
5340 c.checkindex(p, index, 7)
5341 if o.scond == C_XPOST && offset != 0 && offset != 2 {
5342 c.ctxt.Diag("invalid offset: %v", p)
5345 S = (index >> 1) & 1
5346 size = (index & 1) << 1
5349 c.checkindex(p, index, 3)
5350 if o.scond == C_XPOST && offset != 0 && offset != 4 {
5351 c.ctxt.Diag("invalid offset: %v", p)
5358 c.checkindex(p, index, 1)
5359 if o.scond == C_XPOST && offset != 0 && offset != 8 {
5360 c.ctxt.Diag("invalid offset: %v", p)
5367 c.ctxt.Diag("invalid arrangement: %v", p)
5370 if o.scond == C_XPOST {
5376 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)
5378 case 97: /* vld1 offset(Rn), vt.<T>[index] */
5379 at := int((p.To.Reg >> 5) & 15)
5380 rt := int((p.To.Reg) & 31)
5381 rf := int((p.From.Reg) & 31)
5382 r := int(p.From.Index & 31)
5383 index := int(p.To.Index)
5384 offset := int32(c.regoff(&p.From))
5386 if o.scond == C_XPOST {
5387 if (p.From.Index != 0) && (offset != 0) {
5388 c.ctxt.Diag("invalid offset: %v", p)
5390 if p.From.Index == 0 && offset == 0 {
5391 c.ctxt.Diag("invalid offset: %v", p)
5405 c.checkindex(p, index, 15)
5406 if o.scond == C_XPOST && offset != 0 && offset != 1 {
5407 c.ctxt.Diag("invalid offset: %v", p)
5410 S = (index >> 2) & 1
5414 c.checkindex(p, index, 7)
5415 if o.scond == C_XPOST && offset != 0 && offset != 2 {
5416 c.ctxt.Diag("invalid offset: %v", p)
5419 S = (index >> 1) & 1
5420 size = (index & 1) << 1
5423 c.checkindex(p, index, 3)
5424 if o.scond == C_XPOST && offset != 0 && offset != 4 {
5425 c.ctxt.Diag("invalid offset: %v", p)
5432 c.checkindex(p, index, 1)
5433 if o.scond == C_XPOST && offset != 0 && offset != 8 {
5434 c.ctxt.Diag("invalid offset: %v", p)
5441 c.ctxt.Diag("invalid arrangement: %v", p)
5444 if o.scond == C_XPOST {
5450 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)
5452 case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
5453 if isRegShiftOrExt(&p.From) {
5454 // extended or shifted offset register.
5455 c.checkShiftAmount(p, &p.From)
5457 o1 = c.opldrr(p, p.As, true)
5458 o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
5460 // (Rn)(Rm), no extension or shift.
5461 o1 = c.opldrr(p, p.As, false)
5462 o1 |= uint32(p.From.Index&31) << 16
5464 o1 |= uint32(p.From.Reg&31) << 5
5466 o1 |= uint32(rt & 31)
5468 case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
5469 if isRegShiftOrExt(&p.To) {
5470 // extended or shifted offset register.
5471 c.checkShiftAmount(p, &p.To)
5473 o1 = c.opstrr(p, p.As, true)
5474 o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
5476 // (Rn)(Rm), no extension or shift.
5477 o1 = c.opstrr(p, p.As, false)
5478 o1 |= uint32(p.To.Index&31) << 16
5480 o1 |= uint32(p.To.Reg&31) << 5
5481 rf := int(p.From.Reg)
5482 o1 |= uint32(rf & 31)
5484 case 100: /* VTBL/VTBX Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
5485 af := int((p.From.Reg >> 5) & 15)
5486 at := int((p.To.Reg >> 5) & 15)
5488 c.ctxt.Diag("invalid arrangement: %v\n", p)
5497 c.ctxt.Diag("invalid arrangement: %v", p)
5499 rf := int(p.From.Reg)
5501 offset := int(p.GetFrom3().Offset)
5502 opcode := (offset >> 12) & 15
5505 len = 0 // one register
5507 len = 1 // two register
5509 len = 2 // three registers
5511 len = 3 // four registers
5513 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
5522 o1 = q<<30 | 0xe<<24 | len<<13 | op<<12
5523 o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
5525 case 101: // VMOVQ $vcon1, $vcon2, Vd or VMOVD|VMOVS $vcon, Vd -> FMOVQ/FMOVD/FMOVS pool(PC), Vd: load from constant pool.
5526 o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
5528 case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
5529 o1 = c.opirr(p, p.As)
5531 af := uint8((p.Reg >> 5) & 15)
5532 at := uint8((p.To.Reg >> 5) & 15)
5533 shift := int(p.From.Offset)
5534 if p.As == AVUXTL || p.As == AVUXTL2 {
5536 af = uint8((p.From.Reg >> 5) & 15)
5541 var immh, width uint8
5542 switch pack(Q, af, at) {
5543 case pack(0, ARNG_8B, ARNG_8H):
5545 case pack(1, ARNG_16B, ARNG_8H):
5547 case pack(0, ARNG_4H, ARNG_4S):
5549 case pack(1, ARNG_8H, ARNG_4S):
5551 case pack(0, ARNG_2S, ARNG_2D):
5553 case pack(1, ARNG_4S, ARNG_2D):
5556 c.ctxt.Diag("operand mismatch: %v\n", p)
5558 if !(0 <= shift && shift <= int(width-1)) {
5559 c.ctxt.Diag("shift amount out of range: %v\n", p)
5561 o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
5563 case 103: /* VEOR3/VBCAX Va.B16, Vm.B16, Vn.B16, Vd.B16 */
5564 ta := (p.From.Reg >> 5) & 15
5565 tm := (p.Reg >> 5) & 15
5566 td := (p.To.Reg >> 5) & 15
5567 tn := ((p.GetFrom3().Reg) >> 5) & 15
5569 if ta != tm || ta != tn || ta != td || ta != ARNG_16B {
5570 c.ctxt.Diag("invalid arrangement: %v", p)
5574 o1 = c.oprrr(p, p.As)
5575 ra := int(p.From.Reg)
5577 rn := int(p.GetFrom3().Reg)
5579 o1 |= uint32(rm&31)<<16 | uint32(ra&31)<<10 | uint32(rn&31)<<5 | uint32(rd)&31
5581 case 104: /* vxar $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
5582 af := ((p.GetFrom3().Reg) >> 5) & 15
5583 at := (p.To.Reg >> 5) & 15
5584 a := (p.Reg >> 5) & 15
5585 index := int(p.From.Offset)
5587 if af != a || af != at {
5588 c.ctxt.Diag("invalid arrangement: %v", p)
5593 c.ctxt.Diag("invalid arrangement, should be D2: %v", p)
5597 if index < 0 || index > 63 {
5598 c.ctxt.Diag("illegal offset: %v", p)
5601 o1 = c.opirr(p, p.As)
5602 rf := (p.GetFrom3().Reg) & 31
5603 rt := (p.To.Reg) & 31
5606 o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
5608 case 105: /* vuaddw{2} Vm.<Tb>, Vn.<Ta>, Vd.<Ta> */
5609 af := uint8((p.From.Reg >> 5) & 15)
5610 at := uint8((p.To.Reg >> 5) & 15)
5611 a := uint8((p.Reg >> 5) & 15)
5613 c.ctxt.Diag("invalid arrangement: %v", p)
5618 if p.As == AVUADDW2 {
5621 switch pack(Q, at, af) {
5622 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5624 case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H):
5626 case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S):
5629 c.ctxt.Diag("operand mismatch: %v\n", p)
5632 o1 = c.oprrr(p, p.As)
5633 rf := int((p.From.Reg) & 31)
5634 rt := int((p.To.Reg) & 31)
5635 r := int((p.Reg) & 31)
5636 o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5638 case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1)
5640 rt := p.GetTo2().Reg
5642 rs1 := int16(p.From.Offset)
5643 rt1 := int16(p.GetTo2().Offset)
5645 enc, ok := atomicCASP[p.As]
5647 c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p)
5649 // for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1
5652 c.ctxt.Diag("source register pair must start from even register: %v\n", p)
5655 c.ctxt.Diag("destination register pair must start from even register: %v\n", p)
5658 c.ctxt.Diag("source register pair must be contiguous: %v\n", p)
5661 c.ctxt.Diag("destination register pair must be contiguous: %v\n", p)
5666 c.ctxt.Diag("illegal destination register: %v\n", p)
5668 o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
5670 case 107: /* tlbi, dc */
5671 op, ok := sysInstFields[SpecialOperand(p.From.Offset)]
5672 if !ok || (p.As == ATLBI && op.cn != 8) || (p.As == ADC && op.cn != 7) {
5673 c.ctxt.Diag("illegal argument: %v\n", p)
5676 o1 = c.opirr(p, p.As)
5679 c.ctxt.Diag("missing register at operand 2: %v\n", p)
5681 o1 |= uint32(p.To.Reg & 0x1F)
5683 if p.To.Reg != 0 || p.Reg != 0 {
5684 c.ctxt.Diag("extraneous register at operand 2: %v\n", p)
5688 o1 |= uint32(SYSARG4(int(op.op1), int(op.cn), int(op.cm), int(op.op2)))
5697 func (c *ctxt7) addrRelocType(p *obj.Prog) objabi.RelocType {
5698 switch movesize(p.As) {
5700 return objabi.R_ARM64_PCREL_LDST8
5702 return objabi.R_ARM64_PCREL_LDST16
5704 return objabi.R_ARM64_PCREL_LDST32
5706 return objabi.R_ARM64_PCREL_LDST64
5708 c.ctxt.Diag("use R_ADDRARM64 relocation type for: %v\n", p)
5714 * basic Rm op Rn -> Rd (using shifted register with 0)
5716 * also Rm*Rn op Ra -> Rd
5717 * also Vm op Vn -> Vd
5719 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
5722 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5725 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5728 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5731 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5734 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5737 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5740 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5742 case ANGCSW, ASBCSW:
5743 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5746 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5749 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5752 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5755 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5758 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5761 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5764 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5767 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5770 return S64 | 0<<29 | 0xA<<24
5773 return S32 | 0<<29 | 0xA<<24
5776 return S64 | 1<<29 | 0xA<<24
5780 return S32 | 1<<29 | 0xA<<24
5783 return S64 | 2<<29 | 0xA<<24
5786 return S32 | 2<<29 | 0xA<<24
5789 return S64 | 3<<29 | 0xA<<24
5792 return S32 | 3<<29 | 0xA<<24
5795 return S64 | 0<<29 | 0xA<<24 | 1<<21
5798 return S32 | 0<<29 | 0xA<<24 | 1<<21
5801 return S64 | 3<<29 | 0xA<<24 | 1<<21
5804 return S32 | 3<<29 | 0xA<<24 | 1<<21
5807 return S64 | 2<<29 | 0xA<<24 | 1<<21
5810 return S32 | 2<<29 | 0xA<<24 | 1<<21
5813 return S64 | 1<<29 | 0xA<<24 | 1<<21
5816 return S32 | 1<<29 | 0xA<<24 | 1<<21
5819 return S64 | OPDP2(10) /* also ASRV */
5822 return S32 | OPDP2(10)
5825 return S64 | OPDP2(8)
5828 return S32 | OPDP2(8)
5831 return S64 | OPDP2(9)
5834 return S32 | OPDP2(9)
5837 return S64 | OPDP2(11)
5840 return S32 | OPDP2(11)
5843 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
5846 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5849 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
5852 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5855 return S32 | OPDP2(16)
5858 return S32 | OPDP2(17)
5861 return S32 | OPDP2(18)
5864 return S64 | OPDP2(19)
5867 return S32 | OPDP2(20)
5870 return S32 | OPDP2(21)
5873 return S32 | OPDP2(22)
5876 return S64 | OPDP2(23)
5879 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5882 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5885 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5888 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5891 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5894 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5897 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5899 case ACINCW, ACSINCW:
5900 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5903 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5905 case ACINVW, ACSINVW:
5906 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5909 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5911 case ACNEGW, ACSNEGW:
5912 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5915 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5918 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5921 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5923 case AMNEGW, AMSUBW:
5924 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5927 return SYSOP(1, 2, 0, 0, 0, 0, 0)
5930 return SYSOP(0, 2, 0, 0, 0, 0, 0)
5933 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5936 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5939 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5942 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5945 return S64 | OPDP2(3)
5948 return S32 | OPDP2(3)
5950 case ASMULL, ASMADDL:
5951 return OPDP3(1, 0, 1, 0)
5953 case ASMNEGL, ASMSUBL:
5954 return OPDP3(1, 0, 1, 1)
5957 return OPDP3(1, 0, 2, 0)
5959 case AUMULL, AUMADDL:
5960 return OPDP3(1, 0, 5, 0)
5962 case AUMNEGL, AUMSUBL:
5963 return OPDP3(1, 0, 5, 1)
5966 return OPDP3(1, 0, 6, 0)
5969 return S64 | OPDP2(2)
5971 case AUREMW, AUDIVW:
5972 return S32 | OPDP2(2)
5975 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
5978 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
5981 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
5984 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
5987 return 0x5E<<24 | 0<<12
5990 return 0x5E<<24 | 1<<12
5993 return 0x5E<<24 | 2<<12
5996 return 0x5E<<24 | 3<<12
5999 return 0x5E<<24 | 4<<12
6002 return 0x5E<<24 | 5<<12
6005 return 0x5E<<24 | 6<<12
6008 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
6011 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
6014 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
6017 return 0xCE<<24 | 3<<21 | 8<<12
6020 return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
6023 return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
6026 return 0xCE<<24 | 3<<22 | 8<<12
6029 return FPCVTI(1, 0, 1, 3, 0)
6032 return FPCVTI(0, 0, 1, 3, 0)
6035 return FPCVTI(1, 0, 0, 3, 0)
6038 return FPCVTI(0, 0, 0, 3, 0)
6041 return FPCVTI(1, 0, 1, 3, 1)
6044 return FPCVTI(0, 0, 1, 3, 1)
6047 return FPCVTI(1, 0, 0, 3, 1)
6050 return FPCVTI(0, 0, 0, 3, 1)
6053 return FPCVTI(1, 0, 1, 0, 2)
6056 return FPCVTI(1, 0, 0, 0, 2)
6059 return FPCVTI(0, 0, 1, 0, 2)
6062 return FPCVTI(0, 0, 0, 0, 2)
6065 return FPCVTI(1, 0, 1, 0, 3)
6068 return FPCVTI(1, 0, 0, 0, 3)
6071 return FPCVTI(0, 0, 1, 0, 3)
6074 return FPCVTI(0, 0, 0, 0, 3)
6077 return FPOP2S(0, 0, 0, 2)
6080 return FPOP2S(0, 0, 1, 2)
6083 return FPOP2S(0, 0, 0, 3)
6086 return FPOP2S(0, 0, 1, 3)
6089 return FPOP3S(0, 0, 1, 0, 0)
6092 return FPOP3S(0, 0, 0, 0, 0)
6095 return FPOP3S(0, 0, 1, 0, 1)
6098 return FPOP3S(0, 0, 0, 0, 1)
6101 return FPOP3S(0, 0, 1, 1, 0)
6104 return FPOP3S(0, 0, 0, 1, 0)
6107 return FPOP3S(0, 0, 1, 1, 1)
6110 return FPOP3S(0, 0, 0, 1, 1)
6113 return FPOP2S(0, 0, 0, 0)
6116 return FPOP2S(0, 0, 1, 0)
6119 return FPOP2S(0, 0, 0, 1)
6122 return FPOP2S(0, 0, 1, 1)
6125 return FPOP2S(0, 0, 0, 4)
6128 return FPOP2S(0, 0, 0, 5)
6131 return FPOP2S(0, 0, 1, 4)
6134 return FPOP2S(0, 0, 1, 5)
6137 return FPOP2S(0, 0, 0, 6)
6140 return FPOP2S(0, 0, 1, 6)
6143 return FPOP2S(0, 0, 0, 7)
6146 return FPOP2S(0, 0, 1, 7)
6149 return FPOP2S(0, 0, 0, 8)
6152 return FPOP2S(0, 0, 1, 8)
6155 return FPCMP(0, 0, 0, 0, 0)
6158 return FPCMP(0, 0, 1, 0, 0)
6161 return FPCMP(0, 0, 0, 0, 16)
6164 return FPCMP(0, 0, 1, 0, 16)
6167 return FPCCMP(0, 0, 0, 0)
6170 return FPCCMP(0, 0, 1, 0)
6173 return FPCCMP(0, 0, 0, 1)
6176 return FPCCMP(0, 0, 1, 1)
6179 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
6182 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
6185 return FPOP1S(0, 0, 0, 0)
6188 return FPOP1S(0, 0, 0, 1)
6191 return FPOP1S(0, 0, 0, 2)
6194 return FPOP1S(0, 0, 0, 3)
6197 return FPOP1S(0, 0, 0, 5)
6200 return FPOP1S(0, 0, 0, 7)
6203 return FPOP1S(0, 0, 0, 8)
6206 return FPOP1S(0, 0, 0, 9)
6209 return FPOP1S(0, 0, 0, 10)
6212 return FPOP1S(0, 0, 0, 11)
6215 return FPOP1S(0, 0, 0, 12)
6218 return FPOP1S(0, 0, 0, 14)
6221 return FPOP1S(0, 0, 0, 15)
6224 return FPOP1S(0, 0, 1, 0)
6227 return FPOP1S(0, 0, 1, 1)
6230 return FPOP1S(0, 0, 1, 2)
6233 return FPOP1S(0, 0, 1, 3)
6236 return FPOP1S(0, 0, 1, 4)
6239 return FPOP1S(0, 0, 1, 7)
6242 return FPOP1S(0, 0, 1, 8)
6245 return FPOP1S(0, 0, 1, 9)
6248 return FPOP1S(0, 0, 1, 10)
6251 return FPOP1S(0, 0, 1, 11)
6254 return FPOP1S(0, 0, 1, 12)
6257 return FPOP1S(0, 0, 1, 14)
6260 return FPOP1S(0, 0, 1, 15)
6263 return FPOP1S(0, 0, 3, 4)
6266 return FPOP1S(0, 0, 3, 5)
6269 return 7<<25 | 1<<21 | 1<<15 | 1<<10
6272 return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
6275 return 7<<25 | 1<<21 | 1<<15 | 15<<10
6278 return 7<<25 | 1<<21 | 7<<10
6281 return 0xCE<<24 | 1<<21
6284 return 1<<29 | 0x71<<21 | 0x23<<10
6287 return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
6290 return 0xE<<24 | 3<<12 | 2<<10
6293 return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
6296 return 1<<29 | 0x71<<21 | 7<<10
6302 return 7<<25 | 5<<21 | 7<<10
6305 return 3<<26 | 2<<24 | 1<<21 | 3<<11
6308 return 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
6311 return 11<<26 | 2<<24 | 1<<21 | 1<<11
6314 return 3<<26 | 2<<24 | 1<<21 | 1<<11
6317 return 7<<25 | 5<<21 | 7<<10
6320 return 7<<25 | 3<<20 | 3<<15 | 7<<11
6323 return 1<<29 | 7<<25 | 3<<20 | 7<<11
6326 return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
6329 return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
6331 case AVPMULL, AVPMULL2:
6332 return 0xE<<24 | 1<<21 | 0x38<<10
6335 return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
6337 case AVLD1, AVLD2, AVLD3, AVLD4:
6338 return 3<<26 | 1<<22
6340 case AVLD1R, AVLD3R:
6341 return 0xD<<24 | 1<<22
6343 case AVLD2R, AVLD4R:
6344 return 0xD<<24 | 3<<21
6347 return 1<<29 | 7<<25 | 7<<21 | 7<<10
6350 return 1<<29 | 0x75<<21 | 7<<10
6353 return 1<<29 | 0x73<<21 | 7<<10
6356 return 0xE<<24 | 1<<21 | 0x23<<10
6359 return 1<<29 | 7<<25 | 1<<21 | 0x19<<10
6362 return 1<<29 | 7<<25 | 1<<21 | 0x1b<<10
6365 return 7<<25 | 3<<11
6368 return 7<<25 | 1<<14 | 3<<11
6370 case AVUADDW, AVUADDW2:
6371 return 0x17<<25 | 1<<21 | 1<<12
6374 return 7<<25 | 5<<11
6377 return 7<<25 | 1<<14 | 5<<11
6380 c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
6388 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
6390 /* op $addcon, Rn, Rd */
6392 return S64 | 0<<30 | 0<<29 | 0x11<<24
6395 return S64 | 0<<30 | 1<<29 | 0x11<<24
6398 return S32 | 0<<30 | 0<<29 | 0x11<<24
6401 return S32 | 0<<30 | 1<<29 | 0x11<<24
6404 return S64 | 1<<30 | 0<<29 | 0x11<<24
6407 return S64 | 1<<30 | 1<<29 | 0x11<<24
6410 return S32 | 1<<30 | 0<<29 | 0x11<<24
6413 return S32 | 1<<30 | 1<<29 | 0x11<<24
6415 /* op $imm(SB), Rd; op label, Rd */
6417 return 0<<31 | 0x10<<24
6420 return 1<<31 | 0x10<<24
6422 /* op $bimm, Rn, Rd */
6424 return S64 | 0<<29 | 0x24<<23
6427 return S32 | 0<<29 | 0x24<<23 | 0<<22
6430 return S64 | 1<<29 | 0x24<<23
6433 return S32 | 1<<29 | 0x24<<23 | 0<<22
6436 return S64 | 2<<29 | 0x24<<23
6439 return S32 | 2<<29 | 0x24<<23 | 0<<22
6441 case AANDS, ABICS, ATST:
6442 return S64 | 3<<29 | 0x24<<23
6444 case AANDSW, ABICSW, ATSTW:
6445 return S32 | 3<<29 | 0x24<<23 | 0<<22
6448 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
6451 return S32 | 0<<29 | 0x26<<23 | 0<<22
6453 /* op $width, $lsb, Rn, Rd */
6455 return S64 | 2<<29 | 0x26<<23 | 1<<22
6459 return S32 | 2<<29 | 0x26<<23 | 0<<22
6461 /* op $imms, $immr, Rn, Rd */
6463 return S64 | 1<<29 | 0x26<<23 | 1<<22
6466 return S32 | 1<<29 | 0x26<<23 | 0<<22
6469 return S64 | 0<<29 | 0x26<<23 | 1<<22
6472 return S32 | 0<<29 | 0x26<<23 | 0<<22
6475 return S64 | 2<<29 | 0x26<<23 | 1<<22
6478 return S32 | 2<<29 | 0x26<<23 | 0<<22
6481 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
6484 return S32 | 1<<29 | 0x26<<23 | 0<<22
6487 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
6490 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
6493 return S64 | 0x1A<<25 | 1<<24
6496 return S32 | 0x1A<<25 | 1<<24
6499 return S64 | 0x1A<<25 | 0<<24
6502 return S32 | 0x1A<<25 | 0<<24
6505 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6508 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6511 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6514 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6517 return S64 | 3<<29 | 0x25<<23
6520 return S32 | 3<<29 | 0x25<<23
6523 return S64 | 0<<29 | 0x25<<23
6526 return S32 | 0<<29 | 0x25<<23
6529 return S64 | 2<<29 | 0x25<<23
6532 return S32 | 2<<29 | 0x25<<23
6535 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
6542 return SYSOP(0, 1, 0, 0, 0, 0, 0)
6545 return SYSOP(1, 1, 0, 0, 0, 0, 0)
6554 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
6557 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
6560 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
6563 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
6566 return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
6569 return 0x5E<<23 | 1<<10
6572 return 0x1E<<23 | 21<<10
6575 return 0x5E<<23 | 17<<10
6578 return 0x5E<<23 | 21<<10
6580 case AVUSHLL, AVUXTL:
6581 return 1<<29 | 15<<24 | 0x29<<10
6583 case AVUSHLL2, AVUXTL2:
6584 return 3<<29 | 15<<24 | 0x29<<10
6587 return 0xCE<<24 | 1<<23
6590 return 1<<29 | 15<<24 | 5<<10
6593 return 0xf9<<24 | 2<<22
6596 c.ctxt.Diag("%v: bad irr %v", p, a)
6600 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
6603 return S64 | OPBIT(5)
6606 return S32 | OPBIT(5)
6609 return S64 | OPBIT(4)
6612 return S32 | OPBIT(4)
6615 return S64 | OPBIT(0)
6618 return S32 | OPBIT(0)
6621 return S64 | OPBIT(3)
6624 return S32 | OPBIT(2)
6627 return S64 | OPBIT(1)
6630 return S32 | OPBIT(1)
6633 return S64 | OPBIT(2)
6636 c.ctxt.Diag("bad bit op\n%v", p)
6642 * add/subtract sign or zero-extended register
6644 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
6645 extension := uint32(0)
6657 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6660 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6663 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6666 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6669 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6672 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6675 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6678 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6681 c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
6685 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
6688 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
6691 return 0xD4<<24 | 0<<21 | 2
6694 return 0xD4<<24 | 0<<21 | 3
6697 return 0xD4<<24 | 1<<21 | 0
6700 return 0xD4<<24 | 2<<21 | 0
6703 return 0xD4<<24 | 5<<21 | 1
6706 return 0xD4<<24 | 5<<21 | 2
6709 return 0xD4<<24 | 5<<21 | 3
6712 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
6715 c.ctxt.Diag("%v: bad imm %v", p, a)
6719 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
6723 if p.To.Type == obj.TYPE_BRANCH {
6725 } else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp
6729 // TODO: don't use brdist for this case, as it isn't a branch.
6730 // (Calls from omovlit, and maybe adr/adrp opcodes as well.)
6734 v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
6735 if (v & ((1 << uint(shift)) - 1)) != 0 {
6736 c.ctxt.Diag("misaligned label\n%v", p)
6739 t = int64(1) << uint(flen-1)
6740 if v < -t || v >= t {
6741 c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
6742 panic("branch too far")
6746 return v & ((t << 1) - 1)
6750 * pc-relative branches
6752 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
6800 return OPBcc(0xd) /* imm19<<5 | cond */
6803 return 0<<31 | 5<<26 /* imm26 */
6805 case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
6806 return 1<<31 | 5<<26
6809 c.ctxt.Diag("%v: bad bra %v", p, a)
6813 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
6816 return OPBLR(1) /* BLR */
6819 return OPBLR(0) /* BR */
6822 return OPBLR(2) /* RET */
6825 c.ctxt.Diag("%v: bad brr %v", p, a)
6829 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
6832 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
6835 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
6856 c.ctxt.Diag("%v: bad op0 %v", p, a)
6863 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
6866 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
6869 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
6872 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
6875 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
6878 return LDSTX(3, 0, 1, 1, 1)
6881 return LDSTX(2, 0, 1, 1, 1)
6884 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
6887 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
6890 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
6893 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
6896 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
6899 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
6902 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
6905 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
6908 return LDSTX(3, 0, 1, 1, 0)
6911 return LDSTX(2, 0, 1, 1, 0)
6914 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6917 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6920 c.ctxt.Diag("bad opload %v\n%v", a, p)
6924 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
6927 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
6930 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
6933 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
6936 return LDSTX(3, 0, 0, 1, 1)
6939 return LDSTX(2, 0, 0, 1, 1)
6942 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
6945 return LDSTX(3, 0, 0, 1, 1)
6948 return LDSTX(2, 0, 0, 1, 1)
6951 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
6954 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
6957 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
6960 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
6963 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
6966 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
6969 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
6972 return LDSTX(3, 0, 0, 1, 0)
6975 return LDSTX(2, 0, 0, 1, 0)
6978 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
6981 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6984 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6987 c.ctxt.Diag("bad opstore %v\n%v", a, p)
6992 * load/store register (scaled 12-bit unsigned immediate) C3.3.13
6993 * these produce 64-bit values (when there's an option)
6995 func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
6996 if v < 0 || v >= (1<<12) {
6997 c.ctxt.Diag("offset out of range: %d\n%v", v, p)
6999 o |= (v & 0xFFF) << 10
7000 o |= int32(b&31) << 5
7007 * load/store register (unscaled 9-bit signed immediate) C3.3.12
7009 func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
7010 if v < -256 || v > 255 {
7011 c.ctxt.Diag("offset out of range: %d\n%v", v, p)
7013 o |= (v & 0x1FF) << 12
7014 o |= int32(b&31) << 5
7020 // scaled 12-bit unsigned immediate offset.
7021 // unscaled 9-bit signed immediate offset.
7022 // pre/post-indexed store.
7023 // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
7024 func (c *ctxt7) opstr(p *obj.Prog, a obj.As) uint32 {
7025 enc := c.opldr(p, a)
7028 enc = enc &^ (1 << 22)
7036 // scaled 12-bit unsigned immediate offset.
7037 // unscaled 9-bit signed immediate offset.
7038 // pre/post-indexed load.
7039 // and the 12-bit and 9-bit are distinguished in olsr12u and oslr9s.
7040 func (c *ctxt7) opldr(p *obj.Prog, a obj.As) uint32 {
7043 return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
7046 return LDSTR(2, 0, 2)
7049 return LDSTR(2, 0, 1)
7052 return LDSTR(1, 0, 2)
7055 return LDSTR(1, 0, 1)
7058 return LDSTR(0, 0, 2)
7061 return LDSTR(0, 0, 1)
7064 return LDSTR(2, 1, 1)
7067 return LDSTR(3, 1, 1)
7070 return LDSTR(0, 1, 3)
7073 c.ctxt.Diag("bad opldr %v\n%v", a, p)
7077 // olsxrr attaches register operands to a load/store opcode supplied in o.
7078 // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
7079 func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
7080 o |= int32(r1&31) << 5
7081 o |= int32(r2&31) << 16
7086 // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
7087 // for load instruction with register offset.
7088 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
7089 func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
7090 OptionS := uint32(0x1a)
7092 OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
7096 return OptionS<<10 | 0x3<<21 | 0x1f<<27
7098 return OptionS<<10 | 0x5<<21 | 0x17<<27
7100 return OptionS<<10 | 0x3<<21 | 0x17<<27
7102 return OptionS<<10 | 0x5<<21 | 0x0f<<27
7104 return OptionS<<10 | 0x3<<21 | 0x0f<<27
7106 return OptionS<<10 | 0x5<<21 | 0x07<<27
7108 return OptionS<<10 | 0x3<<21 | 0x07<<27
7110 return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
7112 return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
7114 c.ctxt.Diag("bad opldrr %v\n%v", a, p)
7118 // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
7119 // for store instruction with register offset.
7120 // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
7121 func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
7122 OptionS := uint32(0x1a)
7124 OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
7128 return OptionS<<10 | 0x1<<21 | 0x1f<<27
7130 return OptionS<<10 | 0x1<<21 | 0x17<<27
7132 return OptionS<<10 | 0x1<<21 | 0x0f<<27
7134 return OptionS<<10 | 0x1<<21 | 0x07<<27
7136 return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
7138 return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
7140 c.ctxt.Diag("bad opstrr %v\n%v", a, p)
7144 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
7145 if (v & 0xFFF000) != 0 {
7147 c.ctxt.Diag("%v misuses oaddi", p)
7153 o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
7158 * load a literal value into dr
7160 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
7162 if p.Pool == nil { /* not in literal pool */
7164 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
7166 /* TODO: could be clever, and use general constant builder */
7167 o1 = int32(c.opirr(p, AADD))
7169 v := int32(c.instoffset)
7170 if v != 0 && (v&0xFFF) == 0 {
7172 o1 |= 1 << 22 /* shift, by 12 */
7175 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
7179 case AFMOVS, AVMOVS:
7181 w = 0 /* 32-bit SIMD/FP */
7183 case AFMOVD, AVMOVD:
7185 w = 1 /* 64-bit SIMD/FP */
7189 w = 2 /* 128-bit SIMD/FP */
7192 if p.Pool.As == ADWORD {
7194 } else if p.Pool.To.Offset < 0 {
7195 w = 2 /* 32-bit, sign-extended to 64-bit */
7196 } else if p.Pool.To.Offset >= 0 {
7197 w = 0 /* 32-bit, zero-extended to 64-bit */
7199 c.ctxt.Diag("invalid operand %v in %v", a, p)
7202 case AMOVBU, AMOVHU, AMOVWU:
7203 w = 0 /* 32-bit, zero-extended to 64-bit */
7205 case AMOVB, AMOVH, AMOVW:
7206 w = 2 /* 32-bit, sign-extended to 64-bit */
7209 c.ctxt.Diag("invalid operation %v in %v", as, p)
7212 v := int32(c.brdist(p, 0, 19, 2))
7213 o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
7214 o1 |= (v & 0x7FFFF) << 5
7215 o1 |= int32(dr & 31)
7221 // load a constant (MOVCON or BITCON) in a into rt
7222 func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
7223 if cls := oclass(a); (cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0) && rt != REGZERO {
7224 // or $bitcon, REGZERO, rt. rt can't be ZR.
7234 o1 = c.opirr(p, as1)
7235 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
7240 d := uint32(a.Offset)
7241 s := movcon(int64(d))
7242 if s < 0 || 16*s >= 32 {
7244 s = movcon(int64(d))
7245 if s < 0 || 16*s >= 32 {
7246 c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
7248 o1 = c.opirr(p, AMOVNW)
7250 o1 = c.opirr(p, AMOVZW)
7252 o1 |= MOVCONST(int64(d), s, rt)
7257 if s < 0 || 16*s >= 64 {
7260 if s < 0 || 16*s >= 64 {
7261 c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
7263 o1 = c.opirr(p, AMOVN)
7265 o1 = c.opirr(p, AMOVZ)
7267 o1 |= MOVCONST(d, s, rt)
7272 // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
7273 // put the instruction sequence in os and return the number of instructions.
7274 func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
7277 d := uint32(a.Offset)
7278 // use MOVZW and MOVKW to load a constant to rt
7279 os[0] = c.opirr(p, AMOVZW)
7280 os[0] |= MOVCONST(int64(d), 0, rt)
7281 os[1] = c.opirr(p, AMOVKW)
7282 os[1] |= MOVCONST(int64(d), 1, rt)
7292 for i = 0; i < 4; i++ {
7293 immh[i] = uint64((d >> uint(i*16)) & 0xffff)
7296 } else if immh[i] == 0xffff {
7301 if zeroCount == 4 || negCount == 4 {
7302 c.ctxt.Diag("the immediate should be MOVCON: %v", p)
7305 case zeroCount == 3:
7307 for i = 0; i < 4; i++ {
7309 os[0] = c.opirr(p, AMOVZ)
7310 os[0] |= MOVCONST(d, i, rt)
7318 for i = 0; i < 4; i++ {
7319 if immh[i] != 0xffff {
7320 os[0] = c.opirr(p, AMOVN)
7321 os[0] |= MOVCONST(dn, i, rt)
7327 case zeroCount == 2:
7328 // one MOVZ and one MOVK
7329 for i = 0; i < 4; i++ {
7331 os[0] = c.opirr(p, AMOVZ)
7332 os[0] |= MOVCONST(d, i, rt)
7339 os[1] = c.opirr(p, AMOVK)
7340 os[1] |= MOVCONST(d, i, rt)
7346 // one MOVN and one MOVK
7347 for i = 0; i < 4; i++ {
7348 if immh[i] != 0xffff {
7349 os[0] = c.opirr(p, AMOVN)
7350 os[0] |= MOVCONST(dn, i, rt)
7356 if immh[i] != 0xffff {
7357 os[1] = c.opirr(p, AMOVK)
7358 os[1] |= MOVCONST(d, i, rt)
7363 case zeroCount == 1:
7364 // one MOVZ and two MOVKs
7365 for i = 0; i < 4; i++ {
7367 os[0] = c.opirr(p, AMOVZ)
7368 os[0] |= MOVCONST(d, i, rt)
7374 for j := 1; i < 4; i++ {
7376 os[j] = c.opirr(p, AMOVK)
7377 os[j] |= MOVCONST(d, i, rt)
7384 // one MOVN and two MOVKs
7385 for i = 0; i < 4; i++ {
7386 if immh[i] != 0xffff {
7387 os[0] = c.opirr(p, AMOVN)
7388 os[0] |= MOVCONST(dn, i, rt)
7394 for j := 1; i < 4; i++ {
7395 if immh[i] != 0xffff {
7396 os[j] = c.opirr(p, AMOVK)
7397 os[j] |= MOVCONST(d, i, rt)
7404 // one MOVZ and 3 MOVKs
7405 os[0] = c.opirr(p, AMOVZ)
7406 os[0] |= MOVCONST(d, 0, rt)
7407 for i = 1; i < 4; i++ {
7408 os[i] = c.opirr(p, AMOVK)
7409 os[i] |= MOVCONST(d, i, rt)
7418 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
7421 if (o & (1 << 31)) == 0 {
7426 if r < 0 || uint32(r) >= b {
7427 c.ctxt.Diag("illegal bit number\n%v", p)
7429 o |= (uint32(r) & 0x3F) << 16
7430 if s < 0 || uint32(s) >= b {
7431 c.ctxt.Diag("illegal bit number\n%v", p)
7433 o |= (uint32(s) & 0x3F) << 10
7434 o |= (uint32(rf&31) << 5) | uint32(rt&31)
7438 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
7441 if (o & (1 << 31)) != 0 {
7446 if v < 0 || uint32(v) > b {
7447 c.ctxt.Diag("illegal bit number\n%v", p)
7449 o |= uint32(v) << 10
7450 o |= uint32(rn&31) << 5
7451 o |= uint32(rm&31) << 16
7452 o |= uint32(rt & 31)
7456 /* generate instruction encoding for ldp and stp series */
7457 func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
7459 if o.scond == C_XPOST || o.scond == C_XPRE {
7463 case ALDP, ALDPW, ALDPSW:
7464 c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7467 c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
7469 case AFLDPD, AFLDPQ, AFLDPS:
7470 c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7475 case AFLDPQ, AFSTPQ:
7476 if vo < -1024 || vo > 1008 || vo%16 != 0 {
7477 c.ctxt.Diag("invalid offset %v\n", p)
7481 case AFLDPD, AFSTPD:
7482 if vo < -512 || vo > 504 || vo%8 != 0 {
7483 c.ctxt.Diag("invalid offset %v\n", p)
7487 case AFLDPS, AFSTPS:
7488 if vo < -256 || vo > 252 || vo%4 != 0 {
7489 c.ctxt.Diag("invalid offset %v\n", p)
7494 if vo < -512 || vo > 504 || vo%8 != 0 {
7495 c.ctxt.Diag("invalid offset %v\n", p)
7500 if vo < -256 || vo > 252 || vo%4 != 0 {
7501 c.ctxt.Diag("invalid offset %v\n", p)
7506 if vo < -256 || vo > 252 || vo%4 != 0 {
7507 c.ctxt.Diag("invalid offset %v\n", p)
7512 c.ctxt.Diag("invalid instruction %v\n", p)
7514 // check register pair
7516 case AFLDPQ, AFLDPD, AFLDPS, AFSTPQ, AFSTPD, AFSTPS:
7517 if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
7518 c.ctxt.Diag("invalid register pair %v\n", p)
7520 case ALDP, ALDPW, ALDPSW:
7521 if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
7522 c.ctxt.Diag("invalid register pair %v\n", p)
7525 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
7526 c.ctxt.Diag("invalid register pair %v\n", p)
7529 // other conditional flag bits
7538 ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
7542 func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
7543 if p.As == AVLD1 || p.As == AVST1 {
7547 o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
7549 case AVLD1R, AVLD2R:
7551 case AVLD3R, AVLD4R:
7559 c.ctxt.Diag("unsupported instruction:%v\n", p.As)
7565 * size in log2(bytes)
7567 func movesize(a obj.As) int {
7575 case AMOVW, AMOVWU, AFMOVS:
7589 // rm is the Rm register value, o is the extension, amount is the left shift value.
7590 func roff(rm int16, o uint32, amount int16) uint32 {
7591 return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
7594 // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
7595 func (c *ctxt7) encRegShiftOrExt(p *obj.Prog, a *obj.Addr, r int16) uint32 {
7600 case REG_UXTB <= r && r < REG_UXTH:
7601 return roff(rm, 0, num)
7602 case REG_UXTH <= r && r < REG_UXTW:
7603 return roff(rm, 1, num)
7604 case REG_UXTW <= r && r < REG_UXTX:
7605 if a.Type == obj.TYPE_MEM {
7607 return roff(rm, 2, 2)
7609 return roff(rm, 2, 6)
7612 return roff(rm, 2, num)
7614 case REG_UXTX <= r && r < REG_SXTB:
7615 return roff(rm, 3, num)
7616 case REG_SXTB <= r && r < REG_SXTH:
7617 return roff(rm, 4, num)
7618 case REG_SXTH <= r && r < REG_SXTW:
7619 return roff(rm, 5, num)
7620 case REG_SXTW <= r && r < REG_SXTX:
7621 if a.Type == obj.TYPE_MEM {
7623 return roff(rm, 6, 2)
7625 return roff(rm, 6, 6)
7628 return roff(rm, 6, num)
7630 case REG_SXTX <= r && r < REG_SPECIAL:
7631 if a.Type == obj.TYPE_MEM {
7633 return roff(rm, 7, 2)
7635 return roff(rm, 7, 6)
7638 return roff(rm, 7, num)
7640 case REG_LSL <= r && r < REG_ARNG:
7641 if a.Type == obj.TYPE_MEM { // (R1)(R2<<1)
7642 return roff(rm, 3, 6)
7643 } else if isADDWop(p.As) {
7644 return roff(rm, 2, num)
7646 return roff(rm, 3, num)
7648 c.ctxt.Diag("unsupported register extension type.")
7654 // pack returns the encoding of the "Q" field and two arrangement specifiers.
7655 func pack(q uint32, arngA, arngB uint8) uint32 {
7656 return uint32(q)<<16 | uint32(arngA)<<8 | uint32(arngB)