// Copyright (c) 2011-2022 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. output header {{ namespace Aarch64 { StaticInstPtr decodeDataProcImm(ExtMachInst machInst); StaticInstPtr decodeBranchExcSys(const Decoder &dec, ExtMachInst machInst); StaticInstPtr decodeLoadsStores(ExtMachInst machInst); StaticInstPtr decodeDataProcReg(ExtMachInst machInst); template StaticInstPtr decodeFpAdvSIMD(ExtMachInst machInst); StaticInstPtr decodeFp(ExtMachInst machInst); template StaticInstPtr decodeAdvSIMD(ExtMachInst machInst); StaticInstPtr decodeAdvSIMDScalar(ExtMachInst machInst); StaticInstPtr decodeSveInt(ExtMachInst machInst); StaticInstPtr decodeSveFp(ExtMachInst machInst); StaticInstPtr decodeSveMem(ExtMachInst machInst); StaticInstPtr decodeGem5Ops(ExtMachInst machInst); } }}; output decoder {{ namespace Aarch64 { StaticInstPtr decodeDataProcImm(ExtMachInst machInst) { RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rdsp = makeSP(rd); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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, rdzr, int_reg::Zero, sext<21>(imm)); else return new AdrpXImm(machInst, rdzr, int_reg::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, rdzr, rnsp, imm); case 0x2: return new SubXImm(machInst, rdsp, rnsp, imm); case 0x3: return new SubXImmCc(machInst, rdzr, rnsp, imm); default: GEM5_UNREACHABLE; } } 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, rdzr, rn, imm); default: GEM5_UNREACHABLE; } } case 0x5: { RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); uint32_t imm16 = bits(machInst, 20, 5); uint32_t hw = bits(machInst, 22, 21); switch (opc) { case 0x0: return new Movn(machInst, rdzr, imm16, hw * 16); case 0x1: return new Unknown64(machInst); case 0x2: return new Movz(machInst, rdzr, imm16, hw * 16); case 0x3: return new Movk(machInst, rdzr, imm16, hw * 16); default: GEM5_UNREACHABLE; } } case 0x6: if ((sf != n) || (!sf && (bits(immr, 5) || bits(imms, 5)))) return new Unknown64(machInst); switch (opc) { case 0x0: return new Sbfm64(machInst, rdzr, rn, immr, imms); case 0x1: return new Bfm64(machInst, rdzr, rn, immr, imms); case 0x2: return new Ubfm64(machInst, rdzr, rn, immr, imms); case 0x3: return new Unknown64(machInst); default: GEM5_UNREACHABLE; } case 0x7: { RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 20, 16); if (opc || bits(machInst, 21)) return new Unknown64(machInst); else return new Extr64(machInst, rdzr, rn, rm, imms); } } return new FailUnimplemented("Unhandled Case8", machInst); } } }}; output decoder {{ namespace Aarch64 { StaticInstPtr decodeBranchExcSys(const Decoder &dec, 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: { RegIndex rt = (RegIndex)(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); auto imm16 = bits(machInst, 20, 5); uint8_t decVal = (bits(machInst, 1, 0) << 0) | (bits(machInst, 23, 21) << 2); switch (decVal) { case 0x01: return new Svc64(machInst, imm16); case 0x02: return new Hvc64(machInst, imm16); case 0x03: return new Smc64(machInst, imm16); case 0x04: return new Brk64(machInst, imm16); case 0x08: return new Hlt64(machInst, imm16); case 0x0c: return new Tcancel64(machInst, imm16); 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); RegIndex rt = (RegIndex)(uint8_t)bits(machInst, 4, 0); switch (op0) { case 0x0: // early out for TME if (crn == 0x3 && op1 == 0x3 && op2 == 0x3) { switch (crm) { case 0x0: if (rt == 0b11111) return new Tcommit64(machInst); else return new Tstart64(machInst, rt); case 0x1: return new Ttest64(machInst, rt); default: return new Unknown64(machInst); } } else if (rt != 0x1f || l) return new Unknown64(machInst); if (crn == 0x2 && op1 == 0x3) { switch (crm) { case 0x0: 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); case 0x7: return new Xpaclri(machInst, int_reg::X30); } break; case 0x1: switch (op2) { case 0x0: return new Pacia1716(machInst, int_reg::X17, int_reg::X16); case 0x2: return new Pacib1716(machInst, int_reg::X17, int_reg::X16); case 0x4: return new Autia1716(machInst, int_reg::X17, int_reg::X16); case 0x6: return new Autib1716(machInst, int_reg::X17, int_reg::X16); } break; case 0x2: switch (op2) { case 0x0: return new WarnUnimplemented( "esb", machInst); case 0x1: return new WarnUnimplemented( "psb csync", machInst); case 0x2: return new WarnUnimplemented( "tsb csync", machInst); case 0x4: return new WarnUnimplemented( "csdb", machInst); } break; case 0x3: switch (op2) { case 0x0: return new Paciaz(machInst, int_reg::X30, int_reg::Zero); case 0x1: return new Paciasp(machInst, int_reg::X30, int_reg::Spx); case 0x2: return new Pacibz(machInst, int_reg::X30, int_reg::Zero); case 0x3: return new Pacibsp(machInst, int_reg::X30, int_reg::Spx); case 0x4: return new Autiaz(machInst, int_reg::X30, int_reg::Zero); case 0x5: return new Autiasp(machInst, int_reg::X30, int_reg::Spx); case 0x6: return new Autibz(machInst, int_reg::X30, int_reg::Zero); case 0x7: return new Autibsp(machInst, int_reg::X30, int_reg::Spx); } break; case 0x4: switch (op2 & 0x1) { case 0x0: return new WarnUnimplemented( "bti", machInst); } break; } return new WarnUnimplemented( "unallocated_hint", machInst); } else if (crn == 0x3 && op1 == 0x3) { switch (op2) { case 0x2: return new Clrex64(machInst); case 0x4: switch (bits(crm, 3, 2)) { case 0x1: // Non-Shareable return new Dsb64Local(machInst); case 0x0: // OuterShareable case 0x2: // InnerShareable case 0x3: // FullSystem return new Dsb64Shareable( machInst, dec.dvmEnabled); default: GEM5_UNREACHABLE; } case 0x5: return new Dmb64(machInst); case 0x6: return new Isb64(machInst); default: return new Unknown64(machInst); } } else if (crn == 0x4) { // MSR immediate: moving immediate value to selected // bits of the PSTATE switch (op1 << 3 | op2) { case 0x3: // UAO return new MsrImm64( machInst, MISCREG_UAO, crm); case 0x4: // PAN return new MsrImm64( machInst, MISCREG_PAN, crm); case 0x5: // SP return new MsrImm64( machInst, MISCREG_SPSEL, crm); case 0x1b: // SVE SVCR - SMSTART/SMSTOP return decodeSmeMgmt(machInst); case 0x1e: // DAIFSet return new MsrImmDAIFSet64( machInst, MISCREG_DAIF, crm); case 0x1f: // DAIFClr return new MsrImmDAIFClr64( machInst, MISCREG_DAIF, 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); // Check for invalid registers if (miscReg == MISCREG_UNKNOWN) { auto full_mnemonic = csprintf("%s op0:%d op1:%d crn:%d crm:%d op2:%d", read ? "mrs" : "msr", op0, op1, crn, crm, op2); return new FailUnimplemented(read ? "mrs" : "msr", machInst, full_mnemonic); } else if (miscReg == MISCREG_IMPDEF_UNIMPL) { auto full_mnemonic = csprintf("%s op0:%d op1:%d crn:%d crm:%d op2:%d", read ? "mrs" : "msr", op0, op1, crn, crm, op2); return new MiscRegImplDefined64( read ? "mrs" : "msr", machInst, MiscRegNum64(op0, op1, crn, crm, op2), rt, read, full_mnemonic); } else { if (read) { switch (miscReg) { case MISCREG_NZCV: return new MrsNZCV64(machInst, rt, miscReg); case MISCREG_DC_CIVAC_Xt: case MISCREG_DC_CVAC_Xt: case MISCREG_DC_IVAC_Xt: case MISCREG_DC_ZVA_Xt: return new Unknown64(machInst); default: { StaticInstPtr si = new Mrs64(machInst, rt, miscReg); if (lookUpMiscReg[miscReg].info[MISCREG_UNVERIFIABLE]) si->setFlag(StaticInst::IsUnverifiable); return si; } } } else { switch (miscReg) { case MISCREG_NZCV: return new MsrNZCV64(machInst, miscReg, rt); case MISCREG_DC_ZVA_Xt: return new Dczva(machInst, rt, miscReg); case MISCREG_DC_CVAU_Xt: return new Dccvau(machInst, rt, miscReg); case MISCREG_DC_CVAC_Xt: return new Dccvac(machInst, rt, miscReg); case MISCREG_DC_CIVAC_Xt: return new Dccivac(machInst, rt, miscReg); case MISCREG_DC_IVAC_Xt: return new Dcivac(machInst, rt, miscReg); // 64-bit TLBIs split into "Local" // and "Shareable" case MISCREG_TLBI_ALLE3: case MISCREG_TLBI_ALLE2: case MISCREG_TLBI_ALLE1: case MISCREG_TLBI_VMALLS12E1: case MISCREG_TLBI_VMALLE1: case MISCREG_TLBI_VAE3_Xt: case MISCREG_TLBI_VALE3_Xt: case MISCREG_TLBI_VAE2_Xt: case MISCREG_TLBI_VALE2_Xt: case MISCREG_TLBI_VAE1_Xt: case MISCREG_TLBI_VALE1_Xt: case MISCREG_TLBI_ASIDE1_Xt: case MISCREG_TLBI_VAAE1_Xt: case MISCREG_TLBI_VAALE1_Xt: case MISCREG_TLBI_IPAS2E1_Xt: case MISCREG_TLBI_IPAS2LE1_Xt: return new Tlbi64LocalHub( machInst, miscReg, rt); case MISCREG_TLBI_ALLE3IS: case MISCREG_TLBI_ALLE2IS: case MISCREG_TLBI_ALLE1IS: case MISCREG_TLBI_VMALLS12E1IS: case MISCREG_TLBI_VMALLE1IS: case MISCREG_TLBI_VAE3IS_Xt: case MISCREG_TLBI_VALE3IS_Xt: case MISCREG_TLBI_VAE2IS_Xt: case MISCREG_TLBI_VALE2IS_Xt: case MISCREG_TLBI_VAE1IS_Xt: case MISCREG_TLBI_VALE1IS_Xt: case MISCREG_TLBI_ASIDE1IS_Xt: case MISCREG_TLBI_VAAE1IS_Xt: case MISCREG_TLBI_VAALE1IS_Xt: case MISCREG_TLBI_IPAS2E1IS_Xt: case MISCREG_TLBI_IPAS2LE1IS_Xt: return new Tlbi64ShareableHub( machInst, miscReg, rt, dec.dvmEnabled); default: return new Msr64(machInst, miscReg, rt); } } } } break; default: GEM5_UNREACHABLE; } } 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, 12); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 4, 0); uint8_t op4 = bits(machInst, 4, 0); if (op2 != 0x1f || op3 != 0x0) return new Unknown64(machInst); switch (opc) { case 0x0: if (bits(machInst, 11) == 0) return new Br64(machInst, rn); else if (op4 != 0x1f) return new Unknown64(machInst); // 24(Z):0, 11(A):1 if (bits(machInst, 10) == 0) return new Braaz(machInst, rn); else return new Brabz(machInst, rn); case 0x1: if (bits(machInst, 11) == 0) return new Blr64(machInst, rn); else if (op4 != 0x1f) return new Unknown64(machInst); // 24(Z):0, 11(A):1 if (bits(machInst, 10) == 0) return new Blraaz(machInst, rn); else return new Blrabz(machInst, rn); case 0x2: if (op4 == 0x1f) { bool m = bits(machInst, 10); if (m) return new Retab(machInst); else return new Retaa(machInst); } else return new Ret64(machInst, rn); case 0x4: if (rn != 0x1f) return new Unknown64(machInst); if (bits(machInst, 11) == 0) return new Eret64(machInst); else if (op4 != 0x1f) return new Unknown64(machInst); // 24(Z):0, 11(A):1 if (bits(machInst, 10) == 0) return new Eretaa(machInst); else return new Eretab(machInst); case 0x5: if (rn != 0x1f) return new Unknown64(machInst); return new FailUnimplemented("dret", machInst); case 0x8: if (bits(machInst, 11) == 0) return new Unknown64(machInst); if (bits(machInst, 10) == 0) return new Braa(machInst, rn, makeSP(rm)); else return new Brab(machInst, rn, makeSP(rm)); case 0x9: if (bits(machInst, 11) == 0) return new Unknown64(machInst); if (bits(machInst, 10) == 0) return new Blraa(machInst, rn, makeSP(rm)); else return new Blrab(machInst, rn, makeSP(rm)); default: return new Unknown64(machInst); } } [[fallthrough]]; default: return new Unknown64(machInst); } return new FailUnimplemented("Unhandled Case7", machInst); } } }}; output decoder {{ namespace Aarch64 { StaticInstPtr decodeAtomicArithOp(ExtMachInst machInst) { uint8_t opc = bits(machInst, 14, 12); uint8_t o3 = bits(machInst, 15); uint8_t size_ar = bits(machInst, 23, 22)<<0 | bits(machInst, 31, 30)<<2; RegIndex rt = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rnsp = makeSP(rn); RegIndex rs = (RegIndex)(uint8_t)bits(machInst, 20, 16); uint8_t A_rt = bits(machInst, 4, 0)<<0 | bits(machInst, 23)<<5; switch(opc) { case 0x0: switch(size_ar){ case 0x0: if (o3 == 1) return new SWPB(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDB(machInst, rt, rnsp, rs); else return new LDADDB(machInst, rt, rnsp, rs); case 0x1 : if (o3 == 1) return new SWPLB(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDLB(machInst, rt, rnsp, rs); else return new LDADDLB(machInst, rt, rnsp, rs); case 0x2: if (o3 == 1) return new SWPAB(machInst, rt, rnsp, rs); else return new LDADDAB(machInst, rt, rnsp, rs); case 0x3: if (o3 == 1) return new SWPLAB(machInst, rt, rnsp, rs); else return new LDADDLAB(machInst, rt, rnsp, rs); case 0x4: if (o3 == 1) return new SWPH(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDH(machInst, rt, rnsp, rs); else return new LDADDH(machInst, rt, rnsp, rs); case 0x5 : if (o3 == 1) return new SWPLH(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDLH(machInst, rt, rnsp, rs); else return new LDADDLH(machInst, rt, rnsp, rs); case 0x6: if (o3 == 1) return new SWPAH(machInst, rt, rnsp, rs); else return new LDADDAH(machInst, rt, rnsp, rs); case 0x7: if (o3 == 1) return new SWPLAH(machInst, rt, rnsp, rs); else return new LDADDLAH(machInst, rt, rnsp, rs); case 0x8: if (o3 == 1) return new SWP(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADD(machInst, rt, rnsp, rs); else return new LDADD(machInst, rt, rnsp, rs); case 0x9 : if (o3 == 1) return new SWPL(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDL(machInst, rt, rnsp, rs); else return new LDADDL(machInst, rt, rnsp, rs); case 0xa: if (o3 == 1) return new SWPA(machInst, rt, rnsp, rs); else return new LDADDA(machInst, rt, rnsp, rs); case 0xb: if (o3 == 1) return new SWPLA(machInst, rt, rnsp, rs); else return new LDADDLA(machInst, rt, rnsp, rs); case 0xc: if (o3 == 1) return new SWP64(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADD64(machInst, rt, rnsp, rs); else return new LDADD64(machInst, rt, rnsp, rs); case 0xd : if (o3 == 1) return new SWPL64(machInst, rt, rnsp, rs); else if (A_rt == 0x1f) return new STADDL64(machInst, rt, rnsp, rs); else return new LDADDL64(machInst, rt, rnsp, rs); case 0xe: if (o3 == 1) return new SWPA64(machInst, rt, rnsp, rs); else return new LDADDA64(machInst, rt, rnsp, rs); case 0xf: if (o3 == 1) return new SWPLA64(machInst, rt, rnsp, rs); else return new LDADDLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x1: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STCLRB(machInst, rt, rnsp, rs); else return new LDCLRB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STCLRLB(machInst, rt, rnsp, rs); else return new LDCLRLB(machInst, rt, rnsp, rs); case 0x2: return new LDCLRAB(machInst, rt, rnsp, rs); case 0x3: return new LDCLRLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STCLRH(machInst, rt, rnsp, rs); else return new LDCLRH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STCLRLH(machInst, rt, rnsp, rs); else return new LDCLRLH(machInst, rt, rnsp, rs); case 0x6: return new LDCLRAH(machInst, rt, rnsp, rs); case 0x7: return new LDCLRLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STCLR(machInst, rt, rnsp, rs); else return new LDCLR(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STCLRL(machInst, rt, rnsp, rs); else return new LDCLRL(machInst, rt, rnsp, rs); case 0xa: return new LDCLRA(machInst, rt, rnsp, rs); case 0xb: return new LDCLRLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STCLR64(machInst, rt, rnsp, rs); else return new LDCLR64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STCLRL64(machInst, rt, rnsp, rs); else return new LDCLRL64(machInst, rt, rnsp, rs); case 0xe: return new LDCLRA64(machInst, rt, rnsp, rs); case 0xf: return new LDCLRLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x2: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STEORB(machInst, rt, rnsp, rs); else return new LDEORB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STEORLB(machInst, rt, rnsp, rs); else return new LDEORLB(machInst, rt, rnsp, rs); case 0x2: return new LDEORAB(machInst, rt, rnsp, rs); case 0x3: return new LDEORLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STEORH(machInst, rt, rnsp, rs); else return new LDEORH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STEORLH(machInst, rt, rnsp, rs); else return new LDEORLH(machInst, rt, rnsp, rs); case 0x6: return new LDEORAH(machInst, rt, rnsp, rs); case 0x7: return new LDEORLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STEOR(machInst, rt, rnsp, rs); else return new LDEOR(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STEORL(machInst, rt, rnsp, rs); else return new LDEORL(machInst, rt, rnsp, rs); case 0xa: return new LDEORA(machInst, rt, rnsp, rs); case 0xb: return new LDEORLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STEOR64(machInst, rt, rnsp, rs); else return new LDEOR64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STEORL64(machInst, rt, rnsp, rs); else return new LDEORL64(machInst, rt, rnsp, rs); case 0xe: return new LDEORA64(machInst, rt, rnsp, rs); case 0xf: return new LDEORLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x3: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STSETB(machInst, rt, rnsp, rs); else return new LDSETB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STSETLB(machInst, rt, rnsp, rs); else return new LDSETLB(machInst, rt, rnsp, rs); case 0x2: return new LDSETAB(machInst, rt, rnsp, rs); case 0x3: return new LDSETLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STSETH(machInst, rt, rnsp, rs); else return new LDSETH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STSETLH(machInst, rt, rnsp, rs); else return new LDSETLH(machInst, rt, rnsp, rs); case 0x6: return new LDSETAH(machInst, rt, rnsp, rs); case 0x7: return new LDSETLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STSET(machInst, rt, rnsp, rs); else return new LDSET(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STSETL(machInst, rt, rnsp, rs); else return new LDSETL(machInst, rt, rnsp, rs); case 0xa: return new LDSETA(machInst, rt, rnsp, rs); case 0xb: return new LDSETLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STSET64(machInst, rt, rnsp, rs); else return new LDSET64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STSETL64(machInst, rt, rnsp, rs); else return new LDSETL64(machInst, rt, rnsp, rs); case 0xe: return new LDSETA64(machInst, rt, rnsp, rs); case 0xf: return new LDSETLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x4: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STSMAXB(machInst, rt, rnsp, rs); else return new LDSMAXB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STSMAXLB(machInst, rt, rnsp, rs); else return new LDSMAXLB(machInst, rt, rnsp, rs); case 0x2: return new LDSMAXAB(machInst, rt, rnsp, rs); case 0x3: return new LDSMAXLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STSMAXH(machInst, rt, rnsp, rs); else return new LDSMAXH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STSMAXLH(machInst, rt, rnsp, rs); else return new LDSMAXLH(machInst, rt, rnsp, rs); case 0x6: return new LDSMAXAH(machInst, rt, rnsp, rs); case 0x7: return new LDSMAXLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STSMAX(machInst, rt, rnsp, rs); else return new LDSMAX(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STSMAXL(machInst, rt, rnsp, rs); else return new LDSMAXL(machInst, rt, rnsp, rs); case 0xa: return new LDSMAXA(machInst, rt, rnsp, rs); case 0xb: return new LDSMAXLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STSMAX64(machInst, rt, rnsp, rs); else return new LDSMAX64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STSMAXL64(machInst, rt, rnsp, rs); else return new LDSMAXL64(machInst, rt, rnsp, rs); case 0xe: return new LDSMAXA64(machInst, rt, rnsp, rs); case 0xf: return new LDSMAXLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x5: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STSMINB(machInst, rt, rnsp, rs); else return new LDSMINB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STSMINLB(machInst, rt, rnsp, rs); else return new LDSMINLB(machInst, rt, rnsp, rs); case 0x2: return new LDSMINAB(machInst, rt, rnsp, rs); case 0x3: return new LDSMINLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STSMINH(machInst, rt, rnsp, rs); else return new LDSMINH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STSMINLH(machInst, rt, rnsp, rs); else return new LDSMINLH(machInst, rt, rnsp, rs); case 0x6: return new LDSMINAH(machInst, rt, rnsp, rs); case 0x7: return new LDSMINLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STSMIN(machInst, rt, rnsp, rs); else return new LDSMIN(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STSMINL(machInst, rt, rnsp, rs); else return new LDSMINL(machInst, rt, rnsp, rs); case 0xa: return new LDSMINA(machInst, rt, rnsp, rs); case 0xb: return new LDSMINLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STSMIN64(machInst, rt, rnsp, rs); else return new LDSMIN64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STSMINL64(machInst, rt, rnsp, rs); else return new LDSMINL64(machInst, rt, rnsp, rs); case 0xe: return new LDSMINA64(machInst, rt, rnsp, rs); case 0xf: return new LDSMINLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x6: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STUMAXB(machInst, rt, rnsp, rs); else return new LDUMAXB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STUMAXLB(machInst, rt, rnsp, rs); else return new LDUMAXLB(machInst, rt, rnsp, rs); case 0x2: return new LDUMAXAB(machInst, rt, rnsp, rs); case 0x3: return new LDUMAXLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STUMAXH(machInst, rt, rnsp, rs); else return new LDUMAXH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STUMAXLH(machInst, rt, rnsp, rs); else return new LDUMAXLH(machInst, rt, rnsp, rs); case 0x6: return new LDUMAXAH(machInst, rt, rnsp, rs); case 0x7: return new LDUMAXLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STUMAX(machInst, rt, rnsp, rs); else return new LDUMAX(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STUMAXL(machInst, rt, rnsp, rs); else return new LDUMAXL(machInst, rt, rnsp, rs); case 0xa: return new LDUMAXA(machInst, rt, rnsp, rs); case 0xb: return new LDUMAXLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STUMAX64(machInst, rt, rnsp, rs); else return new LDUMAX64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STUMAXL64(machInst, rt, rnsp, rs); else return new LDUMAXL64(machInst, rt, rnsp, rs); case 0xe: return new LDUMAXA64(machInst, rt, rnsp, rs); case 0xf: return new LDUMAXLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0x7: switch(size_ar){ case 0x0: if (A_rt == 0x1f) return new STUMINB(machInst, rt, rnsp, rs); else return new LDUMINB(machInst, rt, rnsp, rs); case 0x1 : if (A_rt == 0x1f) return new STUMINLB(machInst, rt, rnsp, rs); else return new LDUMINLB(machInst, rt, rnsp, rs); case 0x2: return new LDUMINAB(machInst, rt, rnsp, rs); case 0x3: return new LDUMINLAB(machInst, rt, rnsp, rs); case 0x4: if (A_rt == 0x1f) return new STUMINH(machInst, rt, rnsp, rs); else return new LDUMINH(machInst, rt, rnsp, rs); case 0x5 : if (A_rt == 0x1f) return new STUMINLH(machInst, rt, rnsp, rs); else return new LDUMINLH(machInst, rt, rnsp, rs); case 0x6: return new LDUMINAH(machInst, rt, rnsp, rs); case 0x7: return new LDUMINLAH(machInst, rt, rnsp, rs); case 0x8: if (A_rt == 0x1f) return new STUMIN(machInst, rt, rnsp, rs); else return new LDUMIN(machInst, rt, rnsp, rs); case 0x9 : if (A_rt == 0x1f) return new STUMINL(machInst, rt, rnsp, rs); else return new LDUMINL(machInst, rt, rnsp, rs); case 0xa: return new LDUMINA(machInst, rt, rnsp, rs); case 0xb: return new LDUMINLA(machInst, rt, rnsp, rs); case 0xc: if (A_rt == 0x1f) return new STUMIN64(machInst, rt, rnsp, rs); else return new LDUMIN64(machInst, rt, rnsp, rs); case 0xd : if (A_rt == 0x1f) return new STUMINL64(machInst, rt, rnsp, rs); else return new LDUMINL64(machInst, rt, rnsp, rs); case 0xe: return new LDUMINA64(machInst, rt, rnsp, rs); case 0xf: return new LDUMINLA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } default: return new Unknown64(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); RegIndex rt = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rnsp = makeSP(rn); RegIndex rt2 = (RegIndex)(uint8_t)bits(machInst, 14, 10); RegIndex rs = (RegIndex)(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); default: GEM5_UNREACHABLE; } 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); default: GEM5_UNREACHABLE; } case 0x2: switch (size) { case 0x0: return new CASP32(machInst, rt, rnsp, rs); case 0x1: return new CASP64(machInst, rt, rnsp, rs); case 0x2: return new STXPW64(machInst, rs, rt, rt2, rnsp); case 0x3: return new STXPX64(machInst, rs, rt, rt2, rnsp); default: GEM5_UNREACHABLE; } case 0x3: switch (size) { case 0x0: return new CASPL32(machInst, rt, rnsp, rs); case 0x1: return new CASPL64(machInst, rt, rnsp, rs); case 0x2: return new STLXPW64(machInst, rs, rt, rt2, rnsp); case 0x3: return new STLXPX64(machInst, rs, rt, rt2, rnsp); default: GEM5_UNREACHABLE; } 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); default: GEM5_UNREACHABLE; } 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); default: GEM5_UNREACHABLE; } case 0x6: switch (size) { case 0x0: return new CASPA32(machInst, rt, rnsp, rs); case 0x1: return new CASPA64(machInst, rt, rnsp, rs); case 0x2: return new LDXPW64(machInst, rt, rt2, rnsp); case 0x3: return new LDXPX64(machInst, rt, rt2, rnsp); default: GEM5_UNREACHABLE; } case 0x7: switch (size) { case 0x0: return new CASPAL32(machInst, rt, rnsp, rs); case 0x1: return new CASPAL64(machInst, rt, rnsp, rs); case 0x2: return new LDAXPW64(machInst, rt, rt2, rnsp); case 0x3: return new LDAXPX64(machInst, rt, rt2, rnsp); default: GEM5_UNREACHABLE; } 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); default: GEM5_UNREACHABLE; } case 0xa: switch (size) { case 0x0: return new CASB(machInst, rt, rnsp, rs); case 0x1: return new CASH(machInst, rt, rnsp, rs); case 0x2: return new CAS32(machInst, rt, rnsp, rs); case 0x3: return new CAS64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0xb: switch (size) { case 0x0: return new CASLB(machInst, rt, rnsp, rs); case 0x1: return new CASLH(machInst, rt, rnsp, rs); case 0x2: return new CASL32(machInst, rt, rnsp, rs); case 0x3: return new CASL64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } 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: GEM5_UNREACHABLE; } case 0xe: switch (size) { case 0x0: return new CASAB(machInst, rt, rnsp, rs); case 0x1: return new CASAH(machInst, rt, rnsp, rs); case 0x2: return new CASA32(machInst, rt, rnsp, rs); case 0x3: return new CASA64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } case 0xf: switch (size) { case 0x0: return new CASALB(machInst, rt, rnsp, rs); case 0x1: return new CASALH(machInst, rt, rnsp, rs); case 0x2: return new CASAL32(machInst, rt, rnsp, rs); case 0x3: return new CASAL64(machInst, rt, rnsp, rs); default: GEM5_UNREACHABLE; } 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; RegIndex rt = (RegIndex)(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; RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rt = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rt2 = (RegIndex)(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); RegIndex rt = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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) { uint8_t group = bits(machInst, 11, 10); switch (group) { case 0x0: { if ((switchVal & 0x7) == 0x2 && bits(machInst, 20, 12) == 0x1fc) { RegIndex rt = (RegIndex)(uint32_t) bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t) bits(machInst, 9, 5); RegIndex rnsp = makeSP(rn); uint8_t size = bits(machInst, 31, 30); switch (size) { case 0x0: return new LDAPRB64(machInst, rt, rnsp); case 0x1: return new LDAPRH64(machInst, rt, rnsp); case 0x2: return new LDAPRW64(machInst, rt, rnsp); case 0x3: return new LDAPRX64(machInst, rt, rnsp); default: GEM5_UNREACHABLE; } } else { return decodeAtomicArithOp(machInst); } } case 0x1: case 0x3: { RegIndex rt = (RegIndex)(uint32_t) bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t) bits(machInst, 9, 5); uint8_t s = bits(machInst, 22); uint64_t imm9 = bits(machInst, 20, 12); uint64_t imm10 = sext<10>(s<<9 | imm9)<<3; uint8_t val = bits(machInst, 23)<<1 | bits(machInst, 11); switch (val) { case 0x0: return new LDRAA_REG(machInst, rt, makeSP(rn), imm10); case 0x1: return new LDRAA_PRE(machInst, rt, makeSP(rn), imm10); case 0x2: return new LDRAB_REG(machInst, rt, makeSP(rn), imm10); case 0x3: return new LDRAB_PRE(machInst, rt, makeSP(rn), imm10); default: GEM5_UNREACHABLE; } } case 0x2: { if (!bits(machInst, 14)) return new Unknown64(machInst); RegIndex rt = (RegIndex)(uint32_t) bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t) bits(machInst, 9, 5); RegIndex rnsp = makeSP(rn); RegIndex rm = (RegIndex)(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); } } default: return new Unknown64(machInst); } } else { // bit 29:27=111, 25:24=00, 21=0 switch (bits(machInst, 11, 10)) { case 0x0: { RegIndex rt = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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: { RegIndex rt = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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: { RegIndex rt = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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: { RegIndex rt = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex 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); } } default: GEM5_UNREACHABLE; } } } default: GEM5_UNREACHABLE; } 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); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 20, 16); switch (switchVal) { case 0x0: return new AndXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x1: return new BicXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x2: return new OrrXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x3: return new OrnXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x4: return new EorXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x5: return new EonXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x6: return new AndXSRegCc(machInst, rdzr, rn, rm, imm6, type); case 0x7: return new BicXSRegCc(machInst, rdzr, rn, rm, imm6, type); default: GEM5_UNREACHABLE; } } 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); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 20, 16); switch (switchVal) { case 0x0: return new AddXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x1: return new AddXSRegCc(machInst, rdzr, rn, rm, imm6, type); case 0x2: return new SubXSReg(machInst, rdzr, rn, rm, imm6, type); case 0x3: return new SubXSRegCc(machInst, rdzr, rn, rm, imm6, type); default: GEM5_UNREACHABLE; } } 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); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdsp = makeSP(rd); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rnsp = makeSP(rn); RegIndex rm = (RegIndex)(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, rdzr, rnsp, rm, type, imm3); case 0x2: return new SubXEReg(machInst, rdsp, rnsp, rm, type, imm3); case 0x3: return new SubXERegCc(machInst, rdzr, rnsp, rm, type, imm3); default: GEM5_UNREACHABLE; } } } case 0x2: { if (bits(machInst, 21) == 1) return new Unknown64(machInst); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(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, rdzr, rn, rm, 0, LSL); case 0x1: return new AdcXSRegCc(machInst, rdzr, rn, rm, 0, LSL); case 0x2: return new SbcXSReg(machInst, rdzr, rn, rm, 0, LSL); case 0x3: return new SbcXSRegCc(machInst, rdzr, rn, rm, 0, LSL); default: GEM5_UNREACHABLE; } } 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); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); if (bits(machInst, 11) == 0) { RegIndex rm = (RegIndex)(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); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 20, 16); ConditionCode cond = (ConditionCode)(uint8_t)bits(machInst, 15, 12); switch (switchVal) { case 0x0: return new Csel64(machInst, rdzr, rn, rm, cond); case 0x1: return new Csinc64(machInst, rdzr, rn, rm, cond); case 0x2: return new Csinv64(machInst, rdzr, rn, rm, cond); case 0x3: return new Csneg64(machInst, rdzr, rn, rm, cond); default: GEM5_UNREACHABLE; } } 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, rdzr, rn, rm); case 0x3: return new Sdiv64(machInst, rdzr, rn, rm); case 0x8: return new Lslv64(machInst, rdzr, rn, rm); case 0x9: return new Lsrv64(machInst, rdzr, rn, rm); case 0xa: return new Asrv64(machInst, rdzr, rn, rm); case 0xb: return new Rorv64(machInst, rdzr, rn, rm); case 0xc: return new Pacga(machInst, rd, rn, makeSP(rm)); case 0x10: return new Crc32b64(machInst, rdzr, rn, rm); case 0x11: return new Crc32h64(machInst, rdzr, rn, rm); case 0x12: return new Crc32w64(machInst, rdzr, rn, rm); case 0x13: return new Crc32x64(machInst, rdzr, rn, rm); case 0x14: return new Crc32cb64(machInst, rdzr, rn, rm); case 0x15: return new Crc32ch64(machInst, rdzr, rn, rm); case 0x16: return new Crc32cw64(machInst, rdzr, rn, rm); case 0x17: return new Crc32cx64(machInst, rdzr, rn, rm); default: return new Unknown64(machInst); } } else { uint8_t dm = bits(machInst, 20, 14); switch(dm){ case 0x4: { uint8_t zflags = bits(machInst, 13, 10); switch (zflags) { case 0x0: return new Pacia(machInst, rd, makeSP(rn)); case 0x1: return new Pacib(machInst, rd, makeSP(rn)); case 0x2: return new Pacda(machInst, rd, makeSP(rn)); case 0x3: return new Pacdb(machInst, rd, makeSP(rn)); case 0x4: return new Autia(machInst, rd, makeSP(rn)); case 0x5: return new Autib(machInst, rd, makeSP(rn)); case 0x6: return new Autda(machInst, rd, makeSP(rn)); case 0x7: return new Autdb(machInst, rd, makeSP(rn)); case 0x8: if (rn == 0x1f) return new Paciza(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0x9: if (rn == 0x1f) return new Pacizb(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xa: if (rn == 0x1f) return new Pacdza(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xb: if (rn == 0x1f) return new Pacdzb(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xc: if (rn == 0x1f) return new Autiza(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xd: if (rn == 0x1f) return new Autizb(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xe: if (rn == 0x1f) return new Autdza(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); case 0xf: if (rn == 0x1f) return new Autdzb(machInst, rd, int_reg::Zero); else return new Unknown64(machInst); default: return new Unknown64(machInst); } } case 0x5: { if (rn != 0x1f) return new Unknown64(machInst); bool d = bits(machInst,10); if (d) return new Xpacd(machInst, rd); else return new Xpaci(machInst, rd); } } if (dm != 0 || bits(machInst, 29) != 0) { // dm !=0 and dm != 0x1 return new Unknown64(machInst); } uint8_t switchVal = bits(machInst, 15, 10); switch (switchVal) { case 0x0: return new Rbit64(machInst, rdzr, rn); case 0x1: return new Rev1664(machInst, rdzr, rn); case 0x2: if (bits(machInst, 31) == 0) return new Rev64(machInst, rdzr, rn); else return new Rev3264(machInst, rdzr, rn); case 0x3: if (bits(machInst, 31) != 1) return new Unknown64(machInst); return new Rev64(machInst, rdzr, rn); case 0x4: return new Clz64(machInst, rdzr, rn); case 0x5: return new Cls64(machInst, rdzr, rn); default: return new Unknown64(machInst); } } default: GEM5_UNREACHABLE; } } case 0x3: { if (bits(machInst, 30, 29) != 0x0 || (bits(machInst, 23, 21) != 0 && bits(machInst, 31) == 0)) return new Unknown64(machInst); RegIndex rd = (RegIndex)(uint8_t)bits(machInst, 4, 0); RegIndex rdzr = makeZero(rd); RegIndex rn = (RegIndex)(uint8_t)bits(machInst, 9, 5); RegIndex ra = (RegIndex)(uint8_t)bits(machInst, 14, 10); RegIndex rm = (RegIndex)(uint8_t)bits(machInst, 20, 16); switch (bits(machInst, 23, 21)) { case 0x0: if (bits(machInst, 15) == 0) return new Madd64(machInst, rdzr, ra, rn, rm); else return new Msub64(machInst, rdzr, ra, rn, rm); case 0x1: if (bits(machInst, 15) == 0) return new Smaddl64(machInst, rdzr, ra, rn, rm); else return new Smsubl64(machInst, rdzr, ra, rn, rm); case 0x2: if (bits(machInst, 15) != 0) return new Unknown64(machInst); return new Smulh64(machInst, rdzr, rn, rm); case 0x5: if (bits(machInst, 15) == 0) return new Umaddl64(machInst, rdzr, ra, rn, rm); else return new Umsubl64(machInst, rdzr, ra, rn, rm); case 0x6: if (bits(machInst, 15) != 0) return new Unknown64(machInst); return new Umulh64(machInst, rdzr, rn, rm); default: return new Unknown64(machInst); } } default: GEM5_UNREACHABLE; } return new FailUnimplemented("Unhandled Case2", machInst); } } }}; output decoder {{ namespace Aarch64 { template 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) == 0x4) { return decodeCryptoAES(machInst); } else if (bits(machInst, 20, 17) == 0x8) { return decodeNeonAcrossLanes(machInst); } else { return new Unknown64(machInst); } } else if (bits(machInst, 15) == 1) { return decodeNeon3SameExtra(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); RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(uint32_t)bits(machInst, 20, 16); RegIndex ra = (RegIndex)(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); RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(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); } 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); RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(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, FpDataType::Fp32); 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, FpDataType::Fp64); 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); RegIndex rm = (RegIndex)(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 2: return new FJcvtFpSFixedDW(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); } } GEM5_UNREACHABLE; case 0x1: { if (bits(machInst, 31) || bits(machInst, 29) || bits(machInst, 23)) { return new Unknown64(machInst); } RegIndex rm = (RegIndex)(uint32_t) bits(machInst, 20, 16); RegIndex rn = (RegIndex)(uint32_t) bits(machInst, 9, 5); uint8_t imm = (RegIndex)(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); } RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(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); RegIndex rd = (RegIndex)(uint32_t)bits(machInst, 4, 0); RegIndex rn = (RegIndex)(uint32_t)bits(machInst, 9, 5); RegIndex rm = (RegIndex)(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); } default: GEM5_UNREACHABLE; } } GEM5_UNREACHABLE; } } }}; 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) == 0x4) { return decodeCryptoTwoRegSHA(machInst); } else if (bits(machInst, 20, 17) == 0x8) { return decodeNeonScPwise(machInst); } else { return new Unknown64(machInst); } } else if (bits(machInst, 15) && bits(machInst, 10) == 1) { return decodeNeonSc3SameExtra(machInst); } else if (bits(machInst, 23, 22) == 0 && bits(machInst, 15) == 0) { if (bits(machInst, 10) == 1) { return decodeNeonScCopy(machInst); } else { return decodeCryptoThreeRegSHA(machInst); } } else { return new Unknown64(machInst); } return new FailUnimplemented("Unhandled Case6", machInst); } } }}; output decoder {{ namespace Aarch64 { template 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); } } } }}; let {{ decoder_output =''' namespace Aarch64 {''' for decoderFlavor, type_dict in decoders.items(): decoder_output +=''' template StaticInstPtr decodeFpAdvSIMD<%(df)sDecoder>(ExtMachInst machInst); ''' % { "df" : decoderFlavor } decoder_output +=''' }''' }}; def format Aarch64() {{ decode_block = ''' { using namespace Aarch64; if (bits(machInst, 27) == 0x0) { if (bits(machInst, 28) == 0x0) { if (bits(machInst, 26) == 0x1) { if (bits(machInst, 31) == 0x0) { if (bits(machInst, 25) == 0x1) { return new Unknown64(machInst); } switch (bits(machInst, 30, 29)) { case 0x0: case 0x1: case 0x2: return decodeSveInt(machInst); case 0x3: return decodeSveFp(machInst); } } else { return decodeSveMem(machInst); } } else { if ((bits(machInst, 25) == 0x0) && \ (bits(machInst, 31) == 0x1)) { // bit 31:25=1xx0000 return decodeSmeInst(machInst); } else { return new Unknown64(machInst); } } } else if (bits(machInst, 26) == 0) // bit 28:26=100 return decodeDataProcImm(machInst); else // bit 28:26=101 return decodeBranchExcSys(*this, 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 new Gem5Op64(machInst); } else { // bit 27:25=111 switch(decoderFlavor){ default: return decodeFpAdvSIMD(machInst); } } } ''' }};