neon64.isa revision 11165:d90aec9435bd
1// Copyright (c) 2012-2013 ARM Limited
2// All rights reserved
3//
4// The license below extends only to copyright in the software and shall
5// not be construed as granting a license to any other intellectual
6// property including but not limited to intellectual property relating
7// to a hardware implementation of the functionality of the software
8// licensed hereunder.  You may use the software subject to the license
9// terms below provided that you ensure that this notice is replicated
10// unmodified and in its entirety in all distributions of the software,
11// modified or unmodified, in source code or in binary form.
12//
13// Redistribution and use in source and binary forms, with or without
14// modification, are permitted provided that the following conditions are
15// met: redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer;
17// redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution;
20// neither the name of the copyright holders nor the names of its
21// contributors may be used to endorse or promote products derived from
22// this software without specific prior written permission.
23//
24// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35//
36// Authors: Giacomo Gabrielli
37//          Mbou Eyole
38
39output header {{
40namespace Aarch64
41{
42    // AdvSIMD three same
43    template <typename DecoderFeatures>
44    StaticInstPtr decodeNeon3Same(ExtMachInst machInst);
45    // AdvSIMD three different
46    inline StaticInstPtr decodeNeon3Diff(ExtMachInst machInst);
47    // AdvSIMD two-reg misc
48    inline StaticInstPtr decodeNeon2RegMisc(ExtMachInst machInst);
49    // AdvSIMD across lanes
50    inline StaticInstPtr decodeNeonAcrossLanes(ExtMachInst machInst);
51    // AdvSIMD copy
52    inline StaticInstPtr decodeNeonCopy(ExtMachInst machInst);
53    // AdvSIMD vector x indexed element
54    template <typename DecoderFeatures>
55    StaticInstPtr decodeNeonIndexedElem(ExtMachInst machInst);
56    // AdvSIMD modified immediate
57    inline StaticInstPtr decodeNeonModImm(ExtMachInst machInst);
58    // AdvSIMD shift by immediate
59    inline StaticInstPtr decodeNeonShiftByImm(ExtMachInst machInst);
60    // AdvSIMD TBL/TBX
61    inline StaticInstPtr decodeNeonTblTbx(ExtMachInst machInst);
62    // AdvSIMD ZIP/UZP/TRN
63    inline StaticInstPtr decodeNeonZipUzpTrn(ExtMachInst machInst);
64    // AdvSIMD EXT
65    inline StaticInstPtr decodeNeonExt(ExtMachInst machInst);
66
67    // AdvSIMD scalar three same
68    inline StaticInstPtr decodeNeonSc3Same(ExtMachInst machInst);
69    // AdvSIMD scalar three different
70    inline StaticInstPtr decodeNeonSc3Diff(ExtMachInst machInst);
71    // AdvSIMD scalar two-reg misc
72    inline StaticInstPtr decodeNeonSc2RegMisc(ExtMachInst machInst);
73    // AdvSIMD scalar pairwise
74    inline StaticInstPtr decodeNeonScPwise(ExtMachInst machInst);
75    // AdvSIMD scalar copy
76    inline StaticInstPtr decodeNeonScCopy(ExtMachInst machInst);
77    // AdvSIMD scalar x indexed element
78    inline StaticInstPtr decodeNeonScIndexedElem(ExtMachInst machInst);
79    // AdvSIMD scalar shift by immediate
80    inline StaticInstPtr decodeNeonScShiftByImm(ExtMachInst machInst);
81
82    // AdvSIMD load/store
83    inline StaticInstPtr decodeNeonMem(ExtMachInst machInst);
84}
85}};
86
87output decoder {{
88namespace Aarch64
89{
90    template <typename DecoderFeatures>
91    StaticInstPtr
92    decodeNeon3Same(ExtMachInst machInst)
93    {
94        uint8_t q = bits(machInst, 30);
95        uint8_t u = bits(machInst, 29);
96        uint8_t size = bits(machInst, 23, 22);
97        uint8_t opcode = bits(machInst, 15, 11);
98
99        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
100        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
101        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
102
103        uint8_t size_q = (size << 1) | q;
104        uint8_t sz_q = size_q & 0x3;
105
106        switch (opcode) {
107          case 0x00:
108            if (size == 0x3)
109                return new Unknown64(machInst);
110            if (u)
111                return decodeNeonUThreeSReg<UhaddDX, UhaddQX>(
112                    q, size, machInst, vd, vn, vm);
113            else
114                return decodeNeonSThreeSReg<ShaddDX, ShaddQX>(
115                    q, size, machInst, vd, vn, vm);
116          case 0x01:
117            if (size_q == 0x6)
118                return new Unknown64(machInst);
119            if (u)
120                return decodeNeonUThreeXReg<UqaddDX, UqaddQX>(
121                    q, size, machInst, vd, vn, vm);
122            else
123                return decodeNeonSThreeXReg<SqaddDX, SqaddQX>(
124                    q, size, machInst, vd, vn, vm);
125          case 0x02:
126            if (size == 0x3)
127                return new Unknown64(machInst);
128            if (u)
129                return decodeNeonUThreeSReg<UrhaddDX, UrhaddQX>(
130                    q, size, machInst, vd, vn, vm);
131            else
132                return decodeNeonSThreeSReg<SrhaddDX, SrhaddQX>(
133                    q, size, machInst, vd, vn, vm);
134          case 0x03:
135            switch (size) {
136              case 0x0:
137                if (u) {
138                    if (q)
139                        return new EorQX<uint64_t>(machInst, vd, vn, vm);
140                    else
141                        return new EorDX<uint64_t>(machInst, vd, vn, vm);
142                } else {
143                    if (q)
144                        return new AndQX<uint64_t>(machInst, vd, vn, vm);
145                    else
146                        return new AndDX<uint64_t>(machInst, vd, vn, vm);
147                }
148              case 0x1:
149                if (u) {
150                    if (q)
151                        return new BslQX<uint64_t>(machInst, vd, vn, vm);
152                    else
153                        return new BslDX<uint64_t>(machInst, vd, vn, vm);
154                } else {
155                    if (q)
156                        return new BicQX<uint64_t>(machInst, vd, vn, vm);
157                    else
158                        return new BicDX<uint64_t>(machInst, vd, vn, vm);
159                }
160              case 0x2:
161                if (u) {
162                    if (q)
163                        return new BitQX<uint64_t>(machInst, vd, vn, vm);
164                    else
165                        return new BitDX<uint64_t>(machInst, vd, vn, vm);
166                } else {
167                    if (q)
168                        return new OrrQX<uint64_t>(machInst, vd, vn, vm);
169                    else
170                        return new OrrDX<uint64_t>(machInst, vd, vn, vm);
171                }
172              case 0x3:
173                if (u) {
174                    if (q)
175                        return new BifQX<uint64_t>(machInst, vd, vn, vm);
176                    else
177                        return new BifDX<uint64_t>(machInst, vd, vn, vm);
178                } else {
179                    if (q)
180                        return new OrnQX<uint64_t>(machInst, vd, vn, vm);
181                    else
182                        return new OrnDX<uint64_t>(machInst, vd, vn, vm);
183                }
184            }
185          case 0x04:
186            if (size == 0x3)
187                return new Unknown64(machInst);
188            if (u)
189                return decodeNeonUThreeSReg<UhsubDX, UhsubQX>(
190                    q, size, machInst, vd, vn, vm);
191            else
192                return decodeNeonSThreeSReg<ShsubDX, ShsubQX>(
193                    q, size, machInst, vd, vn, vm);
194          case 0x05:
195            if (size_q == 0x6)
196                return new Unknown64(machInst);
197            if (u)
198                return decodeNeonUThreeXReg<UqsubDX, UqsubQX>(
199                    q, size, machInst, vd, vn, vm);
200            else
201                return decodeNeonSThreeXReg<SqsubDX, SqsubQX>(
202                    q, size, machInst, vd, vn, vm);
203          case 0x06:
204            if (size_q == 0x6)
205                return new Unknown64(machInst);
206            if (u)
207                return decodeNeonUThreeXReg<CmhiDX, CmhiQX>(
208                    q, size, machInst, vd, vn, vm);
209            else
210                return decodeNeonSThreeXReg<CmgtDX, CmgtQX>(
211                    q, size, machInst, vd, vn, vm);
212          case 0x07:
213            if (size_q == 0x6)
214                return new Unknown64(machInst);
215            if (u)
216                return decodeNeonUThreeXReg<CmhsDX, CmhsQX>(
217                    q, size, machInst, vd, vn, vm);
218            else
219                return decodeNeonSThreeXReg<CmgeDX, CmgeQX>(
220                    q, size, machInst, vd, vn, vm);
221          case 0x08:
222            if (size_q == 0x6)
223                return new Unknown64(machInst);
224            if (u)
225                return decodeNeonUThreeXReg<UshlDX, UshlQX>(
226                    q, size, machInst, vd, vn, vm);
227            else
228                return decodeNeonSThreeXReg<SshlDX, SshlQX>(
229                    q, size, machInst, vd, vn, vm);
230          case 0x09:
231            if (size_q == 0x6)
232                return new Unknown64(machInst);
233            if (u)
234                return decodeNeonUThreeXReg<UqshlDX, UqshlQX>(
235                    q, size, machInst, vd, vn, vm);
236            else
237                return decodeNeonSThreeXReg<SqshlDX, SqshlQX>(
238                    q, size, machInst, vd, vn, vm);
239          case 0x0a:
240            if (size_q == 0x6)
241                return new Unknown64(machInst);
242            if (u)
243                return decodeNeonUThreeXReg<UrshlDX, UrshlQX>(
244                    q, size, machInst, vd, vn, vm);
245            else
246                return decodeNeonSThreeXReg<SrshlDX, SrshlQX>(
247                    q, size, machInst, vd, vn, vm);
248          case 0x0b:
249            if (size_q == 0x6)
250                return new Unknown64(machInst);
251            if (u)
252                return decodeNeonUThreeXReg<UqrshlDX, UqrshlQX>(
253                    q, size, machInst, vd, vn, vm);
254            else
255                return decodeNeonSThreeXReg<SqrshlDX, SqrshlQX>(
256                    q, size, machInst, vd, vn, vm);
257          case 0x0c:
258            if (size == 0x3)
259                return new Unknown64(machInst);
260            if (u)
261                return decodeNeonUThreeSReg<UmaxDX, UmaxQX>(
262                    q, size, machInst, vd, vn, vm);
263            else
264                return decodeNeonSThreeSReg<SmaxDX, SmaxQX>(
265                    q, size, machInst, vd, vn, vm);
266          case 0x0d:
267            if (size == 0x3)
268                return new Unknown64(machInst);
269            if (u)
270                return decodeNeonUThreeSReg<UminDX, UminQX>(
271                    q, size, machInst, vd, vn, vm);
272            else
273                return decodeNeonSThreeSReg<SminDX, SminQX>(
274                    q, size, machInst, vd, vn, vm);
275          case 0x0e:
276            if (size == 0x3)
277                return new Unknown64(machInst);
278            if (u)
279                return decodeNeonUThreeSReg<UabdDX, UabdQX>(
280                    q, size, machInst, vd, vn, vm);
281            else
282                return decodeNeonSThreeSReg<SabdDX, SabdQX>(
283                    q, size, machInst, vd, vn, vm);
284          case 0x0f:
285            if (size == 0x3)
286                return new Unknown64(machInst);
287            if (u)
288                return decodeNeonUThreeSReg<UabaDX, UabaQX>(
289                    q, size, machInst, vd, vn, vm);
290            else
291                return decodeNeonSThreeSReg<SabaDX, SabaQX>(
292                    q, size, machInst, vd, vn, vm);
293          case 0x10:
294            if (size_q == 0x6)
295                return new Unknown64(machInst);
296            if (u)
297                return decodeNeonUThreeXReg<SubDX, SubQX>(
298                    q, size, machInst, vd, vn, vm);
299            else
300                return decodeNeonUThreeXReg<AddDX, AddQX>(
301                    q, size, machInst, vd, vn, vm);
302          case 0x11:
303            if (size_q == 0x6)
304                return new Unknown64(machInst);
305            if (u)
306                return decodeNeonUThreeXReg<CmeqDX, CmeqQX>(
307                    q, size, machInst, vd, vn, vm);
308            else
309                return decodeNeonUThreeXReg<CmtstDX, CmtstQX>(
310                    q, size, machInst, vd, vn, vm);
311          case 0x12:
312            if (size == 0x3)
313                return new Unknown64(machInst);
314            if (u)
315                return decodeNeonUThreeSReg<MlsDX, MlsQX>(
316                    q, size, machInst, vd, vn, vm);
317            else
318                return decodeNeonUThreeSReg<MlaDX, MlaQX>(
319                    q, size, machInst, vd, vn, vm);
320          case 0x13:
321            if (size == 0x3 || (size != 0x0 && bits(machInst, 29)))
322                return new Unknown64(machInst);
323            if (u) {
324                if (q)
325                    return new PmulQX<uint8_t>(machInst, vd, vn, vm);
326                else
327                    return new PmulDX<uint8_t>(machInst, vd, vn, vm);
328            } else {
329                return decodeNeonUThreeSReg<MulDX, MulQX>(
330                    q, size, machInst, vd, vn, vm);
331            }
332          case 0x14:
333            if (size == 0x3)
334                return new Unknown64(machInst);
335            if (u)
336                return decodeNeonUThreeSReg<UmaxpDX, UmaxpQX>(
337                    q, size, machInst, vd, vn, vm);
338            else
339                return decodeNeonSThreeSReg<SmaxpDX, SmaxpQX>(
340                    q, size, machInst, vd, vn, vm);
341          case 0x15:
342            if (size == 0x3)
343                return new Unknown64(machInst);
344            if (u)
345                return decodeNeonUThreeSReg<UminpDX, UminpQX>(
346                    q, size, machInst, vd, vn, vm);
347            else
348                return decodeNeonSThreeSReg<SminpDX, SminpQX>(
349                    q, size, machInst, vd, vn, vm);
350          case 0x16:
351            if (size == 0x3 || size == 0x0)
352                return new Unknown64(machInst);
353            if (u) {
354                if (q)
355                    return decodeNeonSThreeHAndWReg<SqrdmulhQX>(
356                        size, machInst, vd, vn, vm);
357                else
358                    return decodeNeonSThreeHAndWReg<SqrdmulhDX>(
359                        size, machInst, vd, vn, vm);
360            } else {
361                if (q)
362                    return decodeNeonSThreeHAndWReg<SqdmulhQX>(
363                        size, machInst, vd, vn, vm);
364                else
365                    return decodeNeonSThreeHAndWReg<SqdmulhDX>(
366                        size, machInst, vd, vn, vm);
367            }
368          case 0x17:
369            if (u || size_q == 0x6)
370                return new Unknown64(machInst);
371            else
372                return decodeNeonUThreeXReg<AddpDX, AddpQX>(
373                    q, size, machInst, vd, vn, vm);
374          case 0x18:
375            if (sz_q == 0x2)
376                return new Unknown64(machInst);
377            if (size < 0x2) {
378                if (u)
379                    return decodeNeonUThreeFpReg<FmaxnmpDX, FmaxnmpQX>(
380                        q, size & 0x1, machInst, vd, vn, vm);
381                else
382                    return decodeNeonUThreeFpReg<FmaxnmDX, FmaxnmQX>(
383                        q, size & 0x1, machInst, vd, vn, vm);
384            } else {
385                if (u)
386                    return decodeNeonUThreeFpReg<FminnmpDX, FminnmpQX>(
387                        q, size & 0x1, machInst, vd, vn, vm);
388                else
389                    return decodeNeonUThreeFpReg<FminnmDX, FminnmQX>(
390                        q, size & 0x1, machInst, vd, vn, vm);
391            }
392          case 0x19:
393            if (size < 0x2) {
394                if (u || sz_q == 0x2)
395                    return new Unknown64(machInst);
396                else
397                    return decodeNeonUThreeFpReg<FmlaDX, FmlaQX>(
398                        q, size & 0x1, machInst, vd, vn, vm);
399            } else {
400                if (u || sz_q == 0x2)
401                    return new Unknown64(machInst);
402                else
403                    return decodeNeonUThreeFpReg<FmlsDX, FmlsQX>(
404                        q, size & 0x1, machInst, vd, vn, vm);
405            }
406          case 0x1a:
407            if (sz_q == 0x2)
408                return new Unknown64(machInst);
409            if (size < 0x2) {
410                if (u)
411                    return decodeNeonUThreeFpReg<FaddpDX, FaddpQX>(
412                        q, size & 0x1, machInst, vd, vn, vm);
413                else
414                    return decodeNeonUThreeFpReg<FaddDX, FaddQX>(
415                        q, size & 0x1, machInst, vd, vn, vm);
416            } else {
417                if (u)
418                    return decodeNeonUThreeFpReg<FabdDX, FabdQX>(
419                        q, size & 0x1, machInst, vd, vn, vm);
420                else
421                    return decodeNeonUThreeFpReg<FsubDX, FsubQX>(
422                        q, size & 0x1, machInst, vd, vn, vm);
423            }
424          case 0x1b:
425            if (size < 0x2 && sz_q != 0x2) {
426                if (u)
427                    return decodeNeonUThreeFpReg<FmulDX, FmulQX>(
428                        q, size & 0x1, machInst, vd, vn, vm);
429                else
430                    return decodeNeonUThreeFpReg<FmulxDX, FmulxQX>(
431                        q, size & 0x1, machInst, vd, vn, vm);
432            } else {
433                return new Unknown64(machInst);
434            }
435          case 0x1c:
436            if (size < 0x2) {
437                if (u)
438                    return decodeNeonUThreeFpReg<FcmgeDX, FcmgeQX>(
439                        q, size & 0x1, machInst, vd, vn, vm);
440                else
441                    return decodeNeonUThreeFpReg<FcmeqDX, FcmeqQX>(
442                        q, size & 0x1, machInst, vd, vn, vm);
443            } else {
444                if (u)
445                    return decodeNeonUThreeFpReg<FcmgtDX, FcmgtQX>(
446                        q, size & 0x1, machInst, vd, vn, vm);
447                else
448                    return new Unknown64(machInst);
449            }
450          case 0x1d:
451            if (size < 0x2) {
452                if (u)
453                    return decodeNeonUThreeFpReg<FacgeDX, FacgeQX>(
454                        q, size & 0x1, machInst, vd, vn, vm);
455                else
456                    return new Unknown64(machInst);
457            } else {
458                if (u)
459                    return decodeNeonUThreeFpReg<FacgtDX, FacgtQX>(
460                        q, size & 0x1, machInst, vd, vn, vm);
461                else
462                    return new Unknown64(machInst);
463            }
464          case 0x1e:
465            if (sz_q == 0x2)
466                return new Unknown64(machInst);
467            if (size < 0x2) {
468                if (u)
469                    return decodeNeonUThreeFpReg<FmaxpDX, FmaxpQX>(
470                        q, size & 0x1, machInst, vd, vn, vm);
471                else
472                    return decodeNeonUThreeFpReg<FmaxDX, FmaxQX>(
473                        q, size & 0x1, machInst, vd, vn, vm);
474            } else {
475                if (u)
476                    return decodeNeonUThreeFpReg<FminpDX, FminpQX>(
477                        q, size & 0x1, machInst, vd, vn, vm);
478                else
479                    return decodeNeonUThreeFpReg<FminDX, FminQX>(
480                        q, size & 0x1, machInst, vd, vn, vm);
481            }
482          case 0x1f:
483            if (sz_q == 0x2)
484                return new Unknown64(machInst);
485            if (size < 0x2) {
486                if (u)
487                    return decodeNeonUThreeFpReg<FdivDX, FdivQX>(
488                        q, size & 0x1, machInst, vd, vn, vm);
489                else
490                    return decodeNeonUThreeFpReg<FrecpsDX, FrecpsQX>(
491                        q, size & 0x1, machInst, vd, vn, vm);
492            } else {
493                if (u)
494                    return new Unknown64(machInst);
495                else
496                    return decodeNeonUThreeFpReg<FrsqrtsDX, FrsqrtsQX>(
497                        q, size & 0x1, machInst, vd, vn, vm);
498            }
499          default:
500            return new Unknown64(machInst);
501        }
502    }
503
504    StaticInstPtr
505    decodeNeon3Diff(ExtMachInst machInst)
506    {
507        uint8_t q = bits(machInst, 30);
508        uint8_t u = bits(machInst, 29);
509        uint8_t size = bits(machInst, 23, 22);
510        uint8_t opcode = bits(machInst, 15, 12);
511
512        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
513        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
514        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
515
516        switch (opcode) {
517          case 0x0:
518            if (size == 0x3)
519                return new Unknown64(machInst);
520            if (u)
521                return decodeNeonUThreeSReg<UaddlX, Uaddl2X>(
522                    q, size, machInst, vd, vn, vm);
523            else
524                return decodeNeonSThreeSReg<SaddlX, Saddl2X>(
525                    q, size, machInst, vd, vn, vm);
526          case 0x1:
527            if (size == 0x3)
528                return new Unknown64(machInst);
529            if (u)
530                return decodeNeonUThreeSReg<UaddwX, Uaddw2X>(
531                    q, size, machInst, vd, vn, vm);
532            else
533                return decodeNeonSThreeSReg<SaddwX, Saddw2X>(
534                    q, size, machInst, vd, vn, vm);
535          case 0x2:
536            if (size == 0x3)
537                return new Unknown64(machInst);
538            if (u)
539                return decodeNeonUThreeSReg<UsublX, Usubl2X>(
540                    q, size, machInst, vd, vn, vm);
541            else
542                return decodeNeonSThreeSReg<SsublX, Ssubl2X>(
543                    q, size, machInst, vd, vn, vm);
544          case 0x3:
545            if (size == 0x3)
546                return new Unknown64(machInst);
547            if (u)
548                return decodeNeonUThreeSReg<UsubwX, Usubw2X>(
549                    q, size, machInst, vd, vn, vm);
550            else
551                return decodeNeonSThreeSReg<SsubwX, Ssubw2X>(
552                    q, size, machInst, vd, vn, vm);
553          case 0x4:
554            if (size == 0x3)
555                return new Unknown64(machInst);
556            if (u)
557                return decodeNeonUThreeSReg<RaddhnX, Raddhn2X>(
558                    q, size, machInst, vd, vn, vm);
559            else
560                return decodeNeonUThreeSReg<AddhnX, Addhn2X>(
561                    q, size, machInst, vd, vn, vm);
562          case 0x5:
563            if (size == 0x3)
564                return new Unknown64(machInst);
565            if (u)
566                return decodeNeonUThreeSReg<UabalX, Uabal2X>(
567                    q, size, machInst, vd, vn, vm);
568            else
569                return decodeNeonSThreeSReg<SabalX, Sabal2X>(
570                    q, size, machInst, vd, vn, vm);
571          case 0x6:
572            if (size == 0x3)
573                return new Unknown64(machInst);
574            if (u)
575                return decodeNeonUThreeSReg<RsubhnX, Rsubhn2X>(
576                    q, size, machInst, vd, vn, vm);
577            else
578                return decodeNeonUThreeSReg<SubhnX, Subhn2X>(
579                    q, size, machInst, vd, vn, vm);
580          case 0x7:
581            if (size == 0x3)
582                return new Unknown64(machInst);
583            if (u)
584                return decodeNeonUThreeSReg<UabdlX, Uabdl2X>(
585                    q, size, machInst, vd, vn, vm);
586            else
587                return decodeNeonSThreeSReg<SabdlX, Sabdl2X>(
588                    q, size, machInst, vd, vn, vm);
589          case 0x8:
590            if (size == 0x3)
591                return new Unknown64(machInst);
592            if (u)
593                return decodeNeonUThreeSReg<UmlalX, Umlal2X>(
594                    q, size, machInst, vd, vn, vm);
595            else
596                return decodeNeonSThreeSReg<SmlalX, Smlal2X>(
597                    q, size, machInst, vd, vn, vm);
598          case 0x9:
599            if (u || (size == 0x0 || size == 0x3)) {
600                return new Unknown64(machInst);
601            } else {
602                if (q) {
603                    return decodeNeonSThreeHAndWReg<Sqdmlal2X>(
604                        size, machInst, vd, vn, vm);
605                } else {
606                    return decodeNeonSThreeHAndWReg<SqdmlalX>(
607                        size, machInst, vd, vn, vm);
608                }
609            }
610          case 0xa:
611            if (size == 0x3)
612                return new Unknown64(machInst);
613            if (u)
614                return decodeNeonUThreeSReg<UmlslX, Umlsl2X>(
615                    q, size, machInst, vd, vn, vm);
616            else
617                return decodeNeonSThreeSReg<SmlslX, Smlsl2X>(
618                    q, size, machInst, vd, vn, vm);
619          case 0xb:
620            if (u || (size == 0x0 || size == 0x3)) {
621                return new Unknown64(machInst);
622            } else {
623                if (q) {
624                    return decodeNeonSThreeHAndWReg<Sqdmlsl2X>(
625                        size, machInst, vd, vn, vm);
626                } else {
627                    return decodeNeonSThreeHAndWReg<SqdmlslX>(
628                        size, machInst, vd, vn, vm);
629                }
630            }
631          case 0xc:
632            if (size == 0x3)
633                return new Unknown64(machInst);
634            if (u)
635                return decodeNeonUThreeSReg<UmullX, Umull2X>(
636                    q, size, machInst, vd, vn, vm);
637            else
638                return decodeNeonSThreeSReg<SmullX, Smull2X>(
639                    q, size, machInst, vd, vn, vm);
640          case 0xd:
641            if (u || (size == 0x0 || size == 0x3)) {
642                return new Unknown64(machInst);
643            } else {
644                if (q) {
645                    return decodeNeonSThreeHAndWReg<Sqdmull2X>(
646                        size, machInst, vd, vn, vm);
647                } else {
648                    return decodeNeonSThreeHAndWReg<SqdmullX>(
649                        size, machInst, vd, vn, vm);
650                }
651            }
652          case 0xe:
653            if (u || size != 0) {
654                return new Unknown64(machInst);
655            } else {
656                if (q)
657                    return new Pmull2X<uint8_t>(machInst, vd, vn, vm);
658                else
659                    return new PmullX<uint8_t>(machInst, vd, vn, vm);
660            }
661          default:
662            return new Unknown64(machInst);
663        }
664    }
665
666    StaticInstPtr
667    decodeNeon2RegMisc(ExtMachInst machInst)
668    {
669        uint8_t q = bits(machInst, 30);
670        uint8_t u = bits(machInst, 29);
671        uint8_t size = bits(machInst, 23, 22);
672        uint8_t opcode = bits(machInst, 16, 12);
673
674        IntRegIndex vd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
675        IntRegIndex vn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
676
677        uint8_t size_q = (size << 1) | q;
678        uint8_t sz_q = size_q & 0x3;
679        uint8_t op = (uint8_t)((bits(machInst, 12) << 1) |
680                               bits(machInst, 29));
681        uint8_t switchVal = opcode | ((u ? 1 : 0) << 5);
682
683        switch (switchVal) {
684          case 0x00:
685            if (op + size >= 3)
686                return new Unknown64(machInst);
687            return decodeNeonUTwoMiscSReg<Rev64DX, Rev64QX>(
688                q, size, machInst, vd, vn);
689          case 0x01:
690            if (op + size >= 3)
691                return new Unknown64(machInst);
692            if (q)
693                return new Rev16QX<uint8_t>(machInst, vd, vn);
694            else
695                return new Rev16DX<uint8_t>(machInst, vd, vn);
696          case 0x02:
697            if (size == 0x3)
698                return new Unknown64(machInst);
699            return decodeNeonSTwoMiscSReg<SaddlpDX, SaddlpQX>(
700                q, size, machInst, vd, vn);
701          case 0x03:
702            if (size_q == 0x6)
703                return new Unknown64(machInst);
704            return decodeNeonUTwoMiscXReg<SuqaddDX, SuqaddQX>(
705                q, size, machInst, vd, vn);
706          case 0x04:
707            if (size == 0x3)
708                return new Unknown64(machInst);
709            return decodeNeonSTwoMiscSReg<ClsDX, ClsQX>(
710                q, size, machInst, vd, vn);
711          case 0x05:
712            if (size != 0x0)
713                return new Unknown64(machInst);
714            if (q)
715                return new CntQX<uint8_t>(machInst, vd, vn);
716            else
717                return new CntDX<uint8_t>(machInst, vd, vn);
718          case 0x06:
719            if (size == 0x3)
720                return new Unknown64(machInst);
721            return decodeNeonSTwoMiscSReg<SadalpDX, SadalpQX>(
722                q, size, machInst, vd, vn);
723          case 0x07:
724            if (size_q == 0x6)
725                return new Unknown64(machInst);
726            return decodeNeonSTwoMiscXReg<SqabsDX, SqabsQX>(
727                q, size, machInst, vd, vn);
728          case 0x08:
729            if (size_q == 0x6)
730                return new Unknown64(machInst);
731            return decodeNeonSTwoMiscXReg<CmgtZeroDX, CmgtZeroQX>(
732                q, size, machInst, vd, vn);
733          case 0x09:
734            if (size_q == 0x6)
735                return new Unknown64(machInst);
736            return decodeNeonSTwoMiscXReg<CmeqZeroDX, CmeqZeroQX>(
737                q, size, machInst, vd, vn);
738          case 0x0a:
739            if (size_q == 0x6)
740                return new Unknown64(machInst);
741            return decodeNeonSTwoMiscXReg<CmltZeroDX, CmltZeroQX>(
742                q, size, machInst, vd, vn);
743          case 0x0b:
744            if (size_q == 0x6)
745                return new Unknown64(machInst);
746            return decodeNeonSTwoMiscXReg<AbsDX, AbsQX>(
747                q, size, machInst, vd, vn);
748          case 0x0c:
749            if (size < 0x2 || sz_q == 0x2)
750                return new Unknown64(machInst);
751            return decodeNeonUTwoMiscFpReg<FcmgtZeroDX, FcmgtZeroQX>(
752                q, size & 0x1, machInst, vd, vn);
753          case 0x0d:
754            if (size < 0x2 || sz_q == 0x2)
755                return new Unknown64(machInst);
756            return decodeNeonUTwoMiscFpReg<FcmeqZeroDX, FcmeqZeroQX>(
757                q, size & 0x1, machInst, vd, vn);
758          case 0x0e:
759            if (size < 0x2 || sz_q == 0x2)
760                return new Unknown64(machInst);
761            return decodeNeonUTwoMiscFpReg<FcmltZeroDX, FcmltZeroQX>(
762                q, size & 0x1, machInst, vd, vn);
763          case 0x0f:
764            if (size < 0x2 || sz_q == 0x2)
765                return new Unknown64(machInst);
766            return decodeNeonUTwoMiscFpReg<FabsDX, FabsQX>(
767                q, size & 0x1, machInst, vd, vn);
768          case 0x12:
769            if (size == 0x3)
770                return new Unknown64(machInst);
771            return decodeNeonUTwoMiscSReg<XtnX, Xtn2X>(
772                q, size, machInst, vd, vn);
773          case 0x14:
774            if (size == 0x3)
775                return new Unknown64(machInst);
776            return decodeNeonSTwoMiscSReg<SqxtnX, Sqxtn2X>(
777                q, size, machInst, vd, vn);
778          case 0x16:
779            if (size > 0x1)
780                return new Unknown64(machInst);
781            if (q) {
782                if (size)
783                    return new Fcvtn2X<uint32_t>(machInst, vd, vn);
784                else
785                    return new Fcvtn2X<uint16_t>(machInst, vd, vn);
786            } else {
787                if (size)
788                    return new FcvtnX<uint32_t>(machInst, vd, vn);
789                else
790                    return new FcvtnX<uint16_t>(machInst, vd, vn);
791            }
792          case 0x17:
793            if (size > 0x1)
794                return new Unknown64(machInst);
795            if (q) {
796                if (size)
797                    return new Fcvtl2X<uint32_t>(machInst, vd, vn);
798                else
799                    return new Fcvtl2X<uint16_t>(machInst, vd, vn);
800            } else {
801                if (size)
802                    return new FcvtlX<uint32_t>(machInst, vd, vn);
803                else
804                    return new FcvtlX<uint16_t>(machInst, vd, vn);
805            }
806          case 0x18:
807            if (sz_q == 0x2)
808                return new Unknown64(machInst);
809            if (size < 0x2)
810                return decodeNeonUTwoMiscFpReg<FrintnDX, FrintnQX>(
811                    q, size & 0x1, machInst, vd, vn);
812            else
813                return decodeNeonUTwoMiscFpReg<FrintpDX, FrintpQX>(
814                    q, size & 0x1, machInst, vd, vn);
815          case 0x19:
816            if (sz_q == 0x2)
817                return new Unknown64(machInst);
818            if (size < 0x2)
819                return decodeNeonUTwoMiscFpReg<FrintmDX, FrintmQX>(
820                    q, size & 0x1, machInst, vd, vn);
821            else
822                return decodeNeonUTwoMiscFpReg<FrintzDX, FrintzQX>(
823                    q, size & 0x1, machInst, vd, vn);
824          case 0x1a:
825            if (sz_q == 0x2)
826                return new Unknown64(machInst);
827            if (size < 0x2)
828                return decodeNeonUTwoMiscFpReg<FcvtnsDX, FcvtnsQX>(
829                    q, size & 0x1, machInst, vd, vn);
830            else
831                return decodeNeonUTwoMiscFpReg<FcvtpsDX, FcvtpsQX>(
832                    q, size & 0x1, machInst, vd, vn);
833          case 0x1b:
834            if (sz_q == 0x2)
835                return new Unknown64(machInst);
836            if (size < 0x2)
837                return decodeNeonUTwoMiscFpReg<FcvtmsDX, FcvtmsQX>(
838                    q, size & 0x1, machInst, vd, vn);
839            else
840                return decodeNeonUTwoMiscFpReg<FcvtzsIntDX, FcvtzsIntQX>(
841                    q, size & 0x1, machInst, vd, vn);
842          case 0x1c:
843            if (size < 0x2) {
844                if (sz_q == 0x2)
845                    return new Unknown64(machInst);
846                return decodeNeonUTwoMiscFpReg<FcvtasDX, FcvtasQX>(
847                    q, size & 0x1, machInst, vd, vn);
848            } else {
849                if (size & 0x1)
850                    return new Unknown64(machInst);
851                if (q)
852                    return new UrecpeQX<uint32_t>(machInst, vd, vn);
853                else
854                    return new UrecpeDX<uint32_t>(machInst, vd, vn);
855            }
856          case 0x1d:
857            if (sz_q == 0x2)
858                return new Unknown64(machInst);
859            if (size < 0x2) {
860                if (q) {
861                    if (size & 0x1)
862                        return new ScvtfIntDQX<uint64_t>(machInst, vd, vn);
863                    else
864                        return new ScvtfIntSQX<uint32_t>(machInst, vd, vn);
865                } else {
866                    if (size & 0x1)
867                        return new Unknown(machInst);
868                    else
869                        return new ScvtfIntDX<uint32_t>(machInst, vd, vn);
870                }
871            } else {
872                return decodeNeonUTwoMiscFpReg<FrecpeDX, FrecpeQX>(
873                    q, size & 0x1, machInst, vd, vn);
874            }
875          case 0x20:
876            if (op + size >= 3)
877                return new Unknown64(machInst);
878            if (q) {
879                if (size & 0x1)
880                    return new Rev32QX<uint16_t>(machInst, vd, vn);
881                else
882                    return new Rev32QX<uint8_t>(machInst, vd, vn);
883            } else {
884                if (size & 0x1)
885                    return new Rev32DX<uint16_t>(machInst, vd, vn);
886                else
887                    return new Rev32DX<uint8_t>(machInst, vd, vn);
888            }
889          case 0x22:
890            if (size == 0x3)
891                return new Unknown64(machInst);
892            return decodeNeonUTwoMiscSReg<UaddlpDX, UaddlpQX>(
893                q, size, machInst, vd, vn);
894          case 0x23:
895            if (size_q == 0x6)
896                return new Unknown64(machInst);
897            return decodeNeonUTwoMiscXReg<UsqaddDX, UsqaddQX>(
898                q, size, machInst, vd, vn);
899            return new Unknown64(machInst);
900          case 0x24:
901            if (size == 0x3)
902                return new Unknown64(machInst);
903            return decodeNeonSTwoMiscSReg<ClzDX, ClzQX>(
904                q, size, machInst, vd, vn);
905          case 0x25:
906            if (size == 0x0) {
907                if (q)
908                    return new MvnQX<uint64_t>(machInst, vd, vn);
909                else
910                    return new MvnDX<uint64_t>(machInst, vd, vn);
911            } else if (size == 0x1) {
912                if (q)
913                    return new RbitQX<uint8_t>(machInst, vd, vn);
914                else
915                    return new RbitDX<uint8_t>(machInst, vd, vn);
916            } else {
917                return new Unknown64(machInst);
918            }
919          case 0x26:
920            if (size == 0x3)
921                return new Unknown64(machInst);
922            return decodeNeonUTwoMiscSReg<UadalpDX, UadalpQX>(
923                q, size, machInst, vd, vn);
924          case 0x27:
925            if (size_q == 0x6)
926                return new Unknown64(machInst);
927            return decodeNeonSTwoMiscXReg<SqnegDX, SqnegQX>(
928                q, size, machInst, vd, vn);
929          case 0x28:
930            if (size_q == 0x6)
931                return new Unknown64(machInst);
932            return decodeNeonSTwoMiscXReg<CmgeZeroDX, CmgeZeroQX>(
933                q, size, machInst, vd, vn);
934          case 0x29:
935            if (size_q == 0x6)
936                return new Unknown64(machInst);
937            return decodeNeonSTwoMiscXReg<CmleZeroDX, CmleZeroQX>(
938                q, size, machInst, vd, vn);
939          case 0x2b:
940            if (size_q == 0x6)
941                return new Unknown64(machInst);
942            return decodeNeonSTwoMiscXReg<NegDX, NegQX>(
943                q, size, machInst, vd, vn);
944          case 0x2c:
945            if (size < 0x2 || sz_q == 0x2)
946                return new Unknown64(machInst);
947            return decodeNeonUTwoMiscFpReg<FcmgeZeroDX, FcmgeZeroQX>(
948                q, size & 0x1, machInst, vd, vn);
949          case 0x2d:
950            if (size < 0x2 || sz_q == 0x2)
951                return new Unknown64(machInst);
952            return decodeNeonUTwoMiscFpReg<FcmleZeroDX, FcmleZeroQX>(
953                q, size & 0x1, machInst, vd, vn);
954          case 0x2f:
955            if (size < 0x2 || size_q == 0x6)
956                return new Unknown64(machInst);
957            return decodeNeonUTwoMiscFpReg<FnegDX, FnegQX>(
958                q, size & 0x1, machInst, vd, vn);
959          case 0x32:
960            if (size == 0x3)
961                return new Unknown64(machInst);
962            return decodeNeonSTwoMiscSReg<SqxtunX, Sqxtun2X>(
963                q, size, machInst, vd, vn);
964          case 0x33:
965            if (size == 0x3)
966                return new Unknown64(machInst);
967            return decodeNeonUTwoMiscSReg<ShllX, Shll2X>(
968                q, size, machInst, vd, vn);
969          case 0x34:
970            if (size == 0x3)
971                return new Unknown64(machInst);
972            return decodeNeonUTwoMiscSReg<UqxtnX, Uqxtn2X>(
973                q, size, machInst, vd, vn);
974          case 0x36:
975            if (size != 0x1)
976                return new Unknown64(machInst);
977            if (q)
978                return new Fcvtxn2X<uint32_t>(machInst, vd, vn);
979            else
980                return new FcvtxnX<uint32_t>(machInst, vd, vn);
981          case 0x38:
982            if (size > 0x1 || sz_q == 0x2)
983                return new Unknown64(machInst);
984            return decodeNeonUTwoMiscFpReg<FrintaDX, FrintaQX>(
985                q, size & 0x1, machInst, vd, vn);
986          case 0x39:
987            if (sz_q == 0x2)
988                return new Unknown64(machInst);
989            if (size < 0x2)
990                return decodeNeonUTwoMiscFpReg<FrintxDX, FrintxQX>(
991                    q, size & 0x1, machInst, vd, vn);
992            else
993                return decodeNeonUTwoMiscFpReg<FrintiDX, FrintiQX>(
994                    q, size & 0x1, machInst, vd, vn);
995          case 0x3a:
996            if (sz_q == 0x2)
997                return new Unknown64(machInst);
998            if (size < 0x2)
999                return decodeNeonUTwoMiscFpReg<FcvtnuDX, FcvtnuQX>(
1000                    q, size & 0x1, machInst, vd, vn);
1001            else
1002                return decodeNeonUTwoMiscFpReg<FcvtpuDX, FcvtpuQX>(
1003                    q, size & 0x1, machInst, vd, vn);
1004          case 0x3b:
1005            if (sz_q == 0x2)
1006                return new Unknown64(machInst);
1007            if (size < 0x2)
1008                return decodeNeonUTwoMiscFpReg<FcvtmuDX, FcvtmuQX>(
1009                    q, size & 0x1, machInst, vd, vn);
1010            else
1011                return decodeNeonUTwoMiscFpReg<FcvtzuIntDX, FcvtzuIntQX>(
1012                    q, size & 0x1, machInst, vd, vn);
1013          case 0x3c:
1014            if (size < 0x2) {
1015                return decodeNeonUTwoMiscFpReg<FcvtauDX, FcvtauQX>(
1016                    q, size & 0x1, machInst, vd, vn);
1017            } else if (size == 0x2) {
1018                if (q)
1019                    return new UrsqrteQX<uint32_t>(machInst, vd, vn);
1020                else
1021                    return new UrsqrteDX<uint32_t>(machInst, vd, vn);
1022            } else {
1023                return new Unknown64(machInst);
1024            }
1025          case 0x3d:
1026            if (sz_q == 0x2)
1027                return new Unknown64(machInst);
1028            if (size < 0x2)
1029                return decodeNeonUTwoMiscFpReg<UcvtfIntDX, UcvtfIntQX>(
1030                    q, size & 0x1, machInst, vd, vn);
1031            else
1032                return decodeNeonUTwoMiscFpReg<FrsqrteDX, FrsqrteQX>(
1033                    q, size & 0x1, machInst, vd, vn);
1034          case 0x3f:
1035            if (size < 0x2 || sz_q == 0x2)
1036                return new Unknown64(machInst);
1037            return decodeNeonUTwoMiscFpReg<FsqrtDX, FsqrtQX>(
1038                q, size & 0x1, machInst, vd, vn);
1039          default:
1040            return new Unknown64(machInst);
1041        }
1042    }
1043
1044    StaticInstPtr
1045    decodeNeonAcrossLanes(ExtMachInst machInst)
1046    {
1047        uint8_t q = bits(machInst, 30);
1048        uint8_t u = bits(machInst, 29);
1049        uint8_t size = bits(machInst, 23, 22);
1050        uint8_t opcode = bits(machInst, 16, 12);
1051
1052        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1053        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1054
1055        uint8_t size_q = (size << 1) | q;
1056        uint8_t sz_q = size_q & 0x3;
1057        uint8_t switchVal = opcode | ((u ? 1 : 0) << 5);
1058
1059        switch (switchVal) {
1060          case 0x03:
1061            if (size_q == 0x4 || size == 0x3)
1062                return new Unknown64(machInst);
1063            return decodeNeonSAcrossLanesLongReg<SaddlvDX, SaddlvQX,
1064                                                 SaddlvBQX>(
1065                q, size, machInst, vd, vn);
1066          case 0x0a:
1067            if (size_q == 0x4 || size == 0x3)
1068                return new Unknown64(machInst);
1069            return decodeNeonSAcrossLanesReg<SmaxvDX, SmaxvQX>(
1070                q, size, machInst, vd, vn);
1071          case 0x1a:
1072            if (size_q == 0x4 || size == 0x3)
1073                return new Unknown64(machInst);
1074            return decodeNeonSAcrossLanesReg<SminvDX, SminvQX>(
1075                q, size, machInst, vd, vn);
1076          case 0x1b:
1077            if (size_q == 0x4 || size == 0x3)
1078                return new Unknown64(machInst);
1079            return decodeNeonUAcrossLanesReg<AddvDX, AddvQX>(
1080                q, size, machInst, vd, vn);
1081          case 0x23:
1082            if (size_q == 0x4 || size == 0x3)
1083                return new Unknown64(machInst);
1084            return decodeNeonUAcrossLanesLongReg<UaddlvDX, UaddlvQX,
1085                                                 UaddlvBQX>(
1086                q, size, machInst, vd, vn);
1087          case 0x2a:
1088            if (size_q == 0x4 || size == 0x3)
1089                return new Unknown64(machInst);
1090            return decodeNeonUAcrossLanesReg<UmaxvDX, UmaxvQX>(
1091                q, size, machInst, vd, vn);
1092          case 0x2c:
1093            if (sz_q != 0x1)
1094                return new Unknown64(machInst);
1095            if (size < 0x2) {
1096                if (q)
1097                    return new FmaxnmvQX<uint32_t>(machInst, vd, vn);
1098                else
1099                    return new Unknown64(machInst);
1100            } else {
1101                if (q)
1102                    return new FminnmvQX<uint32_t>(machInst, vd, vn);
1103                else
1104                    return new Unknown64(machInst);
1105            }
1106          case 0x2f:
1107            if (sz_q != 0x1)
1108                return new Unknown64(machInst);
1109            if (size < 0x2) {
1110                if (q)
1111                    return new FmaxvQX<uint32_t>(machInst, vd, vn);
1112                else
1113                    return new Unknown64(machInst);
1114            } else {
1115                if (q)
1116                    return new FminvQX<uint32_t>(machInst, vd, vn);
1117                else
1118                    return new Unknown64(machInst);
1119            }
1120          case 0x3a:
1121            if (size_q == 0x4 || size == 0x3)
1122                return new Unknown64(machInst);
1123            return decodeNeonUAcrossLanesReg<UminvDX, UminvQX>(
1124                q, size, machInst, vd, vn);
1125          default:
1126            return new Unknown64(machInst);
1127        }
1128    }
1129
1130    StaticInstPtr
1131    decodeNeonCopy(ExtMachInst machInst)
1132    {
1133        uint8_t q = bits(machInst, 30);
1134        uint8_t op = bits(machInst, 29);
1135        uint8_t imm5 = bits(machInst, 20, 16);
1136        uint8_t imm4 = bits(machInst, 14, 11);
1137
1138        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1139        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1140
1141        uint8_t imm5_pos = findLsbSet(imm5);
1142        uint8_t index1 = 0, index2 = 0;
1143
1144        if (op) {
1145            if (!q || (imm4 & mask(imm5_pos)))
1146                return new Unknown64(machInst);
1147
1148            index1 = bits(imm5, 4, imm5_pos + 1);  // dst
1149            index2 = bits(imm4, 3, imm5_pos);  // src
1150
1151            switch (imm5_pos) {
1152              case 0:
1153                return new InsElemX<uint8_t>(machInst, vd, vn, index1, index2);
1154              case 1:
1155                return new InsElemX<uint16_t>(machInst, vd, vn, index1, index2);
1156              case 2:
1157                return new InsElemX<uint32_t>(machInst, vd, vn, index1, index2);
1158              case 3:
1159                return new InsElemX<uint64_t>(machInst, vd, vn, index1, index2);
1160              default:
1161                return new Unknown64(machInst);
1162            }
1163        }
1164
1165        switch (imm4) {
1166          case 0x0:
1167            index1 = bits(imm5, 4, imm5_pos + 1);
1168            switch (imm5_pos) {
1169              case 0:
1170                if (q)
1171                    return new DupElemQX<uint8_t>(machInst, vd, vn, index1);
1172                else
1173                    return new DupElemDX<uint8_t>(machInst, vd, vn, index1);
1174              case 1:
1175                if (q)
1176                    return new DupElemQX<uint16_t>(machInst, vd, vn, index1);
1177                else
1178                    return new DupElemDX<uint16_t>(machInst, vd, vn, index1);
1179              case 2:
1180                if (q)
1181                    return new DupElemQX<uint32_t>(machInst, vd, vn, index1);
1182                else
1183                    return new DupElemDX<uint32_t>(machInst, vd, vn, index1);
1184              case 3:
1185                if (q)
1186                    return new DupElemQX<uint64_t>(machInst, vd, vn, index1);
1187                else
1188                    return new Unknown64(machInst);
1189              default:
1190                return new Unknown64(machInst);
1191            }
1192          case 0x1:
1193            switch (imm5) {
1194              case 0x1:
1195                if (q)
1196                    return new DupGprWQX<uint8_t>(machInst, vd, vn);
1197                else
1198                    return new DupGprWDX<uint8_t>(machInst, vd, vn);
1199              case 0x2:
1200                if (q)
1201                    return new DupGprWQX<uint16_t>(machInst, vd, vn);
1202                else
1203                    return new DupGprWDX<uint16_t>(machInst, vd, vn);
1204              case 0x4:
1205                if (q)
1206                    return new DupGprWQX<uint32_t>(machInst, vd, vn);
1207                else
1208                    return new DupGprWDX<uint32_t>(machInst, vd, vn);
1209              case 0x8:
1210                if (q)
1211                    return new DupGprXQX<uint64_t>(machInst, vd, vn);
1212                else
1213                    return new Unknown64(machInst);
1214            }
1215          case 0x3:
1216            index1 = imm5 >> (imm5_pos + 1);
1217            switch (imm5_pos) {
1218              case 0:
1219                return new InsGprWX<uint8_t>(machInst, vd, vn, index1);
1220              case 1:
1221                return new InsGprWX<uint16_t>(machInst, vd, vn, index1);
1222              case 2:
1223                return new InsGprWX<uint32_t>(machInst, vd, vn, index1);
1224              case 3:
1225                return new InsGprXX<uint64_t>(machInst, vd, vn, index1);
1226              default:
1227                return new Unknown64(machInst);
1228            }
1229          case 0x5:
1230            index1 = bits(imm5, 4, imm5_pos + 1);
1231            switch (imm5_pos) {
1232              case 0:
1233                if (q)
1234                    return new SmovXX<int8_t>(machInst, vd, vn, index1);
1235                else
1236                    return new SmovWX<int8_t>(machInst, vd, vn, index1);
1237              case 1:
1238                if (q)
1239                    return new SmovXX<int16_t>(machInst, vd, vn, index1);
1240                else
1241                    return new SmovWX<int16_t>(machInst, vd, vn, index1);
1242              case 2:
1243                if (q)
1244                    return new SmovXX<int32_t>(machInst, vd, vn, index1);
1245                else
1246                    return new Unknown64(machInst);
1247              default:
1248                return new Unknown64(machInst);
1249            }
1250          case 0x7:
1251            index1 = imm5 >> (imm5_pos + 1);
1252
1253            if ((q && imm5_pos != 3) || (!q && imm5_pos >= 3))
1254                return new Unknown64(machInst);
1255
1256            switch (imm5_pos) {
1257              case 0:
1258                return new UmovWX<uint8_t>(machInst, vd, vn, index1);
1259              case 1:
1260                return new UmovWX<uint16_t>(machInst, vd, vn, index1);
1261              case 2:
1262                return new UmovWX<uint32_t>(machInst, vd, vn, index1);
1263              case 3:
1264                return new UmovXX<uint64_t>(machInst, vd, vn, index1);
1265              default:
1266                return new Unknown64(machInst);
1267            }
1268          default:
1269            return new Unknown64(machInst);
1270        }
1271    }
1272
1273    template <typename DecoderFeatures>
1274    StaticInstPtr
1275    decodeNeonIndexedElem(ExtMachInst machInst)
1276    {
1277        uint8_t q = bits(machInst, 30);
1278        uint8_t u = bits(machInst, 29);
1279        uint8_t size = bits(machInst, 23, 22);
1280        uint8_t L = bits(machInst, 21);
1281        uint8_t M = bits(machInst, 20);
1282        uint8_t opcode = bits(machInst, 15, 12);
1283        uint8_t H = bits(machInst, 11);
1284
1285        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1286        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1287        IntRegIndex vm_bf = (IntRegIndex) (uint8_t) bits(machInst, 19, 16);
1288
1289        uint8_t index = 0;
1290        uint8_t index_fp = 0;
1291        uint8_t vmh = 0;
1292        uint8_t sz = size & 0x1;
1293        uint8_t sz_q = (sz << 1) | bits(machInst, 30);
1294        uint8_t sz_L = (sz << 1) | L;
1295
1296        // Index and 2nd register operand for integer instructions
1297        if (size == 0x1) {
1298            index = (H << 2) | (L << 1) | M;
1299            // vmh = 0;
1300        } else if (size == 0x2) {
1301            index = (H << 1) | L;
1302            vmh = M;
1303        }
1304        IntRegIndex vm = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf);
1305
1306        // Index and 2nd register operand for FP instructions
1307        vmh = M;
1308        if ((size & 0x1) == 0) {
1309            index_fp = (H << 1) | L;
1310        } else if (L == 0) {
1311            index_fp = H;
1312        }
1313        IntRegIndex vm_fp = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf);
1314
1315        switch (opcode) {
1316          case 0x0:
1317            if (!u || (size == 0x0 || size == 0x3))
1318                return new Unknown64(machInst);
1319            else
1320                return decodeNeonUThreeImmHAndWReg<MlaElemDX, MlaElemQX>(
1321                    q, size, machInst, vd, vn, vm, index);
1322          case 0x1:
1323            if (!u && size >= 2 && sz_q != 0x2 && sz_L != 0x3)
1324                return decodeNeonUThreeImmFpReg<FmlaElemDX, FmlaElemQX>(
1325                    q, sz, machInst, vd, vn, vm_fp, index_fp);
1326            else
1327                return new Unknown64(machInst);
1328          case 0x2:
1329            if (size == 0x0 || size == 0x3)
1330                return new Unknown64(machInst);
1331            if (u)
1332                return decodeNeonUThreeImmHAndWReg<UmlalElemX, UmlalElem2X>(
1333                    q, size, machInst, vd, vn, vm, index);
1334            else
1335                return decodeNeonSThreeImmHAndWReg<SmlalElemX, SmlalElem2X>(
1336                    q, size, machInst, vd, vn, vm, index);
1337          case 0x3:
1338            if (u || (size == 0x0 || size == 0x3))
1339                return new Unknown64(machInst);
1340            else
1341                return decodeNeonSThreeImmHAndWReg<SqdmlalElemX,
1342                                                   SqdmlalElem2X>(
1343                    q, size, machInst, vd, vn, vm, index);
1344          case 0x4:
1345            if (u && !(size == 0x0 || size == 0x3))
1346                return decodeNeonUThreeImmHAndWReg<MlsElemDX, MlsElemQX>(
1347                    q, size, machInst, vd, vn, vm, index);
1348            else
1349                return new Unknown64(machInst);
1350          case 0x5:
1351            if (!u && size >= 0x2 && sz_L != 0x3 && sz_q != 0x2)
1352                return decodeNeonUThreeImmFpReg<FmlsElemDX, FmlsElemQX>(
1353                    q, sz, machInst, vd, vn, vm_fp, index_fp);
1354            else
1355                return new Unknown64(machInst);
1356          case 0x6:
1357            if (size == 0x0 || size == 0x3)
1358                return new Unknown64(machInst);
1359            if (u)
1360                return decodeNeonUThreeImmHAndWReg<UmlslElemX, UmlslElem2X>(
1361                    q, size, machInst, vd, vn, vm, index);
1362            else
1363                return decodeNeonSThreeImmHAndWReg<SmlslElemX, SmlslElem2X>(
1364                    q, size, machInst, vd, vn, vm, index);
1365          case 0x7:
1366            if (u || (size == 0x0 || size == 0x3))
1367                return new Unknown64(machInst);
1368            else
1369                return decodeNeonSThreeImmHAndWReg<SqdmlslElemX,
1370                                                   SqdmlslElem2X>(
1371                    q, size, machInst, vd, vn, vm, index);
1372          case 0x8:
1373            if (u || (size == 0x0 || size == 0x3))
1374                return new Unknown64(machInst);
1375            else
1376                return decodeNeonUThreeImmHAndWReg<MulElemDX, MulElemQX>(
1377                    q, size, machInst, vd, vn, vm, index);
1378          case 0x9:
1379            if (size >= 2 && sz_q != 0x2 && sz_L != 0x3) {
1380                if (u)
1381                    return decodeNeonUThreeImmFpReg<FmulxElemDX, FmulxElemQX>(
1382                        q, sz, machInst, vd, vn, vm_fp, index_fp);
1383                else
1384                    return decodeNeonUThreeImmFpReg<FmulElemDX, FmulElemQX>(
1385                        q, sz, machInst, vd, vn, vm_fp, index_fp);
1386            } else {
1387                return new Unknown64(machInst);
1388            }
1389          case 0xa:
1390            if (size == 0x0 || size == 0x3)
1391                return new Unknown64(machInst);
1392            if (u)
1393                return decodeNeonUThreeImmHAndWReg<UmullElemX, UmullElem2X>(
1394                    q, size, machInst, vd, vn, vm, index);
1395            else
1396                return decodeNeonSThreeImmHAndWReg<SmullElemX, SmullElem2X>(
1397                    q, size, machInst, vd, vn, vm, index);
1398          case 0xb:
1399            if (u || (size == 0x0 || size == 0x3))
1400                return new Unknown64(machInst);
1401            else
1402                return decodeNeonSThreeImmHAndWReg<SqdmullElemX, SqdmullElem2X>(
1403                    q, size, machInst, vd, vn, vm, index);
1404          case 0xc:
1405            if (u || (size == 0x0 || size == 0x3))
1406                return new Unknown64(machInst);
1407            else
1408                return decodeNeonSThreeImmHAndWReg<SqdmulhElemDX, SqdmulhElemQX>(
1409                    q, size, machInst, vd, vn, vm, index);
1410          case 0xd:
1411            if (u || (size == 0x0 || size == 0x3))
1412                return new Unknown64(machInst);
1413            else
1414                return decodeNeonSThreeImmHAndWReg<SqrdmulhElemDX, SqrdmulhElemQX>(
1415                    q, size, machInst, vd, vn, vm, index);
1416          default:
1417            return new Unknown64(machInst);
1418        }
1419    }
1420
1421    StaticInstPtr
1422    decodeNeonModImm(ExtMachInst machInst)
1423    {
1424        uint8_t q = bits(machInst, 30);
1425        uint8_t op = bits(machInst, 29);
1426        uint8_t abcdefgh = (bits(machInst, 18, 16) << 5) |
1427                           bits(machInst, 9, 5);
1428        uint8_t cmode = bits(machInst, 15, 12);
1429        uint8_t o2 = bits(machInst, 11);
1430
1431        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1432
1433        if (o2 == 0x1 || (op == 0x1 && cmode == 0xf && !q))
1434            return new Unknown64(machInst);
1435
1436        bool immValid = true;
1437        const uint64_t bigImm = simd_modified_imm(op, cmode, abcdefgh,
1438                                                  immValid,
1439                                                  true /* isAarch64 */);
1440        if (!immValid) {
1441            return new Unknown(machInst);
1442        }
1443
1444        if (op) {
1445            if (bits(cmode, 3) == 0) {
1446                if (bits(cmode, 0) == 0) {
1447                    if (q)
1448                        return new MvniQX<uint64_t>(machInst, vd, bigImm);
1449                    else
1450                        return new MvniDX<uint64_t>(machInst, vd, bigImm);
1451                } else {
1452                    if (q)
1453                        return new BicImmQX<uint64_t>(machInst, vd, bigImm);
1454                    else
1455                        return new BicImmDX<uint64_t>(machInst, vd, bigImm);
1456                }
1457            } else {
1458                if (bits(cmode, 2) == 1) {
1459                    switch (bits(cmode, 1, 0)) {
1460                      case 0:
1461                      case 1:
1462                        if (q)
1463                            return new MvniQX<uint64_t>(machInst, vd, bigImm);
1464                        else
1465                            return new MvniDX<uint64_t>(machInst, vd, bigImm);
1466                      case 2:
1467                        if (q)
1468                            return new MoviQX<uint64_t>(machInst, vd, bigImm);
1469                        else
1470                            return new MoviDX<uint64_t>(machInst, vd, bigImm);
1471                      case 3:
1472                        if (q)
1473                            return new FmovQX<uint64_t>(machInst, vd, bigImm);
1474                        else
1475                            return new MoviDX<uint64_t>(machInst, vd, bigImm);
1476                    }
1477                } else {
1478                    if (bits(cmode, 0) == 0) {
1479                        if (q)
1480                            return new MvniQX<uint64_t>(machInst, vd, bigImm);
1481                        else
1482                            return new MvniDX<uint64_t>(machInst, vd, bigImm);
1483                    } else {
1484                        if (q)
1485                            return new BicImmQX<uint64_t>(machInst, vd,
1486                                                          bigImm);
1487                        else
1488                            return new BicImmDX<uint64_t>(machInst, vd,
1489                                                          bigImm);
1490                    }
1491                }
1492            }
1493        } else {
1494            if (bits(cmode, 3) == 0) {
1495                if (bits(cmode, 0) == 0) {
1496                    if (q)
1497                        return new MoviQX<uint64_t>(machInst, vd, bigImm);
1498                    else
1499                        return new MoviDX<uint64_t>(machInst, vd, bigImm);
1500                } else {
1501                    if (q)
1502                        return new OrrImmQX<uint64_t>(machInst, vd, bigImm);
1503                    else
1504                        return new OrrImmDX<uint64_t>(machInst, vd, bigImm);
1505                }
1506            } else {
1507                if (bits(cmode, 2) == 1) {
1508                    if (bits(cmode, 1, 0) == 0x3) {
1509                        if (q)
1510                            return new FmovQX<uint32_t>(machInst, vd, bigImm);
1511                        else
1512                            return new FmovDX<uint32_t>(machInst, vd, bigImm);
1513                    } else {
1514                        if (q)
1515                            return new MoviQX<uint64_t>(machInst, vd, bigImm);
1516                        else
1517                            return new MoviDX<uint64_t>(machInst, vd, bigImm);
1518                    }
1519                } else {
1520                    if (bits(cmode, 0) == 0) {
1521                        if (q)
1522                            return new MoviQX<uint64_t>(machInst, vd, bigImm);
1523                        else
1524                            return new MoviDX<uint64_t>(machInst, vd, bigImm);
1525                    } else {
1526                        if (q)
1527                            return new OrrImmQX<uint64_t>(machInst, vd,
1528                                                          bigImm);
1529                        else
1530                            return new OrrImmDX<uint64_t>(machInst, vd, bigImm);
1531                    }
1532                }
1533            }
1534        }
1535        return new Unknown(machInst);
1536    }
1537
1538    StaticInstPtr
1539    decodeNeonShiftByImm(ExtMachInst machInst)
1540    {
1541        uint8_t q = bits(machInst, 30);
1542        uint8_t u = bits(machInst, 29);
1543        uint8_t immh = bits(machInst, 22, 19);
1544        uint8_t immb = bits(machInst, 18, 16);
1545        uint8_t opcode = bits(machInst, 15, 11);
1546
1547        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1548        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1549
1550        uint8_t immh3 = bits(machInst, 22);
1551        uint8_t immh3_q = (immh3 << 1) | q;
1552        uint8_t op_u = (bits(machInst, 12) << 1) | u;
1553        uint8_t size = findMsbSet(immh);
1554        int shiftAmt = 0;
1555
1556        switch (opcode) {
1557          case 0x00:
1558            if (immh3_q == 0x2)
1559                return new Unknown64(machInst);
1560            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1561            if (u)
1562                return decodeNeonUTwoShiftXReg<UshrDX, UshrQX>(
1563                    q, size, machInst, vd, vn, shiftAmt);
1564            else
1565                return decodeNeonSTwoShiftXReg<SshrDX, SshrQX>(
1566                    q, size, machInst, vd, vn, shiftAmt);
1567          case 0x02:
1568            if (immh3_q == 0x2)
1569                return new Unknown64(machInst);
1570            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1571            if (u)
1572                return decodeNeonUTwoShiftXReg<UsraDX, UsraQX>(
1573                    q, size, machInst, vd, vn, shiftAmt);
1574            else
1575                return decodeNeonSTwoShiftXReg<SsraDX, SsraQX>(
1576                    q, size, machInst, vd, vn, shiftAmt);
1577          case 0x04:
1578            if (immh3_q == 0x2)
1579                return new Unknown64(machInst);
1580            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1581            if (u)
1582                return decodeNeonUTwoShiftXReg<UrshrDX, UrshrQX>(
1583                    q, size, machInst, vd, vn, shiftAmt);
1584            else
1585                return decodeNeonSTwoShiftXReg<SrshrDX, SrshrQX>(
1586                    q, size, machInst, vd, vn, shiftAmt);
1587          case 0x06:
1588            if (immh3_q == 0x2)
1589                return new Unknown64(machInst);
1590            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1591            if (u)
1592                return decodeNeonUTwoShiftXReg<UrsraDX, UrsraQX>(
1593                    q, size, machInst, vd, vn, shiftAmt);
1594            else
1595                return decodeNeonSTwoShiftXReg<SrsraDX, SrsraQX>(
1596                    q, size, machInst, vd, vn, shiftAmt);
1597          case 0x08:
1598            if (u && !(immh3_q == 0x2)) {
1599                shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1600                return decodeNeonUTwoShiftXReg<SriDX, SriQX>(
1601                    q, size, machInst, vd, vn, shiftAmt);
1602            } else {
1603                return new Unknown64(machInst);
1604            }
1605          case 0x0a:
1606            if (immh3_q == 0x2)
1607                return new Unknown64(machInst);
1608            shiftAmt = ((immh << 3) | immb) - (8 << size);
1609            if (u)
1610                return decodeNeonUTwoShiftXReg<SliDX, SliQX>(
1611                    q, size, machInst, vd, vn, shiftAmt);
1612            else
1613                return decodeNeonUTwoShiftXReg<ShlDX, ShlQX>(
1614                    q, size, machInst, vd, vn, shiftAmt);
1615          case 0x0c:
1616            if (u && !(immh3_q == 0x2 || op_u == 0x0)) {
1617                shiftAmt = ((immh << 3) | immb) - (8 << size);
1618                return decodeNeonSTwoShiftXReg<SqshluDX, SqshluQX>(
1619                    q, size, machInst, vd, vn, shiftAmt);
1620            } else {
1621                return new Unknown64(machInst);
1622            }
1623          case 0x0e:
1624            if (immh3_q == 0x2 || op_u == 0x0)
1625                return new Unknown64(machInst);
1626            shiftAmt = ((immh << 3) | immb) - (8 << size);
1627            if (u)
1628                return decodeNeonUTwoShiftXReg<UqshlImmDX, UqshlImmQX>(
1629                    q, size, machInst, vd, vn, shiftAmt);
1630            else
1631                return decodeNeonSTwoShiftXReg<SqshlImmDX, SqshlImmQX>(
1632                    q, size, machInst, vd, vn, shiftAmt);
1633          case 0x10:
1634            if (immh3)
1635                return new Unknown64(machInst);
1636            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1637            if (u)
1638                return decodeNeonSTwoShiftSReg<SqshrunX, Sqshrun2X>(
1639                    q, size, machInst, vd, vn, shiftAmt);
1640            else
1641                return decodeNeonUTwoShiftSReg<ShrnX, Shrn2X>(
1642                    q, size, machInst, vd, vn, shiftAmt);
1643          case 0x11:
1644            if (immh3)
1645                return new Unknown64(machInst);
1646            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1647            if (u)
1648                return decodeNeonSTwoShiftSReg<SqrshrunX, Sqrshrun2X>(
1649                    q, size, machInst, vd, vn, shiftAmt);
1650            else
1651                return decodeNeonUTwoShiftSReg<RshrnX, Rshrn2X>(
1652                    q, size, machInst, vd, vn, shiftAmt);
1653          case 0x12:
1654            if (immh3)
1655                return new Unknown64(machInst);
1656            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1657            if (u)
1658                return decodeNeonUTwoShiftSReg<UqshrnX, Uqshrn2X>(
1659                    q, size, machInst, vd, vn, shiftAmt);
1660            else
1661                return decodeNeonSTwoShiftSReg<SqshrnX, Sqshrn2X>(
1662                    q, size, machInst, vd, vn, shiftAmt);
1663          case 0x13:
1664            if (immh3)
1665                return new Unknown64(machInst);
1666            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1667            if (u)
1668                return decodeNeonUTwoShiftSReg<UqrshrnX, Uqrshrn2X>(
1669                    q, size, machInst, vd, vn, shiftAmt);
1670            else
1671                return decodeNeonSTwoShiftSReg<SqrshrnX, Sqrshrn2X>(
1672                    q, size, machInst, vd, vn, shiftAmt);
1673          case 0x14:
1674            if (immh3)
1675                return new Unknown64(machInst);
1676            shiftAmt = ((immh << 3) | immb) - (8 << size);
1677            if (u)
1678                return decodeNeonUTwoShiftSReg<UshllX, Ushll2X>(
1679                    q, size, machInst, vd, vn, shiftAmt);
1680            else
1681                return decodeNeonSTwoShiftSReg<SshllX, Sshll2X>(
1682                    q, size, machInst, vd, vn, shiftAmt);
1683          case 0x1c:
1684            if (immh < 0x4 || immh3_q == 0x2)
1685                return new Unknown64(machInst);
1686            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1687            if (u) {
1688                return decodeNeonUTwoShiftFpReg<UcvtfFixedDX, UcvtfFixedQX>(
1689                    q, size & 0x1, machInst, vd, vn, shiftAmt);
1690            } else {
1691                if (q) {
1692                    if (size & 0x1)
1693                        return new ScvtfFixedDQX<uint64_t>(machInst, vd, vn,
1694                                                           shiftAmt);
1695                    else
1696                        return new ScvtfFixedSQX<uint32_t>(machInst, vd, vn,
1697                                                           shiftAmt);
1698                } else {
1699                    if (size & 0x1)
1700                        return new Unknown(machInst);
1701                    else
1702                        return new ScvtfFixedDX<uint32_t>(machInst, vd, vn,
1703                                                          shiftAmt);
1704                }
1705            }
1706          case 0x1f:
1707            if (immh < 0x4 || immh3_q == 0x2)
1708                return new Unknown64(machInst);
1709            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
1710            if (u)
1711                return decodeNeonUTwoShiftFpReg<FcvtzuFixedDX, FcvtzuFixedQX>(
1712                    q, size & 0x1, machInst, vd, vn, shiftAmt);
1713            else
1714                return decodeNeonUTwoShiftFpReg<FcvtzsFixedDX, FcvtzsFixedQX>(
1715                    q, size & 0x1, machInst, vd, vn, shiftAmt);
1716          default:
1717            return new Unknown64(machInst);
1718        }
1719    }
1720
1721    StaticInstPtr
1722    decodeNeonTblTbx(ExtMachInst machInst)
1723    {
1724        uint8_t q = bits(machInst, 30);
1725
1726        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1727        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1728        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
1729
1730        uint8_t switchVal = bits(machInst, 14, 12);
1731
1732        switch (switchVal) {
1733          case 0x0:
1734            if (q)
1735                return new Tbl1QX<uint8_t>(machInst, vd, vn, vm);
1736            else
1737                return new Tbl1DX<uint8_t>(machInst, vd, vn, vm);
1738          case 0x1:
1739            if (q)
1740                return new Tbx1QX<uint8_t>(machInst, vd, vn, vm);
1741            else
1742                return new Tbx1DX<uint8_t>(machInst, vd, vn, vm);
1743          case 0x2:
1744            if (q)
1745                return new Tbl2QX<uint8_t>(machInst, vd, vn, vm);
1746            else
1747                return new Tbl2DX<uint8_t>(machInst, vd, vn, vm);
1748          case 0x3:
1749            if (q)
1750                return new Tbx2QX<uint8_t>(machInst, vd, vn, vm);
1751            else
1752                return new Tbx2DX<uint8_t>(machInst, vd, vn, vm);
1753          case 0x4:
1754            if (q)
1755                return new Tbl3QX<uint8_t>(machInst, vd, vn, vm);
1756            else
1757                return new Tbl3DX<uint8_t>(machInst, vd, vn, vm);
1758          case 0x5:
1759            if (q)
1760                return new Tbx3QX<uint8_t>(machInst, vd, vn, vm);
1761            else
1762                return new Tbx3DX<uint8_t>(machInst, vd, vn, vm);
1763          case 0x6:
1764            if (q)
1765                return new Tbl4QX<uint8_t>(machInst, vd, vn, vm);
1766            else
1767                return new Tbl4DX<uint8_t>(machInst, vd, vn, vm);
1768          case 0x7:
1769            if (q)
1770                return new Tbx4QX<uint8_t>(machInst, vd, vn, vm);
1771            else
1772                return new Tbx4DX<uint8_t>(machInst, vd, vn, vm);
1773          default:
1774            return new Unknown64(machInst);
1775        }
1776
1777        return new Unknown64(machInst);
1778    }
1779
1780    StaticInstPtr
1781    decodeNeonZipUzpTrn(ExtMachInst machInst)
1782    {
1783        uint8_t q = bits(machInst, 30);
1784        uint8_t size = bits(machInst, 23, 22);
1785        uint8_t opcode = bits(machInst, 14, 12);
1786
1787        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1788        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1789        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
1790
1791        switch (opcode) {
1792          case 0x1:
1793            return decodeNeonUThreeXReg<Uzp1DX, Uzp1QX>(
1794                q, size, machInst, vd, vn, vm);
1795          case 0x2:
1796            return decodeNeonUThreeXReg<Trn1DX, Trn1QX>(
1797                q, size, machInst, vd, vn, vm);
1798          case 0x3:
1799            return decodeNeonUThreeXReg<Zip1DX, Zip1QX>(
1800                q, size, machInst, vd, vn, vm);
1801          case 0x5:
1802            return decodeNeonUThreeXReg<Uzp2DX, Uzp2QX>(
1803                q, size, machInst, vd, vn, vm);
1804          case 0x6:
1805            return decodeNeonUThreeXReg<Trn2DX, Trn2QX>(
1806                q, size, machInst, vd, vn, vm);
1807          case 0x7:
1808            return decodeNeonUThreeXReg<Zip2DX, Zip2QX>(
1809                q, size, machInst, vd, vn, vm);
1810          default:
1811            return new Unknown64(machInst);
1812        }
1813        return new Unknown64(machInst);
1814    }
1815
1816    StaticInstPtr
1817    decodeNeonExt(ExtMachInst machInst)
1818    {
1819        uint8_t q = bits(machInst, 30);
1820        uint8_t op2 = bits(machInst, 23, 22);
1821        uint8_t imm4 = bits(machInst, 14, 11);
1822
1823        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1824        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1825        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
1826
1827        if (op2 != 0 || (q == 0x0 && bits(imm4, 3) == 0x1))
1828            return new Unknown64(machInst);
1829
1830        uint8_t index = q ? imm4 : imm4 & 0x7;
1831
1832        if (q) {
1833            return new ExtQX<uint8_t>(machInst, vd, vn, vm, index);
1834        } else {
1835            return new ExtDX<uint8_t>(machInst, vd, vn, vm, index);
1836        }
1837    }
1838
1839    StaticInstPtr
1840    decodeNeonSc3Same(ExtMachInst machInst)
1841    {
1842        uint8_t u = bits(machInst, 29);
1843        uint8_t size = bits(machInst, 23, 22);
1844        uint8_t opcode = bits(machInst, 15, 11);
1845        uint8_t s = bits(machInst, 11);
1846
1847        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1848        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1849        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
1850
1851        switch (opcode) {
1852          case 0x01:
1853            if (u)
1854                return decodeNeonUThreeUReg<UqaddScX>(
1855                    size, machInst, vd, vn, vm);
1856            else
1857                return decodeNeonSThreeUReg<SqaddScX>(
1858                    size, machInst, vd, vn, vm);
1859          case 0x05:
1860            if (u)
1861                return decodeNeonUThreeUReg<UqsubScX>(
1862                    size, machInst, vd, vn, vm);
1863            else
1864                return decodeNeonSThreeUReg<SqsubScX>(
1865                    size, machInst, vd, vn, vm);
1866          case 0x06:
1867            if (size != 0x3)
1868                return new Unknown64(machInst);
1869            if (u)
1870                return new CmhiDX<uint64_t>(machInst, vd, vn, vm);
1871            else
1872                return new CmgtDX<int64_t>(machInst, vd, vn, vm);
1873          case 0x07:
1874            if (size != 0x3)
1875                return new Unknown64(machInst);
1876            if (u)
1877                return new CmhsDX<uint64_t>(machInst, vd, vn, vm);
1878            else
1879                return new CmgeDX<int64_t>(machInst, vd, vn, vm);
1880          case 0x08:
1881            if (!s && size != 0x3)
1882                return new Unknown64(machInst);
1883            if (u)
1884                return new UshlDX<uint64_t>(machInst, vd, vn, vm);
1885            else
1886                return new SshlDX<int64_t>(machInst, vd, vn, vm);
1887          case 0x09:
1888            if (!s && size != 0x3)
1889                return new Unknown64(machInst);
1890            if (u)
1891                return decodeNeonUThreeUReg<UqshlScX>(
1892                    size, machInst, vd, vn, vm);
1893            else
1894                return decodeNeonSThreeUReg<SqshlScX>(
1895                    size, machInst, vd, vn, vm);
1896          case 0x0a:
1897            if (!s && size != 0x3)
1898                return new Unknown64(machInst);
1899            if (u)
1900                return new UrshlDX<uint64_t>(machInst, vd, vn, vm);
1901            else
1902                return new SrshlDX<int64_t>(machInst, vd, vn, vm);
1903          case 0x0b:
1904            if (!s && size != 0x3)
1905                return new Unknown64(machInst);
1906            if (u)
1907                return decodeNeonUThreeUReg<UqrshlScX>(
1908                    size, machInst, vd, vn, vm);
1909            else
1910                return decodeNeonSThreeUReg<SqrshlScX>(
1911                    size, machInst, vd, vn, vm);
1912          case 0x10:
1913            if (size != 0x3)
1914                return new Unknown64(machInst);
1915            if (u)
1916                return new SubDX<uint64_t>(machInst, vd, vn, vm);
1917            else
1918                return new AddDX<uint64_t>(machInst, vd, vn, vm);
1919          case 0x11:
1920            if (size != 0x3)
1921                return new Unknown64(machInst);
1922            if (u)
1923                return new CmeqDX<uint64_t>(machInst, vd, vn, vm);
1924            else
1925                return new CmtstDX<uint64_t>(machInst, vd, vn, vm);
1926          case 0x16:
1927            if (size == 0x3 || size == 0x0)
1928                return new Unknown64(machInst);
1929            if (u)
1930                return decodeNeonSThreeHAndWReg<SqrdmulhScX>(
1931                    size, machInst, vd, vn, vm);
1932            else
1933                return decodeNeonSThreeHAndWReg<SqdmulhScX>(
1934                    size, machInst, vd, vn, vm);
1935          case 0x1a:
1936            if (!u || size < 0x2)
1937                return new Unknown64(machInst);
1938            else
1939                return decodeNeonUThreeScFpReg<FabdScX>(
1940                    size & 0x1, machInst, vd, vn, vm);
1941          case 0x1b:
1942            if (u || size > 0x1)
1943                return new Unknown64(machInst);
1944            else
1945                return decodeNeonUThreeScFpReg<FmulxScX>(
1946                    size & 0x1, machInst, vd, vn, vm);
1947          case 0x1c:
1948            if (size < 0x2) {
1949                if (u)
1950                    return decodeNeonUThreeScFpReg<FcmgeScX>(
1951                        size & 0x1, machInst, vd, vn, vm);
1952                else
1953                    return decodeNeonUThreeScFpReg<FcmeqScX>(
1954                        size & 0x1, machInst, vd, vn, vm);
1955            } else {
1956                if (u)
1957                    return decodeNeonUThreeScFpReg<FcmgtScX>(
1958                        size & 0x1, machInst, vd, vn, vm);
1959                else
1960                    return new Unknown64(machInst);
1961            }
1962          case 0x1d:
1963            if (!u)
1964                return new Unknown64(machInst);
1965            if (size < 0x2)
1966                return decodeNeonUThreeScFpReg<FacgeScX>(
1967                    size & 0x1, machInst, vd, vn, vm);
1968            else
1969                return decodeNeonUThreeScFpReg<FacgtScX>(
1970                    size & 0x1, machInst, vd, vn, vm);
1971          case 0x1f:
1972            if (u)
1973                return new Unknown64(machInst);
1974            if (size < 0x2)
1975                return decodeNeonUThreeScFpReg<FrecpsScX>(
1976                    size & 0x1, machInst, vd, vn, vm);
1977            else
1978                return decodeNeonUThreeScFpReg<FrsqrtsScX>(
1979                    size & 0x1, machInst, vd, vn, vm);
1980          default:
1981            return new Unknown64(machInst);
1982        }
1983    }
1984
1985    StaticInstPtr
1986    decodeNeonSc3Diff(ExtMachInst machInst)
1987    {
1988        if (bits(machInst, 29))
1989            return new Unknown64(machInst);
1990
1991        uint8_t size = bits(machInst, 23, 22);
1992        if (size == 0x0 || size == 0x3)
1993            return new Unknown64(machInst);
1994
1995        uint8_t opcode = bits(machInst, 15, 12);
1996
1997        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
1998        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
1999        IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
2000
2001        switch (opcode) {
2002          case 0x9:
2003            return decodeNeonSThreeHAndWReg<SqdmlalScX>(size, machInst, vd, vn, vm);
2004          case 0xb:
2005            return decodeNeonSThreeHAndWReg<SqdmlslScX>(size, machInst, vd, vn, vm);
2006          case 0xd:
2007            return decodeNeonSThreeHAndWReg<SqdmullScX>(size, machInst, vd, vn, vm);
2008          default:
2009            return new Unknown64(machInst);
2010        }
2011    }
2012
2013    StaticInstPtr
2014    decodeNeonSc2RegMisc(ExtMachInst machInst)
2015    {
2016        uint8_t u = bits(machInst, 29);
2017        uint8_t size = bits(machInst, 23, 22);
2018        uint8_t opcode = bits(machInst, 16, 12);
2019
2020        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2021        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2022
2023        uint8_t switchVal = opcode | ((u ? 1 : 0) << 5);
2024        switch (switchVal) {
2025          case 0x03:
2026            return decodeNeonUTwoMiscUReg<SuqaddScX>(size, machInst, vd, vn);
2027          case 0x07:
2028            return decodeNeonSTwoMiscUReg<SqabsScX>(size, machInst, vd, vn);
2029          case 0x08:
2030            if (size != 0x3)
2031                return new Unknown64(machInst);
2032            else
2033                return new CmgtZeroDX<int64_t>(machInst, vd, vn);
2034          case 0x09:
2035            if (size != 0x3)
2036                return new Unknown64(machInst);
2037            else
2038                return new CmeqZeroDX<int64_t>(machInst, vd, vn);
2039          case 0x0a:
2040            if (size != 0x3)
2041                return new Unknown64(machInst);
2042            else
2043                return new CmltZeroDX<int64_t>(machInst, vd, vn);
2044          case 0x0b:
2045            if (size != 0x3)
2046                return new Unknown64(machInst);
2047            else
2048                return new AbsDX<int64_t>(machInst, vd, vn);
2049          case 0x0c:
2050            if (size < 0x2)
2051                return new Unknown64(machInst);
2052            else
2053                return decodeNeonUTwoMiscScFpReg<FcmgtZeroScX>(
2054                    size & 0x1, machInst, vd, vn);
2055          case 0x0d:
2056            if (size < 0x2)
2057                return new Unknown64(machInst);
2058            else
2059                return decodeNeonUTwoMiscScFpReg<FcmeqZeroScX>(
2060                    size & 0x1, machInst, vd, vn);
2061          case 0x0e:
2062            if (size < 0x2)
2063                return new Unknown64(machInst);
2064            else
2065                return decodeNeonUTwoMiscScFpReg<FcmltZeroScX>(
2066                    size & 0x1, machInst, vd, vn);
2067          case 0x14:
2068            if (size == 0x3) {
2069                return new Unknown64(machInst);
2070            } else {
2071                switch (size) {
2072                  case 0x0:
2073                    return new SqxtnScX<int8_t>(machInst, vd, vn);
2074                  case 0x1:
2075                    return new SqxtnScX<int16_t>(machInst, vd, vn);
2076                  case 0x2:
2077                    return new SqxtnScX<int32_t>(machInst, vd, vn);
2078                }
2079            }
2080          case 0x1a:
2081            if (size < 0x2)
2082                return decodeNeonUTwoMiscScFpReg<FcvtnsScX>(
2083                    size & 0x1, machInst, vd, vn);
2084            else
2085                return decodeNeonUTwoMiscScFpReg<FcvtpsScX>(
2086                    size & 0x1, machInst, vd, vn);
2087          case 0x1b:
2088            if (size < 0x2)
2089                return decodeNeonUTwoMiscScFpReg<FcvtmsScX>(
2090                    size & 0x1, machInst, vd, vn);
2091            else
2092                return decodeNeonUTwoMiscScFpReg<FcvtzsIntScX>(
2093                    size & 0x1, machInst, vd, vn);
2094          case 0x1c:
2095            if (size < 0x2)
2096                return decodeNeonUTwoMiscScFpReg<FcvtasScX>(
2097                    size & 0x1, machInst, vd, vn);
2098            else
2099                return new Unknown64(machInst);
2100          case 0x1d:
2101            if (size < 0x2) {
2102                if (size & 0x1)
2103                    return new ScvtfIntScDX<uint64_t>(machInst, vd, vn);
2104                else
2105                    return new ScvtfIntScSX<uint32_t>(machInst, vd, vn);
2106            } else {
2107                return decodeNeonUTwoMiscScFpReg<FrecpeScX>(
2108                    size & 0x1, machInst, vd, vn);
2109            }
2110          case 0x1f:
2111            if (size < 0x2)
2112                return new Unknown64(machInst);
2113            else
2114                return decodeNeonUTwoMiscScFpReg<FrecpxX>(
2115                    size & 0x1, machInst, vd, vn);
2116          case 0x23:
2117            return decodeNeonUTwoMiscUReg<UsqaddScX>(size, machInst, vd, vn);
2118          case 0x27:
2119            return decodeNeonSTwoMiscUReg<SqnegScX>(size, machInst, vd, vn);
2120          case 0x28:
2121            if (size != 0x3)
2122                return new Unknown64(machInst);
2123            else
2124                return new CmgeZeroDX<int64_t>(machInst, vd, vn);
2125          case 0x29:
2126            if (size != 0x3)
2127                return new Unknown64(machInst);
2128            else
2129                return new CmleZeroDX<int64_t>(machInst, vd, vn);
2130          case 0x2b:
2131            if (size != 0x3)
2132                return new Unknown64(machInst);
2133            else
2134                return new NegDX<int64_t>(machInst, vd, vn);
2135          case 0x2c:
2136            if (size < 0x2)
2137                return new Unknown64(machInst);
2138            else
2139                return decodeNeonUTwoMiscScFpReg<FcmgeZeroScX>(
2140                    size & 0x1, machInst, vd, vn);
2141          case 0x2d:
2142            if (size < 0x2)
2143                return new Unknown64(machInst);
2144            else
2145                return decodeNeonUTwoMiscScFpReg<FcmleZeroScX>(
2146                    size & 0x1, machInst, vd, vn);
2147          case 0x32:
2148            if (size == 0x3) {
2149                return new Unknown64(machInst);
2150            } else {
2151                switch (size) {
2152                  case 0x0:
2153                    return new SqxtunScX<int8_t>(machInst, vd, vn);
2154                  case 0x1:
2155                    return new SqxtunScX<int16_t>(machInst, vd, vn);
2156                  case 0x2:
2157                    return new SqxtunScX<int32_t>(machInst, vd, vn);
2158                }
2159            }
2160          case 0x34:
2161            if (size == 0x3) {
2162                return new Unknown64(machInst);
2163            } else {
2164                switch (size) {
2165                  case 0x0:
2166                    return new UqxtnScX<uint8_t>(machInst, vd, vn);
2167                  case 0x1:
2168                    return new UqxtnScX<uint16_t>(machInst, vd, vn);
2169                  case 0x2:
2170                    return new UqxtnScX<uint32_t>(machInst, vd, vn);
2171                }
2172            }
2173          case 0x36:
2174            if (size != 0x1) {
2175                return new Unknown64(machInst);
2176            } else {
2177                return new FcvtxnScX<uint32_t>(machInst, vd, vn);
2178            }
2179          case 0x3a:
2180            if (size < 0x2)
2181                return decodeNeonUTwoMiscScFpReg<FcvtnuScX>(
2182                    size & 0x1, machInst, vd, vn);
2183            else
2184                return decodeNeonUTwoMiscScFpReg<FcvtpuScX>(
2185                    size & 0x1, machInst, vd, vn);
2186          case 0x3b:
2187            if (size < 0x2)
2188                return decodeNeonUTwoMiscScFpReg<FcvtmuScX>(
2189                    size & 0x1, machInst, vd, vn);
2190            else
2191                return decodeNeonUTwoMiscScFpReg<FcvtzuIntScX>(
2192                    size & 0x1, machInst, vd, vn);
2193          case 0x3c:
2194            if (size < 0x2)
2195                return decodeNeonUTwoMiscScFpReg<FcvtauScX>(
2196                    size & 0x1, machInst, vd, vn);
2197            else
2198                return new Unknown64(machInst);
2199          case 0x3d:
2200            if (size < 0x2)
2201                return decodeNeonUTwoMiscScFpReg<UcvtfIntScX>(
2202                    size & 0x1, machInst, vd, vn);
2203            else
2204                return decodeNeonUTwoMiscScFpReg<FrsqrteScX>(
2205                    size & 0x1, machInst, vd, vn);
2206          default:
2207            return new Unknown64(machInst);
2208        }
2209    }
2210
2211    StaticInstPtr
2212    decodeNeonScPwise(ExtMachInst machInst)
2213    {
2214        uint8_t u = bits(machInst, 29);
2215        uint8_t size = bits(machInst, 23, 22);
2216        uint8_t opcode = bits(machInst, 16, 12);
2217
2218        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2219        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2220
2221        if (!u) {
2222            if (opcode == 0x1b && size == 0x3)
2223                return new AddpScQX<uint64_t>(machInst, vd, vn);
2224            else
2225                return new Unknown64(machInst);
2226        }
2227
2228        uint8_t switchVal = (opcode << 0) | (size << 5);
2229        switch (switchVal) {
2230          case 0x0c:
2231          case 0x2c:
2232            return decodeNeonUTwoMiscPwiseScFpReg<FmaxnmpScDX, FmaxnmpScQX>(
2233                    size & 0x1, machInst, vd, vn);
2234          case 0x0d:
2235          case 0x2d:
2236            return decodeNeonUTwoMiscPwiseScFpReg<FaddpScDX, FaddpScQX>(
2237                    size & 0x1, machInst, vd, vn);
2238          case 0x0f:
2239          case 0x2f:
2240            return decodeNeonUTwoMiscPwiseScFpReg<FmaxpScDX, FmaxpScQX>(
2241                    size & 0x1, machInst, vd, vn);
2242          case 0x4c:
2243          case 0x6c:
2244            return decodeNeonUTwoMiscPwiseScFpReg<FminnmpScDX, FminnmpScQX>(
2245                    size & 0x1, machInst, vd, vn);
2246          case 0x4f:
2247          case 0x6f:
2248            return decodeNeonUTwoMiscPwiseScFpReg<FminpScDX, FminpScQX>(
2249                    size & 0x1, machInst, vd, vn);
2250          default:
2251            return new Unknown64(machInst);
2252        }
2253    }
2254
2255    StaticInstPtr
2256    decodeNeonScCopy(ExtMachInst machInst)
2257    {
2258        if (bits(machInst, 14, 11) != 0 || bits(machInst, 29))
2259            return new Unknown64(machInst);
2260
2261        uint8_t imm5 = bits(machInst, 20, 16);
2262
2263        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2264        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2265
2266        uint8_t size = findLsbSet(imm5);
2267        uint8_t index = bits(imm5, 4, size + 1);
2268
2269        return decodeNeonUTwoShiftUReg<DupElemScX>(
2270            size, machInst, vd, vn, index);
2271    }
2272
2273    StaticInstPtr
2274    decodeNeonScIndexedElem(ExtMachInst machInst)
2275    {
2276        uint8_t u = bits(machInst, 29);
2277        uint8_t size = bits(machInst, 23, 22);
2278        uint8_t L = bits(machInst, 21);
2279        uint8_t M = bits(machInst, 20);
2280        uint8_t opcode = bits(machInst, 15, 12);
2281        uint8_t H = bits(machInst, 11);
2282
2283        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2284        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2285        IntRegIndex vm_bf = (IntRegIndex) (uint8_t) bits(machInst, 19, 16);
2286
2287        uint8_t index = 0;
2288        uint8_t index_fp = 0;
2289        uint8_t vmh = 0;
2290        uint8_t sz_L = bits(machInst, 22, 21);
2291
2292        // Index and 2nd register operand for integer instructions
2293        if (size == 0x1) {
2294            index = (H << 2) | (L << 1) | M;
2295            // vmh = 0;
2296        } else if (size == 0x2) {
2297            index = (H << 1) | L;
2298            vmh = M;
2299        } else if (size == 0x3) {
2300            index = H;
2301            vmh = M;
2302        }
2303        IntRegIndex vm = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf);
2304
2305        // Index and 2nd register operand for FP instructions
2306        vmh = M;
2307        if ((size & 0x1) == 0) {
2308            index_fp = (H << 1) | L;
2309        } else if (L == 0) {
2310            index_fp = H;
2311        }
2312        IntRegIndex vm_fp = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf);
2313
2314        if (u && opcode != 9)
2315            return new Unknown64(machInst);
2316
2317        switch (opcode) {
2318          case 0x1:
2319            if (size < 2 || sz_L == 0x3)
2320                return new Unknown64(machInst);
2321            else
2322                return decodeNeonUThreeImmScFpReg<FmlaElemScX>(
2323                    size & 0x1, machInst, vd, vn, vm_fp, index_fp);
2324          case 0x3:
2325            if (size == 0x0 || size == 0x3)
2326                return new Unknown64(machInst);
2327            else
2328                return decodeNeonSThreeImmHAndWReg<SqdmlalElemScX>(
2329                    size, machInst, vd, vn, vm, index);
2330          case 0x5:
2331            if (size < 2 || sz_L == 0x3)
2332                return new Unknown64(machInst);
2333            else
2334                return decodeNeonUThreeImmScFpReg<FmlsElemScX>(
2335                    size & 0x1, machInst, vd, vn, vm_fp, index_fp);
2336          case 0x7:
2337            if (size == 0x0 || size == 0x3)
2338                return new Unknown64(machInst);
2339            else
2340                return decodeNeonSThreeImmHAndWReg<SqdmlslElemScX>(
2341                    size, machInst, vd, vn, vm, index);
2342          case 0x9:
2343            if (size < 2 || sz_L == 0x3)
2344                return new Unknown64(machInst);
2345            if (u)
2346                return decodeNeonUThreeImmScFpReg<FmulxElemScX>(
2347                    size & 0x1, machInst, vd, vn, vm_fp, index_fp);
2348            else
2349                return decodeNeonUThreeImmScFpReg<FmulElemScX>(
2350                    size & 0x1, machInst, vd, vn, vm_fp, index_fp);
2351          case 0xb:
2352            if (size == 0x0 || size == 0x3)
2353                return new Unknown64(machInst);
2354            else
2355                return decodeNeonSThreeImmHAndWReg<SqdmullElemScX>(
2356                    size, machInst, vd, vn, vm, index);
2357          case 0xc:
2358            if (size == 0x0 || size == 0x3)
2359                return new Unknown64(machInst);
2360            else
2361                return decodeNeonSThreeImmHAndWReg<SqdmulhElemScX>(
2362                    size, machInst, vd, vn, vm, index);
2363          case 0xd:
2364            if (size == 0x0 || size == 0x3)
2365                return new Unknown64(machInst);
2366            else
2367                return decodeNeonSThreeImmHAndWReg<SqrdmulhElemScX>(
2368                    size, machInst, vd, vn, vm, index);
2369          default:
2370            return new Unknown64(machInst);
2371        }
2372    }
2373
2374    StaticInstPtr
2375    decodeNeonScShiftByImm(ExtMachInst machInst)
2376    {
2377        bool u = bits(machInst, 29);
2378        uint8_t immh = bits(machInst, 22, 19);
2379        uint8_t immb = bits(machInst, 18, 16);
2380        uint8_t opcode = bits(machInst, 15, 11);
2381
2382        IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2383        IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2384
2385        uint8_t immh3 = bits(machInst, 22);
2386        uint8_t size = findMsbSet(immh);
2387        int shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2388
2389        if (immh == 0x0)
2390            return new Unknown64(machInst);
2391
2392        switch (opcode) {
2393          case 0x00:
2394            if (!immh3)
2395                return new Unknown64(machInst);
2396            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2397            if (u)
2398                return new UshrDX<uint64_t>(machInst, vd, vn, shiftAmt);
2399            else
2400                return new SshrDX<int64_t>(machInst, vd, vn, shiftAmt);
2401          case 0x02:
2402            if (!immh3)
2403                return new Unknown64(machInst);
2404            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2405            if (u)
2406                return new UsraDX<uint64_t>(machInst, vd, vn, shiftAmt);
2407            else
2408                return new SsraDX<int64_t>(machInst, vd, vn, shiftAmt);
2409          case 0x04:
2410            if (!immh3)
2411                return new Unknown64(machInst);
2412            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2413            if (u)
2414                return new UrshrDX<uint64_t>(machInst, vd, vn, shiftAmt);
2415            else
2416                return new SrshrDX<int64_t>(machInst, vd, vn, shiftAmt);
2417          case 0x06:
2418            if (!immh3)
2419                return new Unknown64(machInst);
2420            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2421            if (u)
2422                return new UrsraDX<uint64_t>(machInst, vd, vn, shiftAmt);
2423            else
2424                return new SrsraDX<int64_t>(machInst, vd, vn, shiftAmt);
2425          case 0x08:
2426            if (!immh3)
2427                return new Unknown64(machInst);
2428            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2429            if (u)
2430                return new SriDX<uint64_t>(machInst, vd, vn, shiftAmt);
2431            else
2432                return new Unknown64(machInst);
2433          case 0x0a:
2434            if (!immh3)
2435                return new Unknown64(machInst);
2436            shiftAmt = ((immh << 3) | immb) - (8 << size);
2437            if (u)
2438                return new SliDX<uint64_t>(machInst, vd, vn, shiftAmt);
2439            else
2440                return new ShlDX<uint64_t>(machInst, vd, vn, shiftAmt);
2441          case 0x0c:
2442            if (u) {
2443                shiftAmt = ((immh << 3) | immb) - (8 << size);
2444                return decodeNeonSTwoShiftUReg<SqshluScX>(
2445                    size, machInst, vd, vn, shiftAmt);
2446            } else {
2447                return new Unknown64(machInst);
2448            }
2449          case 0x0e:
2450            shiftAmt = ((immh << 3) | immb) - (8 << size);
2451            if (u)
2452                return decodeNeonUTwoShiftUReg<UqshlImmScX>(
2453                    size, machInst, vd, vn, shiftAmt);
2454            else
2455                return decodeNeonSTwoShiftUReg<SqshlImmScX>(
2456                    size, machInst, vd, vn, shiftAmt);
2457          case 0x10:
2458            if (!u || immh3)
2459                return new Unknown64(machInst);
2460            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2461            return decodeNeonSTwoShiftUSReg<SqshrunScX>(
2462                size, machInst, vd, vn, shiftAmt);
2463          case 0x11:
2464            if (!u || immh3)
2465                return new Unknown64(machInst);
2466            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2467            return decodeNeonSTwoShiftUSReg<SqrshrunScX>(
2468                size, machInst, vd, vn, shiftAmt);
2469          case 0x12:
2470            if (immh3)
2471                return new Unknown64(machInst);
2472            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2473            if (u)
2474                return decodeNeonUTwoShiftUSReg<UqshrnScX>(
2475                    size, machInst, vd, vn, shiftAmt);
2476            else
2477                return decodeNeonSTwoShiftUSReg<SqshrnScX>(
2478                    size, machInst, vd, vn, shiftAmt);
2479          case 0x13:
2480            if (immh3)
2481                return new Unknown64(machInst);
2482            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2483            if (u)
2484                return decodeNeonUTwoShiftUSReg<UqrshrnScX>(
2485                    size, machInst, vd, vn, shiftAmt);
2486            else
2487                return decodeNeonSTwoShiftUSReg<SqrshrnScX>(
2488                    size, machInst, vd, vn, shiftAmt);
2489          case 0x1c:
2490            if (immh < 0x4)
2491                return new Unknown64(machInst);
2492            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2493            if (u) {
2494                return decodeNeonUTwoShiftUFpReg<UcvtfFixedScX>(
2495                    size & 0x1, machInst, vd, vn, shiftAmt);
2496            } else {
2497                if (size & 0x1)
2498                    return new ScvtfFixedScDX<uint64_t>(machInst, vd, vn,
2499                                                        shiftAmt);
2500                else
2501                    return new ScvtfFixedScSX<uint32_t>(machInst, vd, vn,
2502                                                        shiftAmt);
2503            }
2504          case 0x1f:
2505            if (immh < 0x4)
2506                return new Unknown64(machInst);
2507            shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
2508            if (u)
2509                return decodeNeonUTwoShiftUFpReg<FcvtzuFixedScX>(
2510                    size & 0x1, machInst, vd, vn, shiftAmt);
2511            else
2512                return decodeNeonUTwoShiftUFpReg<FcvtzsFixedScX>(
2513                    size & 0x1, machInst, vd, vn, shiftAmt);
2514          default:
2515            return new Unknown64(machInst);
2516        }
2517    }
2518
2519    StaticInstPtr
2520    decodeNeonMem(ExtMachInst machInst)
2521    {
2522        uint8_t dataSize = bits(machInst, 30) ? 128 : 64;
2523        bool multiple = bits(machInst, 24, 23) < 0x2;
2524        bool load = bits(machInst, 22);
2525
2526        uint8_t numStructElems = 0;
2527        uint8_t numRegs = 0;
2528
2529        if (multiple) {  // AdvSIMD load/store multiple structures
2530            uint8_t opcode = bits(machInst, 15, 12);
2531            uint8_t eSize = bits(machInst, 11, 10);
2532            bool wb = !(bits(machInst, 20, 16) == 0x0 && !bits(machInst, 23));
2533
2534            switch (opcode) {
2535              case 0x0:  // LD/ST4 (4 regs)
2536                numStructElems = 4;
2537                numRegs = 4;
2538                break;
2539              case 0x2:  // LD/ST1 (4 regs)
2540                numStructElems = 1;
2541                numRegs = 4;
2542                break;
2543              case 0x4:  // LD/ST3 (3 regs)
2544                numStructElems = 3;
2545                numRegs = 3;
2546                break;
2547              case 0x6:  // LD/ST1 (3 regs)
2548                numStructElems = 1;
2549                numRegs = 3;
2550                break;
2551              case 0x7:  // LD/ST1 (1 reg)
2552                numStructElems = 1;
2553                numRegs = 1;
2554                break;
2555              case 0x8:  // LD/ST2 (2 regs)
2556                numStructElems = 2;
2557                numRegs = 2;
2558                break;
2559              case 0xa:  // LD/ST1 (2 regs)
2560                numStructElems = 1;
2561                numRegs = 2;
2562                break;
2563              default:
2564                return new Unknown64(machInst);
2565            }
2566
2567            IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2568            IntRegIndex rn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2569            IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
2570
2571            if (load) {
2572                return new VldMult64(machInst, rn, vd, rm, eSize, dataSize,
2573                                     numStructElems, numRegs, wb);
2574            } else {
2575                return new VstMult64(machInst, rn, vd, rm, eSize, dataSize,
2576                                     numStructElems, numRegs, wb);
2577            }
2578        } else {  // AdvSIMD load/store single structure
2579            uint8_t scale = bits(machInst, 15, 14);
2580            uint8_t numStructElems = (((uint8_t) bits(machInst, 13) << 1) |
2581                                      (uint8_t) bits(machInst, 21)) + 1;
2582            uint8_t index = 0;
2583            bool wb = !(bits(machInst, 20, 16) == 0x0 && !bits(machInst, 23));
2584            bool replicate = false;
2585
2586            switch (scale) {
2587              case 0x0:
2588                index = ((uint8_t) bits(machInst, 30) << 3) |
2589                    ((uint8_t) bits(machInst, 12) << 2) |
2590                    (uint8_t) bits(machInst, 11, 10);
2591                break;
2592              case 0x1:
2593                index = ((uint8_t) bits(machInst, 30) << 2) |
2594                    ((uint8_t) bits(machInst, 12) << 1) |
2595                    (uint8_t) bits(machInst, 11);
2596                break;
2597              case 0x2:
2598                if (bits(machInst, 10) == 0x0) {
2599                    index = ((uint8_t) bits(machInst, 30) << 1) |
2600                        bits(machInst, 12);
2601                } else {
2602                    index = (uint8_t) bits(machInst, 30);
2603                    scale = 0x3;
2604                }
2605                break;
2606              case 0x3:
2607                scale = bits(machInst, 11, 10);
2608                replicate = true;
2609                break;
2610              default:
2611                return new Unknown64(machInst);
2612            }
2613
2614            uint8_t eSize = scale;
2615
2616            IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0);
2617            IntRegIndex rn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5);
2618            IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16);
2619
2620            if (load) {
2621                return new VldSingle64(machInst, rn, vd, rm, eSize, dataSize,
2622                                       numStructElems, index, wb, replicate);
2623            } else {
2624                return new VstSingle64(machInst, rn, vd, rm, eSize, dataSize,
2625                                       numStructElems, index, wb, replicate);
2626            }
2627        }
2628    }
2629}
2630}};
2631