qemu/tests/tcg/hexagon/unaligned_pc.c
Matheus Tavares Bernardino e1b526f1d8 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>
2024-06-08 17:48:50 -07:00

108 lines
2.1 KiB
C

#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;
}