aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMatheus Tavares Bernardino <quic_mathbern@quicinc.com>2024-05-03 13:53:15 -0300
committerBrian Cain <bcain@quicinc.com>2024-06-08 17:48:50 -0700
commite1b526f1d86b7c51b97227989b9ba2925cc53069 (patch)
tree2eca193f6709a5e6f894fbe1483e45fb0f1c76b5 /tests
parenta1852002c7509569eaaedb783925f34350fe0a84 (diff)
downloadqemu-e1b526f1d86b7c51b97227989b9ba2925cc53069.zip
qemu-e1b526f1d86b7c51b97227989b9ba2925cc53069.tar.gz
qemu-e1b526f1d86b7c51b97227989b9ba2925cc53069.tar.bz2
Hexagon: add PC alignment check and exception
The Hexagon Programmer's Reference Manual says that the exception 0x1e should be raised upon an unaligned program counter. Let's implement that and also add some tests. Signed-off-by: Matheus Tavares Bernardino <quic_mathbern@quicinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Reviewed-by: Brian Cain <bcain@quicinc.com> Message-Id: <277b7aeda2c717a96d4dde936b3ac77707cb6517.1714755107.git.quic_mathbern@quicinc.com> Signed-off-by: Brian Cain <bcain@quicinc.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/tcg/hexagon/Makefile.target2
-rw-r--r--tests/tcg/hexagon/unaligned_pc.c107
2 files changed, 109 insertions, 0 deletions
diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target
index f839b2c..e5182c0 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 += unaligned_pc
run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \
test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr)
@@ -107,6 +108,7 @@ overflow: overflow.c hex_test.h
preg_alias: preg_alias.c hex_test.h
read_write_overlap: read_write_overlap.c hex_test.h
reg_mut: reg_mut.c hex_test.h
+unaligned_pc: unaligned_pc.c
# This test has to be compiled for the -mv67t target
usr: usr.c hex_test.h
diff --git a/tests/tcg/hexagon/unaligned_pc.c b/tests/tcg/hexagon/unaligned_pc.c
new file mode 100644
index 0000000..e9dc7cb
--- /dev/null
+++ b/tests/tcg/hexagon/unaligned_pc.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <stdlib.h>
+
+/* will be changed in signal handler */
+volatile sig_atomic_t completed_tests;
+static jmp_buf after_test;
+static int nr_tests;
+
+void __attribute__((naked)) test_return(void)
+{
+ asm volatile(
+ "allocframe(#0x8)\n"
+ "r0 = #0xffffffff\n"
+ "framekey = r0\n"
+ "dealloc_return\n"
+ :
+ :
+ : "r0", "r29", "r30", "r31", "framekey");
+}
+
+void test_endloop(void)
+{
+ asm volatile(
+ "loop0(1f, #2)\n"
+ "1: r0 = #0x3\n"
+ "sa0 = r0\n"
+ "{ nop }:endloop0\n"
+ :
+ :
+ : "r0", "sa0", "lc0", "usr");
+}
+
+asm(
+ ".pushsection .text.unaligned\n"
+ ".org 0x3\n"
+ ".global test_multi_cof_unaligned\n"
+ "test_multi_cof_unaligned:\n"
+ " jumpr r31\n"
+ ".popsection\n"
+);
+
+#define SYS_EXIT 94
+
+void test_multi_cof(void)
+{
+ asm volatile(
+ "p0 = cmp.eq(r0, r0)\n"
+ "{\n"
+ " if (p0) jump test_multi_cof_unaligned\n"
+ " if (!p0) jump 1f\n"
+ "}\n"
+ "1:"
+ " r0 = #1\n"
+ " r6 = #%0\n"
+ " trap0(#1)\n"
+ :
+ : "i"(SYS_EXIT)
+ : "p0", "r0", "r6");
+}
+
+void sigbus_handler(int signum)
+{
+ /* retore framekey after test_return */
+ asm volatile(
+ "r0 = #0\n"
+ "framekey = r0\n"
+ :
+ :
+ : "r0", "framekey");
+ printf("Test %d complete\n", completed_tests);
+ completed_tests++;
+ siglongjmp(after_test, 1);
+}
+
+void test_done(void)
+{
+ int err = (completed_tests != nr_tests);
+ puts(err ? "FAIL" : "PASS");
+ exit(err);
+}
+
+typedef void (*test_fn)(void);
+
+int main()
+{
+ test_fn tests[] = { test_return, test_endloop, test_multi_cof, test_done };
+ nr_tests = (sizeof(tests) / sizeof(tests[0])) - 1;
+
+ struct sigaction sa = {
+ .sa_sigaction = sigbus_handler,
+ .sa_flags = SA_SIGINFO
+ };
+
+ if (sigaction(SIGBUS, &sa, NULL) < 0) {
+ perror("sigaction");
+ return EXIT_FAILURE;
+ }
+
+ sigsetjmp(after_test, 1);
+ tests[completed_tests]();
+
+ /* should never get here */
+ puts("FAIL");
+ return 1;
+}