Skip to content

Commit a8ab870

Browse files
committed
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 <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-id: [email protected]
1 parent db397a8 commit a8ab870

File tree

1 file changed

+35
-21
lines changed

1 file changed

+35
-21
lines changed

target/arm/vfp_helper.c

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,12 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
113113
set_float_exception_flags(0, &env->vfp.standard_fp_status_f16);
114114
}
115115

116-
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
116+
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
117117
{
118118
uint64_t changed = env->vfp.fpcr;
119119

120120
changed ^= val;
121+
changed &= mask;
121122
if (changed & (3 << 22)) {
122123
int i = (val >> 22) & 3;
123124
switch (i) {
@@ -167,7 +168,7 @@ static void vfp_set_fpsr_to_host(CPUARMState *env, uint32_t val)
167168
{
168169
}
169170

170-
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val)
171+
static void vfp_set_fpcr_to_host(CPUARMState *env, uint32_t val, uint32_t mask)
171172
{
172173
}
173174

@@ -239,31 +240,38 @@ void vfp_set_fpsr(CPUARMState *env, uint32_t val)
239240
env->vfp.fpsr = val;
240241
}
241242

242-
void vfp_set_fpcr(CPUARMState *env, uint32_t val)
243+
static void vfp_set_fpcr_masked(CPUARMState *env, uint32_t val, uint32_t mask)
243244
{
245+
/*
246+
* We only set FPCR bits defined by mask, and leave the others alone.
247+
* We assume the mask is sensible (e.g. doesn't try to set only
248+
* part of a field)
249+
*/
244250
ARMCPU *cpu = env_archcpu(env);
245251

246252
/* When ARMv8.2-FP16 is not supported, FZ16 is RES0. */
247253
if (!cpu_isar_feature(any_fp16, cpu)) {
248254
val &= ~FPCR_FZ16;
249255
}
250256

251-
vfp_set_fpcr_to_host(env, val);
252-
253-
if (!arm_feature(env, ARM_FEATURE_M)) {
254-
/*
255-
* Short-vector length and stride; on M-profile these bits
256-
* are used for different purposes.
257-
* We can't make this conditional be "if MVFR0.FPShVec != 0",
258-
* because in v7A no-short-vector-support cores still had to
259-
* allow Stride/Len to be written with the only effect that
260-
* some insns are required to UNDEF if the guest sets them.
261-
*/
262-
env->vfp.vec_len = extract32(val, 16, 3);
263-
env->vfp.vec_stride = extract32(val, 20, 2);
264-
} else if (cpu_isar_feature(aa32_mve, cpu)) {
265-
env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
266-
FPCR_LTPSIZE_LENGTH);
257+
vfp_set_fpcr_to_host(env, val, mask);
258+
259+
if (mask & (FPCR_LEN_MASK | FPCR_STRIDE_MASK)) {
260+
if (!arm_feature(env, ARM_FEATURE_M)) {
261+
/*
262+
* Short-vector length and stride; on M-profile these bits
263+
* are used for different purposes.
264+
* We can't make this conditional be "if MVFR0.FPShVec != 0",
265+
* because in v7A no-short-vector-support cores still had to
266+
* allow Stride/Len to be written with the only effect that
267+
* some insns are required to UNDEF if the guest sets them.
268+
*/
269+
env->vfp.vec_len = extract32(val, 16, 3);
270+
env->vfp.vec_stride = extract32(val, 20, 2);
271+
} else if (cpu_isar_feature(aa32_mve, cpu)) {
272+
env->v7m.ltpsize = extract32(val, FPCR_LTPSIZE_SHIFT,
273+
FPCR_LTPSIZE_LENGTH);
274+
}
267275
}
268276

269277
/*
@@ -276,12 +284,18 @@ void vfp_set_fpcr(CPUARMState *env, uint32_t val)
276284
* bits.
277285
*/
278286
val &= FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK | FPCR_FZ16;
279-
env->vfp.fpcr = val;
287+
env->vfp.fpcr &= ~mask;
288+
env->vfp.fpcr |= val;
289+
}
290+
291+
void vfp_set_fpcr(CPUARMState *env, uint32_t val)
292+
{
293+
vfp_set_fpcr_masked(env, val, MAKE_64BIT_MASK(0, 32));
280294
}
281295

282296
void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
283297
{
284-
vfp_set_fpcr(env, val & FPSCR_FPCR_MASK);
298+
vfp_set_fpcr_masked(env, val, FPSCR_FPCR_MASK);
285299
vfp_set_fpsr(env, val & FPSCR_FPSR_MASK);
286300
}
287301

0 commit comments

Comments
 (0)