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