]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/internal/obj/arm64/asm7.go
all: fix typos in go file comments
[gostls13.git] / src / cmd / internal / obj / arm64 / asm7.go
1 // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
2 // https://code.google.com/p/ken-cc/source/browse/
3 //
4 //      Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5 //      Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6 //      Portions Copyright © 1997-1999 Vita Nuova Limited
7 //      Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8 //      Portions Copyright © 2004,2006 Bruce Ellis
9 //      Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10 //      Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11 //      Portions Copyright © 2009 The Go Authors. All rights reserved.
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a copy
14 // of this software and associated documentation files (the "Software"), to deal
15 // in the Software without restriction, including without limitation the rights
16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 // copies of the Software, and to permit persons to whom the Software is
18 // furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included in
21 // all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 // THE SOFTWARE.
30
31 package arm64
32
33 import (
34         "cmd/internal/obj"
35         "cmd/internal/objabi"
36         "fmt"
37         "log"
38         "math"
39         "sort"
40         "strings"
41 )
42
43 // ctxt7 holds state while assembling a single function.
44 // Each function gets a fresh ctxt7.
45 // This allows for multiple functions to be safely concurrently assembled.
46 type ctxt7 struct {
47         ctxt       *obj.Link
48         newprog    obj.ProgAlloc
49         cursym     *obj.LSym
50         blitrl     *obj.Prog
51         elitrl     *obj.Prog
52         autosize   int32
53         extrasize  int32
54         instoffset int64
55         pc         int64
56         pool       struct {
57                 start uint32
58                 size  uint32
59         }
60 }
61
62 const (
63         funcAlign = 16
64 )
65
66 const (
67         REGFROM = 1
68 )
69
70 type Optab struct {
71         as    obj.As
72         a1    uint8
73         a2    uint8
74         a3    uint8
75         a4    uint8
76         type_ int8
77         size_ int8 // the value of this field is not static, use the size() method to return the value
78         param int16
79         flag  int8
80         scond uint16
81 }
82
83 func IsAtomicInstruction(as obj.As) bool {
84         if _, ok := atomicLDADD[as]; ok {
85                 return true
86         }
87         if _, ok := atomicSWP[as]; ok {
88                 return true
89         }
90         return false
91 }
92
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,
159 }
160
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,
190 }
191 var atomicCASP = map[obj.As]uint32{
192         ACASPD: 1<<30 | 0x41<<21 | 0x1f<<10,
193         ACASPW: 0<<30 | 0x41<<21 | 0x1f<<10,
194 }
195
196 var oprange [ALAST & obj.AMask][]Optab
197
198 var xcmp [C_NCLASS][C_NCLASS]bool
199
200 const (
201         S32     = 0 << 31
202         S64     = 1 << 31
203         Sbit    = 1 << 29
204         LSL0_32 = 2 << 13
205         LSL0_64 = 3 << 13
206 )
207
208 func OPDP2(x uint32) uint32 {
209         return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
210 }
211
212 func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
213         return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
214 }
215
216 func OPBcc(x uint32) uint32 {
217         return 0x2A<<25 | 0<<24 | 0<<4 | x&15
218 }
219
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
223 }
224
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
227 }
228
229 func SYSHINT(x uint32) uint32 {
230         return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
231 }
232
233 func LDSTR(sz uint32, v uint32, opc uint32) uint32 {
234         return sz<<30 | 7<<27 | v<<26 | opc<<22
235 }
236
237 func LD2STR(o uint32) uint32 {
238         return o &^ (3 << 22)
239 }
240
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
243 }
244
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
247 }
248
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
251 }
252
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
255 }
256
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
259 }
260
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
263 }
264
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
267 }
268
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
271 }
272
273 func OPBIT(x uint32) uint32 {
274         return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
275 }
276
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)
279 }
280
281 const (
282         // Optab.flag
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
289 )
290
291 var optab = []Optab{
292         /* struct Optab:
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},
295
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},
345
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},
356
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 */
405
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},
417
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},
421
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},
424
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},
429
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},
442
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},
446
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},
480
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},
514
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},
523
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},
533
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},
540
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},
550
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},
557
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},
567
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},
574
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},
584
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},
591
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},
601
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},
608
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},
618
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},
625
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},
634
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},
642
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},
651
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},
659
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},
667
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},
675
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
680         in this way. */
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},
696
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},
712
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},
728
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},
744
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},
761
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},
777
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},
790
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},
816
817         /* special */
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},
834
835         /* encryption instructions */
836         {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
837         {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
838         {ASHA1C, C_VREG, C_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},
847
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
858
859         {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
860 }
861
862 // Valid pstate field values, and value to use in instruction.
863 // Doesn't include special registers.
864 var pstatefield = []struct {
865         opd SpecialOperand
866         enc uint32
867 }{
868         {SPOP_DAIFSet, 3<<16 | 4<<12 | 6<<5},
869         {SPOP_DAIFClr, 3<<16 | 4<<12 | 7<<5},
870 }
871
872 var prfopfield = map[SpecialOperand]uint32{
873         SPOP_PLDL1KEEP: 0,
874         SPOP_PLDL1STRM: 1,
875         SPOP_PLDL2KEEP: 2,
876         SPOP_PLDL2STRM: 3,
877         SPOP_PLDL3KEEP: 4,
878         SPOP_PLDL3STRM: 5,
879         SPOP_PLIL1KEEP: 8,
880         SPOP_PLIL1STRM: 9,
881         SPOP_PLIL2KEEP: 10,
882         SPOP_PLIL2STRM: 11,
883         SPOP_PLIL3KEEP: 12,
884         SPOP_PLIL3STRM: 13,
885         SPOP_PSTL1KEEP: 16,
886         SPOP_PSTL1STRM: 17,
887         SPOP_PSTL2KEEP: 18,
888         SPOP_PSTL2STRM: 19,
889         SPOP_PSTL3KEEP: 20,
890         SPOP_PSTL3STRM: 21,
891 }
892
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 {
899         op1         uint8
900         cn          uint8
901         cm          uint8
902         op2         uint8
903         hasOperand2 bool
904 }{
905         // TLBI
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},
984         // DC
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},
1013 }
1014
1015 // Used for padding NOOP instruction
1016 const OP_NOOP = 0xd503201f
1017
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)
1022         }
1023         return int(-pc & (alignedValue - 1))
1024 }
1025
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)
1033         if sz != -1 {
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.") {
1041                         return 8
1042                 }
1043         }
1044         return int(o.size_)
1045 }
1046
1047 func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
1048         if ctxt.Retpoline {
1049                 ctxt.Diag("-spectre=ret not supported on arm64")
1050                 ctxt.Retpoline = false // don't keep printing
1051         }
1052
1053         p := cursym.Func().Text
1054         if p == nil || p.Link == nil { // handle external functions and ELF section symbols
1055                 return
1056         }
1057
1058         if oprange[AAND&obj.AMask] == nil {
1059                 ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
1060         }
1061
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
1064
1065         bflag := 1
1066         pc := int64(0)
1067         p.Pc = pc
1068         var m int
1069         var o *Optab
1070         for p = p.Link; p != nil; p = p.Link {
1071                 p.Pc = pc
1072                 o = c.oplook(p)
1073                 m = o.size(c.ctxt, p)
1074                 if m == 0 {
1075                         switch p.As {
1076                         case obj.APCALIGN:
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)
1082                                 }
1083                                 break
1084                         case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1085                                 continue
1086                         default:
1087                                 c.ctxt.Diag("zero-width instruction\n%v", p)
1088                         }
1089                 }
1090                 pc += int64(m)
1091
1092                 if o.flag&LFROM != 0 {
1093                         c.addpool(p, &p.From)
1094                 }
1095                 if o.flag&LFROM128 != 0 {
1096                         c.addpool128(p, &p.From, p.GetFrom3())
1097                 }
1098                 if o.flag&LTO != 0 {
1099                         c.addpool(p, &p.To)
1100                 }
1101                 if c.blitrl != nil {
1102                         c.checkpool(p)
1103                 }
1104         }
1105
1106         c.cursym.Size = pc
1107
1108         /*
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.
1113          */
1114         for bflag != 0 {
1115                 bflag = 0
1116                 pc = 0
1117                 for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
1118                         p.Pc = pc
1119                         o = c.oplook(p)
1120
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
1124                                 var toofar bool
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
1129                                 }
1130                                 if toofar {
1131                                         q := c.newprog()
1132                                         q.Link = p.Link
1133                                         p.Link = q
1134                                         q.As = AB
1135                                         q.To.Type = obj.TYPE_BRANCH
1136                                         q.To.SetTarget(p.To.Target())
1137                                         p.To.SetTarget(q)
1138                                         q = c.newprog()
1139                                         q.Link = p.Link
1140                                         p.Link = q
1141                                         q.As = AB
1142                                         q.To.Type = obj.TYPE_BRANCH
1143                                         q.To.SetTarget(q.Link.Link)
1144                                         bflag = 1
1145                                 }
1146                         }
1147                         m = o.size(c.ctxt, p)
1148
1149                         if m == 0 {
1150                                 switch p.As {
1151                                 case obj.APCALIGN:
1152                                         alignedValue := p.From.Offset
1153                                         m = pcAlignPadLength(pc, alignedValue, ctxt)
1154                                         break
1155                                 case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
1156                                         continue
1157                                 default:
1158                                         c.ctxt.Diag("zero-width instruction\n%v", p)
1159                                 }
1160                         }
1161
1162                         pc += int64(m)
1163                 }
1164         }
1165
1166         pc += -pc & (funcAlign - 1)
1167         c.cursym.Size = pc
1168
1169         /*
1170          * lay out the code, emitting code and data relocations.
1171          */
1172         c.cursym.Grow(c.cursym.Size)
1173         bp := c.cursym.P
1174         psz := int32(0)
1175         var i int
1176         var out [6]uint32
1177         for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
1178                 c.pc = p.Pc
1179                 o = c.oplook(p)
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)
1183                 }
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)
1190                                 bp = bp[4:]
1191                                 psz += 4
1192                         }
1193                 } else {
1194                         c.asmout(p, o, out[:])
1195                         for i = 0; i < sz/4; i++ {
1196                                 c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
1197                                 bp = bp[4:]
1198                                 psz += 4
1199                         }
1200                 }
1201         }
1202
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)
1208
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)
1216                 }
1217         }
1218 }
1219
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
1227 }
1228
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) {
1233                 return false
1234         }
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
1241         // mark it.
1242         o := c.oplook(p)
1243         return o.size(c.ctxt, p) > 4 && o.flag&NOTUSETMP == 0
1244 }
1245
1246 /*
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.
1250  */
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,
1253         // flush the pool.
1254         if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) || p.Link == nil {
1255                 c.flushpool(p)
1256         }
1257 }
1258
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)
1266                 }
1267                 q := c.newprog()
1268                 if p.Link == nil {
1269                         // If p is the last instruction of the function, insert an UNDEF instruction in case the
1270                         // exection fall through to the pool.
1271                         q.As = obj.AUNDEF
1272                 } else {
1273                         // Else insert a branch to the next instruction of p.
1274                         q.As = AB
1275                         q.To.Type = obj.TYPE_BRANCH
1276                         q.To.SetTarget(p.Link)
1277                 }
1278                 q.Link = c.blitrl
1279                 q.Pos = p.Pos
1280                 c.blitrl = q
1281         }
1282
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 {
1287                 q.Pos = p.Pos
1288         }
1289
1290         c.elitrl.Link = p.Link
1291         p.Link = c.blitrl
1292
1293         c.blitrl = nil /* BUG: should refer back to values until out-of-range */
1294         c.elitrl = nil
1295         c.pool.size = 0
1296         c.pool.start = 0
1297 }
1298
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) {
1302         q := c.newprog()
1303         q.As = ADWORD
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.
1306
1307         t := c.newprog()
1308         t.As = ADWORD
1309         t.To.Type = obj.TYPE_CONST
1310         t.To.Offset = ah.Offset
1311
1312         q.Link = t
1313
1314         if c.blitrl == nil {
1315                 c.blitrl = q
1316                 c.pool.start = uint32(p.Pc)
1317         } else {
1318                 c.elitrl.Link = q
1319         }
1320
1321         c.elitrl = t
1322         c.pool.size = roundUp(c.pool.size, 16)
1323         c.pool.size += 16
1324         p.Pool = q
1325 }
1326
1327 /*
1328  * MOVD foo(SB), R is actually
1329  *   MOVD addr, REGTMP
1330  *   MOVD REGTMP, R
1331  * where addr is the address of the DWORD containing the address of foo.
1332  *
1333  * TODO: hash
1334  */
1335 func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
1336         cls := c.aclass(a)
1337         lit := c.instoffset
1338         t := c.newprog()
1339         t.As = AWORD
1340         sz := 4
1341
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.
1345                         t.As = ADWORD
1346                         sz = 8
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
1351                 t.As = ADWORD
1352                 sz = 8
1353         }
1354
1355         t.To.Type = obj.TYPE_CONST
1356         t.To.Offset = lit
1357
1358         for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
1359                 if q.To == t.To {
1360                         p.Pool = q
1361                         return
1362                 }
1363         }
1364
1365         if c.blitrl == nil {
1366                 c.blitrl = t
1367                 c.pool.start = uint32(p.Pc)
1368         } else {
1369                 c.elitrl.Link = t
1370         }
1371         c.elitrl = t
1372         if t.As == ADWORD {
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)
1377         }
1378         c.pool.size += uint32(sz)
1379         p.Pool = t
1380 }
1381
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)
1386         }
1387         return (x + to - 1) &^ (to - 1)
1388 }
1389
1390 func (c *ctxt7) regoff(a *obj.Addr) uint32 {
1391         c.instoffset = 0
1392         c.aclass(a)
1393         return uint32(c.instoffset)
1394 }
1395
1396 func isSTLXRop(op obj.As) bool {
1397         switch op {
1398         case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
1399                 ASTXR, ASTXRW, ASTXRB, ASTXRH:
1400                 return true
1401         }
1402         return false
1403 }
1404
1405 func isSTXPop(op obj.As) bool {
1406         switch op {
1407         case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
1408                 return true
1409         }
1410         return false
1411 }
1412
1413 func isANDop(op obj.As) bool {
1414         switch op {
1415         case AAND, AORR, AEOR, AANDS, ATST,
1416                 ABIC, AEON, AORN, ABICS:
1417                 return true
1418         }
1419         return false
1420 }
1421
1422 func isANDWop(op obj.As) bool {
1423         switch op {
1424         case AANDW, AORRW, AEORW, AANDSW, ATSTW,
1425                 ABICW, AEONW, AORNW, ABICSW:
1426                 return true
1427         }
1428         return false
1429 }
1430
1431 func isADDop(op obj.As) bool {
1432         switch op {
1433         case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
1434                 return true
1435         }
1436         return false
1437 }
1438
1439 func isADDWop(op obj.As) bool {
1440         switch op {
1441         case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
1442                 return true
1443         }
1444         return false
1445 }
1446
1447 func isADDSop(op obj.As) bool {
1448         switch op {
1449         case AADDS, AADDSW, ASUBS, ASUBSW:
1450                 return true
1451         }
1452         return false
1453 }
1454
1455 func isNEGop(op obj.As) bool {
1456         switch op {
1457         case ANEG, ANEGW, ANEGS, ANEGSW:
1458                 return true
1459         }
1460         return false
1461 }
1462
1463 func isRegShiftOrExt(a *obj.Addr) bool {
1464         return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
1465 }
1466
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
1472
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
1476 }
1477
1478 func isaddcon(v int64) bool {
1479         /* uimm12 or uimm24? */
1480         if v < 0 {
1481                 return false
1482         }
1483         if (v & 0xFFF) == 0 {
1484                 v >>= 12
1485         }
1486         return v <= 0xFFF
1487 }
1488
1489 func isaddcon2(v int64) bool {
1490         return 0 <= v && v <= 0xFFFFFF
1491 }
1492
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 {
1501                 return false
1502         }
1503         // determine the period and sign-extend a unit to 64 bits
1504         switch {
1505         case x != x>>32|x<<32:
1506                 // period is 64
1507                 // nothing to do
1508         case x != x>>16|x<<48:
1509                 // period is 32
1510                 x = uint64(int64(int32(x)))
1511         case x != x>>8|x<<56:
1512                 // period is 16
1513                 x = uint64(int64(int16(x)))
1514         case x != x>>4|x<<60:
1515                 // period is 8
1516                 x = uint64(int64(int8(x)))
1517         default:
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
1523                 return true
1524         }
1525         return sequenceOfOnes(x) || sequenceOfOnes(^x)
1526 }
1527
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
1531         y += x
1532         return (y-1)&y == 0
1533 }
1534
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
1541 // N=1           -- period=64
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 {
1549         if mode == 32 {
1550                 x &= 0xffffffff
1551                 x = x<<32 | x
1552         }
1553         var period uint32
1554         // determine the period and sign-extend a unit to 64 bits
1555         switch {
1556         case x != x>>32|x<<32:
1557                 period = 64
1558         case x != x>>16|x<<48:
1559                 period = 32
1560                 x = uint64(int64(int32(x)))
1561         case x != x>>8|x<<56:
1562                 period = 16
1563                 x = uint64(int64(int16(x)))
1564         case x != x>>4|x<<60:
1565                 period = 8
1566                 x = uint64(int64(int8(x)))
1567         case x != x>>2|x<<62:
1568                 period = 4
1569                 x = uint64(int64(x<<60) >> 60)
1570         default:
1571                 period = 2
1572                 x = uint64(int64(x<<62) >> 62)
1573         }
1574         neg := false
1575         if int64(x) < 0 {
1576                 x = ^x
1577                 neg = true
1578         }
1579         y := x & -x // lowest set bit of x.
1580         s := log2(y)
1581         n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
1582         if neg {
1583                 // ^x is a sequence of n ones left shifted by s bits
1584                 // adjust n, s for x
1585                 s = n + s
1586                 n = period - n
1587         }
1588
1589         N := uint32(0)
1590         if mode == 64 && period == 64 {
1591                 N = 1
1592         }
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
1596 }
1597
1598 func log2(x uint64) uint32 {
1599         if x == 0 {
1600                 panic("log2 of 0")
1601         }
1602         n := uint32(0)
1603         if x >= 1<<32 {
1604                 x >>= 32
1605                 n += 32
1606         }
1607         if x >= 1<<16 {
1608                 x >>= 16
1609                 n += 16
1610         }
1611         if x >= 1<<8 {
1612                 x >>= 8
1613                 n += 8
1614         }
1615         if x >= 1<<4 {
1616                 x >>= 4
1617                 n += 4
1618         }
1619         if x >= 1<<2 {
1620                 x >>= 2
1621                 n += 2
1622         }
1623         if x >= 1<<1 {
1624                 x >>= 1
1625                 n += 1
1626         }
1627         return n
1628 }
1629
1630 func autoclass(l int64) int {
1631         if l == 0 {
1632                 return C_ZAUTO
1633         }
1634
1635         if l < 0 {
1636                 if l >= -256 && (l&15) == 0 {
1637                         return C_NSAUTO_16
1638                 }
1639                 if l >= -256 && (l&7) == 0 {
1640                         return C_NSAUTO_8
1641                 }
1642                 if l >= -256 && (l&3) == 0 {
1643                         return C_NSAUTO_4
1644                 }
1645                 if l >= -256 {
1646                         return C_NSAUTO
1647                 }
1648                 if l >= -512 && (l&15) == 0 {
1649                         return C_NPAUTO_16
1650                 }
1651                 if l >= -512 && (l&7) == 0 {
1652                         return C_NPAUTO
1653                 }
1654                 if l >= -1024 && (l&15) == 0 {
1655                         return C_NQAUTO_16
1656                 }
1657                 if l >= -4095 {
1658                         return C_NAUTO4K
1659                 }
1660                 return C_LAUTO
1661         }
1662
1663         if l <= 255 {
1664                 if (l & 15) == 0 {
1665                         return C_PSAUTO_16
1666                 }
1667                 if (l & 7) == 0 {
1668                         return C_PSAUTO_8
1669                 }
1670                 if (l & 3) == 0 {
1671                         return C_PSAUTO_4
1672                 }
1673                 return C_PSAUTO
1674         }
1675         if l <= 504 {
1676                 if l&15 == 0 {
1677                         return C_PPAUTO_16
1678                 }
1679                 if l&7 == 0 {
1680                         return C_PPAUTO
1681                 }
1682         }
1683         if l <= 1008 {
1684                 if l&15 == 0 {
1685                         return C_PQAUTO_16
1686                 }
1687         }
1688         if l <= 4095 {
1689                 if l&15 == 0 {
1690                         return C_UAUTO4K_16
1691                 }
1692                 if l&7 == 0 {
1693                         return C_UAUTO4K_8
1694                 }
1695                 if l&3 == 0 {
1696                         return C_UAUTO4K_4
1697                 }
1698                 if l&1 == 0 {
1699                         return C_UAUTO4K_2
1700                 }
1701                 return C_UAUTO4K
1702         }
1703         if l <= 8190 {
1704                 if l&15 == 0 {
1705                         return C_UAUTO8K_16
1706                 }
1707                 if l&7 == 0 {
1708                         return C_UAUTO8K_8
1709                 }
1710                 if l&3 == 0 {
1711                         return C_UAUTO8K_4
1712                 }
1713                 if l&1 == 0 {
1714                         return C_UAUTO8K
1715                 }
1716         }
1717         if l <= 16380 {
1718                 if l&15 == 0 {
1719                         return C_UAUTO16K_16
1720                 }
1721                 if l&7 == 0 {
1722                         return C_UAUTO16K_8
1723                 }
1724                 if l&3 == 0 {
1725                         return C_UAUTO16K
1726                 }
1727         }
1728         if l <= 32760 {
1729                 if l&15 == 0 {
1730                         return C_UAUTO32K_16
1731                 }
1732                 if l&7 == 0 {
1733                         return C_UAUTO32K
1734                 }
1735         }
1736         if l <= 65520 && (l&15) == 0 {
1737                 return C_UAUTO64K
1738         }
1739         return C_LAUTO
1740 }
1741
1742 func oregclass(l int64) int {
1743         return autoclass(l) - C_ZAUTO + C_ZOREG
1744 }
1745
1746 /*
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
1750  */
1751 func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
1752         s := 0
1753         if cls >= C_SEXT1 && cls <= C_SEXT16 {
1754                 s = cls - C_SEXT1
1755         } else {
1756                 switch cls {
1757                 case C_UAUTO4K, C_UOREG4K, C_ZOREG:
1758                         s = 0
1759                 case C_UAUTO8K, C_UOREG8K:
1760                         s = 1
1761                 case C_UAUTO16K, C_UOREG16K:
1762                         s = 2
1763                 case C_UAUTO32K, C_UOREG32K:
1764                         s = 3
1765                 case C_UAUTO64K, C_UOREG64K:
1766                         s = 4
1767                 default:
1768                         c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
1769                 }
1770         }
1771         vs := v >> uint(s)
1772         if vs<<uint(s) != v {
1773                 c.ctxt.Diag("odd offset: %d\n%v", v, p)
1774         }
1775         return vs
1776 }
1777
1778 /*
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.
1782  */
1783 func movcon(v int64) int {
1784         for s := 0; s < 64; s += 16 {
1785                 if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
1786                         return s / 16
1787                 }
1788         }
1789         return -1
1790 }
1791
1792 func rclass(r int16) int {
1793         switch {
1794         case REG_R0 <= r && r <= REG_R30: // not 31
1795                 return C_REG
1796         case r == REGZERO:
1797                 return C_ZREG
1798         case REG_F0 <= r && r <= REG_F31:
1799                 return C_FREG
1800         case REG_V0 <= r && r <= REG_V31:
1801                 return C_VREG
1802         case r == REGSP:
1803                 return C_RSP
1804         case r >= REG_ARNG && r < REG_ELEM:
1805                 return C_ARNG
1806         case r >= REG_ELEM && r < REG_ELEM_END:
1807                 return C_ELEM
1808         case r >= REG_UXTB && r < REG_SPECIAL,
1809                 r >= REG_LSL && r < REG_ARNG:
1810                 return C_EXTREG
1811         case r >= REG_SPECIAL:
1812                 return C_SPR
1813         }
1814         return C_GOK
1815 }
1816
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
1826         // anyway.
1827         vbitcon := uint64(v)<<32 | uint64(v)
1828         if v == 0 {
1829                 return C_ZCON
1830         }
1831         if isaddcon(int64(v)) {
1832                 if v <= 0xFFF {
1833                         if isbitcon(vbitcon) {
1834                                 return C_ABCON0
1835                         }
1836                         return C_ADDCON0
1837                 }
1838                 if isbitcon(vbitcon) {
1839                         return C_ABCON
1840                 }
1841                 if movcon(int64(v)) >= 0 {
1842                         return C_AMCON
1843                 }
1844                 if movcon(int64(^v)) >= 0 {
1845                         return C_AMCON
1846                 }
1847                 return C_ADDCON
1848         }
1849
1850         t := movcon(int64(v))
1851         if t >= 0 {
1852                 if isbitcon(vbitcon) {
1853                         return C_MBCON
1854                 }
1855                 return C_MOVCON
1856         }
1857
1858         t = movcon(int64(^v))
1859         if t >= 0 {
1860                 if isbitcon(vbitcon) {
1861                         return C_MBCON
1862                 }
1863                 return C_MOVCON
1864         }
1865
1866         if isbitcon(vbitcon) {
1867                 return C_BITCON
1868         }
1869
1870         if 0 <= v && v <= 0xffffff {
1871                 return C_ADDCON2
1872         }
1873         return C_LCON
1874 }
1875
1876 // con64class reclassifies the constant of C_VCON and C_LCON class.
1877 func (c *ctxt7) con64class(a *obj.Addr) int {
1878         zeroCount := 0
1879         negCount := 0
1880         for i := uint(0); i < 4; i++ {
1881                 immh := uint32(a.Offset >> (i * 16) & 0xffff)
1882                 if immh == 0 {
1883                         zeroCount++
1884                 } else if immh == 0xffff {
1885                         negCount++
1886                 }
1887         }
1888         if zeroCount >= 3 || negCount >= 3 {
1889                 return C_MOVCON
1890         } else if zeroCount == 2 || negCount == 2 {
1891                 return C_MOVCON2
1892         } else if zeroCount == 1 || negCount == 1 {
1893                 return C_MOVCON3
1894         } else {
1895                 return C_VCON
1896         }
1897 }
1898
1899 func (c *ctxt7) aclass(a *obj.Addr) int {
1900         switch a.Type {
1901         case obj.TYPE_NONE:
1902                 return C_NONE
1903
1904         case obj.TYPE_REG:
1905                 return rclass(a.Reg)
1906
1907         case obj.TYPE_REGREG:
1908                 return C_PAIR
1909
1910         case obj.TYPE_SHIFT:
1911                 return C_SHIFT
1912
1913         case obj.TYPE_REGLIST:
1914                 return C_LIST
1915
1916         case obj.TYPE_MEM:
1917                 // The base register should be an integer register.
1918                 if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
1919                         break
1920                 }
1921                 switch a.Name {
1922                 case obj.NAME_EXTERN, obj.NAME_STATIC:
1923                         if a.Sym == nil {
1924                                 break
1925                         }
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 {
1930                                                 return C_TLS_IE
1931                                         } else {
1932                                                 return C_TLS_LE
1933                                         }
1934                                 }
1935                                 return C_ADDR
1936                         }
1937                         return C_LEXT
1938
1939                 case obj.NAME_GOTREF:
1940                         return C_GOTADDR
1941
1942                 case obj.NAME_AUTO:
1943                         if a.Reg == REGSP {
1944                                 // unset base register for better printing, since
1945                                 // a.Offset is still relative to pseudo-SP.
1946                                 a.Reg = obj.REG_NONE
1947                         }
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)
1951
1952                 case obj.NAME_PARAM:
1953                         if a.Reg == REGSP {
1954                                 // unset base register for better printing, since
1955                                 // a.Offset is still relative to pseudo-FP.
1956                                 a.Reg = obj.REG_NONE
1957                         }
1958                         c.instoffset = int64(c.autosize) + a.Offset + 8
1959                         return autoclass(c.instoffset)
1960
1961                 case obj.NAME_NONE:
1962                         if a.Index != 0 {
1963                                 if a.Offset != 0 {
1964                                         if isRegShiftOrExt(a) {
1965                                                 // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
1966                                                 return C_ROFF
1967                                         }
1968                                         return C_GOK
1969                                 }
1970                                 // register offset, (Rn)(Rm)
1971                                 return C_ROFF
1972                         }
1973                         c.instoffset = a.Offset
1974                         return oregclass(c.instoffset)
1975                 }
1976                 return C_GOK
1977
1978         case obj.TYPE_FCONST:
1979                 return C_FCON
1980
1981         case obj.TYPE_TEXTSIZE:
1982                 return C_TEXTSIZE
1983
1984         case obj.TYPE_CONST, obj.TYPE_ADDR:
1985                 switch a.Name {
1986                 case obj.NAME_NONE:
1987                         c.instoffset = a.Offset
1988                         if a.Reg != 0 && a.Reg != REGZERO {
1989                                 break
1990                         }
1991                         v := c.instoffset
1992                         if v == 0 {
1993                                 return C_ZCON
1994                         }
1995                         if isaddcon(v) {
1996                                 if v <= 0xFFF {
1997                                         if isbitcon(uint64(v)) {
1998                                                 return C_ABCON0
1999                                         }
2000                                         return C_ADDCON0
2001                                 }
2002                                 if isbitcon(uint64(v)) {
2003                                         return C_ABCON
2004                                 }
2005                                 if movcon(v) >= 0 {
2006                                         return C_AMCON
2007                                 }
2008                                 if movcon(^v) >= 0 {
2009                                         return C_AMCON
2010                                 }
2011                                 return C_ADDCON
2012                         }
2013
2014                         t := movcon(v)
2015                         if t >= 0 {
2016                                 if isbitcon(uint64(v)) {
2017                                         return C_MBCON
2018                                 }
2019                                 return C_MOVCON
2020                         }
2021
2022                         t = movcon(^v)
2023                         if t >= 0 {
2024                                 if isbitcon(uint64(v)) {
2025                                         return C_MBCON
2026                                 }
2027                                 return C_MOVCON
2028                         }
2029
2030                         if isbitcon(uint64(v)) {
2031                                 return C_BITCON
2032                         }
2033
2034                         if 0 <= v && v <= 0xffffff {
2035                                 return C_ADDCON2
2036                         }
2037
2038                         if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
2039                                 return C_LCON
2040                         }
2041                         return C_VCON
2042
2043                 case obj.NAME_EXTERN, obj.NAME_STATIC:
2044                         if a.Sym == nil {
2045                                 return C_GOK
2046                         }
2047                         if a.Sym.Type == objabi.STLSBSS {
2048                                 c.ctxt.Diag("taking address of TLS variable is not supported")
2049                         }
2050                         c.instoffset = a.Offset
2051                         return C_VCONADDR
2052
2053                 case obj.NAME_AUTO:
2054                         if a.Reg == REGSP {
2055                                 // unset base register for better printing, since
2056                                 // a.Offset is still relative to pseudo-SP.
2057                                 a.Reg = obj.REG_NONE
2058                         }
2059                         // The frame top 8 or 16 bytes are for FP
2060                         c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
2061
2062                 case obj.NAME_PARAM:
2063                         if a.Reg == REGSP {
2064                                 // unset base register for better printing, since
2065                                 // a.Offset is still relative to pseudo-FP.
2066                                 a.Reg = obj.REG_NONE
2067                         }
2068                         c.instoffset = int64(c.autosize) + a.Offset + 8
2069                 default:
2070                         return C_GOK
2071                 }
2072                 cf := c.instoffset
2073                 if isaddcon(cf) || isaddcon(-cf) {
2074                         return C_AACON
2075                 }
2076                 if isaddcon2(cf) {
2077                         return C_AACON2
2078                 }
2079
2080                 return C_LACON
2081
2082         case obj.TYPE_BRANCH:
2083                 return C_SBRA
2084
2085         case obj.TYPE_SPECIAL:
2086                 opd := SpecialOperand(a.Offset)
2087                 if SPOP_EQ <= opd && opd <= SPOP_NV {
2088                         return C_COND
2089                 }
2090                 return C_SPOP
2091         }
2092         return C_GOK
2093 }
2094
2095 func oclass(a *obj.Addr) int {
2096         return int(a.Class) - 1
2097 }
2098
2099 func (c *ctxt7) oplook(p *obj.Prog) *Optab {
2100         a1 := int(p.Optab)
2101         if a1 != 0 {
2102                 return &optab[a1-1]
2103         }
2104         a1 = int(p.From.Class)
2105         if a1 == 0 {
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 {
2109                         a0 = C_LCON
2110                 }
2111                 a1 = a0 + 1
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 {
2120                                         ra0 = C_LCON
2121                                 }
2122                                 a1 = ra0 + 1
2123                                 p.From.Class = int8(a1)
2124                         }
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)
2129                         }
2130                 }
2131         }
2132
2133         a1--
2134         a3 := C_NONE + 1
2135         if p.GetFrom3() != nil && p.RestArgs[0].Pos == 0 {
2136                 a3 = int(p.GetFrom3().Class)
2137                 if a3 == 0 {
2138                         a3 = c.aclass(p.GetFrom3()) + 1
2139                         p.GetFrom3().Class = int8(a3)
2140                 }
2141         }
2142
2143         a3--
2144         a4 := int(p.To.Class)
2145         if a4 == 0 {
2146                 a4 = c.aclass(&p.To) + 1
2147                 p.To.Class = int8(a4)
2148         }
2149
2150         a4--
2151         a2 := C_NONE
2152         if p.Reg != 0 {
2153                 a2 = rclass(p.Reg)
2154         }
2155
2156         if false {
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)
2159         }
2160
2161         ops := oprange[p.As&obj.AMask]
2162         c1 := &xcmp[a1]
2163         c2 := &xcmp[a2]
2164         c3 := &xcmp[a3]
2165         c4 := &xcmp[a4]
2166         c5 := &xcmp[p.Scond>>5]
2167         for i := range ops {
2168                 op := &ops[i]
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)
2171                         return op
2172                 }
2173         }
2174
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}
2178 }
2179
2180 func cmp(a int, b int) bool {
2181         if a == b {
2182                 return true
2183         }
2184         switch a {
2185         case C_RSP:
2186                 if b == C_REG {
2187                         return true
2188                 }
2189
2190         case C_ZREG:
2191                 if b == C_REG {
2192                         return true
2193                 }
2194
2195         case C_ADDCON0:
2196                 if b == C_ZCON || b == C_ABCON0 {
2197                         return true
2198                 }
2199
2200         case C_ADDCON:
2201                 if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
2202                         return true
2203                 }
2204
2205         case C_MBCON:
2206                 if b == C_ABCON0 {
2207                         return true
2208                 }
2209
2210         case C_BITCON:
2211                 if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
2212                         return true
2213                 }
2214
2215         case C_MOVCON:
2216                 if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_ABCON0 || b == C_AMCON {
2217                         return true
2218                 }
2219
2220         case C_ADDCON2:
2221                 if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
2222                         return true
2223                 }
2224
2225         case C_LCON:
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 {
2227                         return true
2228                 }
2229
2230         case C_MOVCON2:
2231                 return cmp(C_LCON, b)
2232
2233         case C_VCON:
2234                 return cmp(C_LCON, b)
2235
2236         case C_LACON:
2237                 if b == C_AACON || b == C_AACON2 {
2238                         return true
2239                 }
2240
2241         case C_SEXT2:
2242                 if b == C_SEXT1 {
2243                         return true
2244                 }
2245
2246         case C_SEXT4:
2247                 if b == C_SEXT1 || b == C_SEXT2 {
2248                         return true
2249                 }
2250
2251         case C_SEXT8:
2252                 if b >= C_SEXT1 && b <= C_SEXT4 {
2253                         return true
2254                 }
2255
2256         case C_SEXT16:
2257                 if b >= C_SEXT1 && b <= C_SEXT8 {
2258                         return true
2259                 }
2260
2261         case C_LEXT:
2262                 if b >= C_SEXT1 && b <= C_SEXT16 {
2263                         return true
2264                 }
2265
2266         case C_NSAUTO_8:
2267                 if b == C_NSAUTO_16 {
2268                         return true
2269                 }
2270
2271         case C_NSAUTO_4:
2272                 if b == C_NSAUTO_16 || b == C_NSAUTO_8 {
2273                         return true
2274                 }
2275
2276         case C_NSAUTO:
2277                 switch b {
2278                 case C_NSAUTO_4, C_NSAUTO_8, C_NSAUTO_16:
2279                         return true
2280                 }
2281
2282         case C_NPAUTO_16:
2283                 switch b {
2284                 case C_NSAUTO_16:
2285                         return true
2286                 }
2287
2288         case C_NPAUTO:
2289                 switch b {
2290                 case C_NSAUTO_16, C_NSAUTO_8, C_NPAUTO_16:
2291                         return true
2292                 }
2293
2294         case C_NQAUTO_16:
2295                 switch b {
2296                 case C_NSAUTO_16, C_NPAUTO_16:
2297                         return true
2298                 }
2299
2300         case C_NAUTO4K:
2301                 switch b {
2302                 case C_NSAUTO_16, C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO_16,
2303                         C_NPAUTO, C_NQAUTO_16:
2304                         return true
2305                 }
2306
2307         case C_PSAUTO_16:
2308                 if b == C_ZAUTO {
2309                         return true
2310                 }
2311
2312         case C_PSAUTO_8:
2313                 if b == C_ZAUTO || b == C_PSAUTO_16 {
2314                         return true
2315                 }
2316
2317         case C_PSAUTO_4:
2318                 switch b {
2319                 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8:
2320                         return true
2321                 }
2322
2323         case C_PSAUTO:
2324                 switch b {
2325                 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PSAUTO_4:
2326                         return true
2327                 }
2328
2329         case C_PPAUTO_16:
2330                 switch b {
2331                 case C_ZAUTO, C_PSAUTO_16:
2332                         return true
2333                 }
2334
2335         case C_PPAUTO:
2336                 switch b {
2337                 case C_ZAUTO, C_PSAUTO_16, C_PSAUTO_8, C_PPAUTO_16:
2338                         return true
2339                 }
2340
2341         case C_PQAUTO_16:
2342                 switch b {
2343                 case C_ZAUTO, C_PSAUTO_16, C_PPAUTO_16:
2344                         return true
2345                 }
2346
2347         case C_UAUTO4K:
2348                 switch b {
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:
2352                         return true
2353                 }
2354
2355         case C_UAUTO8K:
2356                 switch b {
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:
2361                         return true
2362                 }
2363
2364         case C_UAUTO16K:
2365                 switch b {
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:
2371                         return true
2372                 }
2373
2374         case C_UAUTO32K:
2375                 switch b {
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,
2381                         C_UAUTO32K_16:
2382                         return true
2383                 }
2384
2385         case C_UAUTO64K:
2386                 switch b {
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,
2389                         C_UAUTO32K_16:
2390                         return true
2391                 }
2392
2393         case C_LAUTO:
2394                 switch b {
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,
2402                         C_UAUTO64K:
2403                         return true
2404                 }
2405
2406         case C_NSOREG_8:
2407                 if b == C_NSOREG_16 {
2408                         return true
2409                 }
2410
2411         case C_NSOREG_4:
2412                 if b == C_NSOREG_8 || b == C_NSOREG_16 {
2413                         return true
2414                 }
2415
2416         case C_NSOREG:
2417                 switch b {
2418                 case C_NSOREG_4, C_NSOREG_8, C_NSOREG_16:
2419                         return true
2420                 }
2421
2422         case C_NPOREG_16:
2423                 switch b {
2424                 case C_NSOREG_16:
2425                         return true
2426                 }
2427
2428         case C_NPOREG:
2429                 switch b {
2430                 case C_NSOREG_16, C_NSOREG_8, C_NPOREG_16:
2431                         return true
2432                 }
2433
2434         case C_NQOREG_16:
2435                 switch b {
2436                 case C_NSOREG_16, C_NPOREG_16:
2437                         return true
2438                 }
2439
2440         case C_NOREG4K:
2441                 switch b {
2442                 case C_NSOREG_16, C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG_16, C_NPOREG, C_NQOREG_16:
2443                         return true
2444                 }
2445
2446         case C_PSOREG_16:
2447                 if b == C_ZOREG {
2448                         return true
2449                 }
2450
2451         case C_PSOREG_8:
2452                 if b == C_ZOREG || b == C_PSOREG_16 {
2453                         return true
2454                 }
2455
2456         case C_PSOREG_4:
2457                 switch b {
2458                 case C_ZOREG, C_PSOREG_16, C_PSOREG_8:
2459                         return true
2460                 }
2461
2462         case C_PSOREG:
2463                 switch b {
2464                 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PSOREG_4:
2465                         return true
2466                 }
2467
2468         case C_PPOREG_16:
2469                 switch b {
2470                 case C_ZOREG, C_PSOREG_16:
2471                         return true
2472                 }
2473
2474         case C_PPOREG:
2475                 switch b {
2476                 case C_ZOREG, C_PSOREG_16, C_PSOREG_8, C_PPOREG_16:
2477                         return true
2478                 }
2479
2480         case C_PQOREG_16:
2481                 switch b {
2482                 case C_ZOREG, C_PSOREG_16, C_PPOREG_16:
2483                         return true
2484                 }
2485
2486         case C_UOREG4K:
2487                 switch b {
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:
2491                         return true
2492                 }
2493
2494         case C_UOREG8K:
2495                 switch b {
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:
2500                         return true
2501                 }
2502
2503         case C_UOREG16K:
2504                 switch b {
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:
2510                         return true
2511                 }
2512
2513         case C_UOREG32K:
2514                 switch b {
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,
2520                         C_UOREG32K_16:
2521                         return true
2522                 }
2523
2524         case C_UOREG64K:
2525                 switch b {
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,
2528                         C_UOREG32K_16:
2529                         return true
2530                 }
2531
2532         case C_LOREG:
2533                 switch b {
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,
2541                         C_UOREG64K:
2542                         return true
2543                 }
2544
2545         case C_LBRA:
2546                 if b == C_SBRA {
2547                         return true
2548                 }
2549         }
2550
2551         return false
2552 }
2553
2554 type ocmp []Optab
2555
2556 func (x ocmp) Len() int {
2557         return len(x)
2558 }
2559
2560 func (x ocmp) Swap(i, j int) {
2561         x[i], x[j] = x[j], x[i]
2562 }
2563
2564 func (x ocmp) Less(i, j int) bool {
2565         p1 := &x[i]
2566         p2 := &x[j]
2567         if p1.as != p2.as {
2568                 return p1.as < p2.as
2569         }
2570         if p1.a1 != p2.a1 {
2571                 return p1.a1 < p2.a1
2572         }
2573         if p1.a2 != p2.a2 {
2574                 return p1.a2 < p2.a2
2575         }
2576         if p1.a3 != p2.a3 {
2577                 return p1.a3 < p2.a3
2578         }
2579         if p1.a4 != p2.a4 {
2580                 return p1.a4 < p2.a4
2581         }
2582         if p1.scond != p2.scond {
2583                 return p1.scond < p2.scond
2584         }
2585         return false
2586 }
2587
2588 func oprangeset(a obj.As, t []Optab) {
2589         oprange[a&obj.AMask] = t
2590 }
2591
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.
2597                 return
2598         }
2599
2600         var n int
2601         for i := 0; i < C_GOK; i++ {
2602                 for n = 0; n < C_GOK; n++ {
2603                         if cmp(n, i) {
2604                                 xcmp[i][n] = true
2605                         }
2606                 }
2607         }
2608         for n = 0; optab[n].as != obj.AXXX; n++ {
2609         }
2610         sort.Sort(ocmp(optab[:n]))
2611         for i := 0; i < n; i++ {
2612                 r := optab[i].as
2613                 start := i
2614                 for optab[i].as == r {
2615                         i++
2616                 }
2617                 t := optab[start:i]
2618                 i--
2619                 oprangeset(r, t)
2620                 switch r {
2621                 default:
2622                         ctxt.Diag("unknown op in build: %v", r)
2623                         ctxt.DiagFlush()
2624                         log.Fatalf("bad code")
2625
2626                 case AADD:
2627                         oprangeset(AADDS, t)
2628                         oprangeset(ASUB, t)
2629                         oprangeset(ASUBS, t)
2630                         oprangeset(AADDW, t)
2631                         oprangeset(AADDSW, t)
2632                         oprangeset(ASUBW, t)
2633                         oprangeset(ASUBSW, t)
2634
2635                 case AAND: /* logical immediate, logical shifted register */
2636                         oprangeset(AANDW, t)
2637                         oprangeset(AEOR, t)
2638                         oprangeset(AEORW, t)
2639                         oprangeset(AORR, t)
2640                         oprangeset(AORRW, t)
2641                         oprangeset(ABIC, t)
2642                         oprangeset(ABICW, t)
2643                         oprangeset(AEON, t)
2644                         oprangeset(AEONW, t)
2645                         oprangeset(AORN, t)
2646                         oprangeset(AORNW, t)
2647
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)
2652
2653                 case ANEG:
2654                         oprangeset(ANEGS, t)
2655                         oprangeset(ANEGSW, t)
2656                         oprangeset(ANEGW, t)
2657
2658                 case AADC: /* rn=Rd */
2659                         oprangeset(AADCW, t)
2660
2661                         oprangeset(AADCS, t)
2662                         oprangeset(AADCSW, t)
2663                         oprangeset(ASBC, t)
2664                         oprangeset(ASBCW, t)
2665                         oprangeset(ASBCS, t)
2666                         oprangeset(ASBCSW, t)
2667
2668                 case ANGC: /* rn=REGZERO */
2669                         oprangeset(ANGCW, t)
2670
2671                         oprangeset(ANGCS, t)
2672                         oprangeset(ANGCSW, t)
2673
2674                 case ACMP:
2675                         oprangeset(ACMPW, t)
2676                         oprangeset(ACMN, t)
2677                         oprangeset(ACMNW, t)
2678
2679                 case ATST:
2680                         oprangeset(ATSTW, t)
2681
2682                         /* register/register, and shifted */
2683                 case AMVN:
2684                         oprangeset(AMVNW, t)
2685
2686                 case AMOVK:
2687                         oprangeset(AMOVKW, t)
2688                         oprangeset(AMOVN, t)
2689                         oprangeset(AMOVNW, t)
2690                         oprangeset(AMOVZ, t)
2691                         oprangeset(AMOVZW, t)
2692
2693                 case ASWPD:
2694                         for i := range atomicLDADD {
2695                                 oprangeset(i, t)
2696                         }
2697                         for i := range atomicSWP {
2698                                 if i == ASWPD {
2699                                         continue
2700                                 }
2701                                 oprangeset(i, t)
2702                         }
2703
2704                 case ACASPD:
2705                         oprangeset(ACASPW, t)
2706                 case ABEQ:
2707                         oprangeset(ABNE, t)
2708                         oprangeset(ABCS, t)
2709                         oprangeset(ABHS, t)
2710                         oprangeset(ABCC, t)
2711                         oprangeset(ABLO, t)
2712                         oprangeset(ABMI, t)
2713                         oprangeset(ABPL, t)
2714                         oprangeset(ABVS, t)
2715                         oprangeset(ABVC, t)
2716                         oprangeset(ABHI, t)
2717                         oprangeset(ABLS, t)
2718                         oprangeset(ABGE, t)
2719                         oprangeset(ABLT, t)
2720                         oprangeset(ABGT, t)
2721                         oprangeset(ABLE, t)
2722
2723                 case ALSL:
2724                         oprangeset(ALSLW, t)
2725                         oprangeset(ALSR, t)
2726                         oprangeset(ALSRW, t)
2727                         oprangeset(AASR, t)
2728                         oprangeset(AASRW, t)
2729                         oprangeset(AROR, t)
2730                         oprangeset(ARORW, t)
2731
2732                 case ACLS:
2733                         oprangeset(ACLSW, t)
2734                         oprangeset(ACLZ, t)
2735                         oprangeset(ACLZW, t)
2736                         oprangeset(ARBIT, t)
2737                         oprangeset(ARBITW, t)
2738                         oprangeset(AREV, t)
2739                         oprangeset(AREVW, t)
2740                         oprangeset(AREV16, t)
2741                         oprangeset(AREV16W, t)
2742                         oprangeset(AREV32, t)
2743
2744                 case ASDIV:
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)
2756
2757                 case AMADD:
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)
2765
2766                 case AREM:
2767                         oprangeset(AREMW, t)
2768                         oprangeset(AUREM, t)
2769                         oprangeset(AUREMW, t)
2770
2771                 case AMUL:
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)
2781
2782                 case AMOVB:
2783                         oprangeset(AMOVBU, t)
2784
2785                 case AMOVH:
2786                         oprangeset(AMOVHU, t)
2787
2788                 case AMOVW:
2789                         oprangeset(AMOVWU, t)
2790
2791                 case ABFM:
2792                         oprangeset(ABFMW, t)
2793                         oprangeset(ASBFM, t)
2794                         oprangeset(ASBFMW, t)
2795                         oprangeset(AUBFM, t)
2796                         oprangeset(AUBFMW, t)
2797
2798                 case ABFI:
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)
2810
2811                 case AEXTR:
2812                         oprangeset(AEXTRW, t)
2813
2814                 case ASXTB:
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)
2824
2825                 case ACCMN:
2826                         oprangeset(ACCMNW, t)
2827                         oprangeset(ACCMP, t)
2828                         oprangeset(ACCMPW, t)
2829
2830                 case ACSEL:
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)
2838
2839                 case ACINC:
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)
2846
2847                         // aliases, Rm=Rn=REGZERO, !cond
2848                 case ACSET:
2849                         oprangeset(ACSETW, t)
2850
2851                         oprangeset(ACSETM, t)
2852                         oprangeset(ACSETMW, t)
2853
2854                 case AMOVD,
2855                         AB,
2856                         ABL,
2857                         AWORD,
2858                         ADWORD,
2859                         obj.ARET,
2860                         obj.ATEXT:
2861                         break
2862
2863                 case AFLDPQ:
2864                         break
2865                 case AFSTPQ:
2866                         break
2867                 case ALDP:
2868                         oprangeset(AFLDPD, t)
2869
2870                 case ASTP:
2871                         oprangeset(AFSTPD, t)
2872
2873                 case ASTPW:
2874                         oprangeset(AFSTPS, t)
2875
2876                 case ALDPW:
2877                         oprangeset(ALDPSW, t)
2878                         oprangeset(AFLDPS, t)
2879
2880                 case AERET:
2881                         oprangeset(AWFE, t)
2882                         oprangeset(AWFI, t)
2883                         oprangeset(AYIELD, t)
2884                         oprangeset(ASEV, t)
2885                         oprangeset(ASEVL, t)
2886                         oprangeset(ANOOP, t)
2887                         oprangeset(ADRPS, t)
2888
2889                 case ACBZ:
2890                         oprangeset(ACBZW, t)
2891                         oprangeset(ACBNZ, t)
2892                         oprangeset(ACBNZW, t)
2893
2894                 case ATBZ:
2895                         oprangeset(ATBNZ, t)
2896
2897                 case AADR, AADRP:
2898                         break
2899
2900                 case ACLREX:
2901                         break
2902
2903                 case ASVC:
2904                         oprangeset(AHVC, t)
2905                         oprangeset(AHLT, t)
2906                         oprangeset(ASMC, t)
2907                         oprangeset(ABRK, t)
2908                         oprangeset(ADCPS1, t)
2909                         oprangeset(ADCPS2, t)
2910                         oprangeset(ADCPS3, t)
2911
2912                 case AFADDS:
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)
2930
2931                 case AFMSUBD:
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)
2939
2940                 case AFCVTSD:
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)
2966
2967                 case AFCMPS:
2968                         oprangeset(AFCMPD, t)
2969                         oprangeset(AFCMPES, t)
2970                         oprangeset(AFCMPED, t)
2971
2972                 case AFCCMPS:
2973                         oprangeset(AFCCMPD, t)
2974                         oprangeset(AFCCMPES, t)
2975                         oprangeset(AFCCMPED, t)
2976
2977                 case AFCSELD:
2978                         oprangeset(AFCSELS, t)
2979
2980                 case AFMOVQ, AFMOVD, AFMOVS,
2981                         AVMOVQ, AVMOVD, AVMOVS:
2982                         break
2983
2984                 case AFCVTZSD:
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)
2992
2993                 case ASCVTFD:
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)
3001
3002                 case ASYS:
3003                         oprangeset(AAT, t)
3004                         oprangeset(AIC, t)
3005
3006                 case ATLBI:
3007                         oprangeset(ADC, t)
3008
3009                 case ASYSL, AHINT:
3010                         break
3011
3012                 case ADMB:
3013                         oprangeset(ADSB, t)
3014                         oprangeset(AISB, t)
3015
3016                 case AMRS, AMSR:
3017                         break
3018
3019                 case ALDAR:
3020                         oprangeset(ALDARW, t)
3021                         oprangeset(ALDARB, t)
3022                         oprangeset(ALDARH, t)
3023                         fallthrough
3024
3025                 case ALDXR:
3026                         oprangeset(ALDXRB, t)
3027                         oprangeset(ALDXRH, t)
3028                         oprangeset(ALDXRW, t)
3029
3030                 case ALDAXR:
3031                         oprangeset(ALDAXRB, t)
3032                         oprangeset(ALDAXRH, t)
3033                         oprangeset(ALDAXRW, t)
3034
3035                 case ALDXP:
3036                         oprangeset(ALDXPW, t)
3037                         oprangeset(ALDAXP, t)
3038                         oprangeset(ALDAXPW, t)
3039
3040                 case ASTLR:
3041                         oprangeset(ASTLRB, t)
3042                         oprangeset(ASTLRH, t)
3043                         oprangeset(ASTLRW, t)
3044
3045                 case ASTXR:
3046                         oprangeset(ASTXRB, t)
3047                         oprangeset(ASTXRH, t)
3048                         oprangeset(ASTXRW, t)
3049
3050                 case ASTLXR:
3051                         oprangeset(ASTLXRB, t)
3052                         oprangeset(ASTLXRH, t)
3053                         oprangeset(ASTLXRW, t)
3054
3055                 case ASTXP:
3056                         oprangeset(ASTLXP, t)
3057                         oprangeset(ASTLXPW, t)
3058                         oprangeset(ASTXPW, t)
3059
3060                 case AVADDP:
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)
3073
3074                 case AVADD:
3075                         oprangeset(AVSUB, t)
3076                         oprangeset(AVRAX1, t)
3077
3078                 case AAESD:
3079                         oprangeset(AAESE, t)
3080                         oprangeset(AAESMC, t)
3081                         oprangeset(AAESIMC, t)
3082                         oprangeset(ASHA1SU1, t)
3083                         oprangeset(ASHA256SU0, t)
3084                         oprangeset(ASHA512SU0, t)
3085
3086                 case ASHA1C:
3087                         oprangeset(ASHA1P, t)
3088                         oprangeset(ASHA1M, t)
3089
3090                 case ASHA256H:
3091                         oprangeset(ASHA256H2, t)
3092                         oprangeset(ASHA512H, t)
3093                         oprangeset(ASHA512H2, t)
3094
3095                 case ASHA1SU0:
3096                         oprangeset(ASHA256SU1, t)
3097                         oprangeset(ASHA512SU1, t)
3098
3099                 case AVADDV:
3100                         oprangeset(AVUADDLV, t)
3101
3102                 case AVFMLA:
3103                         oprangeset(AVFMLS, t)
3104
3105                 case AVPMULL:
3106                         oprangeset(AVPMULL2, t)
3107
3108                 case AVUSHR:
3109                         oprangeset(AVSHL, t)
3110                         oprangeset(AVSRI, t)
3111                         oprangeset(AVSLI, t)
3112                         oprangeset(AVUSRA, t)
3113
3114                 case AVREV32:
3115                         oprangeset(AVCNT, t)
3116                         oprangeset(AVRBIT, t)
3117                         oprangeset(AVREV64, t)
3118                         oprangeset(AVREV16, t)
3119
3120                 case AVZIP1:
3121                         oprangeset(AVZIP2, t)
3122                         oprangeset(AVTRN1, t)
3123                         oprangeset(AVTRN2, t)
3124
3125                 case AVUXTL:
3126                         oprangeset(AVUXTL2, t)
3127
3128                 case AVUSHLL:
3129                         oprangeset(AVUSHLL2, t)
3130
3131                 case AVLD1R:
3132                         oprangeset(AVLD2, t)
3133                         oprangeset(AVLD2R, t)
3134                         oprangeset(AVLD3, t)
3135                         oprangeset(AVLD3R, t)
3136                         oprangeset(AVLD4, t)
3137                         oprangeset(AVLD4R, t)
3138
3139                 case AVEOR3:
3140                         oprangeset(AVBCAX, t)
3141
3142                 case AVUADDW:
3143                         oprangeset(AVUADDW2, t)
3144
3145                 case AVTBL:
3146                         oprangeset(AVTBX, t)
3147
3148                 case ASHA1H,
3149                         AVCNT,
3150                         AVMOV,
3151                         AVLD1,
3152                         AVST1,
3153                         AVST2,
3154                         AVST3,
3155                         AVST4,
3156                         AVDUP,
3157                         AVMOVI,
3158                         APRFM,
3159                         AVEXT,
3160                         AVXAR:
3161                         break
3162
3163                 case obj.ANOP,
3164                         obj.AUNDEF,
3165                         obj.AFUNCDATA,
3166                         obj.APCALIGN,
3167                         obj.APCDATA,
3168                         obj.ADUFFZERO,
3169                         obj.ADUFFCOPY:
3170                         break
3171                 }
3172         }
3173 }
3174
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))
3182
3183         if l != 0 || h&0xffff != 0 {
3184                 return -1
3185         }
3186         h1 := h & 0x7fc00000
3187         if h1 != 0x40000000 && h1 != 0x3fc00000 {
3188                 return -1
3189         }
3190         n := 0
3191
3192         // sign bit (a)
3193         if h&0x80000000 != 0 {
3194                 n |= 1 << 7
3195         }
3196
3197         // exp sign bit (b)
3198         if h1 == 0x3fc00000 {
3199                 n |= 1 << 6
3200         }
3201
3202         // rest of exp and mantissa (cd-efgh)
3203         n |= int((h >> 16) & 0x3f)
3204
3205         //print("match %.8lux %.8lux %d\n", l, h, n);
3206         return n
3207 }
3208
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
3212 }
3213
3214 func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
3215         return SYSARG5(0, op1, Cn, Cm, op2)
3216 }
3217
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)
3223         }
3224         if isload && rt1 == rt2 {
3225                 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
3226         }
3227 }
3228
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)
3233         }
3234 }
3235
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
3239         switch as {
3240         case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3241                 offset = p.From.Offset
3242                 list = p.To.Offset
3243         case AVST1, AVST2, AVST3, AVST4:
3244                 offset = p.To.Offset
3245                 list = p.From.Offset
3246         default:
3247                 c.ctxt.Diag("invalid operation on op %v", p.As)
3248         }
3249         opcode := (list >> 12) & 15
3250         q := (list >> 30) & 1
3251         size := (list >> 10) & 3
3252         if offset == 0 {
3253                 return
3254         }
3255         switch opcode {
3256         case 0x7:
3257                 n = 1 // one register
3258         case 0xa:
3259                 n = 2 // two registers
3260         case 0x6:
3261                 n = 3 // three registers
3262         case 0x2:
3263                 n = 4 // four registers
3264         default:
3265                 c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
3266         }
3267
3268         switch as {
3269         case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
3270                 if offset != n*(1<<uint(size)) {
3271                         c.ctxt.Diag("invalid post-increment offset: %v", p)
3272                 }
3273         default:
3274                 if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
3275                         c.ctxt.Diag("invalid post-increment offset: %v", p)
3276                 }
3277         }
3278
3279         switch as {
3280         case AVLD1, AVST1:
3281                 return
3282         case AVLD1R:
3283                 expect = 1
3284         case AVLD2, AVST2, AVLD2R:
3285                 expect = 2
3286         case AVLD3, AVST3, AVLD3R:
3287                 expect = 3
3288         case AVLD4, AVST4, AVLD4R:
3289                 expect = 4
3290         }
3291
3292         if expect != n {
3293                 c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
3294         }
3295 }
3296
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) {
3300         var amount int16
3301         amount = (a.Index >> 5) & 7
3302         switch p.As {
3303         case AMOVB, AMOVBU:
3304                 if amount != 0 {
3305                         c.ctxt.Diag("invalid index shift amount: %v", p)
3306                 }
3307         case AMOVH, AMOVHU:
3308                 if amount != 1 && amount != 0 {
3309                         c.ctxt.Diag("invalid index shift amount: %v", p)
3310                 }
3311         case AMOVW, AMOVWU, AFMOVS:
3312                 if amount != 2 && amount != 0 {
3313                         c.ctxt.Diag("invalid index shift amount: %v", p)
3314                 }
3315         case AMOVD, AFMOVD:
3316                 if amount != 3 && amount != 0 {
3317                         c.ctxt.Diag("invalid index shift amount: %v", p)
3318                 }
3319         default:
3320                 panic("invalid operation")
3321         }
3322 }
3323
3324 func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
3325         var os [5]uint32
3326         o1 := uint32(0)
3327         o2 := uint32(0)
3328         o3 := uint32(0)
3329         o4 := uint32(0)
3330         o5 := uint32(0)
3331         if false { /*debug['P']*/
3332                 fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
3333         }
3334         switch o.type_ {
3335         default:
3336                 c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
3337
3338         case 0: /* pseudo ops */
3339                 break
3340
3341         case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
3342                 o1 = c.oprrr(p, p.As)
3343
3344                 rf := int(p.From.Reg)
3345                 rt := int(p.To.Reg)
3346                 r := int(p.Reg)
3347                 if p.To.Type == obj.TYPE_NONE {
3348                         rt = REGZERO
3349                 }
3350                 if r == 0 {
3351                         r = rt
3352                 }
3353                 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3354
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)
3358                 }
3359                 o1 = c.opirr(p, p.As)
3360
3361                 rt := int(p.To.Reg)
3362                 if p.To.Type == obj.TYPE_NONE {
3363                         if (o1 & Sbit) == 0 {
3364                                 c.ctxt.Diag("ineffective ZR destination\n%v", p)
3365                         }
3366                         rt = REGZERO
3367                 }
3368
3369                 r := int(p.Reg)
3370                 if r == 0 {
3371                         r = rt
3372                 }
3373                 v := int32(c.regoff(&p.From))
3374                 o1 = c.oaddi(p, int32(o1), v, r, rt)
3375
3376         case 3: /* op R<<n[,R],R (shifted register) */
3377                 o1 = c.oprrr(p, p.As)
3378
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)
3383                 }
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)
3387                 }
3388                 o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
3389                 rt := int(p.To.Reg)
3390                 if p.To.Type == obj.TYPE_NONE {
3391                         rt = REGZERO
3392                 }
3393                 r := int(p.Reg)
3394                 if p.As == AMVN || p.As == AMVNW || isNEGop(p.As) {
3395                         r = REGZERO
3396                 } else if r == 0 {
3397                         r = rt
3398                 }
3399                 o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3400
3401         case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
3402                 rt := int(p.To.Reg)
3403                 r := int(o.param)
3404
3405                 if r == 0 {
3406                         r = REGZERO
3407                 } else if r == REGFROM {
3408                         r = int(p.From.Reg)
3409                 }
3410                 if r == 0 {
3411                         r = REGSP
3412                 }
3413
3414                 v := int32(c.regoff(&p.From))
3415                 var op int32
3416                 if v < 0 {
3417                         v = -v
3418                         op = int32(c.opirr(p, ASUB))
3419                 } else {
3420                         op = int32(c.opirr(p, AADD))
3421                 }
3422
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)
3428                         break
3429                 }
3430
3431                 o1 = c.oaddi(p, op, v, r, rt)
3432
3433         case 5: /* b s; bl s */
3434                 o1 = c.opbra(p, p.As)
3435
3436                 if p.To.Sym == nil {
3437                         o1 |= uint32(c.brdist(p, 0, 26, 2))
3438                         break
3439                 }
3440
3441                 rel := obj.Addrel(c.cursym)
3442                 rel.Off = int32(c.pc)
3443                 rel.Siz = 4
3444                 rel.Sym = p.To.Sym
3445                 rel.Add = p.To.Offset
3446                 rel.Type = objabi.R_CALLARM64
3447
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)
3454                         rel.Siz = 0
3455                         rel.Type = objabi.R_CALLIND
3456                 }
3457
3458         case 7: /* beq s */
3459                 o1 = c.opbra(p, p.As)
3460
3461                 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
3462
3463         case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
3464                 rt := int(p.To.Reg)
3465
3466                 rf := int(p.Reg)
3467                 if rf == 0 {
3468                         rf = rt
3469                 }
3470                 v := int32(p.From.Offset)
3471                 switch p.As {
3472                 case AASR:
3473                         o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
3474
3475                 case AASRW:
3476                         o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
3477
3478                 case ALSL:
3479                         o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
3480
3481                 case ALSLW:
3482                         o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
3483
3484                 case ALSR:
3485                         o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
3486
3487                 case ALSRW:
3488                         o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
3489
3490                 case AROR:
3491                         o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
3492
3493                 case ARORW:
3494                         o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
3495
3496                 default:
3497                         c.ctxt.Diag("bad shift $con\n%v", p)
3498                         break
3499                 }
3500
3501         case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
3502                 o1 = c.oprrr(p, p.As)
3503
3504                 r := int(p.Reg)
3505                 if r == 0 {
3506                         r = int(p.To.Reg)
3507                 }
3508                 o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
3509
3510         case 10: /* brk/hvc/.../svc [$con] */
3511                 o1 = c.opimm(p, p.As)
3512
3513                 if p.From.Type != obj.TYPE_NONE {
3514                         o1 |= uint32((p.From.Offset & 0xffff) << 5)
3515                 }
3516
3517         case 11: /* dword */
3518                 c.aclass(&p.To)
3519
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)
3525                         rel.Siz = 8
3526                         rel.Sym = p.To.Sym
3527                         rel.Add = p.To.Offset
3528                         rel.Type = objabi.R_ADDR
3529                         o2 = 0
3530                         o1 = o2
3531                 }
3532
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[:])
3537                 if num == 0 {
3538                         c.ctxt.Diag("invalid constant: %v", p)
3539                 }
3540                 o1 = os[0]
3541                 o2 = os[1]
3542                 o3 = os[2]
3543                 o4 = os[3]
3544
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)
3548                 }
3549                 if p.To.Reg == REG_RSP && isADDSop(p.As) {
3550                         c.ctxt.Diag("illegal destination register: %v\n", p)
3551                 }
3552                 o := uint32(0)
3553                 num := uint8(0)
3554                 cls := oclass(&p.From)
3555                 if isADDWop(p.As) {
3556                         if !cmp(C_LCON, cls) {
3557                                 c.ctxt.Diag("illegal combination: %v", p)
3558                         }
3559                         num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3560                 } else {
3561                         num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3562                 }
3563                 if num == 0 {
3564                         c.ctxt.Diag("invalid constant: %v", p)
3565                 }
3566                 rt := int(p.To.Reg)
3567                 if p.To.Type == obj.TYPE_NONE {
3568                         rt = REGZERO
3569                 }
3570                 r := int(p.Reg)
3571                 if r == 0 {
3572                         r = rt
3573                 }
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
3577                         o |= LSL0_64
3578                 } else {
3579                         o = c.oprrr(p, p.As)
3580                         o |= REGTMP & 31 << 16 /* shift is 0 */
3581                 }
3582
3583                 o |= uint32(r&31) << 5
3584                 o |= uint32(rt & 31)
3585
3586                 os[num] = o
3587                 o1 = os[0]
3588                 o2 = os[1]
3589                 o3 = os[2]
3590                 o4 = os[3]
3591                 o5 = os[4]
3592
3593         case 14: /* word */
3594                 if c.aclass(&p.To) == C_ADDR {
3595                         c.ctxt.Diag("address constant needs DWORD\n%v", p)
3596                 }
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)
3602
3603                         rel.Off = int32(c.pc)
3604                         rel.Siz = 4
3605                         rel.Sym = p.To.Sym
3606                         rel.Add = p.To.Offset
3607                         rel.Type = objabi.R_ADDR
3608                         o1 = 0
3609                 }
3610
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)
3613
3614                 rf := int(p.From.Reg)
3615                 rt := int(p.To.Reg)
3616                 var r int
3617                 var ra int
3618                 if p.From3Type() == obj.TYPE_REG {
3619                         r = int(p.GetFrom3().Reg)
3620                         ra = int(p.Reg)
3621                         if ra == 0 {
3622                                 ra = REGZERO
3623                         }
3624                 } else {
3625                         r = int(p.Reg)
3626                         if r == 0 {
3627                                 r = rt
3628                         }
3629                         ra = REGZERO
3630                 }
3631
3632                 o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
3633
3634         case 16: /* XremY R[,R],R -> XdivY; XmsubY */
3635                 o1 = c.oprrr(p, p.As)
3636
3637                 rf := int(p.From.Reg)
3638                 rt := int(p.To.Reg)
3639                 r := int(p.Reg)
3640                 if r == 0 {
3641                         r = rt
3642                 }
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)
3647
3648         case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
3649                 o1 = c.oprrr(p, p.As)
3650
3651                 rf := int(p.From.Reg)
3652                 rt := int(p.To.Reg)
3653                 r := int(p.Reg)
3654                 if p.To.Type == obj.TYPE_NONE {
3655                         rt = REGZERO
3656                 }
3657                 if r == 0 {
3658                         r = REGZERO
3659                 }
3660                 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
3661
3662         case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
3663                 o1 = c.oprrr(p, p.As)
3664
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)
3668                 } else {
3669                         cond -= SPOP_EQ
3670                 }
3671
3672                 r := int(p.Reg)
3673                 var rf int = r
3674                 if p.From3Type() == obj.TYPE_NONE {
3675                         /* CINC/CINV/CNEG or CSET/CSETM*/
3676                         if r == 0 {
3677                                 /* CSET/CSETM */
3678                                 rf = REGZERO
3679                                 r = rf
3680                         }
3681                         cond ^= 1
3682                 } else {
3683                         rf = int(p.GetFrom3().Reg) /* CSEL */
3684                 }
3685
3686                 rt := int(p.To.Reg)
3687                 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
3688
3689         case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
3690                 nzcv := int(p.To.Offset)
3691
3692                 cond := SpecialOperand(p.From.Offset)
3693                 if cond < SPOP_EQ || cond > SPOP_NV {
3694                         c.ctxt.Diag("invalid condition\n%v", p)
3695                 } else {
3696                         cond -= SPOP_EQ
3697                 }
3698                 var rf int
3699                 if p.GetFrom3().Type == obj.TYPE_REG {
3700                         o1 = c.oprrr(p, p.As)
3701                         rf = int(p.GetFrom3().Reg) /* Rm */
3702                 } else {
3703                         o1 = c.opirr(p, p.As)
3704                         rf = int(p.GetFrom3().Offset & 0x1F)
3705                 }
3706
3707                 o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
3708
3709         case 20: /* movT R,O(R) -> strT */
3710                 v := int32(c.regoff(&p.To))
3711                 sz := int32(1 << uint(movesize(p.As)))
3712
3713                 r := int(p.To.Reg)
3714                 if r == 0 {
3715                         r = int(o.param)
3716                 }
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))
3719                 } else {
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))
3722                 }
3723
3724         case 21: /* movT O(R),R -> ldrT */
3725                 v := int32(c.regoff(&p.From))
3726                 sz := int32(1 << uint(movesize(p.As)))
3727
3728                 r := int(p.From.Reg)
3729                 if r == 0 {
3730                         r = int(o.param)
3731                 }
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))
3734                 } else {
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))
3738                 }
3739
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)
3743                 }
3744
3745                 v := int32(p.From.Offset)
3746
3747                 if v < -256 || v > 255 {
3748                         c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3749                 }
3750                 o1 = c.opldr(p, p.As)
3751                 if o.scond == C_XPOST {
3752                         o1 |= 1 << 10
3753                 } else {
3754                         o1 |= 3 << 10
3755                 }
3756                 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
3757
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)
3761                 }
3762
3763                 v := int32(p.To.Offset)
3764
3765                 if v < -256 || v > 255 {
3766                         c.ctxt.Diag("offset out of range [-256,255]: %v", p)
3767                 }
3768                 o1 = c.opstr(p, p.As)
3769                 if o.scond == C_XPOST {
3770                         o1 |= 1 << 10
3771                 } else {
3772                         o1 |= 3 << 10
3773                 }
3774                 o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
3775
3776         case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
3777                 rf := int(p.From.Reg)
3778                 rt := int(p.To.Reg)
3779                 s := rf == REGSP || rt == REGSP
3780                 if p.As == AMVN || p.As == AMVNW {
3781                         if s {
3782                                 c.ctxt.Diag("illegal SP reference\n%v", p)
3783                         }
3784                         o1 = c.oprrr(p, p.As)
3785                         o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3786                 } else if s {
3787                         o1 = c.opirr(p, p.As)
3788                         o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
3789                 } else {
3790                         o1 = c.oprrr(p, p.As)
3791                         o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3792                 }
3793
3794         case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
3795                 o1 = c.oprrr(p, p.As)
3796
3797                 rf := int(p.From.Reg)
3798                 if rf == C_NONE {
3799                         rf = int(p.To.Reg)
3800                 }
3801                 rt := int(p.To.Reg)
3802                 o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
3803
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)
3807                 }
3808                 if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 ||
3809                         (p.From.Reg >= REG_LSL && p.From.Reg < REG_ARNG) {
3810                         amount := (p.From.Reg >> 5) & 7
3811                         if amount > 4 {
3812                                 c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
3813                         }
3814                         o1 = c.opxrrr(p, p.As, true)
3815                         o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Reg) /* includes reg, op, etc */
3816                 } else {
3817                         o1 = c.opxrrr(p, p.As, false)
3818                         o1 |= uint32(p.From.Reg&31) << 16
3819                 }
3820                 rt := int(p.To.Reg)
3821                 if p.To.Type == obj.TYPE_NONE {
3822                         rt = REGZERO
3823                 }
3824                 r := int(p.Reg)
3825                 if r == 0 {
3826                         r = rt
3827                 }
3828                 o1 |= (uint32(r&31) << 5) | uint32(rt&31)
3829
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)
3833                 }
3834                 o := uint32(0)
3835                 num := uint8(0)
3836                 cls := oclass(&p.From)
3837                 if isANDWop(p.As) {
3838                         if !cmp(C_LCON, cls) {
3839                                 c.ctxt.Diag("illegal combination: %v", p)
3840                         }
3841                         num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
3842                 } else {
3843                         num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
3844                 }
3845
3846                 if num == 0 {
3847                         c.ctxt.Diag("invalid constant: %v", p)
3848                 }
3849                 rt := int(p.To.Reg)
3850                 if p.To.Type == obj.TYPE_NONE {
3851                         rt = REGZERO
3852                 }
3853                 r := int(p.Reg)
3854                 if r == 0 {
3855                         r = rt
3856                 }
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)
3861
3862                 os[num] = o
3863                 o1 = os[0]
3864                 o2 = os[1]
3865                 o3 = os[2]
3866                 o4 = os[3]
3867                 o5 = os[4]
3868
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)
3875                         if p.As == AFMOVD {
3876                                 o1 |= 1<<31 | 1<<22 // 64-bit
3877                         }
3878                         if fc == C_REG || fc == C_ZREG {
3879                                 o1 |= 1 << 16 // FMOV Rx, Fy
3880                         }
3881                 } else {
3882                         o1 = c.oprrr(p, p.As)
3883                 }
3884                 o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
3885
3886         case 30: /* movT R,L(R) -> strT */
3887                 // if offset L can be split into hi+lo, and both fit into instructions, do
3888                 //      add $hi, R, Rtmp
3889                 //      str R, lo(Rtmp)
3890                 // otherwise, use constant pool
3891                 //      mov $L, Rtmp (from constant pool)
3892                 //      str R, (R+Rtmp)
3893                 s := movesize(o.as)
3894                 if s < 0 {
3895                         c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3896                 }
3897
3898                 r := int(p.To.Reg)
3899                 if r == 0 {
3900                         r = int(o.param)
3901                 }
3902
3903                 v := int32(c.regoff(&p.To))
3904                 var hi int32
3905                 if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3906                         // negative or unaligned offset, use constant pool
3907                         goto storeusepool
3908                 }
3909
3910                 hi = v - (v & (0xFFF << uint(s)))
3911                 if hi&0xFFF != 0 {
3912                         c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
3913                 }
3914                 if hi&^0xFFF000 != 0 {
3915                         // hi doesn't fit into an ADD instruction
3916                         goto storeusepool
3917                 }
3918
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))
3921                 break
3922
3923         storeusepool:
3924                 if r == REGTMP || p.From.Reg == REGTMP {
3925                         c.ctxt.Diag("REGTMP used in large offset store: %v", p)
3926                 }
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)
3929
3930         case 31: /* movT L(R), R -> ldrT */
3931                 // if offset L can be split into hi+lo, and both fit into instructions, do
3932                 //      add $hi, R, Rtmp
3933                 //      ldr lo(Rtmp), R
3934                 // otherwise, use constant pool
3935                 //      mov $L, Rtmp (from constant pool)
3936                 //      ldr (R+Rtmp), R
3937                 s := movesize(o.as)
3938                 if s < 0 {
3939                         c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
3940                 }
3941
3942                 r := int(p.From.Reg)
3943                 if r == 0 {
3944                         r = int(o.param)
3945                 }
3946
3947                 v := int32(c.regoff(&p.From))
3948                 var hi int32
3949                 if v < 0 || (v&((1<<uint(s))-1)) != 0 {
3950                         // negative or unaligned offset, use constant pool
3951                         goto loadusepool
3952                 }
3953
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)
3957                 }
3958                 if hi&^0xFFF000 != 0 {
3959                         // hi doesn't fit into an ADD instruction
3960                         goto loadusepool
3961                 }
3962
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))
3965                 break
3966
3967         loadusepool:
3968                 if r == REGTMP || p.From.Reg == REGTMP {
3969                         c.ctxt.Diag("REGTMP used in large offset load: %v", p)
3970                 }
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)
3973
3974         case 32: /* mov $con, R -> movz/movn */
3975                 o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
3976
3977         case 33: /* movk $uimm16 << pos */
3978                 o1 = c.opirr(p, p.As)
3979
3980                 d := p.From.Offset
3981                 if d == 0 {
3982                         c.ctxt.Diag("zero shifts cannot be handled correctly: %v", p)
3983                 }
3984                 s := movcon(d)
3985                 if s < 0 || s >= 4 {
3986                         c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
3987                 }
3988                 if (o1&S64) == 0 && s >= 2 {
3989                         c.ctxt.Diag("illegal bit position\n%v", p)
3990                 }
3991                 if ((uint64(d) >> uint(s*16)) >> 16) != 0 {
3992                         c.ctxt.Diag("requires uimm16\n%v", p)
3993                 }
3994                 rt := int(p.To.Reg)
3995
3996                 o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
3997
3998         case 34: /* mov $lacon,R */
3999                 o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
4000
4001                 if o1 == 0 {
4002                         break
4003                 }
4004                 o2 = c.opxrrr(p, AADD, false)
4005                 o2 |= REGTMP & 31 << 16
4006                 o2 |= LSL0_64
4007                 r := int(p.From.Reg)
4008                 if r == 0 {
4009                         r = int(o.param)
4010                 }
4011                 o2 |= uint32(r&31) << 5
4012                 o2 |= uint32(p.To.Reg & 31)
4013
4014         case 35: /* mov SPR,R -> mrs */
4015                 o1 = c.oprrr(p, AMRS)
4016
4017                 // SysRegEnc function returns the system register encoding and accessFlags.
4018                 _, v, accessFlags := SysRegEnc(p.From.Reg)
4019                 if v == 0 {
4020                         c.ctxt.Diag("illegal system register:\n%v", p)
4021                 }
4022                 if (o1 & (v &^ (3 << 19))) != 0 {
4023                         c.ctxt.Diag("MRS register value overlap\n%v", p)
4024                 }
4025                 if accessFlags&SR_READ == 0 {
4026                         c.ctxt.Diag("system register is not readable: %v", p)
4027                 }
4028
4029                 o1 |= v
4030                 o1 |= uint32(p.To.Reg & 31)
4031
4032         case 36: /* mov R,SPR */
4033                 o1 = c.oprrr(p, AMSR)
4034
4035                 // SysRegEnc function returns the system register encoding and accessFlags.
4036                 _, v, accessFlags := SysRegEnc(p.To.Reg)
4037                 if v == 0 {
4038                         c.ctxt.Diag("illegal system register:\n%v", p)
4039                 }
4040                 if (o1 & (v &^ (3 << 19))) != 0 {
4041                         c.ctxt.Diag("MSR register value overlap\n%v", p)
4042                 }
4043                 if accessFlags&SR_WRITE == 0 {
4044                         c.ctxt.Diag("system register is not writable: %v", p)
4045                 }
4046
4047                 o1 |= v
4048                 o1 |= uint32(p.From.Reg & 31)
4049
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)
4053                 }
4054                 o1 = c.opirr(p, AMSR)
4055                 o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
4056                 v := uint32(0)
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 {
4063                                 if pf.opd == opd {
4064                                         v = pf.enc
4065                                         break
4066                                 }
4067                         }
4068                 }
4069
4070                 if v == 0 {
4071                         c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
4072                 }
4073                 o1 |= v
4074
4075         case 38: /* clrex [$imm] */
4076                 o1 = c.opimm(p, p.As)
4077
4078                 if p.To.Type == obj.TYPE_NONE {
4079                         o1 |= 0xF << 8
4080                 } else {
4081                         o1 |= uint32((p.To.Offset & 0xF) << 8)
4082                 }
4083
4084         case 39: /* cbz R, rel */
4085                 o1 = c.opirr(p, p.As)
4086
4087                 o1 |= uint32(p.From.Reg & 31)
4088                 o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
4089
4090         case 40: /* tbz */
4091                 o1 = c.opirr(p, p.As)
4092
4093                 v := int32(p.From.Offset)
4094                 if v < 0 || v > 63 {
4095                         c.ctxt.Diag("illegal bit number\n%v", p)
4096                 }
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)
4100
4101         case 41: /* eret, nop, others with no operands */
4102                 o1 = c.op0(p, p.As)
4103
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))
4106
4107         case 43: /* bfm aliases */
4108                 r := int(p.From.Offset)
4109                 s := int(p.GetFrom3().Offset)
4110                 rf := int(p.Reg)
4111                 rt := int(p.To.Reg)
4112                 if rf == 0 {
4113                         rf = rt
4114                 }
4115                 switch p.As {
4116                 case ABFI:
4117                         if r != 0 {
4118                                 r = 64 - r
4119                         }
4120                         o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
4121
4122                 case ABFIW:
4123                         if r != 0 {
4124                                 r = 32 - r
4125                         }
4126                         o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
4127
4128                 case ABFXIL:
4129                         o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
4130
4131                 case ABFXILW:
4132                         o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
4133
4134                 case ASBFIZ:
4135                         if r != 0 {
4136                                 r = 64 - r
4137                         }
4138                         o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
4139
4140                 case ASBFIZW:
4141                         if r != 0 {
4142                                 r = 32 - r
4143                         }
4144                         o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
4145
4146                 case ASBFX:
4147                         o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
4148
4149                 case ASBFXW:
4150                         o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
4151
4152                 case AUBFIZ:
4153                         if r != 0 {
4154                                 r = 64 - r
4155                         }
4156                         o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
4157
4158                 case AUBFIZW:
4159                         if r != 0 {
4160                                 r = 32 - r
4161                         }
4162                         o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
4163
4164                 case AUBFX:
4165                         o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
4166
4167                 case AUBFXW:
4168                         o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
4169
4170                 default:
4171                         c.ctxt.Diag("bad bfm alias\n%v", p)
4172                         break
4173                 }
4174
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))
4177
4178         case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
4179                 rf := int(p.From.Reg)
4180
4181                 rt := int(p.To.Reg)
4182                 as := p.As
4183                 if rf == REGZERO {
4184                         as = AMOVWU /* clearer in disassembly */
4185                 }
4186                 switch as {
4187                 case AMOVB, ASXTB:
4188                         o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
4189
4190                 case AMOVH, ASXTH:
4191                         o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
4192
4193                 case AMOVW, ASXTW:
4194                         o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
4195
4196                 case AMOVBU, AUXTB:
4197                         o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
4198
4199                 case AMOVHU, AUXTH:
4200                         o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
4201
4202                 case AMOVWU:
4203                         o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
4204
4205                 case AUXTW:
4206                         o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
4207
4208                 case ASXTBW:
4209                         o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
4210
4211                 case ASXTHW:
4212                         o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
4213
4214                 case AUXTBW:
4215                         o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
4216
4217                 case AUXTHW:
4218                         o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
4219
4220                 default:
4221                         c.ctxt.Diag("bad sxt %v", as)
4222                         break
4223                 }
4224
4225         case 46: /* cls */
4226                 o1 = c.opbit(p, p.As)
4227
4228                 o1 |= uint32(p.From.Reg&31) << 5
4229                 o1 |= uint32(p.To.Reg & 31)
4230
4231         case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt
4232                 rs := p.From.Reg
4233                 rt := p.RegTo2
4234                 rb := p.To.Reg
4235
4236                 // rt can't be sp.
4237                 if rt == REG_RSP {
4238                         c.ctxt.Diag("illegal destination register: %v\n", p)
4239                 }
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)
4244                         }
4245                         o1 |= enc
4246                 } else if enc, ok := atomicSWP[p.As]; ok {
4247                         o1 |= enc
4248                 } else {
4249                         c.ctxt.Diag("invalid atomic instructions: %v\n", p)
4250                 }
4251                 o1 |= uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
4252
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)
4257                 if op&Sbit != 0 {
4258                         c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
4259                 }
4260                 rt := int(p.To.Reg)
4261                 r := int(p.Reg)
4262                 if r == 0 {
4263                         r = rt
4264                 }
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)
4267
4268         case 50: /* sys/sysl */
4269                 o1 = c.opirr(p, p.As)
4270
4271                 if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
4272                         c.ctxt.Diag("illegal SYS argument\n%v", p)
4273                 }
4274                 o1 |= uint32(p.From.Offset)
4275                 if p.To.Type == obj.TYPE_REG {
4276                         o1 |= uint32(p.To.Reg & 31)
4277                 } else {
4278                         o1 |= 0x1F
4279                 }
4280
4281         case 51: /* dmb */
4282                 o1 = c.opirr(p, p.As)
4283
4284                 if p.From.Type == obj.TYPE_CONST {
4285                         o1 |= uint32((p.From.Offset & 0xF) << 8)
4286                 }
4287
4288         case 52: /* hint */
4289                 o1 = c.opirr(p, p.As)
4290
4291                 o1 |= uint32((p.From.Offset & 0x7F) << 5)
4292
4293         case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
4294                 a := p.As
4295                 rt := int(p.To.Reg)
4296                 if p.To.Type == obj.TYPE_NONE {
4297                         rt = REGZERO
4298                 }
4299                 r := int(p.Reg)
4300                 if r == 0 {
4301                         r = rt
4302                 }
4303                 if r == REG_RSP {
4304                         c.ctxt.Diag("illegal source register: %v", p)
4305                         break
4306                 }
4307                 mode := 64
4308                 v := uint64(p.From.Offset)
4309                 switch p.As {
4310                 case AANDW, AORRW, AEORW, AANDSW, ATSTW:
4311                         mode = 32
4312                 case ABIC, AORN, AEON, ABICS:
4313                         v = ^v
4314                 case ABICW, AORNW, AEONW, ABICSW:
4315                         v = ^v
4316                         mode = 32
4317                 }
4318                 o1 = c.opirr(p, a)
4319                 o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
4320
4321         case 54: /* floating point arith */
4322                 o1 = c.oprrr(p, p.As)
4323                 rf := int(p.From.Reg)
4324                 rt := int(p.To.Reg)
4325                 r := int(p.Reg)
4326                 if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
4327                         r = rf
4328                         rf = 0
4329                 } else if r == 0 {
4330                         r = rt
4331                 }
4332                 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4333
4334         case 55: /* floating-point constant */
4335                 var rf int
4336                 o1 = 0xf<<25 | 1<<21 | 1<<12
4337                 rf = c.chipfloat7(p.From.Val.(float64))
4338                 if rf < 0 {
4339                         c.ctxt.Diag("invalid floating-point immediate\n%v", p)
4340                 }
4341                 if p.As == AFMOVD {
4342                         o1 |= 1 << 22
4343                 }
4344                 o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
4345
4346         case 56: /* floating point compare */
4347                 o1 = c.oprrr(p, p.As)
4348
4349                 var rf int
4350                 if p.From.Type == obj.TYPE_FCONST {
4351                         o1 |= 8 /* zero */
4352                         rf = 0
4353                 } else {
4354                         rf = int(p.From.Reg)
4355                 }
4356                 rt := int(p.Reg)
4357                 o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
4358
4359         case 57: /* floating point conditional compare */
4360                 o1 = c.oprrr(p, p.As)
4361
4362                 cond := SpecialOperand(p.From.Offset)
4363                 if cond < SPOP_EQ || cond > SPOP_NV {
4364                         c.ctxt.Diag("invalid condition\n%v", p)
4365                 } else {
4366                         cond -= SPOP_EQ
4367                 }
4368
4369                 nzcv := int(p.To.Offset)
4370                 if nzcv&^0xF != 0 {
4371                         c.ctxt.Diag("implausible condition\n%v", p)
4372                 }
4373                 rf := int(p.Reg)
4374                 if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
4375                         c.ctxt.Diag("illegal FCCMP\n%v", p)
4376                         break
4377                 }
4378                 rt := int(p.GetFrom3().Reg)
4379                 o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
4380
4381         case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
4382                 o1 = c.opload(p, p.As)
4383
4384                 o1 |= 0x1F << 16
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)
4389                         }
4390                         o1 |= uint32(p.To.Offset&31) << 10
4391                 } else {
4392                         o1 |= 0x1F << 10
4393                 }
4394                 o1 |= uint32(p.To.Reg & 31)
4395
4396         case 59: /* stxr/stlxr/stxp/stlxp */
4397                 s := p.RegTo2
4398                 n := p.To.Reg
4399                 t := p.From.Reg
4400                 if isSTLXRop(p.As) {
4401                         if s == t || (s == n && n != REGSP) {
4402                                 c.ctxt.Diag("constrained unpredictable behavior: %v", p)
4403                         }
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)
4408                         }
4409                 }
4410                 if s == REG_RSP {
4411                         c.ctxt.Diag("illegal destination register: %v\n", p)
4412                 }
4413                 o1 = c.opstore(p, p.As)
4414
4415                 if p.RegTo2 != obj.REG_NONE {
4416                         o1 |= uint32(p.RegTo2&31) << 16
4417                 } else {
4418                         o1 |= 0x1F << 16
4419                 }
4420                 if isSTXPop(p.As) {
4421                         o1 |= uint32(p.From.Offset&31) << 10
4422                 }
4423                 o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
4424
4425         case 60: /* adrp label,r */
4426                 d := c.brdist(p, 12, 21, 0)
4427
4428                 o1 = ADR(1, uint32(d), uint32(p.To.Reg))
4429
4430         case 61: /* adr label, r */
4431                 d := c.brdist(p, 0, 21, 0)
4432
4433                 o1 = ADR(0, uint32(d), uint32(p.To.Reg))
4434
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)
4438                 }
4439                 if p.To.Reg == REG_RSP && isADDSop(p.As) {
4440                         c.ctxt.Diag("illegal destination register: %v\n", p)
4441                 }
4442                 lsl0 := LSL0_64
4443                 if isADDWop(p.As) || isANDWop(p.As) {
4444                         o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
4445                         lsl0 = LSL0_32
4446                 } else {
4447                         o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
4448                 }
4449
4450                 rt := int(p.To.Reg)
4451                 if p.To.Type == obj.TYPE_NONE {
4452                         rt = REGZERO
4453                 }
4454                 r := int(p.Reg)
4455                 if r == 0 {
4456                         r = rt
4457                 }
4458                 if p.To.Reg == REGSP || r == REGSP {
4459                         o2 = c.opxrrr(p, p.As, false)
4460                         o2 |= REGTMP & 31 << 16
4461                         o2 |= uint32(lsl0)
4462                 } else {
4463                         o2 = c.oprrr(p, p.As)
4464                         o2 |= REGTMP & 31 << 16 /* shift is 0 */
4465                 }
4466                 o2 |= uint32(r&31) << 5
4467                 o2 |= uint32(rt & 31)
4468
4469         /* reloc ops */
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)
4473                 }
4474                 o1 = ADR(1, 0, REGTMP)
4475                 rel := obj.Addrel(c.cursym)
4476                 rel.Off = int32(c.pc)
4477                 rel.Siz = 8
4478                 rel.Sym = p.To.Sym
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
4485                         break
4486                 }
4487                 o2 = c.olsr12u(p, int32(c.opstr(p, p.As)), 0, REGTMP, int(p.From.Reg))
4488                 rel.Type = c.addrRelocType(p)
4489
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)
4494                 rel.Siz = 8
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
4502                         break
4503                 }
4504                 o2 = c.olsr12u(p, int32(c.opldr(p, p.As)), 0, REGTMP, int(p.To.Reg))
4505                 rel.Type = c.addrRelocType(p)
4506
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 {
4511                         r = int(o.param)
4512                 }
4513                 if r == obj.REG_NONE {
4514                         c.ctxt.Diag("invalid ldp source: %v\n", p)
4515                 }
4516                 o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4517
4518         case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
4519                 r := int(p.To.Reg)
4520                 if r == obj.REG_NONE {
4521                         r = int(o.param)
4522                 }
4523                 if r == obj.REG_NONE {
4524                         c.ctxt.Diag("invalid stp destination: %v\n", p)
4525                 }
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)
4528
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.
4532                 if p.As == AMOVW {
4533                         c.ctxt.Diag("invalid load of 32-bit address: %v", p)
4534                 }
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)
4539                 rel.Siz = 8
4540                 rel.Sym = p.From.Sym
4541                 rel.Add = p.From.Offset
4542                 rel.Type = objabi.R_ADDRARM64
4543
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)
4549                 rel.Siz = 4
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")
4554                 }
4555
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)
4561                 rel.Siz = 8
4562                 rel.Sym = p.From.Sym
4563                 rel.Add = 0
4564                 rel.Type = objabi.R_ARM64_TLS_IE
4565                 if p.From.Offset != 0 {
4566                         c.ctxt.Diag("invalid offset on MOVW $tlsvar")
4567                 }
4568
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)
4574                 rel.Siz = 8
4575                 rel.Sym = p.From.Sym
4576                 rel.Add = 0
4577                 rel.Type = objabi.R_ARM64_GOTPCREL
4578
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)
4585                         break
4586                 }
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)
4591
4592                 Q := 0
4593                 size := 0
4594                 switch af {
4595                 case ARNG_16B:
4596                         Q = 1
4597                         size = 0
4598                 case ARNG_2D:
4599                         Q = 1
4600                         size = 3
4601                 case ARNG_2S:
4602                         Q = 0
4603                         size = 2
4604                 case ARNG_4H:
4605                         Q = 0
4606                         size = 1
4607                 case ARNG_4S:
4608                         Q = 1
4609                         size = 2
4610                 case ARNG_8B:
4611                         Q = 0
4612                         size = 0
4613                 case ARNG_8H:
4614                         Q = 1
4615                         size = 1
4616                 default:
4617                         c.ctxt.Diag("invalid arrangement: %v", p)
4618                 }
4619
4620                 switch p.As {
4621                 case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
4622                         if af != ARNG_16B && af != ARNG_8B {
4623                                 c.ctxt.Diag("invalid arrangement: %v", p)
4624                         }
4625                 case AVFMLA, AVFMLS:
4626                         if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
4627                                 c.ctxt.Diag("invalid arrangement: %v", p)
4628                         }
4629                 case AVUMAX, AVUMIN:
4630                         if af == ARNG_2D {
4631                                 c.ctxt.Diag("invalid arrangement: %v", p)
4632                         }
4633                 }
4634                 switch p.As {
4635                 case AVAND, AVEOR:
4636                         size = 0
4637                 case AVBSL:
4638                         size = 1
4639                 case AVORR, AVBIT, AVBIF:
4640                         size = 2
4641                 case AVFMLA, AVFMLS:
4642                         if af == ARNG_2D {
4643                                 size = 1
4644                         } else {
4645                                 size = 0
4646                         }
4647                 case AVRAX1:
4648                         if af != ARNG_2D {
4649                                 c.ctxt.Diag("invalid arrangement: %v", p)
4650                         }
4651                         size = 0
4652                         Q = 0
4653                 }
4654
4655                 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
4656
4657         case 73: /* vmov V.<T>[index], R */
4658                 rf := int(p.From.Reg)
4659                 rt := int(p.To.Reg)
4660                 imm5 := 0
4661                 o1 = 7<<25 | 0xf<<10
4662                 index := int(p.From.Index)
4663                 switch (p.From.Reg >> 5) & 15 {
4664                 case ARNG_B:
4665                         c.checkindex(p, index, 15)
4666                         imm5 |= 1
4667                         imm5 |= index << 1
4668                 case ARNG_H:
4669                         c.checkindex(p, index, 7)
4670                         imm5 |= 2
4671                         imm5 |= index << 2
4672                 case ARNG_S:
4673                         c.checkindex(p, index, 3)
4674                         imm5 |= 4
4675                         imm5 |= index << 3
4676                 case ARNG_D:
4677                         c.checkindex(p, index, 1)
4678                         imm5 |= 8
4679                         imm5 |= index << 4
4680                         o1 |= 1 << 30
4681                 default:
4682                         c.ctxt.Diag("invalid arrangement: %v", p)
4683                 }
4684                 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4685
4686         case 74:
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 {
4691                         r = int(o.param)
4692                 }
4693                 if r == obj.REG_NONE {
4694                         c.ctxt.Diag("invalid ldp source: %v", p)
4695                 }
4696                 v := int32(c.regoff(&p.From))
4697
4698                 if v > 0 {
4699                         if v > 4095 {
4700                                 c.ctxt.Diag("offset out of range: %v", p)
4701                         }
4702                         o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4703                 }
4704                 if v < 0 {
4705                         if v < -4095 {
4706                                 c.ctxt.Diag("offset out of range: %v", p)
4707                         }
4708                         o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4709                 }
4710                 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
4711
4712         case 75:
4713                 //      mov $L, Rtmp (from constant pool)
4714                 //      add Rtmp, R, Rtmp
4715                 //      ldp (Rtmp), (R1, R2)
4716                 r := int(p.From.Reg)
4717                 if r == REGTMP {
4718                         c.ctxt.Diag("REGTMP used in large offset load: %v", p)
4719                 }
4720                 if r == obj.REG_NONE {
4721                         r = int(o.param)
4722                 }
4723                 if r == obj.REG_NONE {
4724                         c.ctxt.Diag("invalid ldp source: %v", p)
4725                 }
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)
4732
4733         case 76:
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)
4738                 }
4739                 r := int(p.To.Reg)
4740                 if r == obj.REG_NONE {
4741                         r = int(o.param)
4742                 }
4743                 if r == obj.REG_NONE {
4744                         c.ctxt.Diag("invalid stp destination: %v", p)
4745                 }
4746                 v := int32(c.regoff(&p.To))
4747                 if v > 0 {
4748                         if v > 4095 {
4749                                 c.ctxt.Diag("offset out of range: %v", p)
4750                         }
4751                         o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
4752                 }
4753                 if v < 0 {
4754                         if v < -4095 {
4755                                 c.ctxt.Diag("offset out of range: %v", p)
4756                         }
4757                         o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
4758                 }
4759                 o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
4760
4761         case 77:
4762                 //      mov $L, Rtmp (from constant pool)
4763                 //      add Rtmp, R, Rtmp
4764                 //      stp (R1, R2), (Rtmp)
4765                 r := int(p.To.Reg)
4766                 if r == REGTMP || p.From.Reg == REGTMP || p.From.Offset == REGTMP {
4767                         c.ctxt.Diag("REGTMP used in large offset store: %v", p)
4768                 }
4769                 if r == obj.REG_NONE {
4770                         r = int(o.param)
4771                 }
4772                 if r == obj.REG_NONE {
4773                         c.ctxt.Diag("invalid stp destination: %v", p)
4774                 }
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)
4781
4782         case 78: /* vmov R, V.<T>[index] */
4783                 rf := int(p.From.Reg)
4784                 rt := int(p.To.Reg)
4785                 imm5 := 0
4786                 o1 = 1<<30 | 7<<25 | 7<<10
4787                 index := int(p.To.Index)
4788                 switch (p.To.Reg >> 5) & 15 {
4789                 case ARNG_B:
4790                         c.checkindex(p, index, 15)
4791                         imm5 |= 1
4792                         imm5 |= index << 1
4793                 case ARNG_H:
4794                         c.checkindex(p, index, 7)
4795                         imm5 |= 2
4796                         imm5 |= index << 2
4797                 case ARNG_S:
4798                         c.checkindex(p, index, 3)
4799                         imm5 |= 4
4800                         imm5 |= index << 3
4801                 case ARNG_D:
4802                         c.checkindex(p, index, 1)
4803                         imm5 |= 8
4804                         imm5 |= index << 4
4805                 default:
4806                         c.ctxt.Diag("invalid arrangement: %v", p)
4807                 }
4808                 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4809
4810         case 79: /* vdup Vn.<T>[index], Vd.<T> */
4811                 rf := int(p.From.Reg)
4812                 rt := int(p.To.Reg)
4813                 o1 = 7<<25 | 1<<10
4814                 var imm5, Q int
4815                 index := int(p.From.Index)
4816                 switch (p.To.Reg >> 5) & 15 {
4817                 case ARNG_16B:
4818                         c.checkindex(p, index, 15)
4819                         Q = 1
4820                         imm5 = 1
4821                         imm5 |= index << 1
4822                 case ARNG_2D:
4823                         c.checkindex(p, index, 1)
4824                         Q = 1
4825                         imm5 = 8
4826                         imm5 |= index << 4
4827                 case ARNG_2S:
4828                         c.checkindex(p, index, 3)
4829                         Q = 0
4830                         imm5 = 4
4831                         imm5 |= index << 3
4832                 case ARNG_4H:
4833                         c.checkindex(p, index, 7)
4834                         Q = 0
4835                         imm5 = 2
4836                         imm5 |= index << 2
4837                 case ARNG_4S:
4838                         c.checkindex(p, index, 3)
4839                         Q = 1
4840                         imm5 = 4
4841                         imm5 |= index << 3
4842                 case ARNG_8B:
4843                         c.checkindex(p, index, 15)
4844                         Q = 0
4845                         imm5 = 1
4846                         imm5 |= index << 1
4847                 case ARNG_8H:
4848                         c.checkindex(p, index, 7)
4849                         Q = 1
4850                         imm5 = 2
4851                         imm5 |= index << 2
4852                 default:
4853                         c.ctxt.Diag("invalid arrangement: %v", p)
4854                 }
4855                 o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
4856                 o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4857
4858         case 80: /* vmov/vdup V.<T>[index], Vn */
4859                 rf := int(p.From.Reg)
4860                 rt := int(p.To.Reg)
4861                 imm5 := 0
4862                 index := int(p.From.Index)
4863                 switch p.As {
4864                 case AVMOV, AVDUP:
4865                         o1 = 1<<30 | 15<<25 | 1<<10
4866                         switch (p.From.Reg >> 5) & 15 {
4867                         case ARNG_B:
4868                                 c.checkindex(p, index, 15)
4869                                 imm5 |= 1
4870                                 imm5 |= index << 1
4871                         case ARNG_H:
4872                                 c.checkindex(p, index, 7)
4873                                 imm5 |= 2
4874                                 imm5 |= index << 2
4875                         case ARNG_S:
4876                                 c.checkindex(p, index, 3)
4877                                 imm5 |= 4
4878                                 imm5 |= index << 3
4879                         case ARNG_D:
4880                                 c.checkindex(p, index, 1)
4881                                 imm5 |= 8
4882                                 imm5 |= index << 4
4883                         default:
4884                                 c.ctxt.Diag("invalid arrangement: %v", p)
4885                         }
4886                 default:
4887                         c.ctxt.Diag("unsupported op %v", p.As)
4888                 }
4889                 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
4890
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 {
4896                         o1 |= 1 << 23
4897                         if p.From.Index == 0 {
4898                                 // immediate offset variant
4899                                 o1 |= 0x1f << 16
4900                         } else {
4901                                 // register offset variant
4902                                 if isRegShiftOrExt(&p.From) {
4903                                         c.ctxt.Diag("invalid extended register op: %v\n", p)
4904                                 }
4905                                 o1 |= uint32(p.From.Index&0x1f) << 16
4906                         }
4907                 }
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
4913
4914         case 82: /* vmov/vdup Rn, Vd.<T> */
4915                 rf := int(p.From.Reg)
4916                 rt := int(p.To.Reg)
4917                 o1 = 7<<25 | 3<<10
4918                 var imm5, Q uint32
4919                 switch (p.To.Reg >> 5) & 15 {
4920                 case ARNG_16B:
4921                         Q = 1
4922                         imm5 = 1
4923                 case ARNG_2D:
4924                         Q = 1
4925                         imm5 = 8
4926                 case ARNG_2S:
4927                         Q = 0
4928                         imm5 = 4
4929                 case ARNG_4H:
4930                         Q = 0
4931                         imm5 = 2
4932                 case ARNG_4S:
4933                         Q = 1
4934                         imm5 = 4
4935                 case ARNG_8B:
4936                         Q = 0
4937                         imm5 = 1
4938                 case ARNG_8H:
4939                         Q = 1
4940                         imm5 = 2
4941                 default:
4942                         c.ctxt.Diag("invalid arrangement: %v\n", p)
4943                 }
4944                 o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
4945                 o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
4946
4947         case 83: /* vmov Vn.<T>, Vd.<T> */
4948                 af := int((p.From.Reg >> 5) & 15)
4949                 at := int((p.To.Reg >> 5) & 15)
4950                 if af != at {
4951                         c.ctxt.Diag("invalid arrangement: %v\n", p)
4952                 }
4953                 o1 = c.oprrr(p, p.As)
4954                 rf := int((p.From.Reg) & 31)
4955                 rt := int((p.To.Reg) & 31)
4956
4957                 var Q, size uint32
4958                 switch af {
4959                 case ARNG_8B:
4960                         Q = 0
4961                         size = 0
4962                 case ARNG_16B:
4963                         Q = 1
4964                         size = 0
4965                 case ARNG_4H:
4966                         Q = 0
4967                         size = 1
4968                 case ARNG_8H:
4969                         Q = 1
4970                         size = 1
4971                 case ARNG_2S:
4972                         Q = 0
4973                         size = 2
4974                 case ARNG_4S:
4975                         Q = 1
4976                         size = 2
4977                 default:
4978                         c.ctxt.Diag("invalid arrangement: %v\n", p)
4979                 }
4980
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)
4983                 }
4984
4985                 if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
4986                         c.ctxt.Diag("invalid arrangement: %v", p)
4987                 }
4988
4989                 if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
4990                         c.ctxt.Diag("invalid arrangement: %v", p)
4991                 }
4992
4993                 if p.As == AVMOV {
4994                         o1 |= uint32(rf&31) << 16
4995                 }
4996
4997                 if p.As == AVRBIT {
4998                         size = 1
4999                 }
5000
5001                 o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
5002
5003         case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
5004                 c.checkoffset(p, p.As)
5005                 r := int(p.To.Reg)
5006                 o1 = 3 << 26
5007                 if o.scond == C_XPOST {
5008                         o1 |= 1 << 23
5009                         if p.To.Index == 0 {
5010                                 // immediate offset variant
5011                                 o1 |= 0x1f << 16
5012                         } else {
5013                                 // register offset variant
5014                                 if isRegShiftOrExt(&p.To) {
5015                                         c.ctxt.Diag("invalid extended register: %v\n", p)
5016                                 }
5017                                 o1 |= uint32(p.To.Index&31) << 16
5018                         }
5019                 }
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
5025
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)
5031                 Q := 0
5032                 size := 0
5033                 switch af {
5034                 case ARNG_8B:
5035                         Q = 0
5036                         size = 0
5037                 case ARNG_16B:
5038                         Q = 1
5039                         size = 0
5040                 case ARNG_4H:
5041                         Q = 0
5042                         size = 1
5043                 case ARNG_8H:
5044                         Q = 1
5045                         size = 1
5046                 case ARNG_4S:
5047                         Q = 1
5048                         size = 2
5049                 default:
5050                         c.ctxt.Diag("invalid arrangement: %v\n", p)
5051                 }
5052                 o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
5053
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)
5059                 }
5060                 rt := int((p.To.Reg) & 31)
5061                 Q := 0
5062                 switch at {
5063                 case ARNG_8B:
5064                         Q = 0
5065                 case ARNG_16B:
5066                         Q = 1
5067                 default:
5068                         c.ctxt.Diag("invalid arrangement: %v\n", p)
5069                 }
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)
5072
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)
5076                 }
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)
5081                 rel.Siz = 8
5082                 rel.Sym = p.To.Sym
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)
5086
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)
5092                 rel.Siz = 8
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)
5097
5098         case 89: /* vadd/vsub Vm, Vn, Vd */
5099                 switch p.As {
5100                 case AVADD:
5101                         o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5102
5103                 case AVSUB:
5104                         o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
5105
5106                 default:
5107                         c.ctxt.Diag("bad opcode: %v\n", p)
5108                         break
5109                 }
5110
5111                 rf := int(p.From.Reg)
5112                 rt := int(p.To.Reg)
5113                 r := int(p.Reg)
5114                 if r == 0 {
5115                         r = rt
5116                 }
5117                 o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
5118
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
5123         // exception.
5124         case 90:
5125                 o1 = 0xbea71700
5126
5127         case 91: /* prfm imm(Rn), <prfop | $imm5> */
5128                 imm := uint32(p.From.Offset)
5129                 r := p.From.Reg
5130                 var v uint32
5131                 var ok bool
5132                 if p.To.Type == obj.TYPE_CONST {
5133                         v = uint32(p.To.Offset)
5134                         ok = v <= 31
5135                 } else {
5136                         v, ok = prfopfield[SpecialOperand(p.To.Offset)]
5137                 }
5138                 if !ok {
5139                         c.ctxt.Diag("illegal prefetch operation:\n%v", p)
5140                 }
5141
5142                 o1 = c.opirr(p, p.As)
5143                 o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
5144
5145         case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
5146                 rf := int(p.From.Reg)
5147                 rt := int(p.To.Reg)
5148                 imm4 := 0
5149                 imm5 := 0
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)
5155                 }
5156                 switch (p.To.Reg >> 5) & 15 {
5157                 case ARNG_B:
5158                         c.checkindex(p, index1, 15)
5159                         c.checkindex(p, index2, 15)
5160                         imm5 |= 1
5161                         imm5 |= index1 << 1
5162                         imm4 |= index2
5163                 case ARNG_H:
5164                         c.checkindex(p, index1, 7)
5165                         c.checkindex(p, index2, 7)
5166                         imm5 |= 2
5167                         imm5 |= index1 << 2
5168                         imm4 |= index2 << 1
5169                 case ARNG_S:
5170                         c.checkindex(p, index1, 3)
5171                         c.checkindex(p, index2, 3)
5172                         imm5 |= 4
5173                         imm5 |= index1 << 3
5174                         imm4 |= index2 << 2
5175                 case ARNG_D:
5176                         c.checkindex(p, index1, 1)
5177                         c.checkindex(p, index2, 1)
5178                         imm5 |= 8
5179                         imm5 |= index1 << 4
5180                         imm4 |= index2 << 3
5181                 default:
5182                         c.ctxt.Diag("invalid arrangement: %v", p)
5183                 }
5184                 o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5185
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)
5190                 if af != a {
5191                         c.ctxt.Diag("invalid arrangement: %v", p)
5192                 }
5193
5194                 var Q, size uint32
5195                 if p.As == AVPMULL2 {
5196                         Q = 1
5197                 }
5198                 switch pack(Q, at, af) {
5199                 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5200                         size = 0
5201                 case pack(0, ARNG_1Q, ARNG_1D), pack(1, ARNG_1Q, ARNG_2D):
5202                         size = 3
5203                 default:
5204                         c.ctxt.Diag("operand mismatch: %v\n", p)
5205                 }
5206
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)
5212
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)
5218
5219                 if af != a || af != at {
5220                         c.ctxt.Diag("invalid arrangement: %v", p)
5221                         break
5222                 }
5223
5224                 var Q uint32
5225                 var b int
5226                 if af == ARNG_8B {
5227                         Q = 0
5228                         b = 7
5229                 } else if af == ARNG_16B {
5230                         Q = 1
5231                         b = 15
5232                 } else {
5233                         c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
5234                         break
5235                 }
5236
5237                 if index < 0 || index > b {
5238                         c.ctxt.Diag("illegal offset: %v", p)
5239                 }
5240
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)
5245
5246                 o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
5247
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)
5252
5253                 if af != at {
5254                         c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5255                 }
5256
5257                 var Q uint32
5258                 var imax, esize int
5259
5260                 switch af {
5261                 case ARNG_8B, ARNG_4H, ARNG_2S:
5262                         Q = 0
5263                 case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
5264                         Q = 1
5265                 default:
5266                         c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
5267                 }
5268
5269                 switch af {
5270                 case ARNG_8B, ARNG_16B:
5271                         imax = 15
5272                         esize = 8
5273                 case ARNG_4H, ARNG_8H:
5274                         imax = 31
5275                         esize = 16
5276                 case ARNG_2S, ARNG_4S:
5277                         imax = 63
5278                         esize = 32
5279                 case ARNG_2D:
5280                         imax = 127
5281                         esize = 64
5282                 }
5283
5284                 imm := 0
5285                 switch p.As {
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)
5290                         }
5291                 case AVSHL, AVSLI:
5292                         imm = esize + shift
5293                         if imm > imax {
5294                                 c.ctxt.Diag("shift out of range: %v", p)
5295                         }
5296                 default:
5297                         c.ctxt.Diag("invalid instruction %v\n", p)
5298                 }
5299
5300                 o1 = c.opirr(p, p.As)
5301                 rt := int((p.To.Reg) & 31)
5302                 rf := int((p.Reg) & 31)
5303
5304                 o1 |= ((Q & 1) << 30) | (uint32(imm&0x7f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
5305
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))
5313
5314                 if o.scond == C_XPOST {
5315                         if (p.To.Index != 0) && (offset != 0) {
5316                                 c.ctxt.Diag("invalid offset: %v", p)
5317                         }
5318                         if p.To.Index == 0 && offset == 0 {
5319                                 c.ctxt.Diag("invalid offset: %v", p)
5320                         }
5321                 }
5322
5323                 if offset != 0 {
5324                         r = 31
5325                 }
5326
5327                 var Q, S, size int
5328                 var opcode uint32
5329                 switch af {
5330                 case ARNG_B:
5331                         c.checkindex(p, index, 15)
5332                         if o.scond == C_XPOST && offset != 0 && offset != 1 {
5333                                 c.ctxt.Diag("invalid offset: %v", p)
5334                         }
5335                         Q = index >> 3
5336                         S = (index >> 2) & 1
5337                         size = index & 3
5338                         opcode = 0
5339                 case ARNG_H:
5340                         c.checkindex(p, index, 7)
5341                         if o.scond == C_XPOST && offset != 0 && offset != 2 {
5342                                 c.ctxt.Diag("invalid offset: %v", p)
5343                         }
5344                         Q = index >> 2
5345                         S = (index >> 1) & 1
5346                         size = (index & 1) << 1
5347                         opcode = 2
5348                 case ARNG_S:
5349                         c.checkindex(p, index, 3)
5350                         if o.scond == C_XPOST && offset != 0 && offset != 4 {
5351                                 c.ctxt.Diag("invalid offset: %v", p)
5352                         }
5353                         Q = index >> 1
5354                         S = index & 1
5355                         size = 0
5356                         opcode = 4
5357                 case ARNG_D:
5358                         c.checkindex(p, index, 1)
5359                         if o.scond == C_XPOST && offset != 0 && offset != 8 {
5360                                 c.ctxt.Diag("invalid offset: %v", p)
5361                         }
5362                         Q = index
5363                         S = 0
5364                         size = 1
5365                         opcode = 4
5366                 default:
5367                         c.ctxt.Diag("invalid arrangement: %v", p)
5368                 }
5369
5370                 if o.scond == C_XPOST {
5371                         o1 |= 27 << 23
5372                 } else {
5373                         o1 |= 26 << 23
5374                 }
5375
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)
5377
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))
5385
5386                 if o.scond == C_XPOST {
5387                         if (p.From.Index != 0) && (offset != 0) {
5388                                 c.ctxt.Diag("invalid offset: %v", p)
5389                         }
5390                         if p.From.Index == 0 && offset == 0 {
5391                                 c.ctxt.Diag("invalid offset: %v", p)
5392                         }
5393                 }
5394
5395                 if offset != 0 {
5396                         r = 31
5397                 }
5398
5399                 Q := 0
5400                 S := 0
5401                 size := 0
5402                 var opcode uint32
5403                 switch at {
5404                 case ARNG_B:
5405                         c.checkindex(p, index, 15)
5406                         if o.scond == C_XPOST && offset != 0 && offset != 1 {
5407                                 c.ctxt.Diag("invalid offset: %v", p)
5408                         }
5409                         Q = index >> 3
5410                         S = (index >> 2) & 1
5411                         size = index & 3
5412                         opcode = 0
5413                 case ARNG_H:
5414                         c.checkindex(p, index, 7)
5415                         if o.scond == C_XPOST && offset != 0 && offset != 2 {
5416                                 c.ctxt.Diag("invalid offset: %v", p)
5417                         }
5418                         Q = index >> 2
5419                         S = (index >> 1) & 1
5420                         size = (index & 1) << 1
5421                         opcode = 2
5422                 case ARNG_S:
5423                         c.checkindex(p, index, 3)
5424                         if o.scond == C_XPOST && offset != 0 && offset != 4 {
5425                                 c.ctxt.Diag("invalid offset: %v", p)
5426                         }
5427                         Q = index >> 1
5428                         S = index & 1
5429                         size = 0
5430                         opcode = 4
5431                 case ARNG_D:
5432                         c.checkindex(p, index, 1)
5433                         if o.scond == C_XPOST && offset != 0 && offset != 8 {
5434                                 c.ctxt.Diag("invalid offset: %v", p)
5435                         }
5436                         Q = index
5437                         S = 0
5438                         size = 1
5439                         opcode = 4
5440                 default:
5441                         c.ctxt.Diag("invalid arrangement: %v", p)
5442                 }
5443
5444                 if o.scond == C_XPOST {
5445                         o1 |= 110 << 21
5446                 } else {
5447                         o1 |= 106 << 21
5448                 }
5449
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)
5451
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)
5456
5457                         o1 = c.opldrr(p, p.As, true)
5458                         o1 |= c.encRegShiftOrExt(p, &p.From, p.From.Index) /* includes reg, op, etc */
5459                 } else {
5460                         // (Rn)(Rm), no extension or shift.
5461                         o1 = c.opldrr(p, p.As, false)
5462                         o1 |= uint32(p.From.Index&31) << 16
5463                 }
5464                 o1 |= uint32(p.From.Reg&31) << 5
5465                 rt := int(p.To.Reg)
5466                 o1 |= uint32(rt & 31)
5467
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)
5472
5473                         o1 = c.opstrr(p, p.As, true)
5474                         o1 |= c.encRegShiftOrExt(p, &p.To, p.To.Index) /* includes reg, op, etc */
5475                 } else {
5476                         // (Rn)(Rm), no extension or shift.
5477                         o1 = c.opstrr(p, p.As, false)
5478                         o1 |= uint32(p.To.Index&31) << 16
5479                 }
5480                 o1 |= uint32(p.To.Reg&31) << 5
5481                 rf := int(p.From.Reg)
5482                 o1 |= uint32(rf & 31)
5483
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)
5487                 if af != at {
5488                         c.ctxt.Diag("invalid arrangement: %v\n", p)
5489                 }
5490                 var q, len uint32
5491                 switch af {
5492                 case ARNG_8B:
5493                         q = 0
5494                 case ARNG_16B:
5495                         q = 1
5496                 default:
5497                         c.ctxt.Diag("invalid arrangement: %v", p)
5498                 }
5499                 rf := int(p.From.Reg)
5500                 rt := int(p.To.Reg)
5501                 offset := int(p.GetFrom3().Offset)
5502                 opcode := (offset >> 12) & 15
5503                 switch opcode {
5504                 case 0x7:
5505                         len = 0 // one register
5506                 case 0xa:
5507                         len = 1 // two register
5508                 case 0x6:
5509                         len = 2 // three registers
5510                 case 0x2:
5511                         len = 3 // four registers
5512                 default:
5513                         c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
5514                 }
5515                 var op uint32
5516                 switch p.As {
5517                 case AVTBL:
5518                         op = 0
5519                 case AVTBX:
5520                         op = 1
5521                 }
5522                 o1 = q<<30 | 0xe<<24 | len<<13 | op<<12
5523                 o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
5524
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))
5527
5528         case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
5529                 o1 = c.opirr(p, p.As)
5530                 rf := p.Reg
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 {
5535                         rf = p.From.Reg
5536                         af = uint8((p.From.Reg >> 5) & 15)
5537                         shift = 0
5538                 }
5539
5540                 Q := (o1 >> 30) & 1
5541                 var immh, width uint8
5542                 switch pack(Q, af, at) {
5543                 case pack(0, ARNG_8B, ARNG_8H):
5544                         immh, width = 1, 8
5545                 case pack(1, ARNG_16B, ARNG_8H):
5546                         immh, width = 1, 8
5547                 case pack(0, ARNG_4H, ARNG_4S):
5548                         immh, width = 2, 16
5549                 case pack(1, ARNG_8H, ARNG_4S):
5550                         immh, width = 2, 16
5551                 case pack(0, ARNG_2S, ARNG_2D):
5552                         immh, width = 4, 32
5553                 case pack(1, ARNG_4S, ARNG_2D):
5554                         immh, width = 4, 32
5555                 default:
5556                         c.ctxt.Diag("operand mismatch: %v\n", p)
5557                 }
5558                 if !(0 <= shift && shift <= int(width-1)) {
5559                         c.ctxt.Diag("shift amount out of range: %v\n", p)
5560                 }
5561                 o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
5562
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
5568
5569                 if ta != tm || ta != tn || ta != td || ta != ARNG_16B {
5570                         c.ctxt.Diag("invalid arrangement: %v", p)
5571                         break
5572                 }
5573
5574                 o1 = c.oprrr(p, p.As)
5575                 ra := int(p.From.Reg)
5576                 rm := int(p.Reg)
5577                 rn := int(p.GetFrom3().Reg)
5578                 rd := int(p.To.Reg)
5579                 o1 |= uint32(rm&31)<<16 | uint32(ra&31)<<10 | uint32(rn&31)<<5 | uint32(rd)&31
5580
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)
5586
5587                 if af != a || af != at {
5588                         c.ctxt.Diag("invalid arrangement: %v", p)
5589                         break
5590                 }
5591
5592                 if af != ARNG_2D {
5593                         c.ctxt.Diag("invalid arrangement, should be D2: %v", p)
5594                         break
5595                 }
5596
5597                 if index < 0 || index > 63 {
5598                         c.ctxt.Diag("illegal offset: %v", p)
5599                 }
5600
5601                 o1 = c.opirr(p, p.As)
5602                 rf := (p.GetFrom3().Reg) & 31
5603                 rt := (p.To.Reg) & 31
5604                 r := (p.Reg) & 31
5605
5606                 o1 |= (uint32(r&31) << 16) | (uint32(index&63) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
5607
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)
5612                 if at != a {
5613                         c.ctxt.Diag("invalid arrangement: %v", p)
5614                         break
5615                 }
5616
5617                 var Q, size uint32
5618                 if p.As == AVUADDW2 {
5619                         Q = 1
5620                 }
5621                 switch pack(Q, at, af) {
5622                 case pack(0, ARNG_8H, ARNG_8B), pack(1, ARNG_8H, ARNG_16B):
5623                         size = 0
5624                 case pack(0, ARNG_4S, ARNG_4H), pack(1, ARNG_4S, ARNG_8H):
5625                         size = 1
5626                 case pack(0, ARNG_2D, ARNG_2S), pack(1, ARNG_2D, ARNG_4S):
5627                         size = 2
5628                 default:
5629                         c.ctxt.Diag("operand mismatch: %v\n", p)
5630                 }
5631
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)
5637
5638         case 106: // CASPx (Rs, Rs+1), (Rb), (Rt, Rt+1)
5639                 rs := p.From.Reg
5640                 rt := p.GetTo2().Reg
5641                 rb := p.To.Reg
5642                 rs1 := int16(p.From.Offset)
5643                 rt1 := int16(p.GetTo2().Offset)
5644
5645                 enc, ok := atomicCASP[p.As]
5646                 if !ok {
5647                         c.ctxt.Diag("invalid CASP-like atomic instructions: %v\n", p)
5648                 }
5649                 // for CASPx-like instructions, Rs<0> != 1 && Rt<0> != 1
5650                 switch {
5651                 case rs&1 != 0:
5652                         c.ctxt.Diag("source register pair must start from even register: %v\n", p)
5653                         break
5654                 case rt&1 != 0:
5655                         c.ctxt.Diag("destination register pair must start from even register: %v\n", p)
5656                         break
5657                 case rs != rs1-1:
5658                         c.ctxt.Diag("source register pair must be contiguous: %v\n", p)
5659                         break
5660                 case rt != rt1-1:
5661                         c.ctxt.Diag("destination register pair must be contiguous: %v\n", p)
5662                         break
5663                 }
5664                 // rt can't be sp.
5665                 if rt == REG_RSP {
5666                         c.ctxt.Diag("illegal destination register: %v\n", p)
5667                 }
5668                 o1 |= enc | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
5669
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)
5674                         break
5675                 }
5676                 o1 = c.opirr(p, p.As)
5677                 if op.hasOperand2 {
5678                         if p.To.Reg == 0 {
5679                                 c.ctxt.Diag("missing register at operand 2: %v\n", p)
5680                         }
5681                         o1 |= uint32(p.To.Reg & 0x1F)
5682                 } else {
5683                         if p.To.Reg != 0 || p.Reg != 0 {
5684                                 c.ctxt.Diag("extraneous register at operand 2: %v\n", p)
5685                         }
5686                         o1 |= uint32(0x1F)
5687                 }
5688                 o1 |= uint32(SYSARG4(int(op.op1), int(op.cn), int(op.cm), int(op.op2)))
5689         }
5690         out[0] = o1
5691         out[1] = o2
5692         out[2] = o3
5693         out[3] = o4
5694         out[4] = o5
5695 }
5696
5697 func (c *ctxt7) addrRelocType(p *obj.Prog) objabi.RelocType {
5698         switch movesize(p.As) {
5699         case 0:
5700                 return objabi.R_ARM64_PCREL_LDST8
5701         case 1:
5702                 return objabi.R_ARM64_PCREL_LDST16
5703         case 2:
5704                 return objabi.R_ARM64_PCREL_LDST32
5705         case 3:
5706                 return objabi.R_ARM64_PCREL_LDST64
5707         default:
5708                 c.ctxt.Diag("use R_ADDRARM64 relocation type for: %v\n", p)
5709         }
5710         return -1
5711 }
5712
5713 /*
5714  * basic Rm op Rn -> Rd (using shifted register with 0)
5715  * also op Rn -> Rt
5716  * also Rm*Rn op Ra -> Rd
5717  * also Vm op Vn -> Vd
5718  */
5719 func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
5720         switch a {
5721         case AADC:
5722                 return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5723
5724         case AADCW:
5725                 return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
5726
5727         case AADCS:
5728                 return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5729
5730         case AADCSW:
5731                 return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
5732
5733         case ANGC, ASBC:
5734                 return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5735
5736         case ANGCS, ASBCS:
5737                 return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5738
5739         case ANGCW, ASBCW:
5740                 return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
5741
5742         case ANGCSW, ASBCSW:
5743                 return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
5744
5745         case AADD:
5746                 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5747
5748         case AADDW:
5749                 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5750
5751         case ACMN, AADDS:
5752                 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5753
5754         case ACMNW, AADDSW:
5755                 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5756
5757         case ASUB:
5758                 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5759
5760         case ASUBW:
5761                 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5762
5763         case ACMP, ASUBS:
5764                 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5765
5766         case ACMPW, ASUBSW:
5767                 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
5768
5769         case AAND:
5770                 return S64 | 0<<29 | 0xA<<24
5771
5772         case AANDW:
5773                 return S32 | 0<<29 | 0xA<<24
5774
5775         case AMOVD, AORR:
5776                 return S64 | 1<<29 | 0xA<<24
5777
5778                 //      case AMOVW:
5779         case AMOVWU, AORRW:
5780                 return S32 | 1<<29 | 0xA<<24
5781
5782         case AEOR:
5783                 return S64 | 2<<29 | 0xA<<24
5784
5785         case AEORW:
5786                 return S32 | 2<<29 | 0xA<<24
5787
5788         case AANDS, ATST:
5789                 return S64 | 3<<29 | 0xA<<24
5790
5791         case AANDSW, ATSTW:
5792                 return S32 | 3<<29 | 0xA<<24
5793
5794         case ABIC:
5795                 return S64 | 0<<29 | 0xA<<24 | 1<<21
5796
5797         case ABICW:
5798                 return S32 | 0<<29 | 0xA<<24 | 1<<21
5799
5800         case ABICS:
5801                 return S64 | 3<<29 | 0xA<<24 | 1<<21
5802
5803         case ABICSW:
5804                 return S32 | 3<<29 | 0xA<<24 | 1<<21
5805
5806         case AEON:
5807                 return S64 | 2<<29 | 0xA<<24 | 1<<21
5808
5809         case AEONW:
5810                 return S32 | 2<<29 | 0xA<<24 | 1<<21
5811
5812         case AMVN, AORN:
5813                 return S64 | 1<<29 | 0xA<<24 | 1<<21
5814
5815         case AMVNW, AORNW:
5816                 return S32 | 1<<29 | 0xA<<24 | 1<<21
5817
5818         case AASR:
5819                 return S64 | OPDP2(10) /* also ASRV */
5820
5821         case AASRW:
5822                 return S32 | OPDP2(10)
5823
5824         case ALSL:
5825                 return S64 | OPDP2(8)
5826
5827         case ALSLW:
5828                 return S32 | OPDP2(8)
5829
5830         case ALSR:
5831                 return S64 | OPDP2(9)
5832
5833         case ALSRW:
5834                 return S32 | OPDP2(9)
5835
5836         case AROR:
5837                 return S64 | OPDP2(11)
5838
5839         case ARORW:
5840                 return S32 | OPDP2(11)
5841
5842         case ACCMN:
5843                 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
5844
5845         case ACCMNW:
5846                 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5847
5848         case ACCMP:
5849                 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
5850
5851         case ACCMPW:
5852                 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
5853
5854         case ACRC32B:
5855                 return S32 | OPDP2(16)
5856
5857         case ACRC32H:
5858                 return S32 | OPDP2(17)
5859
5860         case ACRC32W:
5861                 return S32 | OPDP2(18)
5862
5863         case ACRC32X:
5864                 return S64 | OPDP2(19)
5865
5866         case ACRC32CB:
5867                 return S32 | OPDP2(20)
5868
5869         case ACRC32CH:
5870                 return S32 | OPDP2(21)
5871
5872         case ACRC32CW:
5873                 return S32 | OPDP2(22)
5874
5875         case ACRC32CX:
5876                 return S64 | OPDP2(23)
5877
5878         case ACSEL:
5879                 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5880
5881         case ACSELW:
5882                 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5883
5884         case ACSET:
5885                 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5886
5887         case ACSETW:
5888                 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5889
5890         case ACSETM:
5891                 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5892
5893         case ACSETMW:
5894                 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5895
5896         case ACINC, ACSINC:
5897                 return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5898
5899         case ACINCW, ACSINCW:
5900                 return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5901
5902         case ACINV, ACSINV:
5903                 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5904
5905         case ACINVW, ACSINVW:
5906                 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
5907
5908         case ACNEG, ACSNEG:
5909                 return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5910
5911         case ACNEGW, ACSNEGW:
5912                 return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
5913
5914         case AMUL, AMADD:
5915                 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5916
5917         case AMULW, AMADDW:
5918                 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
5919
5920         case AMNEG, AMSUB:
5921                 return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5922
5923         case AMNEGW, AMSUBW:
5924                 return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
5925
5926         case AMRS:
5927                 return SYSOP(1, 2, 0, 0, 0, 0, 0)
5928
5929         case AMSR:
5930                 return SYSOP(0, 2, 0, 0, 0, 0, 0)
5931
5932         case ANEG:
5933                 return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5934
5935         case ANEGW:
5936                 return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
5937
5938         case ANEGS:
5939                 return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5940
5941         case ANEGSW:
5942                 return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
5943
5944         case AREM, ASDIV:
5945                 return S64 | OPDP2(3)
5946
5947         case AREMW, ASDIVW:
5948                 return S32 | OPDP2(3)
5949
5950         case ASMULL, ASMADDL:
5951                 return OPDP3(1, 0, 1, 0)
5952
5953         case ASMNEGL, ASMSUBL:
5954                 return OPDP3(1, 0, 1, 1)
5955
5956         case ASMULH:
5957                 return OPDP3(1, 0, 2, 0)
5958
5959         case AUMULL, AUMADDL:
5960                 return OPDP3(1, 0, 5, 0)
5961
5962         case AUMNEGL, AUMSUBL:
5963                 return OPDP3(1, 0, 5, 1)
5964
5965         case AUMULH:
5966                 return OPDP3(1, 0, 6, 0)
5967
5968         case AUREM, AUDIV:
5969                 return S64 | OPDP2(2)
5970
5971         case AUREMW, AUDIVW:
5972                 return S32 | OPDP2(2)
5973
5974         case AAESE:
5975                 return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
5976
5977         case AAESD:
5978                 return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
5979
5980         case AAESMC:
5981                 return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
5982
5983         case AAESIMC:
5984                 return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
5985
5986         case ASHA1C:
5987                 return 0x5E<<24 | 0<<12
5988
5989         case ASHA1P:
5990                 return 0x5E<<24 | 1<<12
5991
5992         case ASHA1M:
5993                 return 0x5E<<24 | 2<<12
5994
5995         case ASHA1SU0:
5996                 return 0x5E<<24 | 3<<12
5997
5998         case ASHA256H:
5999                 return 0x5E<<24 | 4<<12
6000
6001         case ASHA256H2:
6002                 return 0x5E<<24 | 5<<12
6003
6004         case ASHA256SU1:
6005                 return 0x5E<<24 | 6<<12
6006
6007         case ASHA1H:
6008                 return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
6009
6010         case ASHA1SU1:
6011                 return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
6012
6013         case ASHA256SU0:
6014                 return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
6015
6016         case ASHA512H:
6017                 return 0xCE<<24 | 3<<21 | 8<<12
6018
6019         case ASHA512H2:
6020                 return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
6021
6022         case ASHA512SU1:
6023                 return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
6024
6025         case ASHA512SU0:
6026                 return 0xCE<<24 | 3<<22 | 8<<12
6027
6028         case AFCVTZSD:
6029                 return FPCVTI(1, 0, 1, 3, 0)
6030
6031         case AFCVTZSDW:
6032                 return FPCVTI(0, 0, 1, 3, 0)
6033
6034         case AFCVTZSS:
6035                 return FPCVTI(1, 0, 0, 3, 0)
6036
6037         case AFCVTZSSW:
6038                 return FPCVTI(0, 0, 0, 3, 0)
6039
6040         case AFCVTZUD:
6041                 return FPCVTI(1, 0, 1, 3, 1)
6042
6043         case AFCVTZUDW:
6044                 return FPCVTI(0, 0, 1, 3, 1)
6045
6046         case AFCVTZUS:
6047                 return FPCVTI(1, 0, 0, 3, 1)
6048
6049         case AFCVTZUSW:
6050                 return FPCVTI(0, 0, 0, 3, 1)
6051
6052         case ASCVTFD:
6053                 return FPCVTI(1, 0, 1, 0, 2)
6054
6055         case ASCVTFS:
6056                 return FPCVTI(1, 0, 0, 0, 2)
6057
6058         case ASCVTFWD:
6059                 return FPCVTI(0, 0, 1, 0, 2)
6060
6061         case ASCVTFWS:
6062                 return FPCVTI(0, 0, 0, 0, 2)
6063
6064         case AUCVTFD:
6065                 return FPCVTI(1, 0, 1, 0, 3)
6066
6067         case AUCVTFS:
6068                 return FPCVTI(1, 0, 0, 0, 3)
6069
6070         case AUCVTFWD:
6071                 return FPCVTI(0, 0, 1, 0, 3)
6072
6073         case AUCVTFWS:
6074                 return FPCVTI(0, 0, 0, 0, 3)
6075
6076         case AFADDS:
6077                 return FPOP2S(0, 0, 0, 2)
6078
6079         case AFADDD:
6080                 return FPOP2S(0, 0, 1, 2)
6081
6082         case AFSUBS:
6083                 return FPOP2S(0, 0, 0, 3)
6084
6085         case AFSUBD:
6086                 return FPOP2S(0, 0, 1, 3)
6087
6088         case AFMADDD:
6089                 return FPOP3S(0, 0, 1, 0, 0)
6090
6091         case AFMADDS:
6092                 return FPOP3S(0, 0, 0, 0, 0)
6093
6094         case AFMSUBD:
6095                 return FPOP3S(0, 0, 1, 0, 1)
6096
6097         case AFMSUBS:
6098                 return FPOP3S(0, 0, 0, 0, 1)
6099
6100         case AFNMADDD:
6101                 return FPOP3S(0, 0, 1, 1, 0)
6102
6103         case AFNMADDS:
6104                 return FPOP3S(0, 0, 0, 1, 0)
6105
6106         case AFNMSUBD:
6107                 return FPOP3S(0, 0, 1, 1, 1)
6108
6109         case AFNMSUBS:
6110                 return FPOP3S(0, 0, 0, 1, 1)
6111
6112         case AFMULS:
6113                 return FPOP2S(0, 0, 0, 0)
6114
6115         case AFMULD:
6116                 return FPOP2S(0, 0, 1, 0)
6117
6118         case AFDIVS:
6119                 return FPOP2S(0, 0, 0, 1)
6120
6121         case AFDIVD:
6122                 return FPOP2S(0, 0, 1, 1)
6123
6124         case AFMAXS:
6125                 return FPOP2S(0, 0, 0, 4)
6126
6127         case AFMINS:
6128                 return FPOP2S(0, 0, 0, 5)
6129
6130         case AFMAXD:
6131                 return FPOP2S(0, 0, 1, 4)
6132
6133         case AFMIND:
6134                 return FPOP2S(0, 0, 1, 5)
6135
6136         case AFMAXNMS:
6137                 return FPOP2S(0, 0, 0, 6)
6138
6139         case AFMAXNMD:
6140                 return FPOP2S(0, 0, 1, 6)
6141
6142         case AFMINNMS:
6143                 return FPOP2S(0, 0, 0, 7)
6144
6145         case AFMINNMD:
6146                 return FPOP2S(0, 0, 1, 7)
6147
6148         case AFNMULS:
6149                 return FPOP2S(0, 0, 0, 8)
6150
6151         case AFNMULD:
6152                 return FPOP2S(0, 0, 1, 8)
6153
6154         case AFCMPS:
6155                 return FPCMP(0, 0, 0, 0, 0)
6156
6157         case AFCMPD:
6158                 return FPCMP(0, 0, 1, 0, 0)
6159
6160         case AFCMPES:
6161                 return FPCMP(0, 0, 0, 0, 16)
6162
6163         case AFCMPED:
6164                 return FPCMP(0, 0, 1, 0, 16)
6165
6166         case AFCCMPS:
6167                 return FPCCMP(0, 0, 0, 0)
6168
6169         case AFCCMPD:
6170                 return FPCCMP(0, 0, 1, 0)
6171
6172         case AFCCMPES:
6173                 return FPCCMP(0, 0, 0, 1)
6174
6175         case AFCCMPED:
6176                 return FPCCMP(0, 0, 1, 1)
6177
6178         case AFCSELS:
6179                 return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
6180
6181         case AFCSELD:
6182                 return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
6183
6184         case AFMOVS:
6185                 return FPOP1S(0, 0, 0, 0)
6186
6187         case AFABSS:
6188                 return FPOP1S(0, 0, 0, 1)
6189
6190         case AFNEGS:
6191                 return FPOP1S(0, 0, 0, 2)
6192
6193         case AFSQRTS:
6194                 return FPOP1S(0, 0, 0, 3)
6195
6196         case AFCVTSD:
6197                 return FPOP1S(0, 0, 0, 5)
6198
6199         case AFCVTSH:
6200                 return FPOP1S(0, 0, 0, 7)
6201
6202         case AFRINTNS:
6203                 return FPOP1S(0, 0, 0, 8)
6204
6205         case AFRINTPS:
6206                 return FPOP1S(0, 0, 0, 9)
6207
6208         case AFRINTMS:
6209                 return FPOP1S(0, 0, 0, 10)
6210
6211         case AFRINTZS:
6212                 return FPOP1S(0, 0, 0, 11)
6213
6214         case AFRINTAS:
6215                 return FPOP1S(0, 0, 0, 12)
6216
6217         case AFRINTXS:
6218                 return FPOP1S(0, 0, 0, 14)
6219
6220         case AFRINTIS:
6221                 return FPOP1S(0, 0, 0, 15)
6222
6223         case AFMOVD:
6224                 return FPOP1S(0, 0, 1, 0)
6225
6226         case AFABSD:
6227                 return FPOP1S(0, 0, 1, 1)
6228
6229         case AFNEGD:
6230                 return FPOP1S(0, 0, 1, 2)
6231
6232         case AFSQRTD:
6233                 return FPOP1S(0, 0, 1, 3)
6234
6235         case AFCVTDS:
6236                 return FPOP1S(0, 0, 1, 4)
6237
6238         case AFCVTDH:
6239                 return FPOP1S(0, 0, 1, 7)
6240
6241         case AFRINTND:
6242                 return FPOP1S(0, 0, 1, 8)
6243
6244         case AFRINTPD:
6245                 return FPOP1S(0, 0, 1, 9)
6246
6247         case AFRINTMD:
6248                 return FPOP1S(0, 0, 1, 10)
6249
6250         case AFRINTZD:
6251                 return FPOP1S(0, 0, 1, 11)
6252
6253         case AFRINTAD:
6254                 return FPOP1S(0, 0, 1, 12)
6255
6256         case AFRINTXD:
6257                 return FPOP1S(0, 0, 1, 14)
6258
6259         case AFRINTID:
6260                 return FPOP1S(0, 0, 1, 15)
6261
6262         case AFCVTHS:
6263                 return FPOP1S(0, 0, 3, 4)
6264
6265         case AFCVTHD:
6266                 return FPOP1S(0, 0, 3, 5)
6267
6268         case AVADD:
6269                 return 7<<25 | 1<<21 | 1<<15 | 1<<10
6270
6271         case AVSUB:
6272                 return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
6273
6274         case AVADDP:
6275                 return 7<<25 | 1<<21 | 1<<15 | 15<<10
6276
6277         case AVAND:
6278                 return 7<<25 | 1<<21 | 7<<10
6279
6280         case AVBCAX:
6281                 return 0xCE<<24 | 1<<21
6282
6283         case AVCMEQ:
6284                 return 1<<29 | 0x71<<21 | 0x23<<10
6285
6286         case AVCNT:
6287                 return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
6288
6289         case AVZIP1:
6290                 return 0xE<<24 | 3<<12 | 2<<10
6291
6292         case AVZIP2:
6293                 return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
6294
6295         case AVEOR:
6296                 return 1<<29 | 0x71<<21 | 7<<10
6297
6298         case AVEOR3:
6299                 return 0xCE << 24
6300
6301         case AVORR:
6302                 return 7<<25 | 5<<21 | 7<<10
6303
6304         case AVREV16:
6305                 return 3<<26 | 2<<24 | 1<<21 | 3<<11
6306
6307         case AVRAX1:
6308                 return 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
6309
6310         case AVREV32:
6311                 return 11<<26 | 2<<24 | 1<<21 | 1<<11
6312
6313         case AVREV64:
6314                 return 3<<26 | 2<<24 | 1<<21 | 1<<11
6315
6316         case AVMOV:
6317                 return 7<<25 | 5<<21 | 7<<10
6318
6319         case AVADDV:
6320                 return 7<<25 | 3<<20 | 3<<15 | 7<<11
6321
6322         case AVUADDLV:
6323                 return 1<<29 | 7<<25 | 3<<20 | 7<<11
6324
6325         case AVFMLA:
6326                 return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
6327
6328         case AVFMLS:
6329                 return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
6330
6331         case AVPMULL, AVPMULL2:
6332                 return 0xE<<24 | 1<<21 | 0x38<<10
6333
6334         case AVRBIT:
6335                 return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
6336
6337         case AVLD1, AVLD2, AVLD3, AVLD4:
6338                 return 3<<26 | 1<<22
6339
6340         case AVLD1R, AVLD3R:
6341                 return 0xD<<24 | 1<<22
6342
6343         case AVLD2R, AVLD4R:
6344                 return 0xD<<24 | 3<<21
6345
6346         case AVBIF:
6347                 return 1<<29 | 7<<25 | 7<<21 | 7<<10
6348
6349         case AVBIT:
6350                 return 1<<29 | 0x75<<21 | 7<<10
6351
6352         case AVBSL:
6353                 return 1<<29 | 0x73<<21 | 7<<10
6354
6355         case AVCMTST:
6356                 return 0xE<<24 | 1<<21 | 0x23<<10
6357
6358         case AVUMAX:
6359                 return 1<<29 | 7<<25 | 1<<21 | 0x19<<10
6360
6361         case AVUMIN:
6362                 return 1<<29 | 7<<25 | 1<<21 | 0x1b<<10
6363
6364         case AVUZP1:
6365                 return 7<<25 | 3<<11
6366
6367         case AVUZP2:
6368                 return 7<<25 | 1<<14 | 3<<11
6369
6370         case AVUADDW, AVUADDW2:
6371                 return 0x17<<25 | 1<<21 | 1<<12
6372
6373         case AVTRN1:
6374                 return 7<<25 | 5<<11
6375
6376         case AVTRN2:
6377                 return 7<<25 | 1<<14 | 5<<11
6378         }
6379
6380         c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
6381         return 0
6382 }
6383
6384 /*
6385  * imm -> Rd
6386  * imm op Rn -> Rd
6387  */
6388 func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
6389         switch a {
6390         /* op $addcon, Rn, Rd */
6391         case AMOVD, AADD:
6392                 return S64 | 0<<30 | 0<<29 | 0x11<<24
6393
6394         case ACMN, AADDS:
6395                 return S64 | 0<<30 | 1<<29 | 0x11<<24
6396
6397         case AMOVW, AADDW:
6398                 return S32 | 0<<30 | 0<<29 | 0x11<<24
6399
6400         case ACMNW, AADDSW:
6401                 return S32 | 0<<30 | 1<<29 | 0x11<<24
6402
6403         case ASUB:
6404                 return S64 | 1<<30 | 0<<29 | 0x11<<24
6405
6406         case ACMP, ASUBS:
6407                 return S64 | 1<<30 | 1<<29 | 0x11<<24
6408
6409         case ASUBW:
6410                 return S32 | 1<<30 | 0<<29 | 0x11<<24
6411
6412         case ACMPW, ASUBSW:
6413                 return S32 | 1<<30 | 1<<29 | 0x11<<24
6414
6415                 /* op $imm(SB), Rd; op label, Rd */
6416         case AADR:
6417                 return 0<<31 | 0x10<<24
6418
6419         case AADRP:
6420                 return 1<<31 | 0x10<<24
6421
6422                 /* op $bimm, Rn, Rd */
6423         case AAND, ABIC:
6424                 return S64 | 0<<29 | 0x24<<23
6425
6426         case AANDW, ABICW:
6427                 return S32 | 0<<29 | 0x24<<23 | 0<<22
6428
6429         case AORR, AORN:
6430                 return S64 | 1<<29 | 0x24<<23
6431
6432         case AORRW, AORNW:
6433                 return S32 | 1<<29 | 0x24<<23 | 0<<22
6434
6435         case AEOR, AEON:
6436                 return S64 | 2<<29 | 0x24<<23
6437
6438         case AEORW, AEONW:
6439                 return S32 | 2<<29 | 0x24<<23 | 0<<22
6440
6441         case AANDS, ABICS, ATST:
6442                 return S64 | 3<<29 | 0x24<<23
6443
6444         case AANDSW, ABICSW, ATSTW:
6445                 return S32 | 3<<29 | 0x24<<23 | 0<<22
6446
6447         case AASR:
6448                 return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
6449
6450         case AASRW:
6451                 return S32 | 0<<29 | 0x26<<23 | 0<<22
6452
6453                 /* op $width, $lsb, Rn, Rd */
6454         case ABFI:
6455                 return S64 | 2<<29 | 0x26<<23 | 1<<22
6456                 /* alias of BFM */
6457
6458         case ABFIW:
6459                 return S32 | 2<<29 | 0x26<<23 | 0<<22
6460
6461                 /* op $imms, $immr, Rn, Rd */
6462         case ABFM:
6463                 return S64 | 1<<29 | 0x26<<23 | 1<<22
6464
6465         case ABFMW:
6466                 return S32 | 1<<29 | 0x26<<23 | 0<<22
6467
6468         case ASBFM:
6469                 return S64 | 0<<29 | 0x26<<23 | 1<<22
6470
6471         case ASBFMW:
6472                 return S32 | 0<<29 | 0x26<<23 | 0<<22
6473
6474         case AUBFM:
6475                 return S64 | 2<<29 | 0x26<<23 | 1<<22
6476
6477         case AUBFMW:
6478                 return S32 | 2<<29 | 0x26<<23 | 0<<22
6479
6480         case ABFXIL:
6481                 return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
6482
6483         case ABFXILW:
6484                 return S32 | 1<<29 | 0x26<<23 | 0<<22
6485
6486         case AEXTR:
6487                 return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
6488
6489         case AEXTRW:
6490                 return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
6491
6492         case ACBNZ:
6493                 return S64 | 0x1A<<25 | 1<<24
6494
6495         case ACBNZW:
6496                 return S32 | 0x1A<<25 | 1<<24
6497
6498         case ACBZ:
6499                 return S64 | 0x1A<<25 | 0<<24
6500
6501         case ACBZW:
6502                 return S32 | 0x1A<<25 | 0<<24
6503
6504         case ACCMN:
6505                 return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6506
6507         case ACCMNW:
6508                 return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6509
6510         case ACCMP:
6511                 return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
6512
6513         case ACCMPW:
6514                 return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
6515
6516         case AMOVK:
6517                 return S64 | 3<<29 | 0x25<<23
6518
6519         case AMOVKW:
6520                 return S32 | 3<<29 | 0x25<<23
6521
6522         case AMOVN:
6523                 return S64 | 0<<29 | 0x25<<23
6524
6525         case AMOVNW:
6526                 return S32 | 0<<29 | 0x25<<23
6527
6528         case AMOVZ:
6529                 return S64 | 2<<29 | 0x25<<23
6530
6531         case AMOVZW:
6532                 return S32 | 2<<29 | 0x25<<23
6533
6534         case AMSR:
6535                 return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
6536
6537         case AAT,
6538                 ADC,
6539                 AIC,
6540                 ATLBI,
6541                 ASYS:
6542                 return SYSOP(0, 1, 0, 0, 0, 0, 0)
6543
6544         case ASYSL:
6545                 return SYSOP(1, 1, 0, 0, 0, 0, 0)
6546
6547         case ATBZ:
6548                 return 0x36 << 24
6549
6550         case ATBNZ:
6551                 return 0x37 << 24
6552
6553         case ADSB:
6554                 return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
6555
6556         case ADMB:
6557                 return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
6558
6559         case AISB:
6560                 return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
6561
6562         case AHINT:
6563                 return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
6564
6565         case AVEXT:
6566                 return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
6567
6568         case AVUSHR:
6569                 return 0x5E<<23 | 1<<10
6570
6571         case AVSHL:
6572                 return 0x1E<<23 | 21<<10
6573
6574         case AVSRI:
6575                 return 0x5E<<23 | 17<<10
6576
6577         case AVSLI:
6578                 return 0x5E<<23 | 21<<10
6579
6580         case AVUSHLL, AVUXTL:
6581                 return 1<<29 | 15<<24 | 0x29<<10
6582
6583         case AVUSHLL2, AVUXTL2:
6584                 return 3<<29 | 15<<24 | 0x29<<10
6585
6586         case AVXAR:
6587                 return 0xCE<<24 | 1<<23
6588
6589         case AVUSRA:
6590                 return 1<<29 | 15<<24 | 5<<10
6591
6592         case APRFM:
6593                 return 0xf9<<24 | 2<<22
6594         }
6595
6596         c.ctxt.Diag("%v: bad irr %v", p, a)
6597         return 0
6598 }
6599
6600 func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
6601         switch a {
6602         case ACLS:
6603                 return S64 | OPBIT(5)
6604
6605         case ACLSW:
6606                 return S32 | OPBIT(5)
6607
6608         case ACLZ:
6609                 return S64 | OPBIT(4)
6610
6611         case ACLZW:
6612                 return S32 | OPBIT(4)
6613
6614         case ARBIT:
6615                 return S64 | OPBIT(0)
6616
6617         case ARBITW:
6618                 return S32 | OPBIT(0)
6619
6620         case AREV:
6621                 return S64 | OPBIT(3)
6622
6623         case AREVW:
6624                 return S32 | OPBIT(2)
6625
6626         case AREV16:
6627                 return S64 | OPBIT(1)
6628
6629         case AREV16W:
6630                 return S32 | OPBIT(1)
6631
6632         case AREV32:
6633                 return S64 | OPBIT(2)
6634
6635         default:
6636                 c.ctxt.Diag("bad bit op\n%v", p)
6637                 return 0
6638         }
6639 }
6640
6641 /*
6642  * add/subtract sign or zero-extended register
6643  */
6644 func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
6645         extension := uint32(0)
6646         if !extend {
6647                 if isADDop(a) {
6648                         extension = LSL0_64
6649                 }
6650                 if isADDWop(a) {
6651                         extension = LSL0_32
6652                 }
6653         }
6654
6655         switch a {
6656         case AADD:
6657                 return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6658
6659         case AADDW:
6660                 return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6661
6662         case ACMN, AADDS:
6663                 return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6664
6665         case ACMNW, AADDSW:
6666                 return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6667
6668         case ASUB:
6669                 return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6670
6671         case ASUBW:
6672                 return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6673
6674         case ACMP, ASUBS:
6675                 return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6676
6677         case ACMPW, ASUBSW:
6678                 return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
6679         }
6680
6681         c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
6682         return 0
6683 }
6684
6685 func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
6686         switch a {
6687         case ASVC:
6688                 return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
6689
6690         case AHVC:
6691                 return 0xD4<<24 | 0<<21 | 2
6692
6693         case ASMC:
6694                 return 0xD4<<24 | 0<<21 | 3
6695
6696         case ABRK:
6697                 return 0xD4<<24 | 1<<21 | 0
6698
6699         case AHLT:
6700                 return 0xD4<<24 | 2<<21 | 0
6701
6702         case ADCPS1:
6703                 return 0xD4<<24 | 5<<21 | 1
6704
6705         case ADCPS2:
6706                 return 0xD4<<24 | 5<<21 | 2
6707
6708         case ADCPS3:
6709                 return 0xD4<<24 | 5<<21 | 3
6710
6711         case ACLREX:
6712                 return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
6713         }
6714
6715         c.ctxt.Diag("%v: bad imm %v", p, a)
6716         return 0
6717 }
6718
6719 func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
6720         v := int64(0)
6721         t := int64(0)
6722         var q *obj.Prog
6723         if p.To.Type == obj.TYPE_BRANCH {
6724                 q = p.To.Target()
6725         } else if p.From.Type == obj.TYPE_BRANCH { // adr, adrp
6726                 q = p.From.Target()
6727         }
6728         if q == nil {
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.)
6731                 q = p.Pool
6732         }
6733         if q != nil {
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)
6737                 }
6738                 v >>= uint(shift)
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")
6743                 }
6744         }
6745
6746         return v & ((t << 1) - 1)
6747 }
6748
6749 /*
6750  * pc-relative branches
6751  */
6752 func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
6753         switch a {
6754         case ABEQ:
6755                 return OPBcc(0x0)
6756
6757         case ABNE:
6758                 return OPBcc(0x1)
6759
6760         case ABCS:
6761                 return OPBcc(0x2)
6762
6763         case ABHS:
6764                 return OPBcc(0x2)
6765
6766         case ABCC:
6767                 return OPBcc(0x3)
6768
6769         case ABLO:
6770                 return OPBcc(0x3)
6771
6772         case ABMI:
6773                 return OPBcc(0x4)
6774
6775         case ABPL:
6776                 return OPBcc(0x5)
6777
6778         case ABVS:
6779                 return OPBcc(0x6)
6780
6781         case ABVC:
6782                 return OPBcc(0x7)
6783
6784         case ABHI:
6785                 return OPBcc(0x8)
6786
6787         case ABLS:
6788                 return OPBcc(0x9)
6789
6790         case ABGE:
6791                 return OPBcc(0xa)
6792
6793         case ABLT:
6794                 return OPBcc(0xb)
6795
6796         case ABGT:
6797                 return OPBcc(0xc)
6798
6799         case ABLE:
6800                 return OPBcc(0xd) /* imm19<<5 | cond */
6801
6802         case AB:
6803                 return 0<<31 | 5<<26 /* imm26 */
6804
6805         case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
6806                 return 1<<31 | 5<<26
6807         }
6808
6809         c.ctxt.Diag("%v: bad bra %v", p, a)
6810         return 0
6811 }
6812
6813 func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
6814         switch a {
6815         case ABL:
6816                 return OPBLR(1) /* BLR */
6817
6818         case AB:
6819                 return OPBLR(0) /* BR */
6820
6821         case obj.ARET:
6822                 return OPBLR(2) /* RET */
6823         }
6824
6825         c.ctxt.Diag("%v: bad brr %v", p, a)
6826         return 0
6827 }
6828
6829 func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
6830         switch a {
6831         case ADRPS:
6832                 return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
6833
6834         case AERET:
6835                 return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
6836
6837         case ANOOP:
6838                 return SYSHINT(0)
6839
6840         case AYIELD:
6841                 return SYSHINT(1)
6842
6843         case AWFE:
6844                 return SYSHINT(2)
6845
6846         case AWFI:
6847                 return SYSHINT(3)
6848
6849         case ASEV:
6850                 return SYSHINT(4)
6851
6852         case ASEVL:
6853                 return SYSHINT(5)
6854         }
6855
6856         c.ctxt.Diag("%v: bad op0 %v", p, a)
6857         return 0
6858 }
6859
6860 /*
6861  * register offset
6862  */
6863 func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
6864         switch a {
6865         case ALDAR:
6866                 return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
6867
6868         case ALDARW:
6869                 return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
6870
6871         case ALDARB:
6872                 return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
6873
6874         case ALDARH:
6875                 return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
6876
6877         case ALDAXP:
6878                 return LDSTX(3, 0, 1, 1, 1)
6879
6880         case ALDAXPW:
6881                 return LDSTX(2, 0, 1, 1, 1)
6882
6883         case ALDAXR:
6884                 return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
6885
6886         case ALDAXRW:
6887                 return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
6888
6889         case ALDAXRB:
6890                 return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
6891
6892         case ALDAXRH:
6893                 return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
6894
6895         case ALDXR:
6896                 return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
6897
6898         case ALDXRB:
6899                 return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
6900
6901         case ALDXRH:
6902                 return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
6903
6904         case ALDXRW:
6905                 return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
6906
6907         case ALDXP:
6908                 return LDSTX(3, 0, 1, 1, 0)
6909
6910         case ALDXPW:
6911                 return LDSTX(2, 0, 1, 1, 0)
6912
6913         case AMOVNP:
6914                 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6915
6916         case AMOVNPW:
6917                 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6918         }
6919
6920         c.ctxt.Diag("bad opload %v\n%v", a, p)
6921         return 0
6922 }
6923
6924 func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
6925         switch a {
6926         case ASTLR:
6927                 return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
6928
6929         case ASTLRB:
6930                 return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
6931
6932         case ASTLRH:
6933                 return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
6934
6935         case ASTLP:
6936                 return LDSTX(3, 0, 0, 1, 1)
6937
6938         case ASTLPW:
6939                 return LDSTX(2, 0, 0, 1, 1)
6940
6941         case ASTLRW:
6942                 return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
6943
6944         case ASTLXP:
6945                 return LDSTX(3, 0, 0, 1, 1)
6946
6947         case ASTLXPW:
6948                 return LDSTX(2, 0, 0, 1, 1)
6949
6950         case ASTLXR:
6951                 return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
6952
6953         case ASTLXRB:
6954                 return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
6955
6956         case ASTLXRH:
6957                 return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
6958
6959         case ASTLXRW:
6960                 return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
6961
6962         case ASTXR:
6963                 return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
6964
6965         case ASTXRB:
6966                 return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
6967
6968         case ASTXRH:
6969                 return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
6970
6971         case ASTXP:
6972                 return LDSTX(3, 0, 0, 1, 0)
6973
6974         case ASTXPW:
6975                 return LDSTX(2, 0, 0, 1, 0)
6976
6977         case ASTXRW:
6978                 return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
6979
6980         case AMOVNP:
6981                 return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6982
6983         case AMOVNPW:
6984                 return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
6985         }
6986
6987         c.ctxt.Diag("bad opstore %v\n%v", a, p)
6988         return 0
6989 }
6990
6991 /*
6992  * load/store register (scaled 12-bit unsigned immediate) C3.3.13
6993  *      these produce 64-bit values (when there's an option)
6994  */
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)
6998         }
6999         o |= (v & 0xFFF) << 10
7000         o |= int32(b&31) << 5
7001         o |= int32(r & 31)
7002         o |= 1 << 24
7003         return uint32(o)
7004 }
7005
7006 /*
7007  * load/store register (unscaled 9-bit signed immediate) C3.3.12
7008  */
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)
7012         }
7013         o |= (v & 0x1FF) << 12
7014         o |= int32(b&31) << 5
7015         o |= int32(r & 31)
7016         return uint32(o)
7017 }
7018
7019 // store(immediate)
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)
7026         switch p.As {
7027         case AFMOVQ:
7028                 enc = enc &^ (1 << 22)
7029         default:
7030                 enc = LD2STR(enc)
7031         }
7032         return enc
7033 }
7034
7035 // load(immediate)
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 {
7041         switch a {
7042         case AMOVD:
7043                 return LDSTR(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
7044
7045         case AMOVW:
7046                 return LDSTR(2, 0, 2)
7047
7048         case AMOVWU:
7049                 return LDSTR(2, 0, 1)
7050
7051         case AMOVH:
7052                 return LDSTR(1, 0, 2)
7053
7054         case AMOVHU:
7055                 return LDSTR(1, 0, 1)
7056
7057         case AMOVB:
7058                 return LDSTR(0, 0, 2)
7059
7060         case AMOVBU:
7061                 return LDSTR(0, 0, 1)
7062
7063         case AFMOVS:
7064                 return LDSTR(2, 1, 1)
7065
7066         case AFMOVD:
7067                 return LDSTR(3, 1, 1)
7068
7069         case AFMOVQ:
7070                 return LDSTR(0, 1, 3)
7071         }
7072
7073         c.ctxt.Diag("bad opldr %v\n%v", a, p)
7074         return 0
7075 }
7076
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
7082         o |= int32(r & 31)
7083         return uint32(o)
7084 }
7085
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)
7091         if extension {
7092                 OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
7093         }
7094         switch a {
7095         case AMOVD:
7096                 return OptionS<<10 | 0x3<<21 | 0x1f<<27
7097         case AMOVW:
7098                 return OptionS<<10 | 0x5<<21 | 0x17<<27
7099         case AMOVWU:
7100                 return OptionS<<10 | 0x3<<21 | 0x17<<27
7101         case AMOVH:
7102                 return OptionS<<10 | 0x5<<21 | 0x0f<<27
7103         case AMOVHU:
7104                 return OptionS<<10 | 0x3<<21 | 0x0f<<27
7105         case AMOVB:
7106                 return OptionS<<10 | 0x5<<21 | 0x07<<27
7107         case AMOVBU:
7108                 return OptionS<<10 | 0x3<<21 | 0x07<<27
7109         case AFMOVS:
7110                 return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
7111         case AFMOVD:
7112                 return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
7113         }
7114         c.ctxt.Diag("bad opldrr %v\n%v", a, p)
7115         return 0
7116 }
7117
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)
7123         if extension {
7124                 OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
7125         }
7126         switch a {
7127         case AMOVD:
7128                 return OptionS<<10 | 0x1<<21 | 0x1f<<27
7129         case AMOVW, AMOVWU:
7130                 return OptionS<<10 | 0x1<<21 | 0x17<<27
7131         case AMOVH, AMOVHU:
7132                 return OptionS<<10 | 0x1<<21 | 0x0f<<27
7133         case AMOVB, AMOVBU:
7134                 return OptionS<<10 | 0x1<<21 | 0x07<<27
7135         case AFMOVS:
7136                 return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
7137         case AFMOVD:
7138                 return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
7139         }
7140         c.ctxt.Diag("bad opstrr %v\n%v", a, p)
7141         return 0
7142 }
7143
7144 func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
7145         if (v & 0xFFF000) != 0 {
7146                 if v&0xFFF != 0 {
7147                         c.ctxt.Diag("%v misuses oaddi", p)
7148                 }
7149                 v >>= 12
7150                 o1 |= 1 << 22
7151         }
7152
7153         o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
7154         return uint32(o1)
7155 }
7156
7157 /*
7158  * load a literal value into dr
7159  */
7160 func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
7161         var o1 int32
7162         if p.Pool == nil { /* not in literal pool */
7163                 c.aclass(a)
7164                 c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
7165
7166                 /* TODO: could be clever, and use general constant builder */
7167                 o1 = int32(c.opirr(p, AADD))
7168
7169                 v := int32(c.instoffset)
7170                 if v != 0 && (v&0xFFF) == 0 {
7171                         v >>= 12
7172                         o1 |= 1 << 22 /* shift, by 12 */
7173                 }
7174
7175                 o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
7176         } else {
7177                 fp, w := 0, 0
7178                 switch as {
7179                 case AFMOVS, AVMOVS:
7180                         fp = 1
7181                         w = 0 /* 32-bit SIMD/FP */
7182
7183                 case AFMOVD, AVMOVD:
7184                         fp = 1
7185                         w = 1 /* 64-bit SIMD/FP */
7186
7187                 case AVMOVQ:
7188                         fp = 1
7189                         w = 2 /* 128-bit SIMD/FP */
7190
7191                 case AMOVD:
7192                         if p.Pool.As == ADWORD {
7193                                 w = 1 /* 64-bit */
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 */
7198                         } else {
7199                                 c.ctxt.Diag("invalid operand %v in %v", a, p)
7200                         }
7201
7202                 case AMOVBU, AMOVHU, AMOVWU:
7203                         w = 0 /* 32-bit, zero-extended to 64-bit */
7204
7205                 case AMOVB, AMOVH, AMOVW:
7206                         w = 2 /* 32-bit, sign-extended to 64-bit */
7207
7208                 default:
7209                         c.ctxt.Diag("invalid operation %v in %v", as, p)
7210                 }
7211
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)
7216         }
7217
7218         return uint32(o1)
7219 }
7220
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.
7225                 mode := 64
7226                 var as1 obj.As
7227                 switch as {
7228                 case AMOVW:
7229                         as1 = AORRW
7230                         mode = 32
7231                 case AMOVD:
7232                         as1 = AORR
7233                 }
7234                 o1 = c.opirr(p, as1)
7235                 o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
7236                 return o1
7237         }
7238
7239         if as == AMOVW {
7240                 d := uint32(a.Offset)
7241                 s := movcon(int64(d))
7242                 if s < 0 || 16*s >= 32 {
7243                         d = ^d
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)
7247                         }
7248                         o1 = c.opirr(p, AMOVNW)
7249                 } else {
7250                         o1 = c.opirr(p, AMOVZW)
7251                 }
7252                 o1 |= MOVCONST(int64(d), s, rt)
7253         }
7254         if as == AMOVD {
7255                 d := a.Offset
7256                 s := movcon(d)
7257                 if s < 0 || 16*s >= 64 {
7258                         d = ^d
7259                         s = movcon(d)
7260                         if s < 0 || 16*s >= 64 {
7261                                 c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
7262                         }
7263                         o1 = c.opirr(p, AMOVN)
7264                 } else {
7265                         o1 = c.opirr(p, AMOVZ)
7266                 }
7267                 o1 |= MOVCONST(d, s, rt)
7268         }
7269         return o1
7270 }
7271
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) {
7275         switch as {
7276         case AMOVW:
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)
7283                 return 2
7284
7285         case AMOVD:
7286                 d := a.Offset
7287                 dn := ^d
7288                 var immh [4]uint64
7289                 var i int
7290                 zeroCount := int(0)
7291                 negCount := int(0)
7292                 for i = 0; i < 4; i++ {
7293                         immh[i] = uint64((d >> uint(i*16)) & 0xffff)
7294                         if immh[i] == 0 {
7295                                 zeroCount++
7296                         } else if immh[i] == 0xffff {
7297                                 negCount++
7298                         }
7299                 }
7300
7301                 if zeroCount == 4 || negCount == 4 {
7302                         c.ctxt.Diag("the immediate should be MOVCON: %v", p)
7303                 }
7304                 switch {
7305                 case zeroCount == 3:
7306                         // one MOVZ
7307                         for i = 0; i < 4; i++ {
7308                                 if immh[i] != 0 {
7309                                         os[0] = c.opirr(p, AMOVZ)
7310                                         os[0] |= MOVCONST(d, i, rt)
7311                                         break
7312                                 }
7313                         }
7314                         return 1
7315
7316                 case negCount == 3:
7317                         // one MOVN
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)
7322                                         break
7323                                 }
7324                         }
7325                         return 1
7326
7327                 case zeroCount == 2:
7328                         // one MOVZ and one MOVK
7329                         for i = 0; i < 4; i++ {
7330                                 if immh[i] != 0 {
7331                                         os[0] = c.opirr(p, AMOVZ)
7332                                         os[0] |= MOVCONST(d, i, rt)
7333                                         i++
7334                                         break
7335                                 }
7336                         }
7337                         for ; i < 4; i++ {
7338                                 if immh[i] != 0 {
7339                                         os[1] = c.opirr(p, AMOVK)
7340                                         os[1] |= MOVCONST(d, i, rt)
7341                                 }
7342                         }
7343                         return 2
7344
7345                 case negCount == 2:
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)
7351                                         i++
7352                                         break
7353                                 }
7354                         }
7355                         for ; i < 4; i++ {
7356                                 if immh[i] != 0xffff {
7357                                         os[1] = c.opirr(p, AMOVK)
7358                                         os[1] |= MOVCONST(d, i, rt)
7359                                 }
7360                         }
7361                         return 2
7362
7363                 case zeroCount == 1:
7364                         // one MOVZ and two MOVKs
7365                         for i = 0; i < 4; i++ {
7366                                 if immh[i] != 0 {
7367                                         os[0] = c.opirr(p, AMOVZ)
7368                                         os[0] |= MOVCONST(d, i, rt)
7369                                         i++
7370                                         break
7371                                 }
7372                         }
7373
7374                         for j := 1; i < 4; i++ {
7375                                 if immh[i] != 0 {
7376                                         os[j] = c.opirr(p, AMOVK)
7377                                         os[j] |= MOVCONST(d, i, rt)
7378                                         j++
7379                                 }
7380                         }
7381                         return 3
7382
7383                 case negCount == 1:
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)
7389                                         i++
7390                                         break
7391                                 }
7392                         }
7393
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)
7398                                         j++
7399                                 }
7400                         }
7401                         return 3
7402
7403                 default:
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)
7410                         }
7411                         return 4
7412                 }
7413         default:
7414                 return 0
7415         }
7416 }
7417
7418 func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
7419         var b uint32
7420         o := c.opirr(p, a)
7421         if (o & (1 << 31)) == 0 {
7422                 b = 32
7423         } else {
7424                 b = 64
7425         }
7426         if r < 0 || uint32(r) >= b {
7427                 c.ctxt.Diag("illegal bit number\n%v", p)
7428         }
7429         o |= (uint32(r) & 0x3F) << 16
7430         if s < 0 || uint32(s) >= b {
7431                 c.ctxt.Diag("illegal bit number\n%v", p)
7432         }
7433         o |= (uint32(s) & 0x3F) << 10
7434         o |= (uint32(rf&31) << 5) | uint32(rt&31)
7435         return o
7436 }
7437
7438 func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
7439         var b uint32
7440         o := c.opirr(p, a)
7441         if (o & (1 << 31)) != 0 {
7442                 b = 63
7443         } else {
7444                 b = 31
7445         }
7446         if v < 0 || uint32(v) > b {
7447                 c.ctxt.Diag("illegal bit number\n%v", p)
7448         }
7449         o |= uint32(v) << 10
7450         o |= uint32(rn&31) << 5
7451         o |= uint32(rm&31) << 16
7452         o |= uint32(rt & 31)
7453         return o
7454 }
7455
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 {
7458         wback := false
7459         if o.scond == C_XPOST || o.scond == C_XPRE {
7460                 wback = true
7461         }
7462         switch p.As {
7463         case ALDP, ALDPW, ALDPSW:
7464                 c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7465         case ASTP, ASTPW:
7466                 if wback {
7467                         c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
7468                 }
7469         case AFLDPD, AFLDPQ, AFLDPS:
7470                 c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
7471         }
7472         var ret uint32
7473         // check offset
7474         switch p.As {
7475         case AFLDPQ, AFSTPQ:
7476                 if vo < -1024 || vo > 1008 || vo%16 != 0 {
7477                         c.ctxt.Diag("invalid offset %v\n", p)
7478                 }
7479                 vo /= 16
7480                 ret = 2<<30 | 1<<26
7481         case AFLDPD, AFSTPD:
7482                 if vo < -512 || vo > 504 || vo%8 != 0 {
7483                         c.ctxt.Diag("invalid offset %v\n", p)
7484                 }
7485                 vo /= 8
7486                 ret = 1<<30 | 1<<26
7487         case AFLDPS, AFSTPS:
7488                 if vo < -256 || vo > 252 || vo%4 != 0 {
7489                         c.ctxt.Diag("invalid offset %v\n", p)
7490                 }
7491                 vo /= 4
7492                 ret = 1 << 26
7493         case ALDP, ASTP:
7494                 if vo < -512 || vo > 504 || vo%8 != 0 {
7495                         c.ctxt.Diag("invalid offset %v\n", p)
7496                 }
7497                 vo /= 8
7498                 ret = 2 << 30
7499         case ALDPW, ASTPW:
7500                 if vo < -256 || vo > 252 || vo%4 != 0 {
7501                         c.ctxt.Diag("invalid offset %v\n", p)
7502                 }
7503                 vo /= 4
7504                 ret = 0
7505         case ALDPSW:
7506                 if vo < -256 || vo > 252 || vo%4 != 0 {
7507                         c.ctxt.Diag("invalid offset %v\n", p)
7508                 }
7509                 vo /= 4
7510                 ret = 1 << 30
7511         default:
7512                 c.ctxt.Diag("invalid instruction %v\n", p)
7513         }
7514         // check register pair
7515         switch p.As {
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)
7519                 }
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)
7523                 }
7524         case ASTP, ASTPW:
7525                 if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
7526                         c.ctxt.Diag("invalid register pair %v\n", p)
7527                 }
7528         }
7529         // other conditional flag bits
7530         switch o.scond {
7531         case C_XPOST:
7532                 ret |= 1 << 23
7533         case C_XPRE:
7534                 ret |= 3 << 23
7535         default:
7536                 ret |= 2 << 23
7537         }
7538         ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
7539         return ret
7540 }
7541
7542 func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
7543         if p.As == AVLD1 || p.As == AVST1 {
7544                 return o1
7545         }
7546
7547         o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
7548         switch p.As {
7549         case AVLD1R, AVLD2R:
7550                 o1 |= 0xC << 12
7551         case AVLD3R, AVLD4R:
7552                 o1 |= 0xE << 12
7553         case AVLD2, AVST2:
7554                 o1 |= 8 << 12
7555         case AVLD3, AVST3:
7556                 o1 |= 4 << 12
7557         case AVLD4, AVST4:
7558         default:
7559                 c.ctxt.Diag("unsupported instruction:%v\n", p.As)
7560         }
7561         return o1
7562 }
7563
7564 /*
7565  * size in log2(bytes)
7566  */
7567 func movesize(a obj.As) int {
7568         switch a {
7569         case AFMOVQ:
7570                 return 4
7571
7572         case AMOVD, AFMOVD:
7573                 return 3
7574
7575         case AMOVW, AMOVWU, AFMOVS:
7576                 return 2
7577
7578         case AMOVH, AMOVHU:
7579                 return 1
7580
7581         case AMOVB, AMOVBU:
7582                 return 0
7583
7584         default:
7585                 return -1
7586         }
7587 }
7588
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
7592 }
7593
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 {
7596         var num, rm int16
7597         num = (r >> 5) & 7
7598         rm = r & 31
7599         switch {
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 {
7606                         if num == 0 {
7607                                 return roff(rm, 2, 2)
7608                         } else {
7609                                 return roff(rm, 2, 6)
7610                         }
7611                 } else {
7612                         return roff(rm, 2, num)
7613                 }
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 {
7622                         if num == 0 {
7623                                 return roff(rm, 6, 2)
7624                         } else {
7625                                 return roff(rm, 6, 6)
7626                         }
7627                 } else {
7628                         return roff(rm, 6, num)
7629                 }
7630         case REG_SXTX <= r && r < REG_SPECIAL:
7631                 if a.Type == obj.TYPE_MEM {
7632                         if num == 0 {
7633                                 return roff(rm, 7, 2)
7634                         } else {
7635                                 return roff(rm, 7, 6)
7636                         }
7637                 } else {
7638                         return roff(rm, 7, num)
7639                 }
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)
7645                 }
7646                 return roff(rm, 3, num)
7647         default:
7648                 c.ctxt.Diag("unsupported register extension type.")
7649         }
7650
7651         return 0
7652 }
7653
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)
7657 }