On 10/12/20 8:37 AM, Peter Maydell wrote:
> @@ -198,8 +200,14 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t
> val)
> /*
> * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
> * and also for the trapped-exception-handling bits IxE.
> + * From v8.1M with the low-overhead-loop extension bits
> + * [18:16] are used for LTPSIZE and (since we don't implement
> + * MVE) always read as 4 and ignore writes.
> */
> val &= 0xf7c0009f;
> + if (cpu_isar_feature(aa32_lob, cpu)) {
> + val |= 4 << 16;
> + }
> }
>
> vfp_set_fpscr_to_host(env, val);
> @@ -212,9 +220,18 @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t
> val)
> * (which are stored in fp_status), and the other RES0 bits
> * in between, then we clear all of the low 16 bits.
> */
> - env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
> - env->vfp.vec_len = (val >> 16) & 7;
> - env->vfp.vec_stride = (val >> 20) & 3;
> + if (cpu_isar_feature(aa32_lob, cpu)) {
> + /*
> + * M-profile low-overhead-loop extension: [18:16] are LTPSIZE
> + * and we keep them in vfp.xregs[].
> + */
> + env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7cf0000;
> + } else {
> + /* Those bits might be the old-style short vector length/stride */
> + env->vfp.xregs[ARM_VFP_FPSCR] = val & 0xf7c80000;
> + env->vfp.vec_len = (val >> 16) & 7;
> + env->vfp.vec_stride = (val >> 20) & 3;
> + }
I think these two sets of masking are confusing.
Perhaps usefully rearranged as
if (!fp16) {
val &= ~fz16;
}
vfp_set_fpscr_to_host(env, val);
if (!m-profile) {
vec_len = extract32(val, 16, 3);
vec_stride = extract32(val, 20, 2);
}
val &= 0xf7c80000;
if (lob) {
val |= 4 << 16;
}
fpscr = val;
Which then obviates the next patch.
r~