| // 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 (bits(machInst, 31) || bits(machInst, 29)) |
| return new Unknown64(machInst); |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5); |
| IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16); |
| IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 14, 10); |
| uint8_t switchVal = (bits(machInst, 23, 21) << 1) | |
| (bits(machInst, 15) << 0); |
| switch (switchVal) { |
| case 0x0: // FMADD Sd = Sa + Sn*Sm |
| return new FMAddS(machInst, rd, rn, rm, ra); |
| case 0x1: // FMSUB Sd = Sa + (-Sn)*Sm |
| return new FMSubS(machInst, rd, rn, rm, ra); |
| case 0x2: // FNMADD Sd = (-Sa) + (-Sn)*Sm |
| return new FNMAddS(machInst, rd, rn, rm, ra); |
| case 0x3: // FNMSUB Sd = (-Sa) + Sn*Sm |
| return new FNMSubS(machInst, rd, rn, rm, ra); |
| case 0x4: // FMADD Dd = Da + Dn*Dm |
| return new FMAddD(machInst, rd, rn, rm, ra); |
| case 0x5: // FMSUB Dd = Da + (-Dn)*Dm |
| return new FMSubD(machInst, rd, rn, rm, ra); |
| case 0x6: // FNMADD Dd = (-Da) + (-Dn)*Dm |
| return new FNMAddD(machInst, rd, rn, rm, ra); |
| case 0x7: // FNMSUB Dd = (-Da) + Dn*Dm |
| return new FNMSubD(machInst, rd, rn, rm, ra); |
| default: |
| return new Unknown64(machInst); |
| } |
| } else if (bits(machInst, 21) == 0) { |
| bool s = bits(machInst, 29); |
| if (s) |
| return new Unknown64(machInst); |
| uint8_t switchVal = bits(machInst, 20, 16); |
| uint8_t type = bits(machInst, 23, 22); |
| uint8_t scale = bits(machInst, 15, 10); |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5); |
| if (bits(machInst, 18, 17) == 3 && scale != 0) |
| return new Unknown64(machInst); |
| // 30:24=0011110, 21=0 |
| switch (switchVal) { |
| case 0x00: |
| return new FailUnimplemented("fcvtns", machInst); |
| case 0x01: |
| return new FailUnimplemented("fcvtnu", machInst); |
| case 0x02: |
| switch ( (bits(machInst, 31) << 2) | type ) { |
| case 0: // SCVTF Sd = convertFromInt(Wn/(2^fbits)) |
| return new FcvtSFixedFpSW(machInst, rd, rn, scale); |
| case 1: // SCVTF Dd = convertFromInt(Wn/(2^fbits)) |
| return new FcvtSFixedFpDW(machInst, rd, rn, scale); |
| case 4: // SCVTF Sd = convertFromInt(Xn/(2^fbits)) |
| return new FcvtSFixedFpSX(machInst, rd, rn, scale); |
| case 5: // SCVTF Dd = convertFromInt(Xn/(2^fbits)) |
| return new FcvtSFixedFpDX(machInst, rd, rn, scale); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x03: |
| switch ( (bits(machInst, 31) << 2) | type ) { |
| case 0: // UCVTF Sd = convertFromInt(Wn/(2^fbits)) |
| return new FcvtUFixedFpSW(machInst, rd, rn, scale); |
| case 1: // UCVTF Dd = convertFromInt(Wn/(2^fbits)) |
| return new FcvtUFixedFpDW(machInst, rd, rn, scale); |
| case 4: // UCVTF Sd = convertFromInt(Xn/(2^fbits)) |
| return new FcvtUFixedFpSX(machInst, rd, rn, scale); |
| case 5: // UCVTF Dd = convertFromInt(Xn/(2^fbits)) |
| return new FcvtUFixedFpDX(machInst, rd, rn, scale); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x04: |
| return new FailUnimplemented("fcvtas", machInst); |
| case 0x05: |
| return new FailUnimplemented("fcvtau", machInst); |
| case 0x08: |
| return new FailUnimplemented("fcvtps", machInst); |
| case 0x09: |
| return new FailUnimplemented("fcvtpu", machInst); |
| case 0x0e: |
| return new FailUnimplemented("fmov elem. to 64", machInst); |
| case 0x0f: |
| return new FailUnimplemented("fmov 64 bit", machInst); |
| case 0x10: |
| return new FailUnimplemented("fcvtms", machInst); |
| case 0x11: |
| return new FailUnimplemented("fcvtmu", machInst); |
| case 0x18: |
| switch ( (bits(machInst, 31) << 2) | type ) { |
| case 0: // FCVTZS Wd = convertToIntExactTowardZero(Sn*(2^fbits)) |
| return new FcvtFpSFixedSW(machInst, rd, rn, scale); |
| case 1: // FCVTZS Wd = convertToIntExactTowardZero(Dn*(2^fbits)) |
| return new FcvtFpSFixedDW(machInst, rd, rn, scale); |
| case 4: // FCVTZS Xd = convertToIntExactTowardZero(Sn*(2^fbits)) |
| return new FcvtFpSFixedSX(machInst, rd, rn, scale); |
| case 5: // FCVTZS Xd = convertToIntExactTowardZero(Dn*(2^fbits)) |
| return new FcvtFpSFixedDX(machInst, rd, rn, scale); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x19: |
| switch ( (bits(machInst, 31) << 2) | type ) { |
| case 0: // FCVTZU Wd = convertToIntExactTowardZero(Sn*(2^fbits)) |
| return new FcvtFpUFixedSW(machInst, rd, rn, scale); |
| case 1: // FCVTZU Wd = convertToIntExactTowardZero(Dn*(2^fbits)) |
| return new FcvtFpUFixedDW(machInst, rd, rn, scale); |
| case 4: // FCVTZU Xd = convertToIntExactTowardZero(Sn*(2^fbits)) |
| return new FcvtFpUFixedSX(machInst, rd, rn, scale); |
| case 5: // FCVTZU Xd = convertToIntExactTowardZero(Dn*(2^fbits)) |
| return new FcvtFpUFixedDX(machInst, rd, rn, scale); |
| default: |
| return new Unknown64(machInst); |
| } |
| default: |
| return new Unknown64(machInst); |
| } |
| } else { |
| // 30=0, 28:24=11110, 21=1 |
| uint8_t type = bits(machInst, 23, 22); |
| uint8_t imm8 = bits(machInst, 20, 13); |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5); |
| switch (bits(machInst, 11, 10)) { |
| case 0x0: |
| if (bits(machInst, 12) == 1) { |
| if (bits(machInst, 31) || |
| bits(machInst, 29) || |
| bits(machInst, 9, 5)) { |
| return new Unknown64(machInst); |
| } |
| // 31:29=000, 28:24=11110, 21=1, 12:10=100 |
| if (type == 0) { |
| // FMOV S[d] = imm8<7>:NOT(imm8<6>):Replicate(imm8<6>,5) |
| // :imm8<5:0>:Zeros(19) |
| uint32_t imm = vfp_modified_imm(imm8, |
| 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); |
| IntRegIndex rm = (IntRegIndex)(uint32_t) |
| bits(machInst, 20, 16); |
| // 28:23=000111100, 21=1, 15:10=001000, 2:0=000 |
| switch (switchVal) { |
| case 0x0: |
| // FCMP flags = compareQuiet(Sn,Sm) |
| return new FCmpRegS(machInst, rn, rm); |
| case 0x1: |
| // FCMP flags = compareQuiet(Sn,0.0) |
| return new FCmpImmS(machInst, rn, 0); |
| case 0x2: |
| // FCMPE flags = compareSignaling(Sn,Sm) |
| return new FCmpERegS(machInst, rn, rm); |
| case 0x3: |
| // FCMPE flags = compareSignaling(Sn,0.0) |
| return new FCmpEImmS(machInst, rn, 0); |
| case 0x4: |
| // FCMP flags = compareQuiet(Dn,Dm) |
| return new FCmpRegD(machInst, rn, rm); |
| case 0x5: |
| // FCMP flags = compareQuiet(Dn,0.0) |
| return new FCmpImmD(machInst, rn, 0); |
| case 0x6: |
| // FCMPE flags = compareSignaling(Dn,Dm) |
| return new FCmpERegD(machInst, rn, rm); |
| case 0x7: |
| // FCMPE flags = compareSignaling(Dn,0.0) |
| return new FCmpEImmD(machInst, rn, 0); |
| default: |
| return new Unknown64(machInst); |
| } |
| } else if (bits(machInst, 14) == 1) { |
| if (bits(machInst, 31) || bits(machInst, 29)) |
| return new Unknown64(machInst); |
| uint8_t opcode = bits(machInst, 20, 15); |
| // Bits 31:24=00011110, 21=1, 14:10=10000 |
| switch (opcode) { |
| case 0x0: |
| if (type == 0) |
| // FMOV Sd = Sn |
| return new FmovRegS(machInst, rd, rn); |
| else if (type == 1) |
| // FMOV Dd = Dn |
| return new FmovRegD(machInst, rd, rn); |
| break; |
| case 0x1: |
| if (type == 0) |
| // FABS Sd = abs(Sn) |
| return new FAbsS(machInst, rd, rn); |
| else if (type == 1) |
| // FABS Dd = abs(Dn) |
| return new FAbsD(machInst, rd, rn); |
| break; |
| case 0x2: |
| if (type == 0) |
| // FNEG Sd = -Sn |
| return new FNegS(machInst, rd, rn); |
| else if (type == 1) |
| // FNEG Dd = -Dn |
| return new FNegD(machInst, rd, rn); |
| break; |
| case 0x3: |
| if (type == 0) |
| // FSQRT Sd = sqrt(Sn) |
| return new FSqrtS(machInst, rd, rn); |
| else if (type == 1) |
| // FSQRT Dd = sqrt(Dn) |
| return new FSqrtD(machInst, rd, rn); |
| break; |
| case 0x4: |
| if (type == 1) |
| // FCVT Sd = convertFormat(Dn) |
| return new FcvtFpDFpS(machInst, rd, rn); |
| else if (type == 3) |
| // FCVT Sd = convertFormat(Hn) |
| return new FcvtFpHFpS(machInst, rd, rn); |
| break; |
| case 0x5: |
| if (type == 0) |
| // FCVT Dd = convertFormat(Sn) |
| return new FCvtFpSFpD(machInst, rd, rn); |
| else if (type == 3) |
| // FCVT Dd = convertFormat(Hn) |
| return new FcvtFpHFpD(machInst, rd, rn); |
| break; |
| case 0x7: |
| if (type == 0) |
| // FCVT Hd = convertFormat(Sn) |
| return new FcvtFpSFpH(machInst, rd, rn); |
| else if (type == 1) |
| // FCVT Hd = convertFormat(Dn) |
| return new FcvtFpDFpH(machInst, rd, rn); |
| break; |
| case 0x8: |
| if (type == 0) // FRINTN Sd = roundToIntegralTiesToEven(Sn) |
| return new FRIntNS(machInst, rd, rn); |
| else if (type == 1) // FRINTN Dd = roundToIntegralTiesToEven(Dn) |
| return new FRIntND(machInst, rd, rn); |
| break; |
| case 0x9: |
| if (type == 0) // FRINTP Sd = roundToIntegralTowardPlusInf(Sn) |
| return new FRIntPS(machInst, rd, rn); |
| else if (type == 1) // FRINTP Dd = roundToIntegralTowardPlusInf(Dn) |
| return new FRIntPD(machInst, rd, rn); |
| break; |
| case 0xa: |
| if (type == 0) // FRINTM Sd = roundToIntegralTowardMinusInf(Sn) |
| return new FRIntMS(machInst, rd, rn); |
| else if (type == 1) // FRINTM Dd = roundToIntegralTowardMinusInf(Dn) |
| return new FRIntMD(machInst, rd, rn); |
| break; |
| case 0xb: |
| if (type == 0) // FRINTZ Sd = roundToIntegralTowardZero(Sn) |
| return new FRIntZS(machInst, rd, rn); |
| else if (type == 1) // FRINTZ Dd = roundToIntegralTowardZero(Dn) |
| return new FRIntZD(machInst, rd, rn); |
| break; |
| case 0xc: |
| if (type == 0) // FRINTA Sd = roundToIntegralTiesToAway(Sn) |
| return new FRIntAS(machInst, rd, rn); |
| else if (type == 1) // FRINTA Dd = roundToIntegralTiesToAway(Dn) |
| return new FRIntAD(machInst, rd, rn); |
| break; |
| case 0xe: |
| if (type == 0) // FRINTX Sd = roundToIntegralExact(Sn) |
| return new FRIntXS(machInst, rd, rn); |
| else if (type == 1) // FRINTX Dd = roundToIntegralExact(Dn) |
| return new FRIntXD(machInst, rd, rn); |
| break; |
| case 0xf: |
| if (type == 0) // FRINTI Sd = roundToIntegral(Sn) |
| return new FRIntIS(machInst, rd, rn); |
| else if (type == 1) // FRINTI Dd = roundToIntegral(Dn) |
| return new FRIntID(machInst, rd, rn); |
| break; |
| default: |
| return new Unknown64(machInst); |
| } |
| return new Unknown64(machInst); |
| } else if (bits(machInst, 15) == 1) { |
| return new Unknown64(machInst); |
| } else { |
| if (bits(machInst, 29)) |
| return new Unknown64(machInst); |
| uint8_t rmode = bits(machInst, 20, 19); |
| uint8_t switchVal1 = bits(machInst, 18, 16); |
| uint8_t switchVal2 = (type << 1) | bits(machInst, 31); |
| // 30:24=0011110, 21=1, 15:10=000000 |
| switch (switchVal1) { |
| case 0x0: |
| switch ((switchVal2 << 2) | rmode) { |
| case 0x0: //FCVTNS Wd = convertToIntExactTiesToEven(Sn) |
| return new FcvtFpSIntWSN(machInst, rd, rn); |
| case 0x1: //FCVTPS Wd = convertToIntExactTowardPlusInf(Sn) |
| return new FcvtFpSIntWSP(machInst, rd, rn); |
| case 0x2: //FCVTMS Wd = convertToIntExactTowardMinusInf(Sn) |
| return new FcvtFpSIntWSM(machInst, rd, rn); |
| case 0x3: //FCVTZS Wd = convertToIntExactTowardZero(Sn) |
| return new FcvtFpSIntWSZ(machInst, rd, rn); |
| case 0x4: //FCVTNS Xd = convertToIntExactTiesToEven(Sn) |
| return new FcvtFpSIntXSN(machInst, rd, rn); |
| case 0x5: //FCVTPS Xd = convertToIntExactTowardPlusInf(Sn) |
| return new FcvtFpSIntXSP(machInst, rd, rn); |
| case 0x6: //FCVTMS Xd = convertToIntExactTowardMinusInf(Sn) |
| return new FcvtFpSIntXSM(machInst, rd, rn); |
| case 0x7: //FCVTZS Xd = convertToIntExactTowardZero(Sn) |
| return new FcvtFpSIntXSZ(machInst, rd, rn); |
| case 0x8: //FCVTNS Wd = convertToIntExactTiesToEven(Dn) |
| return new FcvtFpSIntWDN(machInst, rd, rn); |
| case 0x9: //FCVTPS Wd = convertToIntExactTowardPlusInf(Dn) |
| return new FcvtFpSIntWDP(machInst, rd, rn); |
| case 0xA: //FCVTMS Wd = convertToIntExactTowardMinusInf(Dn) |
| return new FcvtFpSIntWDM(machInst, rd, rn); |
| case 0xB: //FCVTZS Wd = convertToIntExactTowardZero(Dn) |
| return new FcvtFpSIntWDZ(machInst, rd, rn); |
| case 0xC: //FCVTNS Xd = convertToIntExactTiesToEven(Dn) |
| return new FcvtFpSIntXDN(machInst, rd, rn); |
| case 0xD: //FCVTPS Xd = convertToIntExactTowardPlusInf(Dn) |
| return new FcvtFpSIntXDP(machInst, rd, rn); |
| case 0xE: //FCVTMS Xd = convertToIntExactTowardMinusInf(Dn) |
| return new FcvtFpSIntXDM(machInst, rd, rn); |
| case 0xF: //FCVTZS Xd = convertToIntExactTowardZero(Dn) |
| return new FcvtFpSIntXDZ(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x1: |
| switch ((switchVal2 << 2) | rmode) { |
| case 0x0: //FCVTNU Wd = convertToIntExactTiesToEven(Sn) |
| return new FcvtFpUIntWSN(machInst, rd, rn); |
| case 0x1: //FCVTPU Wd = convertToIntExactTowardPlusInf(Sn) |
| return new FcvtFpUIntWSP(machInst, rd, rn); |
| case 0x2: //FCVTMU Wd = convertToIntExactTowardMinusInf(Sn) |
| return new FcvtFpUIntWSM(machInst, rd, rn); |
| case 0x3: //FCVTZU Wd = convertToIntExactTowardZero(Sn) |
| return new FcvtFpUIntWSZ(machInst, rd, rn); |
| case 0x4: //FCVTNU Xd = convertToIntExactTiesToEven(Sn) |
| return new FcvtFpUIntXSN(machInst, rd, rn); |
| case 0x5: //FCVTPU Xd = convertToIntExactTowardPlusInf(Sn) |
| return new FcvtFpUIntXSP(machInst, rd, rn); |
| case 0x6: //FCVTMU Xd = convertToIntExactTowardMinusInf(Sn) |
| return new FcvtFpUIntXSM(machInst, rd, rn); |
| case 0x7: //FCVTZU Xd = convertToIntExactTowardZero(Sn) |
| return new FcvtFpUIntXSZ(machInst, rd, rn); |
| case 0x8: //FCVTNU Wd = convertToIntExactTiesToEven(Dn) |
| return new FcvtFpUIntWDN(machInst, rd, rn); |
| case 0x9: //FCVTPU Wd = convertToIntExactTowardPlusInf(Dn) |
| return new FcvtFpUIntWDP(machInst, rd, rn); |
| case 0xA: //FCVTMU Wd = convertToIntExactTowardMinusInf(Dn) |
| return new FcvtFpUIntWDM(machInst, rd, rn); |
| case 0xB: //FCVTZU Wd = convertToIntExactTowardZero(Dn) |
| return new FcvtFpUIntWDZ(machInst, rd, rn); |
| case 0xC: //FCVTNU Xd = convertToIntExactTiesToEven(Dn) |
| return new FcvtFpUIntXDN(machInst, rd, rn); |
| case 0xD: //FCVTPU Xd = convertToIntExactTowardPlusInf(Dn) |
| return new FcvtFpUIntXDP(machInst, rd, rn); |
| case 0xE: //FCVTMU Xd = convertToIntExactTowardMinusInf(Dn) |
| return new FcvtFpUIntXDM(machInst, rd, rn); |
| case 0xF: //FCVTZU Xd = convertToIntExactTowardZero(Dn) |
| return new FcvtFpUIntXDZ(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x2: |
| if (rmode != 0) |
| return new Unknown64(machInst); |
| switch (switchVal2) { |
| case 0: // SCVTF Sd = convertFromInt(Wn) |
| return new FcvtWSIntFpS(machInst, rd, rn); |
| case 1: // SCVTF Sd = convertFromInt(Xn) |
| return new FcvtXSIntFpS(machInst, rd, rn); |
| case 2: // SCVTF Dd = convertFromInt(Wn) |
| return new FcvtWSIntFpD(machInst, rd, rn); |
| case 3: // SCVTF Dd = convertFromInt(Xn) |
| return new FcvtXSIntFpD(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x3: |
| switch (switchVal2) { |
| case 0: // UCVTF Sd = convertFromInt(Wn) |
| return new FcvtWUIntFpS(machInst, rd, rn); |
| case 1: // UCVTF Sd = convertFromInt(Xn) |
| return new FcvtXUIntFpS(machInst, rd, rn); |
| case 2: // UCVTF Dd = convertFromInt(Wn) |
| return new FcvtWUIntFpD(machInst, rd, rn); |
| case 3: // UCVTF Dd = convertFromInt(Xn) |
| return new FcvtXUIntFpD(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x4: |
| if (rmode != 0) |
| return new Unknown64(machInst); |
| switch (switchVal2) { |
| case 0: // FCVTAS Wd = convertToIntExactTiesToAway(Sn) |
| return new FcvtFpSIntWSA(machInst, rd, rn); |
| case 1: // FCVTAS Xd = convertToIntExactTiesToAway(Sn) |
| return new FcvtFpSIntXSA(machInst, rd, rn); |
| case 2: // FCVTAS Wd = convertToIntExactTiesToAway(Dn) |
| return new FcvtFpSIntWDA(machInst, rd, rn); |
| case 3: // FCVTAS Wd = convertToIntExactTiesToAway(Dn) |
| return new FcvtFpSIntXDA(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x5: |
| switch (switchVal2) { |
| case 0: // FCVTAU Wd = convertToIntExactTiesToAway(Sn) |
| return new FcvtFpUIntWSA(machInst, rd, rn); |
| case 1: // FCVTAU Xd = convertToIntExactTiesToAway(Sn) |
| return new FcvtFpUIntXSA(machInst, rd, rn); |
| case 2: // FCVTAU Wd = convertToIntExactTiesToAway(Dn) |
| return new FcvtFpUIntWDA(machInst, rd, rn); |
| case 3: // FCVTAU Xd = convertToIntExactTiesToAway(Dn) |
| return new FcvtFpUIntXDA(machInst, rd, rn); |
| default: |
| return new Unknown64(machInst); |
| } |
| case 0x06: |
| switch (switchVal2) { |
| case 0: // FMOV Wd = Sn |
| if (rmode != 0) |
| return new Unknown64(machInst); |
| return new FmovRegCoreW(machInst, rd, rn); |
| case 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); |
| } |
| IntRegIndex rm = (IntRegIndex)(uint32_t) bits(machInst, 20, 16); |
| IntRegIndex rn = (IntRegIndex)(uint32_t) bits(machInst, 9, 5); |
| uint8_t imm = (IntRegIndex)(uint32_t) bits(machInst, 3, 0); |
| ConditionCode cond = |
| (ConditionCode)(uint8_t)(bits(machInst, 15, 12)); |
| uint8_t switchVal = (bits(machInst, 4) << 0) | |
| (bits(machInst, 22) << 1); |
| // 31:23=000111100, 21=1, 11:10=01 |
| switch (switchVal) { |
| case 0x0: |
| // FCCMP flags = if cond the compareQuiet(Sn,Sm) else #nzcv |
| return new FCCmpRegS(machInst, rn, rm, cond, imm); |
| case 0x1: |
| // FCCMP flags = if cond then compareSignaling(Sn,Sm) |
| // else #nzcv |
| return new FCCmpERegS(machInst, rn, rm, cond, imm); |
| case 0x2: |
| // FCCMP flags = if cond then compareQuiet(Dn,Dm) else #nzcv |
| return new FCCmpRegD(machInst, rn, rm, cond, imm); |
| case 0x3: |
| // FCCMP flags = if cond then compareSignaling(Dn,Dm) |
| // else #nzcv |
| return new FCCmpERegD(machInst, rn, rm, cond, imm); |
| default: |
| return new Unknown64(machInst); |
| } |
| } |
| case 0x2: |
| { |
| if (bits(machInst, 31) || |
| bits(machInst, 29) || |
| bits(machInst, 23)) { |
| return new Unknown64(machInst); |
| } |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5); |
| IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16); |
| uint8_t switchVal = (bits(machInst, 15, 12) << 0) | |
| (bits(machInst, 22) << 4); |
| switch (switchVal) { |
| case 0x00: // FMUL Sd = Sn * Sm |
| return new FMulS(machInst, rd, rn, rm); |
| case 0x10: // FMUL Dd = Dn * Dm |
| return new FMulD(machInst, rd, rn, rm); |
| case 0x01: // FDIV Sd = Sn / Sm |
| return new FDivS(machInst, rd, rn, rm); |
| case 0x11: // FDIV Dd = Dn / Dm |
| return new FDivD(machInst, rd, rn, rm); |
| case 0x02: // FADD Sd = Sn + Sm |
| return new FAddS(machInst, rd, rn, rm); |
| case 0x12: // FADD Dd = Dn + Dm |
| return new FAddD(machInst, rd, rn, rm); |
| case 0x03: // FSUB Sd = Sn - Sm |
| return new FSubS(machInst, rd, rn, rm); |
| case 0x13: // FSUB Dd = Dn - Dm |
| return new FSubD(machInst, rd, rn, rm); |
| case 0x04: // FMAX Sd = max(Sn, Sm) |
| return new FMaxS(machInst, rd, rn, rm); |
| case 0x14: // FMAX Dd = max(Dn, Dm) |
| return new FMaxD(machInst, rd, rn, rm); |
| case 0x05: // FMIN Sd = min(Sn, Sm) |
| return new FMinS(machInst, rd, rn, rm); |
| case 0x15: // FMIN Dd = min(Dn, Dm) |
| return new FMinD(machInst, rd, rn, rm); |
| case 0x06: // FMAXNM Sd = maxNum(Sn, Sm) |
| return new FMaxNMS(machInst, rd, rn, rm); |
| case 0x16: // FMAXNM Dd = maxNum(Dn, Dm) |
| return new FMaxNMD(machInst, rd, rn, rm); |
| case 0x07: // FMINNM Sd = minNum(Sn, Sm) |
| return new FMinNMS(machInst, rd, rn, rm); |
| case 0x17: // FMINNM Dd = minNum(Dn, Dm) |
| return new FMinNMD(machInst, rd, rn, rm); |
| case 0x08: // FNMUL Sd = -(Sn * Sm) |
| return new FNMulS(machInst, rd, rn, rm); |
| case 0x18: // FNMUL Dd = -(Dn * Dm) |
| return new FNMulD(machInst, rd, rn, rm); |
| default: |
| return new Unknown64(machInst); |
| } |
| } |
| case 0x3: |
| { |
| if (bits(machInst, 31) || bits(machInst, 29)) |
| return new Unknown64(machInst); |
| uint8_t type = bits(machInst, 23, 22); |
| IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 4, 0); |
| IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 9, 5); |
| IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 20, 16); |
| ConditionCode cond = |
| (ConditionCode)(uint8_t)(bits(machInst, 15, 12)); |
| if (type == 0) // FCSEL Sd = if cond then Sn else Sm |
| return new FCSelS(machInst, rd, rn, rm, cond); |
| else if (type == 1) // FCSEL Dd = if cond then Dn else Dm |
| return new FCSelD(machInst, rd, rn, rm, cond); |
| else |
| return new Unknown64(machInst); |
| } |
| 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 <typename DecoderFeatures> |
| StaticInstPtr |
| decodeFpAdvSIMD(ExtMachInst machInst) |
| { |
| |
| if (bits(machInst, 28) == 0) { |
| if (bits(machInst, 31) == 0) { |
| return decodeAdvSIMD<DecoderFeatures>(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, 25) != 0x2) { |
| return new Unknown64(machInst); |
| } |
| if (bits(machInst, 31) == 0x0) { |
| 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, 26) == 0) |
| // bit 28:26=100 |
| return decodeDataProcImm(machInst); |
| else |
| // bit 28:26=101 |
| return decodeBranchExcSys(machInst); |
| } else if (bits(machInst, 25) == 0) { |
| // bit 27=1, 25=0 |
| return decodeLoadsStores(machInst); |
| } else if (bits(machInst, 26) == 0) { |
| // bit 27:25=101 |
| return decodeDataProcReg(machInst); |
| } else if (bits(machInst, 24) == 1 && |
| bits(machInst, 31, 28) == 0xF) { |
| return new Gem5Op64(machInst); |
| } else { |
| // bit 27:25=111 |
| switch(decoderFlavor){ |
| default: |
| return decodeFpAdvSIMD<GenericDecoder>(machInst); |
| } |
| } |
| } |
| ''' |
| }}; |