| // Copyright (c) 2011-2020 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(ExtMachInst machInst); |
| StaticInstPtr decodeLoadsStores(ExtMachInst machInst); |
| StaticInstPtr decodeDataProcReg(ExtMachInst machInst); |
| |
| template <typename DecoderFeatures> |
| StaticInstPtr decodeFpAdvSIMD(ExtMachInst machInst); |
| StaticInstPtr decodeFp(ExtMachInst machInst); |
| template <typename DecoderFeatures> |
| 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) |
| { |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rdsp = makeSP(rd); |
| IntRegIndex rdzr = makeZero(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, rdzr, INTREG_ZERO, sext<21>(imm)); |
| else |
| return new AdrpXImm(machInst, rdzr, 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, 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: |
| { |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex 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: |
| { |
| IntRegIndex rm = (IntRegIndex)(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(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); |
| |
| 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); |
| IntRegIndex rt = (IntRegIndex)(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, INTREG_X30); |
| } |
| break; |
| case 0x1: |
| switch (op2) { |
| case 0x0: |
| return new Pacia1716(machInst, INTREG_X17, |
| INTREG_X16); |
| case 0x2: |
| return new Pacib1716(machInst, INTREG_X17, |
| INTREG_X16); |
| case 0x4: |
| return new Autia1716(machInst, INTREG_X17, |
| INTREG_X16); |
| case 0x6: |
| return new Autib1716(machInst, INTREG_X17, |
| INTREG_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, |
| INTREG_X30, INTREG_ZERO); |
| case 0x1: |
| return new Paciasp(machInst, |
| INTREG_X30, INTREG_SPX); |
| case 0x2: |
| return new Pacibz(machInst, |
| INTREG_X30, INTREG_ZERO); |
| case 0x3: |
| return new Pacibsp(machInst, |
| INTREG_X30, INTREG_SPX); |
| case 0x4: |
| return new Autiaz(machInst, |
| INTREG_X30, INTREG_ZERO); |
| case 0x5: |
| return new Autiasp(machInst, |
| INTREG_X30, INTREG_SPX); |
| case 0x6: |
| return new Autibz(machInst, |
| INTREG_X30, INTREG_ZERO); |
| case 0x7: |
| return new Autibsp(machInst, |
| INTREG_X30, INTREG_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: |
| 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: 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 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); |
| if (read) { |
| if ((miscReg == MISCREG_DC_CIVAC_Xt) || |
| (miscReg == MISCREG_DC_CVAC_Xt) || |
| (miscReg == MISCREG_DC_IVAC_Xt) || |
| (miscReg == MISCREG_DC_ZVA_Xt)) { |
| return new Unknown64(machInst); |
| } |
| } |
| // 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); |
| |
| uint32_t iss = msrMrs64IssBuild( |
| read, op0, op1, crn, crm, op2, rt); |
| |
| return new MiscRegImplDefined64( |
| read ? "mrs" : "msr", |
| machInst, miscReg, read, iss, full_mnemonic, |
| miscRegInfo[miscReg][MISCREG_WARN_NOT_FAIL]); |
| |
| } 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 (read) { |
| StaticInstPtr si = new Mrs64(machInst, rt, miscReg, iss); |
| if (miscRegInfo[miscReg][MISCREG_UNVERIFIABLE]) |
| si->setFlag(StaticInst::IsUnverifiable); |
| return si; |
| } else { |
| switch (miscReg) { |
| case MISCREG_DC_ZVA_Xt: |
| return new Dczva(machInst, rt, miscReg, iss); |
| case MISCREG_DC_CVAU_Xt: |
| return new Dccvau(machInst, rt, miscReg, iss); |
| case MISCREG_DC_CVAC_Xt: |
| return new Dccvac(machInst, rt, miscReg, iss); |
| case MISCREG_DC_CIVAC_Xt: |
| return new Dccivac(machInst, rt, miscReg, iss); |
| case MISCREG_DC_IVAC_Xt: |
| return new Dcivac(machInst, rt, miscReg, iss); |
| default: |
| return new Msr64(machInst, 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(read ? "mrs" : "msr", |
| machInst, |
| csprintf("%s %s", |
| read ? "mrs" : "msr", |
| miscRegName[miscReg])); |
| } |
| } |
| 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); |
| IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5); |
| IntRegIndex rm = (IntRegIndex)(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; |
| IntRegIndex rt = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint8_t)bits(machInst, 9, 5); |
| IntRegIndex rnsp = makeSP(rn); |
| IntRegIndex rs = (IntRegIndex)(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); |
| 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); |
| 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; |
| 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) { |
| uint8_t group = bits(machInst, 11, 10); |
| switch (group) { |
| case 0x0: |
| { |
| if ((switchVal & 0x7) == 0x2 && |
| bits(machInst, 20, 12) == 0x1fc) { |
| IntRegIndex rt = (IntRegIndex)(uint32_t) |
| bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t) |
| bits(machInst, 9, 5); |
| IntRegIndex 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: |
| { |
| IntRegIndex rt = (IntRegIndex)(uint32_t) |
| bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(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); |
| 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); |
| |
| } |
| } |
| 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); |
| } |
| } |
| 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); |
| IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rdzr = makeZero(rd); |
| 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, 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); |
| IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rdzr = makeZero(rd); |
| 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, 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); |
| IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rdsp = makeSP(rd); |
| IntRegIndex rdzr = makeZero(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, 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); |
| IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rdzr = makeZero(rd); |
| 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, 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); |
| 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 rdzr = makeZero(rd); |
| 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, 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, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0x9: |
| if (rn == 0x1f) |
| return new Pacizb(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xa: |
| if (rn == 0x1f) |
| return new Pacdza(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xb: |
| if (rn == 0x1f) |
| return new Pacdzb(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xc: |
| if (rn == 0x1f) |
| return new Autiza(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xd: |
| if (rn == 0x1f) |
| return new Autizb(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xe: |
| if (rn == 0x1f) |
| return new Autdza(machInst, rd, |
| INTREG_ZERO); |
| else |
| return new Unknown64(machInst); |
| case 0xf: |
| if (rn == 0x1f) |
| return new Autdzb(machInst, rd, |
| INTREG_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); |
| IntRegIndex rd = (IntRegIndex)(uint8_t)bits(machInst, 4, 0); |
| IntRegIndex rdzr = makeZero(rd); |
| 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, 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 <typename DecoderFeatures> |
| StaticInstPtr |
| decodeAdvSIMD(ExtMachInst machInst) |
| { |
| if (bits(machInst, 24) == 1) { |
| if (bits(machInst, 10) == 0) { |
| return decodeNeonIndexedElem<DecoderFeatures>(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<DecoderFeatures>(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<DecoderFeatures>(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 |