1c587bddbSIlya Leoshkevich #include <stddef.h>
2c587bddbSIlya Leoshkevich #include <stdio.h>
3c587bddbSIlya Leoshkevich #include <string.h>
4c587bddbSIlya Leoshkevich #include <sys/mman.h>
5c587bddbSIlya Leoshkevich
6c587bddbSIlya Leoshkevich #define DEFINE_ASM(_name, _code) \
7c587bddbSIlya Leoshkevich extern const char _name[]; \
8c587bddbSIlya Leoshkevich extern const char _name ## _end[]; \
9c587bddbSIlya Leoshkevich asm(" .globl " #_name "\n" \
10c587bddbSIlya Leoshkevich #_name ":\n" \
11c587bddbSIlya Leoshkevich " " _code "\n" \
12c587bddbSIlya Leoshkevich " .globl " #_name "_end\n" \
13c587bddbSIlya Leoshkevich #_name "_end:\n");
14c587bddbSIlya Leoshkevich
15c587bddbSIlya Leoshkevich DEFINE_ASM(br_r14, "br %r14");
160c5c4d5bSIlya Leoshkevich DEFINE_ASM(brasl_r0, "brasl %r0,-0x100000000");
170c5c4d5bSIlya Leoshkevich DEFINE_ASM(brcl_0xf, "brcl 0xf,-0x100000000");
18c587bddbSIlya Leoshkevich
19c587bddbSIlya Leoshkevich struct test {
20c587bddbSIlya Leoshkevich const char *code;
21c587bddbSIlya Leoshkevich const char *code_end;
22c587bddbSIlya Leoshkevich };
23c587bddbSIlya Leoshkevich
24c587bddbSIlya Leoshkevich static const struct test tests[] = {
25c587bddbSIlya Leoshkevich {
26c587bddbSIlya Leoshkevich .code = brasl_r0,
27c587bddbSIlya Leoshkevich .code_end = brasl_r0_end,
28c587bddbSIlya Leoshkevich },
29c587bddbSIlya Leoshkevich {
30c587bddbSIlya Leoshkevich .code = brcl_0xf,
31c587bddbSIlya Leoshkevich .code_end = brcl_0xf_end,
32c587bddbSIlya Leoshkevich },
33c587bddbSIlya Leoshkevich };
34c587bddbSIlya Leoshkevich
main(void)35c587bddbSIlya Leoshkevich int main(void)
36c587bddbSIlya Leoshkevich {
37c587bddbSIlya Leoshkevich unsigned char *buf;
38c587bddbSIlya Leoshkevich size_t length = 0;
39c587bddbSIlya Leoshkevich size_t i;
40c587bddbSIlya Leoshkevich
41c587bddbSIlya Leoshkevich for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
42c587bddbSIlya Leoshkevich size_t test_length = 0x100000000 + (tests[i].code_end - tests[i].code);
43c587bddbSIlya Leoshkevich
44c587bddbSIlya Leoshkevich if (test_length > length) {
45c587bddbSIlya Leoshkevich length = test_length;
46c587bddbSIlya Leoshkevich }
47c587bddbSIlya Leoshkevich }
48c587bddbSIlya Leoshkevich
49c587bddbSIlya Leoshkevich buf = mmap(NULL, length, PROT_READ | PROT_WRITE | PROT_EXEC,
50c587bddbSIlya Leoshkevich MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
51c587bddbSIlya Leoshkevich if (buf == MAP_FAILED) {
52c587bddbSIlya Leoshkevich perror("SKIP: mmap() failed");
53c587bddbSIlya Leoshkevich return 0;
54c587bddbSIlya Leoshkevich }
55c587bddbSIlya Leoshkevich
56c587bddbSIlya Leoshkevich memcpy(buf, br_r14, br_r14_end - br_r14);
57c587bddbSIlya Leoshkevich for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
58c587bddbSIlya Leoshkevich void (*code)(void) = (void *)(buf + 0x100000000);
59c587bddbSIlya Leoshkevich
60c587bddbSIlya Leoshkevich memcpy(code, tests[i].code, tests[i].code_end - tests[i].code);
61c587bddbSIlya Leoshkevich code();
62c587bddbSIlya Leoshkevich memset(code, 0, tests[i].code_end - tests[i].code);
63c587bddbSIlya Leoshkevich }
64c587bddbSIlya Leoshkevich
65c587bddbSIlya Leoshkevich munmap(buf, length);
66c587bddbSIlya Leoshkevich
67c587bddbSIlya Leoshkevich return 0;
68c587bddbSIlya Leoshkevich }
69