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