qemu/tests/tcg/s390x/branch-relative-long.c
<<
>>
Prefs
   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
  15DEFINE_ASM(br_r14, "br %r14");
  16DEFINE_ASM(brasl_r0, "brasl %r0,.-0x100000000");
  17DEFINE_ASM(brcl_0xf, "brcl 0xf,.-0x100000000");
  18
  19struct test {
  20    const char *code;
  21    const char *code_end;
  22};
  23
  24static 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
  35int 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