summaryrefslogtreecommitdiffstats
path: root/migration/multifd.c
diff options
context:
space:
mode:
authorPeter Maydell2020-10-09 16:47:12 +0200
committerPeter Maydell2020-10-20 17:12:00 +0200
commit5288145d716338ace0f83e3ff05c4d07715bb4f4 (patch)
treef526149591e4c8b64c76778225df14c8cbc2109f /migration/multifd.c
parentMerge remote-tracking branch 'remotes/aperard/tags/pull-xen-20201020' into st... (diff)
downloadqemu-5288145d716338ace0f83e3ff05c4d07715bb4f4.tar.gz
qemu-5288145d716338ace0f83e3ff05c4d07715bb4f4.tar.xz
qemu-5288145d716338ace0f83e3ff05c4d07715bb4f4.zip
target/arm: Fix SMLAD incorrect setting of Q bit
The SMLAD instruction is supposed to: * signed multiply Rn[15:0] * Rm[15:0] * signed multiply Rn[31:16] * Rm[31:16] * perform a signed addition of the products and Ra * set Rd to the low 32 bits of the theoretical infinite-precision result * set the Q flag if the sign-extension of Rd would differ from the infinite-precision result (ie on overflow) Our current implementation doesn't quite do this, though: it performs an addition of the products setting Q on overflow, and then it adds Ra, again possibly setting Q. This sometimes incorrectly sets Q when the architecturally mandated only-check-for-overflow-once algorithm does not. For instance: r1 = 0x80008000; r2 = 0x80008000; r3 = 0xffffffff smlad r0, r1, r2, r3 This is (-32768 * -32768) + (-32768 * -32768) - 1 The products are both 0x4000_0000, so when added together as 32-bit signed numbers they overflow (and QEMU sets Q), but because the addition of Ra == -1 brings the total back down to 0x7fff_ffff there is no overflow for the complete operation and setting Q is incorrect. Fix this edge case by resorting to 64-bit arithmetic for the case where we need to add three values together. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20201009144712.11187-1-peter.maydell@linaro.org
Diffstat (limited to 'migration/multifd.c')
0 files changed, 0 insertions, 0 deletions