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
+}