summary refs log tree commit diff stats
path: root/target/arm/helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2019-11-19 13:20:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2019-11-19 13:20:27 +0000
commit6e553f2a1b8450c9e9721fb60e3ef134492a4a39 (patch)
tree67488bf8631a2493fd3a53f631d0bf2e5d477c83 /target/arm/helper.c
parent83ad95957c7e66f2685fb38c9675949d3bf478eb (diff)
downloadfocaccia-qemu-6e553f2a1b8450c9e9721fb60e3ef134492a4a39.tar.gz
focaccia-qemu-6e553f2a1b8450c9e9721fb60e3ef134492a4a39.zip
target/arm: Merge arm_cpu_vq_map_next_smaller into sole caller
Coverity reports, in sve_zcr_get_valid_len,

"Subtract operation overflows on operands
arm_cpu_vq_map_next_smaller(cpu, start_vq + 1U) and 1U"

First, the aarch32 stub version of arm_cpu_vq_map_next_smaller,
returning 0, does exactly what Coverity reports.  Remove it.

Second, the aarch64 version of arm_cpu_vq_map_next_smaller has
a set of asserts, but they don't cover the case in question.
Further, there is a fair amount of extra arithmetic needed to
convert from the 0-based zcr register, to the 1-base vq form,
to the 0-based bitmap, and back again.  This can be simplified
by leaving the value in the 0-based form.

Finally, use test_bit to simplify the common case, where the
length in the zcr registers is in fact a supported length.

Reported-by: Coverity (CID 1407217)
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Message-id: 20191118091414.19440-1-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r--target/arm/helper.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c
index be67e2c66d..a089fb5a69 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -5363,9 +5363,14 @@ int sve_exception_el(CPUARMState *env, int el)
 
 static uint32_t sve_zcr_get_valid_len(ARMCPU *cpu, uint32_t start_len)
 {
-    uint32_t start_vq = (start_len & 0xf) + 1;
+    uint32_t end_len;
 
-    return arm_cpu_vq_map_next_smaller(cpu, start_vq + 1) - 1;
+    end_len = start_len &= 0xf;
+    if (!test_bit(start_len, cpu->sve_vq_map)) {
+        end_len = find_last_bit(cpu->sve_vq_map, start_len);
+        assert(end_len < start_len);
+    }
+    return end_len;
 }
 
 /*