From: Richard Henderson <[email protected]>
Reviewed-by: Jim MacArthur <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
(cherry picked from commit 4278a7ba36c2f7f5297c8ed886646a4a453f555c)
(Mjt: adjust across make=>meson conversion in tcg tests)
Signed-off-by: Michael Tokarev <[email protected]>
diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target
index 613bbf0939a..51a3ed76a87 100644
--- a/tests/tcg/arm/Makefile.target
+++ b/tests/tcg/arm/Makefile.target
@@ -32,6 +32,8 @@ run-fcvt: fcvt
ARM_TESTS += pcalign-a32
pcalign-a32: CFLAGS+=-marm
+ARM_TESTS += issue4448
+
ifeq ($(CONFIG_ARM_COMPATIBLE_SEMIHOSTING),y)
# Semihosting smoke test for linux-user
diff --git a/tests/tcg/arm/issue4448.c b/tests/tcg/arm/issue4448.c
new file mode 100644
index 00000000000..0a498373a89
--- /dev/null
+++ b/tests/tcg/arm/issue4448.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <assert.h>
+#include <stdint.h>
+
+/* Signed 64-bit product, constant operand first then second. */
+#define SMULL_CONST_LHS(k, x, lo, hi) \
+ __asm__("mov r0, #" #k "\n\tsmull %0, %1, r0, %2" \
+ : "=&r"(lo), "=&r"(hi) : "r"(x) : "r0", "cc")
+
+#define SMULL_CONST_RHS(k, x, lo, hi) \
+ __asm__("mov r0, #" #k "\n\tsmull %0, %1, %2, r0" \
+ : "=&r"(lo), "=&r"(hi) : "r"(x) : "r0", "cc")
+
+/* Unsigned 64-bit product, for contrast: this one is folded correctly. */
+#define UMULL_CONST_LHS(k, x, lo, hi) \
+ __asm__("mov r0, #" #k "\n\tumull %0, %1, r0, %2" \
+ : "=&r"(lo), "=&r"(hi) : "r"(x) : "r0", "cc")
+
+static int64_t s64(int32_t hi, int32_t lo)
+{
+ return ((int64_t)hi << 32) | (uint32_t)lo;
+}
+
+static uint64_t u64(int32_t hi, int32_t lo)
+{
+ return ((uint64_t)(uint32_t)hi << 32) | (uint32_t)lo;
+}
+
+int main(void)
+{
+ static const int32_t values[] = { 1961612, -1479053948, -7, 0 };
+
+ for (unsigned i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
+ int32_t x = values[i];
+ int32_t lo, hi;
+
+ SMULL_CONST_LHS(1, x, lo, hi);
+ assert(x == s64(hi, lo));
+
+ SMULL_CONST_RHS(1, x, lo, hi);
+ assert(x == s64(hi, lo));
+
+ UMULL_CONST_LHS(1, x, lo, hi);
+ assert((uint32_t)x == u64(hi, lo));
+
+ SMULL_CONST_LHS(0, x, lo, hi);
+ assert(0 == u64(hi, lo));
+ }
+ return 0;
+}
--
2.47.3