diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 186ee621a6..07492e9f9a 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -255,6 +255,15 @@ static void arm_cpu_reset(DeviceState *dev) uint8_t *rom; uint32_t vecbase; + if (cpu_isar_feature(aa32_lob, cpu)) { + /* + * LTPSIZE is constant 4 if MVE not implemented, and resets + * to an UNKNOWN value if MVE is implemented. We choose to + * always reset to 4. + */ + env->v7m.ltpsize = 4; + } + if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { env->v7m.secure = true; } else { diff --git a/target/arm/cpu.h b/target/arm/cpu.h index a432f301f1..49cd5cabcf 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -549,6 +549,7 @@ typedef struct CPUARMState { uint32_t fpdscr[M_REG_NUM_BANKS]; uint32_t cpacr[M_REG_NUM_BANKS]; uint32_t nsacr; + int ltpsize; } v7m; /* Information associated with an exception about to be taken: diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 364856498c..01b9d8557f 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -174,6 +174,12 @@ uint32_t HELPER(vfp_get_fpscr)(CPUARMState *env) | (env->vfp.vec_len << 16) | (env->vfp.vec_stride << 20); + /* + * M-profile LTPSIZE overlaps A-profile Stride; whichever of the + * two is not applicable to this CPU will always be zero. + */ + fpscr |= env->v7m.ltpsize << 16; + fpscr |= vfp_get_fpscr_from_host(env); i = env->vfp.qc[0] | env->vfp.qc[1] | env->vfp.qc[2] | env->vfp.qc[3];