summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa/formats/neon64.isa
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/isa/formats/neon64.isa')
-rw-r--r--src/arch/arm/isa/formats/neon64.isa2626
1 files changed, 2626 insertions, 0 deletions
diff --git a/src/arch/arm/isa/formats/neon64.isa b/src/arch/arm/isa/formats/neon64.isa
new file mode 100644
index 000000000..72bbd0c60
--- /dev/null
+++ b/src/arch/arm/isa/formats/neon64.isa
@@ -0,0 +1,2626 @@
+// 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
+ StaticInstPtr decodeNeon3Same(ExtMachInst machInst);
+ // AdvSIMD three different
+ StaticInstPtr decodeNeon3Diff(ExtMachInst machInst);
+ // AdvSIMD two-reg misc
+ StaticInstPtr decodeNeon2RegMisc(ExtMachInst machInst);
+ // AdvSIMD across lanes
+ StaticInstPtr decodeNeonAcrossLanes(ExtMachInst machInst);
+ // AdvSIMD copy
+ StaticInstPtr decodeNeonCopy(ExtMachInst machInst);
+ // AdvSIMD vector x indexed element
+ StaticInstPtr decodeNeonIndexedElem(ExtMachInst machInst);
+ // AdvSIMD modified immediate
+ StaticInstPtr decodeNeonModImm(ExtMachInst machInst);
+ // AdvSIMD shift by immediate
+ StaticInstPtr decodeNeonShiftByImm(ExtMachInst machInst);
+ // AdvSIMD TBL/TBX
+ StaticInstPtr decodeNeonTblTbx(ExtMachInst machInst);
+ // AdvSIMD ZIP/UZP/TRN
+ StaticInstPtr decodeNeonZipUzpTrn(ExtMachInst machInst);
+ // AdvSIMD EXT
+ StaticInstPtr decodeNeonExt(ExtMachInst machInst);
+
+ // AdvSIMD scalar three same
+ StaticInstPtr decodeNeonSc3Same(ExtMachInst machInst);
+ // AdvSIMD scalar three different
+ StaticInstPtr decodeNeonSc3Diff(ExtMachInst machInst);
+ // AdvSIMD scalar two-reg misc
+ StaticInstPtr decodeNeonSc2RegMisc(ExtMachInst machInst);
+ // AdvSIMD scalar pairwise
+ StaticInstPtr decodeNeonScPwise(ExtMachInst machInst);
+ // AdvSIMD scalar copy
+ StaticInstPtr decodeNeonScCopy(ExtMachInst machInst);
+ // AdvSIMD scalar x indexed element
+ StaticInstPtr decodeNeonScIndexedElem(ExtMachInst machInst);
+ // AdvSIMD scalar shift by immediate
+ StaticInstPtr decodeNeonScShiftByImm(ExtMachInst machInst);
+
+ // AdvSIMD load/store
+ StaticInstPtr decodeNeonMem(ExtMachInst machInst);
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ 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<UhaddDX, UhaddQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<ShaddDX, ShaddQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x01:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UqaddDX, UqaddQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SqaddDX, SqaddQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x02:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UrhaddDX, UrhaddQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SrhaddDX, SrhaddQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x03:
+ switch (size) {
+ case 0x0:
+ if (u) {
+ if (q)
+ return new EorQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new EorDX<uint64_t>(machInst, vd, vn, vm);
+ } else {
+ if (q)
+ return new AndQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new AndDX<uint64_t>(machInst, vd, vn, vm);
+ }
+ case 0x1:
+ if (u) {
+ if (q)
+ return new BslQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new BslDX<uint64_t>(machInst, vd, vn, vm);
+ } else {
+ if (q)
+ return new BicQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new BicDX<uint64_t>(machInst, vd, vn, vm);
+ }
+ case 0x2:
+ if (u) {
+ if (q)
+ return new BitQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new BitDX<uint64_t>(machInst, vd, vn, vm);
+ } else {
+ if (q)
+ return new OrrQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new OrrDX<uint64_t>(machInst, vd, vn, vm);
+ }
+ case 0x3:
+ if (u) {
+ if (q)
+ return new BifQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new BifDX<uint64_t>(machInst, vd, vn, vm);
+ } else {
+ if (q)
+ return new OrnQX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new OrnDX<uint64_t>(machInst, vd, vn, vm);
+ }
+ }
+ case 0x04:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UhsubDX, UhsubQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<ShsubDX, ShsubQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x05:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UqsubDX, UqsubQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SqsubDX, SqsubQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x06:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<CmhiDX, CmhiQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<CmgtDX, CmgtQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x07:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<CmhsDX, CmhsQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<CmgeDX, CmgeQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x08:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UshlDX, UshlQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SshlDX, SshlQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x09:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UqshlDX, UqshlQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SqshlDX, SqshlQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0a:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UrshlDX, UrshlQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SrshlDX, SrshlQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0b:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<UqrshlDX, UqrshlQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeXReg<SqrshlDX, SqrshlQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0c:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UmaxDX, UmaxQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SmaxDX, SmaxQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0d:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UminDX, UminQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SminDX, SminQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0e:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UabdDX, UabdQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SabdDX, SabdQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x0f:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UabaDX, UabaQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SabaDX, SabaQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x10:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<SubDX, SubQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeXReg<AddDX, AddQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x11:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeXReg<CmeqDX, CmeqQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeXReg<CmtstDX, CmtstQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x12:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<MlsDX, MlsQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeSReg<MlaDX, MlaQX>(
+ 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<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new PmulDX<uint8_t>(machInst, vd, vn, vm);
+ } else {
+ return decodeNeonUThreeSReg<MulDX, MulQX>(
+ q, size, machInst, vd, vn, vm);
+ }
+ case 0x14:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UmaxpDX, UmaxpQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SmaxpDX, SmaxpQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x15:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UminpDX, UminpQX>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SminpDX, SminpQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x16:
+ if (size == 0x3 || size == 0x0)
+ return new Unknown64(machInst);
+ if (u) {
+ if (q)
+ return decodeNeonSThreeHAndWReg<SqrdmulhQX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeHAndWReg<SqrdmulhDX>(
+ size, machInst, vd, vn, vm);
+ } else {
+ if (q)
+ return decodeNeonSThreeHAndWReg<SqdmulhQX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeHAndWReg<SqdmulhDX>(
+ size, machInst, vd, vn, vm);
+ }
+ case 0x17:
+ if (u || size_q == 0x6)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeXReg<AddpDX, AddpQX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x18:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FmaxnmpDX, FmaxnmpQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FmaxnmDX, FmaxnmQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return decodeNeonUThreeFpReg<FminnmpDX, FminnmpQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FminnmDX, FminnmQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ }
+ case 0x19:
+ if (size < 0x2) {
+ if (u || sz_q == 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeFpReg<FmlaDX, FmlaQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u || sz_q == 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeFpReg<FmlsDX, FmlsQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ }
+ case 0x1a:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FaddpDX, FaddpQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FaddDX, FaddQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return decodeNeonUThreeFpReg<FabdDX, FabdQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FsubDX, FsubQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ }
+ case 0x1b:
+ if (size < 0x2 && sz_q != 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FmulDX, FmulQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FmulxDX, FmulxQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ return new Unknown64(machInst);
+ }
+ case 0x1c:
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FcmgeDX, FcmgeQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FcmeqDX, FcmeqQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return decodeNeonUThreeFpReg<FcmgtDX, FcmgtQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return new Unknown64(machInst);
+ }
+ case 0x1d:
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FacgeDX, FacgeQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return new Unknown64(machInst);
+ } else {
+ if (u)
+ return decodeNeonUThreeFpReg<FacgtDX, FacgtQX>(
+ 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<FmaxpDX, FmaxpQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FmaxDX, FmaxQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return decodeNeonUThreeFpReg<FminpDX, FminpQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FminDX, FminQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ }
+ case 0x1f:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeFpReg<FdivDX, FdivQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeFpReg<FrecpsDX, FrecpsQX>(
+ q, size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeFpReg<FrsqrtsDX, FrsqrtsQX>(
+ 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<UaddlX, Uaddl2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SaddlX, Saddl2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x1:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UaddwX, Uaddw2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SaddwX, Saddw2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x2:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UsublX, Usubl2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SsublX, Ssubl2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x3:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UsubwX, Usubw2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SsubwX, Ssubw2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x4:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<RaddhnX, Raddhn2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeSReg<AddhnX, Addhn2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x5:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UabalX, Uabal2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SabalX, Sabal2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x6:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<RsubhnX, Rsubhn2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeSReg<SubhnX, Subhn2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x7:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UabdlX, Uabdl2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SabdlX, Sabdl2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x8:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UmlalX, Umlal2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SmlalX, Smlal2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0x9:
+ if (u || (size == 0x0 || size == 0x3)) {
+ return new Unknown64(machInst);
+ } else {
+ if (q) {
+ return decodeNeonSThreeHAndWReg<Sqdmlal2X>(
+ size, machInst, vd, vn, vm);
+ } else {
+ return decodeNeonSThreeHAndWReg<SqdmlalX>(
+ size, machInst, vd, vn, vm);
+ }
+ }
+ case 0xa:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UmlslX, Umlsl2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SmlslX, Smlsl2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0xb:
+ if (u || (size == 0x0 || size == 0x3)) {
+ return new Unknown64(machInst);
+ } else {
+ if (q) {
+ return decodeNeonSThreeHAndWReg<Sqdmlsl2X>(
+ size, machInst, vd, vn, vm);
+ } else {
+ return decodeNeonSThreeHAndWReg<SqdmlslX>(
+ size, machInst, vd, vn, vm);
+ }
+ }
+ case 0xc:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeSReg<UmullX, Umull2X>(
+ q, size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeSReg<SmullX, Smull2X>(
+ q, size, machInst, vd, vn, vm);
+ case 0xd:
+ if (u || (size == 0x0 || size == 0x3)) {
+ return new Unknown64(machInst);
+ } else {
+ if (q) {
+ return decodeNeonSThreeHAndWReg<Sqdmull2X>(
+ size, machInst, vd, vn, vm);
+ } else {
+ return decodeNeonSThreeHAndWReg<SqdmullX>(
+ size, machInst, vd, vn, vm);
+ }
+ }
+ case 0xe:
+ if (u || size != 0) {
+ return new Unknown64(machInst);
+ } else {
+ if (q)
+ return new Pmull2X<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new PmullX<uint8_t>(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<Rev64DX, Rev64QX>(
+ q, size, machInst, vd, vn);
+ case 0x01:
+ if (op + size >= 3)
+ return new Unknown64(machInst);
+ if (q)
+ return new Rev16QX<uint8_t>(machInst, vd, vn);
+ else
+ return new Rev16DX<uint8_t>(machInst, vd, vn);
+ case 0x02:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<SaddlpDX, SaddlpQX>(
+ q, size, machInst, vd, vn);
+ case 0x03:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscXReg<SuqaddDX, SuqaddQX>(
+ q, size, machInst, vd, vn);
+ case 0x04:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<ClsDX, ClsQX>(
+ q, size, machInst, vd, vn);
+ case 0x05:
+ if (size != 0x0)
+ return new Unknown64(machInst);
+ if (q)
+ return new CntQX<uint8_t>(machInst, vd, vn);
+ else
+ return new CntDX<uint8_t>(machInst, vd, vn);
+ case 0x06:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<SadalpDX, SadalpQX>(
+ q, size, machInst, vd, vn);
+ case 0x07:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<SqabsDX, SqabsQX>(
+ q, size, machInst, vd, vn);
+ case 0x08:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<CmgtZeroDX, CmgtZeroQX>(
+ q, size, machInst, vd, vn);
+ case 0x09:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<CmeqZeroDX, CmeqZeroQX>(
+ q, size, machInst, vd, vn);
+ case 0x0a:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<CmltZeroDX, CmltZeroQX>(
+ q, size, machInst, vd, vn);
+ case 0x0b:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<AbsDX, AbsQX>(
+ q, size, machInst, vd, vn);
+ case 0x0c:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcmgtZeroDX, FcmgtZeroQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x0d:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcmeqZeroDX, FcmeqZeroQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x0e:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcmltZeroDX, FcmltZeroQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x0f:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FabsDX, FabsQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x12:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscSReg<XtnX, Xtn2X>(
+ q, size, machInst, vd, vn);
+ case 0x14:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<SqxtnX, Sqxtn2X>(
+ q, size, machInst, vd, vn);
+ case 0x16:
+ if (size > 0x1)
+ return new Unknown64(machInst);
+ if (q) {
+ if (size)
+ return new Fcvtn2X<uint32_t>(machInst, vd, vn);
+ else
+ return new Fcvtn2X<uint16_t>(machInst, vd, vn);
+ } else {
+ if (size)
+ return new FcvtnX<uint32_t>(machInst, vd, vn);
+ else
+ return new FcvtnX<uint16_t>(machInst, vd, vn);
+ }
+ case 0x17:
+ if (size > 0x1)
+ return new Unknown64(machInst);
+ if (q) {
+ if (size)
+ return new Fcvtl2X<uint32_t>(machInst, vd, vn);
+ else
+ return new Fcvtl2X<uint16_t>(machInst, vd, vn);
+ } else {
+ if (size)
+ return new FcvtlX<uint32_t>(machInst, vd, vn);
+ else
+ return new FcvtlX<uint16_t>(machInst, vd, vn);
+ }
+ case 0x18:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FrintnDX, FrintnQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FrintpDX, FrintpQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x19:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FrintmDX, FrintmQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FrintzDX, FrintzQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x1a:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FcvtnsDX, FcvtnsQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FcvtpsDX, FcvtpsQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x1b:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FcvtmsDX, FcvtmsQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FcvtzsIntDX, FcvtzsIntQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x1c:
+ if (size < 0x2) {
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcvtasDX, FcvtasQX>(
+ q, size & 0x1, machInst, vd, vn);
+ } else {
+ if (size & 0x1)
+ return new Unknown64(machInst);
+ if (q)
+ return new UrecpeQX<uint32_t>(machInst, vd, vn);
+ else
+ return new UrecpeDX<uint32_t>(machInst, vd, vn);
+ }
+ case 0x1d:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2) {
+ if (q) {
+ if (size & 0x1)
+ return new ScvtfIntDQX<uint64_t>(machInst, vd, vn);
+ else
+ return new ScvtfIntSQX<uint32_t>(machInst, vd, vn);
+ } else {
+ if (size & 0x1)
+ return new Unknown(machInst);
+ else
+ return new ScvtfIntDX<uint32_t>(machInst, vd, vn);
+ }
+ } else {
+ return decodeNeonUTwoMiscFpReg<FrecpeDX, FrecpeQX>(
+ q, size & 0x1, machInst, vd, vn);
+ }
+ case 0x20:
+ if (op + size >= 3)
+ return new Unknown64(machInst);
+ if (q) {
+ if (size & 0x1)
+ return new Rev32QX<uint16_t>(machInst, vd, vn);
+ else
+ return new Rev32QX<uint8_t>(machInst, vd, vn);
+ } else {
+ if (size & 0x1)
+ return new Rev32DX<uint16_t>(machInst, vd, vn);
+ else
+ return new Rev32DX<uint8_t>(machInst, vd, vn);
+ }
+ case 0x22:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscSReg<UaddlpDX, UaddlpQX>(
+ q, size, machInst, vd, vn);
+ case 0x23:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscXReg<UsqaddDX, UsqaddQX>(
+ q, size, machInst, vd, vn);
+ return new Unknown64(machInst);
+ case 0x24:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<ClzDX, ClzQX>(
+ q, size, machInst, vd, vn);
+ case 0x25:
+ if (size == 0x0) {
+ if (q)
+ return new MvnQX<uint64_t>(machInst, vd, vn);
+ else
+ return new MvnDX<uint64_t>(machInst, vd, vn);
+ } else if (size == 0x1) {
+ if (q)
+ return new RbitQX<uint8_t>(machInst, vd, vn);
+ else
+ return new RbitDX<uint8_t>(machInst, vd, vn);
+ } else {
+ return new Unknown64(machInst);
+ }
+ case 0x26:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscSReg<UadalpDX, UadalpQX>(
+ q, size, machInst, vd, vn);
+ case 0x27:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<SqnegDX, SqnegQX>(
+ q, size, machInst, vd, vn);
+ case 0x28:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<CmgeZeroDX, CmgeZeroQX>(
+ q, size, machInst, vd, vn);
+ case 0x29:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<CmleZeroDX, CmleZeroQX>(
+ q, size, machInst, vd, vn);
+ case 0x2b:
+ if (size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscXReg<NegDX, NegQX>(
+ q, size, machInst, vd, vn);
+ case 0x2c:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcmgeZeroDX, FcmgeZeroQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x2d:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FcmleZeroDX, FcmleZeroQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x2f:
+ if (size < 0x2 || size_q == 0x6)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FnegDX, FnegQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x32:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSTwoMiscSReg<SqxtunX, Sqxtun2X>(
+ q, size, machInst, vd, vn);
+ case 0x33:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscSReg<ShllX, Shll2X>(
+ q, size, machInst, vd, vn);
+ case 0x34:
+ if (size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscSReg<UqxtnX, Uqxtn2X>(
+ q, size, machInst, vd, vn);
+ case 0x36:
+ if (size != 0x1)
+ return new Unknown64(machInst);
+ if (q)
+ return new Fcvtxn2X<uint32_t>(machInst, vd, vn);
+ else
+ return new FcvtxnX<uint32_t>(machInst, vd, vn);
+ case 0x38:
+ if (size > 0x1 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FrintaDX, FrintaQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x39:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FrintxDX, FrintxQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FrintiDX, FrintiQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x3a:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FcvtnuDX, FcvtnuQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FcvtpuDX, FcvtpuQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x3b:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<FcvtmuDX, FcvtmuQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FcvtzuIntDX, FcvtzuIntQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x3c:
+ if (size < 0x2) {
+ return decodeNeonUTwoMiscFpReg<FcvtauDX, FcvtauQX>(
+ q, size & 0x1, machInst, vd, vn);
+ } else if (size == 0x2) {
+ if (q)
+ return new UrsqrteQX<uint32_t>(machInst, vd, vn);
+ else
+ return new UrsqrteDX<uint32_t>(machInst, vd, vn);
+ } else {
+ return new Unknown64(machInst);
+ }
+ case 0x3d:
+ if (sz_q == 0x2)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUTwoMiscFpReg<UcvtfIntDX, UcvtfIntQX>(
+ q, size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscFpReg<FrsqrteDX, FrsqrteQX>(
+ q, size & 0x1, machInst, vd, vn);
+ case 0x3f:
+ if (size < 0x2 || sz_q == 0x2)
+ return new Unknown64(machInst);
+ return decodeNeonUTwoMiscFpReg<FsqrtDX, FsqrtQX>(
+ 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<SaddlvDX, SaddlvQX,
+ SaddlvBQX>(
+ q, size, machInst, vd, vn);
+ case 0x0a:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSAcrossLanesReg<SmaxvDX, SmaxvQX>(
+ q, size, machInst, vd, vn);
+ case 0x1a:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonSAcrossLanesReg<SminvDX, SminvQX>(
+ q, size, machInst, vd, vn);
+ case 0x1b:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUAcrossLanesReg<AddvDX, AddvQX>(
+ q, size, machInst, vd, vn);
+ case 0x23:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUAcrossLanesLongReg<UaddlvDX, UaddlvQX,
+ UaddlvBQX>(
+ q, size, machInst, vd, vn);
+ case 0x2a:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUAcrossLanesReg<UmaxvDX, UmaxvQX>(
+ q, size, machInst, vd, vn);
+ case 0x2c:
+ if (sz_q != 0x1)
+ return new Unknown64(machInst);
+ if (size < 0x2) {
+ if (q)
+ return new FmaxnmvQX<uint32_t>(machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ } else {
+ if (q)
+ return new FminnmvQX<uint32_t>(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<uint32_t>(machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ } else {
+ if (q)
+ return new FminvQX<uint32_t>(machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ }
+ case 0x3a:
+ if (size_q == 0x4 || size == 0x3)
+ return new Unknown64(machInst);
+ return decodeNeonUAcrossLanesReg<UminvDX, UminvQX>(
+ 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<uint8_t>(machInst, vd, vn, index1, index2);
+ case 1:
+ return new InsElemX<uint16_t>(machInst, vd, vn, index1, index2);
+ case 2:
+ return new InsElemX<uint32_t>(machInst, vd, vn, index1, index2);
+ case 3:
+ return new InsElemX<uint64_t>(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<uint8_t>(machInst, vd, vn, index1);
+ else
+ return new DupElemDX<uint8_t>(machInst, vd, vn, index1);
+ case 1:
+ if (q)
+ return new DupElemQX<uint16_t>(machInst, vd, vn, index1);
+ else
+ return new DupElemDX<uint16_t>(machInst, vd, vn, index1);
+ case 2:
+ if (q)
+ return new DupElemQX<uint32_t>(machInst, vd, vn, index1);
+ else
+ return new DupElemDX<uint32_t>(machInst, vd, vn, index1);
+ case 3:
+ if (q)
+ return new DupElemQX<uint64_t>(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<uint8_t>(machInst, vd, vn);
+ else
+ return new DupGprWDX<uint8_t>(machInst, vd, vn);
+ case 0x2:
+ if (q)
+ return new DupGprWQX<uint16_t>(machInst, vd, vn);
+ else
+ return new DupGprWDX<uint16_t>(machInst, vd, vn);
+ case 0x4:
+ if (q)
+ return new DupGprWQX<uint32_t>(machInst, vd, vn);
+ else
+ return new DupGprWDX<uint32_t>(machInst, vd, vn);
+ case 0x8:
+ if (q)
+ return new DupGprXQX<uint64_t>(machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ }
+ case 0x3:
+ index1 = imm5 >> (imm5_pos + 1);
+ switch (imm5_pos) {
+ case 0:
+ return new InsGprWX<uint8_t>(machInst, vd, vn, index1);
+ case 1:
+ return new InsGprWX<uint16_t>(machInst, vd, vn, index1);
+ case 2:
+ return new InsGprWX<uint32_t>(machInst, vd, vn, index1);
+ case 3:
+ return new InsGprXX<uint64_t>(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<int8_t>(machInst, vd, vn, index1);
+ else
+ return new SmovWX<int8_t>(machInst, vd, vn, index1);
+ case 1:
+ if (q)
+ return new SmovXX<int16_t>(machInst, vd, vn, index1);
+ else
+ return new SmovWX<int16_t>(machInst, vd, vn, index1);
+ case 2:
+ if (q)
+ return new SmovXX<int32_t>(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<uint8_t>(machInst, vd, vn, index1);
+ case 1:
+ return new UmovWX<uint16_t>(machInst, vd, vn, index1);
+ case 2:
+ return new UmovWX<uint32_t>(machInst, vd, vn, index1);
+ case 3:
+ return new UmovXX<uint64_t>(machInst, vd, vn, index1);
+ default:
+ return new Unknown64(machInst);
+ }
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+
+ 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<MlaElemDX, MlaElemQX>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x1:
+ if (!u && size >= 2 && sz_q != 0x2 && sz_L != 0x3)
+ return decodeNeonUThreeImmFpReg<FmlaElemDX, FmlaElemQX>(
+ 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<UmlalElemX, UmlalElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ else
+ return decodeNeonSThreeImmHAndWReg<SmlalElemX, SmlalElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x3:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmlalElemX,
+ SqdmlalElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x4:
+ if (u && !(size == 0x0 || size == 0x3))
+ return decodeNeonUThreeImmHAndWReg<MlsElemDX, MlsElemQX>(
+ 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<FmlsElemDX, FmlsElemQX>(
+ 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<UmlslElemX, UmlslElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ else
+ return decodeNeonSThreeImmHAndWReg<SmlslElemX, SmlslElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x7:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmlslElemX,
+ SqdmlslElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x8:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeImmHAndWReg<MulElemDX, MulElemQX>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0x9:
+ if (size >= 2 && sz_q != 0x2 && sz_L != 0x3) {
+ if (u)
+ return decodeNeonUThreeImmFpReg<FmulxElemDX, FmulxElemQX>(
+ q, sz, machInst, vd, vn, vm_fp, index_fp);
+ else
+ return decodeNeonUThreeImmFpReg<FmulElemDX, FmulElemQX>(
+ 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<UmullElemX, UmullElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ else
+ return decodeNeonSThreeImmHAndWReg<SmullElemX, SmullElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0xb:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmullElemX, SqdmullElem2X>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0xc:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmulhElemDX, SqdmulhElemQX>(
+ q, size, machInst, vd, vn, vm, index);
+ case 0xd:
+ if (u || (size == 0x0 || size == 0x3))
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqrdmulhElemDX, SqrdmulhElemQX>(
+ 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<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MvniDX<uint64_t>(machInst, vd, bigImm);
+ } else {
+ if (q)
+ return new BicImmQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new BicImmDX<uint64_t>(machInst, vd, bigImm);
+ }
+ } else {
+ if (bits(cmode, 2) == 1) {
+ switch (bits(cmode, 1, 0)) {
+ case 0:
+ case 1:
+ if (q)
+ return new MvniQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MvniDX<uint64_t>(machInst, vd, bigImm);
+ case 2:
+ if (q)
+ return new MoviQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MoviDX<uint64_t>(machInst, vd, bigImm);
+ case 3:
+ if (q)
+ return new FmovQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MoviDX<uint64_t>(machInst, vd, bigImm);
+ }
+ } else {
+ if (bits(cmode, 0) == 0) {
+ if (q)
+ return new MvniQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MvniDX<uint64_t>(machInst, vd, bigImm);
+ } else {
+ if (q)
+ return new BicImmQX<uint64_t>(machInst, vd,
+ bigImm);
+ else
+ return new BicImmDX<uint64_t>(machInst, vd,
+ bigImm);
+ }
+ }
+ }
+ } else {
+ if (bits(cmode, 3) == 0) {
+ if (bits(cmode, 0) == 0) {
+ if (q)
+ return new MoviQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MoviDX<uint64_t>(machInst, vd, bigImm);
+ } else {
+ if (q)
+ return new OrrImmQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new OrrImmDX<uint64_t>(machInst, vd, bigImm);
+ }
+ } else {
+ if (bits(cmode, 2) == 1) {
+ if (bits(cmode, 1, 0) == 0x3) {
+ if (q)
+ return new FmovQX<uint32_t>(machInst, vd, bigImm);
+ else
+ return new FmovDX<uint32_t>(machInst, vd, bigImm);
+ } else {
+ if (q)
+ return new MoviQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MoviDX<uint64_t>(machInst, vd, bigImm);
+ }
+ } else {
+ if (bits(cmode, 0) == 0) {
+ if (q)
+ return new MoviQX<uint64_t>(machInst, vd, bigImm);
+ else
+ return new MoviDX<uint64_t>(machInst, vd, bigImm);
+ } else {
+ if (q)
+ return new OrrImmQX<uint64_t>(machInst, vd,
+ bigImm);
+ else
+ return new OrrImmDX<uint64_t>(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<UshrDX, UshrQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftXReg<SshrDX, SshrQX>(
+ 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<UsraDX, UsraQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftXReg<SsraDX, SsraQX>(
+ 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<UrshrDX, UrshrQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftXReg<SrshrDX, SrshrQX>(
+ 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<UrsraDX, UrsraQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftXReg<SrsraDX, SrsraQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ case 0x08:
+ if (u && !(immh3_q == 0x2)) {
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ return decodeNeonUTwoShiftXReg<SriDX, SriQX>(
+ 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<SliDX, SliQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonUTwoShiftXReg<ShlDX, ShlQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ case 0x0c:
+ if (u && !(immh3_q == 0x2 || op_u == 0x0)) {
+ shiftAmt = ((immh << 3) | immb) - (8 << size);
+ return decodeNeonSTwoShiftXReg<SqshluDX, SqshluQX>(
+ 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<UqshlImmDX, UqshlImmQX>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftXReg<SqshlImmDX, SqshlImmQX>(
+ 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<SqshrunX, Sqshrun2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonUTwoShiftSReg<ShrnX, Shrn2X>(
+ 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<SqrshrunX, Sqrshrun2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonUTwoShiftSReg<RshrnX, Rshrn2X>(
+ 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<UqshrnX, Uqshrn2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftSReg<SqshrnX, Sqshrn2X>(
+ 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<UqrshrnX, Uqrshrn2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftSReg<SqrshrnX, Sqrshrn2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ case 0x14:
+ if (immh3)
+ return new Unknown64(machInst);
+ shiftAmt = ((immh << 3) | immb) - (8 << size);
+ if (u)
+ return decodeNeonUTwoShiftSReg<UshllX, Ushll2X>(
+ q, size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftSReg<SshllX, Sshll2X>(
+ 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<UcvtfFixedDX, UcvtfFixedQX>(
+ q, size & 0x1, machInst, vd, vn, shiftAmt);
+ } else {
+ if (q) {
+ if (size & 0x1)
+ return new ScvtfFixedDQX<uint64_t>(machInst, vd, vn,
+ shiftAmt);
+ else
+ return new ScvtfFixedSQX<uint32_t>(machInst, vd, vn,
+ shiftAmt);
+ } else {
+ if (size & 0x1)
+ return new Unknown(machInst);
+ else
+ return new ScvtfFixedDX<uint32_t>(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<FcvtzuFixedDX, FcvtzuFixedQX>(
+ q, size & 0x1, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonUTwoShiftFpReg<FcvtzsFixedDX, FcvtzsFixedQX>(
+ 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<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbl1DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x1:
+ if (q)
+ return new Tbx1QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbx1DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x2:
+ if (q)
+ return new Tbl2QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbl2DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x3:
+ if (q)
+ return new Tbx2QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbx2DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x4:
+ if (q)
+ return new Tbl3QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbl3DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x5:
+ if (q)
+ return new Tbx3QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbx3DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x6:
+ if (q)
+ return new Tbl4QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbl4DX<uint8_t>(machInst, vd, vn, vm);
+ case 0x7:
+ if (q)
+ return new Tbx4QX<uint8_t>(machInst, vd, vn, vm);
+ else
+ return new Tbx4DX<uint8_t>(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<Uzp1DX, Uzp1QX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x2:
+ return decodeNeonUThreeXReg<Trn1DX, Trn1QX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x3:
+ return decodeNeonUThreeXReg<Zip1DX, Zip1QX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x5:
+ return decodeNeonUThreeXReg<Uzp2DX, Uzp2QX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x6:
+ return decodeNeonUThreeXReg<Trn2DX, Trn2QX>(
+ q, size, machInst, vd, vn, vm);
+ case 0x7:
+ return decodeNeonUThreeXReg<Zip2DX, Zip2QX>(
+ 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<uint8_t>(machInst, vd, vn, vm, index);
+ } else {
+ return new ExtDX<uint8_t>(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<UqaddScX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeUReg<SqaddScX>(
+ size, machInst, vd, vn, vm);
+ case 0x05:
+ if (u)
+ return decodeNeonUThreeUReg<UqsubScX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeUReg<SqsubScX>(
+ size, machInst, vd, vn, vm);
+ case 0x06:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new CmhiDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new CmgtDX<int64_t>(machInst, vd, vn, vm);
+ case 0x07:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new CmhsDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new CmgeDX<int64_t>(machInst, vd, vn, vm);
+ case 0x08:
+ if (!s && size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new UshlDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new SshlDX<int64_t>(machInst, vd, vn, vm);
+ case 0x09:
+ if (!s && size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeUReg<UqshlScX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeUReg<SqshlScX>(
+ size, machInst, vd, vn, vm);
+ case 0x0a:
+ if (!s && size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new UrshlDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new SrshlDX<int64_t>(machInst, vd, vn, vm);
+ case 0x0b:
+ if (!s && size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeUReg<UqrshlScX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeUReg<SqrshlScX>(
+ size, machInst, vd, vn, vm);
+ case 0x10:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new SubDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new AddDX<uint64_t>(machInst, vd, vn, vm);
+ case 0x11:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return new CmeqDX<uint64_t>(machInst, vd, vn, vm);
+ else
+ return new CmtstDX<uint64_t>(machInst, vd, vn, vm);
+ case 0x16:
+ if (size == 0x3 || size == 0x0)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonSThreeHAndWReg<SqrdmulhScX>(
+ size, machInst, vd, vn, vm);
+ else
+ return decodeNeonSThreeHAndWReg<SqdmulhScX>(
+ size, machInst, vd, vn, vm);
+ case 0x1a:
+ if (!u || size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeScFpReg<FabdScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ case 0x1b:
+ if (u || size > 0x1)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeScFpReg<FmulxScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ case 0x1c:
+ if (size < 0x2) {
+ if (u)
+ return decodeNeonUThreeScFpReg<FcmgeScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeScFpReg<FcmeqScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ } else {
+ if (u)
+ return decodeNeonUThreeScFpReg<FcmgtScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ else
+ return new Unknown64(machInst);
+ }
+ case 0x1d:
+ if (!u)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUThreeScFpReg<FacgeScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeScFpReg<FacgtScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ case 0x1f:
+ if (u)
+ return new Unknown64(machInst);
+ if (size < 0x2)
+ return decodeNeonUThreeScFpReg<FrecpsScX>(
+ size & 0x1, machInst, vd, vn, vm);
+ else
+ return decodeNeonUThreeScFpReg<FrsqrtsScX>(
+ 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<SqdmlalScX>(size, machInst, vd, vn, vm);
+ case 0xb:
+ return decodeNeonSThreeHAndWReg<SqdmlslScX>(size, machInst, vd, vn, vm);
+ case 0xd:
+ return decodeNeonSThreeHAndWReg<SqdmullScX>(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<SuqaddScX>(size, machInst, vd, vn);
+ case 0x07:
+ return decodeNeonSTwoMiscUReg<SqabsScX>(size, machInst, vd, vn);
+ case 0x08:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new CmgtZeroDX<int64_t>(machInst, vd, vn);
+ case 0x09:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new CmeqZeroDX<int64_t>(machInst, vd, vn);
+ case 0x0a:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new CmltZeroDX<int64_t>(machInst, vd, vn);
+ case 0x0b:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new AbsDX<int64_t>(machInst, vd, vn);
+ case 0x0c:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcmgtZeroScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x0d:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcmeqZeroScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x0e:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcmltZeroScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x14:
+ if (size == 0x3) {
+ return new Unknown64(machInst);
+ } else {
+ switch (size) {
+ case 0x0:
+ return new SqxtnScX<int8_t>(machInst, vd, vn);
+ case 0x1:
+ return new SqxtnScX<int16_t>(machInst, vd, vn);
+ case 0x2:
+ return new SqxtnScX<int32_t>(machInst, vd, vn);
+ }
+ }
+ case 0x1a:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtnsScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcvtpsScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x1b:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtmsScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcvtzsIntScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x1c:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtasScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ case 0x1d:
+ if (size < 0x2) {
+ if (size & 0x1)
+ return new ScvtfIntScDX<uint64_t>(machInst, vd, vn);
+ else
+ return new ScvtfIntScSX<uint32_t>(machInst, vd, vn);
+ } else {
+ return decodeNeonUTwoMiscScFpReg<FrecpeScX>(
+ size & 0x1, machInst, vd, vn);
+ }
+ case 0x1f:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FrecpxX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x23:
+ return decodeNeonUTwoMiscUReg<UsqaddScX>(size, machInst, vd, vn);
+ case 0x27:
+ return decodeNeonSTwoMiscUReg<SqnegScX>(size, machInst, vd, vn);
+ case 0x28:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new CmgeZeroDX<int64_t>(machInst, vd, vn);
+ case 0x29:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new CmleZeroDX<int64_t>(machInst, vd, vn);
+ case 0x2b:
+ if (size != 0x3)
+ return new Unknown64(machInst);
+ else
+ return new NegDX<int64_t>(machInst, vd, vn);
+ case 0x2c:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcmgeZeroScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x2d:
+ if (size < 0x2)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcmleZeroScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x32:
+ if (size == 0x3) {
+ return new Unknown64(machInst);
+ } else {
+ switch (size) {
+ case 0x0:
+ return new SqxtunScX<int8_t>(machInst, vd, vn);
+ case 0x1:
+ return new SqxtunScX<int16_t>(machInst, vd, vn);
+ case 0x2:
+ return new SqxtunScX<int32_t>(machInst, vd, vn);
+ }
+ }
+ case 0x34:
+ if (size == 0x3) {
+ return new Unknown64(machInst);
+ } else {
+ switch (size) {
+ case 0x0:
+ return new UqxtnScX<uint8_t>(machInst, vd, vn);
+ case 0x1:
+ return new UqxtnScX<uint16_t>(machInst, vd, vn);
+ case 0x2:
+ return new UqxtnScX<uint32_t>(machInst, vd, vn);
+ }
+ }
+ case 0x36:
+ if (size != 0x1) {
+ return new Unknown64(machInst);
+ } else {
+ return new FcvtxnScX<uint32_t>(machInst, vd, vn);
+ }
+ case 0x3a:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtnuScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcvtpuScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x3b:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtmuScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscScFpReg<FcvtzuIntScX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x3c:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<FcvtauScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ case 0x3d:
+ if (size < 0x2)
+ return decodeNeonUTwoMiscScFpReg<UcvtfIntScX>(
+ size & 0x1, machInst, vd, vn);
+ else
+ return decodeNeonUTwoMiscScFpReg<FrsqrteScX>(
+ 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<uint64_t>(machInst, vd, vn);
+ else
+ return new Unknown64(machInst);
+ }
+
+ uint8_t switchVal = (opcode << 0) | (size << 5);
+ switch (switchVal) {
+ case 0x0c:
+ case 0x2c:
+ return decodeNeonUTwoMiscPwiseScFpReg<FmaxnmpScDX, FmaxnmpScQX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x0d:
+ case 0x2d:
+ return decodeNeonUTwoMiscPwiseScFpReg<FaddpScDX, FaddpScQX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x0f:
+ case 0x2f:
+ return decodeNeonUTwoMiscPwiseScFpReg<FmaxpScDX, FmaxpScQX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x4c:
+ case 0x6c:
+ return decodeNeonUTwoMiscPwiseScFpReg<FminnmpScDX, FminnmpScQX>(
+ size & 0x1, machInst, vd, vn);
+ case 0x4f:
+ case 0x6f:
+ return decodeNeonUTwoMiscPwiseScFpReg<FminpScDX, FminpScQX>(
+ 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<DupElemScX>(
+ 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<FmlaElemScX>(
+ size & 0x1, machInst, vd, vn, vm_fp, index_fp);
+ case 0x3:
+ if (size == 0x0 || size == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmlalElemScX>(
+ size, machInst, vd, vn, vm, index);
+ case 0x5:
+ if (size < 2 || sz_L == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonUThreeImmScFpReg<FmlsElemScX>(
+ size & 0x1, machInst, vd, vn, vm_fp, index_fp);
+ case 0x7:
+ if (size == 0x0 || size == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmlslElemScX>(
+ size, machInst, vd, vn, vm, index);
+ case 0x9:
+ if (size < 2 || sz_L == 0x3)
+ return new Unknown64(machInst);
+ if (u)
+ return decodeNeonUThreeImmScFpReg<FmulxElemScX>(
+ size & 0x1, machInst, vd, vn, vm_fp, index_fp);
+ else
+ return decodeNeonUThreeImmScFpReg<FmulElemScX>(
+ size & 0x1, machInst, vd, vn, vm_fp, index_fp);
+ case 0xb:
+ if (size == 0x0 || size == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmullElemScX>(
+ size, machInst, vd, vn, vm, index);
+ case 0xc:
+ if (size == 0x0 || size == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqdmulhElemScX>(
+ size, machInst, vd, vn, vm, index);
+ case 0xd:
+ if (size == 0x0 || size == 0x3)
+ return new Unknown64(machInst);
+ else
+ return decodeNeonSThreeImmHAndWReg<SqrdmulhElemScX>(
+ 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<uint64_t>(machInst, vd, vn, shiftAmt);
+ else
+ return new SshrDX<int64_t>(machInst, vd, vn, shiftAmt);
+ case 0x02:
+ if (!immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return new UsraDX<uint64_t>(machInst, vd, vn, shiftAmt);
+ else
+ return new SsraDX<int64_t>(machInst, vd, vn, shiftAmt);
+ case 0x04:
+ if (!immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return new UrshrDX<uint64_t>(machInst, vd, vn, shiftAmt);
+ else
+ return new SrshrDX<int64_t>(machInst, vd, vn, shiftAmt);
+ case 0x06:
+ if (!immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return new UrsraDX<uint64_t>(machInst, vd, vn, shiftAmt);
+ else
+ return new SrsraDX<int64_t>(machInst, vd, vn, shiftAmt);
+ case 0x08:
+ if (!immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return new SriDX<uint64_t>(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<uint64_t>(machInst, vd, vn, shiftAmt);
+ else
+ return new ShlDX<uint64_t>(machInst, vd, vn, shiftAmt);
+ case 0x0c:
+ if (u) {
+ shiftAmt = ((immh << 3) | immb) - (8 << size);
+ return decodeNeonSTwoShiftUReg<SqshluScX>(
+ size, machInst, vd, vn, shiftAmt);
+ } else {
+ return new Unknown64(machInst);
+ }
+ case 0x0e:
+ shiftAmt = ((immh << 3) | immb) - (8 << size);
+ if (u)
+ return decodeNeonUTwoShiftUReg<UqshlImmScX>(
+ size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftUReg<SqshlImmScX>(
+ size, machInst, vd, vn, shiftAmt);
+ case 0x10:
+ if (!u || immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ return decodeNeonSTwoShiftUSReg<SqshrunScX>(
+ size, machInst, vd, vn, shiftAmt);
+ case 0x11:
+ if (!u || immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ return decodeNeonSTwoShiftUSReg<SqrshrunScX>(
+ size, machInst, vd, vn, shiftAmt);
+ case 0x12:
+ if (immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return decodeNeonUTwoShiftUSReg<UqshrnScX>(
+ size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftUSReg<SqshrnScX>(
+ size, machInst, vd, vn, shiftAmt);
+ case 0x13:
+ if (immh3)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return decodeNeonUTwoShiftUSReg<UqrshrnScX>(
+ size, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonSTwoShiftUSReg<SqrshrnScX>(
+ 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<UcvtfFixedScX>(
+ size & 0x1, machInst, vd, vn, shiftAmt);
+ } else {
+ if (size & 0x1)
+ return new ScvtfFixedScDX<uint64_t>(machInst, vd, vn,
+ shiftAmt);
+ else
+ return new ScvtfFixedScSX<uint32_t>(machInst, vd, vn,
+ shiftAmt);
+ }
+ case 0x1f:
+ if (immh < 0x4)
+ return new Unknown64(machInst);
+ shiftAmt = (8 << (size + 1)) - ((immh << 3) | immb);
+ if (u)
+ return decodeNeonUTwoShiftUFpReg<FcvtzuFixedScX>(
+ size & 0x1, machInst, vd, vn, shiftAmt);
+ else
+ return decodeNeonUTwoShiftUFpReg<FcvtzsFixedScX>(
+ 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);
+ }
+ }
+ }
+}
+}};