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