// Copyright (c) 2012-2013 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Giacomo Gabrielli // Mbou Eyole output header {{ namespace Aarch64 { // AdvSIMD three same template StaticInstPtr decodeNeon3Same(ExtMachInst machInst); // AdvSIMD three different inline StaticInstPtr decodeNeon3Diff(ExtMachInst machInst); // AdvSIMD two-reg misc inline StaticInstPtr decodeNeon2RegMisc(ExtMachInst machInst); // AdvSIMD across lanes inline StaticInstPtr decodeNeonAcrossLanes(ExtMachInst machInst); // AdvSIMD copy inline StaticInstPtr decodeNeonCopy(ExtMachInst machInst); // AdvSIMD vector x indexed element template StaticInstPtr decodeNeonIndexedElem(ExtMachInst machInst); // AdvSIMD modified immediate inline StaticInstPtr decodeNeonModImm(ExtMachInst machInst); // AdvSIMD shift by immediate inline StaticInstPtr decodeNeonShiftByImm(ExtMachInst machInst); // AdvSIMD TBL/TBX inline StaticInstPtr decodeNeonTblTbx(ExtMachInst machInst); // AdvSIMD ZIP/UZP/TRN inline StaticInstPtr decodeNeonZipUzpTrn(ExtMachInst machInst); // AdvSIMD EXT inline StaticInstPtr decodeNeonExt(ExtMachInst machInst); // AdvSIMD scalar three same inline StaticInstPtr decodeNeonSc3Same(ExtMachInst machInst); // AdvSIMD scalar three different inline StaticInstPtr decodeNeonSc3Diff(ExtMachInst machInst); // AdvSIMD scalar two-reg misc inline StaticInstPtr decodeNeonSc2RegMisc(ExtMachInst machInst); // AdvSIMD scalar pairwise inline StaticInstPtr decodeNeonScPwise(ExtMachInst machInst); // AdvSIMD scalar copy inline StaticInstPtr decodeNeonScCopy(ExtMachInst machInst); // AdvSIMD scalar x indexed element inline StaticInstPtr decodeNeonScIndexedElem(ExtMachInst machInst); // AdvSIMD scalar shift by immediate inline StaticInstPtr decodeNeonScShiftByImm(ExtMachInst machInst); // AdvSIMD load/store inline StaticInstPtr decodeNeonMem(ExtMachInst machInst); } }}; output decoder {{ namespace Aarch64 { template StaticInstPtr decodeNeon3Same(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 15, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); uint8_t size_q = (size << 1) | q; uint8_t sz_q = size_q & 0x3; switch (opcode) { case 0x00: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x01: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x02: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x03: switch (size) { case 0x0: if (u) { if (q) return new EorQX(machInst, vd, vn, vm); else return new EorDX(machInst, vd, vn, vm); } else { if (q) return new AndQX(machInst, vd, vn, vm); else return new AndDX(machInst, vd, vn, vm); } case 0x1: if (u) { if (q) return new BslQX(machInst, vd, vn, vm); else return new BslDX(machInst, vd, vn, vm); } else { if (q) return new BicQX(machInst, vd, vn, vm); else return new BicDX(machInst, vd, vn, vm); } case 0x2: if (u) { if (q) return new BitQX(machInst, vd, vn, vm); else return new BitDX(machInst, vd, vn, vm); } else { if (q) return new OrrQX(machInst, vd, vn, vm); else return new OrrDX(machInst, vd, vn, vm); } case 0x3: if (u) { if (q) return new BifQX(machInst, vd, vn, vm); else return new BifDX(machInst, vd, vn, vm); } else { if (q) return new OrnQX(machInst, vd, vn, vm); else return new OrnDX(machInst, vd, vn, vm); } default: M5_UNREACHABLE; } case 0x04: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x05: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x06: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x07: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x08: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x09: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x0a: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x0b: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeXReg( q, size, machInst, vd, vn, vm); case 0x0c: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x0d: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x0e: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x0f: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x10: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x11: if (size_q == 0x6) return new Unknown64(machInst); if (u) return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); else return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x12: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); case 0x13: if (size == 0x3 || (size != 0x0 && bits(machInst, 29))) return new Unknown64(machInst); if (u) { if (q) return new PmulQX(machInst, vd, vn, vm); else return new PmulDX(machInst, vd, vn, vm); } else { return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); } case 0x14: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x15: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x16: if (size == 0x3 || size == 0x0) return new Unknown64(machInst); if (u) { if (q) return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } else { if (q) return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } case 0x17: if (u || size_q == 0x6) return new Unknown64(machInst); else return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x18: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } case 0x19: if (size < 0x2) { if (u || sz_q == 0x2) return new Unknown64(machInst); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u || sz_q == 0x2) return new Unknown64(machInst); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } case 0x1a: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } case 0x1b: if (size < 0x2 && sz_q != 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { return new Unknown64(machInst); } case 0x1c: if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return new Unknown64(machInst); } case 0x1d: if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return new Unknown64(machInst); } else { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return new Unknown64(machInst); } case 0x1e: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } case 0x1f: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) { if (u) return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } else { if (u) return new Unknown64(machInst); else return decodeNeonUThreeFpReg( q, size & 0x1, machInst, vd, vn, vm); } default: return new Unknown64(machInst); } } StaticInstPtr decodeNeon3Diff(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 15, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); switch (opcode) { case 0x0: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x1: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x2: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x3: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x4: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); case 0x5: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x6: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); case 0x7: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x8: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0x9: if (u || (size == 0x0 || size == 0x3)) { return new Unknown64(machInst); } else { if (q) { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } else { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } } case 0xa: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0xb: if (u || (size == 0x0 || size == 0x3)) { return new Unknown64(machInst); } else { if (q) { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } else { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } } case 0xc: if (size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeSReg( q, size, machInst, vd, vn, vm); else return decodeNeonSThreeSReg( q, size, machInst, vd, vn, vm); case 0xd: if (u || (size == 0x0 || size == 0x3)) { return new Unknown64(machInst); } else { if (q) { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } else { return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); } } case 0xe: if (u || size != 0) { return new Unknown64(machInst); } else { if (q) return new Pmull2X(machInst, vd, vn, vm); else return new PmullX(machInst, vd, vn, vm); } default: return new Unknown64(machInst); } } StaticInstPtr decodeNeon2RegMisc(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 16, 12); IntRegIndex vd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5); uint8_t size_q = (size << 1) | q; uint8_t sz_q = size_q & 0x3; uint8_t op = (uint8_t)((bits(machInst, 12) << 1) | bits(machInst, 29)); uint8_t switchVal = opcode | ((u ? 1 : 0) << 5); switch (switchVal) { case 0x00: if (op + size >= 3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x01: if (op + size >= 3) return new Unknown64(machInst); if (q) return new Rev16QX(machInst, vd, vn); else return new Rev16DX(machInst, vd, vn); case 0x02: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x03: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonUTwoMiscXReg( q, size, machInst, vd, vn); case 0x04: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x05: if (size != 0x0) return new Unknown64(machInst); if (q) return new CntQX(machInst, vd, vn); else return new CntDX(machInst, vd, vn); case 0x06: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x07: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x08: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x09: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x0a: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x0b: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x0c: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x0d: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x0e: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x0f: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x12: if (size == 0x3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x14: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x16: if (size > 0x1) return new Unknown64(machInst); if (q) { if (size) return new Fcvtn2X(machInst, vd, vn); else return new Fcvtn2X(machInst, vd, vn); } else { if (size) return new FcvtnX(machInst, vd, vn); else return new FcvtnX(machInst, vd, vn); } case 0x17: if (size > 0x1) return new Unknown64(machInst); if (q) { if (size) return new Fcvtl2X(machInst, vd, vn); else return new Fcvtl2X(machInst, vd, vn); } else { if (size) return new FcvtlX(machInst, vd, vn); else return new FcvtlX(machInst, vd, vn); } case 0x18: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x19: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x1a: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x1b: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x1c: if (size < 0x2) { if (sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); } else { if (size & 0x1) return new Unknown64(machInst); if (q) return new UrecpeQX(machInst, vd, vn); else return new UrecpeDX(machInst, vd, vn); } case 0x1d: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) { if (q) { if (size & 0x1) return new ScvtfIntDQX(machInst, vd, vn); else return new ScvtfIntSQX(machInst, vd, vn); } else { if (size & 0x1) return new Unknown(machInst); else return new ScvtfIntDX(machInst, vd, vn); } } else { return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); } case 0x20: if (op + size >= 3) return new Unknown64(machInst); if (q) { if (size & 0x1) return new Rev32QX(machInst, vd, vn); else return new Rev32QX(machInst, vd, vn); } else { if (size & 0x1) return new Rev32DX(machInst, vd, vn); else return new Rev32DX(machInst, vd, vn); } case 0x22: if (size == 0x3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x23: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonUTwoMiscXReg( q, size, machInst, vd, vn); return new Unknown64(machInst); case 0x24: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x25: if (size == 0x0) { if (q) return new MvnQX(machInst, vd, vn); else return new MvnDX(machInst, vd, vn); } else if (size == 0x1) { if (q) return new RbitQX(machInst, vd, vn); else return new RbitDX(machInst, vd, vn); } else { return new Unknown64(machInst); } case 0x26: if (size == 0x3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x27: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x28: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x29: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x2b: if (size_q == 0x6) return new Unknown64(machInst); return decodeNeonSTwoMiscXReg( q, size, machInst, vd, vn); case 0x2c: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x2d: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x2f: if (size < 0x2 || size_q == 0x6) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x32: if (size == 0x3) return new Unknown64(machInst); return decodeNeonSTwoMiscSReg( q, size, machInst, vd, vn); case 0x33: if (size == 0x3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x34: if (size == 0x3) return new Unknown64(machInst); return decodeNeonUTwoMiscSReg( q, size, machInst, vd, vn); case 0x36: if (size != 0x1) return new Unknown64(machInst); if (q) return new Fcvtxn2X(machInst, vd, vn); else return new FcvtxnX(machInst, vd, vn); case 0x38: if (size > 0x1 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x39: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x3a: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x3b: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x3c: if (size < 0x2) { return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); } else if (size == 0x2) { if (q) return new UrsqrteQX(machInst, vd, vn); else return new UrsqrteDX(machInst, vd, vn); } else { return new Unknown64(machInst); } case 0x3d: if (sz_q == 0x2) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); case 0x3f: if (size < 0x2 || sz_q == 0x2) return new Unknown64(machInst); return decodeNeonUTwoMiscFpReg( q, size & 0x1, machInst, vd, vn); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonAcrossLanes(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 16, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t size_q = (size << 1) | q; uint8_t sz_q = size_q & 0x3; uint8_t switchVal = opcode | ((u ? 1 : 0) << 5); switch (switchVal) { case 0x03: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonSAcrossLanesLongReg( q, size, machInst, vd, vn); case 0x0a: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonSAcrossLanesReg( q, size, machInst, vd, vn); case 0x1a: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonSAcrossLanesReg( q, size, machInst, vd, vn); case 0x1b: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonUAcrossLanesReg( q, size, machInst, vd, vn); case 0x23: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonUAcrossLanesLongReg( q, size, machInst, vd, vn); case 0x2a: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonUAcrossLanesReg( q, size, machInst, vd, vn); case 0x2c: if (sz_q != 0x1) return new Unknown64(machInst); if (size < 0x2) { if (q) return new FmaxnmvQX(machInst, vd, vn); else return new Unknown64(machInst); } else { if (q) return new FminnmvQX(machInst, vd, vn); else return new Unknown64(machInst); } case 0x2f: if (sz_q != 0x1) return new Unknown64(machInst); if (size < 0x2) { if (q) return new FmaxvQX(machInst, vd, vn); else return new Unknown64(machInst); } else { if (q) return new FminvQX(machInst, vd, vn); else return new Unknown64(machInst); } case 0x3a: if (size_q == 0x4 || size == 0x3) return new Unknown64(machInst); return decodeNeonUAcrossLanesReg( q, size, machInst, vd, vn); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonCopy(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t op = bits(machInst, 29); uint8_t imm5 = bits(machInst, 20, 16); uint8_t imm4 = bits(machInst, 14, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t imm5_pos = findLsbSet(imm5); uint8_t index1 = 0, index2 = 0; if (op) { if (!q || (imm4 & mask(imm5_pos))) return new Unknown64(machInst); index1 = bits(imm5, 4, imm5_pos + 1); // dst index2 = bits(imm4, 3, imm5_pos); // src switch (imm5_pos) { case 0: return new InsElemX(machInst, vd, vn, index1, index2); case 1: return new InsElemX(machInst, vd, vn, index1, index2); case 2: return new InsElemX(machInst, vd, vn, index1, index2); case 3: return new InsElemX(machInst, vd, vn, index1, index2); default: return new Unknown64(machInst); } } switch (imm4) { case 0x0: index1 = bits(imm5, 4, imm5_pos + 1); switch (imm5_pos) { case 0: if (q) return new DupElemQX(machInst, vd, vn, index1); else return new DupElemDX(machInst, vd, vn, index1); case 1: if (q) return new DupElemQX(machInst, vd, vn, index1); else return new DupElemDX(machInst, vd, vn, index1); case 2: if (q) return new DupElemQX(machInst, vd, vn, index1); else return new DupElemDX(machInst, vd, vn, index1); case 3: if (q) return new DupElemQX(machInst, vd, vn, index1); else return new Unknown64(machInst); default: return new Unknown64(machInst); } case 0x1: switch (imm5) { case 0x1: if (q) return new DupGprWQX(machInst, vd, vn); else return new DupGprWDX(machInst, vd, vn); case 0x2: if (q) return new DupGprWQX(machInst, vd, vn); else return new DupGprWDX(machInst, vd, vn); case 0x4: if (q) return new DupGprWQX(machInst, vd, vn); else return new DupGprWDX(machInst, vd, vn); case 0x8: if (q) return new DupGprXQX(machInst, vd, vn); else return new Unknown64(machInst); default: return new Unknown64(machInst); } case 0x3: index1 = imm5 >> (imm5_pos + 1); switch (imm5_pos) { case 0: return new InsGprWX(machInst, vd, vn, index1); case 1: return new InsGprWX(machInst, vd, vn, index1); case 2: return new InsGprWX(machInst, vd, vn, index1); case 3: return new InsGprXX(machInst, vd, vn, index1); default: return new Unknown64(machInst); } case 0x5: index1 = bits(imm5, 4, imm5_pos + 1); switch (imm5_pos) { case 0: if (q) return new SmovXX(machInst, vd, vn, index1); else return new SmovWX(machInst, vd, vn, index1); case 1: if (q) return new SmovXX(machInst, vd, vn, index1); else return new SmovWX(machInst, vd, vn, index1); case 2: if (q) return new SmovXX(machInst, vd, vn, index1); else return new Unknown64(machInst); default: return new Unknown64(machInst); } case 0x7: index1 = imm5 >> (imm5_pos + 1); if ((q && imm5_pos != 3) || (!q && imm5_pos >= 3)) return new Unknown64(machInst); switch (imm5_pos) { case 0: return new UmovWX(machInst, vd, vn, index1); case 1: return new UmovWX(machInst, vd, vn, index1); case 2: return new UmovWX(machInst, vd, vn, index1); case 3: return new UmovXX(machInst, vd, vn, index1); default: return new Unknown64(machInst); } default: return new Unknown64(machInst); } } template StaticInstPtr decodeNeonIndexedElem(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t L = bits(machInst, 21); uint8_t M = bits(machInst, 20); uint8_t opcode = bits(machInst, 15, 12); uint8_t H = bits(machInst, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm_bf = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); uint8_t index = 0; uint8_t index_fp = 0; uint8_t vmh = 0; uint8_t sz = size & 0x1; uint8_t sz_q = (sz << 1) | bits(machInst, 30); uint8_t sz_L = (sz << 1) | L; // Index and 2nd register operand for integer instructions if (size == 0x1) { index = (H << 2) | (L << 1) | M; // vmh = 0; } else if (size == 0x2) { index = (H << 1) | L; vmh = M; } IntRegIndex vm = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf); // Index and 2nd register operand for FP instructions vmh = M; if ((size & 0x1) == 0) { index_fp = (H << 1) | L; } else if (L == 0) { index_fp = H; } IntRegIndex vm_fp = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf); switch (opcode) { case 0x0: if (!u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x1: if (!u && size >= 2 && sz_q != 0x2 && sz_L != 0x3) return decodeNeonUThreeImmFpReg( q, sz, machInst, vd, vn, vm_fp, index_fp); else return new Unknown64(machInst); case 0x2: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x3: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x4: if (u && !(size == 0x0 || size == 0x3)) return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); else return new Unknown64(machInst); case 0x5: if (!u && size >= 0x2 && sz_L != 0x3 && sz_q != 0x2) return decodeNeonUThreeImmFpReg( q, sz, machInst, vd, vn, vm_fp, index_fp); else return new Unknown64(machInst); case 0x6: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x7: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x8: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0x9: if (size >= 2 && sz_q != 0x2 && sz_L != 0x3) { if (u) return decodeNeonUThreeImmFpReg( q, sz, machInst, vd, vn, vm_fp, index_fp); else return decodeNeonUThreeImmFpReg( q, sz, machInst, vd, vn, vm_fp, index_fp); } else { return new Unknown64(machInst); } case 0xa: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0xb: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0xc: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); case 0xd: if (u || (size == 0x0 || size == 0x3)) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( q, size, machInst, vd, vn, vm, index); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonModImm(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t op = bits(machInst, 29); uint8_t abcdefgh = (bits(machInst, 18, 16) << 5) | bits(machInst, 9, 5); uint8_t cmode = bits(machInst, 15, 12); uint8_t o2 = bits(machInst, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); if (o2 == 0x1 || (op == 0x1 && cmode == 0xf && !q)) return new Unknown64(machInst); bool immValid = true; const uint64_t bigImm = simd_modified_imm(op, cmode, abcdefgh, immValid, true /* isAarch64 */); if (!immValid) { return new Unknown(machInst); } if (op) { if (bits(cmode, 3) == 0) { if (bits(cmode, 0) == 0) { if (q) return new MvniQX(machInst, vd, bigImm); else return new MvniDX(machInst, vd, bigImm); } else { if (q) return new BicImmQX(machInst, vd, bigImm); else return new BicImmDX(machInst, vd, bigImm); } } else { if (bits(cmode, 2) == 1) { switch (bits(cmode, 1, 0)) { case 0: case 1: if (q) return new MvniQX(machInst, vd, bigImm); else return new MvniDX(machInst, vd, bigImm); case 2: if (q) return new MoviQX(machInst, vd, bigImm); else return new MoviDX(machInst, vd, bigImm); case 3: if (q) return new FmovQX(machInst, vd, bigImm); else return new MoviDX(machInst, vd, bigImm); } } else { if (bits(cmode, 0) == 0) { if (q) return new MvniQX(machInst, vd, bigImm); else return new MvniDX(machInst, vd, bigImm); } else { if (q) return new BicImmQX(machInst, vd, bigImm); else return new BicImmDX(machInst, vd, bigImm); } } } } else { if (bits(cmode, 3) == 0) { if (bits(cmode, 0) == 0) { if (q) return new MoviQX(machInst, vd, bigImm); else return new MoviDX(machInst, vd, bigImm); } else { if (q) return new OrrImmQX(machInst, vd, bigImm); else return new OrrImmDX(machInst, vd, bigImm); } } else { if (bits(cmode, 2) == 1) { if (bits(cmode, 1, 0) == 0x3) { if (q) return new FmovQX(machInst, vd, bigImm); else return new FmovDX(machInst, vd, bigImm); } else { if (q) return new MoviQX(machInst, vd, bigImm); else return new MoviDX(machInst, vd, bigImm); } } else { if (bits(cmode, 0) == 0) { if (q) return new MoviQX(machInst, vd, bigImm); else return new MoviDX(machInst, vd, bigImm); } else { if (q) return new OrrImmQX(machInst, vd, bigImm); else return new OrrImmDX(machInst, vd, bigImm); } } } } return new Unknown(machInst); } StaticInstPtr decodeNeonShiftByImm(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t u = bits(machInst, 29); uint8_t immh = bits(machInst, 22, 19); uint8_t immb = bits(machInst, 18, 16); uint8_t opcode = bits(machInst, 15, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t immh3 = bits(machInst, 22); uint8_t immh3_q = (immh3 << 1) | q; uint8_t op_u = (bits(machInst, 12) << 1) | u; uint8_t size = findMsbSet(immh); int shiftAmt = 0; switch (opcode) { case 0x00: if (immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x02: if (immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x04: if (immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x06: if (immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x08: if (u && !(immh3_q == 0x2)) { shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); } else { return new Unknown64(machInst); } case 0x0a: if (immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = ((immh << 3) | immb) - (8 << size); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x0c: if (u && !(immh3_q == 0x2 || op_u == 0x0)) { shiftAmt = ((immh << 3) | immb) - (8 << size); return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); } else { return new Unknown64(machInst); } case 0x0e: if (immh3_q == 0x2 || op_u == 0x0) return new Unknown64(machInst); shiftAmt = ((immh << 3) | immb) - (8 << size); if (u) return decodeNeonUTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftXReg( q, size, machInst, vd, vn, shiftAmt); case 0x10: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonSTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonUTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); case 0x11: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonSTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonUTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); case 0x12: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); case 0x13: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); case 0x14: if (immh3) return new Unknown64(machInst); shiftAmt = ((immh << 3) | immb) - (8 << size); if (u) return decodeNeonUTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftSReg( q, size, machInst, vd, vn, shiftAmt); case 0x1c: if (immh < 0x4 || immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) { return decodeNeonUTwoShiftFpReg( q, size & 0x1, machInst, vd, vn, shiftAmt); } else { if (q) { if (size & 0x1) return new ScvtfFixedDQX(machInst, vd, vn, shiftAmt); else return new ScvtfFixedSQX(machInst, vd, vn, shiftAmt); } else { if (size & 0x1) return new Unknown(machInst); else return new ScvtfFixedDX(machInst, vd, vn, shiftAmt); } } case 0x1f: if (immh < 0x4 || immh3_q == 0x2) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftFpReg( q, size & 0x1, machInst, vd, vn, shiftAmt); else return decodeNeonUTwoShiftFpReg( q, size & 0x1, machInst, vd, vn, shiftAmt); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonTblTbx(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); uint8_t switchVal = bits(machInst, 14, 12); switch (switchVal) { case 0x0: if (q) return new Tbl1QX(machInst, vd, vn, vm); else return new Tbl1DX(machInst, vd, vn, vm); case 0x1: if (q) return new Tbx1QX(machInst, vd, vn, vm); else return new Tbx1DX(machInst, vd, vn, vm); case 0x2: if (q) return new Tbl2QX(machInst, vd, vn, vm); else return new Tbl2DX(machInst, vd, vn, vm); case 0x3: if (q) return new Tbx2QX(machInst, vd, vn, vm); else return new Tbx2DX(machInst, vd, vn, vm); case 0x4: if (q) return new Tbl3QX(machInst, vd, vn, vm); else return new Tbl3DX(machInst, vd, vn, vm); case 0x5: if (q) return new Tbx3QX(machInst, vd, vn, vm); else return new Tbx3DX(machInst, vd, vn, vm); case 0x6: if (q) return new Tbl4QX(machInst, vd, vn, vm); else return new Tbl4DX(machInst, vd, vn, vm); case 0x7: if (q) return new Tbx4QX(machInst, vd, vn, vm); else return new Tbx4DX(machInst, vd, vn, vm); default: return new Unknown64(machInst); } return new Unknown64(machInst); } StaticInstPtr decodeNeonZipUzpTrn(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 14, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); switch (opcode) { case 0x1: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x2: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x3: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x5: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x6: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); case 0x7: return decodeNeonUThreeXReg( q, size, machInst, vd, vn, vm); default: return new Unknown64(machInst); } return new Unknown64(machInst); } StaticInstPtr decodeNeonExt(ExtMachInst machInst) { uint8_t q = bits(machInst, 30); uint8_t op2 = bits(machInst, 23, 22); uint8_t imm4 = bits(machInst, 14, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); if (op2 != 0 || (q == 0x0 && bits(imm4, 3) == 0x1)) return new Unknown64(machInst); uint8_t index = q ? imm4 : imm4 & 0x7; if (q) { return new ExtQX(machInst, vd, vn, vm, index); } else { return new ExtDX(machInst, vd, vn, vm, index); } } StaticInstPtr decodeNeonSc3Same(ExtMachInst machInst) { uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 15, 11); uint8_t s = bits(machInst, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); switch (opcode) { case 0x01: if (u) return decodeNeonUThreeUReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeUReg( size, machInst, vd, vn, vm); case 0x05: if (u) return decodeNeonUThreeUReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeUReg( size, machInst, vd, vn, vm); case 0x06: if (size != 0x3) return new Unknown64(machInst); if (u) return new CmhiDX(machInst, vd, vn, vm); else return new CmgtDX(machInst, vd, vn, vm); case 0x07: if (size != 0x3) return new Unknown64(machInst); if (u) return new CmhsDX(machInst, vd, vn, vm); else return new CmgeDX(machInst, vd, vn, vm); case 0x08: if (!s && size != 0x3) return new Unknown64(machInst); if (u) return new UshlDX(machInst, vd, vn, vm); else return new SshlDX(machInst, vd, vn, vm); case 0x09: if (!s && size != 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeUReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeUReg( size, machInst, vd, vn, vm); case 0x0a: if (!s && size != 0x3) return new Unknown64(machInst); if (u) return new UrshlDX(machInst, vd, vn, vm); else return new SrshlDX(machInst, vd, vn, vm); case 0x0b: if (!s && size != 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeUReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeUReg( size, machInst, vd, vn, vm); case 0x10: if (size != 0x3) return new Unknown64(machInst); if (u) return new SubDX(machInst, vd, vn, vm); else return new AddDX(machInst, vd, vn, vm); case 0x11: if (size != 0x3) return new Unknown64(machInst); if (u) return new CmeqDX(machInst, vd, vn, vm); else return new CmtstDX(machInst, vd, vn, vm); case 0x16: if (size == 0x3 || size == 0x0) return new Unknown64(machInst); if (u) return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); else return decodeNeonSThreeHAndWReg( size, machInst, vd, vn, vm); case 0x1a: if (!u || size < 0x2) return new Unknown64(machInst); else return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); case 0x1b: if (u || size > 0x1) return new Unknown64(machInst); else return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); case 0x1c: if (size < 0x2) { if (u) return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); } else { if (u) return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); else return new Unknown64(machInst); } case 0x1d: if (!u) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); case 0x1f: if (u) return new Unknown64(machInst); if (size < 0x2) return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); else return decodeNeonUThreeScFpReg( size & 0x1, machInst, vd, vn, vm); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonSc3Diff(ExtMachInst machInst) { if (bits(machInst, 29)) return new Unknown64(machInst); uint8_t size = bits(machInst, 23, 22); if (size == 0x0 || size == 0x3) return new Unknown64(machInst); uint8_t opcode = bits(machInst, 15, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); switch (opcode) { case 0x9: return decodeNeonSThreeHAndWReg(size, machInst, vd, vn, vm); case 0xb: return decodeNeonSThreeHAndWReg(size, machInst, vd, vn, vm); case 0xd: return decodeNeonSThreeHAndWReg(size, machInst, vd, vn, vm); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonSc2RegMisc(ExtMachInst machInst) { uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 16, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t switchVal = opcode | ((u ? 1 : 0) << 5); switch (switchVal) { case 0x03: return decodeNeonUTwoMiscUReg(size, machInst, vd, vn); case 0x07: return decodeNeonSTwoMiscUReg(size, machInst, vd, vn); case 0x08: if (size != 0x3) return new Unknown64(machInst); else return new CmgtZeroDX(machInst, vd, vn); case 0x09: if (size != 0x3) return new Unknown64(machInst); else return new CmeqZeroDX(machInst, vd, vn); case 0x0a: if (size != 0x3) return new Unknown64(machInst); else return new CmltZeroDX(machInst, vd, vn); case 0x0b: if (size != 0x3) return new Unknown64(machInst); else return new AbsDX(machInst, vd, vn); case 0x0c: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x0d: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x0e: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x14: switch (size) { case 0x0: return new SqxtnScX(machInst, vd, vn); case 0x1: return new SqxtnScX(machInst, vd, vn); case 0x2: return new SqxtnScX(machInst, vd, vn); case 0x3: return new Unknown64(machInst); default: M5_UNREACHABLE; } case 0x1a: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x1b: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x1c: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return new Unknown64(machInst); case 0x1d: if (size < 0x2) { if (size & 0x1) return new ScvtfIntScDX(machInst, vd, vn); else return new ScvtfIntScSX(machInst, vd, vn); } else { return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); } case 0x1f: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x23: return decodeNeonUTwoMiscUReg(size, machInst, vd, vn); case 0x27: return decodeNeonSTwoMiscUReg(size, machInst, vd, vn); case 0x28: if (size != 0x3) return new Unknown64(machInst); else return new CmgeZeroDX(machInst, vd, vn); case 0x29: if (size != 0x3) return new Unknown64(machInst); else return new CmleZeroDX(machInst, vd, vn); case 0x2b: if (size != 0x3) return new Unknown64(machInst); else return new NegDX(machInst, vd, vn); case 0x2c: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x2d: if (size < 0x2) return new Unknown64(machInst); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x32: switch (size) { case 0x0: return new SqxtunScX(machInst, vd, vn); case 0x1: return new SqxtunScX(machInst, vd, vn); case 0x2: return new SqxtunScX(machInst, vd, vn); case 0x3: return new Unknown64(machInst); default: M5_UNREACHABLE; } case 0x34: switch (size) { case 0x0: return new UqxtnScX(machInst, vd, vn); case 0x1: return new UqxtnScX(machInst, vd, vn); case 0x2: return new UqxtnScX(machInst, vd, vn); case 0x3: return new Unknown64(machInst); default: M5_UNREACHABLE; } case 0x36: if (size != 0x1) { return new Unknown64(machInst); } else { return new FcvtxnScX(machInst, vd, vn); } case 0x3a: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x3b: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); case 0x3c: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return new Unknown64(machInst); case 0x3d: if (size < 0x2) return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); else return decodeNeonUTwoMiscScFpReg( size & 0x1, machInst, vd, vn); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonScPwise(ExtMachInst machInst) { uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t opcode = bits(machInst, 16, 12); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); if (!u) { if (opcode == 0x1b && size == 0x3) return new AddpScQX(machInst, vd, vn); else return new Unknown64(machInst); } uint8_t switchVal = (opcode << 0) | (size << 5); switch (switchVal) { case 0x0c: case 0x2c: return decodeNeonUTwoMiscPwiseScFpReg( size & 0x1, machInst, vd, vn); case 0x0d: case 0x2d: return decodeNeonUTwoMiscPwiseScFpReg( size & 0x1, machInst, vd, vn); case 0x0f: case 0x2f: return decodeNeonUTwoMiscPwiseScFpReg( size & 0x1, machInst, vd, vn); case 0x4c: case 0x6c: return decodeNeonUTwoMiscPwiseScFpReg( size & 0x1, machInst, vd, vn); case 0x4f: case 0x6f: return decodeNeonUTwoMiscPwiseScFpReg( size & 0x1, machInst, vd, vn); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonScCopy(ExtMachInst machInst) { if (bits(machInst, 14, 11) != 0 || bits(machInst, 29)) return new Unknown64(machInst); uint8_t imm5 = bits(machInst, 20, 16); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t size = findLsbSet(imm5); uint8_t index = bits(imm5, 4, size + 1); return decodeNeonUTwoShiftUReg( size, machInst, vd, vn, index); } StaticInstPtr decodeNeonScIndexedElem(ExtMachInst machInst) { uint8_t u = bits(machInst, 29); uint8_t size = bits(machInst, 23, 22); uint8_t L = bits(machInst, 21); uint8_t M = bits(machInst, 20); uint8_t opcode = bits(machInst, 15, 12); uint8_t H = bits(machInst, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex vm_bf = (IntRegIndex) (uint8_t) bits(machInst, 19, 16); uint8_t index = 0; uint8_t index_fp = 0; uint8_t vmh = 0; uint8_t sz_L = bits(machInst, 22, 21); // Index and 2nd register operand for integer instructions if (size == 0x1) { index = (H << 2) | (L << 1) | M; // vmh = 0; } else if (size == 0x2) { index = (H << 1) | L; vmh = M; } else if (size == 0x3) { index = H; vmh = M; } IntRegIndex vm = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf); // Index and 2nd register operand for FP instructions vmh = M; if ((size & 0x1) == 0) { index_fp = (H << 1) | L; } else if (L == 0) { index_fp = H; } IntRegIndex vm_fp = (IntRegIndex) (uint8_t) (vmh << 4 | vm_bf); if (u && opcode != 9) return new Unknown64(machInst); switch (opcode) { case 0x1: if (size < 2 || sz_L == 0x3) return new Unknown64(machInst); else return decodeNeonUThreeImmScFpReg( size & 0x1, machInst, vd, vn, vm_fp, index_fp); case 0x3: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( size, machInst, vd, vn, vm, index); case 0x5: if (size < 2 || sz_L == 0x3) return new Unknown64(machInst); else return decodeNeonUThreeImmScFpReg( size & 0x1, machInst, vd, vn, vm_fp, index_fp); case 0x7: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( size, machInst, vd, vn, vm, index); case 0x9: if (size < 2 || sz_L == 0x3) return new Unknown64(machInst); if (u) return decodeNeonUThreeImmScFpReg( size & 0x1, machInst, vd, vn, vm_fp, index_fp); else return decodeNeonUThreeImmScFpReg( size & 0x1, machInst, vd, vn, vm_fp, index_fp); case 0xb: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( size, machInst, vd, vn, vm, index); case 0xc: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( size, machInst, vd, vn, vm, index); case 0xd: if (size == 0x0 || size == 0x3) return new Unknown64(machInst); else return decodeNeonSThreeImmHAndWReg( size, machInst, vd, vn, vm, index); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonScShiftByImm(ExtMachInst machInst) { bool u = bits(machInst, 29); uint8_t immh = bits(machInst, 22, 19); uint8_t immb = bits(machInst, 18, 16); uint8_t opcode = bits(machInst, 15, 11); IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex vn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); uint8_t immh3 = bits(machInst, 22); uint8_t size = findMsbSet(immh); int shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (immh == 0x0) return new Unknown64(machInst); switch (opcode) { case 0x00: if (!immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return new UshrDX(machInst, vd, vn, shiftAmt); else return new SshrDX(machInst, vd, vn, shiftAmt); case 0x02: if (!immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return new UsraDX(machInst, vd, vn, shiftAmt); else return new SsraDX(machInst, vd, vn, shiftAmt); case 0x04: if (!immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return new UrshrDX(machInst, vd, vn, shiftAmt); else return new SrshrDX(machInst, vd, vn, shiftAmt); case 0x06: if (!immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return new UrsraDX(machInst, vd, vn, shiftAmt); else return new SrsraDX(machInst, vd, vn, shiftAmt); case 0x08: if (!immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return new SriDX(machInst, vd, vn, shiftAmt); else return new Unknown64(machInst); case 0x0a: if (!immh3) return new Unknown64(machInst); shiftAmt = ((immh << 3) | immb) - (8 << size); if (u) return new SliDX(machInst, vd, vn, shiftAmt); else return new ShlDX(machInst, vd, vn, shiftAmt); case 0x0c: if (u) { shiftAmt = ((immh << 3) | immb) - (8 << size); return decodeNeonSTwoShiftUReg( size, machInst, vd, vn, shiftAmt); } else { return new Unknown64(machInst); } case 0x0e: shiftAmt = ((immh << 3) | immb) - (8 << size); if (u) return decodeNeonUTwoShiftUReg( size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftUReg( size, machInst, vd, vn, shiftAmt); case 0x10: if (!u || immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); return decodeNeonSTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); case 0x11: if (!u || immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); return decodeNeonSTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); case 0x12: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); case 0x13: if (immh3) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); else return decodeNeonSTwoShiftUSReg( size, machInst, vd, vn, shiftAmt); case 0x1c: if (immh < 0x4) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) { return decodeNeonUTwoShiftUFpReg( size & 0x1, machInst, vd, vn, shiftAmt); } else { if (size & 0x1) return new ScvtfFixedScDX(machInst, vd, vn, shiftAmt); else return new ScvtfFixedScSX(machInst, vd, vn, shiftAmt); } case 0x1f: if (immh < 0x4) return new Unknown64(machInst); shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb); if (u) return decodeNeonUTwoShiftUFpReg( size & 0x1, machInst, vd, vn, shiftAmt); else return decodeNeonUTwoShiftUFpReg( size & 0x1, machInst, vd, vn, shiftAmt); default: return new Unknown64(machInst); } } StaticInstPtr decodeNeonMem(ExtMachInst machInst) { uint8_t dataSize = bits(machInst, 30) ? 128 : 64; bool multiple = bits(machInst, 24, 23) < 0x2; bool load = bits(machInst, 22); uint8_t numStructElems = 0; uint8_t numRegs = 0; if (multiple) { // AdvSIMD load/store multiple structures uint8_t opcode = bits(machInst, 15, 12); uint8_t eSize = bits(machInst, 11, 10); bool wb = !(bits(machInst, 20, 16) == 0x0 && !bits(machInst, 23)); switch (opcode) { case 0x0: // LD/ST4 (4 regs) numStructElems = 4; numRegs = 4; break; case 0x2: // LD/ST1 (4 regs) numStructElems = 1; numRegs = 4; break; case 0x4: // LD/ST3 (3 regs) numStructElems = 3; numRegs = 3; break; case 0x6: // LD/ST1 (3 regs) numStructElems = 1; numRegs = 3; break; case 0x7: // LD/ST1 (1 reg) numStructElems = 1; numRegs = 1; break; case 0x8: // LD/ST2 (2 regs) numStructElems = 2; numRegs = 2; break; case 0xa: // LD/ST1 (2 regs) numStructElems = 1; numRegs = 2; break; default: return new Unknown64(machInst); } IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex rn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); if (load) { return new VldMult64(machInst, rn, vd, rm, eSize, dataSize, numStructElems, numRegs, wb); } else { return new VstMult64(machInst, rn, vd, rm, eSize, dataSize, numStructElems, numRegs, wb); } } else { // AdvSIMD load/store single structure uint8_t scale = bits(machInst, 15, 14); uint8_t numStructElems = (((uint8_t) bits(machInst, 13) << 1) | (uint8_t) bits(machInst, 21)) + 1; uint8_t index = 0; bool wb = !(bits(machInst, 20, 16) == 0x0 && !bits(machInst, 23)); bool replicate = false; switch (scale) { case 0x0: index = ((uint8_t) bits(machInst, 30) << 3) | ((uint8_t) bits(machInst, 12) << 2) | (uint8_t) bits(machInst, 11, 10); break; case 0x1: index = ((uint8_t) bits(machInst, 30) << 2) | ((uint8_t) bits(machInst, 12) << 1) | (uint8_t) bits(machInst, 11); break; case 0x2: if (bits(machInst, 10) == 0x0) { index = ((uint8_t) bits(machInst, 30) << 1) | bits(machInst, 12); } else { index = (uint8_t) bits(machInst, 30); scale = 0x3; } break; case 0x3: scale = bits(machInst, 11, 10); replicate = true; break; default: return new Unknown64(machInst); } uint8_t eSize = scale; IntRegIndex vd = (IntRegIndex) (uint8_t) bits(machInst, 4, 0); IntRegIndex rn = (IntRegIndex) (uint8_t) bits(machInst, 9, 5); IntRegIndex rm = (IntRegIndex) (uint8_t) bits(machInst, 20, 16); if (load) { return new VldSingle64(machInst, rn, vd, rm, eSize, dataSize, numStructElems, index, wb, replicate); } else { return new VstSingle64(machInst, rn, vd, rm, eSize, dataSize, numStructElems, index, wb, replicate); } } } } }};