aboutsummaryrefslogtreecommitdiff
path: root/module-common.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-07-22 18:29:55 +0100
committerPeter Maydell <peter.maydell@linaro.org>2024-07-29 16:56:46 +0100
commitea3f5a90f036734522e9af3bffd77e69e9f47355 (patch)
treed923744fd93d1abf8703776a79dfc175902e2e79 /module-common.c
parent56f1c0db928aae0b83fd91c89ddb226b137e2b21 (diff)
downloadqemu-ea3f5a90f036734522e9af3bffd77e69e9f47355.zip
qemu-ea3f5a90f036734522e9af3bffd77e69e9f47355.tar.gz
qemu-ea3f5a90f036734522e9af3bffd77e69e9f47355.tar.bz2
target/arm: Fix UMOPA/UMOPS of 16-bit values
The UMOPA/UMOPS instructions are supposed to multiply unsigned 8 or 16 bit elements and accumulate the products into a 64-bit element. In the Arm ARM pseudocode, this is done with the usual infinite-precision signed arithmetic. However our implementation doesn't quite get it right, because in the DEF_IMOP_64() macro we do: sum += (NTYPE)(n >> 0) * (MTYPE)(m >> 0); where NTYPE and MTYPE are uint16_t or int16_t. In the uint16_t case, the C usual arithmetic conversions mean the values are converted to "int" type and the multiply is done as a 32-bit multiply. This means that if the inputs are, for example, 0xffff and 0xffff then the result is 0xFFFE0001 as an int, which is then promoted to uint64_t for the accumulation into sum; this promotion incorrectly sign extends the multiply. Avoid the incorrect sign extension by casting to int64_t before the multiply, so we do the multiply as 64-bit signed arithmetic, which is a type large enough that the multiply can never overflow into the sign bit. (The equivalent 8-bit operations in DEF_IMOP_32() are fine, because the 8-bit multiplies can never overflow into the sign bit of a 32-bit integer.) Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2372 Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20240722172957.1041231-3-peter.maydell@linaro.org
Diffstat (limited to 'module-common.c')
0 files changed, 0 insertions, 0 deletions