ed5979
From e419493e6ec188461aa6f06c1b1cdc8a698859df Mon Sep 17 00:00:00 2001
ed5979
From: Richard Henderson <richard.henderson@linaro.org>
ed5979
Date: Sat, 14 Jan 2023 15:21:03 -1000
ed5979
Subject: [PATCH 6/8] target/i386: Fix 32-bit AD[CO]X insns in 64-bit mode
ed5979
MIME-Version: 1.0
ed5979
Content-Type: text/plain; charset=UTF-8
ed5979
Content-Transfer-Encoding: 8bit
ed5979
ed5979
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
ed5979
RH-MergeRequest: 154: target/i386: fix bugs in emulation of BMI instructions
ed5979
RH-Bugzilla: 2173590
ed5979
RH-Acked-by: Emanuele Giuseppe Esposito <eesposit@redhat.com>
ed5979
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
ed5979
RH-Acked-by: Bandan Das <None>
ed5979
RH-Commit: [6/7] 0fa4d3858319d4f877a5b3f31776121a72e2c57a (bonzini/rhel-qemu-kvm)
ed5979
ed5979
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2173590
ed5979
Upstream-Status: merged
ed5979
ed5979
Failure to truncate the inputs results in garbage for the carry-out.
ed5979
ed5979
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1373
ed5979
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
ed5979
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
ed5979
Message-Id: <20230115012103.3131796-1-richard.henderson@linaro.org>
ed5979
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
ed5979
(cherry picked from commit 6fbef9426bac7184b5d5887589d8386e732865eb)
ed5979
---
ed5979
 target/i386/tcg/emit.c.inc       |  2 +
ed5979
 tests/tcg/x86_64/Makefile.target |  3 ++
ed5979
 tests/tcg/x86_64/adox.c          | 69 ++++++++++++++++++++++++++++++++
ed5979
 3 files changed, 74 insertions(+)
ed5979
 create mode 100644 tests/tcg/x86_64/adox.c
ed5979
ed5979
diff --git a/target/i386/tcg/emit.c.inc b/target/i386/tcg/emit.c.inc
ed5979
index 0d7c6e80ae..e61ae9a2e9 100644
ed5979
--- a/target/i386/tcg/emit.c.inc
ed5979
+++ b/target/i386/tcg/emit.c.inc
ed5979
@@ -1037,6 +1037,8 @@ static void gen_ADCOX(DisasContext *s, CPUX86State *env, MemOp ot, int cc_op)
ed5979
 #ifdef TARGET_X86_64
ed5979
     case MO_32:
ed5979
         /* If TL is 64-bit just do everything in 64-bit arithmetic.  */
ed5979
+        tcg_gen_ext32u_tl(s->T0, s->T0);
ed5979
+        tcg_gen_ext32u_tl(s->T1, s->T1);
ed5979
         tcg_gen_add_i64(s->T0, s->T0, s->T1);
ed5979
         tcg_gen_add_i64(s->T0, s->T0, carry_in);
ed5979
         tcg_gen_shri_i64(carry_out, s->T0, 32);
ed5979
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
ed5979
index 4eac78293f..e64aab1b81 100644
ed5979
--- a/tests/tcg/x86_64/Makefile.target
ed5979
+++ b/tests/tcg/x86_64/Makefile.target
ed5979
@@ -12,11 +12,14 @@ ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
ed5979
 X86_64_TESTS += vsyscall
ed5979
 X86_64_TESTS += noexec
ed5979
 X86_64_TESTS += cmpxchg
ed5979
+X86_64_TESTS += adox
ed5979
 TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
ed5979
 else
ed5979
 TESTS=$(MULTIARCH_TESTS)
ed5979
 endif
ed5979
 
ed5979
+adox: CFLAGS=-O2
ed5979
+
ed5979
 run-test-i386-ssse3: QEMU_OPTS += -cpu max
ed5979
 run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
ed5979
 
ed5979
diff --git a/tests/tcg/x86_64/adox.c b/tests/tcg/x86_64/adox.c
ed5979
new file mode 100644
ed5979
index 0000000000..36be644c8b
ed5979
--- /dev/null
ed5979
+++ b/tests/tcg/x86_64/adox.c
ed5979
@@ -0,0 +1,69 @@
ed5979
+/* See if ADOX give expected results */
ed5979
+
ed5979
+#include <assert.h>
ed5979
+#include <stdint.h>
ed5979
+#include <stdbool.h>
ed5979
+
ed5979
+static uint64_t adoxq(bool *c_out, uint64_t a, uint64_t b, bool c)
ed5979
+{
ed5979
+    asm ("addl $0x7fffffff, %k1\n\t"
ed5979
+         "adoxq %2, %0\n\t"
ed5979
+         "seto %b1"
ed5979
+         : "+r"(a), "=&r"(c) : "r"(b), "1"((int)c));
ed5979
+    *c_out = c;
ed5979
+    return a;
ed5979
+}
ed5979
+
ed5979
+static uint64_t adoxl(bool *c_out, uint64_t a, uint64_t b, bool c)
ed5979
+{
ed5979
+    asm ("addl $0x7fffffff, %k1\n\t"
ed5979
+         "adoxl %k2, %k0\n\t"
ed5979
+         "seto %b1"
ed5979
+         : "+r"(a), "=&r"(c) : "r"(b), "1"((int)c));
ed5979
+    *c_out = c;
ed5979
+    return a;
ed5979
+}
ed5979
+
ed5979
+int main()
ed5979
+{
ed5979
+    uint64_t r;
ed5979
+    bool c;
ed5979
+
ed5979
+    r = adoxq(&c, 0, 0, 0);
ed5979
+    assert(r == 0);
ed5979
+    assert(c == 0);
ed5979
+
ed5979
+    r = adoxl(&c, 0, 0, 0);
ed5979
+    assert(r == 0);
ed5979
+    assert(c == 0);
ed5979
+
ed5979
+    r = adoxl(&c, 0x100000000, 0, 0);
ed5979
+    assert(r == 0);
ed5979
+    assert(c == 0);
ed5979
+
ed5979
+    r = adoxq(&c, 0, 0, 1);
ed5979
+    assert(r == 1);
ed5979
+    assert(c == 0);
ed5979
+
ed5979
+    r = adoxl(&c, 0, 0, 1);
ed5979
+    assert(r == 1);
ed5979
+    assert(c == 0);
ed5979
+
ed5979
+    r = adoxq(&c, -1, -1, 0);
ed5979
+    assert(r == -2);
ed5979
+    assert(c == 1);
ed5979
+
ed5979
+    r = adoxl(&c, -1, -1, 0);
ed5979
+    assert(r == 0xfffffffe);
ed5979
+    assert(c == 1);
ed5979
+
ed5979
+    r = adoxq(&c, -1, -1, 1);
ed5979
+    assert(r == -1);
ed5979
+    assert(c == 1);
ed5979
+
ed5979
+    r = adoxl(&c, -1, -1, 1);
ed5979
+    assert(r == 0xffffffff);
ed5979
+    assert(c == 1);
ed5979
+
ed5979
+    return 0;
ed5979
+}
ed5979
-- 
ed5979
2.39.1
ed5979