diff options
author | Matheus Tavares Bernardino <quic_mathbern@quicinc.com> | 2024-05-03 13:53:15 -0300 |
---|---|---|
committer | Brian Cain <bcain@quicinc.com> | 2024-06-08 17:48:50 -0700 |
commit | e1b526f1d86b7c51b97227989b9ba2925cc53069 (patch) | |
tree | 2eca193f6709a5e6f894fbe1483e45fb0f1c76b5 /tests | |
parent | a1852002c7509569eaaedb783925f34350fe0a84 (diff) | |
download | qemu-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.target | 2 | ||||
-rw-r--r-- | tests/tcg/hexagon/unaligned_pc.c | 107 |
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; +} |