target/arm: Implement XPSR GE bits

In the M-profile architecture, if the CPU implements the DSP extension
then the XPSR has GE bits, in the same way as the A-profile CPSR. When
we added DSP extension support we forgot to add support for reading
and writing the GE bits, which are stored in env->GE. We did put in
the code to add XPSR_GE to the mask of bits to update in the v7m_msr
helper, but forgot it in v7m_mrs. We also must not allow the XPSR we
pull off the stack on exception return to set the nonexistent GE bits.
Correct these errors:
* read and write env->GE in xpsr_read() and xpsr_write()
* only set GE bits on exception return if DSP present
* read GE bits for MRS if DSP present

Backports commit f1e2598c46d480c9e21213a244bc514200762828 from qemu
This commit is contained in:
Peter Maydell 2019-05-09 17:46:24 -04:00 committed by Lioncash
parent bcb1270f23
commit 7861820e94
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
2 changed files with 14 additions and 2 deletions

View file

@ -1227,6 +1227,7 @@ static inline uint32_t xpsr_read(CPUARMState *env)
| (env->CF << 29) | ((env->VF & 0x80000000) >> 3) | (env->QF << 27)
| (env->thumb << 24) | ((env->condexec_bits & 3) << 25)
| ((env->condexec_bits & 0xfc) << 8)
| (env->GE << 16)
| env->v7m.exception;
}
@ -1242,6 +1243,9 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
if (mask & XPSR_Q) {
env->QF = ((val & XPSR_Q) != 0);
}
if (mask & XPSR_GE) {
env->GE = (val & XPSR_GE) >> 16;
}
if (mask & XPSR_T) {
env->thumb = ((val & XPSR_T) != 0);
}

View file

@ -8511,7 +8511,7 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
{
CPUARMState *env = &cpu->env;
uint32_t excret;
uint32_t xpsr;
uint32_t xpsr, xpsr_mask;
bool ufault = false;
bool sfault = false;
bool return_to_sp_process;
@ -8972,8 +8972,13 @@ static void do_v7m_exception_exit(ARMCPU *cpu)
}
*frame_sp_p = frameptr;
}
xpsr_mask = ~(XPSR_SPREALIGN | XPSR_SFPA);
if (!arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
xpsr_mask &= ~XPSR_GE;
}
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
xpsr_write(env, xpsr, xpsr_mask);
if (env->v7m.secure) {
bool sfpa = xpsr & XPSR_SFPA;
@ -12455,6 +12460,9 @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
}
if (!(reg & 4)) {
mask |= XPSR_NZCV | XPSR_Q; /* APSR */
if (arm_feature(env, ARM_FEATURE_THUMB_DSP)) {
mask |= XPSR_GE;
}
}
/* EPSR reads as zero */
return xpsr_read(env) & mask;