summaryrefslogtreecommitdiff
path: root/src/arch/arm/isa/formats
diff options
context:
space:
mode:
authorARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
committerARM gem5 Developers <none@none>2014-01-24 15:29:34 -0600
commit612f8f074fa1099cf70faf495d46cc647762a031 (patch)
treebd1e99c43bf15292395eadd4b7ae3f5c823545c3 /src/arch/arm/isa/formats
parentf3585c841e964c98911784a187fc4f081a02a0a6 (diff)
downloadgem5-612f8f074fa1099cf70faf495d46cc647762a031.tar.xz
arm: Add support for ARMv8 (AArch64 & AArch32)
Note: AArch64 and AArch32 interworking is not supported. If you use an AArch64 kernel you are restricted to AArch64 user-mode binaries. This will be addressed in a later patch. Note: Virtualization is only supported in AArch32 mode. This will also be fixed in a later patch. Contributors: Giacomo Gabrielli (TrustZone, LPAE, system-level AArch64, AArch64 NEON, validation) Thomas Grocutt (AArch32 Virtualization, AArch64 FP, validation) Mbou Eyole (AArch64 NEON, validation) Ali Saidi (AArch64 Linux support, code integration, validation) Edmund Grimley-Evans (AArch64 FP) William Wang (AArch64 Linux support) Rene De Jong (AArch64 Linux support, performance opt.) Matt Horsnell (AArch64 MP, validation) Matt Evans (device models, code integration, validation) Chris Adeniyi-Jones (AArch64 syscall-emulation) Prakash Ramrakhyani (validation) Dam Sunwoo (validation) Chander Sudanthi (validation) Stephan Diestelhorst (validation) Andreas Hansson (code integration, performance opt.) Eric Van Hensbergen (performance opt.) Gabe Black
Diffstat (limited to 'src/arch/arm/isa/formats')
-rw-r--r--src/arch/arm/isa/formats/aarch64.isa2035
-rw-r--r--src/arch/arm/isa/formats/branch.isa66
-rw-r--r--src/arch/arm/isa/formats/formats.isa8
-rw-r--r--src/arch/arm/isa/formats/fp.isa103
-rw-r--r--src/arch/arm/isa/formats/mem.isa2
-rw-r--r--src/arch/arm/isa/formats/misc.isa230
-rw-r--r--src/arch/arm/isa/formats/neon64.isa2626
-rw-r--r--src/arch/arm/isa/formats/uncond.isa15
-rw-r--r--src/arch/arm/isa/formats/unimp.isa23
9 files changed, 4955 insertions, 153 deletions
diff --git a/src/arch/arm/isa/formats/aarch64.isa b/src/arch/arm/isa/formats/aarch64.isa
new file mode 100644
index 000000000..3ed70ce81
--- /dev/null
+++ b/src/arch/arm/isa/formats/aarch64.isa
@@ -0,0 +1,2035 @@
+// Copyright (c) 2011-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: Gabe Black
+// Thomas Grocutt
+// Mbou Eyole
+// Giacomo Gabrielli
+
+output header {{
+namespace Aarch64
+{
+ StaticInstPtr decodeDataProcImm(ExtMachInst machInst);
+ StaticInstPtr decodeBranchExcSys(ExtMachInst machInst);
+ StaticInstPtr decodeLoadsStores(ExtMachInst machInst);
+ StaticInstPtr decodeDataProcReg(ExtMachInst machInst);
+
+ StaticInstPtr decodeFpAdvSIMD(ExtMachInst machInst);
+ StaticInstPtr decodeFp(ExtMachInst machInst);
+ StaticInstPtr decodeAdvSIMD(ExtMachInst machInst);
+ StaticInstPtr decodeAdvSIMDScalar(ExtMachInst machInst);
+
+ StaticInstPtr decodeGem5Ops(ExtMachInst machInst);
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeDataProcImm(ExtMachInst machInst)
+ {
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rdsp = makeSP(rd);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+
+ uint8_t opc = bits(machInst, 30, 29);
+ bool sf = bits(machInst, 31);
+ bool n = bits(machInst, 22);
+ uint8_t immr = bits(machInst, 21, 16);
+ uint8_t imms = bits(machInst, 15, 10);
+ switch (bits(machInst, 25, 23)) {
+ case 0x0:
+ case 0x1:
+ {
+ uint64_t immlo = bits(machInst, 30, 29);
+ uint64_t immhi = bits(machInst, 23, 5);
+ uint64_t imm = (immlo << 0) | (immhi << 2);
+ if (bits(machInst, 31) == 0)
+ return new AdrXImm(machInst, rd, INTREG_ZERO, sext<21>(imm));
+ else
+ return new AdrpXImm(machInst, rd, INTREG_ZERO,
+ sext<33>(imm << 12));
+ }
+ case 0x2:
+ case 0x3:
+ {
+ uint32_t imm12 = bits(machInst, 21, 10);
+ uint8_t shift = bits(machInst, 23, 22);
+ uint32_t imm;
+ if (shift == 0x0)
+ imm = imm12 << 0;
+ else if (shift == 0x1)
+ imm = imm12 << 12;
+ else
+ return new Unknown64(machInst);
+ switch (opc) {
+ case 0x0:
+ return new AddXImm(machInst, rdsp, rnsp, imm);
+ case 0x1:
+ return new AddXImmCc(machInst, rd, rnsp, imm);
+ case 0x2:
+ return new SubXImm(machInst, rdsp, rnsp, imm);
+ case 0x3:
+ return new SubXImmCc(machInst, rd, rnsp, imm);
+ }
+ }
+ case 0x4:
+ {
+ if (!sf && n)
+ return new Unknown64(machInst);
+ // len = MSB(n:NOT(imms)), len < 1 is undefined.
+ uint8_t len = 0;
+ if (n) {
+ len = 6;
+ } else if (imms == 0x3f || imms == 0x3e) {
+ return new Unknown64(machInst);
+ } else {
+ len = findMsbSet(imms ^ 0x3f);
+ }
+ // Generate r, s, and size.
+ uint64_t r = bits(immr, len - 1, 0);
+ uint64_t s = bits(imms, len - 1, 0);
+ uint8_t size = 1 << len;
+ if (s == size - 1)
+ return new Unknown64(machInst);
+ // Generate the pattern with s 1s, rotated by r, with size bits.
+ uint64_t pattern = mask(s + 1);
+ if (r) {
+ pattern = (pattern >> r) | (pattern << (size - r));
+ pattern &= mask(size);
+ }
+ uint8_t width = sf ? 64 : 32;
+ // Replicate that to fill up the immediate.
+ for (unsigned i = 1; i < (width / size); i *= 2)
+ pattern |= (pattern << (i * size));
+ uint64_t imm = pattern;
+
+ switch (opc) {
+ case 0x0:
+ return new AndXImm(machInst, rdsp, rn, imm);
+ case 0x1:
+ return new OrrXImm(machInst, rdsp, rn, imm);
+ case 0x2:
+ return new EorXImm(machInst, rdsp, rn, imm);
+ case 0x3:
+ return new AndXImmCc(machInst, rd, rn, imm);
+ }
+ }
+ case 0x5:
+ {
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ uint32_t imm16 = bits(machInst, 20, 5);
+ uint32_t hw = bits(machInst, 22, 21);
+ switch (opc) {
+ case 0x0:
+ return new Movn(machInst, rd, imm16, hw * 16);
+ case 0x1:
+ return new Unknown64(machInst);
+ case 0x2:
+ return new Movz(machInst, rd, imm16, hw * 16);
+ case 0x3:
+ return new Movk(machInst, rd, imm16, hw * 16);
+ }
+ }
+ case 0x6:
+ if ((sf != n) || (!sf && (bits(immr, 5) || bits(imms, 5))))
+ return new Unknown64(machInst);
+ switch (opc) {
+ case 0x0:
+ return new Sbfm64(machInst, rd, rn, immr, imms);
+ case 0x1:
+ return new Bfm64(machInst, rd, rn, immr, imms);
+ case 0x2:
+ return new Ubfm64(machInst, rd, rn, immr, imms);
+ case 0x3:
+ return new Unknown64(machInst);
+ }
+ case 0x7:
+ {
+ IntRegIndex rm = (IntRegIndex)(uint8_t)bits(machInst, 20, 16);
+ if (opc || bits(machInst, 21))
+ return new Unknown64(machInst);
+ else
+ return new Extr64(machInst, rd, rn, rm, imms);
+ }
+ }
+ return new FailUnimplemented("Unhandled Case8", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeBranchExcSys(ExtMachInst machInst)
+ {
+ switch (bits(machInst, 30, 29)) {
+ case 0x0:
+ {
+ int64_t imm = sext<26>(bits(machInst, 25, 0)) << 2;
+ if (bits(machInst, 31) == 0)
+ return new B64(machInst, imm);
+ else
+ return new Bl64(machInst, imm);
+ }
+ case 0x1:
+ {
+ IntRegIndex rt = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ if (bits(machInst, 25) == 0) {
+ int64_t imm = sext<19>(bits(machInst, 23, 5)) << 2;
+ if (bits(machInst, 24) == 0)
+ return new Cbz64(machInst, imm, rt);
+ else
+ return new Cbnz64(machInst, imm, rt);
+ } else {
+ uint64_t bitmask = 0x1;
+ bitmask <<= bits(machInst, 23, 19);
+ int64_t imm = sext<14>(bits(machInst, 18, 5)) << 2;
+ if (bits(machInst, 31))
+ bitmask <<= 32;
+ if (bits(machInst, 24) == 0)
+ return new Tbz64(machInst, bitmask, imm, rt);
+ else
+ return new Tbnz64(machInst, bitmask, imm, rt);
+ }
+ }
+ case 0x2:
+ // bit 30:26=10101
+ if (bits(machInst, 31) == 0) {
+ if (bits(machInst, 25, 24) || bits(machInst, 4))
+ return new Unknown64(machInst);
+ int64_t imm = sext<19>(bits(machInst, 23, 5)) << 2;
+ ConditionCode condCode =
+ (ConditionCode)(uint8_t)(bits(machInst, 3, 0));
+ return new BCond64(machInst, imm, condCode);
+ } else if (bits(machInst, 25, 24) == 0x0) {
+ if (bits(machInst, 4, 2))
+ return new Unknown64(machInst);
+ uint8_t decVal = (bits(machInst, 1, 0) << 0) |
+ (bits(machInst, 23, 21) << 2);
+ switch (decVal) {
+ case 0x01:
+ return new Svc64(machInst);
+ case 0x02:
+ return new FailUnimplemented("hvc", machInst);
+ case 0x03:
+ return new Smc64(machInst);
+ case 0x04:
+ return new FailUnimplemented("brk", machInst);
+ case 0x08:
+ return new FailUnimplemented("hlt", machInst);
+ case 0x15:
+ return new FailUnimplemented("dcps1", machInst);
+ case 0x16:
+ return new FailUnimplemented("dcps2", machInst);
+ case 0x17:
+ return new FailUnimplemented("dcps3", machInst);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 25, 22) == 0x4) {
+ // bit 31:22=1101010100
+ bool l = bits(machInst, 21);
+ uint8_t op0 = bits(machInst, 20, 19);
+ uint8_t op1 = bits(machInst, 18, 16);
+ uint8_t crn = bits(machInst, 15, 12);
+ uint8_t crm = bits(machInst, 11, 8);
+ uint8_t op2 = bits(machInst, 7, 5);
+ IntRegIndex rt = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ switch (op0) {
+ case 0x0:
+ if (rt != 0x1f || l)
+ return new Unknown64(machInst);
+ if (crn == 0x2 && op1 == 0x3) {
+ switch (op2) {
+ case 0x0:
+ return new NopInst(machInst);
+ case 0x1:
+ return new YieldInst(machInst);
+ case 0x2:
+ return new WfeInst(machInst);
+ case 0x3:
+ return new WfiInst(machInst);
+ case 0x4:
+ return new SevInst(machInst);
+ case 0x5:
+ return new SevlInst(machInst);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (crn == 0x3 && op1 == 0x3) {
+ switch (op2) {
+ case 0x2:
+ return new Clrex64(machInst);
+ case 0x4:
+ return new Dsb64(machInst);
+ case 0x5:
+ return new Dmb64(machInst);
+ case 0x6:
+ return new Isb64(machInst);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (crn == 0x4) {
+ // MSR immediate
+ switch (op1 << 3 | op2) {
+ case 0x5:
+ // SP
+ return new MsrSP64(machInst,
+ (IntRegIndex) MISCREG_SPSEL,
+ INTREG_ZERO,
+ crm & 0x1);
+ case 0x1e:
+ // DAIFSet
+ return new MsrDAIFSet64(
+ machInst,
+ (IntRegIndex) MISCREG_DAIF,
+ INTREG_ZERO,
+ crm);
+ case 0x1f:
+ // DAIFClr
+ return new MsrDAIFClr64(
+ machInst,
+ (IntRegIndex) MISCREG_DAIF,
+ INTREG_ZERO,
+ crm);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else {
+ return new Unknown64(machInst);
+ }
+ break;
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ {
+ // bit 31:22=1101010100, 20:19=11
+ bool read = l;
+ MiscRegIndex miscReg =
+ decodeAArch64SysReg(op0, op1, crn, crm, op2);
+ if (read) {
+ if ((miscReg == MISCREG_DC_CIVAC_Xt) ||
+ (miscReg == MISCREG_DC_CVAC_Xt) ||
+ (miscReg == MISCREG_DC_ZVA_Xt)) {
+ return new Unknown64(machInst);
+ }
+ }
+ // Check for invalid registers
+ if (miscReg == MISCREG_UNKNOWN) {
+ return new Unknown64(machInst);
+ } else if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) {
+ if (miscReg == MISCREG_NZCV) {
+ if (read)
+ return new MrsNZCV64(machInst, rt, (IntRegIndex) miscReg);
+ else
+ return new MsrNZCV64(machInst, (IntRegIndex) miscReg, rt);
+ }
+ uint32_t iss = msrMrs64IssBuild(read, op0, op1, crn, crm, op2, rt);
+ if (miscReg == MISCREG_DC_ZVA_Xt && !read)
+ return new Dczva(machInst, rt, (IntRegIndex) miscReg, iss);
+
+ if (read)
+ return new Mrs64(machInst, rt, (IntRegIndex) miscReg, iss);
+ else
+ return new Msr64(machInst, (IntRegIndex) miscReg, rt, iss);
+ } else if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
+ std::string full_mnem = csprintf("%s %s",
+ read ? "mrs" : "msr", miscRegName[miscReg]);
+ return new WarnUnimplemented(read ? "mrs" : "msr",
+ machInst, full_mnem);
+ } else {
+ return new FailUnimplemented(csprintf("%s %s",
+ read ? "mrs" : "msr", miscRegName[miscReg]).c_str(),
+ machInst);
+ }
+ }
+ break;
+ }
+ } else if (bits(machInst, 25) == 0x1) {
+ uint8_t opc = bits(machInst, 24, 21);
+ uint8_t op2 = bits(machInst, 20, 16);
+ uint8_t op3 = bits(machInst, 15, 10);
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ uint8_t op4 = bits(machInst, 4, 0);
+ if (op2 != 0x1f || op3 != 0x0 || op4 != 0x0)
+ return new Unknown64(machInst);
+ switch (opc) {
+ case 0x0:
+ return new Br64(machInst, rn);
+ case 0x1:
+ return new Blr64(machInst, rn);
+ case 0x2:
+ return new Ret64(machInst, rn);
+ case 0x4:
+ if (rn != 0x1f)
+ return new Unknown64(machInst);
+ return new Eret64(machInst);
+ case 0x5:
+ if (rn != 0x1f)
+ return new Unknown64(machInst);
+ return new FailUnimplemented("dret", machInst);
+ }
+ }
+ default:
+ return new Unknown64(machInst);
+ }
+ return new FailUnimplemented("Unhandled Case7", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeLoadsStores(ExtMachInst machInst)
+ {
+ // bit 27,25=10
+ switch (bits(machInst, 29, 28)) {
+ case 0x0:
+ if (bits(machInst, 26) == 0) {
+ if (bits(machInst, 24) != 0)
+ return new Unknown64(machInst);
+ IntRegIndex rt = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ IntRegIndex rt2 = (IntRegIndex)(uint8_t)bits(machInst, 14, 10);
+ IntRegIndex rs = (IntRegIndex)(uint8_t)bits(machInst, 20, 16);
+ uint8_t opc = (bits(machInst, 15) << 0) |
+ (bits(machInst, 23, 21) << 1);
+ uint8_t size = bits(machInst, 31, 30);
+ switch (opc) {
+ case 0x0:
+ switch (size) {
+ case 0x0:
+ return new STXRB64(machInst, rt, rnsp, rs);
+ case 0x1:
+ return new STXRH64(machInst, rt, rnsp, rs);
+ case 0x2:
+ return new STXRW64(machInst, rt, rnsp, rs);
+ case 0x3:
+ return new STXRX64(machInst, rt, rnsp, rs);
+ }
+ case 0x1:
+ switch (size) {
+ case 0x0:
+ return new STLXRB64(machInst, rt, rnsp, rs);
+ case 0x1:
+ return new STLXRH64(machInst, rt, rnsp, rs);
+ case 0x2:
+ return new STLXRW64(machInst, rt, rnsp, rs);
+ case 0x3:
+ return new STLXRX64(machInst, rt, rnsp, rs);
+ }
+ case 0x2:
+ switch (size) {
+ case 0x0:
+ case 0x1:
+ return new Unknown64(machInst);
+ case 0x2:
+ return new STXPW64(machInst, rs, rt, rt2, rnsp);
+ case 0x3:
+ return new STXPX64(machInst, rs, rt, rt2, rnsp);
+ }
+
+ case 0x3:
+ switch (size) {
+ case 0x0:
+ case 0x1:
+ return new Unknown64(machInst);
+ case 0x2:
+ return new STLXPW64(machInst, rs, rt, rt2, rnsp);
+ case 0x3:
+ return new STLXPX64(machInst, rs, rt, rt2, rnsp);
+ }
+
+ case 0x4:
+ switch (size) {
+ case 0x0:
+ return new LDXRB64(machInst, rt, rnsp, rs);
+ case 0x1:
+ return new LDXRH64(machInst, rt, rnsp, rs);
+ case 0x2:
+ return new LDXRW64(machInst, rt, rnsp, rs);
+ case 0x3:
+ return new LDXRX64(machInst, rt, rnsp, rs);
+ }
+ case 0x5:
+ switch (size) {
+ case 0x0:
+ return new LDAXRB64(machInst, rt, rnsp, rs);
+ case 0x1:
+ return new LDAXRH64(machInst, rt, rnsp, rs);
+ case 0x2:
+ return new LDAXRW64(machInst, rt, rnsp, rs);
+ case 0x3:
+ return new LDAXRX64(machInst, rt, rnsp, rs);
+ }
+ case 0x6:
+ switch (size) {
+ case 0x0:
+ case 0x1:
+ return new Unknown64(machInst);
+ case 0x2:
+ return new LDXPW64(machInst, rt, rt2, rnsp);
+ case 0x3:
+ return new LDXPX64(machInst, rt, rt2, rnsp);
+ }
+
+ case 0x7:
+ switch (size) {
+ case 0x0:
+ case 0x1:
+ return new Unknown64(machInst);
+ case 0x2:
+ return new LDAXPW64(machInst, rt, rt2, rnsp);
+ case 0x3:
+ return new LDAXPX64(machInst, rt, rt2, rnsp);
+ }
+
+ case 0x9:
+ switch (size) {
+ case 0x0:
+ return new STLRB64(machInst, rt, rnsp);
+ case 0x1:
+ return new STLRH64(machInst, rt, rnsp);
+ case 0x2:
+ return new STLRW64(machInst, rt, rnsp);
+ case 0x3:
+ return new STLRX64(machInst, rt, rnsp);
+ }
+ case 0xd:
+ switch (size) {
+ case 0x0:
+ return new LDARB64(machInst, rt, rnsp);
+ case 0x1:
+ return new LDARH64(machInst, rt, rnsp);
+ case 0x2:
+ return new LDARW64(machInst, rt, rnsp);
+ case 0x3:
+ return new LDARX64(machInst, rt, rnsp);
+ }
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 31)) {
+ return new Unknown64(machInst);
+ } else {
+ return decodeNeonMem(machInst);
+ }
+ case 0x1:
+ {
+ if (bits(machInst, 24) != 0)
+ return new Unknown64(machInst);
+ uint8_t switchVal = (bits(machInst, 26) << 0) |
+ (bits(machInst, 31, 30) << 1);
+ int64_t imm = sext<19>(bits(machInst, 23, 5)) << 2;
+ IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ switch (switchVal) {
+ case 0x0:
+ return new LDRWL64_LIT(machInst, rt, imm);
+ case 0x1:
+ return new LDRSFP64_LIT(machInst, rt, imm);
+ case 0x2:
+ return new LDRXL64_LIT(machInst, rt, imm);
+ case 0x3:
+ return new LDRDFP64_LIT(machInst, rt, imm);
+ case 0x4:
+ return new LDRSWL64_LIT(machInst, rt, imm);
+ case 0x5:
+ return new BigFpMemLit("ldr", machInst, rt, imm);
+ case 0x6:
+ return new PRFM64_LIT(machInst, rt, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x2:
+ {
+ uint8_t opc = bits(machInst, 31, 30);
+ if (opc >= 3)
+ return new Unknown64(machInst);
+ uint32_t size = 0;
+ bool fp = bits(machInst, 26);
+ bool load = bits(machInst, 22);
+ if (fp) {
+ size = 4 << opc;
+ } else {
+ if ((opc == 1) && !load)
+ return new Unknown64(machInst);
+ size = (opc == 0 || opc == 1) ? 4 : 8;
+ }
+ uint8_t type = bits(machInst, 24, 23);
+ int64_t imm = sext<7>(bits(machInst, 21, 15)) * size;
+
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ IntRegIndex rt = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ IntRegIndex rt2 = (IntRegIndex)(uint8_t)bits(machInst, 14, 10);
+
+ bool noAlloc = (type == 0);
+ bool signExt = !noAlloc && !fp && opc == 1;
+ PairMemOp::AddrMode mode;
+ const char *mnemonic = NULL;
+ switch (type) {
+ case 0x0:
+ case 0x2:
+ mode = PairMemOp::AddrMd_Offset;
+ break;
+ case 0x1:
+ mode = PairMemOp::AddrMd_PostIndex;
+ break;
+ case 0x3:
+ mode = PairMemOp::AddrMd_PreIndex;
+ break;
+ default:
+ return new Unknown64(machInst);
+ }
+ if (load) {
+ if (noAlloc)
+ mnemonic = "ldnp";
+ else if (signExt)
+ mnemonic = "ldpsw";
+ else
+ mnemonic = "ldp";
+ } else {
+ if (noAlloc)
+ mnemonic = "stnp";
+ else
+ mnemonic = "stp";
+ }
+
+ return new LdpStp(mnemonic, machInst, size, fp, load, noAlloc,
+ signExt, false, false, imm, mode, rn, rt, rt2);
+ }
+ // bit 29:27=111, 25=0
+ case 0x3:
+ {
+ uint8_t switchVal = (bits(machInst, 23, 22) << 0) |
+ (bits(machInst, 26) << 2) |
+ (bits(machInst, 31, 30) << 3);
+ if (bits(machInst, 24) == 1) {
+ uint64_t imm12 = bits(machInst, 21, 10);
+ IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ switch (switchVal) {
+ case 0x00:
+ return new STRB64_IMM(machInst, rt, rnsp, imm12);
+ case 0x01:
+ return new LDRB64_IMM(machInst, rt, rnsp, imm12);
+ case 0x02:
+ return new LDRSBX64_IMM(machInst, rt, rnsp, imm12);
+ case 0x03:
+ return new LDRSBW64_IMM(machInst, rt, rnsp, imm12);
+ case 0x04:
+ return new STRBFP64_IMM(machInst, rt, rnsp, imm12);
+ case 0x05:
+ return new LDRBFP64_IMM(machInst, rt, rnsp, imm12);
+ case 0x06:
+ return new BigFpMemImm("str", machInst, false,
+ rt, rnsp, imm12 << 4);
+ case 0x07:
+ return new BigFpMemImm("ldr", machInst, true,
+ rt, rnsp, imm12 << 4);
+ case 0x08:
+ return new STRH64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x09:
+ return new LDRH64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x0a:
+ return new LDRSHX64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x0b:
+ return new LDRSHW64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x0c:
+ return new STRHFP64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x0d:
+ return new LDRHFP64_IMM(machInst, rt, rnsp, imm12 << 1);
+ case 0x10:
+ return new STRW64_IMM(machInst, rt, rnsp, imm12 << 2);
+ case 0x11:
+ return new LDRW64_IMM(machInst, rt, rnsp, imm12 << 2);
+ case 0x12:
+ return new LDRSW64_IMM(machInst, rt, rnsp, imm12 << 2);
+ case 0x14:
+ return new STRSFP64_IMM(machInst, rt, rnsp, imm12 << 2);
+ case 0x15:
+ return new LDRSFP64_IMM(machInst, rt, rnsp, imm12 << 2);
+ case 0x18:
+ return new STRX64_IMM(machInst, rt, rnsp, imm12 << 3);
+ case 0x19:
+ return new LDRX64_IMM(machInst, rt, rnsp, imm12 << 3);
+ case 0x1a:
+ return new PRFM64_IMM(machInst, rt, rnsp, imm12 << 3);
+ case 0x1c:
+ return new STRDFP64_IMM(machInst, rt, rnsp, imm12 << 3);
+ case 0x1d:
+ return new LDRDFP64_IMM(machInst, rt, rnsp, imm12 << 3);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 21) == 1) {
+ if (bits(machInst, 11, 10) != 0x2)
+ return new Unknown64(machInst);
+ if (!bits(machInst, 14))
+ return new Unknown64(machInst);
+ IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16);
+ ArmExtendType type =
+ (ArmExtendType)(uint32_t)bits(machInst, 15, 13);
+ uint8_t s = bits(machInst, 12);
+ switch (switchVal) {
+ case 0x00:
+ return new STRB64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x01:
+ return new LDRB64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x02:
+ return new LDRSBX64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x03:
+ return new LDRSBW64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x04:
+ return new STRBFP64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x05:
+ return new LDRBFP64_REG(machInst, rt, rnsp, rm, type, 0);
+ case 0x6:
+ return new BigFpMemReg("str", machInst, false,
+ rt, rnsp, rm, type, s * 4);
+ case 0x7:
+ return new BigFpMemReg("ldr", machInst, true,
+ rt, rnsp, rm, type, s * 4);
+ case 0x08:
+ return new STRH64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x09:
+ return new LDRH64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x0a:
+ return new LDRSHX64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x0b:
+ return new LDRSHW64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x0c:
+ return new STRHFP64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x0d:
+ return new LDRHFP64_REG(machInst, rt, rnsp, rm, type, s);
+ case 0x10:
+ return new STRW64_REG(machInst, rt, rnsp, rm, type, s * 2);
+ case 0x11:
+ return new LDRW64_REG(machInst, rt, rnsp, rm, type, s * 2);
+ case 0x12:
+ return new LDRSW64_REG(machInst, rt, rnsp, rm, type, s * 2);
+ case 0x14:
+ return new STRSFP64_REG(machInst, rt, rnsp, rm, type, s * 2);
+ case 0x15:
+ return new LDRSFP64_REG(machInst, rt, rnsp, rm, type, s * 2);
+ case 0x18:
+ return new STRX64_REG(machInst, rt, rnsp, rm, type, s * 3);
+ case 0x19:
+ return new LDRX64_REG(machInst, rt, rnsp, rm, type, s * 3);
+ case 0x1a:
+ return new PRFM64_REG(machInst, rt, rnsp, rm, type, s * 3);
+ case 0x1c:
+ return new STRDFP64_REG(machInst, rt, rnsp, rm, type, s * 3);
+ case 0x1d:
+ return new LDRDFP64_REG(machInst, rt, rnsp, rm, type, s * 3);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else {
+ // bit 29:27=111, 25:24=00, 21=0
+ switch (bits(machInst, 11, 10)) {
+ case 0x0:
+ {
+ IntRegIndex rt =
+ (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn =
+ (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ uint64_t imm = sext<9>(bits(machInst, 20, 12));
+ switch (switchVal) {
+ case 0x00:
+ return new STURB64_IMM(machInst, rt, rnsp, imm);
+ case 0x01:
+ return new LDURB64_IMM(machInst, rt, rnsp, imm);
+ case 0x02:
+ return new LDURSBX64_IMM(machInst, rt, rnsp, imm);
+ case 0x03:
+ return new LDURSBW64_IMM(machInst, rt, rnsp, imm);
+ case 0x04:
+ return new STURBFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x05:
+ return new LDURBFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x06:
+ return new BigFpMemImm("stur", machInst, false,
+ rt, rnsp, imm);
+ case 0x07:
+ return new BigFpMemImm("ldur", machInst, true,
+ rt, rnsp, imm);
+ case 0x08:
+ return new STURH64_IMM(machInst, rt, rnsp, imm);
+ case 0x09:
+ return new LDURH64_IMM(machInst, rt, rnsp, imm);
+ case 0x0a:
+ return new LDURSHX64_IMM(machInst, rt, rnsp, imm);
+ case 0x0b:
+ return new LDURSHW64_IMM(machInst, rt, rnsp, imm);
+ case 0x0c:
+ return new STURHFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x0d:
+ return new LDURHFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x10:
+ return new STURW64_IMM(machInst, rt, rnsp, imm);
+ case 0x11:
+ return new LDURW64_IMM(machInst, rt, rnsp, imm);
+ case 0x12:
+ return new LDURSW64_IMM(machInst, rt, rnsp, imm);
+ case 0x14:
+ return new STURSFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x15:
+ return new LDURSFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x18:
+ return new STURX64_IMM(machInst, rt, rnsp, imm);
+ case 0x19:
+ return new LDURX64_IMM(machInst, rt, rnsp, imm);
+ case 0x1a:
+ return new PRFUM64_IMM(machInst, rt, rnsp, imm);
+ case 0x1c:
+ return new STURDFP64_IMM(machInst, rt, rnsp, imm);
+ case 0x1d:
+ return new LDURDFP64_IMM(machInst, rt, rnsp, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ // bit 29:27=111, 25:24=00, 21=0, 11:10=01
+ case 0x1:
+ {
+ IntRegIndex rt =
+ (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn =
+ (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ uint64_t imm = sext<9>(bits(machInst, 20, 12));
+ switch (switchVal) {
+ case 0x00:
+ return new STRB64_POST(machInst, rt, rnsp, imm);
+ case 0x01:
+ return new LDRB64_POST(machInst, rt, rnsp, imm);
+ case 0x02:
+ return new LDRSBX64_POST(machInst, rt, rnsp, imm);
+ case 0x03:
+ return new LDRSBW64_POST(machInst, rt, rnsp, imm);
+ case 0x04:
+ return new STRBFP64_POST(machInst, rt, rnsp, imm);
+ case 0x05:
+ return new LDRBFP64_POST(machInst, rt, rnsp, imm);
+ case 0x06:
+ return new BigFpMemPost("str", machInst, false,
+ rt, rnsp, imm);
+ case 0x07:
+ return new BigFpMemPost("ldr", machInst, true,
+ rt, rnsp, imm);
+ case 0x08:
+ return new STRH64_POST(machInst, rt, rnsp, imm);
+ case 0x09:
+ return new LDRH64_POST(machInst, rt, rnsp, imm);
+ case 0x0a:
+ return new LDRSHX64_POST(machInst, rt, rnsp, imm);
+ case 0x0b:
+ return new LDRSHW64_POST(machInst, rt, rnsp, imm);
+ case 0x0c:
+ return new STRHFP64_POST(machInst, rt, rnsp, imm);
+ case 0x0d:
+ return new LDRHFP64_POST(machInst, rt, rnsp, imm);
+ case 0x10:
+ return new STRW64_POST(machInst, rt, rnsp, imm);
+ case 0x11:
+ return new LDRW64_POST(machInst, rt, rnsp, imm);
+ case 0x12:
+ return new LDRSW64_POST(machInst, rt, rnsp, imm);
+ case 0x14:
+ return new STRSFP64_POST(machInst, rt, rnsp, imm);
+ case 0x15:
+ return new LDRSFP64_POST(machInst, rt, rnsp, imm);
+ case 0x18:
+ return new STRX64_POST(machInst, rt, rnsp, imm);
+ case 0x19:
+ return new LDRX64_POST(machInst, rt, rnsp, imm);
+ case 0x1c:
+ return new STRDFP64_POST(machInst, rt, rnsp, imm);
+ case 0x1d:
+ return new LDRDFP64_POST(machInst, rt, rnsp, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x2:
+ {
+ IntRegIndex rt =
+ (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn =
+ (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ uint64_t imm = sext<9>(bits(machInst, 20, 12));
+ switch (switchVal) {
+ case 0x00:
+ return new STTRB64_IMM(machInst, rt, rnsp, imm);
+ case 0x01:
+ return new LDTRB64_IMM(machInst, rt, rnsp, imm);
+ case 0x02:
+ return new LDTRSBX64_IMM(machInst, rt, rnsp, imm);
+ case 0x03:
+ return new LDTRSBW64_IMM(machInst, rt, rnsp, imm);
+ case 0x08:
+ return new STTRH64_IMM(machInst, rt, rnsp, imm);
+ case 0x09:
+ return new LDTRH64_IMM(machInst, rt, rnsp, imm);
+ case 0x0a:
+ return new LDTRSHX64_IMM(machInst, rt, rnsp, imm);
+ case 0x0b:
+ return new LDTRSHW64_IMM(machInst, rt, rnsp, imm);
+ case 0x10:
+ return new STTRW64_IMM(machInst, rt, rnsp, imm);
+ case 0x11:
+ return new LDTRW64_IMM(machInst, rt, rnsp, imm);
+ case 0x12:
+ return new LDTRSW64_IMM(machInst, rt, rnsp, imm);
+ case 0x18:
+ return new STTRX64_IMM(machInst, rt, rnsp, imm);
+ case 0x19:
+ return new LDTRX64_IMM(machInst, rt, rnsp, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x3:
+ {
+ IntRegIndex rt =
+ (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn =
+ (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ uint64_t imm = sext<9>(bits(machInst, 20, 12));
+ switch (switchVal) {
+ case 0x00:
+ return new STRB64_PRE(machInst, rt, rnsp, imm);
+ case 0x01:
+ return new LDRB64_PRE(machInst, rt, rnsp, imm);
+ case 0x02:
+ return new LDRSBX64_PRE(machInst, rt, rnsp, imm);
+ case 0x03:
+ return new LDRSBW64_PRE(machInst, rt, rnsp, imm);
+ case 0x04:
+ return new STRBFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x05:
+ return new LDRBFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x06:
+ return new BigFpMemPre("str", machInst, false,
+ rt, rnsp, imm);
+ case 0x07:
+ return new BigFpMemPre("ldr", machInst, true,
+ rt, rnsp, imm);
+ case 0x08:
+ return new STRH64_PRE(machInst, rt, rnsp, imm);
+ case 0x09:
+ return new LDRH64_PRE(machInst, rt, rnsp, imm);
+ case 0x0a:
+ return new LDRSHX64_PRE(machInst, rt, rnsp, imm);
+ case 0x0b:
+ return new LDRSHW64_PRE(machInst, rt, rnsp, imm);
+ case 0x0c:
+ return new STRHFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x0d:
+ return new LDRHFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x10:
+ return new STRW64_PRE(machInst, rt, rnsp, imm);
+ case 0x11:
+ return new LDRW64_PRE(machInst, rt, rnsp, imm);
+ case 0x12:
+ return new LDRSW64_PRE(machInst, rt, rnsp, imm);
+ case 0x14:
+ return new STRSFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x15:
+ return new LDRSFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x18:
+ return new STRX64_PRE(machInst, rt, rnsp, imm);
+ case 0x19:
+ return new LDRX64_PRE(machInst, rt, rnsp, imm);
+ case 0x1c:
+ return new STRDFP64_PRE(machInst, rt, rnsp, imm);
+ case 0x1d:
+ return new LDRDFP64_PRE(machInst, rt, rnsp, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ }
+ }
+ }
+ }
+ return new FailUnimplemented("Unhandled Case1", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeDataProcReg(ExtMachInst machInst)
+ {
+ uint8_t switchVal = (bits(machInst, 28) << 1) |
+ (bits(machInst, 24) << 0);
+ switch (switchVal) {
+ case 0x0:
+ {
+ uint8_t switchVal = (bits(machInst, 21) << 0) |
+ (bits(machInst, 30, 29) << 1);
+ ArmShiftType type = (ArmShiftType)(uint8_t)bits(machInst, 23, 22);
+ uint8_t imm6 = bits(machInst, 15, 10);
+ bool sf = bits(machInst, 31);
+ if (!sf && (imm6 & 0x20))
+ return new Unknown64(machInst);
+ IntRegIndex rd = (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);
+
+ switch (switchVal) {
+ case 0x0:
+ return new AndXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x1:
+ return new BicXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x2:
+ return new OrrXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x3:
+ return new OrnXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x4:
+ return new EorXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x5:
+ return new EonXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x6:
+ return new AndXSRegCc(machInst, rd, rn, rm, imm6, type);
+ case 0x7:
+ return new BicXSRegCc(machInst, rd, rn, rm, imm6, type);
+ }
+ }
+ case 0x1:
+ {
+ uint8_t switchVal = bits(machInst, 30, 29);
+ if (bits(machInst, 21) == 0) {
+ ArmShiftType type =
+ (ArmShiftType)(uint8_t)bits(machInst, 23, 22);
+ if (type == ROR)
+ return new Unknown64(machInst);
+ uint8_t imm6 = bits(machInst, 15, 10);
+ if (!bits(machInst, 31) && bits(imm6, 5))
+ return new Unknown64(machInst);
+ IntRegIndex rd = (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);
+ switch (switchVal) {
+ case 0x0:
+ return new AddXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x1:
+ return new AddXSRegCc(machInst, rd, rn, rm, imm6, type);
+ case 0x2:
+ return new SubXSReg(machInst, rd, rn, rm, imm6, type);
+ case 0x3:
+ return new SubXSRegCc(machInst, rd, rn, rm, imm6, type);
+ }
+ } else {
+ if (bits(machInst, 23, 22) != 0 || bits(machInst, 12, 10) > 0x4)
+ return new Unknown64(machInst);
+ ArmExtendType type =
+ (ArmExtendType)(uint8_t)bits(machInst, 15, 13);
+ uint8_t imm3 = bits(machInst, 12, 10);
+ IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ IntRegIndex rdsp = makeSP(rd);
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ IntRegIndex rnsp = makeSP(rn);
+ IntRegIndex rm = (IntRegIndex)(uint8_t)bits(machInst, 20, 16);
+
+ switch (switchVal) {
+ case 0x0:
+ return new AddXEReg(machInst, rdsp, rnsp, rm, type, imm3);
+ case 0x1:
+ return new AddXERegCc(machInst, rd, rnsp, rm, type, imm3);
+ case 0x2:
+ return new SubXEReg(machInst, rdsp, rnsp, rm, type, imm3);
+ case 0x3:
+ return new SubXERegCc(machInst, rd, rnsp, rm, type, imm3);
+ }
+ }
+ }
+ case 0x2:
+ {
+ if (bits(machInst, 21) == 1)
+ return new Unknown64(machInst);
+ IntRegIndex rd = (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);
+ switch (bits(machInst, 23, 22)) {
+ case 0x0:
+ {
+ if (bits(machInst, 15, 10))
+ return new Unknown64(machInst);
+ uint8_t switchVal = bits(machInst, 30, 29);
+ switch (switchVal) {
+ case 0x0:
+ return new AdcXSReg(machInst, rd, rn, rm, 0, LSL);
+ case 0x1:
+ return new AdcXSRegCc(machInst, rd, rn, rm, 0, LSL);
+ case 0x2:
+ return new SbcXSReg(machInst, rd, rn, rm, 0, LSL);
+ case 0x3:
+ return new SbcXSRegCc(machInst, rd, rn, rm, 0, LSL);
+ }
+ }
+ case 0x1:
+ {
+ if ((bits(machInst, 4) == 1) ||
+ (bits(machInst, 10) == 1) ||
+ (bits(machInst, 29) == 0)) {
+ return new Unknown64(machInst);
+ }
+ ConditionCode cond =
+ (ConditionCode)(uint8_t)bits(machInst, 15, 12);
+ uint8_t flags = bits(machInst, 3, 0);
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ if (bits(machInst, 11) == 0) {
+ IntRegIndex rm =
+ (IntRegIndex)(uint8_t)bits(machInst, 20, 16);
+ if (bits(machInst, 30) == 0) {
+ return new CcmnReg64(machInst, rn, rm, cond, flags);
+ } else {
+ return new CcmpReg64(machInst, rn, rm, cond, flags);
+ }
+ } else {
+ uint8_t imm5 = bits(machInst, 20, 16);
+ if (bits(machInst, 30) == 0) {
+ return new CcmnImm64(machInst, rn, imm5, cond, flags);
+ } else {
+ return new CcmpImm64(machInst, rn, imm5, cond, flags);
+ }
+ }
+ }
+ case 0x2:
+ {
+ if (bits(machInst, 29) == 1 ||
+ bits(machInst, 11) == 1) {
+ return new Unknown64(machInst);
+ }
+ uint8_t switchVal = (bits(machInst, 10) << 0) |
+ (bits(machInst, 30) << 1);
+ IntRegIndex rd = (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);
+ ConditionCode cond =
+ (ConditionCode)(uint8_t)bits(machInst, 15, 12);
+ switch (switchVal) {
+ case 0x0:
+ return new Csel64(machInst, rd, rn, rm, cond);
+ case 0x1:
+ return new Csinc64(machInst, rd, rn, rm, cond);
+ case 0x2:
+ return new Csinv64(machInst, rd, rn, rm, cond);
+ case 0x3:
+ return new Csneg64(machInst, rd, rn, rm, cond);
+ }
+ }
+ case 0x3:
+ if (bits(machInst, 30) == 0) {
+ if (bits(machInst, 29) != 0)
+ return new Unknown64(machInst);
+ uint8_t switchVal = bits(machInst, 15, 10);
+ switch (switchVal) {
+ case 0x2:
+ return new Udiv64(machInst, rd, rn, rm);
+ case 0x3:
+ return new Sdiv64(machInst, rd, rn, rm);
+ case 0x8:
+ return new Lslv64(machInst, rd, rn, rm);
+ case 0x9:
+ return new Lsrv64(machInst, rd, rn, rm);
+ case 0xa:
+ return new Asrv64(machInst, rd, rn, rm);
+ case 0xb:
+ return new Rorv64(machInst, rd, rn, rm);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else {
+ if (bits(machInst, 20, 16) != 0 ||
+ bits(machInst, 29) != 0) {
+ return new Unknown64(machInst);
+ }
+ uint8_t switchVal = bits(machInst, 15, 10);
+ switch (switchVal) {
+ case 0x0:
+ return new Rbit64(machInst, rd, rn);
+ case 0x1:
+ return new Rev1664(machInst, rd, rn);
+ case 0x2:
+ if (bits(machInst, 31) == 0)
+ return new Rev64(machInst, rd, rn);
+ else
+ return new Rev3264(machInst, rd, rn);
+ case 0x3:
+ if (bits(machInst, 31) != 1)
+ return new Unknown64(machInst);
+ return new Rev64(machInst, rd, rn);
+ case 0x4:
+ return new Clz64(machInst, rd, rn);
+ case 0x5:
+ return new Cls64(machInst, rd, rn);
+ }
+ }
+ }
+ }
+ case 0x3:
+ {
+ if (bits(machInst, 30, 29) != 0x0 ||
+ (bits(machInst, 23, 21) != 0 && bits(machInst, 31) == 0))
+ return new Unknown64(machInst);
+ IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5);
+ IntRegIndex ra = (IntRegIndex)(uint8_t)bits(machInst, 14, 10);
+ IntRegIndex rm = (IntRegIndex)(uint8_t)bits(machInst, 20, 16);
+ switch (bits(machInst, 23, 21)) {
+ case 0x0:
+ if (bits(machInst, 15) == 0)
+ return new Madd64(machInst, rd, ra, rn, rm);
+ else
+ return new Msub64(machInst, rd, ra, rn, rm);
+ case 0x1:
+ if (bits(machInst, 15) == 0)
+ return new Smaddl64(machInst, rd, ra, rn, rm);
+ else
+ return new Smsubl64(machInst, rd, ra, rn, rm);
+ case 0x2:
+ if (bits(machInst, 15) != 0)
+ return new Unknown64(machInst);
+ return new Smulh64(machInst, rd, rn, rm);
+ case 0x5:
+ if (bits(machInst, 15) == 0)
+ return new Umaddl64(machInst, rd, ra, rn, rm);
+ else
+ return new Umsubl64(machInst, rd, ra, rn, rm);
+ case 0x6:
+ if (bits(machInst, 15) != 0)
+ return new Unknown64(machInst);
+ return new Umulh64(machInst, rd, rn, rm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ }
+ return new FailUnimplemented("Unhandled Case2", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeAdvSIMD(ExtMachInst machInst)
+ {
+ if (bits(machInst, 24) == 1) {
+ if (bits(machInst, 10) == 0) {
+ return decodeNeonIndexedElem(machInst);
+ } else if (bits(machInst, 23) == 1) {
+ return new Unknown64(machInst);
+ } else {
+ if (bits(machInst, 22, 19)) {
+ return decodeNeonShiftByImm(machInst);
+ } else {
+ return decodeNeonModImm(machInst);
+ }
+ }
+ } else if (bits(machInst, 21) == 1) {
+ if (bits(machInst, 10) == 1) {
+ return decodeNeon3Same(machInst);
+ } else if (bits(machInst, 11) == 0) {
+ return decodeNeon3Diff(machInst);
+ } else if (bits(machInst, 20, 17) == 0x0) {
+ return decodeNeon2RegMisc(machInst);
+ } else if (bits(machInst, 20, 17) == 0x8) {
+ return decodeNeonAcrossLanes(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 24) ||
+ bits(machInst, 21) ||
+ bits(machInst, 15)) {
+ return new Unknown64(machInst);
+ } else if (bits(machInst, 10) == 1) {
+ if (bits(machInst, 23, 22))
+ return new Unknown64(machInst);
+ return decodeNeonCopy(machInst);
+ } else if (bits(machInst, 29) == 1) {
+ return decodeNeonExt(machInst);
+ } else if (bits(machInst, 11) == 1) {
+ return decodeNeonZipUzpTrn(machInst);
+ } else if (bits(machInst, 23, 22) == 0x0) {
+ return decodeNeonTblTbx(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ return new FailUnimplemented("Unhandled Case3", machInst);
+ }
+}
+}};
+
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ // bit 30=0, 28:25=1111
+ decodeFp(ExtMachInst machInst)
+ {
+ if (bits(machInst, 24) == 1) {
+ if (bits(machInst, 31) || bits(machInst, 29))
+ return new Unknown64(machInst);
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16);
+ IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 14, 10);
+ uint8_t switchVal = (bits(machInst, 23, 21) << 1) |
+ (bits(machInst, 15) << 0);
+ switch (switchVal) {
+ case 0x0: // FMADD Sd = Sa + Sn*Sm
+ return new FMAddS(machInst, rd, rn, rm, ra);
+ case 0x1: // FMSUB Sd = Sa + (-Sn)*Sm
+ return new FMSubS(machInst, rd, rn, rm, ra);
+ case 0x2: // FNMADD Sd = (-Sa) + (-Sn)*Sm
+ return new FNMAddS(machInst, rd, rn, rm, ra);
+ case 0x3: // FNMSUB Sd = (-Sa) + Sn*Sm
+ return new FNMSubS(machInst, rd, rn, rm, ra);
+ case 0x4: // FMADD Dd = Da + Dn*Dm
+ return new FMAddD(machInst, rd, rn, rm, ra);
+ case 0x5: // FMSUB Dd = Da + (-Dn)*Dm
+ return new FMSubD(machInst, rd, rn, rm, ra);
+ case 0x6: // FNMADD Dd = (-Da) + (-Dn)*Dm
+ return new FNMAddD(machInst, rd, rn, rm, ra);
+ case 0x7: // FNMSUB Dd = (-Da) + Dn*Dm
+ return new FNMSubD(machInst, rd, rn, rm, ra);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 21) == 0) {
+ bool s = bits(machInst, 29);
+ if (s)
+ return new Unknown64(machInst);
+ uint8_t switchVal = bits(machInst, 20, 16);
+ uint8_t type = bits(machInst, 23, 22);
+ uint8_t scale = bits(machInst, 15, 10);
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ if (bits(machInst, 18, 17) == 3 && scale != 0)
+ return new Unknown64(machInst);
+ // 30:24=0011110, 21=0
+ switch (switchVal) {
+ case 0x00:
+ return new FailUnimplemented("fcvtns", machInst);
+ case 0x01:
+ return new FailUnimplemented("fcvtnu", machInst);
+ case 0x02:
+ switch ( (bits(machInst, 31) << 2) | type ) {
+ case 0: // SCVTF Sd = convertFromInt(Wn/(2^fbits))
+ return new FcvtSFixedFpSW(machInst, rd, rn, scale);
+ case 1: // SCVTF Dd = convertFromInt(Wn/(2^fbits))
+ return new FcvtSFixedFpDW(machInst, rd, rn, scale);
+ case 4: // SCVTF Sd = convertFromInt(Xn/(2^fbits))
+ return new FcvtSFixedFpSX(machInst, rd, rn, scale);
+ case 5: // SCVTF Dd = convertFromInt(Xn/(2^fbits))
+ return new FcvtSFixedFpDX(machInst, rd, rn, scale);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x03:
+ switch ( (bits(machInst, 31) << 2) | type ) {
+ case 0: // UCVTF Sd = convertFromInt(Wn/(2^fbits))
+ return new FcvtUFixedFpSW(machInst, rd, rn, scale);
+ case 1: // UCVTF Dd = convertFromInt(Wn/(2^fbits))
+ return new FcvtUFixedFpDW(machInst, rd, rn, scale);
+ case 4: // UCVTF Sd = convertFromInt(Xn/(2^fbits))
+ return new FcvtUFixedFpSX(machInst, rd, rn, scale);
+ case 5: // UCVTF Dd = convertFromInt(Xn/(2^fbits))
+ return new FcvtUFixedFpDX(machInst, rd, rn, scale);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x04:
+ return new FailUnimplemented("fcvtas", machInst);
+ case 0x05:
+ return new FailUnimplemented("fcvtau", machInst);
+ case 0x08:
+ return new FailUnimplemented("fcvtps", machInst);
+ case 0x09:
+ return new FailUnimplemented("fcvtpu", machInst);
+ case 0x0e:
+ return new FailUnimplemented("fmov elem. to 64", machInst);
+ case 0x0f:
+ return new FailUnimplemented("fmov 64 bit", machInst);
+ case 0x10:
+ return new FailUnimplemented("fcvtms", machInst);
+ case 0x11:
+ return new FailUnimplemented("fcvtmu", machInst);
+ case 0x18:
+ switch ( (bits(machInst, 31) << 2) | type ) {
+ case 0: // FCVTZS Wd = convertToIntExactTowardZero(Sn*(2^fbits))
+ return new FcvtFpSFixedSW(machInst, rd, rn, scale);
+ case 1: // FCVTZS Wd = convertToIntExactTowardZero(Dn*(2^fbits))
+ return new FcvtFpSFixedDW(machInst, rd, rn, scale);
+ case 4: // FCVTZS Xd = convertToIntExactTowardZero(Sn*(2^fbits))
+ return new FcvtFpSFixedSX(machInst, rd, rn, scale);
+ case 5: // FCVTZS Xd = convertToIntExactTowardZero(Dn*(2^fbits))
+ return new FcvtFpSFixedDX(machInst, rd, rn, scale);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x19:
+ switch ( (bits(machInst, 31) << 2) | type ) {
+ case 0: // FCVTZU Wd = convertToIntExactTowardZero(Sn*(2^fbits))
+ return new FcvtFpUFixedSW(machInst, rd, rn, scale);
+ case 1: // FCVTZU Wd = convertToIntExactTowardZero(Dn*(2^fbits))
+ return new FcvtFpUFixedDW(machInst, rd, rn, scale);
+ case 4: // FCVTZU Xd = convertToIntExactTowardZero(Sn*(2^fbits))
+ return new FcvtFpUFixedSX(machInst, rd, rn, scale);
+ case 5: // FCVTZU Xd = convertToIntExactTowardZero(Dn*(2^fbits))
+ return new FcvtFpUFixedDX(machInst, rd, rn, scale);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ } else {
+ // 30=0, 28:24=11110, 21=1
+ uint8_t type = bits(machInst, 23, 22);
+ uint8_t imm8 = bits(machInst, 20, 13);
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ switch (bits(machInst, 11, 10)) {
+ case 0x0:
+ if (bits(machInst, 12) == 1) {
+ if (bits(machInst, 31) ||
+ bits(machInst, 29) ||
+ bits(machInst, 9, 5)) {
+ return new Unknown64(machInst);
+ }
+ // 31:29=000, 28:24=11110, 21=1, 12:10=100
+ if (type == 0) {
+ // FMOV S[d] = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5)
+ // :imm8<5:0>:Zeros(19)
+ uint32_t imm = vfp_modified_imm(imm8, false);
+ return new FmovImmS(machInst, rd, imm);
+ } else if (type == 1) {
+ // FMOV D[d] = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,8)
+ // :imm8<5:0>:Zeros(48)
+ uint64_t imm = vfp_modified_imm(imm8, true);
+ return new FmovImmD(machInst, rd, imm);
+ } else {
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 13) == 1) {
+ if (bits(machInst, 31) ||
+ bits(machInst, 29) ||
+ bits(machInst, 15, 14) ||
+ bits(machInst, 23) ||
+ bits(machInst, 2, 0)) {
+ return new Unknown64(machInst);
+ }
+ uint8_t switchVal = (bits(machInst, 4, 3) << 0) |
+ (bits(machInst, 22) << 2);
+ IntRegIndex rm = (IntRegIndex)(uint32_t)
+ bits(machInst, 20, 16);
+ // 28:23=000111100, 21=1, 15:10=001000, 2:0=000
+ switch (switchVal) {
+ case 0x0:
+ // FCMP flags = compareQuiet(Sn,Sm)
+ return new FCmpRegS(machInst, rn, rm);
+ case 0x1:
+ // FCMP flags = compareQuiet(Sn,0.0)
+ return new FCmpImmS(machInst, rn, 0);
+ case 0x2:
+ // FCMPE flags = compareSignaling(Sn,Sm)
+ return new FCmpERegS(machInst, rn, rm);
+ case 0x3:
+ // FCMPE flags = compareSignaling(Sn,0.0)
+ return new FCmpEImmS(machInst, rn, 0);
+ case 0x4:
+ // FCMP flags = compareQuiet(Dn,Dm)
+ return new FCmpRegD(machInst, rn, rm);
+ case 0x5:
+ // FCMP flags = compareQuiet(Dn,0.0)
+ return new FCmpImmD(machInst, rn, 0);
+ case 0x6:
+ // FCMPE flags = compareSignaling(Dn,Dm)
+ return new FCmpERegD(machInst, rn, rm);
+ case 0x7:
+ // FCMPE flags = compareSignaling(Dn,0.0)
+ return new FCmpEImmD(machInst, rn, 0);
+ default:
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 14) == 1) {
+ if (bits(machInst, 31) || bits(machInst, 29))
+ return new Unknown64(machInst);
+ uint8_t opcode = bits(machInst, 20, 15);
+ // Bits 31:24=00011110, 21=1, 14:10=10000
+ switch (opcode) {
+ case 0x0:
+ if (type == 0)
+ // FMOV Sd = Sn
+ return new FmovRegS(machInst, rd, rn);
+ else if (type == 1)
+ // FMOV Dd = Dn
+ return new FmovRegD(machInst, rd, rn);
+ break;
+ case 0x1:
+ if (type == 0)
+ // FABS Sd = abs(Sn)
+ return new FAbsS(machInst, rd, rn);
+ else if (type == 1)
+ // FABS Dd = abs(Dn)
+ return new FAbsD(machInst, rd, rn);
+ break;
+ case 0x2:
+ if (type == 0)
+ // FNEG Sd = -Sn
+ return new FNegS(machInst, rd, rn);
+ else if (type == 1)
+ // FNEG Dd = -Dn
+ return new FNegD(machInst, rd, rn);
+ break;
+ case 0x3:
+ if (type == 0)
+ // FSQRT Sd = sqrt(Sn)
+ return new FSqrtS(machInst, rd, rn);
+ else if (type == 1)
+ // FSQRT Dd = sqrt(Dn)
+ return new FSqrtD(machInst, rd, rn);
+ break;
+ case 0x4:
+ if (type == 1)
+ // FCVT Sd = convertFormat(Dn)
+ return new FcvtFpDFpS(machInst, rd, rn);
+ else if (type == 3)
+ // FCVT Sd = convertFormat(Hn)
+ return new FcvtFpHFpS(machInst, rd, rn);
+ break;
+ case 0x5:
+ if (type == 0)
+ // FCVT Dd = convertFormat(Sn)
+ return new FCvtFpSFpD(machInst, rd, rn);
+ else if (type == 3)
+ // FCVT Dd = convertFormat(Hn)
+ return new FcvtFpHFpD(machInst, rd, rn);
+ break;
+ case 0x7:
+ if (type == 0)
+ // FCVT Hd = convertFormat(Sn)
+ return new FcvtFpSFpH(machInst, rd, rn);
+ else if (type == 1)
+ // FCVT Hd = convertFormat(Dn)
+ return new FcvtFpDFpH(machInst, rd, rn);
+ break;
+ case 0x8:
+ if (type == 0) // FRINTN Sd = roundToIntegralTiesToEven(Sn)
+ return new FRIntNS(machInst, rd, rn);
+ else if (type == 1) // FRINTN Dd = roundToIntegralTiesToEven(Dn)
+ return new FRIntND(machInst, rd, rn);
+ break;
+ case 0x9:
+ if (type == 0) // FRINTP Sd = roundToIntegralTowardPlusInf(Sn)
+ return new FRIntPS(machInst, rd, rn);
+ else if (type == 1) // FRINTP Dd = roundToIntegralTowardPlusInf(Dn)
+ return new FRIntPD(machInst, rd, rn);
+ break;
+ case 0xa:
+ if (type == 0) // FRINTM Sd = roundToIntegralTowardMinusInf(Sn)
+ return new FRIntMS(machInst, rd, rn);
+ else if (type == 1) // FRINTM Dd = roundToIntegralTowardMinusInf(Dn)
+ return new FRIntMD(machInst, rd, rn);
+ break;
+ case 0xb:
+ if (type == 0) // FRINTZ Sd = roundToIntegralTowardZero(Sn)
+ return new FRIntZS(machInst, rd, rn);
+ else if (type == 1) // FRINTZ Dd = roundToIntegralTowardZero(Dn)
+ return new FRIntZD(machInst, rd, rn);
+ break;
+ case 0xc:
+ if (type == 0) // FRINTA Sd = roundToIntegralTiesToAway(Sn)
+ return new FRIntAS(machInst, rd, rn);
+ else if (type == 1) // FRINTA Dd = roundToIntegralTiesToAway(Dn)
+ return new FRIntAD(machInst, rd, rn);
+ break;
+ case 0xe:
+ if (type == 0) // FRINTX Sd = roundToIntegralExact(Sn)
+ return new FRIntXS(machInst, rd, rn);
+ else if (type == 1) // FRINTX Dd = roundToIntegralExact(Dn)
+ return new FRIntXD(machInst, rd, rn);
+ break;
+ case 0xf:
+ if (type == 0) // FRINTI Sd = roundToIntegral(Sn)
+ return new FRIntIS(machInst, rd, rn);
+ else if (type == 1) // FRINTI Dd = roundToIntegral(Dn)
+ return new FRIntID(machInst, rd, rn);
+ break;
+ default:
+ return new Unknown64(machInst);
+ }
+ return new Unknown64(machInst);
+ } else if (bits(machInst, 15) == 1) {
+ return new Unknown64(machInst);
+ } else {
+ if (bits(machInst, 29))
+ return new Unknown64(machInst);
+ uint8_t rmode = bits(machInst, 20, 19);
+ uint8_t switchVal1 = bits(machInst, 18, 16);
+ uint8_t switchVal2 = (type << 1) | bits(machInst, 31);
+ // 30:24=0011110, 21=1, 15:10=000000
+ switch (switchVal1) {
+ case 0x0:
+ switch ((switchVal2 << 2) | rmode) {
+ case 0x0: //FCVTNS Wd = convertToIntExactTiesToEven(Sn)
+ return new FcvtFpSIntWSN(machInst, rd, rn);
+ case 0x1: //FCVTPS Wd = convertToIntExactTowardPlusInf(Sn)
+ return new FcvtFpSIntWSP(machInst, rd, rn);
+ case 0x2: //FCVTMS Wd = convertToIntExactTowardMinusInf(Sn)
+ return new FcvtFpSIntWSM(machInst, rd, rn);
+ case 0x3: //FCVTZS Wd = convertToIntExactTowardZero(Sn)
+ return new FcvtFpSIntWSZ(machInst, rd, rn);
+ case 0x4: //FCVTNS Xd = convertToIntExactTiesToEven(Sn)
+ return new FcvtFpSIntXSN(machInst, rd, rn);
+ case 0x5: //FCVTPS Xd = convertToIntExactTowardPlusInf(Sn)
+ return new FcvtFpSIntXSP(machInst, rd, rn);
+ case 0x6: //FCVTMS Xd = convertToIntExactTowardMinusInf(Sn)
+ return new FcvtFpSIntXSM(machInst, rd, rn);
+ case 0x7: //FCVTZS Xd = convertToIntExactTowardZero(Sn)
+ return new FcvtFpSIntXSZ(machInst, rd, rn);
+ case 0x8: //FCVTNS Wd = convertToIntExactTiesToEven(Dn)
+ return new FcvtFpSIntWDN(machInst, rd, rn);
+ case 0x9: //FCVTPS Wd = convertToIntExactTowardPlusInf(Dn)
+ return new FcvtFpSIntWDP(machInst, rd, rn);
+ case 0xA: //FCVTMS Wd = convertToIntExactTowardMinusInf(Dn)
+ return new FcvtFpSIntWDM(machInst, rd, rn);
+ case 0xB: //FCVTZS Wd = convertToIntExactTowardZero(Dn)
+ return new FcvtFpSIntWDZ(machInst, rd, rn);
+ case 0xC: //FCVTNS Xd = convertToIntExactTiesToEven(Dn)
+ return new FcvtFpSIntXDN(machInst, rd, rn);
+ case 0xD: //FCVTPS Xd = convertToIntExactTowardPlusInf(Dn)
+ return new FcvtFpSIntXDP(machInst, rd, rn);
+ case 0xE: //FCVTMS Xd = convertToIntExactTowardMinusInf(Dn)
+ return new FcvtFpSIntXDM(machInst, rd, rn);
+ case 0xF: //FCVTZS Xd = convertToIntExactTowardZero(Dn)
+ return new FcvtFpSIntXDZ(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x1:
+ switch ((switchVal2 << 2) | rmode) {
+ case 0x0: //FCVTNU Wd = convertToIntExactTiesToEven(Sn)
+ return new FcvtFpUIntWSN(machInst, rd, rn);
+ case 0x1: //FCVTPU Wd = convertToIntExactTowardPlusInf(Sn)
+ return new FcvtFpUIntWSP(machInst, rd, rn);
+ case 0x2: //FCVTMU Wd = convertToIntExactTowardMinusInf(Sn)
+ return new FcvtFpUIntWSM(machInst, rd, rn);
+ case 0x3: //FCVTZU Wd = convertToIntExactTowardZero(Sn)
+ return new FcvtFpUIntWSZ(machInst, rd, rn);
+ case 0x4: //FCVTNU Xd = convertToIntExactTiesToEven(Sn)
+ return new FcvtFpUIntXSN(machInst, rd, rn);
+ case 0x5: //FCVTPU Xd = convertToIntExactTowardPlusInf(Sn)
+ return new FcvtFpUIntXSP(machInst, rd, rn);
+ case 0x6: //FCVTMU Xd = convertToIntExactTowardMinusInf(Sn)
+ return new FcvtFpUIntXSM(machInst, rd, rn);
+ case 0x7: //FCVTZU Xd = convertToIntExactTowardZero(Sn)
+ return new FcvtFpUIntXSZ(machInst, rd, rn);
+ case 0x8: //FCVTNU Wd = convertToIntExactTiesToEven(Dn)
+ return new FcvtFpUIntWDN(machInst, rd, rn);
+ case 0x9: //FCVTPU Wd = convertToIntExactTowardPlusInf(Dn)
+ return new FcvtFpUIntWDP(machInst, rd, rn);
+ case 0xA: //FCVTMU Wd = convertToIntExactTowardMinusInf(Dn)
+ return new FcvtFpUIntWDM(machInst, rd, rn);
+ case 0xB: //FCVTZU Wd = convertToIntExactTowardZero(Dn)
+ return new FcvtFpUIntWDZ(machInst, rd, rn);
+ case 0xC: //FCVTNU Xd = convertToIntExactTiesToEven(Dn)
+ return new FcvtFpUIntXDN(machInst, rd, rn);
+ case 0xD: //FCVTPU Xd = convertToIntExactTowardPlusInf(Dn)
+ return new FcvtFpUIntXDP(machInst, rd, rn);
+ case 0xE: //FCVTMU Xd = convertToIntExactTowardMinusInf(Dn)
+ return new FcvtFpUIntXDM(machInst, rd, rn);
+ case 0xF: //FCVTZU Xd = convertToIntExactTowardZero(Dn)
+ return new FcvtFpUIntXDZ(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x2:
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ switch (switchVal2) {
+ case 0: // SCVTF Sd = convertFromInt(Wn)
+ return new FcvtWSIntFpS(machInst, rd, rn);
+ case 1: // SCVTF Sd = convertFromInt(Xn)
+ return new FcvtXSIntFpS(machInst, rd, rn);
+ case 2: // SCVTF Dd = convertFromInt(Wn)
+ return new FcvtWSIntFpD(machInst, rd, rn);
+ case 3: // SCVTF Dd = convertFromInt(Xn)
+ return new FcvtXSIntFpD(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x3:
+ switch (switchVal2) {
+ case 0: // UCVTF Sd = convertFromInt(Wn)
+ return new FcvtWUIntFpS(machInst, rd, rn);
+ case 1: // UCVTF Sd = convertFromInt(Xn)
+ return new FcvtXUIntFpS(machInst, rd, rn);
+ case 2: // UCVTF Dd = convertFromInt(Wn)
+ return new FcvtWUIntFpD(machInst, rd, rn);
+ case 3: // UCVTF Dd = convertFromInt(Xn)
+ return new FcvtXUIntFpD(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x4:
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ switch (switchVal2) {
+ case 0: // FCVTAS Wd = convertToIntExactTiesToAway(Sn)
+ return new FcvtFpSIntWSA(machInst, rd, rn);
+ case 1: // FCVTAS Xd = convertToIntExactTiesToAway(Sn)
+ return new FcvtFpSIntXSA(machInst, rd, rn);
+ case 2: // FCVTAS Wd = convertToIntExactTiesToAway(Dn)
+ return new FcvtFpSIntWDA(machInst, rd, rn);
+ case 3: // FCVTAS Wd = convertToIntExactTiesToAway(Dn)
+ return new FcvtFpSIntXDA(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x5:
+ switch (switchVal2) {
+ case 0: // FCVTAU Wd = convertToIntExactTiesToAway(Sn)
+ return new FcvtFpUIntWSA(machInst, rd, rn);
+ case 1: // FCVTAU Xd = convertToIntExactTiesToAway(Sn)
+ return new FcvtFpUIntXSA(machInst, rd, rn);
+ case 2: // FCVTAU Wd = convertToIntExactTiesToAway(Dn)
+ return new FcvtFpUIntWDA(machInst, rd, rn);
+ case 3: // FCVTAU Xd = convertToIntExactTiesToAway(Dn)
+ return new FcvtFpUIntXDA(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ case 0x06:
+ switch (switchVal2) {
+ case 0: // FMOV Wd = Sn
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ return new FmovRegCoreW(machInst, rd, rn);
+ case 3: // FMOV Xd = Dn
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ return new FmovRegCoreX(machInst, rd, rn);
+ case 5: // FMOV Xd = Vn<127:64>
+ if (rmode != 1)
+ return new Unknown64(machInst);
+ return new FmovURegCoreX(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ break;
+ case 0x07:
+ switch (switchVal2) {
+ case 0: // FMOV Sd = Wn
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ return new FmovCoreRegW(machInst, rd, rn);
+ case 3: // FMOV Xd = Dn
+ if (rmode != 0)
+ return new Unknown64(machInst);
+ return new FmovCoreRegX(machInst, rd, rn);
+ case 5: // FMOV Xd = Vn<127:64>
+ if (rmode != 1)
+ return new Unknown64(machInst);
+ return new FmovUCoreRegX(machInst, rd, rn);
+ default:
+ return new Unknown64(machInst);
+ }
+ break;
+ default: // Warning! missing cases in switch statement above, that still need to be added
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x1:
+ {
+ if (bits(machInst, 31) ||
+ bits(machInst, 29) ||
+ bits(machInst, 23)) {
+ return new Unknown64(machInst);
+ }
+ IntRegIndex rm = (IntRegIndex)(uint32_t) bits(machInst, 20, 16);
+ IntRegIndex rn = (IntRegIndex)(uint32_t) bits(machInst, 9, 5);
+ uint8_t imm = (IntRegIndex)(uint32_t) bits(machInst, 3, 0);
+ ConditionCode cond =
+ (ConditionCode)(uint8_t)(bits(machInst, 15, 12));
+ uint8_t switchVal = (bits(machInst, 4) << 0) |
+ (bits(machInst, 22) << 1);
+ // 31:23=000111100, 21=1, 11:10=01
+ switch (switchVal) {
+ case 0x0:
+ // FCCMP flags = if cond the compareQuiet(Sn,Sm) else #nzcv
+ return new FCCmpRegS(machInst, rn, rm, cond, imm);
+ case 0x1:
+ // FCCMP flags = if cond then compareSignaling(Sn,Sm)
+ // else #nzcv
+ return new FCCmpERegS(machInst, rn, rm, cond, imm);
+ case 0x2:
+ // FCCMP flags = if cond then compareQuiet(Dn,Dm) else #nzcv
+ return new FCCmpRegD(machInst, rn, rm, cond, imm);
+ case 0x3:
+ // FCCMP flags = if cond then compareSignaling(Dn,Dm)
+ // else #nzcv
+ return new FCCmpERegD(machInst, rn, rm, cond, imm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x2:
+ {
+ if (bits(machInst, 31) ||
+ bits(machInst, 29) ||
+ bits(machInst, 23)) {
+ return new Unknown64(machInst);
+ }
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16);
+ uint8_t switchVal = (bits(machInst, 15, 12) << 0) |
+ (bits(machInst, 22) << 4);
+ switch (switchVal) {
+ case 0x00: // FMUL Sd = Sn * Sm
+ return new FMulS(machInst, rd, rn, rm);
+ case 0x10: // FMUL Dd = Dn * Dm
+ return new FMulD(machInst, rd, rn, rm);
+ case 0x01: // FDIV Sd = Sn / Sm
+ return new FDivS(machInst, rd, rn, rm);
+ case 0x11: // FDIV Dd = Dn / Dm
+ return new FDivD(machInst, rd, rn, rm);
+ case 0x02: // FADD Sd = Sn + Sm
+ return new FAddS(machInst, rd, rn, rm);
+ case 0x12: // FADD Dd = Dn + Dm
+ return new FAddD(machInst, rd, rn, rm);
+ case 0x03: // FSUB Sd = Sn - Sm
+ return new FSubS(machInst, rd, rn, rm);
+ case 0x13: // FSUB Dd = Dn - Dm
+ return new FSubD(machInst, rd, rn, rm);
+ case 0x04: // FMAX Sd = max(Sn, Sm)
+ return new FMaxS(machInst, rd, rn, rm);
+ case 0x14: // FMAX Dd = max(Dn, Dm)
+ return new FMaxD(machInst, rd, rn, rm);
+ case 0x05: // FMIN Sd = min(Sn, Sm)
+ return new FMinS(machInst, rd, rn, rm);
+ case 0x15: // FMIN Dd = min(Dn, Dm)
+ return new FMinD(machInst, rd, rn, rm);
+ case 0x06: // FMAXNM Sd = maxNum(Sn, Sm)
+ return new FMaxNMS(machInst, rd, rn, rm);
+ case 0x16: // FMAXNM Dd = maxNum(Dn, Dm)
+ return new FMaxNMD(machInst, rd, rn, rm);
+ case 0x07: // FMINNM Sd = minNum(Sn, Sm)
+ return new FMinNMS(machInst, rd, rn, rm);
+ case 0x17: // FMINNM Dd = minNum(Dn, Dm)
+ return new FMinNMD(machInst, rd, rn, rm);
+ case 0x08: // FNMUL Sd = -(Sn * Sm)
+ return new FNMulS(machInst, rd, rn, rm);
+ case 0x18: // FNMUL Dd = -(Dn * Dm)
+ return new FNMulD(machInst, rd, rn, rm);
+ default:
+ return new Unknown64(machInst);
+ }
+ }
+ case 0x3:
+ {
+ if (bits(machInst, 31) || bits(machInst, 29))
+ return new Unknown64(machInst);
+ uint8_t type = bits(machInst, 23, 22);
+ IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0);
+ IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5);
+ IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16);
+ ConditionCode cond =
+ (ConditionCode)(uint8_t)(bits(machInst, 15, 12));
+ if (type == 0) // FCSEL Sd = if cond then Sn else Sm
+ return new FCSelS(machInst, rd, rn, rm, cond);
+ else if (type == 1) // FCSEL Dd = if cond then Dn else Dm
+ return new FCSelD(machInst, rd, rn, rm, cond);
+ else
+ return new Unknown64(machInst);
+ }
+ }
+ }
+ return new FailUnimplemented("Unhandled Case4", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeAdvSIMDScalar(ExtMachInst machInst)
+ {
+ if (bits(machInst, 24) == 1) {
+ if (bits(machInst, 10) == 0) {
+ return decodeNeonScIndexedElem(machInst);
+ } else if (bits(machInst, 23) == 0) {
+ return decodeNeonScShiftByImm(machInst);
+ }
+ } else if (bits(machInst, 21) == 1) {
+ if (bits(machInst, 10) == 1) {
+ return decodeNeonSc3Same(machInst);
+ } else if (bits(machInst, 11) == 0) {
+ return decodeNeonSc3Diff(machInst);
+ } else if (bits(machInst, 20, 17) == 0x0) {
+ return decodeNeonSc2RegMisc(machInst);
+ } else if (bits(machInst, 20, 17) == 0x8) {
+ return decodeNeonScPwise(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 23, 22) == 0 &&
+ bits(machInst, 15) == 0 &&
+ bits(machInst, 10) == 1) {
+ return decodeNeonScCopy(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ return new FailUnimplemented("Unhandled Case6", machInst);
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeFpAdvSIMD(ExtMachInst machInst)
+ {
+
+ if (bits(machInst, 28) == 0) {
+ if (bits(machInst, 31) == 0) {
+ return decodeAdvSIMD(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ } else if (bits(machInst, 30) == 0) {
+ return decodeFp(machInst);
+ } else if (bits(machInst, 31) == 0) {
+ return decodeAdvSIMDScalar(machInst);
+ } else {
+ return new Unknown64(machInst);
+ }
+ }
+}
+}};
+
+output decoder {{
+namespace Aarch64
+{
+ StaticInstPtr
+ decodeGem5Ops(ExtMachInst machInst)
+ {
+ const uint32_t m5func = bits(machInst, 23, 16);
+ switch (m5func) {
+ case 0x00: return new Arm(machInst);
+ case 0x01: return new Quiesce(machInst);
+ case 0x02: return new QuiesceNs64(machInst);
+ case 0x03: return new QuiesceCycles64(machInst);
+ case 0x04: return new QuiesceTime64(machInst);
+ case 0x07: return new Rpns64(machInst);
+ case 0x09: return new WakeCPU64(machInst);
+ case 0x10: return new Deprecated_ivlb(machInst);
+ case 0x11: return new Deprecated_ivle(machInst);
+ case 0x20: return new Deprecated_exit (machInst);
+ case 0x21: return new M5exit64(machInst);
+ case 0x31: return new Loadsymbol(machInst);
+ case 0x30: return new Initparam64(machInst);
+ case 0x40: return new Resetstats64(machInst);
+ case 0x41: return new Dumpstats64(machInst);
+ case 0x42: return new Dumpresetstats64(machInst);
+ case 0x43: return new M5checkpoint64(machInst);
+ case 0x4F: return new M5writefile64(machInst);
+ case 0x50: return new M5readfile64(machInst);
+ case 0x51: return new M5break(machInst);
+ case 0x52: return new M5switchcpu(machInst);
+ case 0x53: return new M5addsymbol64(machInst);
+ case 0x54: return new M5panic(machInst);
+ case 0x5a: return new M5workbegin64(machInst);
+ case 0x5b: return new M5workend64(machInst);
+ default: return new Unknown64(machInst);
+ }
+ }
+}
+}};
+
+def format Aarch64() {{
+ decode_block = '''
+ {
+ using namespace Aarch64;
+ if (bits(machInst, 27) == 0x0) {
+ if (bits(machInst, 28) == 0x0)
+ return new Unknown64(machInst);
+ else if (bits(machInst, 26) == 0)
+ // bit 28:26=100
+ return decodeDataProcImm(machInst);
+ else
+ // bit 28:26=101
+ return decodeBranchExcSys(machInst);
+ } else if (bits(machInst, 25) == 0) {
+ // bit 27=1, 25=0
+ return decodeLoadsStores(machInst);
+ } else if (bits(machInst, 26) == 0) {
+ // bit 27:25=101
+ return decodeDataProcReg(machInst);
+ } else if (bits(machInst, 24) == 1 &&
+ bits(machInst, 31, 28) == 0xF) {
+ return decodeGem5Ops(machInst);
+ } else {
+ // bit 27:25=111
+ return decodeFpAdvSIMD(machInst);
+ }
+ }
+ '''
+}};
diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa
index f1b17ec90..513506d31 100644
--- a/src/arch/arm/isa/formats/branch.isa
+++ b/src/arch/arm/isa/formats/branch.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010 ARM Limited
+// Copyright (c) 2010, 2012-2013 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -101,7 +101,7 @@ def format Thumb16CondBranchAndSvc() {{
return new B(machInst, sext<9>(bits(machInst, 7, 0) << 1),
(ConditionCode)(uint32_t)bits(machInst, 11, 8));
} else if (bits(machInst, 8)) {
- return new Svc(machInst);
+ return new Svc(machInst, bits(machInst, 7, 0));
} else {
// This space will not be allocated in the future.
return new Unknown(machInst);
@@ -127,7 +127,7 @@ def format Thumb32BranchesAndMiscCtrl() {{
// Permanently undefined.
return new Unknown(machInst);
} else {
- return new WarnUnimplemented("smc", machInst);
+ return new Smc(machInst);
}
} else if ((op & 0x38) != 0x38) {
const uint32_t s = bits(machInst, 26);
@@ -141,20 +141,26 @@ def format Thumb32BranchesAndMiscCtrl() {{
return new B(machInst, imm,
(ConditionCode)(uint32_t)bits(machInst, 25, 22));
} else {
+ // HIGH: 12-11=10, LOW: 15-14=00, 12=0
switch (op) {
case 0x38:
- {
- const IntRegIndex rn =
- (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
- const uint8_t byteMask = bits(machInst, 11, 8);
- return new MsrCpsrReg(machInst, rn, byteMask);
- }
case 0x39:
{
const IntRegIndex rn =
(IntRegIndex)(uint32_t)bits(machInst, 19, 16);
const uint8_t byteMask = bits(machInst, 11, 8);
- return new MsrSpsrReg(machInst, rn, byteMask);
+ const bool r = bits(machInst, 20);
+ if (bits(machInst, 5)) {
+ const uint8_t sysM = (bits(machInst, 4) << 4) |
+ byteMask;
+ return new MsrBankedReg(machInst, rn, sysM, r);
+ } else {
+ if (r) {
+ return new MsrSpsrReg(machInst, rn, byteMask);
+ } else {
+ return new MsrCpsrReg(machInst, rn, byteMask);
+ }
+ }
}
case 0x3a:
{
@@ -196,11 +202,11 @@ def format Thumb32BranchesAndMiscCtrl() {{
case 0x2:
return new Clrex(machInst);
case 0x4:
- return new Dsb(machInst);
+ return new Dsb(machInst, 0);
case 0x5:
- return new Dmb(machInst);
+ return new Dmb(machInst, 0);
case 0x6:
- return new Isb(machInst);
+ return new Isb(machInst, 0);
default:
break;
}
@@ -208,28 +214,44 @@ def format Thumb32BranchesAndMiscCtrl() {{
}
case 0x3c:
{
- // On systems that don't support bxj, bxj == bx
- return new BxReg(machInst,
+ return new BxjReg(machInst,
(IntRegIndex)(uint32_t)bits(machInst, 19, 16),
COND_UC);
}
case 0x3d:
{
const uint32_t imm32 = bits(machInst, 7, 0);
- return new SubsImmPclr(machInst, INTREG_PC, INTREG_LR,
- imm32, false);
+ if (imm32 == 0) {
+ return new Eret(machInst);
+ } else {
+ return new SubsImmPclr(machInst, INTREG_PC,
+ INTREG_LR, imm32, false);
+ }
}
case 0x3e:
+ case 0x3f:
{
+
const IntRegIndex rd =
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
- return new MrsCpsr(machInst, rd);
+ const bool r = bits(machInst, 20);
+ if (bits(machInst, 5)) {
+ const uint8_t sysM = (bits(machInst, 4) << 4) |
+ bits(machInst, 11, 8);
+ return new MrsBankedReg(machInst, rd, sysM, r);
+ } else {
+ if (r) {
+ return new MrsSpsr(machInst, rd);
+ } else {
+ return new MrsCpsr(machInst, rd);
+ }
+ }
}
- case 0x3f:
+ case 0xfe:
{
- const IntRegIndex rd =
- (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
- return new MrsSpsr(machInst, rd);
+ uint32_t imm16 = (bits(machInst, 19, 16) << 12) |
+ (bits(machInst, 11, 0) << 0);
+ return new Hvc(machInst, imm16);
}
}
break;
diff --git a/src/arch/arm/isa/formats/formats.isa b/src/arch/arm/isa/formats/formats.isa
index 90144c101..44e9c5b5e 100644
--- a/src/arch/arm/isa/formats/formats.isa
+++ b/src/arch/arm/isa/formats/formats.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010 ARM Limited
+// Copyright (c) 2010-2011 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -44,6 +44,12 @@
//Include the basic format
##include "basic.isa"
+//Include support for decoding AArch64 instructions
+##include "aarch64.isa"
+
+//Include support for decoding AArch64 NEON instructions
+##include "neon64.isa"
+
//Include support for predicated instructions
##include "pred.isa"
diff --git a/src/arch/arm/isa/formats/fp.isa b/src/arch/arm/isa/formats/fp.isa
index 6d779e541..ccd4589a3 100644
--- a/src/arch/arm/isa/formats/fp.isa
+++ b/src/arch/arm/isa/formats/fp.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010 ARM Limited
+// Copyright (c) 2010-2011 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -151,8 +151,7 @@ let {{
if (singleAll) {
size = bits(machInst, 7, 6);
bool t = bits(machInst, 5);
- unsigned eBytes = (1 << size);
- align = (eBytes - 1) | TLB::AllowUnaligned;
+ align = size | TLB::AllowUnaligned;
if (width == 1) {
regs = t ? 2 : 1;
inc = 1;
@@ -164,7 +163,7 @@ let {{
case 1:
case 2:
if (bits(machInst, 4))
- align = width * eBytes - 1;
+ align = size + width - 1;
break;
case 3:
break;
@@ -173,20 +172,19 @@ let {{
if (bits(machInst, 4) == 0)
return new Unknown(machInst);
size = 2;
- align = 0xf;
+ align = 0x4;
} else if (size == 2) {
if (bits(machInst, 4))
- align = 7;
+ align = 0x3;
} else {
if (bits(machInst, 4))
- align = 4 * eBytes - 1;
+ align = size + 2;
}
break;
}
} else {
size = bits(machInst, 11, 10);
- unsigned eBytes = (1 << size);
- align = (eBytes - 1) | TLB::AllowUnaligned;
+ align = size | TLB::AllowUnaligned;
regs = width;
unsigned indexAlign = bits(machInst, 7, 4);
// If width is 1, inc is always 1. That's overridden later.
@@ -219,13 +217,13 @@ let {{
break;
case 2:
if (bits(indexAlign, 1, 0))
- align = 3;
+ align = 2;
break;
}
break;
case 2:
if (bits(indexAlign, 0))
- align = (2 * eBytes) - 1;
+ align = size + 1;
break;
case 3:
break;
@@ -234,11 +232,11 @@ let {{
case 0:
case 1:
if (bits(indexAlign, 0))
- align = (4 * eBytes) - 1;
+ align = size + 2;
break;
case 2:
if (bits(indexAlign, 0))
- align = (4 << bits(indexAlign, 1, 0)) - 1;
+ align = bits(indexAlign, 1, 0) + 2;
break;
}
break;
@@ -252,9 +250,9 @@ let {{
align = bits(machInst, 5, 4);
if (align == 0) {
// @align wasn't specified, so alignment can be turned off.
- align = ((1 << size) - 1) | TLB::AllowUnaligned;
+ align = size | TLB::AllowUnaligned;
} else {
- align = ((4 << align) - 1);
+ align = align + 2;
}
switch (width) {
case 1:
@@ -588,6 +586,23 @@ let {{
}
}
case 0xc:
+ if (b) {
+ if (!u) {
+ if (bits(c, 1) == 0) {
+ if (q) {
+ return new NVfmaQFp<float>(machInst, vd, vn, vm);
+ } else {
+ return new NVfmaDFp<float>(machInst, vd, vn, vm);
+ }
+ } else {
+ if (q) {
+ return new NVfmsQFp<float>(machInst, vd, vn, vm);
+ } else {
+ return new NVfmsDFp<float>(machInst, vd, vn, vm);
+ }
+ }
+ }
+ }
return new Unknown(machInst);
case 0xd:
if (b) {
@@ -1827,7 +1842,7 @@ let {{
break;
case 0x1:
{
- if (offset == 0 || vd + offset/2 > NumFloatArchRegs) {
+ if (offset == 0 || vd + offset/2 > NumFloatV7ArchRegs) {
break;
}
switch (bits(opcode, 1, 0)) {
@@ -1951,8 +1966,9 @@ let {{
} else if (a == 0x7) {
const IntRegIndex rt =
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
- uint32_t specReg = bits(machInst, 19, 16);
- switch (specReg) {
+ uint32_t reg = bits(machInst, 19, 16);
+ uint32_t specReg;
+ switch (reg) {
case 0:
specReg = MISCREG_FPSID;
break;
@@ -1974,7 +1990,9 @@ let {{
if (specReg == MISCREG_FPSCR) {
return new VmsrFpscr(machInst, (IntRegIndex)specReg, rt);
} else {
- return new Vmsr(machInst, (IntRegIndex)specReg, rt);
+ uint32_t iss = mcrMrcIssBuild(0, bits(machInst, 3, 0), rt,
+ reg, a, bits(machInst, 7, 5));
+ return new Vmsr(machInst, (IntRegIndex)specReg, rt, iss);
}
}
} else if (l == 0 && c == 1) {
@@ -2041,8 +2059,9 @@ let {{
} else if (a == 7) {
const IntRegIndex rt =
(IntRegIndex)(uint32_t)bits(machInst, 15, 12);
- uint32_t specReg = bits(machInst, 19, 16);
- switch (specReg) {
+ uint32_t reg = bits(machInst, 19, 16);
+ uint32_t specReg;
+ switch (reg) {
case 0:
specReg = MISCREG_FPSID;
break;
@@ -2070,7 +2089,9 @@ let {{
} else if (specReg == MISCREG_FPSCR) {
return new VmrsFpscr(machInst, rt, (IntRegIndex)specReg);
} else {
- return new Vmrs(machInst, rt, (IntRegIndex)specReg);
+ uint32_t iss = mcrMrcIssBuild(l, bits(machInst, 3, 0), rt,
+ reg, a, bits(machInst, 7, 5));
+ return new Vmrs(machInst, rt, (IntRegIndex)specReg, iss);
}
}
} else {
@@ -2235,6 +2256,44 @@ let {{
}
}
break;
+ case 0x9:
+ if ((opc3 & 0x1) == 0) {
+ if (single) {
+ return decodeVfpRegRegRegOp<VfnmaS>(
+ machInst, vd, vn, vm, false);
+ } else {
+ return decodeVfpRegRegRegOp<VfnmaD>(
+ machInst, vd, vn, vm, true);
+ }
+ } else {
+ if (single) {
+ return decodeVfpRegRegRegOp<VfnmsS>(
+ machInst, vd, vn, vm, false);
+ } else {
+ return decodeVfpRegRegRegOp<VfnmsD>(
+ machInst, vd, vn, vm, true);
+ }
+ }
+ break;
+ case 0xa:
+ if ((opc3 & 0x1) == 0) {
+ if (single) {
+ return decodeVfpRegRegRegOp<VfmaS>(
+ machInst, vd, vn, vm, false);
+ } else {
+ return decodeVfpRegRegRegOp<VfmaD>(
+ machInst, vd, vn, vm, true);
+ }
+ } else {
+ if (single) {
+ return decodeVfpRegRegRegOp<VfmsS>(
+ machInst, vd, vn, vm, false);
+ } else {
+ return decodeVfpRegRegRegOp<VfmsD>(
+ machInst, vd, vn, vm, true);
+ }
+ }
+ break;
case 0xb:
if ((opc3 & 0x1) == 0) {
const uint32_t baseImm =
diff --git a/src/arch/arm/isa/formats/mem.isa b/src/arch/arm/isa/formats/mem.isa
index f7830eff3..abac27021 100644
--- a/src/arch/arm/isa/formats/mem.isa
+++ b/src/arch/arm/isa/formats/mem.isa
@@ -282,7 +282,7 @@ def format Thumb32SrsRfe() {{
}
} else {
const uint32_t mode = bits(machInst, 4, 0);
- if (badMode((OperatingMode)mode))
+ if (badMode32((OperatingMode)mode))
return new Unknown(machInst);
if (!add && !wb) {
return new %(srs)s(machInst, mode,
diff --git a/src/arch/arm/isa/formats/misc.isa b/src/arch/arm/isa/formats/misc.isa
index 00a37d17b..647f9846d 100644
--- a/src/arch/arm/isa/formats/misc.isa
+++ b/src/arch/arm/isa/formats/misc.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010-2012 ARM Limited
+// Copyright (c) 2010-2013 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -36,19 +36,42 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Authors: Gabe Black
+// Giacomo Gabrielli
+
+def format ArmERet() {{
+ decode_block = "return new Eret(machInst);"
+}};
def format Svc() {{
- decode_block = "return new Svc(machInst);"
+ decode_block = "return new Svc(machInst, bits(machInst, 23, 0));"
+}};
+
+def format ArmSmcHyp() {{
+ decode_block = '''
+ {
+ if (bits(machInst, 21))
+ {
+ return new Smc(machInst);
+ } else {
+ uint32_t imm16 = (bits(machInst, 19, 8) << 4) |
+ (bits(machInst, 3, 0) << 0);
+ return new Hvc(machInst, imm16);
+ }
+ }
+ '''
}};
def format ArmMsrMrs() {{
decode_block = '''
{
const uint8_t byteMask = bits(machInst, 19, 16);
+ const uint8_t sysM = byteMask | (bits(machInst, 8) << 4);
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
const uint32_t opcode = bits(machInst, 24, 21);
const bool useImm = bits(machInst, 25);
+ const bool r = bits(machInst, 22);
+ const bool isBanked = bits(machInst, 9);
const uint32_t unrotated = bits(machInst, 7, 0);
const uint32_t rotation = (bits(machInst, 11, 8) << 1);
@@ -56,20 +79,36 @@ def format ArmMsrMrs() {{
switch (opcode) {
case 0x8:
- return new MrsCpsr(machInst, rd);
+ if (isBanked) {
+ return new MrsBankedReg(machInst, rd, sysM, r!=0);
+ } else {
+ return new MrsCpsr(machInst, rd);
+ }
case 0x9:
if (useImm) {
return new MsrCpsrImm(machInst, imm, byteMask);
} else {
- return new MsrCpsrReg(machInst, rn, byteMask);
+ if (isBanked) {
+ return new MsrBankedReg(machInst, rn, sysM, r!=0);
+ } else {
+ return new MsrCpsrReg(machInst, rn, byteMask);
+ }
}
case 0xa:
- return new MrsSpsr(machInst, rd);
+ if (isBanked) {
+ return new MrsBankedReg(machInst, rd, sysM, r!=0);
+ } else {
+ return new MrsSpsr(machInst, rd);
+ }
case 0xb:
if (useImm) {
return new MsrSpsrImm(machInst, imm, byteMask);
} else {
- return new MsrSpsrReg(machInst, rn, byteMask);
+ if (isBanked) {
+ return new MsrBankedReg(machInst, rn, sysM, r!=0);
+ } else {
+ return new MsrSpsrReg(machInst, rn, byteMask);
+ }
}
default:
return new Unknown(machInst);
@@ -99,16 +138,17 @@ let {{
switch (miscReg) {
case MISCREG_NOP:
return new NopInst(machInst);
- case NUM_MISCREGS:
+ case MISCREG_CP14_UNIMPL:
return new FailUnimplemented(
csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
crn, opc1, crm, opc2, isRead ? "read" : "write").c_str(),
machInst);
default:
+ uint32_t iss = mcrMrcIssBuild(isRead, crm, rt, crn, opc1, opc2);
if (isRead) {
- return new Mrc14(machInst, rt, (IntRegIndex)miscReg);
+ return new Mrc14(machInst, rt, (IntRegIndex)miscReg, iss);
} else {
- return new Mcr14(machInst, (IntRegIndex)miscReg, rt);
+ return new Mcr14(machInst, (IntRegIndex)miscReg, rt, iss);
}
}
}
@@ -123,8 +163,8 @@ def format McrMrc14() {{
let {{
header_output = '''
- StaticInstPtr
- decodeMcrMrc15(ExtMachInst machInst);
+ StaticInstPtr decodeMcrMrc14(ExtMachInst machInst);
+ StaticInstPtr decodeMcrMrc15(ExtMachInst machInst);
'''
decoder_output = '''
StaticInstPtr
@@ -136,107 +176,50 @@ let {{
const uint32_t crm = bits(machInst, 3, 0);
const MiscRegIndex miscReg = decodeCP15Reg(crn, opc1, crm, opc2);
const IntRegIndex rt = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
-
const bool isRead = bits(machInst, 20);
+ uint32_t iss = mcrMrcIssBuild(isRead, crm, rt, crn, opc1, opc2);
switch (miscReg) {
case MISCREG_NOP:
return new NopInst(machInst);
- case NUM_MISCREGS:
+ case MISCREG_CP15_UNIMPL:
return new FailUnimplemented(
csprintf("miscreg crn:%d opc1:%d crm:%d opc2:%d %s unknown",
crn, opc1, crm, opc2, isRead ? "read" : "write").c_str(),
machInst);
- case MISCREG_DCCISW:
- return new WarnUnimplemented(
- isRead ? "mrc dccisw" : "mcr dcisw", machInst);
- case MISCREG_DCCIMVAC:
- return new WarnUnimplemented(
- isRead ? "mrc dccimvac" : "mcr dccimvac", machInst);
- case MISCREG_DCIMVAC:
- return new WarnUnimplemented(
- isRead ? "mrc dcimvac" : "mcr dcimvac", machInst);
case MISCREG_DCCMVAC:
return new FlushPipeInst(
isRead ? "mrc dccmvac" : "mcr dccmvac", machInst);
- case MISCREG_DCCMVAU:
- return new WarnUnimplemented(
- isRead ? "mrc dccmvau" : "mcr dccmvau", machInst);
case MISCREG_CP15ISB:
- return new Isb(machInst);
+ return new Isb(machInst, iss);
case MISCREG_CP15DSB:
- return new Dsb(machInst);
+ return new Dsb(machInst, iss);
case MISCREG_CP15DMB:
- return new Dmb(machInst);
- case MISCREG_ICIALLUIS:
- return new WarnUnimplemented(
- isRead ? "mrc icialluis" : "mcr icialluis", machInst);
- case MISCREG_ICIMVAU:
- return new WarnUnimplemented(
- isRead ? "mrc icimvau" : "mcr icimvau", machInst);
- case MISCREG_BPIMVA:
- return new WarnUnimplemented(
- isRead ? "mrc bpimva" : "mcr bpimva", machInst);
- case MISCREG_BPIALLIS:
- return new WarnUnimplemented(
- isRead ? "mrc bpiallis" : "mcr bpiallis", machInst);
- case MISCREG_BPIALL:
- return new WarnUnimplemented(
- isRead ? "mrc bpiall" : "mcr bpiall", machInst);
- case MISCREG_L2LATENCY:
- return new WarnUnimplemented(
- isRead ? "mrc l2latency" : "mcr l2latency", machInst);
- case MISCREG_CRN15:
- return new WarnUnimplemented(
- isRead ? "mrc crn15" : "mcr crn15", machInst);
-
- // Write only.
- case MISCREG_TLBIALLIS:
- case MISCREG_TLBIMVAIS:
- case MISCREG_TLBIASIDIS:
- case MISCREG_TLBIMVAAIS:
- case MISCREG_ITLBIALL:
- case MISCREG_ITLBIMVA:
- case MISCREG_ITLBIASID:
- case MISCREG_DTLBIALL:
- case MISCREG_DTLBIMVA:
- case MISCREG_DTLBIASID:
- case MISCREG_TLBIALL:
- case MISCREG_TLBIMVA:
- case MISCREG_TLBIASID:
- case MISCREG_TLBIMVAA:
- if (isRead) {
- return new Unknown(machInst);
- } else {
- return new Mcr15(machInst, (IntRegIndex)miscReg, rt);
- }
+ return new Dmb(machInst, iss);
+ default:
+ if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
+ std::string full_mnem = csprintf("%s %s",
+ isRead ? "mrc" : "mcr", miscRegName[miscReg]);
+ warn("\\tinstruction '%s' unimplemented\\n", full_mnem);
- // Read only in user mode.
- case MISCREG_TPIDRURO:
- if (isRead) {
- return new Mrc15User(machInst, rt, (IntRegIndex)miscReg);
- } else {
- return new Mcr15(machInst, (IntRegIndex)miscReg, rt);
+ // Remove the warn flag and set the implemented flag. This
+ // prevents the instruction warning a second time, it also
+ // means the instruction is actually generated. Actually
+ // creating the instruction to access an register that isn't
+ // implemented sounds a bit silly, but its required to get
+ // the correct behaviour for hyp traps and undef exceptions.
+ miscRegInfo[miscReg][MISCREG_IMPLEMENTED] = true;
+ miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL] = false;
}
- // Read/write in user mode.
- case MISCREG_TPIDRURW:
- if (isRead) {
- return new Mrc15User(machInst, rt, (IntRegIndex)miscReg);
+ if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) {
+ if (isRead)
+ return new Mrc15(machInst, rt, (IntRegIndex)miscReg, iss);
+ return new Mcr15(machInst, (IntRegIndex)miscReg, rt, iss);
} else {
- return new Mcr15User(machInst, (IntRegIndex)miscReg, rt);
- }
-
- // Read/write, priveleged only.
- default:
- if (miscReg >= MISCREG_CP15_UNIMP_START)
return new FailUnimplemented(csprintf("%s %s",
isRead ? "mrc" : "mcr", miscRegName[miscReg]).c_str(),
machInst);
- if (isRead) {
- return new Mrc15(machInst, rt, (IntRegIndex)miscReg);
- } else {
- return new Mcr15(machInst, (IntRegIndex)miscReg, rt);
}
}
}
@@ -248,3 +231,70 @@ def format McrMrc15() {{
return decodeMcrMrc15(machInst);
'''
}};
+
+let {{
+ header_output = '''
+ StaticInstPtr
+ decodeMcrrMrrc15(ExtMachInst machInst);
+ '''
+ decoder_output = '''
+ StaticInstPtr
+ decodeMcrrMrrc15(ExtMachInst machInst)
+ {
+ const uint32_t crm = bits(machInst, 3, 0);
+ const uint32_t opc1 = bits(machInst, 7, 4);
+ const MiscRegIndex miscReg = decodeCP15Reg64(crm, opc1);
+ const IntRegIndex rt = (IntRegIndex) (uint32_t) bits(machInst, 15, 12);
+ const IntRegIndex rt2 = (IntRegIndex) (uint32_t) bits(machInst, 19, 16);
+
+ const bool isRead = bits(machInst, 20);
+
+ switch (miscReg) {
+ case MISCREG_CP15_UNIMPL:
+ return new FailUnimplemented(
+ csprintf("miscreg crm:%d opc1:%d 64-bit %s unknown",
+ crm, opc1, isRead ? "read" : "write").c_str(),
+ machInst);
+ default:
+ if (miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]) {
+ std::string full_mnem = csprintf("%s %s",
+ isRead ? "mrrc" : "mcrr", miscRegName[miscReg]);
+ warn("\\tinstruction '%s' unimplemented\\n", full_mnem);
+
+ // Remove the warn flag and set the implemented flag. This
+ // prevents the instruction warning a second time, it also
+ // means the instruction is actually generated. Actually
+ // creating the instruction to access an register that isn't
+ // implemented sounds a bit silly, but its required to get
+ // the correct behaviour for hyp traps and undef exceptions.
+ miscRegInfo[miscReg][MISCREG_IMPLEMENTED] = true;
+ miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL] = false;
+ }
+
+ if (miscRegInfo[miscReg][MISCREG_IMPLEMENTED]) {
+ uint32_t iss = mcrrMrrcIssBuild(isRead, crm, rt, rt2, opc1);
+
+ if (isRead)
+ return new Mrrc15(machInst, (IntRegIndex) miscReg, rt2, rt, iss);
+ return new Mcrr15(machInst, rt2, rt, (IntRegIndex) miscReg, iss);
+ } else {
+ return new FailUnimplemented(csprintf("%s %s",
+ isRead ? "mrrc" : "mcrr", miscRegName[miscReg]).c_str(),
+ machInst);
+ }
+ }
+ }
+ '''
+}};
+
+def format Mcrr15() {{
+ decode_block = '''
+ return decodeMcrrMrrc15(machInst);
+ '''
+}};
+
+def format Mrrc15() {{
+ decode_block = '''
+ return decodeMcrrMrrc15(machInst);
+ '''
+}};
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);
+ }
+ }
+ }
+}
+}};
diff --git a/src/arch/arm/isa/formats/uncond.isa b/src/arch/arm/isa/formats/uncond.isa
index 4a18a55bb..c376cd9ce 100644
--- a/src/arch/arm/isa/formats/uncond.isa
+++ b/src/arch/arm/isa/formats/uncond.isa
@@ -99,11 +99,11 @@ def format ArmUnconditional() {{
case 0x1:
return new Clrex(machInst);
case 0x4:
- return new Dsb(machInst);
+ return new Dsb(machInst, 0);
case 0x5:
- return new Dmb(machInst);
+ return new Dmb(machInst, 0);
case 0x6:
- return new Isb(machInst);
+ return new Isb(machInst, 0);
}
}
} else if (bits(op2, 0) == 0) {
@@ -166,7 +166,7 @@ def format ArmUnconditional() {{
const uint32_t val = ((machInst >> 20) & 0x5);
if (val == 0x4) {
const uint32_t mode = bits(machInst, 4, 0);
- if (badMode((OperatingMode)mode))
+ if (badMode32((OperatingMode)mode))
return new Unknown(machInst);
switch (bits(machInst, 24, 21)) {
case 0x2:
@@ -250,17 +250,10 @@ def format ArmUnconditional() {{
"ldc, ldc2 (immediate)", machInst);
}
}
- if (op1 == 0xC5) {
- return new WarnUnimplemented(
- "mrrc, mrrc2", machInst);
- }
} else {
if (bits(op1, 4, 3) != 0 || bits(op1, 1) == 1) {
return new WarnUnimplemented(
"stc, stc2", machInst);
- } else if (op1 == 0xC4) {
- return new WarnUnimplemented(
- "mcrr, mcrrc", machInst);
}
}
}
diff --git a/src/arch/arm/isa/formats/unimp.isa b/src/arch/arm/isa/formats/unimp.isa
index 1c9a4b402..8e346112c 100644
--- a/src/arch/arm/isa/formats/unimp.isa
+++ b/src/arch/arm/isa/formats/unimp.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2010 ARM Limited
+// Copyright (c) 2010, 2012 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -85,6 +85,9 @@ output header {{
private:
/// Have we warned on this instruction yet?
mutable bool warned;
+ /// Full mnemonic for MRC and MCR instructions including the
+ /// coproc. register name
+ std::string fullMnemonic;
public:
/// Constructor
@@ -96,6 +99,16 @@ output header {{
flags[IsNonSpeculative] = true;
}
+ WarnUnimplemented(const char *_mnemonic, ExtMachInst _machInst,
+ const std::string& _fullMnemonic)
+ : ArmStaticInst(_mnemonic, _machInst, No_OpClass), warned(false),
+ fullMnemonic(_fullMnemonic)
+ {
+ // don't call execute() (which panics) if we're on a
+ // speculative path
+ flags[IsNonSpeculative] = true;
+ }
+
%(BasicExecDeclare)s
std::string
@@ -147,10 +160,7 @@ output exec {{
FailUnimplemented::execute(%(CPU_exec_context)s *xc,
Trace::InstRecord *traceData) const
{
- if (FullSystem)
- return new UndefinedInstruction;
- else
- return new UndefinedInstruction(machInst, false, mnemonic);
+ return new UndefinedInstruction(machInst, false, mnemonic);
}
Fault
@@ -158,7 +168,8 @@ output exec {{
Trace::InstRecord *traceData) const
{
if (!warned) {
- warn("\tinstruction '%s' unimplemented\n", mnemonic);
+ warn("\tinstruction '%s' unimplemented\n",
+ fullMnemonic.size() ? fullMnemonic.c_str() : mnemonic);
warned = true;
}