target/arm: Allow FPCR bits that aren't in FPSCR
In order to allow FPCR bits that aren't in the FPSCR (like the new bits that are defined for FEAT_AFP), we need to make sure that writes to the FPSCR only write to the bits of FPCR that are architecturally mapped, and not the others. Implement this with a new function vfp_set_fpcr_masked() which takes a mask of which bits to update. (We could do the same for FPSR, but we leave that until we actually are likely to need it.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20240628142347.1283015-10-peter.maydell@linaro.org
This commit is contained in:
parent
db397a81ee
commit
a8ab8706d4
@ -113,11 +113,12 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
|
|||||||
set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
|
set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
|
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||||
{
|
{
|
||||||
uint64_t changed = env->vfp.fpcr;
|
uint64_t changed = env->vfp.fpcr;
|
||||||
|
|
||||||
changed ^= val;
|
changed ^= val;
|
||||||
|
changed &= mask;
|
||||||
if (changed & (3 << 22)) {
|
if (changed & (3 << 22)) {
|
||||||
int i = (val >> 22) & 3;
|
int i = (val >> 22) & 3;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
@ -167,7 +168,7 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
|
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,8 +240,13 @@ void vfp_set_fpsr(CPUARMState *env, uint32_t val)
|
|||||||
env->vfp.fpsr = val;
|
env->vfp.fpsr = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
static void vfp_set_fpcr_masked(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* We only set FPCR bits defined by mask, and leave the others alone.
|
||||||
|
* We assume the mask is sensible (e.g. doesn't try to set only
|
||||||
|
* part of a field)
|
||||||
|
*/
|
||||||
ARMCPU *cpu = env_archcpu(env);
|
ARMCPU *cpu = env_archcpu(env);
|
||||||
|
|
||||||
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
|
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
|
||||||
@ -248,8 +254,9 @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
|||||||
val &= ~FPCR_FZ16;
|
val &= ~FPCR_FZ16;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfp_set_fpcr_to_host(env, val);
|
vfp_set_fpcr_to_host(env, val, mask);
|
||||||
|
|
||||||
|
if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK)) {
|
||||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||||
/*
|
/*
|
||||||
* Short-vector length and stride; on M-profile these bits
|
* Short-vector length and stride; on M-profile these bits
|
||||||
@ -265,6 +272,7 @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
|||||||
env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
|
env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
|
||||||
FPCR_LTPSIZE_LENGTH);
|
FPCR_LTPSIZE_LENGTH);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't implement trapped exception handling, so the
|
* We don't implement trapped exception handling, so the
|
||||||
@ -276,12 +284,18 @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
|||||||
* bits.
|
* bits.
|
||||||
*/
|
*/
|
||||||
val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16;
|
val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16;
|
||||||
env->vfp.fpcr = val;
|
env->vfp.fpcr &= ~mask;
|
||||||
|
env->vfp.fpcr |= val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
||||||
|
{
|
||||||
|
vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
||||||
{
|
{
|
||||||
vfp_set_fpcr(env, val & FPSCR_FPCR_MASK);
|
vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
|
||||||
vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
|
vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user