1 /* Check EXECUTE with relative branch instructions as targets. */ 2 #include <assert.h> 3 #include <stdbool.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 struct test { 9 const char *name; 10 void (*func)(long *link, long *magic); 11 long exp_link; 12 }; 13 14 /* Branch instructions and their expected effects. */ 15 #define LINK_64(test) ((long)test ## _exp_link) 16 #define LINK_NONE(test) -1L 17 #define FOR_EACH_INSN(F) \ 18 F(bras, "%[link]", LINK_64) \ 19 F(brasl, "%[link]", LINK_64) \ 20 F(brc, "0x8", LINK_NONE) \ 21 F(brcl, "0x8", LINK_NONE) \ 22 F(brct, "%%r0", LINK_NONE) \ 23 F(brctg, "%%r0", LINK_NONE) \ 24 F(brxh, "%%r2,%%r0", LINK_NONE) \ 25 F(brxhg, "%%r2,%%r0", LINK_NONE) \ 26 F(brxle, "%%r0,%%r1", LINK_NONE) \ 27 F(brxlg, "%%r0,%%r1", LINK_NONE) \ 28 F(crj, "%%r0,%%r0,8", LINK_NONE) \ 29 F(cgrj, "%%r0,%%r0,8", LINK_NONE) \ 30 F(cij, "%%r0,0,8", LINK_NONE) \ 31 F(cgij, "%%r0,0,8", LINK_NONE) \ 32 F(clrj, "%%r0,%%r0,8", LINK_NONE) \ 33 F(clgrj, "%%r0,%%r0,8", LINK_NONE) \ 34 F(clij, "%%r0,0,8", LINK_NONE) \ 35 F(clgij, "%%r0,0,8", LINK_NONE) 36 37 #define INIT_TEST \ 38 "xgr %%r0,%%r0\n" /* %r0 = 0; %cc = 0 */ \ 39 "lghi %%r1,1\n" /* %r1 = 1 */ \ 40 "lghi %%r2,2\n" /* %r2 = 2 */ 41 42 #define CLOBBERS_TEST "cc", "0", "1", "2" 43 44 #define DEFINE_TEST(insn, args, exp_link) \ 45 extern char insn ## _exp_link[]; \ 46 static void test_ ## insn(long *link, long *magic) \ 47 { \ 48 asm(INIT_TEST \ 49 #insn " " args ",0f\n" \ 50 ".globl " #insn "_exp_link\n" \ 51 #insn "_exp_link:\n" \ 52 ".org . + 90\n" \ 53 "0: lgfi %[magic],0x12345678\n" \ 54 : [link] "+r" (*link) \ 55 , [magic] "+r" (*magic) \ 56 : : CLOBBERS_TEST); \ 57 } \ 58 extern char ex_ ## insn ## _exp_link[]; \ 59 static void test_ex_ ## insn(long *link, long *magic) \ 60 { \ 61 unsigned long target; \ 62 \ 63 asm(INIT_TEST \ 64 "larl %[target],0f\n" \ 65 "ex %%r0,0(%[target])\n" \ 66 ".globl ex_" #insn "_exp_link\n" \ 67 "ex_" #insn "_exp_link:\n" \ 68 ".org . + 60\n" \ 69 "0: " #insn " " args ",1f\n" \ 70 ".org . + 120\n" \ 71 "1: lgfi %[magic],0x12345678\n" \ 72 : [target] "=r" (target) \ 73 , [link] "+r" (*link) \ 74 , [magic] "+r" (*magic) \ 75 : : CLOBBERS_TEST); \ 76 } \ 77 extern char exrl_ ## insn ## _exp_link[]; \ 78 static void test_exrl_ ## insn(long *link, long *magic) \ 79 { \ 80 asm(INIT_TEST \ 81 "exrl %%r0,0f\n" \ 82 ".globl exrl_" #insn "_exp_link\n" \ 83 "exrl_" #insn "_exp_link:\n" \ 84 ".org . + 60\n" \ 85 "0: " #insn " " args ",1f\n" \ 86 ".org . + 120\n" \ 87 "1: lgfi %[magic],0x12345678\n" \ 88 : [link] "+r" (*link) \ 89 , [magic] "+r" (*magic) \ 90 : : CLOBBERS_TEST); \ 91 } 92 93 /* Test functions. */ 94 FOR_EACH_INSN(DEFINE_TEST) 95 96 /* Test definitions. */ 97 #define REGISTER_TEST(insn, args, _exp_link) \ 98 { \ 99 .name = #insn, \ 100 .func = test_ ## insn, \ 101 .exp_link = (_exp_link(insn)), \ 102 }, \ 103 { \ 104 .name = "ex " #insn, \ 105 .func = test_ex_ ## insn, \ 106 .exp_link = (_exp_link(ex_ ## insn)), \ 107 }, \ 108 { \ 109 .name = "exrl " #insn, \ 110 .func = test_exrl_ ## insn, \ 111 .exp_link = (_exp_link(exrl_ ## insn)), \ 112 }, 113 114 static const struct test tests[] = { 115 FOR_EACH_INSN(REGISTER_TEST) 116 }; 117 118 int main(int argc, char **argv) 119 { 120 const struct test *test; 121 int ret = EXIT_SUCCESS; 122 bool verbose = false; 123 long link, magic; 124 size_t i; 125 126 for (i = 1; i < argc; i++) { 127 if (strcmp(argv[i], "-v") == 0) { 128 verbose = true; 129 } 130 } 131 132 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 133 test = &tests[i]; 134 if (verbose) { 135 fprintf(stderr, "[ RUN ] %s\n", test->name); 136 } 137 link = -1; 138 magic = -1; 139 test->func(&link, &magic); 140 #define ASSERT_EQ(expected, actual) do { \ 141 if (expected != actual) { \ 142 fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " (0x%lx)\n", \ 143 test->name, expected, actual); \ 144 ret = EXIT_FAILURE; \ 145 } \ 146 } while (0) 147 ASSERT_EQ(test->exp_link, link); 148 ASSERT_EQ(0x12345678L, magic); 149 #undef ASSERT_EQ 150 } 151 152 if (verbose) { 153 fprintf(stderr, ret == EXIT_SUCCESS ? "[ PASSED ]\n" : 154 "[ FAILED ]\n"); 155 } 156 157 return ret; 158 } 159