mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 08:13:54 -06:00
target/arm: Implement v7m_update_fpccr()
Implement the code which updates the FPCCR register on an exception entry where we are going to use lazy FP stacking. We have to defer to the NVIC to determine whether the various exceptions are currently ready or not. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20190416125744.27770-12-peter.maydell@linaro.org
This commit is contained in:
parent
0ed377a801
commit
b593c2b812
3 changed files with 114 additions and 1 deletions
|
@ -8177,6 +8177,71 @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
|
|||
env->thumb = addr & 1;
|
||||
}
|
||||
|
||||
static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
|
||||
bool apply_splim)
|
||||
{
|
||||
/*
|
||||
* Like the pseudocode UpdateFPCCR: save state in FPCAR and FPCCR
|
||||
* that we will need later in order to do lazy FP reg stacking.
|
||||
*/
|
||||
bool is_secure = env->v7m.secure;
|
||||
void *nvic = env->nvic;
|
||||
/*
|
||||
* Some bits are unbanked and live always in fpccr[M_REG_S]; some bits
|
||||
* are banked and we want to update the bit in the bank for the
|
||||
* current security state; and in one case we want to specifically
|
||||
* update the NS banked version of a bit even if we are secure.
|
||||
*/
|
||||
uint32_t *fpccr_s = &env->v7m.fpccr[M_REG_S];
|
||||
uint32_t *fpccr_ns = &env->v7m.fpccr[M_REG_NS];
|
||||
uint32_t *fpccr = &env->v7m.fpccr[is_secure];
|
||||
bool hfrdy, bfrdy, mmrdy, ns_ufrdy, s_ufrdy, sfrdy, monrdy;
|
||||
|
||||
env->v7m.fpcar[is_secure] = frameptr & ~0x7;
|
||||
|
||||
if (apply_splim && arm_feature(env, ARM_FEATURE_V8)) {
|
||||
bool splimviol;
|
||||
uint32_t splim = v7m_sp_limit(env);
|
||||
bool ign = armv7m_nvic_neg_prio_requested(nvic, is_secure) &&
|
||||
(env->v7m.ccr[is_secure] & R_V7M_CCR_STKOFHFNMIGN_MASK);
|
||||
|
||||
splimviol = !ign && frameptr < splim;
|
||||
*fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, SPLIMVIOL, splimviol);
|
||||
}
|
||||
|
||||
*fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, LSPACT, 1);
|
||||
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, S, is_secure);
|
||||
|
||||
*fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, USER, arm_current_el(env) == 0);
|
||||
|
||||
*fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, THREAD,
|
||||
!arm_v7m_is_handler_mode(env));
|
||||
|
||||
hfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_HARD, false);
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
|
||||
|
||||
bfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_BUS, false);
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
|
||||
|
||||
mmrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_MEM, is_secure);
|
||||
*fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, MMRDY, mmrdy);
|
||||
|
||||
ns_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, false);
|
||||
*fpccr_ns = FIELD_DP32(*fpccr_ns, V7M_FPCCR, UFRDY, ns_ufrdy);
|
||||
|
||||
monrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_DEBUG, false);
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, MONRDY, monrdy);
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
|
||||
s_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, true);
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, UFRDY, s_ufrdy);
|
||||
|
||||
sfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_SECURE, false);
|
||||
*fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, SFRDY, sfrdy);
|
||||
}
|
||||
}
|
||||
|
||||
static bool v7m_push_stack(ARMCPU *cpu)
|
||||
{
|
||||
/* Do the "set up stack frame" part of exception entry,
|
||||
|
@ -8324,7 +8389,7 @@ static bool v7m_push_stack(ARMCPU *cpu)
|
|||
}
|
||||
} else {
|
||||
/* Lazy stacking enabled, save necessary info to stack later */
|
||||
/* TODO : equivalent of UpdateFPCCR() pseudocode */
|
||||
v7m_update_fpccr(env, frameptr + 0x20, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue