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
main(int argc,char ** argv)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