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