target/arm: Introduce sve_vqm1_for_el_sm

When Streaming SVE mode is enabled, the size is taken from
SMCR_ELx instead of ZCR_ELx.  The format is shared, but the
set of vector lengths is not.  Further, Streaming SVE does
not require any particular length to be supported.

Adjust sve_vqm1_for_el to pass the current value of PSTATE.SM
to the new function.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220620175235.60881-19-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-06-20 10:52:02 -07:00 committed by Peter Maydell
parent e74c097638
commit 6ca54aa9a8
2 changed files with 32 additions and 9 deletions

View File

@ -1154,13 +1154,18 @@ int sve_exception_el(CPUARMState *env, int cur_el);
int sme_exception_el(CPUARMState *env, int cur_el); int sme_exception_el(CPUARMState *env, int cur_el);
/** /**
* sve_vqm1_for_el: * sve_vqm1_for_el_sm:
* @env: CPUARMState * @env: CPUARMState
* @el: exception level * @el: exception level
* @sm: streaming mode
* *
* Compute the current SVE vector length for @el, in units of * Compute the current vector length for @el & @sm, in units of
* Quadwords Minus 1 -- the same scale used for ZCR_ELx.LEN. * Quadwords Minus 1 -- the same scale used for ZCR_ELx.LEN.
* If @sm, compute for SVL, otherwise NVL.
*/ */
uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm);
/* Likewise, but using @sm = PSTATE.SM. */
uint32_t sve_vqm1_for_el(CPUARMState *env, int el); uint32_t sve_vqm1_for_el(CPUARMState *env, int el);
static inline bool is_a64(CPUARMState *env) static inline bool is_a64(CPUARMState *env)

View File

@ -6272,23 +6272,41 @@ int sme_exception_el(CPUARMState *env, int el)
/* /*
* Given that SVE is enabled, return the vector length for EL. * Given that SVE is enabled, return the vector length for EL.
*/ */
uint32_t sve_vqm1_for_el(CPUARMState *env, int el) uint32_t sve_vqm1_for_el_sm(CPUARMState *env, int el, bool sm)
{ {
ARMCPU *cpu = env_archcpu(env); ARMCPU *cpu = env_archcpu(env);
uint32_t len = cpu->sve_max_vq - 1; uint64_t *cr = env->vfp.zcr_el;
uint32_t map = cpu->sve_vq.map;
uint32_t len = ARM_MAX_VQ - 1;
if (sm) {
cr = env->vfp.smcr_el;
map = cpu->sme_vq.map;
}
if (el <= 1 && !el_is_in_host(env, el)) { if (el <= 1 && !el_is_in_host(env, el)) {
len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[1]); len = MIN(len, 0xf & (uint32_t)cr[1]);
} }
if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) { if (el <= 2 && arm_feature(env, ARM_FEATURE_EL2)) {
len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[2]); len = MIN(len, 0xf & (uint32_t)cr[2]);
} }
if (arm_feature(env, ARM_FEATURE_EL3)) { if (arm_feature(env, ARM_FEATURE_EL3)) {
len = MIN(len, 0xf & (uint32_t)env->vfp.zcr_el[3]); len = MIN(len, 0xf & (uint32_t)cr[3]);
} }
len = 31 - clz32(cpu->sve_vq.map & MAKE_64BIT_MASK(0, len + 1)); map &= MAKE_64BIT_MASK(0, len + 1);
return len; if (map != 0) {
return 31 - clz32(map);
}
/* Bit 0 is always set for Normal SVE -- not so for Streaming SVE. */
assert(sm);
return ctz32(cpu->sme_vq.map);
}
uint32_t sve_vqm1_for_el(CPUARMState *env, int el)
{
return sve_vqm1_for_el_sm(env, el, FIELD_EX64(env->svcr, SVCR, SM));
} }
static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri,