mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
target/arm: Handle SVE vector length changes in system mode
SVE vector length can change when changing EL, or when writing to one of the ZCR_ELn registers. For correctness, our implementation requires that predicate bits that are inaccessible are never set. Which means noticing length changes and zeroing the appropriate register bits. Tested-by: Laurent Desnogues <laurent.desnogues@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20181005175350.30752-5-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
2de7ace292
commit
0ab5953b00
4 changed files with 125 additions and 55 deletions
|
@ -410,45 +410,3 @@ static void aarch64_cpu_register_types(void)
|
|||
}
|
||||
|
||||
type_init(aarch64_cpu_register_types)
|
||||
|
||||
/* The manual says that when SVE is enabled and VQ is widened the
|
||||
* implementation is allowed to zero the previously inaccessible
|
||||
* portion of the registers. The corollary to that is that when
|
||||
* SVE is enabled and VQ is narrowed we are also allowed to zero
|
||||
* the now inaccessible portion of the registers.
|
||||
*
|
||||
* The intent of this is that no predicate bit beyond VQ is ever set.
|
||||
* Which means that some operations on predicate registers themselves
|
||||
* may operate on full uint64_t or even unrolled across the maximum
|
||||
* uint64_t[4]. Performing 4 bits of host arithmetic unconditionally
|
||||
* may well be cheaper than conditionals to restrict the operation
|
||||
* to the relevant portion of a uint16_t[16].
|
||||
*
|
||||
* TODO: Need to call this for changes to the real system registers
|
||||
* and EL state changes.
|
||||
*/
|
||||
void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq)
|
||||
{
|
||||
int i, j;
|
||||
uint64_t pmask;
|
||||
|
||||
assert(vq >= 1 && vq <= ARM_MAX_VQ);
|
||||
assert(vq <= arm_env_get_cpu(env)->sve_max_vq);
|
||||
|
||||
/* Zap the high bits of the zregs. */
|
||||
for (i = 0; i < 32; i++) {
|
||||
memset(&env->vfp.zregs[i].d[2 * vq], 0, 16 * (ARM_MAX_VQ - vq));
|
||||
}
|
||||
|
||||
/* Zap the high bits of the pregs and ffr. */
|
||||
pmask = 0;
|
||||
if (vq & 3) {
|
||||
pmask = ~(-1ULL << (16 * (vq & 3)));
|
||||
}
|
||||
for (j = vq / 4; j < ARM_MAX_VQ / 4; j++) {
|
||||
for (i = 0; i < 17; ++i) {
|
||||
env->vfp.pregs[i].p[j] &= pmask;
|
||||
}
|
||||
pmask = 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue