fp.isa revision 10037
19665Sandreas.hansson@arm.com// -*- mode:c++ -*-
29665Sandreas.hansson@arm.com
39665Sandreas.hansson@arm.com// Copyright (c) 2010-2011 ARM Limited
49665Sandreas.hansson@arm.com// All rights reserved
59665Sandreas.hansson@arm.com//
69665Sandreas.hansson@arm.com// The license below extends only to copyright in the software and shall
79665Sandreas.hansson@arm.com// not be construed as granting a license to any other intellectual
89665Sandreas.hansson@arm.com// property including but not limited to intellectual property relating
99665Sandreas.hansson@arm.com// to a hardware implementation of the functionality of the software
109665Sandreas.hansson@arm.com// licensed hereunder.  You may use the software subject to the license
119665Sandreas.hansson@arm.com// terms below provided that you ensure that this notice is replicated
129665Sandreas.hansson@arm.com// unmodified and in its entirety in all distributions of the software,
135353Svilas.sridharan@gmail.com// modified or unmodified, in source code or in binary form.
143395Shsul@eecs.umich.edu//
153395Shsul@eecs.umich.edu// Copyright (c) 2007-2008 The Florida State University
163395Shsul@eecs.umich.edu// All rights reserved.
173395Shsul@eecs.umich.edu//
183395Shsul@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
193395Shsul@eecs.umich.edu// modification, are permitted provided that the following conditions are
203395Shsul@eecs.umich.edu// met: redistributions of source code must retain the above copyright
213395Shsul@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
223395Shsul@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
233395Shsul@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
243395Shsul@eecs.umich.edu// documentation and/or other materials provided with the distribution;
253395Shsul@eecs.umich.edu// neither the name of the copyright holders nor the names of its
263395Shsul@eecs.umich.edu// contributors may be used to endorse or promote products derived from
273395Shsul@eecs.umich.edu// this software without specific prior written permission.
283395Shsul@eecs.umich.edu//
293395Shsul@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
303395Shsul@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
313395Shsul@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
323395Shsul@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
333395Shsul@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
343395Shsul@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
353395Shsul@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
363395Shsul@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
373395Shsul@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
383395Shsul@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
393395Shsul@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
403395Shsul@eecs.umich.edu//
4113774Sandreas.sandberg@arm.com// Authors: Stephen Hines
4213774Sandreas.sandberg@arm.com
4313774Sandreas.sandberg@arm.com////////////////////////////////////////////////////////////////////
448920Snilay@cs.wisc.edu//
458920Snilay@cs.wisc.edu// Floating Point operate instructions
468920Snilay@cs.wisc.edu//
477025SBrad.Beckmann@amd.com
4813774Sandreas.sandberg@arm.comoutput header {{
4913774Sandreas.sandberg@arm.com
5013774Sandreas.sandberg@arm.com    template<template <typename T> class Base>
5113774Sandreas.sandberg@arm.com    StaticInstPtr
5213774Sandreas.sandberg@arm.com    newNeonMemInst(const unsigned size,
5310747SChris.Emmons@arm.com                   const ExtMachInst &machInst,
549520SAndreas.Sandberg@ARM.com                   const RegIndex dest, const RegIndex ra,
559520SAndreas.Sandberg@ARM.com                   const uint32_t imm, const unsigned extraMemFlags)
569520SAndreas.Sandberg@ARM.com    {
579520SAndreas.Sandberg@ARM.com        switch (size) {
5813432Spau.cabre@metempsy.com          case 0:
5913432Spau.cabre@metempsy.com            return new Base<uint8_t>(machInst, dest, ra, imm, extraMemFlags);
6013432Spau.cabre@metempsy.com          case 1:
6113432Spau.cabre@metempsy.com            return new Base<uint16_t>(machInst, dest, ra, imm, extraMemFlags);
629665Sandreas.hansson@arm.com          case 2:
639665Sandreas.hansson@arm.com            return new Base<uint32_t>(machInst, dest, ra, imm, extraMemFlags);
649665Sandreas.hansson@arm.com          case 3:
659665Sandreas.hansson@arm.com            return new Base<uint64_t>(machInst, dest, ra, imm, extraMemFlags);
6611238Sandreas.sandberg@arm.com          default:
6711238Sandreas.sandberg@arm.com            panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
6811238Sandreas.sandberg@arm.com        }
6911238Sandreas.sandberg@arm.com    }
7011688Sandreas.hansson@arm.com
7111688Sandreas.hansson@arm.com    template<template <typename T> class Base>
7211688Sandreas.hansson@arm.com    StaticInstPtr
7311688Sandreas.hansson@arm.com    newNeonMixInst(const unsigned size,
748920Snilay@cs.wisc.edu                   const ExtMachInst &machInst,
759827Sakash.bagdia@arm.com                   const RegIndex dest, const RegIndex op1,
769827Sakash.bagdia@arm.com                   const uint32_t step)
779827Sakash.bagdia@arm.com    {
789827Sakash.bagdia@arm.com        switch (size) {
799790Sakash.bagdia@arm.com          case 0:
809790Sakash.bagdia@arm.com            return new Base<uint8_t>(machInst, dest, op1, step);
819790Sakash.bagdia@arm.com          case 1:
829790Sakash.bagdia@arm.com            return new Base<uint16_t>(machInst, dest, op1, step);
8311688Sandreas.hansson@arm.com          case 2:
8411688Sandreas.hansson@arm.com            return new Base<uint32_t>(machInst, dest, op1, step);
8511688Sandreas.hansson@arm.com          case 3:
8611688Sandreas.hansson@arm.com            return new Base<uint64_t>(machInst, dest, op1, step);
8711688Sandreas.hansson@arm.com          default:
8811837Swendy.elsasser@arm.com            panic("Unrecognized width %d for Neon mem inst.\n", (1 << size));
8911688Sandreas.hansson@arm.com        }
9011688Sandreas.hansson@arm.com    }
9111688Sandreas.hansson@arm.com
9211688Sandreas.hansson@arm.com}};
9311688Sandreas.hansson@arm.com
9411688Sandreas.hansson@arm.comlet {{
9511688Sandreas.hansson@arm.com    header_output = '''
9611688Sandreas.hansson@arm.com    StaticInstPtr
9711688Sandreas.hansson@arm.com    decodeNeonMem(ExtMachInst machInst);
9811688Sandreas.hansson@arm.com
9911688Sandreas.hansson@arm.com    StaticInstPtr
10011688Sandreas.hansson@arm.com    decodeNeonData(ExtMachInst machInst);
10111688Sandreas.hansson@arm.com    '''
10211688Sandreas.hansson@arm.com
10311688Sandreas.hansson@arm.com    decoder_output = '''
10411688Sandreas.hansson@arm.com    StaticInstPtr
10511688Sandreas.hansson@arm.com    decodeNeonMem(ExtMachInst machInst)
10611688Sandreas.hansson@arm.com    {
10711688Sandreas.hansson@arm.com        const uint32_t b = bits(machInst, 11, 8);
10811688Sandreas.hansson@arm.com        const bool single = bits(machInst, 23);
10911688Sandreas.hansson@arm.com        const bool singleAll = single && (bits(b, 3, 2) == 3);
11011688Sandreas.hansson@arm.com        const bool load = bits(machInst, 21);
11111688Sandreas.hansson@arm.com
11211688Sandreas.hansson@arm.com        unsigned width = 0;
11311688Sandreas.hansson@arm.com
11411688Sandreas.hansson@arm.com        if (single) {
11511688Sandreas.hansson@arm.com            width = bits(b, 1, 0) + 1;
11611688Sandreas.hansson@arm.com        } else {
11711688Sandreas.hansson@arm.com            switch (bits(b, 3, 1)) {
11811688Sandreas.hansson@arm.com              case 0x0: width = 4;
11911688Sandreas.hansson@arm.com                break;
12011688Sandreas.hansson@arm.com              case 0x1: width = (b & 0x1) ? 2 : 1;
12111688Sandreas.hansson@arm.com                break;
12211688Sandreas.hansson@arm.com              case 0x2: width = 3;
12311688Sandreas.hansson@arm.com                break;
12411688Sandreas.hansson@arm.com              case 0x3: width = 1;
12511688Sandreas.hansson@arm.com                break;
12611688Sandreas.hansson@arm.com              case 0x4: width = 2;
12711688Sandreas.hansson@arm.com                break;
12811688Sandreas.hansson@arm.com              case 0x5:
12911688Sandreas.hansson@arm.com                if ((b & 0x1) == 0) {
13011688Sandreas.hansson@arm.com                    width = 1;
13111688Sandreas.hansson@arm.com                    break;
13211688Sandreas.hansson@arm.com                }
13311688Sandreas.hansson@arm.com                // Fall through on purpose.
13411688Sandreas.hansson@arm.com              default:
13511688Sandreas.hansson@arm.com                return new Unknown(machInst);
13613357Sciro.santilli@arm.com            }
13713357Sciro.santilli@arm.com        }
13813357Sciro.santilli@arm.com        assert(width > 0 && width <= 4);
13913357Sciro.santilli@arm.com
14013357Sciro.santilli@arm.com        const RegIndex rm = (RegIndex)(uint32_t)bits(machInst, 3, 0);
14113357Sciro.santilli@arm.com        const RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 19, 16);
14213357Sciro.santilli@arm.com        const RegIndex vd = (RegIndex)(uint32_t)(bits(machInst, 15, 12) |
14313357Sciro.santilli@arm.com                                                 bits(machInst, 22) << 4);
14411688Sandreas.hansson@arm.com        const uint32_t type = bits(machInst, 11, 8);
14511688Sandreas.hansson@arm.com        uint32_t size = 0;
14611688Sandreas.hansson@arm.com        uint32_t align = TLB::MustBeOne;
14711688Sandreas.hansson@arm.com        unsigned inc = 1;
14811688Sandreas.hansson@arm.com        unsigned regs = 1;
14911688Sandreas.hansson@arm.com        unsigned lane = 0;
15011688Sandreas.hansson@arm.com        if (single) {
15111688Sandreas.hansson@arm.com            if (singleAll) {
15211688Sandreas.hansson@arm.com                size = bits(machInst, 7, 6);
15311688Sandreas.hansson@arm.com                bool t = bits(machInst, 5);
15411995Sgabeblack@google.com                align = size | TLB::AllowUnaligned;
15511688Sandreas.hansson@arm.com                if (width == 1) {
15611688Sandreas.hansson@arm.com                    regs = t ? 2 : 1;
15713432Spau.cabre@metempsy.com                    inc = 1;
15813432Spau.cabre@metempsy.com                } else {
15913432Spau.cabre@metempsy.com                    regs = width;
16013432Spau.cabre@metempsy.com                    inc = t ? 2 : 1;
16113432Spau.cabre@metempsy.com                }
16213432Spau.cabre@metempsy.com                switch (width) {
16313432Spau.cabre@metempsy.com                  case 1:
16413432Spau.cabre@metempsy.com                  case 2:
16513432Spau.cabre@metempsy.com                    if (bits(machInst, 4))
16611688Sandreas.hansson@arm.com                        align = size + width - 1;
1679789Sakash.bagdia@arm.com                    break;
1689789Sakash.bagdia@arm.com                  case 3:
1699789Sakash.bagdia@arm.com                    break;
1709800Snilay@cs.wisc.edu                  case 4:
1719800Snilay@cs.wisc.edu                    if (size == 3) {
1729800Snilay@cs.wisc.edu                        if (bits(machInst, 4) == 0)
1739800Snilay@cs.wisc.edu                            return new Unknown(machInst);
1749800Snilay@cs.wisc.edu                        size = 2;
17511251Sradhika.jagtap@ARM.com                        align = 0x4;
17611251Sradhika.jagtap@ARM.com                    } else if (size == 2) {
17711251Sradhika.jagtap@ARM.com                        if (bits(machInst, 4))
17811251Sradhika.jagtap@ARM.com                            align = 0x3;
17911251Sradhika.jagtap@ARM.com                    } else {
18011251Sradhika.jagtap@ARM.com                        if (bits(machInst, 4))
18111251Sradhika.jagtap@ARM.com                            align = size + 2;
18211251Sradhika.jagtap@ARM.com                    }
18311251Sradhika.jagtap@ARM.com                    break;
18411251Sradhika.jagtap@ARM.com                }
18511251Sradhika.jagtap@ARM.com            } else {
18611251Sradhika.jagtap@ARM.com                size = bits(machInst, 11, 10);
18711251Sradhika.jagtap@ARM.com                align = size | TLB::AllowUnaligned;
1889800Snilay@cs.wisc.edu                regs = width;
18910037SARM gem5 Developers                unsigned indexAlign = bits(machInst, 7, 4);
19010037SARM gem5 Developers                // If width is 1, inc is always 1. That's overridden later.
19110037SARM gem5 Developers                switch (size) {
19211626Smichael.lebeane@amd.com                  case 0:
19311626Smichael.lebeane@amd.com                    inc = 1;
19411626Smichael.lebeane@amd.com                    lane = bits(indexAlign, 3, 1);
19511703Smichael.lebeane@amd.com                    break;
19611703Smichael.lebeane@amd.com                  case 1:
19711626Smichael.lebeane@amd.com                    inc = bits(indexAlign, 1) ? 2 : 1;
19811626Smichael.lebeane@amd.com                    lane = bits(indexAlign, 3, 2);
19911626Smichael.lebeane@amd.com                    break;
20011626Smichael.lebeane@amd.com                  case 2:
20111626Smichael.lebeane@amd.com                    inc = bits(indexAlign, 2) ? 2 : 1;
20211626Smichael.lebeane@amd.com                    lane = bits(indexAlign, 3);
20311626Smichael.lebeane@amd.com                    break;
20411626Smichael.lebeane@amd.com                }
20511626Smichael.lebeane@amd.com                // Override inc for width of 1.
20611626Smichael.lebeane@amd.com                if (width == 1) {
20711626Smichael.lebeane@amd.com                    inc = 1;
20811626Smichael.lebeane@amd.com                }
20911626Smichael.lebeane@amd.com                switch (width) {
21011626Smichael.lebeane@amd.com                  case 1:
21111626Smichael.lebeane@amd.com                    switch (size) {
21211626Smichael.lebeane@amd.com                      case 0:
21311626Smichael.lebeane@amd.com                        break;
21411626Smichael.lebeane@amd.com                      case 1:
21511626Smichael.lebeane@amd.com                        if (bits(indexAlign, 0))
21611626Smichael.lebeane@amd.com                            align = 1;
21711626Smichael.lebeane@amd.com                        break;
21811626Smichael.lebeane@amd.com                      case 2:
21911626Smichael.lebeane@amd.com                        if (bits(indexAlign, 1, 0))
22011626Smichael.lebeane@amd.com                            align = 2;
22111626Smichael.lebeane@amd.com                        break;
22211626Smichael.lebeane@amd.com                    }
22311626Smichael.lebeane@amd.com                    break;
22411626Smichael.lebeane@amd.com                  case 2:
22511626Smichael.lebeane@amd.com                    if (bits(indexAlign, 0))
22611626Smichael.lebeane@amd.com                        align = size + 1;
2278920Snilay@cs.wisc.edu                    break;
2288920Snilay@cs.wisc.edu                  case 3:
2298920Snilay@cs.wisc.edu                    break;
2308920Snilay@cs.wisc.edu                  case 4:
2318920Snilay@cs.wisc.edu                    switch (size) {
2328920Snilay@cs.wisc.edu                      case 0:
23310159Sgedare@rtems.org                      case 1:
23410159Sgedare@rtems.org                        if (bits(indexAlign, 0))
2358920Snilay@cs.wisc.edu                            align = size + 2;
2368920Snilay@cs.wisc.edu                        break;
2378920Snilay@cs.wisc.edu                      case 2:
2388920Snilay@cs.wisc.edu                        if (bits(indexAlign, 0))
2398920Snilay@cs.wisc.edu                            align = bits(indexAlign, 1, 0) + 2;
2408920Snilay@cs.wisc.edu                        break;
2418920Snilay@cs.wisc.edu                    }
2428920Snilay@cs.wisc.edu                    break;
2438920Snilay@cs.wisc.edu                }
24410757SCurtis.Dunham@arm.com            }
24510757SCurtis.Dunham@arm.com            if (size == 0x3) {
24610757SCurtis.Dunham@arm.com                return new Unknown(machInst);
2476776SBrad.Beckmann@amd.com            }
2489800Snilay@cs.wisc.edu        } else {
2499800Snilay@cs.wisc.edu            size = bits(machInst, 7, 6);
2509800Snilay@cs.wisc.edu            align = bits(machInst, 5, 4);
2519800Snilay@cs.wisc.edu            if (align == 0) {
2529800Snilay@cs.wisc.edu                // @align wasn't specified, so alignment can be turned off.
25310608Sdam.sunwoo@arm.com                align = size | TLB::AllowUnaligned;
25410608Sdam.sunwoo@arm.com            } else {
25510608Sdam.sunwoo@arm.com                align = align + 2;
25610608Sdam.sunwoo@arm.com            }
25710608Sdam.sunwoo@arm.com            switch (width) {
2589800Snilay@cs.wisc.edu              case 1:
2598920Snilay@cs.wisc.edu                switch (type) {
2608920Snilay@cs.wisc.edu                  case 0x7: regs = 1;
2618920Snilay@cs.wisc.edu                    break;
2628920Snilay@cs.wisc.edu                  case 0xa: regs = 2;
2639357Sandreas.hansson@arm.com                    break;
2648920Snilay@cs.wisc.edu                  case 0x6: regs = 3;
2658920Snilay@cs.wisc.edu                    break;
2668920Snilay@cs.wisc.edu                  case 0x2: regs = 4;
2678920Snilay@cs.wisc.edu                    break;
2688920Snilay@cs.wisc.edu                  default:
2698920Snilay@cs.wisc.edu                    return new Unknown(machInst);
2708920Snilay@cs.wisc.edu                }
2718920Snilay@cs.wisc.edu                break;
2728920Snilay@cs.wisc.edu              case 2:
2738920Snilay@cs.wisc.edu                // Regs doesn't behave exactly as it does in the manual
2748920Snilay@cs.wisc.edu                // because they loop over regs registers twice and we break
2758920Snilay@cs.wisc.edu                // it down in the macroop.
2768920Snilay@cs.wisc.edu                switch (type) {
2778920Snilay@cs.wisc.edu                  case 0x8: regs = 2; inc = 1;
2788920Snilay@cs.wisc.edu                    break;
27911995Sgabeblack@google.com                  case 0x9: regs = 2; inc = 2;
2808920Snilay@cs.wisc.edu                    break;
2813395Shsul@eecs.umich.edu                  case 0x3: regs = 4; inc = 2;
2825361Srstrong@cs.ucsd.edu                    break;
2838920Snilay@cs.wisc.edu                  default:
2848920Snilay@cs.wisc.edu                    return new Unknown(machInst);
2858920Snilay@cs.wisc.edu                }
2869151Satgutier@umich.edu                break;
2879151Satgutier@umich.edu              case 3:
2889151Satgutier@umich.edu                regs = 3;
2899151Satgutier@umich.edu                switch (type) {
2909151Satgutier@umich.edu                  case 0x4: inc = 1;
2919151Satgutier@umich.edu                    break;
2929562Ssaidi@eecs.umich.edu                  case 0x5: inc = 2;;
2938920Snilay@cs.wisc.edu                    break;
2948920Snilay@cs.wisc.edu                  default:
2958920Snilay@cs.wisc.edu                    return new Unknown(machInst);
2968920Snilay@cs.wisc.edu                }
2978920Snilay@cs.wisc.edu                break;
2988920Snilay@cs.wisc.edu              case 4:
2998920Snilay@cs.wisc.edu                regs = 4;
3008920Snilay@cs.wisc.edu                switch (type) {
3018920Snilay@cs.wisc.edu                  case 0: inc = 1;
3028920Snilay@cs.wisc.edu                    break;
3038920Snilay@cs.wisc.edu                  case 1: inc = 2;
3048920Snilay@cs.wisc.edu                    break;
3058920Snilay@cs.wisc.edu                  default:
3068920Snilay@cs.wisc.edu                    return new Unknown(machInst);
3078920Snilay@cs.wisc.edu                }
3088920Snilay@cs.wisc.edu                break;
3098920Snilay@cs.wisc.edu            }
31010037SARM gem5 Developers        }
31110037SARM gem5 Developers
31210037SARM gem5 Developers        if (load) {
31310037SARM gem5 Developers            // Load instructions.
31410037SARM gem5 Developers            if (single) {
31510037SARM gem5 Developers                return new VldSingle(machInst, singleAll, width, rn, vd,
31610037SARM gem5 Developers                                     regs, inc, size, align, rm, lane);
31710037SARM gem5 Developers            } else {
3188920Snilay@cs.wisc.edu                return new VldMult(machInst, width, rn, vd,
3198920Snilay@cs.wisc.edu                                   regs, inc, size, align, rm);
3208920Snilay@cs.wisc.edu            }
3218920Snilay@cs.wisc.edu        } else {
3228920Snilay@cs.wisc.edu            // Store instructions.
3238920Snilay@cs.wisc.edu            if (single) {
3248920Snilay@cs.wisc.edu                if (singleAll) {
3258920Snilay@cs.wisc.edu                    return new Unknown(machInst);
32610803Sbrandon.potter@amd.com                } else {
32710803Sbrandon.potter@amd.com                    return new VstSingle(machInst, false, width, rn, vd,
3288920Snilay@cs.wisc.edu                                         regs, inc, size, align, rm, lane);
3298920Snilay@cs.wisc.edu                }
3308920Snilay@cs.wisc.edu            } else {
3318920Snilay@cs.wisc.edu                return new VstMult(machInst, width, rn, vd,
3328920Snilay@cs.wisc.edu                                   regs, inc, size, align, rm);
3338920Snilay@cs.wisc.edu            }
3348920Snilay@cs.wisc.edu        }
3358920Snilay@cs.wisc.edu        return new Unknown(machInst);
33613774Sandreas.sandberg@arm.com    }
33711688Sandreas.hansson@arm.com    '''
3388920Snilay@cs.wisc.edu
3398920Snilay@cs.wisc.edu    decoder_output += '''
3408920Snilay@cs.wisc.edu    static StaticInstPtr
3418920Snilay@cs.wisc.edu    decodeNeonThreeRegistersSameLength(ExtMachInst machInst)
3428920Snilay@cs.wisc.edu    {
3438920Snilay@cs.wisc.edu        const bool u = THUMB ? bits(machInst, 28) : bits(machInst, 24);
34410747SChris.Emmons@arm.com        const uint32_t a = bits(machInst, 11, 8);
34513731Sandreas.sandberg@arm.com        const bool b = bits(machInst, 4);
34613731Sandreas.sandberg@arm.com        const uint32_t c = bits(machInst, 21, 20);
34713731Sandreas.sandberg@arm.com        const IntRegIndex vd =
3488920Snilay@cs.wisc.edu            (IntRegIndex)(2 * (bits(machInst, 15, 12) |
3498920Snilay@cs.wisc.edu                               (bits(machInst, 22) << 4)));
3508920Snilay@cs.wisc.edu        const IntRegIndex vn =
3518920Snilay@cs.wisc.edu            (IntRegIndex)(2 * (bits(machInst, 19, 16) |
3528920Snilay@cs.wisc.edu                               (bits(machInst, 7) << 4)));
3538920Snilay@cs.wisc.edu        const IntRegIndex vm =
3548920Snilay@cs.wisc.edu            (IntRegIndex)(2 * (bits(machInst, 3, 0) |
3558920Snilay@cs.wisc.edu                               (bits(machInst, 5) << 4)));
35611238Sandreas.sandberg@arm.com        const unsigned size = bits(machInst, 21, 20);
35711238Sandreas.sandberg@arm.com        const bool q = bits(machInst, 6);
35811238Sandreas.sandberg@arm.com        if (q && ((vd & 0x1) || (vn & 0x1) || (vm & 0x1)))
3598920Snilay@cs.wisc.edu            return new Unknown(machInst);
36011238Sandreas.sandberg@arm.com        switch (a) {
36111238Sandreas.sandberg@arm.com          case 0x0:
3629539Satgutier@umich.edu            if (b) {
3639539Satgutier@umich.edu                if (u) {
3649539Satgutier@umich.edu                    return decodeNeonUThreeReg<VqaddUD, VqaddUQ>(
36512079Sgedare@rtems.org                            q, size, machInst, vd, vn, vm);
36612079Sgedare@rtems.org                } else {
3679935Sdam.sunwoo@arm.com                    return decodeNeonSThreeReg<VqaddSD, VqaddSQ>(
3689935Sdam.sunwoo@arm.com                            q, size, machInst, vd, vn, vm);
3699935Sdam.sunwoo@arm.com                }
3709935Sdam.sunwoo@arm.com            } else {
3718920Snilay@cs.wisc.edu                if (size == 3)
3728920Snilay@cs.wisc.edu                    return new Unknown(machInst);
3738920Snilay@cs.wisc.edu                return decodeNeonUSThreeReg<VhaddD, VhaddQ>(
3748920Snilay@cs.wisc.edu                        q, u, size, machInst, vd, vn, vm);
3758920Snilay@cs.wisc.edu            }
3768920Snilay@cs.wisc.edu          case 0x1:
3778920Snilay@cs.wisc.edu            if (!b) {
3788920Snilay@cs.wisc.edu                return decodeNeonUSThreeReg<VrhaddD, VrhaddQ>(
3798920Snilay@cs.wisc.edu                        q, u, size, machInst, vd, vn, vm);
3808920Snilay@cs.wisc.edu            } else {
3818920Snilay@cs.wisc.edu                if (u) {
3828920Snilay@cs.wisc.edu                    switch (c) {
3838956Sjayneel@cs.wisc.edu                      case 0:
3848956Sjayneel@cs.wisc.edu                        if (q) {
3858956Sjayneel@cs.wisc.edu                            return new VeorQ<uint64_t>(machInst, vd, vn, vm);
3868956Sjayneel@cs.wisc.edu                        } else {
38710697SCurtis.Dunham@arm.com                            return new VeorD<uint64_t>(machInst, vd, vn, vm);
38810697SCurtis.Dunham@arm.com                        }
38910594Sgabeblack@google.com                      case 1:
39010594Sgabeblack@google.com                        if (q) {
39110594Sgabeblack@google.com                            return new VbslQ<uint64_t>(machInst, vd, vn, vm);
39210594Sgabeblack@google.com                        } else {
39310594Sgabeblack@google.com                            return new VbslD<uint64_t>(machInst, vd, vn, vm);
39410594Sgabeblack@google.com                        }
39510594Sgabeblack@google.com                      case 2:
39610594Sgabeblack@google.com                        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