valid-slots: packets that legally share a slot and were wrongly
rejected before the fix (load and transfer, load encoded first;
dczeroa packed last with three transfers).

invalid-slots: unassignable packets that must still be rejected:
store + duplex, load + indirect jump, three logical ops competing for
slots 2 and 3, and five ops for four slots.

Signed-off-by: Brian Cain <[email protected]>
---
 tests/tcg/hexagon/Makefile.target |  1 +
 tests/tcg/hexagon/invalid-slots.c | 72 +++++++++++++++++++++++++++++++
 tests/tcg/hexagon/valid-slots.c   | 62 ++++++++++++++++++++++++++
 3 files changed, 135 insertions(+)
 create mode 100644 tests/tcg/hexagon/valid-slots.c

diff --git a/tests/tcg/hexagon/Makefile.target 
b/tests/tcg/hexagon/Makefile.target
index a2a0ffc69b2..80e56f7d055 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -51,6 +51,7 @@ HEX_TESTS += scatter_gather
 HEX_TESTS += hvx_misc
 HEX_TESTS += hvx_histogram
 HEX_TESTS += invalid-slots
+HEX_TESTS += valid-slots
 HEX_TESTS += invalid-encoding
 HEX_TESTS += multiple-writes
 HEX_TESTS += unaligned_pc
diff --git a/tests/tcg/hexagon/invalid-slots.c 
b/tests/tcg/hexagon/invalid-slots.c
index 607027f314d..f2dace2e541 100644
--- a/tests/tcg/hexagon/invalid-slots.c
+++ b/tests/tcg/hexagon/invalid-slots.c
@@ -55,6 +55,75 @@ static int test_invalid_slots(void)
     return sig;
 }
 
+/* Load then indirect jump, load encoded first: no high slot left for jump. */
+static int test_invalid_slots_highslot(void)
+{
+    int sig;
+
+    asm volatile(
+        "r0 = #0\n"
+        "r1 = ##1f\n"
+        "memw(%1) = r1\n"
+        "r3 = #mem\n"
+        ".word 0x91834006\n" /* { r6 = memw(r3+#0); */
+        ".word 0x529fc000\n" /*   jumpr r31 }        */
+        "1:\n"
+        "%0 = r0\n"
+        : "=r"(sig)
+        : "r"(&resume_pc)
+        : "r0", "r1", "r3", "r6", "memory");
+
+    return sig;
+}
+
+/*
+ * Three predicate-logical ops: each is restricted to slots 2 and 3, so the
+ * fourth-and-fifth-slot-free packet still has only two slots for three ops.
+ * No change-of-flow is involved, so the only reason to reject it is the slot
+ * conflict.
+ */
+static int test_invalid_slots_crslot23(void)
+{
+    int sig;
+
+    asm volatile(
+        "r0 = #0\n"
+        "r1 = ##1f\n"
+        "memw(%1) = r1\n"
+        ".word 0x6b024100\n" /* { p0 = and(p1, p2); */
+        ".word 0x6b224103\n" /*   p3 = or(p1, p2);   */
+        ".word 0x6b42c301\n" /*   p1 = xor(p2, p3) } */
+        "1:\n"
+        "%0 = r0\n"
+        : "=r"(sig)
+        : "r"(&resume_pc)
+        : "r0", "r1", "p0", "p1", "p3", "memory");
+
+    return sig;
+}
+
+/* Three transfers plus a duplex: five ops for four slots. */
+static int test_invalid_slots_five(void)
+{
+    int sig;
+
+    asm volatile(
+        "r0 = #0\n"
+        "r1 = ##1f\n"
+        "memw(%1) = r1\n"
+        ".word 0x78004020\n" /* { r0 = #1;           */
+        ".word 0x78004041\n" /*   r1 = #2;            */
+        ".word 0x78004062\n" /*   r2 = #3;            */
+        ".word 0x28452856\n" /*   r5 = #4; r6 = #5 }  */
+        "1:\n"
+        "%0 = r0\n"
+        : "=r"(sig)
+        : "r"(&resume_pc)
+        : "r0", "r1", "r2", "r5", "r6", "memory");
+
+    return sig;
+}
+
 int main()
 {
     struct sigaction act;
@@ -65,6 +134,9 @@ int main()
     assert(sigaction(SIGILL, &act, NULL) == 0);
 
     assert(test_invalid_slots() == SIGILL);
+    assert(test_invalid_slots_highslot() == SIGILL);
+    assert(test_invalid_slots_crslot23() == SIGILL);
+    assert(test_invalid_slots_five() == SIGILL);
 
     puts("PASS");
     return EXIT_SUCCESS;
diff --git a/tests/tcg/hexagon/valid-slots.c b/tests/tcg/hexagon/valid-slots.c
new file mode 100644
index 00000000000..70d9b0b6acf
--- /dev/null
+++ b/tests/tcg/hexagon/valid-slots.c
@@ -0,0 +1,62 @@
+/*
+ * Regression tests for valid packets that qemu incorrectly rejected as
+ * invalid.
+ *
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+int err;
+
+#include "hex_test.h"
+
+/* volatile to keep the load from being optimized away */
+static volatile int buf[2] = { 0x1234, 0 };
+
+/* Load and register transfer in one packet, load encoded first. */
+static int32_t load_imm_pair(void)
+{
+    int32_t out;
+    /* { r6 = memw(r3+#-4); r7 = #0x4ae6 } */
+    asm volatile(
+        "{ r3 = %1 }\n\t"
+        ".word 0x97837fe6\n\t"
+        ".word 0x7845dcc7\n\t"
+        "{ %0 = r6 }\n\t"
+        : "=r"(out) : "r"(&buf[1]) : "r3", "r6", "r7");
+    return out;
+}
+
+static int32_t dcbuf[8] __attribute__((aligned(32)));
+
+/* Slot-0-only op (dczeroa) packed last with three transfers. */
+static void slot0_restricted(int32_t *out)
+{
+    asm volatile(
+        "{ %0 = #0x11\n\t"
+        "  %1 = #0x22\n\t"
+        "  %2 = #0x33\n\t"
+        "  dczeroa(%3) }\n\t"
+        : "=r"(out[0]), "=r"(out[1]), "=r"(out[2])
+        : "r"(dcbuf) : "memory");
+}
+
+int main()
+{
+    int32_t r[3];
+
+    check32(load_imm_pair(), 0x1234);
+
+    dcbuf[0] = 0x5a5a5a5a;
+    slot0_restricted(r);
+    check32(r[0], 0x11);
+    check32(r[1], 0x22);
+    check32(r[2], 0x33);
+    check32(dcbuf[0], 0);       /* dczeroa cleared the line */
+
+    puts(err ? "FAIL" : "PASS");
+    return err;
+}
-- 
2.34.1


Reply via email to