xref: /qemu/tests/tcg/s390x/branch-relative-long.c (revision 0c5c4d5b)
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