@samitouri / QOSamiQemu / commits / d2504d4cea

tests/tcg/hexagon: add slot-assignment tests

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. Reviewed-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>

Brian Cain committed Jul 24, 2026 at 10:18 UTC d2504d4cea329dcec69af4d590cbaa490c409724
3 files changed +135
tests/tcg/hexagon/Makefile.target
+1
@@ -51,6 +51,7 @@ HEX_TESTS += scatter_gather
51 HEX_TESTS += hvx_misc
52 HEX_TESTS += hvx_histogram
53 HEX_TESTS += invalid-slots
54 +HEX_TESTS += valid-slots
55 HEX_TESTS += invalid-encoding
56 HEX_TESTS += multiple-writes
57 HEX_TESTS += unaligned_pc
tests/tcg/hexagon/invalid-slots.c
+72
@@ -55,6 +55,75 @@ static int test_invalid_slots(void)
55 return sig;
56 }
57
58 +/* Load then indirect jump, load encoded first: no high slot left for jump. */
59 +static int test_invalid_slots_highslot(void)
60 +{
61 + int sig;
62 +
63 + asm volatile(
64 + "r0 = #0\n"
65 + "r1 = ##1f\n"
66 + "memw(%1) = r1\n"
67 + "r3 = #mem\n"
68 + ".word 0x91834006\n" /* { r6 = memw(r3+#0); */
69 + ".word 0x529fc000\n" /* jumpr r31 } */
70 + "1:\n"
71 + "%0 = r0\n"
72 + : "=r"(sig)
73 + : "r"(&resume_pc)
74 + : "r0", "r1", "r3", "r6", "memory");
75 +
76 + return sig;
77 +}
78 +
79 +/*
80 + * Three predicate-logical ops: each is restricted to slots 2 and 3, so the
81 + * fourth-and-fifth-slot-free packet still has only two slots for three ops.
82 + * No change-of-flow is involved, so the only reason to reject it is the slot
83 + * conflict.
84 + */
85 +static int test_invalid_slots_crslot23(void)
86 +{
87 + int sig;
88 +
89 + asm volatile(
90 + "r0 = #0\n"
91 + "r1 = ##1f\n"
92 + "memw(%1) = r1\n"
93 + ".word 0x6b024100\n" /* { p0 = and(p1, p2); */
94 + ".word 0x6b224103\n" /* p3 = or(p1, p2); */
95 + ".word 0x6b42c301\n" /* p1 = xor(p2, p3) } */
96 + "1:\n"
97 + "%0 = r0\n"
98 + : "=r"(sig)
99 + : "r"(&resume_pc)
100 + : "r0", "r1", "p0", "p1", "p3", "memory");
101 +
102 + return sig;
103 +}
104 +
105 +/* Three transfers plus a duplex: five ops for four slots. */
106 +static int test_invalid_slots_five(void)
107 +{
108 + int sig;
109 +
110 + asm volatile(
111 + "r0 = #0\n"
112 + "r1 = ##1f\n"
113 + "memw(%1) = r1\n"
114 + ".word 0x78004020\n" /* { r0 = #1; */
115 + ".word 0x78004041\n" /* r1 = #2; */
116 + ".word 0x78004062\n" /* r2 = #3; */
117 + ".word 0x28452856\n" /* r5 = #4; r6 = #5 } */
118 + "1:\n"
119 + "%0 = r0\n"
120 + : "=r"(sig)
121 + : "r"(&resume_pc)
122 + : "r0", "r1", "r2", "r5", "r6", "memory");
123 +
124 + return sig;
125 +}
126 +
127 int main()
128 {
129 struct sigaction act;
@@ -65,6 +134,9 @@ int main()
134 assert(sigaction(SIGILL, &act, NULL) == 0);
135
136 assert(test_invalid_slots() == SIGILL);
137 + assert(test_invalid_slots_highslot() == SIGILL);
138 + assert(test_invalid_slots_crslot23() == SIGILL);
139 + assert(test_invalid_slots_five() == SIGILL);
140
141 puts("PASS");
142 return EXIT_SUCCESS;
tests/tcg/hexagon/valid-slots.c new
+62
@@ -0,0 +1,62 @@
1 +/*
2 + * Regression tests for valid packets that qemu incorrectly rejected as
3 + * invalid.
4 + *
5 + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
6 + * SPDX-License-Identifier: GPL-2.0-or-later
7 + */
8 +
9 +#include <stdio.h>
10 +#include <stdint.h>
11 +
12 +int err;
13 +
14 +#include "hex_test.h"
15 +
16 +/* volatile to keep the load from being optimized away */
17 +static volatile int buf[2] = { 0x1234, 0 };
18 +
19 +/* Load and register transfer in one packet, load encoded first. */
20 +static int32_t load_imm_pair(void)
21 +{
22 + int32_t out;
23 + /* { r6 = memw(r3+#-4); r7 = #0x4ae6 } */
24 + asm volatile(
25 + "{ r3 = %1 }\n\t"
26 + ".word 0x97837fe6\n\t"
27 + ".word 0x7845dcc7\n\t"
28 + "{ %0 = r6 }\n\t"
29 + : "=r"(out) : "r"(&buf[1]) : "r3", "r6", "r7");
30 + return out;
31 +}
32 +
33 +static int32_t dcbuf[8] __attribute__((aligned(32)));
34 +
35 +/* Slot-0-only op (dczeroa) packed last with three transfers. */
36 +static void slot0_restricted(int32_t *out)
37 +{
38 + asm volatile(
39 + "{ %0 = #0x11\n\t"
40 + " %1 = #0x22\n\t"
41 + " %2 = #0x33\n\t"
42 + " dczeroa(%3) }\n\t"
43 + : "=r"(out[0]), "=r"(out[1]), "=r"(out[2])
44 + : "r"(dcbuf) : "memory");
45 +}
46 +
47 +int main()
48 +{
49 + int32_t r[3];
50 +
51 + check32(load_imm_pair(), 0x1234);
52 +
53 + dcbuf[0] = 0x5a5a5a5a;
54 + slot0_restricted(r);
55 + check32(r[0], 0x11);
56 + check32(r[1], 0x22);
57 + check32(r[2], 0x33);
58 + check32(dcbuf[0], 0); /* dczeroa cleared the line */
59 +
60 + puts(err ? "FAIL" : "PASS");
61 + return err;
62 +}