target/i386: fix cmpxchg with 32-bit register destination
commitd1bb978ba1654ddc6e927621b554eebb216fb9dd
authorPaolo Bonzini <pbonzini@redhat.com>
Sun, 11 Sep 2022 12:04:36 +0000 (11 14:04 +0200)
committerRichard Henderson <richard.henderson@linaro.org>
Mon, 14 Nov 2022 23:34:42 +0000 (15 09:34 +1000)
tree90ee84e4dde9310b4175200161b9db54a8bacdde
parent98f10f0e2613ba1ac2ad3f57a5174014f6dcb03d
target/i386: fix cmpxchg with 32-bit register destination

Unlike the memory case, where "the destination operand receives a write
cycle without regard to the result of the comparison", rm must not be
touched altogether if the write fails, including not zero-extending
it on 64-bit processors.  This is not how the movcond currently works,
because it is always followed by a gen_op_mov_reg_v to rm.

To fix it, introduce a new function that is similar to gen_op_mov_reg_v
but writes to a TCG temporary.

Considering that gen_extu(ot, oldv) is not needed in the memory case
either, the two cases for register and memory destinations are different
enough that one might as well fuse the two "if (mod == 3)" into one.
So do that too.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/508
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[rth: Add a test case ]
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
target/i386/tcg/translate.c
tests/tcg/x86_64/Makefile.target
tests/tcg/x86_64/cmpxchg.c [new file with mode: 0644]