mirror of https://github.com/xemu-project/xemu.git
target/arm: Make vfp_set_fpscr() call vfp_set_{fpcr, fpsr}
Make vfp_set_fpscr() call vfp_set_fpsr() and vfp_set_fpcr() instead of the other way around. The masking we do when getting and setting vfp.xregs[ARM_VFP_FPSCR] is a little awkward, but we are going to change where we store the underlying FPSR and FPCR information in a later commit, so it will go away then. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20240628142347.1283015-4-peter.maydell@linaro.org
This commit is contained in:
parent
2de7cf9e05
commit
b167325e93
|
@ -1730,17 +1730,19 @@ uint32_t vfp_get_fpsr(CPUARMState *env);
|
|||
*/
|
||||
uint32_t vfp_get_fpcr(CPUARMState *env);
|
||||
|
||||
static inline void vfp_set_fpsr(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
uint32_t new_fpscr = (vfp_get_fpscr(env) & ~FPSR_MASK) | (val & FPSR_MASK);
|
||||
vfp_set_fpscr(env, new_fpscr);
|
||||
}
|
||||
/**
|
||||
* vfp_set_fpsr: write the AArch64 FPSR
|
||||
* @env: CPU context
|
||||
* @value: new value
|
||||
*/
|
||||
void vfp_set_fpsr(CPUARMState *env, uint32_t value);
|
||||
|
||||
static inline void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
uint32_t new_fpscr = (vfp_get_fpscr(env) & ~FPCR_MASK) | (val & FPCR_MASK);
|
||||
vfp_set_fpscr(env, new_fpscr);
|
||||
}
|
||||
/**
|
||||
* vfp_set_fpcr: write the AArch64 FPCR
|
||||
* @env: CPU context
|
||||
* @value: new value
|
||||
*/
|
||||
void vfp_set_fpcr(CPUARMState *env, uint32_t value);
|
||||
|
||||
enum arm_cpu_mode {
|
||||
ARM_CPU_MODE_USR = 0x10,
|
||||
|
|
|
@ -99,14 +99,27 @@ static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
|
|||
return vfp_exceptbits_from_host(i);
|
||||
}
|
||||
|
||||
static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val)
|
||||
static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
/*
|
||||
* The exception flags are ORed together when we read fpscr so we
|
||||
* only need to preserve the current state in one of our
|
||||
* float_status values.
|
||||
*/
|
||||
int i = vfp_exceptbits_to_host(val);
|
||||
set_float_exception_flags(i, &env->vfp.fp_status);
|
||||
set_float_exception_flags(0, &env->vfp.fp_status_f16);
|
||||
set_float_exception_flags(0, &env->vfp.standard_fp_status);
|
||||
set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
|
||||
}
|
||||
|
||||
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
int i;
|
||||
uint32_t changed = env->vfp.xregs[ARM_VFP_FPSCR];
|
||||
|
||||
changed ^= val;
|
||||
if (changed & (3 << 22)) {
|
||||
i = (val >> 22) & 3;
|
||||
int i = (val >> 22) & 3;
|
||||
switch (i) {
|
||||
case FPROUNDING_TIEEVEN:
|
||||
i = float_round_nearest_even;
|
||||
|
@ -141,17 +154,6 @@ static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val)
|
|||
set_default_nan_mode(dnan_enabled, &env->vfp.fp_status);
|
||||
set_default_nan_mode(dnan_enabled, &env->vfp.fp_status_f16);
|
||||
}
|
||||
|
||||
/*
|
||||
* The exception flags are ORed together when we read fpscr so we
|
||||
* only need to preserve the current state in one of our
|
||||
* float_status values.
|
||||
*/
|
||||
i = vfp_exceptbits_to_host(val);
|
||||
set_float_exception_flags(i, &env->vfp.fp_status);
|
||||
set_float_exception_flags(0, &env->vfp.fp_status_f16);
|
||||
set_float_exception_flags(0, &env->vfp.standard_fp_status);
|
||||
set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -161,7 +163,11 @@ static uint32_t vfp_get_fpsr_from_host(CPUARMState *env)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void vfp_set_fpscr_to_host(CPUARMState *env, uint32_t val)
|
||||
static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
}
|
||||
|
||||
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -204,7 +210,37 @@ uint32_t vfp_get_fpscr(CPUARMState *env)
|
|||
return HELPER(vfp_get_fpscr)(env);
|
||||
}
|
||||
|
||||
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
||||
void vfp_set_fpsr(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
vfp_set_fpsr_to_host(env, val);
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_NEON) ||
|
||||
cpu_isar_feature(aa32_mve, cpu)) {
|
||||
/*
|
||||
* The bit we set within vfp.qc[] is arbitrary; the array as a
|
||||
* whole being zero/non-zero is what counts.
|
||||
*/
|
||||
env->vfp.qc[0] = val & FPCR_QC;
|
||||
env->vfp.qc[1] = 0;
|
||||
env->vfp.qc[2] = 0;
|
||||
env->vfp.qc[3] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The only FPSR bits we keep in vfp.xregs[FPSCR] are NZCV:
|
||||
* the exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
|
||||
* fp_status, and QC is in vfp.qc[]. Store the NZCV bits there,
|
||||
* and zero any of the other FPSR bits (but preserve the FPCR
|
||||
* bits).
|
||||
*/
|
||||
val &= FPCR_NZCV_MASK;
|
||||
env->vfp.xregs[ARM_VFP_FPSCR] &= ~FPSR_MASK;
|
||||
env->vfp.xregs[ARM_VFP_FPSCR] |= val;
|
||||
}
|
||||
|
||||
void vfp_set_fpcr(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
|
||||
|
@ -213,7 +249,7 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
|||
val &= ~FPCR_FZ16;
|
||||
}
|
||||
|
||||
vfp_set_fpscr_to_host(env, val);
|
||||
vfp_set_fpcr_to_host(env, val);
|
||||
|
||||
if (!arm_feature(env, ARM_FEATURE_M)) {
|
||||
/*
|
||||
|
@ -231,28 +267,24 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
|||
FPCR_LTPSIZE_LENGTH);
|
||||
}
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_NEON) ||
|
||||
cpu_isar_feature(aa32_mve, cpu)) {
|
||||
/*
|
||||
* The bit we set within fpscr_q is arbitrary; the register as a
|
||||
* whole being zero/non-zero is what counts.
|
||||
*/
|
||||
env->vfp.qc[0] = val & FPCR_QC;
|
||||
env->vfp.qc[1] = 0;
|
||||
env->vfp.qc[2] = 0;
|
||||
env->vfp.qc[3] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't implement trapped exception handling, so the
|
||||
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
|
||||
*
|
||||
* The exception flags IOC|DZC|OFC|UFC|IXC|IDC are stored in
|
||||
* fp_status; QC, Len and Stride are stored separately earlier.
|
||||
* Clear out all of those and the RES0 bits: only NZCV, AHP, DN,
|
||||
* FZ, RMode and FZ16 are kept in vfp.xregs[FPSCR].
|
||||
* The FPCR bits we keep in vfp.xregs[FPSCR] are AHP, DN, FZ, RMode
|
||||
* and FZ16. Len, Stride and LTPSIZE we just handled. Store those bits
|
||||
* there, and zero any of the other FPCR bits and the RES0 and RAZ/WI
|
||||
* bits.
|
||||
*/
|
||||
env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
|
||||
val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16;
|
||||
env->vfp.xregs[ARM_VFP_FPSCR] &= ~FPCR_MASK;
|
||||
env->vfp.xregs[ARM_VFP_FPSCR] |= val;
|
||||
}
|
||||
|
||||
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
|
||||
{
|
||||
vfp_set_fpcr(env, val & FPCR_MASK);
|
||||
vfp_set_fpsr(env, val & FPSR_MASK);
|
||||
}
|
||||
|
||||
void vfp_set_fpscr(CPUARMState *env, uint32_t val)
|
||||
|
|
Loading…
Reference in New Issue