fp.isa revision 10037:5cac77888310
1// -*- mode:c++ -*-
2
3// Copyright (c) 2010-2011 ARM Limited
4// All rights reserved
5//
6// The license below extends only to copyright in the software and shall
7// not be construed as granting a license to any other intellectual
8// property including but not limited to intellectual property relating
9// to a hardware implementation of the functionality of the software
10// licensed hereunder.  You may use the software subject to the license
11// terms below provided that you ensure that this notice is replicated
12// unmodified and in its entirety in all distributions of the software,
13// modified or unmodified, in source code or in binary form.
14//
15// Copyright (c) 2007-2008 The Florida State University
16// All rights reserved.
17//
18// Redistribution and use in source and binary forms, with or without
19// modification, are permitted provided that the following conditions are
20// met: redistributions of source code must retain the above copyright
21// notice, this list of conditions and the following disclaimer;
22// redistributions in binary form must reproduce the above copyright
23// notice, this list of conditions and the following disclaimer in the
24// documentation and/or other materials provided with the distribution;
25// neither the name of the copyright holders nor the names of its
26// contributors may be used to endorse or promote products derived from
27// this software without specific prior written permission.
28//
29// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40//
41// Authors: Stephen Hines
42
43////////////////////////////////////////////////////////////////////
44//
45// Floating Point operate instructions
46//
47
48output header {{
49
50    template<template <typename T> class Base>
51    StaticInstPtr
52    newNeonMemInst(const unsigned size,
53                   const ExtMachInst &machInst,
54                   const RegIndex dest, const RegIndex ra,
55                   const uint32_t imm, const unsigned extraMemFlags)
56    {
57        switch (size) {
58          case 0:
59            return new Base<uint8_t>(machInst, dest, ra, imm, extraMemFlags);
60          case 1:
61            return new Base<uint16_t>(machInst, dest, ra, imm, extraMemFlags);
62          case 2:
63            return new Base<uint32_t>(machInst, dest, ra, imm, extraMemFlags);
64          case 3:
65            return new Base<uint64_t>(machInst, dest, ra, imm, extraMemFlags);
66          default:
67            panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
68        }
69    }
70
71    template<template <typename T> class Base>
72    StaticInstPtr
73    newNeonMixInst(const unsigned size,
74                   const ExtMachInst &machInst,
75                   const RegIndex dest, const RegIndex op1,
76                   const uint32_t step)
77    {
78        switch (size) {
79          case 0:
80            return new Base<uint8_t>(machInst, dest, op1, step);
81          case 1:
82            return new Base<uint16_t>(machInst, dest, op1, step);
83          case 2:
84            return new Base<uint32_t>(machInst, dest, op1, step);
85          case 3:
86            return new Base<uint64_t>(machInst, dest, op1, step);
87          default:
88            panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
89        }
90    }
91
92}};
93
94let {{
95    header_output = '''
96    StaticInstPtr
97    decodeNeonMem(ExtMachInst machInst);
98
99    StaticInstPtr
100    decodeNeonData(ExtMachInst machInst);
101    '''
102
103    decoder_output = '''
104    StaticInstPtr
105    decodeNeonMem(ExtMachInst machInst)
106    {
107        const uint32_t b = bits(machInst, 11, 8);
108        const bool single = bits(machInst, 23);
109        const bool singleAll = single && (bits(b, 3, 2) == 3);
110        const bool load = bits(machInst, 21);
111
112        unsigned width = 0;
113
114        if (single) {
115            width = bits(b, 1, 0) + 1;
116        } else {
117            switch (bits(b, 3, 1)) {
118              case 0x0: width = 4;
119                break;
120              case 0x1: width = (b & 0x1) ? 2 : 1;
121                break;
122              case 0x2: width = 3;
123                break;
124              case 0x3: width = 1;
125                break;
126              case 0x4: width = 2;
127                break;
128              case 0x5:
129                if ((b & 0x1) == 0) {
130                    width = 1;
131                    break;
132                }
133                // Fall through on purpose.
134              default:
135                return new Unknown(machInst);
136            }
137        }
138        assert(width > 0 && width <= 4);
139
140        const RegIndex rm = (RegIndex)(uint32_t)bits(machInst, 3, 0);
141        const RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 19, 16);
142        const RegIndex vd = (RegIndex)(uint32_t)(bits(machInst, 15, 12) |
143                                                 bits(machInst, 22) << 4);
144        const uint32_t type = bits(machInst, 11, 8);
145        uint32_t size = 0;
146        uint32_t align = TLB::MustBeOne;
147        unsigned inc = 1;
148        unsigned regs = 1;
149        unsigned lane = 0;
150        if (single) {
151            if (singleAll) {
152                size = bits(machInst, 7, 6);
153                bool t = bits(machInst, 5);
154                align = size | TLB::AllowUnaligned;
155                if (width == 1) {
156                    regs = t ? 2 : 1;
157                    inc = 1;
158                } else {
159                    regs = width;
160                    inc = t ? 2 : 1;
161                }
162                switch (width) {
163                  case 1:
164                  case 2:
165                    if (bits(machInst, 4))
166                        align = size + width - 1;
167                    break;
168                  case 3:
169                    break;
170                  case 4:
171                    if (size == 3) {
172                        if (bits(machInst, 4) == 0)
173                            return new Unknown(machInst);
174                        size = 2;
175                        align = 0x4;
176                    } else if (size == 2) {
177                        if (bits(machInst, 4))
178                            align = 0x3;
179                    } else {
180                        if (bits(machInst, 4))
181                            align = size + 2;
182                    }
183                    break;
184                }
185            } else {
186                size = bits(machInst, 11, 10);
187                align = size | TLB::AllowUnaligned;
188                regs = width;
189                unsigned indexAlign = bits(machInst, 7, 4);
190                // If width is 1, inc is always 1. That's overridden later.
191                switch (size) {
192                  case 0:
193                    inc = 1;
194                    lane = bits(indexAlign, 3, 1);
195                    break;
196                  case 1:
197                    inc = bits(indexAlign, 1) ? 2 : 1;
198                    lane = bits(indexAlign, 3, 2);
199                    break;
200                  case 2:
201                    inc = bits(indexAlign, 2) ? 2 : 1;
202                    lane = bits(indexAlign, 3);
203                    break;
204                }
205                // Override inc for width of 1.
206                if (width == 1) {
207                    inc = 1;
208                }
209                switch (width) {
210                  case 1:
211                    switch (size) {
212                      case 0:
213                        break;
214                      case 1:
215                        if (bits(indexAlign, 0))
216                            align = 1;
217                        break;
218                      case 2:
219                        if (bits(indexAlign, 1, 0))
220                            align = 2;
221                        break;
222                    }
223                    break;
224                  case 2:
225                    if (bits(indexAlign, 0))
226                        align = size + 1;
227                    break;
228                  case 3:
229                    break;
230                  case 4:
231                    switch (size) {
232                      case 0:
233                      case 1:
234                        if (bits(indexAlign, 0))
235                            align = size + 2;
236                        break;
237                      case 2:
238                        if (bits(indexAlign, 0))
239                            align = bits(indexAlign, 1, 0) + 2;
240                        break;
241                    }
242                    break;
243                }
244            }
245            if (size == 0x3) {
246                return new Unknown(machInst);
247            }
248        } else {
249            size = bits(machInst, 7, 6);
250            align = bits(machInst, 5, 4);
251            if (align == 0) {
252                // @align wasn't specified, so alignment can be turned off.
253                align = size | TLB::AllowUnaligned;
254            } else {
255                align = align + 2;
256            }
257            switch (width) {
258              case 1:
259                switch (type) {
260                  case 0x7: regs = 1;
261                    break;
262                  case 0xa: regs = 2;
263                    break;
264                  case 0x6: regs = 3;
265                    break;
266                  case 0x2: regs = 4;
267                    break;
268                  default:
269                    return new Unknown(machInst);
270                }
271                break;
272              case 2:
273                // Regs doesn't behave exactly as it does in the manual
274                // because they loop over regs registers twice and we break
275                // it down in the macroop.
276                switch (type) {
277                  case 0x8: regs = 2; inc = 1;
278                    break;
279                  case 0x9: regs = 2; inc = 2;
280                    break;
281                  case 0x3: regs = 4; inc = 2;
282                    break;
283                  default:
284                    return new Unknown(machInst);
285                }
286                break;
287              case 3:
288                regs = 3;
289                switch (type) {
290                  case 0x4: inc = 1;
291                    break;
292                  case 0x5: inc = 2;;
293                    break;
294                  default:
295                    return new Unknown(machInst);
296                }
297                break;
298              case 4:
299                regs = 4;
300                switch (type) {
301                  case 0: inc = 1;
302                    break;
303                  case 1: inc = 2;
304                    break;
305                  default:
306                    return new Unknown(machInst);
307                }
308                break;
309            }
310        }
311
312        if (load) {
313            // Load instructions.
314            if (single) {
315                return new VldSingle(machInst, singleAll, width, rn, vd,
316                                     regs, inc, size, align, rm, lane);
317            } else {
318                return new VldMult(machInst, width, rn, vd,
319                                   regs, inc, size, align, rm);
320            }
321        } else {
322            // Store instructions.
323            if (single) {
324                if (singleAll) {
325                    return new Unknown(machInst);
326                } else {
327                    return new VstSingle(machInst, false, width, rn, vd,
328                                         regs, inc, size, align, rm, lane);
329                }
330            } else {
331                return new VstMult(machInst, width, rn, vd,
332                                   regs, inc, size, align, rm);
333            }
334        }
335        return new Unknown(machInst);
336    }
337    '''
338
339    decoder_output += '''
340    static StaticInstPtr
341    decodeNeonThreeRegistersSameLength(ExtMachInst machInst)
342    {
343        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
344        const uint32_t a = bits(machInst, 11, 8);
345        const bool b = bits(machInst, 4);
346        const uint32_t c = bits(machInst, 21, 20);
347        const IntRegIndex vd =
348            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
349                               (bits(machInst, 22) << 4)));
350        const IntRegIndex vn =
351            (IntRegIndex)(2 * (bits(machInst, 19, 16) |
352                               (bits(machInst, 7) << 4)));
353        const IntRegIndex vm =
354            (IntRegIndex)(2 * (bits(machInst, 3, 0) |
355                               (bits(machInst, 5) << 4)));
356        const unsigned size = bits(machInst, 21, 20);
357        const bool q = bits(machInst, 6);
358        if (q && ((vd & 0x1) || (vn & 0x1) || (vm & 0x1)))
359            return new Unknown(machInst);
360        switch (a) {
361          case 0x0:
362            if (b) {
363                if (u) {
364                    return decodeNeonUThreeReg<VqaddUD, VqaddUQ>(
365                            q, size, machInst, vd, vn, vm);
366                } else {
367                    return decodeNeonSThreeReg<VqaddSD, VqaddSQ>(
368                            q, size, machInst, vd, vn, vm);
369                }
370            } else {
371                if (size == 3)
372                    return new Unknown(machInst);
373                return decodeNeonUSThreeReg<VhaddD, VhaddQ>(
374                        q, u, size, machInst, vd, vn, vm);
375            }
376          case 0x1:
377            if (!b) {
378                return decodeNeonUSThreeReg<VrhaddD, VrhaddQ>(
379                        q, u, size, machInst, vd, vn, vm);
380            } else {
381                if (u) {
382                    switch (c) {
383                      case 0:
384                        if (q) {
385                            return new VeorQ<uint64_t>(machInst, vd, vn, vm);
386                        } else {
387                            return new VeorD<uint64_t>(machInst, vd, vn, vm);
388                        }
389                      case 1:
390                        if (q) {
391                            return new VbslQ<uint64_t>(machInst, vd, vn, vm);
392                        } else {
393                            return new VbslD<uint64_t>(machInst, vd, vn, vm);
394                        }
395                      case 2:
396                        if (q) {
397                            return new VbitQ<uint64_t>(machInst, vd, vn, vm);
398                        } else {
399                            return new VbitD<uint64_t>(machInst, vd, vn, vm);
400                        }
401                      case 3:
402                        if (q) {
403                            return new VbifQ<uint64_t>(machInst, vd, vn, vm);
404                        } else {
405                            return new VbifD<uint64_t>(machInst, vd, vn, vm);
406                        }
407                    }
408                } else {
409                    switch (c) {
410                      case 0:
411                        if (q) {
412                            return new VandQ<uint64_t>(machInst, vd, vn, vm);
413                        } else {
414                            return new VandD<uint64_t>(machInst, vd, vn, vm);
415                        }
416                      case 1:
417                        if (q) {
418                            return new VbicQ<uint64_t>(machInst, vd, vn, vm);
419                        } else {
420                            return new VbicD<uint64_t>(machInst, vd, vn, vm);
421                        }
422                      case 2:
423                        if (vn == vm) {
424                            if (q) {
425                                return new VmovQ<uint64_t>(
426                                        machInst, vd, vn, vm);
427                            } else {
428                                return new VmovD<uint64_t>(
429                                        machInst, vd, vn, vm);
430                            }
431                        } else {
432                            if (q) {
433                                return new VorrQ<uint64_t>(
434                                        machInst, vd, vn, vm);
435                            } else {
436                                return new VorrD<uint64_t>(
437                                        machInst, vd, vn, vm);
438                            }
439                        }
440                      case 3:
441                        if (q) {
442                            return new VornQ<uint64_t>(
443                                    machInst, vd, vn, vm);
444                        } else {
445                            return new VornD<uint64_t>(
446                                    machInst, vd, vn, vm);
447                        }
448                    }
449                }
450            }
451          case 0x2:
452            if (b) {
453                if (u) {
454                    return decodeNeonUThreeReg<VqsubUD, VqsubUQ>(
455                            q, size, machInst, vd, vn, vm);
456                } else {
457                    return decodeNeonSThreeReg<VqsubSD, VqsubSQ>(
458                            q, size, machInst, vd, vn, vm);
459                }
460            } else {
461                if (size == 3)
462                    return new Unknown(machInst);
463                return decodeNeonUSThreeReg<VhsubD, VhsubQ>(
464                        q, u, size, machInst, vd, vn, vm);
465            }
466          case 0x3:
467            if (b) {
468                return decodeNeonUSThreeReg<VcgeD, VcgeQ>(
469                        q, u, size, machInst, vd, vn, vm);
470            } else {
471                return decodeNeonUSThreeReg<VcgtD, VcgtQ>(
472                        q, u, size, machInst, vd, vn, vm);
473            }
474          case 0x4:
475            if (b) {
476                if (u) {
477                    return decodeNeonUThreeReg<VqshlUD, VqshlUQ>(
478                            q, size, machInst, vd, vm, vn);
479                } else {
480                    return decodeNeonSThreeReg<VqshlSD, VqshlSQ>(
481                            q, size, machInst, vd, vm, vn);
482                }
483            } else {
484                return decodeNeonUSThreeReg<VshlD, VshlQ>(
485                        q, u, size, machInst, vd, vm, vn);
486            }
487          case 0x5:
488            if (b) {
489                if (u) {
490                    return decodeNeonUThreeReg<VqrshlUD, VqrshlUQ>(
491                            q, size, machInst, vd, vm, vn);
492                } else {
493                    return decodeNeonSThreeReg<VqrshlSD, VqrshlSQ>(
494                            q, size, machInst, vd, vm, vn);
495                }
496            } else {
497                return decodeNeonUSThreeReg<VrshlD, VrshlQ>(
498                        q, u, size, machInst, vd, vm, vn);
499            }
500          case 0x6:
501            if (b) {
502                return decodeNeonUSThreeReg<VminD, VminQ>(
503                        q, u, size, machInst, vd, vn, vm);
504            } else {
505                return decodeNeonUSThreeReg<VmaxD, VmaxQ>(
506                        q, u, size, machInst, vd, vn, vm);
507            }
508          case 0x7:
509            if (b) {
510                return decodeNeonUSThreeReg<VabaD, VabaQ>(
511                        q, u, size, machInst, vd, vn, vm);
512            } else {
513                if (bits(machInst, 23) == 1) {
514                    if (q) {
515                        return new Unknown(machInst);
516                    } else {
517                        return decodeNeonUSThreeUSReg<Vabdl>(
518                                u, size, machInst, vd, vn, vm);
519                    }
520                } else {
521                    return decodeNeonUSThreeReg<VabdD, VabdQ>(
522                            q, u, size, machInst, vd, vn, vm);
523                }
524            }
525          case 0x8:
526            if (b) {
527                if (u) {
528                    return decodeNeonUThreeReg<VceqD, VceqQ>(
529                            q, size, machInst, vd, vn, vm);
530                } else {
531                    return decodeNeonUThreeReg<VtstD, VtstQ>(
532                            q, size, machInst, vd, vn, vm);
533                }
534            } else {
535                if (u) {
536                    return decodeNeonUThreeReg<NVsubD, NVsubQ>(
537                            q, size, machInst, vd, vn, vm);
538                } else {
539                    return decodeNeonUThreeReg<NVaddD, NVaddQ>(
540                            q, size, machInst, vd, vn, vm);
541                }
542            }
543          case 0x9:
544            if (b) {
545                if (u) {
546                    return decodeNeonUThreeReg<NVmulpD, NVmulpQ>(
547                            q, size, machInst, vd, vn, vm);
548                } else {
549                    return decodeNeonSThreeReg<NVmulD, NVmulQ>(
550                            q, size, machInst, vd, vn, vm);
551                }
552            } else {
553                if (u) {
554                    return decodeNeonUSThreeReg<NVmlsD, NVmlsQ>(
555                            q, u, size, machInst, vd, vn, vm);
556                } else {
557                    return decodeNeonUSThreeReg<NVmlaD, NVmlaQ>(
558                            q, u, size, machInst, vd, vn, vm);
559                }
560            }
561          case 0xa:
562            if (q)
563                return new Unknown(machInst);
564            if (b) {
565                return decodeNeonUSThreeUSReg<VpminD>(
566                        u, size, machInst, vd, vn, vm);
567            } else {
568                return decodeNeonUSThreeUSReg<VpmaxD>(
569                        u, size, machInst, vd, vn, vm);
570            }
571          case 0xb:
572            if (b) {
573                if (u || q) {
574                    return new Unknown(machInst);
575                } else {
576                    return decodeNeonUThreeUSReg<NVpaddD>(
577                            size, machInst, vd, vn, vm);
578                }
579            } else {
580                if (u) {
581                    return decodeNeonSThreeSReg<VqrdmulhD, VqrdmulhQ>(
582                            q, size, machInst, vd, vn, vm);
583                } else {
584                    return decodeNeonSThreeSReg<VqdmulhD, VqdmulhQ>(
585                            q, size, machInst, vd, vn, vm);
586                }
587            }
588          case 0xc:
589            if (b) {
590                if (!u) {
591                    if (bits(c, 1) == 0) {
592                        if (q) {
593                            return new NVfmaQFp<float>(machInst, vd, vn, vm);
594                        } else {
595                            return new NVfmaDFp<float>(machInst, vd, vn, vm);
596                        }
597                    } else {
598                        if (q) {
599                            return new NVfmsQFp<float>(machInst, vd, vn, vm);
600                        } else {
601                            return new NVfmsDFp<float>(machInst, vd, vn, vm);
602                        }
603                    }
604                }
605            }
606            return new Unknown(machInst);
607          case 0xd:
608            if (b) {
609                if (u) {
610                    if (bits(c, 1) == 0) {
611                        if (q) {
612                            return new NVmulQFp<float>(machInst, vd, vn, vm);
613                        } else {
614                            return new NVmulDFp<float>(machInst, vd, vn, vm);
615                        }
616                    } else {
617                        return new Unknown(machInst);
618                    }
619                } else {
620                    if (bits(c, 1) == 0) {
621                        if (q) {
622                            return new NVmlaQFp<float>(machInst, vd, vn, vm);
623                        } else {
624                            return new NVmlaDFp<float>(machInst, vd, vn, vm);
625                        }
626                    } else {
627                        if (q) {
628                            return new NVmlsQFp<float>(machInst, vd, vn, vm);
629                        } else {
630                            return new NVmlsDFp<float>(machInst, vd, vn, vm);
631                        }
632                    }
633                }
634            } else {
635                if (u) {
636                    if (bits(c, 1) == 0) {
637                        if (q) {
638                            return new VpaddQFp<float>(machInst, vd, vn, vm);
639                        } else {
640                            return new VpaddDFp<float>(machInst, vd, vn, vm);
641                        }
642                    } else {
643                        if (q) {
644                            return new VabdQFp<float>(machInst, vd, vn, vm);
645                        } else {
646                            return new VabdDFp<float>(machInst, vd, vn, vm);
647                        }
648                    }
649                } else {
650                    if (bits(c, 1) == 0) {
651                        if (q) {
652                            return new VaddQFp<float>(machInst, vd, vn, vm);
653                        } else {
654                            return new VaddDFp<float>(machInst, vd, vn, vm);
655                        }
656                    } else {
657                        if (q) {
658                            return new VsubQFp<float>(machInst, vd, vn, vm);
659                        } else {
660                            return new VsubDFp<float>(machInst, vd, vn, vm);
661                        }
662                    }
663                }
664            }
665          case 0xe:
666            if (b) {
667                if (u) {
668                    if (bits(c, 1) == 0) {
669                        if (q) {
670                            return new VacgeQFp<float>(machInst, vd, vn, vm);
671                        } else {
672                            return new VacgeDFp<float>(machInst, vd, vn, vm);
673                        }
674                    } else {
675                        if (q) {
676                            return new VacgtQFp<float>(machInst, vd, vn, vm);
677                        } else {
678                            return new VacgtDFp<float>(machInst, vd, vn, vm);
679                        }
680                    }
681                } else {
682                    return new Unknown(machInst);
683                }
684            } else {
685                if (u) {
686                    if (bits(c, 1) == 0) {
687                        if (q) {
688                            return new VcgeQFp<float>(machInst, vd, vn, vm);
689                        } else {
690                            return new VcgeDFp<float>(machInst, vd, vn, vm);
691                        }
692                    } else {
693                        if (q) {
694                            return new VcgtQFp<float>(machInst, vd, vn, vm);
695                        } else {
696                            return new VcgtDFp<float>(machInst, vd, vn, vm);
697                        }
698                    }
699                } else {
700                    if (bits(c, 1) == 0) {
701                        if (q) {
702                            return new VceqQFp<float>(machInst, vd, vn, vm);
703                        } else {
704                            return new VceqDFp<float>(machInst, vd, vn, vm);
705                        }
706                    } else {
707                        return new Unknown(machInst);
708                    }
709                }
710            }
711          case 0xf:
712            if (b) {
713                if (u) {
714                    return new Unknown(machInst);
715                } else {
716                    if (bits(c, 1) == 0) {
717                        if (q) {
718                            return new VrecpsQFp<float>(machInst, vd, vn, vm);
719                        } else {
720                            return new VrecpsDFp<float>(machInst, vd, vn, vm);
721                        }
722                    } else {
723                        if (q) {
724                            return new VrsqrtsQFp<float>(machInst, vd, vn, vm);
725                        } else {
726                            return new VrsqrtsDFp<float>(machInst, vd, vn, vm);
727                        }
728                    }
729                }
730            } else {
731                if (u) {
732                    if (bits(c, 1) == 0) {
733                        if (q) {
734                            return new VpmaxQFp<float>(machInst, vd, vn, vm);
735                        } else {
736                            return new VpmaxDFp<float>(machInst, vd, vn, vm);
737                        }
738                    } else {
739                        if (q) {
740                            return new VpminQFp<float>(machInst, vd, vn, vm);
741                        } else {
742                            return new VpminDFp<float>(machInst, vd, vn, vm);
743                        }
744                    }
745                } else {
746                    if (bits(c, 1) == 0) {
747                        if (q) {
748                            return new VmaxQFp<float>(machInst, vd, vn, vm);
749                        } else {
750                            return new VmaxDFp<float>(machInst, vd, vn, vm);
751                        }
752                    } else {
753                        if (q) {
754                            return new VminQFp<float>(machInst, vd, vn, vm);
755                        } else {
756                            return new VminDFp<float>(machInst, vd, vn, vm);
757                        }
758                    }
759                }
760            }
761        }
762        return new Unknown(machInst);
763    }
764
765    static StaticInstPtr
766    decodeNeonOneRegModImm(ExtMachInst machInst)
767    {
768        const IntRegIndex vd =
769            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
770                               (bits(machInst, 22) << 4)));
771        const bool q = bits(machInst, 6);
772        const bool op = bits(machInst, 5);
773        const uint8_t cmode = bits(machInst, 11, 8);
774        const uint8_t imm = ((THUMB ? bits(machInst, 28) :
775                                      bits(machInst, 24)) << 7) |
776                            (bits(machInst, 18, 16) << 4) |
777                            (bits(machInst, 3, 0) << 0);
778
779        // Check for invalid immediate encodings and return an unknown op
780        // if it happens
781        bool immValid = true;
782        const uint64_t bigImm = simd_modified_imm(op, cmode, imm, immValid);
783        if (!immValid) {
784            return new Unknown(machInst);
785        }
786
787        if (op) {
788            if (bits(cmode, 3) == 0) {
789                if (bits(cmode, 0) == 0) {
790                    if (q)
791                        return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
792                    else
793                        return new NVmvniD<uint64_t>(machInst, vd, bigImm);
794                } else {
795                    if (q)
796                        return new NVbiciQ<uint64_t>(machInst, vd, bigImm);
797                    else
798                        return new NVbiciD<uint64_t>(machInst, vd, bigImm);
799                }
800            } else {
801                if (bits(cmode, 2) == 1) {
802                    switch (bits(cmode, 1, 0)) {
803                      case 0:
804                      case 1:
805                        if (q)
806                            return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
807                        else
808                            return new NVmvniD<uint64_t>(machInst, vd, bigImm);
809                      case 2:
810                        if (q)
811                            return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
812                        else
813                            return new NVmoviD<uint64_t>(machInst, vd, bigImm);
814                      case 3:
815                        if (q)
816                            return new Unknown(machInst);
817                        else
818                            return new Unknown(machInst);
819                    }
820                } else {
821                    if (bits(cmode, 0) == 0) {
822                        if (q)
823                            return new NVmvniQ<uint64_t>(machInst, vd, bigImm);
824                        else
825                            return new NVmvniD<uint64_t>(machInst, vd, bigImm);
826                    } else {
827                        if (q)
828                            return new NVbiciQ<uint64_t>(machInst, vd, bigImm);
829                        else
830                            return new NVbiciD<uint64_t>(machInst, vd, bigImm);
831                    }
832                }
833            }
834        } else {
835            if (bits(cmode, 3) == 0) {
836                if (bits(cmode, 0) == 0) {
837                    if (q)
838                        return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
839                    else
840                        return new NVmoviD<uint64_t>(machInst, vd, bigImm);
841                } else {
842                    if (q)
843                        return new NVorriQ<uint64_t>(machInst, vd, bigImm);
844                    else
845                        return new NVorriD<uint64_t>(machInst, vd, bigImm);
846                }
847            } else {
848                if (bits(cmode, 2) == 1) {
849                    if (q)
850                        return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
851                    else
852                        return new NVmoviD<uint64_t>(machInst, vd, bigImm);
853                } else {
854                    if (bits(cmode, 0) == 0) {
855                        if (q)
856                            return new NVmoviQ<uint64_t>(machInst, vd, bigImm);
857                        else
858                            return new NVmoviD<uint64_t>(machInst, vd, bigImm);
859                    } else {
860                        if (q)
861                            return new NVorriQ<uint64_t>(machInst, vd, bigImm);
862                        else
863                            return new NVorriD<uint64_t>(machInst, vd, bigImm);
864                    }
865                }
866            }
867        }
868        return new Unknown(machInst);
869    }
870
871    static StaticInstPtr
872    decodeNeonTwoRegAndShift(ExtMachInst machInst)
873    {
874        const uint32_t a = bits(machInst, 11, 8);
875        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
876        const bool b = bits(machInst, 6);
877        const bool l = bits(machInst, 7);
878        const IntRegIndex vd =
879            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
880                               (bits(machInst, 22) << 4)));
881        const IntRegIndex vm =
882            (IntRegIndex)(2 * (bits(machInst, 3, 0) |
883                               (bits(machInst, 5) << 4)));
884        unsigned imm6 = bits(machInst, 21, 16);
885        unsigned imm = ((l ? 1 : 0) << 6) | imm6;
886        unsigned size = 3;
887        unsigned lShiftAmt = 0;
888        unsigned bitSel;
889        for (bitSel = 1 << 6; true; bitSel >>= 1) {
890            if (bitSel & imm)
891                break;
892            else if (!size)
893                return new Unknown(machInst);
894            size--;
895        }
896        lShiftAmt = imm6 & ~bitSel;
897        unsigned rShiftAmt = 0;
898        if (a != 0xe && a != 0xf) {
899            if (size > 2)
900                rShiftAmt = 64 - imm6;
901            else
902                rShiftAmt = 2 * (8 << size) - imm6;
903        }
904
905        switch (a) {
906          case 0x0:
907            return decodeNeonUSTwoShiftReg<NVshrD, NVshrQ>(
908                    b, u, size, machInst, vd, vm, rShiftAmt);
909          case 0x1:
910            return decodeNeonUSTwoShiftReg<NVsraD, NVsraQ>(
911                    b, u, size, machInst, vd, vm, rShiftAmt);
912          case 0x2:
913            return decodeNeonUSTwoShiftReg<NVrshrD, NVrshrQ>(
914                    b, u, size, machInst, vd, vm, rShiftAmt);
915          case 0x3:
916            return decodeNeonUSTwoShiftReg<NVrsraD, NVrsraQ>(
917                    b, u, size, machInst, vd, vm, rShiftAmt);
918          case 0x4:
919            if (u) {
920                return decodeNeonUTwoShiftReg<NVsriD, NVsriQ>(
921                        b, size, machInst, vd, vm, rShiftAmt);
922            } else {
923                return new Unknown(machInst);
924            }
925          case 0x5:
926            if (u) {
927                return decodeNeonUTwoShiftReg<NVsliD, NVsliQ>(
928                        b, size, machInst, vd, vm, lShiftAmt);
929            } else {
930                return decodeNeonUTwoShiftReg<NVshlD, NVshlQ>(
931                        b, size, machInst, vd, vm, lShiftAmt);
932            }
933          case 0x6:
934          case 0x7:
935            if (u) {
936                if (a == 0x6) {
937                    return decodeNeonSTwoShiftReg<NVqshlusD, NVqshlusQ>(
938                            b, size, machInst, vd, vm, lShiftAmt);
939                } else {
940                    return decodeNeonUTwoShiftReg<NVqshluD, NVqshluQ>(
941                            b, size, machInst, vd, vm, lShiftAmt);
942                }
943            } else {
944                return decodeNeonSTwoShiftReg<NVqshlD, NVqshlQ>(
945                        b, size, machInst, vd, vm, lShiftAmt);
946            }
947          case 0x8:
948            if (l) {
949                return new Unknown(machInst);
950            } else if (u) {
951                return decodeNeonSTwoShiftSReg<NVqshruns, NVqrshruns>(
952                        b, size, machInst, vd, vm, rShiftAmt);
953            } else {
954                return decodeNeonUTwoShiftSReg<NVshrn, NVrshrn>(
955                        b, size, machInst, vd, vm, rShiftAmt);
956            }
957          case 0x9:
958            if (l) {
959                return new Unknown(machInst);
960            } else if (u) {
961                return decodeNeonUTwoShiftSReg<NVqshrun, NVqrshrun>(
962                        b, size, machInst, vd, vm, rShiftAmt);
963            } else {
964                return decodeNeonSTwoShiftSReg<NVqshrn, NVqrshrn>(
965                        b, size, machInst, vd, vm, rShiftAmt);
966            }
967          case 0xa:
968            if (l || b) {
969                return new Unknown(machInst);
970            } else {
971                return decodeNeonUSTwoShiftSReg<NVmovl, NVshll>(
972                        lShiftAmt, u, size, machInst, vd, vm, lShiftAmt);
973            }
974          case 0xe:
975            if (l) {
976                return new Unknown(machInst);
977            } else {
978                if (bits(imm6, 5) == 0)
979                    return new Unknown(machInst);
980                if (u) {
981                    if (b) {
982                        return new NVcvtu2fpQ<float>(
983                                machInst, vd, vm, 64 - imm6);
984                    } else {
985                        return new NVcvtu2fpD<float>(
986                                machInst, vd, vm, 64 - imm6);
987                    }
988                } else {
989                    if (b) {
990                        return new NVcvts2fpQ<float>(
991                                machInst, vd, vm, 64 - imm6);
992                    } else {
993                        return new NVcvts2fpD<float>(
994                                machInst, vd, vm, 64 - imm6);
995                    }
996                }
997            }
998          case 0xf:
999            if (l) {
1000                return new Unknown(machInst);
1001            } else {
1002                if (bits(imm6, 5) == 0)
1003                    return new Unknown(machInst);
1004                if (u) {
1005                    if (b) {
1006                        return new NVcvt2ufxQ<float>(
1007                                machInst, vd, vm, 64 - imm6);
1008                    } else {
1009                        return new NVcvt2ufxD<float>(
1010                                machInst, vd, vm, 64 - imm6);
1011                    }
1012                } else {
1013                    if (b) {
1014                        return new NVcvt2sfxQ<float>(
1015                                machInst, vd, vm, 64 - imm6);
1016                    } else {
1017                        return new NVcvt2sfxD<float>(
1018                                machInst, vd, vm, 64 - imm6);
1019                    }
1020                }
1021            }
1022        }
1023        return new Unknown(machInst);
1024    }
1025
1026    static StaticInstPtr
1027    decodeNeonThreeRegDiffLengths(ExtMachInst machInst)
1028    {
1029        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
1030        const uint32_t a = bits(machInst, 11, 8);
1031        const IntRegIndex vd =
1032            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
1033                               (bits(machInst, 22) << 4)));
1034        const IntRegIndex vn =
1035            (IntRegIndex)(2 * (bits(machInst, 19, 16) |
1036                               (bits(machInst, 7) << 4)));
1037        const IntRegIndex vm =
1038            (IntRegIndex)(2 * (bits(machInst, 3, 0) |
1039                               (bits(machInst, 5) << 4)));
1040        const unsigned size = bits(machInst, 21, 20);
1041        switch (a) {
1042          case 0x0:
1043            return decodeNeonUSThreeUSReg<Vaddl>(
1044                    u, size, machInst, vd, vn, vm);
1045          case 0x1:
1046            return decodeNeonUSThreeUSReg<Vaddw>(
1047                    u, size, machInst, vd, vn, vm);
1048          case 0x2:
1049            return decodeNeonUSThreeUSReg<Vsubl>(
1050                    u, size, machInst, vd, vn, vm);
1051          case 0x3:
1052            return decodeNeonUSThreeUSReg<Vsubw>(
1053                    u, size, machInst, vd, vn, vm);
1054          case 0x4:
1055            if (u) {
1056                return decodeNeonUThreeUSReg<Vraddhn>(
1057                        size, machInst, vd, vn, vm);
1058            } else {
1059                return decodeNeonUThreeUSReg<Vaddhn>(
1060                        size, machInst, vd, vn, vm);
1061            }
1062          case 0x5:
1063            return decodeNeonUSThreeUSReg<Vabal>(
1064                    u, size, machInst, vd, vn, vm);
1065          case 0x6:
1066            if (u) {
1067                return decodeNeonUThreeUSReg<Vrsubhn>(
1068                        size, machInst, vd, vn, vm);
1069            } else {
1070                return decodeNeonUThreeUSReg<Vsubhn>(
1071                        size, machInst, vd, vn, vm);
1072            }
1073          case 0x7:
1074            if (bits(machInst, 23)) {
1075                return decodeNeonUSThreeUSReg<Vabdl>(
1076                        u, size, machInst, vd, vn, vm);
1077            } else {
1078                return decodeNeonUSThreeReg<VabdD, VabdQ>(
1079                        bits(machInst, 6), u, size, machInst, vd, vn, vm);
1080            }
1081          case 0x8:
1082            return decodeNeonUSThreeUSReg<Vmlal>(
1083                    u, size, machInst, vd, vn, vm);
1084          case 0xa:
1085            return decodeNeonUSThreeUSReg<Vmlsl>(
1086                    u, size, machInst, vd, vn, vm);
1087          case 0x9:
1088            if (u) {
1089                return new Unknown(machInst);
1090            } else {
1091                return decodeNeonSThreeUSReg<Vqdmlal>(
1092                        size, machInst, vd, vn, vm);
1093            }
1094          case 0xb:
1095            if (u) {
1096                return new Unknown(machInst);
1097            } else {
1098                return decodeNeonSThreeUSReg<Vqdmlsl>(
1099                        size, machInst, vd, vn, vm);
1100            }
1101          case 0xc:
1102            return decodeNeonUSThreeUSReg<Vmull>(
1103                    u, size, machInst, vd, vn, vm);
1104          case 0xd:
1105            if (u) {
1106                return new Unknown(machInst);
1107            } else {
1108                return decodeNeonSThreeUSReg<Vqdmull>(
1109                        size, machInst, vd, vn, vm);
1110            }
1111          case 0xe:
1112            return decodeNeonUThreeUSReg<Vmullp>(
1113                    size, machInst, vd, vn, vm);
1114        }
1115        return new Unknown(machInst);
1116    }
1117
1118    static StaticInstPtr
1119    decodeNeonTwoRegScalar(ExtMachInst machInst)
1120    {
1121        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
1122        const uint32_t a = bits(machInst, 11, 8);
1123        const unsigned size = bits(machInst, 21, 20);
1124        const IntRegIndex vd =
1125            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
1126                               (bits(machInst, 22) << 4)));
1127        const IntRegIndex vn =
1128            (IntRegIndex)(2 * (bits(machInst, 19, 16) |
1129                               (bits(machInst, 7) << 4)));
1130        const IntRegIndex vm = (size == 2) ?
1131            (IntRegIndex)(2 * bits(machInst, 3, 0)) :
1132            (IntRegIndex)(2 * bits(machInst, 2, 0));
1133        const unsigned index = (size == 2) ? (unsigned)bits(machInst, 5) :
1134            (bits(machInst, 3) | (bits(machInst, 5) << 1));
1135        switch (a) {
1136          case 0x0:
1137            if (u) {
1138                switch (size) {
1139                  case 1:
1140                    return new VmlasQ<uint16_t>(machInst, vd, vn, vm, index);
1141                  case 2:
1142                    return new VmlasQ<uint32_t>(machInst, vd, vn, vm, index);
1143                  default:
1144                    return new Unknown(machInst);
1145                }
1146            } else {
1147                switch (size) {
1148                  case 1:
1149                    return new VmlasD<uint16_t>(machInst, vd, vn, vm, index);
1150                  case 2:
1151                    return new VmlasD<uint32_t>(machInst, vd, vn, vm, index);
1152                  default:
1153                    return new Unknown(machInst);
1154                }
1155            }
1156          case 0x1:
1157            if (u)
1158                return new VmlasQFp<float>(machInst, vd, vn, vm, index);
1159            else
1160                return new VmlasDFp<float>(machInst, vd, vn, vm, index);
1161          case 0x4:
1162            if (u) {
1163                switch (size) {
1164                  case 1:
1165                    return new VmlssQ<uint16_t>(machInst, vd, vn, vm, index);
1166                  case 2:
1167                    return new VmlssQ<uint32_t>(machInst, vd, vn, vm, index);
1168                  default:
1169                    return new Unknown(machInst);
1170                }
1171            } else {
1172                switch (size) {
1173                  case 1:
1174                    return new VmlssD<uint16_t>(machInst, vd, vn, vm, index);
1175                  case 2:
1176                    return new VmlssD<uint32_t>(machInst, vd, vn, vm, index);
1177                  default:
1178                    return new Unknown(machInst);
1179                }
1180            }
1181          case 0x5:
1182            if (u)
1183                return new VmlssQFp<float>(machInst, vd, vn, vm, index);
1184            else
1185                return new VmlssDFp<float>(machInst, vd, vn, vm, index);
1186          case 0x2:
1187            if (u) {
1188                switch (size) {
1189                  case 1:
1190                    return new Vmlals<uint16_t>(machInst, vd, vn, vm, index);
1191                  case 2:
1192                    return new Vmlals<uint32_t>(machInst, vd, vn, vm, index);
1193                  default:
1194                    return new Unknown(machInst);
1195                }
1196            } else {
1197                switch (size) {
1198                  case 1:
1199                    return new Vmlals<int16_t>(machInst, vd, vn, vm, index);
1200                  case 2:
1201                    return new Vmlals<int32_t>(machInst, vd, vn, vm, index);
1202                  default:
1203                    return new Unknown(machInst);
1204                }
1205            }
1206          case 0x6:
1207            if (u) {
1208                switch (size) {
1209                  case 1:
1210                    return new Vmlsls<uint16_t>(machInst, vd, vn, vm, index);
1211                  case 2:
1212                    return new Vmlsls<uint32_t>(machInst, vd, vn, vm, index);
1213                  default:
1214                    return new Unknown(machInst);
1215                }
1216            } else {
1217                switch (size) {
1218                  case 1:
1219                    return new Vmlsls<int16_t>(machInst, vd, vn, vm, index);
1220                  case 2:
1221                    return new Vmlsls<int32_t>(machInst, vd, vn, vm, index);
1222                  default:
1223                    return new Unknown(machInst);
1224                }
1225            }
1226          case 0x3:
1227            if (u) {
1228                return new Unknown(machInst);
1229            } else {
1230                switch (size) {
1231                  case 1:
1232                    return new Vqdmlals<int16_t>(machInst, vd, vn, vm, index);
1233                  case 2:
1234                    return new Vqdmlals<int32_t>(machInst, vd, vn, vm, index);
1235                  default:
1236                    return new Unknown(machInst);
1237                }
1238            }
1239          case 0x7:
1240            if (u) {
1241                return new Unknown(machInst);
1242            } else {
1243                switch (size) {
1244                  case 1:
1245                    return new Vqdmlsls<int16_t>(machInst, vd, vn, vm, index);
1246                  case 2:
1247                    return new Vqdmlsls<int32_t>(machInst, vd, vn, vm, index);
1248                  default:
1249                    return new Unknown(machInst);
1250                }
1251            }
1252          case 0x8:
1253            if (u) {
1254                switch (size) {
1255                  case 1:
1256                    return new VmulsQ<uint16_t>(machInst, vd, vn, vm, index);
1257                  case 2:
1258                    return new VmulsQ<uint32_t>(machInst, vd, vn, vm, index);
1259                  default:
1260                    return new Unknown(machInst);
1261                }
1262            } else {
1263                switch (size) {
1264                  case 1:
1265                    return new VmulsD<uint16_t>(machInst, vd, vn, vm, index);
1266                  case 2:
1267                    return new VmulsD<uint32_t>(machInst, vd, vn, vm, index);
1268                  default:
1269                    return new Unknown(machInst);
1270                }
1271            }
1272          case 0x9:
1273            if (u)
1274                return new VmulsQFp<float>(machInst, vd, vn, vm, index);
1275            else
1276                return new VmulsDFp<float>(machInst, vd, vn, vm, index);
1277          case 0xa:
1278            if (u) {
1279                switch (size) {
1280                  case 1:
1281                    return new Vmulls<uint16_t>(machInst, vd, vn, vm, index);
1282                  case 2:
1283                    return new Vmulls<uint32_t>(machInst, vd, vn, vm, index);
1284                  default:
1285                    return new Unknown(machInst);
1286                }
1287            } else {
1288                switch (size) {
1289                  case 1:
1290                    return new Vmulls<int16_t>(machInst, vd, vn, vm, index);
1291                  case 2:
1292                    return new Vmulls<int32_t>(machInst, vd, vn, vm, index);
1293                  default:
1294                    return new Unknown(machInst);
1295                }
1296            }
1297          case 0xb:
1298            if (u) {
1299                return new Unknown(machInst);
1300            } else {
1301                if (u) {
1302                    switch (size) {
1303                      case 1:
1304                        return new Vqdmulls<uint16_t>(
1305                                machInst, vd, vn, vm, index);
1306                      case 2:
1307                        return new Vqdmulls<uint32_t>(
1308                                machInst, vd, vn, vm, index);
1309                      default:
1310                        return new Unknown(machInst);
1311                    }
1312                } else {
1313                    switch (size) {
1314                      case 1:
1315                        return new Vqdmulls<int16_t>(
1316                                machInst, vd, vn, vm, index);
1317                      case 2:
1318                        return new Vqdmulls<int32_t>(
1319                                machInst, vd, vn, vm, index);
1320                      default:
1321                        return new Unknown(machInst);
1322                    }
1323                }
1324            }
1325          case 0xc:
1326            if (u) {
1327                switch (size) {
1328                  case 1:
1329                    return new VqdmulhsQ<int16_t>(
1330                            machInst, vd, vn, vm, index);
1331                  case 2:
1332                    return new VqdmulhsQ<int32_t>(
1333                            machInst, vd, vn, vm, index);
1334                  default:
1335                    return new Unknown(machInst);
1336                }
1337            } else {
1338                switch (size) {
1339                  case 1:
1340                    return new VqdmulhsD<int16_t>(
1341                            machInst, vd, vn, vm, index);
1342                  case 2:
1343                    return new VqdmulhsD<int32_t>(
1344                            machInst, vd, vn, vm, index);
1345                  default:
1346                    return new Unknown(machInst);
1347                }
1348            }
1349          case 0xd:
1350            if (u) {
1351                switch (size) {
1352                  case 1:
1353                    return new VqrdmulhsQ<int16_t>(
1354                            machInst, vd, vn, vm, index);
1355                  case 2:
1356                    return new VqrdmulhsQ<int32_t>(
1357                            machInst, vd, vn, vm, index);
1358                  default:
1359                    return new Unknown(machInst);
1360                }
1361            } else {
1362                switch (size) {
1363                  case 1:
1364                    return new VqrdmulhsD<int16_t>(
1365                            machInst, vd, vn, vm, index);
1366                  case 2:
1367                    return new VqrdmulhsD<int32_t>(
1368                            machInst, vd, vn, vm, index);
1369                  default:
1370                    return new Unknown(machInst);
1371                }
1372            }
1373        }
1374        return new Unknown(machInst);
1375    }
1376
1377    static StaticInstPtr
1378    decodeNeonTwoRegMisc(ExtMachInst machInst)
1379    {
1380        const uint32_t a = bits(machInst, 17, 16);
1381        const uint32_t b = bits(machInst, 10, 6);
1382        const bool q = bits(machInst, 6);
1383        const IntRegIndex vd =
1384            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
1385                               (bits(machInst, 22) << 4)));
1386        const IntRegIndex vm =
1387            (IntRegIndex)(2 * (bits(machInst, 3, 0) |
1388                               (bits(machInst, 5) << 4)));
1389        const unsigned size = bits(machInst, 19, 18);
1390        switch (a) {
1391          case 0x0:
1392            switch (bits(b, 4, 1)) {
1393              case 0x0:
1394                switch (size) {
1395                  case 0:
1396                    if (q) {
1397                        return new NVrev64Q<uint8_t>(machInst, vd, vm);
1398                    } else {
1399                        return new NVrev64D<uint8_t>(machInst, vd, vm);
1400                    }
1401                  case 1:
1402                    if (q) {
1403                        return new NVrev64Q<uint16_t>(machInst, vd, vm);
1404                    } else {
1405                        return new NVrev64D<uint16_t>(machInst, vd, vm);
1406                    }
1407                  case 2:
1408                    if (q) {
1409                        return new NVrev64Q<uint32_t>(machInst, vd, vm);
1410                    } else {
1411                        return new NVrev64D<uint32_t>(machInst, vd, vm);
1412                    }
1413                  default:
1414                    return new Unknown(machInst);
1415                }
1416              case 0x1:
1417                switch (size) {
1418                  case 0:
1419                    if (q) {
1420                        return new NVrev32Q<uint8_t>(machInst, vd, vm);
1421                    } else {
1422                        return new NVrev32D<uint8_t>(machInst, vd, vm);
1423                    }
1424                  case 1:
1425                    if (q) {
1426                        return new NVrev32Q<uint16_t>(machInst, vd, vm);
1427                    } else {
1428                        return new NVrev32D<uint16_t>(machInst, vd, vm);
1429                    }
1430                  default:
1431                    return new Unknown(machInst);
1432                }
1433              case 0x2:
1434                if (size != 0) {
1435                    return new Unknown(machInst);
1436                } else if (q) {
1437                    return new NVrev16Q<uint8_t>(machInst, vd, vm);
1438                } else {
1439                    return new NVrev16D<uint8_t>(machInst, vd, vm);
1440                }
1441              case 0x4:
1442                return decodeNeonSTwoMiscSReg<NVpaddlD, NVpaddlQ>(
1443                        q, size, machInst, vd, vm);
1444              case 0x5:
1445                return decodeNeonUTwoMiscSReg<NVpaddlD, NVpaddlQ>(
1446                        q, size, machInst, vd, vm);
1447              case 0x8:
1448                return decodeNeonSTwoMiscReg<NVclsD, NVclsQ>(
1449                        q, size, machInst, vd, vm);
1450              case 0x9:
1451                return decodeNeonSTwoMiscReg<NVclzD, NVclzQ>(
1452                        q, size, machInst, vd, vm);
1453              case 0xa:
1454                return decodeNeonUTwoMiscReg<NVcntD, NVcntQ>(
1455                        q, size, machInst, vd, vm);
1456              case 0xb:
1457                if (q)
1458                    return new NVmvnQ<uint64_t>(machInst, vd, vm);
1459                else
1460                    return new NVmvnD<uint64_t>(machInst, vd, vm);
1461              case 0xc:
1462                return decodeNeonSTwoMiscSReg<NVpadalD, NVpadalQ>(
1463                        q, size, machInst, vd, vm);
1464              case 0xd:
1465                return decodeNeonUTwoMiscSReg<NVpadalD, NVpadalQ>(
1466                        q, size, machInst, vd, vm);
1467              case 0xe:
1468                return decodeNeonSTwoMiscReg<NVqabsD, NVqabsQ>(
1469                        q, size, machInst, vd, vm);
1470              case 0xf:
1471                return decodeNeonSTwoMiscReg<NVqnegD, NVqnegQ>(
1472                        q, size, machInst, vd, vm);
1473              default:
1474                return new Unknown(machInst);
1475            }
1476          case 0x1:
1477            switch (bits(b, 3, 1)) {
1478              case 0x0:
1479                if (bits(b, 4)) {
1480                    if (q) {
1481                        return new NVcgtQFp<float>(machInst, vd, vm);
1482                    } else {
1483                        return new NVcgtDFp<float>(machInst, vd, vm);
1484                    }
1485                } else {
1486                    return decodeNeonSTwoMiscReg<NVcgtD, NVcgtQ>(
1487                            q, size, machInst, vd, vm);
1488                }
1489              case 0x1:
1490                if (bits(b, 4)) {
1491                    if (q) {
1492                        return new NVcgeQFp<float>(machInst, vd, vm);
1493                    } else {
1494                        return new NVcgeDFp<float>(machInst, vd, vm);
1495                    }
1496                } else {
1497                    return decodeNeonSTwoMiscReg<NVcgeD, NVcgeQ>(
1498                            q, size, machInst, vd, vm);
1499                }
1500              case 0x2:
1501                if (bits(b, 4)) {
1502                    if (q) {
1503                        return new NVceqQFp<float>(machInst, vd, vm);
1504                    } else {
1505                        return new NVceqDFp<float>(machInst, vd, vm);
1506                    }
1507                } else {
1508                    return decodeNeonSTwoMiscReg<NVceqD, NVceqQ>(
1509                            q, size, machInst, vd, vm);
1510                }
1511              case 0x3:
1512                if (bits(b, 4)) {
1513                    if (q) {
1514                        return new NVcleQFp<float>(machInst, vd, vm);
1515                    } else {
1516                        return new NVcleDFp<float>(machInst, vd, vm);
1517                    }
1518                } else {
1519                    return decodeNeonSTwoMiscReg<NVcleD, NVcleQ>(
1520                            q, size, machInst, vd, vm);
1521                }
1522              case 0x4:
1523                if (bits(b, 4)) {
1524                    if (q) {
1525                        return new NVcltQFp<float>(machInst, vd, vm);
1526                    } else {
1527                        return new NVcltDFp<float>(machInst, vd, vm);
1528                    }
1529                } else {
1530                    return decodeNeonSTwoMiscReg<NVcltD, NVcltQ>(
1531                            q, size, machInst, vd, vm);
1532                }
1533              case 0x6:
1534                if (bits(machInst, 10)) {
1535                    if (q)
1536                        return new NVabsQFp<float>(machInst, vd, vm);
1537                    else
1538                        return new NVabsDFp<float>(machInst, vd, vm);
1539                } else {
1540                    return decodeNeonSTwoMiscReg<NVabsD, NVabsQ>(
1541                            q, size, machInst, vd, vm);
1542                }
1543              case 0x7:
1544                if (bits(machInst, 10)) {
1545                    if (q)
1546                        return new NVnegQFp<float>(machInst, vd, vm);
1547                    else
1548                        return new NVnegDFp<float>(machInst, vd, vm);
1549                } else {
1550                    return decodeNeonSTwoMiscReg<NVnegD, NVnegQ>(
1551                            q, size, machInst, vd, vm);
1552                }
1553            }
1554          case 0x2:
1555            switch (bits(b, 4, 1)) {
1556              case 0x0:
1557                if (q)
1558                    return new NVswpQ<uint64_t>(machInst, vd, vm);
1559                else
1560                    return new NVswpD<uint64_t>(machInst, vd, vm);
1561              case 0x1:
1562                return decodeNeonUTwoMiscSReg<NVtrnD, NVtrnQ>(
1563                        q, size, machInst, vd, vm);
1564              case 0x2:
1565                return decodeNeonUTwoMiscReg<NVuzpD, NVuzpQ>(
1566                        q, size, machInst, vd, vm);
1567              case 0x3:
1568                return decodeNeonUTwoMiscReg<NVzipD, NVzipQ>(
1569                        q, size, machInst, vd, vm);
1570              case 0x4:
1571                if (b == 0x8) {
1572                    return decodeNeonUTwoMiscUSReg<NVmovn>(
1573                            size, machInst, vd, vm);
1574                } else {
1575                    return decodeNeonSTwoMiscUSReg<NVqmovuns>(
1576                            size, machInst, vd, vm);
1577                }
1578              case 0x5:
1579                if (q) {
1580                    return decodeNeonUTwoMiscUSReg<NVqmovun>(
1581                            size, machInst, vd, vm);
1582                } else {
1583                    return decodeNeonSTwoMiscUSReg<NVqmovn>(
1584                            size, machInst, vd, vm);
1585                }
1586              case 0x6:
1587                if (b == 0xc) {
1588                    return decodeNeonSTwoShiftUSReg<NVshll>(
1589                            size, machInst, vd, vm, 8 << size);
1590                } else {
1591                    return new Unknown(machInst);
1592                }
1593              case 0xc:
1594              case 0xe:
1595                if (b == 0x18) {
1596                    if (size != 1 || (vm % 2))
1597                        return new Unknown(machInst);
1598                    return new NVcvts2h<uint16_t>(machInst, vd, vm);
1599                } else if (b == 0x1c) {
1600                    if (size != 1 || (vd % 2))
1601                        return new Unknown(machInst);
1602                    return new NVcvth2s<uint16_t>(machInst, vd, vm);
1603                } else {
1604                    return new Unknown(machInst);
1605                }
1606              default:
1607                return new Unknown(machInst);
1608            }
1609          case 0x3:
1610            if (bits(b, 4, 3) == 0x3) {
1611                if ((q && (vd % 2 || vm % 2)) || size != 2) {
1612                    return new Unknown(machInst);
1613                } else {
1614                    if (bits(b, 2)) {
1615                        if (bits(b, 1)) {
1616                            if (q) {
1617                                return new NVcvt2ufxQ<float>(
1618                                        machInst, vd, vm, 0);
1619                            } else {
1620                                return new NVcvt2ufxD<float>(
1621                                        machInst, vd, vm, 0);
1622                            }
1623                        } else {
1624                            if (q) {
1625                                return new NVcvt2sfxQ<float>(
1626                                        machInst, vd, vm, 0);
1627                            } else {
1628                                return new NVcvt2sfxD<float>(
1629                                        machInst, vd, vm, 0);
1630                            }
1631                        }
1632                    } else {
1633                        if (bits(b, 1)) {
1634                            if (q) {
1635                                return new NVcvtu2fpQ<float>(
1636                                        machInst, vd, vm, 0);
1637                            } else {
1638                                return new NVcvtu2fpD<float>(
1639                                        machInst, vd, vm, 0);
1640                            }
1641                        } else {
1642                            if (q) {
1643                                return new NVcvts2fpQ<float>(
1644                                        machInst, vd, vm, 0);
1645                            } else {
1646                                return new NVcvts2fpD<float>(
1647                                        machInst, vd, vm, 0);
1648                            }
1649                        }
1650                    }
1651                }
1652            } else if ((b & 0x1a) == 0x10) {
1653                if (bits(b, 2)) {
1654                    if (q) {
1655                        return new NVrecpeQFp<float>(machInst, vd, vm);
1656                    } else {
1657                        return new NVrecpeDFp<float>(machInst, vd, vm);
1658                    }
1659                } else {
1660                    if (q) {
1661                        return new NVrecpeQ<uint32_t>(machInst, vd, vm);
1662                    } else {
1663                        return new NVrecpeD<uint32_t>(machInst, vd, vm);
1664                    }
1665                }
1666            } else if ((b & 0x1a) == 0x12) {
1667                if (bits(b, 2)) {
1668                    if (q) {
1669                        return new NVrsqrteQFp<float>(machInst, vd, vm);
1670                    } else {
1671                        return new NVrsqrteDFp<float>(machInst, vd, vm);
1672                    }
1673                } else {
1674                    if (q) {
1675                        return new NVrsqrteQ<uint32_t>(machInst, vd, vm);
1676                    } else {
1677                        return new NVrsqrteD<uint32_t>(machInst, vd, vm);
1678                    }
1679                }
1680            } else {
1681                return new Unknown(machInst);
1682            }
1683        }
1684        return new Unknown(machInst);
1685    }
1686
1687    StaticInstPtr
1688    decodeNeonData(ExtMachInst machInst)
1689    {
1690        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
1691        const uint32_t a = bits(machInst, 23, 19);
1692        const uint32_t b = bits(machInst, 11, 8);
1693        const uint32_t c = bits(machInst, 7, 4);
1694        if (bits(a, 4) == 0) {
1695            return decodeNeonThreeRegistersSameLength(machInst);
1696        } else if ((c & 0x9) == 1) {
1697            if ((a & 0x7) == 0) {
1698                return decodeNeonOneRegModImm(machInst);
1699            } else {
1700                return decodeNeonTwoRegAndShift(machInst);
1701            }
1702        } else if ((c & 0x9) == 9) {
1703            return decodeNeonTwoRegAndShift(machInst);
1704        } else if (bits(a, 2, 1) != 0x3) {
1705            if ((c & 0x5) == 0) {
1706                return decodeNeonThreeRegDiffLengths(machInst);
1707            } else if ((c & 0x5) == 4) {
1708                return decodeNeonTwoRegScalar(machInst);
1709            }
1710        } else if ((a & 0x16) == 0x16) {
1711            const IntRegIndex vd =
1712                (IntRegIndex)(2 * (bits(machInst, 15, 12) |
1713                                   (bits(machInst, 22) << 4)));
1714            const IntRegIndex vn =
1715                (IntRegIndex)(2 * (bits(machInst, 19, 16) |
1716                                   (bits(machInst, 7) << 4)));
1717            const IntRegIndex vm =
1718                (IntRegIndex)(2 * (bits(machInst, 3, 0) |
1719                                   (bits(machInst, 5) << 4)));
1720            if (!u) {
1721                if (bits(c, 0) == 0) {
1722                    unsigned imm4 = bits(machInst, 11, 8);
1723                    bool q = bits(machInst, 6);
1724                    if (imm4 >= 16 && !q)
1725                        return new Unknown(machInst);
1726                    if (q) {
1727                        return new NVextQ<uint8_t>(machInst, vd, vn, vm, imm4);
1728                    } else {
1729                        return new NVextD<uint8_t>(machInst, vd, vn, vm, imm4);
1730                    }
1731                }
1732            } else if (bits(b, 3) == 0 && bits(c, 0) == 0) {
1733                return decodeNeonTwoRegMisc(machInst);
1734            } else if (bits(b, 3, 2) == 0x2 && bits(c, 0) == 0) {
1735                unsigned length = bits(machInst, 9, 8) + 1;
1736                if ((uint32_t)vn / 2 + length > 32)
1737                    return new Unknown(machInst);
1738                if (bits(machInst, 6) == 0) {
1739                    switch (length) {
1740                      case 1:
1741                        return new NVtbl1(machInst, vd, vn, vm);
1742                      case 2:
1743                        return new NVtbl2(machInst, vd, vn, vm);
1744                      case 3:
1745                        return new NVtbl3(machInst, vd, vn, vm);
1746                      case 4:
1747                        return new NVtbl4(machInst, vd, vn, vm);
1748                    }
1749                } else {
1750                    switch (length) {
1751                      case 1:
1752                        return new NVtbx1(machInst, vd, vn, vm);
1753                      case 2:
1754                        return new NVtbx2(machInst, vd, vn, vm);
1755                      case 3:
1756                        return new NVtbx3(machInst, vd, vn, vm);
1757                      case 4:
1758                        return new NVtbx4(machInst, vd, vn, vm);
1759                    }
1760                }
1761            } else if (b == 0xc && (c & 0x9) == 0) {
1762                unsigned imm4 = bits(machInst, 19, 16);
1763                if (bits(imm4, 2, 0) == 0)
1764                    return new Unknown(machInst);
1765                unsigned size = 0;
1766                while ((imm4 & 0x1) == 0) {
1767                    size++;
1768                    imm4 >>= 1;
1769                }
1770                unsigned index = imm4 >> 1;
1771                const bool q = bits(machInst, 6);
1772                return decodeNeonUTwoShiftSReg<NVdupD, NVdupQ>(
1773                        q, size, machInst, vd, vm, index);
1774            }
1775        }
1776        return new Unknown(machInst);
1777    }
1778    '''
1779}};
1780
1781def format ThumbNeonMem() {{
1782    decode_block = '''
1783    return decodeNeonMem(machInst);
1784    '''
1785}};
1786
1787def format ThumbNeonData() {{
1788    decode_block = '''
1789    return decodeNeonData(machInst);
1790    '''
1791}};
1792
1793let {{
1794    header_output = '''
1795    StaticInstPtr
1796    decodeExtensionRegLoadStore(ExtMachInst machInst);
1797    '''
1798    decoder_output = '''
1799    StaticInstPtr
1800    decodeExtensionRegLoadStore(ExtMachInst machInst)
1801    {
1802        const uint32_t opcode = bits(machInst, 24, 20);
1803        const uint32_t offset = bits(machInst, 7, 0);
1804        const bool single = (bits(machInst, 8) == 0);
1805        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1806        RegIndex vd;
1807        if (single) {
1808            vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1809                                      bits(machInst, 22));
1810        } else {
1811            vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1812                                      (bits(machInst, 22) << 5));
1813        }
1814        switch (bits(opcode, 4, 3)) {
1815          case 0x0:
1816            if (bits(opcode, 4, 1) == 0x2 &&
1817                    !(machInst.thumb == 1 && bits(machInst, 28) == 1) &&
1818                    !(machInst.thumb == 0 && machInst.condCode == 0xf)) {
1819                if ((bits(machInst, 7, 4) & 0xd) != 1) {
1820                    break;
1821                }
1822                const IntRegIndex rt =
1823                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
1824                const IntRegIndex rt2 =
1825                    (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1826                const bool op = bits(machInst, 20);
1827                uint32_t vm;
1828                if (single) {
1829                    vm = (bits(machInst, 3, 0) << 1) | bits(machInst, 5);
1830                } else {
1831                    vm = (bits(machInst, 3, 0) << 1) |
1832                         (bits(machInst, 5) << 5);
1833                }
1834                if (op) {
1835                    return new Vmov2Core2Reg(machInst, rt, rt2,
1836                                             (IntRegIndex)vm);
1837                } else {
1838                    return new Vmov2Reg2Core(machInst, (IntRegIndex)vm,
1839                                             rt, rt2);
1840                }
1841            }
1842            break;
1843          case 0x1:
1844            {
1845                if (offset == 0 || vd + offset/2 > NumFloatV7ArchRegs) {
1846                    break;
1847                }
1848                switch (bits(opcode, 1, 0)) {
1849                  case 0x0:
1850                    return new VLdmStm(machInst, rn, vd, single,
1851                                       true, false, false, offset);
1852                  case 0x1:
1853                    return new VLdmStm(machInst, rn, vd, single,
1854                                       true, false, true, offset);
1855                  case 0x2:
1856                    return new VLdmStm(machInst, rn, vd, single,
1857                                       true, true, false, offset);
1858                  case 0x3:
1859                    // If rn == sp, then this is called vpop.
1860                    return new VLdmStm(machInst, rn, vd, single,
1861                                       true, true, true, offset);
1862                }
1863            }
1864          case 0x2:
1865            if (bits(opcode, 1, 0) == 0x2) {
1866                // If rn == sp, then this is called vpush.
1867                return new VLdmStm(machInst, rn, vd, single,
1868                                   false, true, false, offset);
1869            } else if (bits(opcode, 1, 0) == 0x3) {
1870                return new VLdmStm(machInst, rn, vd, single,
1871                                   false, true, true, offset);
1872            }
1873            // Fall through on purpose
1874          case 0x3:
1875            const bool up = (bits(machInst, 23) == 1);
1876            const uint32_t imm = bits(machInst, 7, 0) << 2;
1877            if (single) {
1878                vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1879                                          (bits(machInst, 22)));
1880            } else {
1881                vd = (RegIndex)(uint32_t)((bits(machInst, 15, 12) << 1) |
1882                                          (bits(machInst, 22) << 5));
1883            }
1884            if (bits(opcode, 1, 0) == 0x0) {
1885                if (single) {
1886                    if (up) {
1887                        return new %(vstr_us)s(machInst, vd, rn, up, imm);
1888                    } else {
1889                        return new %(vstr_s)s(machInst, vd, rn, up, imm);
1890                    }
1891                } else {
1892                    if (up) {
1893                        return new %(vstr_ud)s(machInst, vd, vd + 1,
1894                                               rn, up, imm);
1895                    } else {
1896                        return new %(vstr_d)s(machInst, vd, vd + 1,
1897                                              rn, up, imm);
1898                    }
1899                }
1900            } else if (bits(opcode, 1, 0) == 0x1) {
1901                if (single) {
1902                    if (up) {
1903                        return new %(vldr_us)s(machInst, vd, rn, up, imm);
1904                    } else {
1905                        return new %(vldr_s)s(machInst, vd, rn, up, imm);
1906                    }
1907                } else {
1908                    if (up) {
1909                        return new %(vldr_ud)s(machInst, vd, vd + 1,
1910                                               rn, up, imm);
1911                    } else {
1912                        return new %(vldr_d)s(machInst, vd, vd + 1,
1913                                              rn, up, imm);
1914                    }
1915                }
1916            }
1917        }
1918        return new Unknown(machInst);
1919    }
1920    ''' % {
1921        "vldr_us" : "VLDR_" + loadImmClassName(False, True, False),
1922        "vldr_s" : "VLDR_" + loadImmClassName(False, False, False),
1923        "vldr_ud" : "VLDR_" + loadDoubleImmClassName(False, True, False),
1924        "vldr_d" : "VLDR_" + loadDoubleImmClassName(False, False, False),
1925        "vstr_us" : "VSTR_" + storeImmClassName(False, True, False),
1926        "vstr_s" : "VSTR_" + storeImmClassName(False, False, False),
1927        "vstr_ud" : "VSTR_" + storeDoubleImmClassName(False, True, False),
1928        "vstr_d" : "VSTR_" + storeDoubleImmClassName(False, False, False)
1929    }
1930}};
1931
1932def format ExtensionRegLoadStore() {{
1933    decode_block = '''
1934    return decodeExtensionRegLoadStore(machInst);
1935    '''
1936}};
1937
1938let {{
1939    header_output = '''
1940    StaticInstPtr
1941    decodeShortFpTransfer(ExtMachInst machInst);
1942    '''
1943    decoder_output = '''
1944    StaticInstPtr
1945    decodeShortFpTransfer(ExtMachInst machInst)
1946    {
1947        const uint32_t l = bits(machInst, 20);
1948        const uint32_t c = bits(machInst, 8);
1949        const uint32_t a = bits(machInst, 23, 21);
1950        const uint32_t b = bits(machInst, 6, 5);
1951        if ((machInst.thumb == 1 && bits(machInst, 28) == 1) ||
1952            (machInst.thumb == 0 && machInst.condCode == 0xf)) {
1953            return new Unknown(machInst);
1954        }
1955        if (l == 0 && c == 0) {
1956            if (a == 0) {
1957                const uint32_t vn = (bits(machInst, 19, 16) << 1) |
1958                                    bits(machInst, 7);
1959                const IntRegIndex rt =
1960                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
1961                if (bits(machInst, 20) == 1) {
1962                    return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn);
1963                } else {
1964                    return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt);
1965                }
1966            } else if (a == 0x7) {
1967                const IntRegIndex rt =
1968                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
1969                uint32_t reg = bits(machInst, 19, 16);
1970                uint32_t specReg;
1971                switch (reg) {
1972                  case 0:
1973                    specReg = MISCREG_FPSID;
1974                    break;
1975                  case 1:
1976                    specReg = MISCREG_FPSCR;
1977                    break;
1978                  case 6:
1979                    specReg = MISCREG_MVFR1;
1980                    break;
1981                  case 7:
1982                    specReg = MISCREG_MVFR0;
1983                    break;
1984                  case 8:
1985                    specReg = MISCREG_FPEXC;
1986                    break;
1987                  default:
1988                    return new Unknown(machInst);
1989                }
1990                if (specReg == MISCREG_FPSCR) {
1991                    return new VmsrFpscr(machInst, (IntRegIndex)specReg, rt);
1992                } else {
1993                    uint32_t iss = mcrMrcIssBuild(0, bits(machInst, 3, 0), rt,
1994                        reg, a, bits(machInst, 7, 5));
1995                    return new Vmsr(machInst, (IntRegIndex)specReg, rt, iss);
1996                }
1997            }
1998        } else if (l == 0 && c == 1) {
1999            if (bits(a, 2) == 0) {
2000                uint32_t vd = (bits(machInst, 7) << 5) |
2001                              (bits(machInst, 19, 16) << 1);
2002                // Handle accessing each single precision half of the vector.
2003                vd += bits(machInst, 21);
2004                const IntRegIndex rt =
2005                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
2006                if (bits(machInst, 22) == 1) {
2007                    return new VmovCoreRegB(machInst, (IntRegIndex)vd,
2008                                            rt, bits(machInst, 6, 5));
2009                } else if (bits(machInst, 5) == 1) {
2010                    return new VmovCoreRegH(machInst, (IntRegIndex)vd,
2011                                            rt, bits(machInst, 6));
2012                } else if (bits(machInst, 6) == 0) {
2013                    return new VmovCoreRegW(machInst, (IntRegIndex)vd, rt);
2014                } else {
2015                    return new Unknown(machInst);
2016                }
2017            } else if (bits(b, 1) == 0) {
2018                bool q = bits(machInst, 21);
2019                unsigned be = (bits(machInst, 22) << 1) | (bits(machInst, 5));
2020                IntRegIndex vd = (IntRegIndex)(2 * (uint32_t)
2021                    (bits(machInst, 19, 16) | (bits(machInst, 7) << 4)));
2022                IntRegIndex rt = (IntRegIndex)(uint32_t)
2023                    bits(machInst, 15, 12);
2024                if (q) {
2025                    switch (be) {
2026                      case 0:
2027                        return new NVdupQGpr<uint32_t>(machInst, vd, rt);
2028                      case 1:
2029                        return new NVdupQGpr<uint16_t>(machInst, vd, rt);
2030                      case 2:
2031                        return new NVdupQGpr<uint8_t>(machInst, vd, rt);
2032                      case 3:
2033                        return new Unknown(machInst);
2034                    }
2035                } else {
2036                    switch (be) {
2037                      case 0:
2038                        return new NVdupDGpr<uint32_t>(machInst, vd, rt);
2039                      case 1:
2040                        return new NVdupDGpr<uint16_t>(machInst, vd, rt);
2041                      case 2:
2042                        return new NVdupDGpr<uint8_t>(machInst, vd, rt);
2043                      case 3:
2044                        return new Unknown(machInst);
2045                    }
2046                }
2047            }
2048        } else if (l == 1 && c == 0) {
2049            if (a == 0) {
2050                const uint32_t vn = (bits(machInst, 19, 16) << 1) |
2051                                    bits(machInst, 7);
2052                const IntRegIndex rt =
2053                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
2054                if (bits(machInst, 20) == 1) {
2055                    return new VmovRegCoreW(machInst, rt, (IntRegIndex)vn);
2056                } else {
2057                    return new VmovCoreRegW(machInst, (IntRegIndex)vn, rt);
2058                }
2059            } else if (a == 7) {
2060                const IntRegIndex rt =
2061                    (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
2062                uint32_t reg = bits(machInst, 19, 16);
2063                uint32_t specReg;
2064                switch (reg) {
2065                  case 0:
2066                    specReg = MISCREG_FPSID;
2067                    break;
2068                  case 1:
2069                    specReg = MISCREG_FPSCR;
2070                    break;
2071                  case 6:
2072                    specReg = MISCREG_MVFR1;
2073                    break;
2074                  case 7:
2075                    specReg = MISCREG_MVFR0;
2076                    break;
2077                  case 8:
2078                    specReg = MISCREG_FPEXC;
2079                    break;
2080                  default:
2081                    return new Unknown(machInst);
2082                }
2083                if (rt == 0xf) {
2084                    if (specReg == MISCREG_FPSCR) {
2085                        return new VmrsApsrFpscr(machInst);
2086                    } else {
2087                        return new Unknown(machInst);
2088                    }
2089                } else if (specReg == MISCREG_FPSCR) {
2090                    return new VmrsFpscr(machInst, rt, (IntRegIndex)specReg);
2091                } else {
2092                    uint32_t iss = mcrMrcIssBuild(l, bits(machInst, 3, 0), rt,
2093                        reg, a, bits(machInst, 7, 5));
2094                    return new Vmrs(machInst, rt, (IntRegIndex)specReg, iss);
2095                }
2096            }
2097        } else {
2098            uint32_t vd = (bits(machInst, 7) << 5) |
2099                          (bits(machInst, 19, 16) << 1);
2100            // Handle indexing into each single precision half of the vector.
2101            vd += bits(machInst, 21);
2102            uint32_t index;
2103            const IntRegIndex rt =
2104                (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
2105            const bool u = (bits(machInst, 23) == 1);
2106            if (bits(machInst, 22) == 1) {
2107                index = bits(machInst, 6, 5);
2108                if (u) {
2109                    return new VmovRegCoreUB(machInst, rt,
2110                                             (IntRegIndex)vd, index);
2111                } else {
2112                    return new VmovRegCoreSB(machInst, rt,
2113                                             (IntRegIndex)vd, index);
2114                }
2115            } else if (bits(machInst, 5) == 1) {
2116                index = bits(machInst, 6);
2117                if (u) {
2118                    return new VmovRegCoreUH(machInst, rt,
2119                                             (IntRegIndex)vd, index);
2120                } else {
2121                    return new VmovRegCoreSH(machInst, rt,
2122                                             (IntRegIndex)vd, index);
2123                }
2124            } else if (bits(machInst, 6) == 0 && !u) {
2125                return new VmovRegCoreW(machInst, rt, (IntRegIndex)vd);
2126            } else {
2127                return new Unknown(machInst);
2128            }
2129        }
2130        return new Unknown(machInst);
2131    }
2132    '''
2133}};
2134
2135def format ShortFpTransfer() {{
2136    decode_block = '''
2137    return decodeShortFpTransfer(machInst);
2138    '''
2139}};
2140
2141let {{
2142    header_output = '''
2143    StaticInstPtr
2144    decodeVfpData(ExtMachInst machInst);
2145    '''
2146    decoder_output = '''
2147    StaticInstPtr
2148    decodeVfpData(ExtMachInst machInst)
2149    {
2150        const uint32_t opc1 = bits(machInst, 23, 20);
2151        const uint32_t opc2 = bits(machInst, 19, 16);
2152        const uint32_t opc3 = bits(machInst, 7, 6);
2153        //const uint32_t opc4 = bits(machInst, 3, 0);
2154        const bool single = (bits(machInst, 8) == 0);
2155        // Used to select between vcmp and vcmpe.
2156        const bool e = (bits(machInst, 7) == 1);
2157        IntRegIndex vd;
2158        IntRegIndex vm;
2159        IntRegIndex vn;
2160        if (single) {
2161            vd = (IntRegIndex)(bits(machInst, 22) |
2162                    (bits(machInst, 15, 12) << 1));
2163            vm = (IntRegIndex)(bits(machInst, 5) |
2164                    (bits(machInst, 3, 0) << 1));
2165            vn = (IntRegIndex)(bits(machInst, 7) |
2166                    (bits(machInst, 19, 16) << 1));
2167        } else {
2168            vd = (IntRegIndex)((bits(machInst, 22) << 5) |
2169                    (bits(machInst, 15, 12) << 1));
2170            vm = (IntRegIndex)((bits(machInst, 5) << 5) |
2171                    (bits(machInst, 3, 0) << 1));
2172            vn = (IntRegIndex)((bits(machInst, 7) << 5) |
2173                    (bits(machInst, 19, 16) << 1));
2174        }
2175        switch (opc1 & 0xb /* 1011 */) {
2176          case 0x0:
2177            if (bits(machInst, 6) == 0) {
2178                if (single) {
2179                    return decodeVfpRegRegRegOp<VmlaS>(
2180                            machInst, vd, vn, vm, false);
2181                } else {
2182                    return decodeVfpRegRegRegOp<VmlaD>(
2183                            machInst, vd, vn, vm, true);
2184                }
2185            } else {
2186                if (single) {
2187                    return decodeVfpRegRegRegOp<VmlsS>(
2188                            machInst, vd, vn, vm, false);
2189                } else {
2190                    return decodeVfpRegRegRegOp<VmlsD>(
2191                            machInst, vd, vn, vm, true);
2192                }
2193            }
2194          case 0x1:
2195            if (bits(machInst, 6) == 1) {
2196                if (single) {
2197                    return decodeVfpRegRegRegOp<VnmlaS>(
2198                            machInst, vd, vn, vm, false);
2199                } else {
2200                    return decodeVfpRegRegRegOp<VnmlaD>(
2201                            machInst, vd, vn, vm, true);
2202                }
2203            } else {
2204                if (single) {
2205                    return decodeVfpRegRegRegOp<VnmlsS>(
2206                            machInst, vd, vn, vm, false);
2207                } else {
2208                    return decodeVfpRegRegRegOp<VnmlsD>(
2209                            machInst, vd, vn, vm, true);
2210                }
2211            }
2212          case 0x2:
2213            if ((opc3 & 0x1) == 0) {
2214                if (single) {
2215                    return decodeVfpRegRegRegOp<VmulS>(
2216                            machInst, vd, vn, vm, false);
2217                } else {
2218                    return decodeVfpRegRegRegOp<VmulD>(
2219                            machInst, vd, vn, vm, true);
2220                }
2221            } else {
2222                if (single) {
2223                    return decodeVfpRegRegRegOp<VnmulS>(
2224                            machInst, vd, vn, vm, false);
2225                } else {
2226                    return decodeVfpRegRegRegOp<VnmulD>(
2227                            machInst, vd, vn, vm, true);
2228                }
2229            }
2230          case 0x3:
2231            if ((opc3 & 0x1) == 0) {
2232                if (single) {
2233                    return decodeVfpRegRegRegOp<VaddS>(
2234                            machInst, vd, vn, vm, false);
2235                } else {
2236                    return decodeVfpRegRegRegOp<VaddD>(
2237                            machInst, vd, vn, vm, true);
2238                }
2239            } else {
2240                if (single) {
2241                    return decodeVfpRegRegRegOp<VsubS>(
2242                            machInst, vd, vn, vm, false);
2243                } else {
2244                    return decodeVfpRegRegRegOp<VsubD>(
2245                            machInst, vd, vn, vm, true);
2246                }
2247            }
2248          case 0x8:
2249            if ((opc3 & 0x1) == 0) {
2250                if (single) {
2251                    return decodeVfpRegRegRegOp<VdivS>(
2252                            machInst, vd, vn, vm, false);
2253                } else {
2254                    return decodeVfpRegRegRegOp<VdivD>(
2255                            machInst, vd, vn, vm, true);
2256                }
2257            }
2258            break;
2259          case 0x9:
2260            if ((opc3 & 0x1) == 0) {
2261                if (single) {
2262                    return decodeVfpRegRegRegOp<VfnmaS>(
2263                            machInst, vd, vn, vm, false);
2264                } else {
2265                    return decodeVfpRegRegRegOp<VfnmaD>(
2266                            machInst, vd, vn, vm, true);
2267                }
2268            } else {
2269                if (single) {
2270                    return decodeVfpRegRegRegOp<VfnmsS>(
2271                            machInst, vd, vn, vm, false);
2272                } else {
2273                    return decodeVfpRegRegRegOp<VfnmsD>(
2274                            machInst, vd, vn, vm, true);
2275                }
2276            }
2277            break;
2278          case 0xa:
2279            if ((opc3 & 0x1) == 0) {
2280                if (single) {
2281                    return decodeVfpRegRegRegOp<VfmaS>(
2282                            machInst, vd, vn, vm, false);
2283                } else {
2284                    return decodeVfpRegRegRegOp<VfmaD>(
2285                            machInst, vd, vn, vm, true);
2286                }
2287            } else {
2288                if (single) {
2289                    return decodeVfpRegRegRegOp<VfmsS>(
2290                            machInst, vd, vn, vm, false);
2291                } else {
2292                    return decodeVfpRegRegRegOp<VfmsD>(
2293                            machInst, vd, vn, vm, true);
2294                }
2295            }
2296            break;
2297          case 0xb:
2298            if ((opc3 & 0x1) == 0) {
2299                const uint32_t baseImm =
2300                    bits(machInst, 3, 0) | (bits(machInst, 19, 16) << 4);
2301                if (single) {
2302                    uint32_t imm = vfp_modified_imm(baseImm, false);
2303                    return decodeVfpRegImmOp<VmovImmS>(
2304                            machInst, vd, imm, false);
2305                } else {
2306                    uint64_t imm = vfp_modified_imm(baseImm, true);
2307                    return decodeVfpRegImmOp<VmovImmD>(
2308                            machInst, vd, imm, true);
2309                }
2310            }
2311            switch (opc2) {
2312              case 0x0:
2313                if (opc3 == 1) {
2314                    if (single) {
2315                        return decodeVfpRegRegOp<VmovRegS>(
2316                                machInst, vd, vm, false);
2317                    } else {
2318                        return decodeVfpRegRegOp<VmovRegD>(
2319                                machInst, vd, vm, true);
2320                    }
2321                } else {
2322                    if (single) {
2323                        return decodeVfpRegRegOp<VabsS>(
2324                                machInst, vd, vm, false);
2325                    } else {
2326                        return decodeVfpRegRegOp<VabsD>(
2327                                machInst, vd, vm, true);
2328                    }
2329                }
2330              case 0x1:
2331                if (opc3 == 1) {
2332                    if (single) {
2333                        return decodeVfpRegRegOp<VnegS>(
2334                                machInst, vd, vm, false);
2335                    } else {
2336                        return decodeVfpRegRegOp<VnegD>(
2337                                machInst, vd, vm, true);
2338                    }
2339                } else {
2340                    if (single) {
2341                        return decodeVfpRegRegOp<VsqrtS>(
2342                                machInst, vd, vm, false);
2343                    } else {
2344                        return decodeVfpRegRegOp<VsqrtD>(
2345                                machInst, vd, vm, true);
2346                    }
2347                }
2348              case 0x2:
2349              case 0x3:
2350                {
2351                    const bool toHalf = bits(machInst, 16);
2352                    const bool top = bits(machInst, 7);
2353                    if (top) {
2354                        if (toHalf) {
2355                            return new VcvtFpSFpHT(machInst, vd, vm);
2356                        } else {
2357                            return new VcvtFpHTFpS(machInst, vd, vm);
2358                        }
2359                    } else {
2360                        if (toHalf) {
2361                            return new VcvtFpSFpHB(machInst, vd, vm);
2362                        } else {
2363                            return new VcvtFpHBFpS(machInst, vd, vm);
2364                        }
2365                    }
2366                }
2367              case 0x4:
2368                if (single) {
2369                    if (e) {
2370                        return new VcmpeS(machInst, vd, vm);
2371                    } else {
2372                        return new VcmpS(machInst, vd, vm);
2373                    }
2374                } else {
2375                    if (e) {
2376                        return new VcmpeD(machInst, vd, vm);
2377                    } else {
2378                        return new VcmpD(machInst, vd, vm);
2379                    }
2380                }
2381              case 0x5:
2382                if (single) {
2383                    if (e) {
2384                        return new VcmpeZeroS(machInst, vd, 0);
2385                    } else {
2386                        return new VcmpZeroS(machInst, vd, 0);
2387                    }
2388                } else {
2389                    if (e) {
2390                        return new VcmpeZeroD(machInst, vd, 0);
2391                    } else {
2392                        return new VcmpZeroD(machInst, vd, 0);
2393                    }
2394                }
2395              case 0x7:
2396                if (opc3 == 0x3) {
2397                    if (single) {
2398                        vd = (IntRegIndex)((bits(machInst, 22) << 5) |
2399                                (bits(machInst, 15, 12) << 1));
2400                        return new VcvtFpSFpD(machInst, vd, vm);
2401                    } else {
2402                        vd = (IntRegIndex)(bits(machInst, 22) |
2403                                (bits(machInst, 15, 12) << 1));
2404                        return new VcvtFpDFpS(machInst, vd, vm);
2405                    }
2406                }
2407                break;
2408              case 0x8:
2409                if (bits(machInst, 7) == 0) {
2410                    if (single) {
2411                        return new VcvtUIntFpS(machInst, vd, vm);
2412                    } else {
2413                        vm = (IntRegIndex)(bits(machInst, 5) |
2414                                (bits(machInst, 3, 0) << 1));
2415                        return new VcvtUIntFpD(machInst, vd, vm);
2416                    }
2417                } else {
2418                    if (single) {
2419                        return new VcvtSIntFpS(machInst, vd, vm);
2420                    } else {
2421                        vm = (IntRegIndex)(bits(machInst, 5) |
2422                                (bits(machInst, 3, 0) << 1));
2423                        return new VcvtSIntFpD(machInst, vd, vm);
2424                    }
2425                }
2426              case 0xa:
2427                {
2428                    const bool half = (bits(machInst, 7) == 0);
2429                    const uint32_t imm = bits(machInst, 5) |
2430                                         (bits(machInst, 3, 0) << 1);
2431                    const uint32_t size =
2432                        (bits(machInst, 7) == 0 ? 16 : 32) - imm;
2433                    if (single) {
2434                        if (half) {
2435                            return new VcvtSHFixedFpS(machInst, vd, vd, size);
2436                        } else {
2437                            return new VcvtSFixedFpS(machInst, vd, vd, size);
2438                        }
2439                    } else {
2440                        if (half) {
2441                            return new VcvtSHFixedFpD(machInst, vd, vd, size);
2442                        } else {
2443                            return new VcvtSFixedFpD(machInst, vd, vd, size);
2444                        }
2445                    }
2446                }
2447              case 0xb:
2448                {
2449                    const bool half = (bits(machInst, 7) == 0);
2450                    const uint32_t imm = bits(machInst, 5) |
2451                                         (bits(machInst, 3, 0) << 1);
2452                    const uint32_t size =
2453                        (bits(machInst, 7) == 0 ? 16 : 32) - imm;
2454                    if (single) {
2455                        if (half) {
2456                            return new VcvtUHFixedFpS(machInst, vd, vd, size);
2457                        } else {
2458                            return new VcvtUFixedFpS(machInst, vd, vd, size);
2459                        }
2460                    } else {
2461                        if (half) {
2462                            return new VcvtUHFixedFpD(machInst, vd, vd, size);
2463                        } else {
2464                            return new VcvtUFixedFpD(machInst, vd, vd, size);
2465                        }
2466                    }
2467                }
2468              case 0xc:
2469                if (bits(machInst, 7) == 0) {
2470                    if (single) {
2471                        return new VcvtFpUIntSR(machInst, vd, vm);
2472                    } else {
2473                        vd = (IntRegIndex)(bits(machInst, 22) |
2474                                (bits(machInst, 15, 12) << 1));
2475                        return new VcvtFpUIntDR(machInst, vd, vm);
2476                    }
2477                } else {
2478                    if (single) {
2479                        return new VcvtFpUIntS(machInst, vd, vm);
2480                    } else {
2481                        vd = (IntRegIndex)(bits(machInst, 22) |
2482                                (bits(machInst, 15, 12) << 1));
2483                        return new VcvtFpUIntD(machInst, vd, vm);
2484                    }
2485                }
2486              case 0xd:
2487                if (bits(machInst, 7) == 0) {
2488                    if (single) {
2489                        return new VcvtFpSIntSR(machInst, vd, vm);
2490                    } else {
2491                        vd = (IntRegIndex)(bits(machInst, 22) |
2492                                (bits(machInst, 15, 12) << 1));
2493                        return new VcvtFpSIntDR(machInst, vd, vm);
2494                    }
2495                } else {
2496                    if (single) {
2497                        return new VcvtFpSIntS(machInst, vd, vm);
2498                    } else {
2499                        vd = (IntRegIndex)(bits(machInst, 22) |
2500                                (bits(machInst, 15, 12) << 1));
2501                        return new VcvtFpSIntD(machInst, vd, vm);
2502                    }
2503                }
2504              case 0xe:
2505                {
2506                    const bool half = (bits(machInst, 7) == 0);
2507                    const uint32_t imm = bits(machInst, 5) |
2508                                         (bits(machInst, 3, 0) << 1);
2509                    const uint32_t size =
2510                        (bits(machInst, 7) == 0 ? 16 : 32) - imm;
2511                    if (single) {
2512                        if (half) {
2513                            return new VcvtFpSHFixedS(machInst, vd, vd, size);
2514                        } else {
2515                            return new VcvtFpSFixedS(machInst, vd, vd, size);
2516                        }
2517                    } else {
2518                        if (half) {
2519                            return new VcvtFpSHFixedD(machInst, vd, vd, size);
2520                        } else {
2521                            return new VcvtFpSFixedD(machInst, vd, vd, size);
2522                        }
2523                    }
2524                }
2525              case 0xf:
2526                {
2527                    const bool half = (bits(machInst, 7) == 0);
2528                    const uint32_t imm = bits(machInst, 5) |
2529                                         (bits(machInst, 3, 0) << 1);
2530                    const uint32_t size =
2531                        (bits(machInst, 7) == 0 ? 16 : 32) - imm;
2532                    if (single) {
2533                        if (half) {
2534                            return new VcvtFpUHFixedS(machInst, vd, vd, size);
2535                        } else {
2536                            return new VcvtFpUFixedS(machInst, vd, vd, size);
2537                        }
2538                    } else {
2539                        if (half) {
2540                            return new VcvtFpUHFixedD(machInst, vd, vd, size);
2541                        } else {
2542                            return new VcvtFpUFixedD(machInst, vd, vd, size);
2543                        }
2544                    }
2545                }
2546            }
2547            break;
2548        }
2549        return new Unknown(machInst);
2550    }
2551    '''
2552}};
2553
2554def format VfpData() {{
2555    decode_block = '''
2556    return decodeVfpData(machInst);
2557    '''
2558}};
2559