aboutsummaryrefslogtreecommitdiff
path: root/target-arm
diff options
context:
space:
mode:
Diffstat (limited to 'target-arm')
-rw-r--r--target-arm/cpu.c8
-rw-r--r--target-arm/cpu.h12
-rw-r--r--target-arm/helper.c29
3 files changed, 30 insertions, 19 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 2f949437fd..7384e17561 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -94,8 +94,7 @@ static void arm_cpu_reset(CPUState *s)
/* Userspace expects access to CTL_EL0 and the cache ops */
env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI;
#else
- env->pstate = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F
- | PSTATE_MODE_EL1h;
+ env->pstate = PSTATE_MODE_EL1h;
#endif
}
@@ -110,13 +109,14 @@ static void arm_cpu_reset(CPUState *s)
}
#else
/* SVC mode with interrupts disabled. */
- env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+ env->uncached_cpsr = ARM_CPU_MODE_SVC;
+ env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
/* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
clear at reset. Initial SP and PC are loaded from ROM. */
if (IS_M(env)) {
uint32_t pc;
uint8_t *rom;
- env->uncached_cpsr &= ~CPSR_I;
+ env->daif &= ~PSTATE_I;
rom = rom_ptr(0);
if (rom) {
/* We should really use ldl_phys here, in case the guest
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 9fe7da215c..67e935df42 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -135,6 +135,7 @@ typedef struct CPUARMState {
* NZCV are kept in the split out env->CF/VF/NF/ZF, (which have the same
* semantics as for AArch32, as described in the comments on each field)
* nRW (also known as M[4]) is kept, inverted, in env->aarch64
+ * DAIF (exception masks) are kept in env->daif
* all other bits are stored in their correct places in env->pstate
*/
uint32_t pstate;
@@ -164,6 +165,7 @@ typedef struct CPUARMState {
uint32_t GE; /* cpsr[19:16] */
uint32_t thumb; /* cpsr[5]. 0 = arm mode, 1 = thumb mode. */
uint32_t condexec_bits; /* IT bits. cpsr[15:10,26:25]. */
+ uint32_t daif; /* exception masks, in the bits they are in in PSTATE */
/* System control coprocessor (cp15) */
struct {
@@ -406,9 +408,11 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
#define CPSR_Z (1U << 30)
#define CPSR_N (1U << 31)
#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
+#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
#define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
-#define CACHED_CPSR_BITS (CPSR_T | CPSR_GE | CPSR_IT | CPSR_Q | CPSR_NZCV)
+#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
+ | CPSR_NZCV)
/* Bits writable in user mode. */
#define CPSR_USER (CPSR_NZCV | CPSR_Q | CPSR_GE)
/* Execution state bits. MRS read as zero, MSR writes ignored. */
@@ -431,7 +435,8 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw,
#define PSTATE_Z (1U << 30)
#define PSTATE_N (1U << 31)
#define PSTATE_NZCV (PSTATE_N | PSTATE_Z | PSTATE_C | PSTATE_V)
-#define CACHED_PSTATE_BITS (PSTATE_NZCV)
+#define PSTATE_DAIF (PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F)
+#define CACHED_PSTATE_BITS (PSTATE_NZCV | PSTATE_DAIF)
/* Mode values for AArch64 */
#define PSTATE_MODE_EL3h 13
#define PSTATE_MODE_EL3t 12
@@ -452,7 +457,7 @@ static inline uint32_t pstate_read(CPUARMState *env)
ZF = (env->ZF == 0);
return (env->NF & 0x80000000) | (ZF << 30)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3)
- | env->pstate;
+ | env->pstate | env->daif;
}
static inline void pstate_write(CPUARMState *env, uint32_t val)
@@ -461,6 +466,7 @@ static inline void pstate_write(CPUARMState *env, uint32_t val)
env->NF = val;
env->CF = (val >> 29) & 1;
env->VF = (val << 3) & 0x80000000;
+ env->daif = val & PSTATE_DAIF;
env->pstate = val & ~CACHED_PSTATE_BITS;
}
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 61303b6ce9..01d1ef6679 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2475,7 +2475,7 @@ uint32_t cpsr_read(CPUARMState *env)
(env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 5) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8)
- | (env->GE << 16);
+ | (env->GE << 16) | env->daif;
}
void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
@@ -2502,6 +2502,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
env->GE = (val >> 16) & 0xf;
}
+ env->daif &= ~(CPSR_AIF & mask);
+ env->daif |= val & CPSR_AIF & mask;
+
if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
if (bad_mode_switch(env, val & CPSR_M)) {
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
@@ -2963,7 +2966,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
env->condexec_bits = 0;
/* Switch to the new mode, and to the correct instruction set. */
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
- env->uncached_cpsr |= mask;
+ env->daif |= mask;
/* this is a lie, as the was no c1_sys on V4T/V5, but who cares
* and we should just guard the thumb mode on V4 */
if (arm_feature(env, ARM_FEATURE_V4T)) {
@@ -3636,12 +3639,12 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
case 9: /* PSP */
return env->v7m.current_sp ? env->regs[13] : env->v7m.other_sp;
case 16: /* PRIMASK */
- return (env->uncached_cpsr & CPSR_I) != 0;
+ return (env->daif & PSTATE_I) != 0;
case 17: /* BASEPRI */
case 18: /* BASEPRI_MAX */
return env->v7m.basepri;
case 19: /* FAULTMASK */
- return (env->uncached_cpsr & CPSR_F) != 0;
+ return (env->daif & PSTATE_F) != 0;
case 20: /* CONTROL */
return env->v7m.control;
default:
@@ -3688,10 +3691,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
env->v7m.other_sp = val;
break;
case 16: /* PRIMASK */
- if (val & 1)
- env->uncached_cpsr |= CPSR_I;
- else
- env->uncached_cpsr &= ~CPSR_I;
+ if (val & 1) {
+ env->daif |= PSTATE_I;
+ } else {
+ env->daif &= ~PSTATE_I;
+ }
break;
case 17: /* BASEPRI */
env->v7m.basepri = val & 0xff;
@@ -3702,10 +3706,11 @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val)
env->v7m.basepri = val;
break;
case 19: /* FAULTMASK */
- if (val & 1)
- env->uncached_cpsr |= CPSR_F;
- else
- env->uncached_cpsr &= ~CPSR_F;
+ if (val & 1) {
+ env->daif |= PSTATE_F;
+ } else {
+ env->daif &= ~PSTATE_F;
+ }
break;
case 20: /* CONTROL */
env->v7m.control = val & 3;