61 uint32_t
type, uint32_t cfval)
const
64 ArmShiftType shiftType;
65 shiftType = (ArmShiftType)
type;
78 return (
base >> 31) | -((
base & (1 << 31)) >> 31);
80 return (
base >> shamt) | -((
base & (1 << 31)) >> shamt);
83 return (cfval << 31) | (
base >> 1);
85 return (
base << (32 - shamt)) | (
base >> shamt);
87 ccprintf(std::cerr,
"Unhandled shift type\n");
98 shiftAmt = shiftAmt %
width;
99 ArmShiftType shiftType;
100 shiftType = (ArmShiftType)
type;
105 return base << shiftAmt;
126 ccprintf(std::cerr,
"Unhandled shift type\n");
135 uint64_t shiftAmt, uint8_t
width)
const
137 bool sign_extend =
false;
170 uint64_t tmp = (uint64_t)
bits(
base,
len - 1, 0) << shiftAmt;
172 int sign_bit =
bits(tmp,
len + shiftAmt - 1);
173 tmp = sign_bit ? (tmp | ~mask(
len + shiftAmt)) : tmp;
181 uint32_t
type, uint32_t cfval)
const
183 enum ArmShiftType shiftType;
184 shiftType = (
enum ArmShiftType)
type;
192 return base << shamt;
197 return base >> shamt;
200 return (
base >> 31) | -((
base & (1 << 31)) >> 31);
202 return (
base >> shamt) | -((
base & (1 << 31)) >> shamt);
204 shamt = shamt & 0x1f;
208 return (
base << (32 - shamt)) | (
base >> shamt);
210 ccprintf(std::cerr,
"Unhandled shift type\n");
221 uint32_t
type, uint32_t cfval)
const
223 enum ArmShiftType shiftType;
224 shiftType = (
enum ArmShiftType)
type;
232 return (
base >> (32 - shamt)) & 1;
237 return (
base >> (shamt - 1)) & 1;
242 return (
base >> (shamt - 1)) & 1;
244 shamt = shamt & 0x1f;
248 return (
base >> (shamt - 1)) & 1;
250 ccprintf(std::cerr,
"Unhandled shift type\n");
261 uint32_t
type, uint32_t cfval)
const
263 enum ArmShiftType shiftType;
264 shiftType = (
enum ArmShiftType)
type;
275 return (
base >> (32 - shamt)) & 1;
280 return (
base >> (shamt - 1)) & 1;
284 return (
base >> (shamt - 1)) & 1;
286 shamt = shamt & 0x1f;
289 return (
base >> (shamt - 1)) & 1;
291 ccprintf(std::cerr,
"Unhandled shift type\n");
300 uint8_t opWidth)
const
308 ccprintf(
os,
"%s%s", (opWidth == 32) ?
"w" :
"",
"sp");
310 ccprintf(
os,
"%szr", (opWidth == 32) ?
"w" :
"x");
312 ccprintf(
os,
"%s%d", (opWidth == 32) ?
"w" :
"x", reg_idx);
336 const char *flagtoprfop[]= {
"PLD",
"PLI",
"PST",
"Reserved"};
337 const char *flagtotarget[] = {
"L1",
"L2",
"L3",
"Reserved"};
338 const char *flagtopolicy[] = {
"KEEP",
"STRM"};
340 ccprintf(
os,
"%s%s%s", flagtoprfop[(flag>>3)&3],
341 flagtotarget[(flag>>1)&3], flagtopolicy[flag&1]);
352 bool isSveVecReg)
const
354 ccprintf(
os,
"%s%d", isSveVecReg ?
"z" :
"v", reg_idx);
378 const std::string &suffix,
387 }
else if (withCond64) {
403 if (it != symtab->
end()) {
405 Addr delta = target - it->address();
419 bool noImplicit)
const
475 panic(
"Unrecognized condition code %d.\n", code);
482 const std::string &prefix,
484 const std::string &suffix)
const
488 if (it != symtab->
end()) {
490 if (it->address() !=
addr)
503 ArmShiftType
type)
const
505 bool firstOp =
false;
513 if ((
type == LSR ||
type == ASR) && immShift && shiftAmt == 0)
518 if (immShift && shiftAmt == 0) {
537 if (immShift && shiftAmt == 0) {
549 panic(
"Tried to disassemble unrecognized shift type.\n");
555 os <<
"#" << shiftAmt;
564 int64_t shiftAmt)
const
597 ArmShiftType
type, uint64_t
imm)
const
629 std::stringstream
ss;
637 const auto tc = xc->
tcBase();
641 (hcr.tge || mdcr.tde)) || !
ELIs32(tc,
EL1)) {
643 return std::make_shared<SoftwareBreakpoint>(
machInst,
imm);
646 return std::make_shared<PrefetchAbort>(
readPC(xc),
659 return std::make_shared<SupervisorTrap>(
662 return std::make_shared<HypervisorTrap>(
665 return std::make_shared<SecureMonitorTrap>(
669 panic(
"Illegal EL in advSIMDFPAccessTrap64\n");
678 bool trap_el2 =
false;
681 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h == 0x1) {
682 switch (cptr_en_check.fpen) {
685 trap_el2 = !(
currEL(tc) ==
EL1 && hcr.tge == 1);
688 trap_el2 = (
currEL(tc) ==
EL0 && hcr.tge == 1);
694 }
else if (cptr_en_check.tfp) {
705 if (cptr_en_check.tfp) {
715 CPSR cpsr, CPACR cpacr)
const
718 if (((
el ==
EL0 && cpacr.fpen != 0x3) ||
719 (
el ==
EL1 && !(cpacr.fpen & 0x1))) &&
728 CPSR cpsr, CPACR cpacr,
729 NSACR nsacr, FPEXC fpexc,
730 bool fpexc_check,
bool advsimd)
const
734 const bool is_secure =
isSecure(tc);
740 uint8_t cpacr_cp10 = cpacr.cp10;
741 bool cpacr_asedis = cpacr.asedis;
743 if (have_security && !
ELIs64(tc,
EL3) && !is_secure) {
754 if ((cur_el ==
EL0 && cpacr_cp10 != 0x3) ||
755 (cur_el !=
EL0 && !(cpacr_cp10 & 0x1)))
759 if (fpexc_check && !fpexc.en)
764 if (have_virtualization && !is_secure &&
ELIs64(tc,
EL2))
767 if (have_virtualization && !is_secure) {
769 bool hcptr_cp10 = hcptr.tcp10;
770 bool hcptr_tase = hcptr.tase;
772 if (have_security && !
ELIs64(tc,
EL3) && !is_secure) {
779 if ((
advsimd && hcptr_tase) || hcptr_cp10) {
780 const uint32_t
iss =
advsimd ? (1 << 5) : 0xA;
782 return std::make_shared<UndefinedInstruction>(
786 return std::make_shared<HypervisorTrap>(
796 if (cptr_en_check.tfp)
815 trap = isWfe? !sctlr.ntwe : !sctlr.ntwi;
818 trap = isWfe? hcr.twe : hcr.twi;
821 trap = isWfe? scr.twe : scr.twi;
841 if (
ELIs64(tc, targetEL)) {
849 uint32_t
iss = isWfe? 0x1E00001 :
853 return std::make_shared<UndefinedInstruction>(
857 return std::make_shared<HypervisorTrap>(
861 return std::make_shared<SecureMonitorTrap>(
865 panic(
"Unrecognized Exception Level: %d\n", targetEL);
884 uint32_t
iss = isWfe? 0x1E00001 :
888 return std::make_shared<SupervisorTrap>(
892 return std::make_shared<HypervisorTrap>(
896 return std::make_shared<SecureMonitorTrap>(
900 panic(
"Unrecognized Exception Level: %d\n", targetEL);
915 if (curr_el ==
EL0) {
920 ((curr_el ==
EL0) || (curr_el ==
EL1))) {
936 bool setend_disabled(
false);
939 if (pstate_el ==
EL2) {
978 return std::make_shared<UndefinedInstruction>(
991 return std::make_shared<SupervisorTrap>(
994 return std::make_shared<HypervisorTrap>(
997 return std::make_shared<SecureMonitorTrap>(
1000 panic(
"Unrecognized Exception Level: %d\n", pstateEL);
1012 return std::make_shared<SupervisorTrap>(
1015 return std::make_shared<HypervisorTrap>(
1018 return std::make_shared<SecureMonitorTrap>(
1022 panic(
"Illegal EL in sveAccessTrap\n");
1032 if (svcr_sm_check.sm) {
1039 if ((
el ==
EL0 && cpacr.zen == 0x1) ||
1040 (!(cpacr.zen & 0x1)))
1043 if ((
el ==
EL0 && cpacr.fpen == 0x1) ||
1044 (!(cpacr.fpen & 0x1)))
1052 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1053 if (((cptr_en_check.zen & 0x1) == 0x0) ||
1054 (cptr_en_check.zen == 0x1 &&
el ==
EL0 &&
1058 if (((cptr_en_check.fpen & 0x1) == 0x0) ||
1059 (cptr_en_check.fpen == 0x1 &&
el ==
EL0 &&
1064 if (cptr_en_check.tz == 1)
1066 if (cptr_en_check.tfp == 1)
1074 if (!cptr_en_check.ez)
1076 if (cptr_en_check.tfp)
1088 return std::make_shared<SupervisorTrap>(
1091 return std::make_shared<HypervisorTrap>(
1094 return std::make_shared<SecureMonitorTrap>(
1098 panic(
"Illegal EL in smeAccessTrap\n");
1108 if ((
el ==
EL0 && cpacr.smen == 0x1) ||
1109 (!(cpacr.smen & 0x1)))
1112 if ((
el ==
EL0 && cpacr.fpen == 0x1) ||
1113 (!(cpacr.fpen & 0x1)))
1121 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1122 if (((cptr_en_check.smen & 0x1) == 0x0) ||
1123 (cptr_en_check.smen == 0x1 &&
el ==
EL0 &&
1127 if (((cptr_en_check.fpen & 0x1) == 0x0) ||
1128 (cptr_en_check.fpen == 0x1 &&
el ==
EL0 &&
1133 if (cptr_en_check.tsm == 1)
1135 if (cptr_en_check.tfp == 1)
1143 if (!cptr_en_check.esm)
1145 if (cptr_en_check.tfp)
1158 if ((
el ==
EL0 && cpacr.smen == 0x1) || (!(cpacr.smen & 0x1))) {
1167 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1168 if (((cptr_en_check.smen & 0x1) == 0x0) ||
1169 (cptr_en_check.smen == 0x1 &&
el ==
EL0 &&
1174 if (cptr_en_check.tsm == 1)
1182 if (!cptr_en_check.esm)
1209 const uint8_t it =
itState(spsr);
1211 if (!spsr.t || spsr.il)
1216 if (
bits(it, 7, 4) != 0 &&
bits(it, 3, 0) == 0)
1226 if (
itd &&
bits(it, 2, 0) != 0)
1250 }
else if (spsr & 0x2) {
1252 }
else if (target_el ==
EL0 && spsr.sp) {
1266 if (target_el >
currEL(tc))
1269 bool spsr_mode_is_aarch32 = (spsr.width == 1);
1271 assert(known || (target_el ==
EL0 &&
ELIs64(tc,
EL1)));
1273 if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32))
1296 new_cpsr.mode = cpsr.mode;
1298 new_cpsr.width = cpsr.width;
1299 new_cpsr.el = cpsr.el;
1300 new_cpsr.sp = cpsr.sp;
1304 new_cpsr.il = spsr.il;
1307 }
else if (spsr.width) {
1308 new_cpsr.mode = spsr.mode;
1310 new_cpsr.el = spsr.el;
1311 new_cpsr.sp = spsr.sp;
1316 new_cpsr.nz = spsr.nz;
1317 new_cpsr.c = spsr.c;
1318 new_cpsr.v = spsr.v;
1319 new_cpsr.pan = spsr.pan;
1320 if (new_cpsr.width) {
1323 new_cpsr.q = spsr.q;
1324 new_cpsr.ge = spsr.ge;
1325 new_cpsr.e = spsr.e;
1326 new_cpsr.aif = spsr.aif;
1327 new_cpsr.t = spsr.t;
1328 new_cpsr.it2 = it.top6;
1329 new_cpsr.it1 = it.bottom2;
1332 new_cpsr.daif = spsr.daif;
1333 new_cpsr.uao = spsr.uao;
void printMiscReg(std::ostream &os, RegIndex reg_idx) const
int64_t extendReg64(uint64_t base, ArmExtendType type, uint64_t shiftAmt, uint8_t width) const
Fault checkSveSmeEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an SVE access against CPACR_EL1, CPTR_EL2, and CPTR_EL3, but choosing the correct set of traps ...
void printExtendOperand(bool firstOperand, std::ostream &os, RegIndex rm, ArmExtendType type, int64_t shiftAmt) const
Fault softwareBreakpoint32(ExecContext *xc, uint16_t imm) const
Trigger a Software Breakpoint.
bool shift_carry_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
void printCondition(std::ostream &os, unsigned code, bool noImplicit=false) const
void printMnemonic(std::ostream &os, const std::string &suffix="", bool withPred=true, bool withCond64=false, ConditionCode cond64=COND_UC) const
void printCCReg(std::ostream &os, RegIndex reg_idx) const
bool generalExceptionsToAArch64(ThreadContext *tc, ExceptionLevel pstateEL) const
Return true if exceptions normally routed to EL1 are being handled at an Exception level using AArch6...
Fault checkSveEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an SVE access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
void printMemSymbol(std::ostream &os, const loader::SymbolTable *symtab, const std::string &prefix, const Addr addr, const std::string &suffix) const
Fault undefinedFault32(ThreadContext *tc, ExceptionLevel el) const
UNDEFINED behaviour in AArch32.
static unsigned getCurSmeVecLenInBits(ThreadContext *tc)
Fault checkForWFxTrap64(ThreadContext *tc, ExceptionLevel tgtEl, bool isWfe) const
Check if WFE/WFI instruction execution in aarch64 should be trapped.
static unsigned getCurSveVecLenInBits(ThreadContext *tc)
bool isWFxTrapping(ThreadContext *tc, ExceptionLevel targetEL, bool isWfe) const
Fault disabledFault() const
Fault smeAccessTrap(ExceptionLevel el, uint32_t iss=0) const
Trap an access to SME registers due to access control bits.
int64_t shiftReg64(uint64_t base, uint64_t shiftAmt, ArmShiftType type, uint8_t width) const
Fault checkAdvSIMDOrFPEnabled32(ThreadContext *tc, CPSR cpsr, CPACR cpacr, NSACR nsacr, FPEXC fpexc, bool fpexc_check, bool advsimd) const
Check if a VFP/SIMD access from aarch32 should be allowed.
int32_t shift_rm_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
void printDataInst(std::ostream &os, bool withImm) const
CPSR getPSTATEFromPSR(ThreadContext *tc, CPSR cpsr, CPSR spsr) const
Get the new PSTATE from a SPSR register in preparation for an exception return.
void printPFflags(std::ostream &os, int flag) const
Fault trapWFx(ThreadContext *tc, CPSR cpsr, SCR scr, bool isWfe) const
WFE/WFI trapping helper function.
Fault checkSmeEnabled(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check if SME is enabled by checking the SME and FP bits of CPACR_EL1, CPTR_EL2, and CPTR_EL3.
Fault undefinedFault64(ThreadContext *tc, ExceptionLevel el) const
UNDEFINED behaviour in AArch64.
void printVecReg(std::ostream &os, RegIndex reg_idx, bool isSveVecReg=false) 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 printShiftOperand(std::ostream &os, RegIndex rm, bool immShift, uint32_t shiftAmt, RegIndex rs, ArmShiftType type) const
Fault advSIMDFPAccessTrap64(ExceptionLevel el) const
Trap an access to Advanced SIMD or FP registers due to access control bits.
std::string generateDisassembly(Addr pc, const loader::SymbolTable *symtab) const override
Internal function to generate disassembly string.
static Addr readPC(ExecContext *xc)
Fault checkSmeAccess(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an SME access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
void printFloatReg(std::ostream &os, RegIndex reg_idx) const
Fault checkFPAdvSIMDTrap64(ThreadContext *tc, CPSR cpsr) const
Check an Advaned SIMD access against CPTR_EL2 and CPTR_EL3.
bool shift_carry_rs(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
Fault checkForWFxTrap32(ThreadContext *tc, ExceptionLevel tgtEl, bool isWfe) const
Check if WFE/WFI instruction execution in aarch32 should be trapped.
void printVecPredReg(std::ostream &os, RegIndex reg_idx) const
Fault sveAccessTrap(ExceptionLevel el) const
Trap an access to SVE registers due to access control bits.
Fault checkFPAdvSIMDEnabled64(ThreadContext *tc, CPSR cpsr, CPACR cpacr) const
Check an Advaned SIMD access against CPACR_EL1, CPTR_EL2, and CPTR_EL3.
int32_t shift_rm_imm(uint32_t base, uint32_t shamt, uint32_t type, uint32_t cfval) const
void printTarget(std::ostream &os, Addr target, const loader::SymbolTable *symtab) const
Fault checkSETENDEnabled(ThreadContext *tc, CPSR cpsr) const
Check if SETEND instruction execution in aarch32 should be trapped.
unsigned getCurSveVecLenInBits() const
SelfDebug * getSelfDebug() const
unsigned getCurSmeVecLenInBits() const
bool debugExceptionReturnSS(ThreadContext *tc, CPSR spsr, ExceptionLevel dest)
bool highestELIs64() const
Returns true if the register width of the highest implemented exception level is 64 bits (ARMv8)
static bool haveEL(ThreadContext *tc, ArmISA::ExceptionLevel el)
Return true if the system implements a specific exception level.
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
virtual ThreadContext * tcBase() const =0
Returns a pointer to the ThreadContext.
const char * mnemonic
Base mnemonic (e.g., "add").
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual RegVal readMiscReg(RegIndex misc_reg)=0
virtual BaseISA * getIsaPtr() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
const_iterator end() const
const_iterator findNearest(Addr addr, Addr &next_addr) const
Find the nearest symbol equal to or less than the supplied address (e.g., the label for the enclosing...
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
#define panic(...)
This implements a cprintf based panic() function.
const char *const RegName[NumRegs]
bool ELIs32(ThreadContext *tc, ExceptionLevel el)
bool ELIsInHost(ThreadContext *tc, ExceptionLevel el)
Returns true if the current exception level el is executing a Host OS or an application of a Host OS ...
ExceptionLevel currEL(const ThreadContext *tc)
Returns the current Exception Level (EL) of the provided ThreadContext.
bool isSecure(ThreadContext *tc)
constexpr auto & StackPointerReg
Bitfield< 23, 20 > advsimd
static bool illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
static bool unknownMode32(OperatingMode mode)
static bool unknownMode(OperatingMode mode)
constexpr auto & ReturnAddressReg
bool ELIs64(ThreadContext *tc, ExceptionLevel el)
bool isSecureBelowEL3(ThreadContext *tc)
bool EL2Enabled(ThreadContext *tc)
std::pair< bool, bool > ELUsingAArch32K(ThreadContext *tc, ExceptionLevel el)
This function checks whether selected EL provided as an argument is using the AArch32 ISA.
bool IsSecureEL2Enabled(ThreadContext *tc)
static uint8_t getRestoredITBits(ThreadContext *tc, CPSR spsr)
static ExceptionLevel opModeToEL(OperatingMode mode)
const char *const miscRegName[]
int snsBankedIndex(MiscRegIndex reg, ThreadContext *tc)
static uint8_t itState(CPSR psr)
bool HaveExt(ThreadContext *tc, ArmExtension ext)
Returns true if the provided ThreadContext supports the ArmExtension passed as a second argument.
constexpr auto & FramePointerReg
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
std::shared_ptr< FaultBase > Fault
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
constexpr decltype(nullptr) NoFault
void ccprintf(cp::Print &print)