target/i386: Fix 32-bit AD[CO]X insns in 64-bit mode
Failure to truncate the inputs results in garbage for the carry-out. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1373 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-Id: <20230115012103.3131796-1-richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
003ba52a8b
commit
6fbef9426b
@ -1037,6 +1037,8 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
|
|||||||
#ifdef TARGET_X86_64
|
#ifdef TARGET_X86_64
|
||||||
case MO_32:
|
case MO_32:
|
||||||
/* If TL is 64-bit just do everything in 64-bit arithmetic. */
|
/* If TL is 64-bit just do everything in 64-bit arithmetic. */
|
||||||
|
tcg_gen_ext32u_tl(s->T0, s->T0);
|
||||||
|
tcg_gen_ext32u_tl(s->T1, s->T1);
|
||||||
tcg_gen_add_i64(s->T0, s->T0, s->T1);
|
tcg_gen_add_i64(s->T0, s->T0, s->T1);
|
||||||
tcg_gen_add_i64(s->T0, s->T0, carry_in);
|
tcg_gen_add_i64(s->T0, s->T0, carry_in);
|
||||||
tcg_gen_shri_i64(carry_out, s->T0, 32);
|
tcg_gen_shri_i64(carry_out, s->T0, 32);
|
||||||
|
@ -12,11 +12,14 @@ ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
|
|||||||
X86_64_TESTS += vsyscall
|
X86_64_TESTS += vsyscall
|
||||||
X86_64_TESTS += noexec
|
X86_64_TESTS += noexec
|
||||||
X86_64_TESTS += cmpxchg
|
X86_64_TESTS += cmpxchg
|
||||||
|
X86_64_TESTS += adox
|
||||||
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
|
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
|
||||||
else
|
else
|
||||||
TESTS=$(MULTIARCH_TESTS)
|
TESTS=$(MULTIARCH_TESTS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
adox: CFLAGS=-O2
|
||||||
|
|
||||||
run-test-i386-ssse3: QEMU_OPTS += -cpu max
|
run-test-i386-ssse3: QEMU_OPTS += -cpu max
|
||||||
run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
|
run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
|
||||||
|
|
||||||
|
69
tests/tcg/x86_64/adox.c
Normal file
69
tests/tcg/x86_64/adox.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* See if ADOX give expected results */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static uint64_t adoxq(bool *c_out, uint64_t a, uint64_t b, bool c)
|
||||||
|
{
|
||||||
|
asm ("addl $0x7fffffff, %k1\n\t"
|
||||||
|
"adoxq %2, %0\n\t"
|
||||||
|
"seto %b1"
|
||||||
|
: "+r"(a), "=&r"(c) : "r"(b), "1"((int)c));
|
||||||
|
*c_out = c;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t adoxl(bool *c_out, uint64_t a, uint64_t b, bool c)
|
||||||
|
{
|
||||||
|
asm ("addl $0x7fffffff, %k1\n\t"
|
||||||
|
"adoxl %k2, %k0\n\t"
|
||||||
|
"seto %b1"
|
||||||
|
: "+r"(a), "=&r"(c) : "r"(b), "1"((int)c));
|
||||||
|
*c_out = c;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
uint64_t r;
|
||||||
|
bool c;
|
||||||
|
|
||||||
|
r = adoxq(&c, 0, 0, 0);
|
||||||
|
assert(r == 0);
|
||||||
|
assert(c == 0);
|
||||||
|
|
||||||
|
r = adoxl(&c, 0, 0, 0);
|
||||||
|
assert(r == 0);
|
||||||
|
assert(c == 0);
|
||||||
|
|
||||||
|
r = adoxl(&c, 0x100000000, 0, 0);
|
||||||
|
assert(r == 0);
|
||||||
|
assert(c == 0);
|
||||||
|
|
||||||
|
r = adoxq(&c, 0, 0, 1);
|
||||||
|
assert(r == 1);
|
||||||
|
assert(c == 0);
|
||||||
|
|
||||||
|
r = adoxl(&c, 0, 0, 1);
|
||||||
|
assert(r == 1);
|
||||||
|
assert(c == 0);
|
||||||
|
|
||||||
|
r = adoxq(&c, -1, -1, 0);
|
||||||
|
assert(r == -2);
|
||||||
|
assert(c == 1);
|
||||||
|
|
||||||
|
r = adoxl(&c, -1, -1, 0);
|
||||||
|
assert(r == 0xfffffffe);
|
||||||
|
assert(c == 1);
|
||||||
|
|
||||||
|
r = adoxq(&c, -1, -1, 1);
|
||||||
|
assert(r == -1);
|
||||||
|
assert(c == 1);
|
||||||
|
|
||||||
|
r = adoxl(&c, -1, -1, 1);
|
||||||
|
assert(r == 0xffffffff);
|
||||||
|
assert(c == 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user