blob: c6067191528de4624c5e0d9e5f0ad93ab6d41398 [file] [log] [blame]
Ilya Leoshkevichbfa72592023-04-27 01:58:13 +02001/* 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
8struct 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. */
94FOR_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
114static const struct test tests[] = {
115 FOR_EACH_INSN(REGISTER_TEST)
116};
117
118int 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}