diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2018-03-09 17:09:43 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-09 17:09:43 +0000 |
commit | 85fc716732bc6e85a634335847999f411269f282 (patch) | |
tree | 15ae6a9a0e2d85baa27d03c67af20b749fd9be6c /target/arm | |
parent | 843361ed04017da5f15c3b7a98b2e8849e39a984 (diff) |
linux-user: Implement aarch64 PR_SVE_SET/GET_VL
As an implementation choice, widening VL has zeroed the
previously inaccessible portion of the sve registers.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Acked-by: Alex Bennée <alex.bennee@linaro.org>
Message-id: 20180303143823.27055-2-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/cpu.h | 1 | ||||
-rw-r--r-- | target/arm/cpu64.c | 41 |
2 files changed, 42 insertions, 0 deletions
diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 3fa8fdad21..36711cdb50 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -866,6 +866,7 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, #ifdef TARGET_AARCH64 int aarch64_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); int aarch64_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); +void aarch64_sve_narrow_vq(CPUARMState *env, unsigned vq); #endif target_ulong do_arm_semihosting(CPUARMState *env); diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index dd9ba973f7..f12a485820 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -368,3 +368,44 @@ 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); + + /* 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; + } +} |