45#include "arch/arm/generated/decoder.hh"
60 bool load, uint32_t reglist) :
63 uint32_t regs = reglist;
65 uint32_t mem_ops = ones;
69 bool copy_base = (
bits(reglist,
rn) && load) || !ones;
70 bool force_user = user & !
bits(reglist, 15);
71 bool exception_ret = user &
bits(reglist, 15);
78 + ((ones % 2 == 0 && exception_ret) ? 1 : 0)
91 addr = (ones << 2) - 4;
104 while (mem_ops != 0) {
106 if (load && mem_ops >= 2 &&
128 *uop =
new MicroLdr2Uop(
machInst, reg_idx1, reg_idx2,
133 (*uop)->setFlag(StaticInst::IsControl);
134 (*uop)->setFlag(StaticInst::IsIndirectControl);
137 (*uop)->setFlag(StaticInst::IsCondControl);
139 (*uop)->setFlag(StaticInst::IsUncondControl);
160 }
else if (reg_idx ==
int_reg::Pc && exception_ret) {
162 *uop =
new MicroLdrRetUop(
machInst, reg_idx,
166 *uop =
new MicroLdrUop(
machInst, reg_idx,
172 (*uop)->setFlag(StaticInst::IsControl);
173 (*uop)->setFlag(StaticInst::IsIndirectControl);
176 (*uop)->setFlag(StaticInst::IsCondControl);
178 (*uop)->setFlag(StaticInst::IsUncondControl);
205 *uop =
new MicroUopRegMov(
208 (*uop)->setFlag(StaticInst::IsControl);
209 (*uop)->setFlag(StaticInst::IsIndirectControl);
212 (*uop)->setFlag(StaticInst::IsCondControl);
214 (*uop)->setFlag(StaticInst::IsUncondControl);
217 (*uop)->setFlag(StaticInst::IsReturn);
228 if ((*uop)->isControl())
229 setFlag(StaticInst::IsControl);
230 if ((*uop)->isCondCtrl())
231 setFlag(StaticInst::IsCondControl);
232 if ((*uop)->isUncondCtrl())
233 setFlag(StaticInst::IsUncondControl);
234 if ((*uop)->isIndirectCtrl())
235 setFlag(StaticInst::IsIndirectControl);
236 if ((*uop)->isReturn())
240 (*uop)->setDelayedCommit();
245 uint32_t
size,
bool fp,
bool load,
bool noAlloc,
246 bool signExt,
bool exclusive,
bool acrel,
286 *uop++ =
new MicroStrQBFpXImmUop(
machInst,
rt,
289 *uop++ =
new MicroStrQTFpXImmUop(
machInst,
rt,
299 }
else if (
size == 8) {
312 }
else if (
size == 4) {
337 }
else if (
size == 4) {
366 !(*curUop)->isLastMicroop(); curUop++) {
367 (*curUop)->setDelayedCommit();
372 OpClass __opClass,
bool load,
RegIndex dest,
385 (*uop)->setDelayedCommit();
388 (*uop)->setLastMicroop();
393 OpClass __opClass,
bool load,
RegIndex dest,
405 *uop++=
new MicroStrQBFpXImmUop(
machInst, dest,
base, 0);
406 *uop++ =
new MicroStrQTFpXImmUop(
machInst, dest,
base, 0);
409 (*uop)->setLastMicroop();
413 !(*curUop)->isLastMicroop(); curUop++) {
414 (*curUop)->setDelayedCommit();
419 OpClass __opClass,
bool load,
RegIndex dest,
435 (*uop)->setLastMicroop();
439 !(*curUop)->isLastMicroop(); curUop++) {
440 (*curUop)->setDelayedCommit();
445 OpClass __opClass,
bool load,
RegIndex dest,
461 (*uop)->setDelayedCommit();
466 (*uop)->setLastMicroop();
488 assert(regs > 0 && regs <= 4);
489 assert(regs % elems == 0);
492 bool wb = (
rm != 15);
493 bool deinterleave = (elems > 1);
501 uint32_t noAlign = 0;
506 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
508 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
512 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
514 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
518 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon16Uop>(
522 microOps[uopIdx++] = newNeonMemInst<MicroLdrNeon8Uop>(
530 if (
rm != 15 &&
rm != 13) {
542 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon8Uop>(
547 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon6Uop>(
551 assert(regs == 4 || regs == 2);
553 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
555 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
558 microOps[uopIdx++] = newNeonMixInst<MicroDeintNeon4Uop>(
579 OpClass __opClass,
bool all,
unsigned elems,
581 unsigned inc, uint32_t
size, uint32_t align,
585 assert(regs > 0 && regs <= 4);
586 assert(regs % elems == 0);
588 unsigned eBytes = (1 <<
size);
589 unsigned loadSize = eBytes * elems;
590 [[maybe_unused]]
unsigned loadRegs =
591 (loadSize +
sizeof(uint32_t) - 1) /
sizeof(uint32_t);
593 assert(loadRegs > 0 && loadRegs <= 4);
596 bool wb = (
rm != 15);
607 microOps[uopIdx++] =
new MicroLdrNeon1Uop<uint8_t>(
612 microOps[uopIdx++] =
new MicroLdrNeon2Uop<uint16_t>(
615 microOps[uopIdx++] =
new MicroLdrNeon2Uop<uint8_t>(
620 microOps[uopIdx++] =
new MicroLdrNeon3Uop<uint8_t>(
626 microOps[uopIdx++] =
new MicroLdrNeon4Uop<uint8_t>(
630 microOps[uopIdx++] =
new MicroLdrNeon4Uop<uint16_t>(
634 microOps[uopIdx++] =
new MicroLdrNeon4Uop<uint32_t>(
640 microOps[uopIdx++] =
new MicroLdrNeon6Uop<uint16_t>(
646 microOps[uopIdx++] =
new MicroLdrNeon8Uop<uint16_t>(
650 microOps[uopIdx++] =
new MicroLdrNeon8Uop<uint32_t>(
656 microOps[uopIdx++] =
new MicroLdrNeon12Uop<uint32_t>(
660 microOps[uopIdx++] =
new MicroLdrNeon16Uop<uint32_t>(
668 if (
rm != 15 &&
rm != 13) {
682 microOps[uopIdx++] =
new MicroUnpackAllNeon2to8Uop<uint8_t>(
685 microOps[uopIdx++] =
new MicroUnpackNeon2to8Uop<uint8_t>(
691 microOps[uopIdx++] =
new MicroUnpackAllNeon2to8Uop<uint16_t>(
694 microOps[uopIdx++] =
new MicroUnpackNeon2to8Uop<uint16_t>(
700 microOps[uopIdx++] =
new MicroUnpackAllNeon4to8Uop<uint32_t>(
703 microOps[uopIdx++] =
new MicroUnpackNeon4to8Uop<uint32_t>(
718 microOps[uopIdx++] =
new MicroUnpackAllNeon2to6Uop<uint8_t>(
721 microOps[uopIdx++] =
new MicroUnpackNeon2to6Uop<uint8_t>(
727 microOps[uopIdx++] =
new MicroUnpackAllNeon2to6Uop<uint16_t>(
730 microOps[uopIdx++] =
new MicroUnpackNeon2to6Uop<uint16_t>(
736 microOps[uopIdx++] =
new MicroUnpackAllNeon4to6Uop<uint32_t>(
739 microOps[uopIdx++] =
new MicroUnpackNeon4to6Uop<uint32_t>(
751 assert(loadRegs <= 2);
755 microOps[uopIdx++] =
new MicroUnpackAllNeon2to4Uop<uint8_t>(
758 microOps[uopIdx++] =
new MicroUnpackNeon2to4Uop<uint8_t>(
764 microOps[uopIdx++] =
new MicroUnpackAllNeon2to4Uop<uint16_t>(
767 microOps[uopIdx++] =
new MicroUnpackNeon2to4Uop<uint16_t>(
773 microOps[uopIdx++] =
new MicroUnpackAllNeon2to4Uop<uint32_t>(
776 microOps[uopIdx++] =
new MicroUnpackNeon2to4Uop<uint32_t>(
787 assert(regs == 1 || (
all && regs == 2));
788 assert(loadRegs <= 2);
794 new MicroUnpackAllNeon2to2Uop<uint8_t>(
798 new MicroUnpackNeon2to2Uop<uint8_t>(
805 new MicroUnpackAllNeon2to2Uop<uint16_t>(
809 new MicroUnpackNeon2to2Uop<uint16_t>(
816 new MicroUnpackAllNeon2to2Uop<uint32_t>(
820 new MicroUnpackNeon2to2Uop<uint32_t>(
851 assert(regs > 0 && regs <= 4);
852 assert(regs % elems == 0);
855 bool wb = (
rm != 15);
856 bool interleave = (elems > 1);
862 uint32_t noAlign = 0;
871 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon8Uop>(
876 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon6Uop>(
880 assert(regs == 4 || regs == 2);
882 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
884 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
887 microOps[uopIdx++] = newNeonMixInst<MicroInterNeon4Uop>(
898 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
900 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
904 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
906 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
910 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon16Uop>(
914 microOps[uopIdx++] = newNeonMemInst<MicroStrNeon8Uop>(
922 if (
rm != 15 &&
rm != 13) {
942 OpClass __opClass,
bool all,
unsigned elems,
944 unsigned inc, uint32_t
size, uint32_t align,
949 assert(regs > 0 && regs <= 4);
950 assert(regs % elems == 0);
952 unsigned eBytes = (1 <<
size);
953 unsigned storeSize = eBytes * elems;
954 [[maybe_unused]]
unsigned storeRegs =
955 (storeSize +
sizeof(uint32_t) - 1) /
sizeof(uint32_t);
957 assert(storeRegs > 0 && storeRegs <= 4);
960 bool wb = (
rm != 15);
974 microOps[uopIdx++] =
new MicroPackNeon8to2Uop<uint8_t>(
978 microOps[uopIdx++] =
new MicroPackNeon8to2Uop<uint16_t>(
982 microOps[uopIdx++] =
new MicroPackNeon8to4Uop<uint32_t>(
995 microOps[uopIdx++] =
new MicroPackNeon6to2Uop<uint8_t>(
999 microOps[uopIdx++] =
new MicroPackNeon6to2Uop<uint16_t>(
1003 microOps[uopIdx++] =
new MicroPackNeon6to4Uop<uint32_t>(
1014 assert(storeRegs <= 2);
1017 microOps[uopIdx++] =
new MicroPackNeon4to2Uop<uint8_t>(
1021 microOps[uopIdx++] =
new MicroPackNeon4to2Uop<uint16_t>(
1025 microOps[uopIdx++] =
new MicroPackNeon4to2Uop<uint32_t>(
1035 assert(regs == 1 || (
all && regs == 2));
1036 assert(storeRegs <= 2);
1040 microOps[uopIdx++] =
new MicroPackNeon2to2Uop<uint8_t>(
1044 microOps[uopIdx++] =
new MicroPackNeon2to2Uop<uint16_t>(
1048 microOps[uopIdx++] =
new MicroPackNeon2to2Uop<uint32_t>(
1062 switch (storeSize) {
1064 microOps[uopIdx++] =
new MicroStrNeon1Uop<uint8_t>(
1069 microOps[uopIdx++] =
new MicroStrNeon2Uop<uint16_t>(
1072 microOps[uopIdx++] =
new MicroStrNeon2Uop<uint8_t>(
1077 microOps[uopIdx++] =
new MicroStrNeon3Uop<uint8_t>(
1083 microOps[uopIdx++] =
new MicroStrNeon4Uop<uint8_t>(
1087 microOps[uopIdx++] =
new MicroStrNeon4Uop<uint16_t>(
1091 microOps[uopIdx++] =
new MicroStrNeon4Uop<uint32_t>(
1097 microOps[uopIdx++] =
new MicroStrNeon6Uop<uint16_t>(
1103 microOps[uopIdx++] =
new MicroStrNeon8Uop<uint16_t>(
1107 microOps[uopIdx++] =
new MicroStrNeon8Uop<uint32_t>(
1113 microOps[uopIdx++] =
new MicroStrNeon12Uop<uint32_t>(
1117 microOps[uopIdx++] =
new MicroStrNeon16Uop<uint32_t>(
1125 if (
rm != 15 &&
rm != 13) {
1157 assert(totNumBytes <= 64);
1161 int numMemMicroops = totNumBytes / 16;
1162 int residuum = totNumBytes % 16;
1171 unsigned uopIdx = 0;
1175 for (;
i < numMemMicroops - 1; ++
i) {
1176 microOps[uopIdx++] =
new MicroNeonLoad64(
1178 baseIsSP, 16 ,
eSize);
1180 microOps[uopIdx++] =
new MicroNeonLoad64(
1182 residuum ? residuum : 16 ,
eSize);
1197 for (
int i = 0;
i < numMarshalMicroops; ++
i) {
1199 case 1:
microOps[uopIdx++] =
new MicroDeintNeon64_1Reg(
1203 case 2:
microOps[uopIdx++] =
new MicroDeintNeon64_2Reg(
1207 case 3:
microOps[uopIdx++] =
new MicroDeintNeon64_3Reg(
1211 case 4:
microOps[uopIdx++] =
new MicroDeintNeon64_4Reg(
1215 default:
panic(
"Invalid number of registers");
1242 assert(totNumBytes <= 64);
1246 int numMemMicroops = totNumBytes / 16;
1247 int residuum = totNumBytes % 16;
1252 int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
1256 unsigned uopIdx = 0;
1258 for (
int i = 0;
i < numMarshalMicroops; ++
i) {
1260 case 1:
microOps[uopIdx++] =
new MicroIntNeon64_1Reg(
1264 case 2:
microOps[uopIdx++] =
new MicroIntNeon64_2Reg(
1268 case 3:
microOps[uopIdx++] =
new MicroIntNeon64_3Reg(
1272 case 4:
microOps[uopIdx++] =
new MicroIntNeon64_4Reg(
1276 default:
panic(
"Invalid number of registers");
1283 for (;
i < numMemMicroops - 1; ++
i) {
1284 microOps[uopIdx++] =
new MicroNeonStore64(
1286 baseIsSP, 16 ,
eSize);
1288 microOps[uopIdx++] =
new MicroNeonStore64(
1290 residuum ? residuum : 16 ,
eSize);
1330 int eSizeBytes = 1 <<
eSize;
1332 assert(totNumBytes <= 64);
1336 int numMemMicroops = totNumBytes / 16;
1337 int residuum = totNumBytes % 16;
1346 unsigned uopIdx = 0;
1351 for (;
i < numMemMicroops - 1; ++
i) {
1352 microOps[uopIdx++] =
new MicroNeonLoad64(
1354 baseIsSP, 16 ,
eSize);
1356 microOps[uopIdx++] =
new MicroNeonLoad64(
1358 residuum ? residuum : 16 ,
eSize);
1373 for (
int i = 0;
i < numMarshalMicroops; ++
i) {
1374 microOps[uopIdx++] =
new MicroUnpackNeon64(
1403 int eSizeBytes = 1 <<
eSize;
1405 assert(totNumBytes <= 64);
1409 int numMemMicroops = totNumBytes / 16;
1410 int residuum = totNumBytes % 16;
1415 int numMarshalMicroops = totNumBytes > 32 ? 2 : 1;
1419 unsigned uopIdx = 0;
1421 for (
int i = 0;
i < numMarshalMicroops; ++
i) {
1422 microOps[uopIdx++] =
new MicroPackNeon64(
1430 for (;
i < numMemMicroops - 1; ++
i) {
1431 microOps[uopIdx++] =
new MicroNeonStore64(
1433 baseIsSP, 16 ,
eSize);
1435 microOps[uopIdx++] =
new MicroNeonStore64(
1437 residuum ? residuum : 16 ,
eSize);
1482 for (
int j = 0; j <
count; j++) {
1505 addr -= (single ? 4 : 8);
1513 addr += (single ? 4 : 8);
1532 !(*curUop)->isLastMicroop(); curUop++) {
1543 std::stringstream
ss;
1557 std::stringstream
ss;
1571 std::stringstream
ss;
1581 std::stringstream
ss;
1594 std::stringstream
ss;
1606 std::stringstream
ss;
1620 std::stringstream
ss;
1638 std::stringstream
ss;
1655 std::stringstream
ss;
void printExtendOperand(bool firstOperand, std::ostream &os, RegIndex rm, ArmExtendType type, int64_t shiftAmt) const
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
void printIntReg(std::ostream &os, RegIndex reg_idx, uint8_t opWidth=0) const
Print a register name for disassembly given the unique dependence tag number (FP or int).
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
BigFpMemImmOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool load, RegIndex dest, RegIndex base, int64_t imm)
BigFpMemLitOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex dest, int64_t imm)
BigFpMemPostOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool load, RegIndex dest, RegIndex base, int64_t imm)
BigFpMemPreOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool load, RegIndex dest, RegIndex base, int64_t imm)
BigFpMemRegOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool load, RegIndex dest, RegIndex base, RegIndex offset, ArmExtendType type, int64_t imm)
MacroMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, bool index, bool up, bool user, bool writeback, bool load, uint32_t reglist)
MacroVFPMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, RegIndex vd, bool single, bool up, bool writeback, bool load, uint32_t offset)
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
Base class for Memory microops.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
PairMemOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, uint32_t size, bool fp, bool load, bool noAlloc, bool signExt, bool exclusive, bool acrel, int64_t imm, AddrMode mode, RegIndex rn, RegIndex rt, RegIndex rt2)
void size(size_t newSize) override
PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass)
Constructor.
VldMultOp64(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, RegIndex vd, RegIndex rm, uint8_t eSize, uint8_t dataSize, uint8_t numStructElems, uint8_t numRegs, bool wb)
VldMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, uint32_t size, uint32_t align, RegIndex rm)
VldSingleOp64(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, RegIndex vd, RegIndex rm, uint8_t eSize, uint8_t dataSize, uint8_t numStructElems, uint8_t index, bool wb, bool replicate=false)
VldSingleOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool all, unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, uint32_t size, uint32_t align, RegIndex rm, unsigned lane)
VstMultOp64(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, RegIndex vd, RegIndex rm, uint8_t eSize, uint8_t dataSize, uint8_t numStructElems, uint8_t numRegs, bool wb)
VstMultOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, unsigned width, RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, uint32_t size, uint32_t align, RegIndex rm)
VstSingleOp64(const char *mnem, ExtMachInst machInst, OpClass __opClass, RegIndex rn, RegIndex vd, RegIndex rm, uint8_t eSize, uint8_t dataSize, uint8_t numStructElems, uint8_t index, bool wb, bool replicate=false)
VstSingleOp(const char *mnem, ExtMachInst machInst, OpClass __opClass, bool all, unsigned elems, RegIndex rn, RegIndex vd, unsigned regs, unsigned inc, uint32_t size, uint32_t align, RegIndex rm, unsigned lane)
Static instruction class for unknown (illegal) instructions.
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
constexpr void replaceBits(T &val, unsigned first, unsigned last, B bit_val)
A convenience function to replace bits first to last of val with bit_val in place.
#define panic(...)
This implements a cprintf based panic() function.
static int regInMode(OperatingMode mode, int reg)
static unsigned int number_of_ones(int32_t val)
static bool isSP(RegIndex reg)
const int NumVecV8ArchRegs
static RegIndex makeSP(RegIndex reg)
Copyright (c) 2024 Arm Limited All rights reserved.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
RefCountingPtr< StaticInst > StaticInstPtr
void ccprintf(cp::Print &print)
Utility functions and datatypes used by AArch64 NEON memory instructions.