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),
664 bool trap_el2 =
false;
667 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h == 0x1) {
668 switch (cptr_en_check.fpen) {
671 trap_el2 = !(
currEL(tc) ==
EL1 && hcr.tge == 1);
674 trap_el2 = (
currEL(tc) ==
EL0 && hcr.tge == 1);
680 }
else if (cptr_en_check.tfp) {
691 if (cptr_en_check.tfp) {
701 CPSR cpsr, CPACR cpacr)
const
704 if (((
el ==
EL0 && cpacr.fpen != 0x3) ||
705 (
el ==
EL1 && !(cpacr.fpen & 0x1))) &&
714 CPSR cpsr, CPACR cpacr,
715 NSACR nsacr, FPEXC fpexc,
716 bool fpexc_check,
bool advsimd)
const
720 const bool is_secure =
isSecure(tc);
726 uint8_t cpacr_cp10 = cpacr.cp10;
727 bool cpacr_asedis = cpacr.asedis;
729 if (have_security && !
ELIs64(tc,
EL3) && !is_secure) {
740 if ((cur_el ==
EL0 && cpacr_cp10 != 0x3) ||
741 (cur_el !=
EL0 && !(cpacr_cp10 & 0x1)))
745 if (fpexc_check && !fpexc.en)
750 if (have_virtualization && !is_secure &&
ELIs64(tc,
EL2))
753 if (have_virtualization && !is_secure) {
755 bool hcptr_cp10 = hcptr.tcp10;
756 bool hcptr_tase = hcptr.tase;
758 if (have_security && !
ELIs64(tc,
EL3) && !is_secure) {
765 if ((
advsimd && hcptr_tase) || hcptr_cp10) {
766 const uint32_t
iss =
advsimd ? (1 << 5) : 0xA;
768 return std::make_shared<UndefinedInstruction>(
772 return std::make_shared<HypervisorTrap>(
782 if (cptr_en_check.tfp)
801 trap = isWfe? !sctlr.ntwe : !sctlr.ntwi;
804 trap = isWfe? hcr.twe : hcr.twi;
807 trap = isWfe? scr.twe : scr.twi;
827 if (
ELIs64(tc, targetEL)) {
835 uint32_t
iss = isWfe? 0x1E00001 :
839 return std::make_shared<UndefinedInstruction>(
843 return std::make_shared<HypervisorTrap>(
847 return std::make_shared<SecureMonitorTrap>(
851 panic(
"Unrecognized Exception Level: %d\n", targetEL);
868 uint32_t
iss = is_wfe? 0x1E00001 :
884 if (curr_el ==
EL0) {
889 ((curr_el ==
EL0) || (curr_el ==
EL1))) {
905 bool setend_disabled(
false);
908 if (pstate_el ==
EL2) {
947 return std::make_shared<UndefinedInstruction>(
960 return std::make_shared<SupervisorTrap>(
963 return std::make_shared<HypervisorTrap>(
966 return std::make_shared<SecureMonitorTrap>(
969 panic(
"Unrecognized Exception Level: %d\n", pstateEL);
988 if (svcr_sm_check.sm) {
995 if ((
el ==
EL0 && cpacr.zen == 0x1) ||
996 (!(cpacr.zen & 0x1)))
999 if ((
el ==
EL0 && cpacr.fpen == 0x1) ||
1000 (!(cpacr.fpen & 0x1)))
1008 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1009 if (((cptr_en_check.zen & 0x1) == 0x0) ||
1010 (cptr_en_check.zen == 0x1 &&
el ==
EL0 &&
1014 if (((cptr_en_check.fpen & 0x1) == 0x0) ||
1015 (cptr_en_check.fpen == 0x1 &&
el ==
EL0 &&
1020 if (cptr_en_check.tz == 1)
1022 if (cptr_en_check.tfp == 1)
1030 if (!cptr_en_check.ez)
1032 if (cptr_en_check.tfp)
1051 if ((
el ==
EL0 && cpacr.smen == 0x1) ||
1052 (!(cpacr.smen & 0x1)))
1055 if ((
el ==
EL0 && cpacr.fpen == 0x1) ||
1056 (!(cpacr.fpen & 0x1)))
1064 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1065 if (((cptr_en_check.smen & 0x1) == 0x0) ||
1066 (cptr_en_check.smen == 0x1 &&
el ==
EL0 &&
1070 if (((cptr_en_check.fpen & 0x1) == 0x0) ||
1071 (cptr_en_check.fpen == 0x1 &&
el ==
EL0 &&
1076 if (cptr_en_check.tsm == 1)
1078 if (cptr_en_check.tfp == 1)
1086 if (!cptr_en_check.esm)
1088 if (cptr_en_check.tfp)
1101 if ((
el ==
EL0 && cpacr.smen == 0x1) || (!(cpacr.smen & 0x1))) {
1110 if (
HaveExt(tc, ArmExtension::FEAT_VHE) && hcr.e2h) {
1111 if (((cptr_en_check.smen & 0x1) == 0x0) ||
1112 (cptr_en_check.smen == 0x1 &&
el ==
EL0 &&
1117 if (cptr_en_check.tsm == 1)
1125 if (!cptr_en_check.esm)
1152 const uint8_t it =
itState(spsr);
1154 if (!spsr.t || spsr.il)
1159 if (
bits(it, 7, 4) != 0 &&
bits(it, 3, 0) == 0)
1169 if (
itd &&
bits(it, 2, 0) != 0)
1193 }
else if (spsr & 0x2) {
1195 }
else if (target_el ==
EL0 && spsr.sp) {
1209 if (target_el >
currEL(tc))
1212 bool spsr_mode_is_aarch32 = (spsr.width == 1);
1214 assert(known || (target_el ==
EL0 &&
ELIs64(tc,
EL1)));
1216 if (known && (spsr_mode_is_aarch32 != target_el_is_aarch32))
1239 new_cpsr.mode = cpsr.mode;
1241 new_cpsr.width = cpsr.width;
1242 new_cpsr.el = cpsr.el;
1243 new_cpsr.sp = cpsr.sp;
1247 new_cpsr.il = spsr.il;
1250 }
else if (spsr.width) {
1251 new_cpsr.mode = spsr.mode;
1253 new_cpsr.el = spsr.el;
1254 new_cpsr.sp = spsr.sp;
1259 new_cpsr.nz = spsr.nz;
1260 new_cpsr.c = spsr.c;
1261 new_cpsr.v = spsr.v;
1262 new_cpsr.pan = spsr.pan;
1263 if (new_cpsr.width) {
1266 new_cpsr.q = spsr.q;
1267 new_cpsr.ge = spsr.ge;
1268 new_cpsr.e = spsr.e;
1269 new_cpsr.aif = spsr.aif;
1270 new_cpsr.t = spsr.t;
1271 new_cpsr.it2 = it.top6;
1272 new_cpsr.it1 = it.bottom2;
1275 new_cpsr.daif = spsr.daif;
1276 new_cpsr.uao = spsr.uao;
1319 return std::make_shared<SupervisorTrap>(
getEMI(),
iss,
ec);
1321 return std::make_shared<HypervisorTrap>(
getEMI(),
iss,
ec);
1323 return std::make_shared<SecureMonitorTrap>(
getEMI(),
iss,
ec);
1325 panic(
"Invalid EL: %d\n",
el);
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 generateTrap(ArmISA::ExceptionLevel el, ArmISA::ExceptionClass ec, uint32_t iss) 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
uint64_t getEMI() const override
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 Arm Limited 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)