xref: /openbmc/qemu/tests/tcg/hexagon/unaligned_pc.c (revision 76bccf3c)
1 #include <stdio.h>
2 #include <signal.h>
3 #include <setjmp.h>
4 #include <stdlib.h>
5 
6 /* will be changed in signal handler */
7 volatile sig_atomic_t completed_tests;
8 static jmp_buf after_test;
9 static int nr_tests;
10 
11 void __attribute__((naked)) test_return(void)
12 {
13     asm volatile(
14         "allocframe(#0x8)\n"
15         "r0 = #0xffffffff\n"
16         "framekey = r0\n"
17         "dealloc_return\n"
18         :
19         :
20         : "r0", "r29", "r30", "r31", "framekey");
21 }
22 
23 void test_endloop(void)
24 {
25     asm volatile(
26         "loop0(1f, #2)\n"
27         "1: r0 = #0x3\n"
28         "sa0 = r0\n"
29         "{ nop }:endloop0\n"
30         :
31         :
32         : "r0", "sa0", "lc0", "usr");
33 }
34 
35 asm(
36     ".pushsection .text.unaligned\n"
37     ".org 0x3\n"
38     ".global test_multi_cof_unaligned\n"
39     "test_multi_cof_unaligned:\n"
40     "   jumpr r31\n"
41     ".popsection\n"
42 );
43 
44 #define SYS_EXIT 94
45 
46 void test_multi_cof(void)
47 {
48     asm volatile(
49         "p0 = cmp.eq(r0, r0)\n"
50         "{\n"
51         "    if (p0) jump test_multi_cof_unaligned\n"
52         "    if (!p0) jump 1f\n"
53         "}\n"
54         "1:"
55         "  r0 = #1\n"
56         "  r6 = #%0\n"
57         "  trap0(#1)\n"
58         :
59         : "i"(SYS_EXIT)
60         : "p0", "r0", "r6");
61 }
62 
63 void sigbus_handler(int signum)
64 {
65     /* retore framekey after test_return */
66     asm volatile(
67         "r0 = #0\n"
68         "framekey = r0\n"
69         :
70         :
71         : "r0", "framekey");
72     printf("Test %d complete\n", completed_tests);
73     completed_tests++;
74     siglongjmp(after_test, 1);
75 }
76 
77 void test_done(void)
78 {
79     int err = (completed_tests != nr_tests);
80     puts(err ? "FAIL" : "PASS");
81     exit(err);
82 }
83 
84 typedef void (*test_fn)(void);
85 
86 int main()
87 {
88     test_fn tests[] = { test_return, test_endloop, test_multi_cof, test_done };
89     nr_tests = (sizeof(tests) / sizeof(tests[0])) - 1;
90 
91     struct sigaction sa = {
92         .sa_sigaction = sigbus_handler,
93         .sa_flags = SA_SIGINFO
94     };
95 
96     if (sigaction(SIGBUS, &sa, NULL) < 0) {
97         perror("sigaction");
98         return EXIT_FAILURE;
99     }
100 
101     sigsetjmp(after_test, 1);
102     tests[completed_tests]();
103 
104     /* should never get here */
105     puts("FAIL");
106     return 1;
107 }
108