illegalExceptionReturn(ThreadContext *tc, CPSR cpsr, CPSR spsr)
{
const OperatingMode mode = (OperatingMode) (uint8_t)spsr.mode;
- if (badMode(mode))
+ if (unknownMode(mode))
return true;
const OperatingMode cur_mode = (OperatingMode) (uint8_t)cpsr.mode;
return true;
} else {
// aarch32
- return badMode32(mode);
+ return unknownMode32(mode);
}
return false;
}
} else {
new_cpsr.il = spsr.il;
- if (spsr.width && badMode32((OperatingMode)(uint8_t)spsr.mode)) {
+ if (spsr.width && unknownMode32((OperatingMode)(uint8_t)spsr.mode)) {
new_cpsr.il = 1;
} else if (spsr.width) {
new_cpsr.mode = spsr.mode;
// Now check the new mode is allowed
OperatingMode newMode = (OperatingMode) (val & mask(5));
OperatingMode oldMode = (OperatingMode)(uint32_t)cpsr.mode;
- if (!badMode(newMode)) {
+ if (!badMode(tc, newMode)) {
bool validModeChange = true;
// Check for attempts to enter modes only permitted in
// Secure state from Non-secure state. These are Monitor
}
} else {
const uint32_t mode = bits(machInst, 4, 0);
- if (badMode32((OperatingMode)mode))
+ // We check at decode stage if the mode exists even
+ // if the checking is re-done by Srs::execute.
+ // This is done because we will otherwise panic if
+ // trying to read the banked stack pointer of an
+ // unrecognized mode.
+ if (unknownMode32((OperatingMode)mode))
return new Unknown(machInst);
if (!add && !wb) {
return new %(srs)s(machInst, mode,
const uint32_t val = ((machInst >> 20) & 0x5);
if (val == 0x4) {
const uint32_t mode = bits(machInst, 4, 0);
- if (badMode32((OperatingMode)mode))
+ // We check at decode stage if the mode exists even
+ // if the checking is re-done by Srs::execute.
+ // This is done because we will otherwise panic if
+ // trying to read the banked stack pointer of an
+ // unrecognized mode.
+ if (unknownMode32((OperatingMode)mode))
return new Unknown(machInst);
switch (bits(machInst, 24, 21)) {
case 0x2:
if self.add:
wbDiff = 8
accCode = '''
+
+ auto tc = xc->tcBase();
+ if (badMode32(tc, static_cast<OperatingMode>(regMode))) {
+ return undefinedFault32(tc, opModeToEL(currOpMode(tc)));
+ }
+
CPSR cpsr = Cpsr;
Mem_ud = (uint64_t)cSwap(LR_uw, cpsr.e) |
((uint64_t)cSwap(Spsr_uw, cpsr.e) << 32);
}
static inline bool
- badMode(OperatingMode mode)
+ unknownMode(OperatingMode mode)
{
switch (mode) {
case MODE_EL0T:
}
}
-
static inline bool
- badMode32(OperatingMode mode)
+ unknownMode32(OperatingMode mode)
{
switch (mode) {
case MODE_USER:
}
}
+bool
+badMode32(ThreadContext *tc, OperatingMode mode)
+{
+ return unknownMode32(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
+}
+
+bool
+badMode(ThreadContext *tc, OperatingMode mode)
+{
+ return unknownMode(mode) || !ArmSystem::haveEL(tc, opModeToEL(mode));
+}
+
Addr
purifyTaggedAddr(Addr addr, ThreadContext *tc, ExceptionLevel el,
TTBCR tcr)
bool isBigEndian64(ThreadContext *tc);
+/**
+ * badMode is checking if the execution mode provided as an argument is
+ * valid and implemented for AArch32
+ *
+ * @param tc ThreadContext
+ * @param mode OperatingMode to check
+ * @return false if mode is valid and implemented, true otherwise
+ */
+bool badMode32(ThreadContext *tc, OperatingMode mode);
+
+/**
+ * badMode is checking if the execution mode provided as an argument is
+ * valid and implemented.
+ *
+ * @param tc ThreadContext
+ * @param mode OperatingMode to check
+ * @return false if mode is valid and implemented, true otherwise
+ */
+bool badMode(ThreadContext *tc, OperatingMode mode);
+
static inline uint8_t
itState(CPSR psr)
{