1*5e8a0c62SIlya Leoshkevich /* Check EXECUTE with relative long instructions as targets. */
2*5e8a0c62SIlya Leoshkevich #include <stdlib.h>
3*5e8a0c62SIlya Leoshkevich #include <stdio.h>
4*5e8a0c62SIlya Leoshkevich
5*5e8a0c62SIlya Leoshkevich struct test {
6*5e8a0c62SIlya Leoshkevich const char *name;
7*5e8a0c62SIlya Leoshkevich long (*func)(long reg, long *cc);
8*5e8a0c62SIlya Leoshkevich long exp_reg;
9*5e8a0c62SIlya Leoshkevich long exp_mem;
10*5e8a0c62SIlya Leoshkevich long exp_cc;
11*5e8a0c62SIlya Leoshkevich };
12*5e8a0c62SIlya Leoshkevich
13*5e8a0c62SIlya Leoshkevich /*
14*5e8a0c62SIlya Leoshkevich * Each test sets the MEM_IDXth element of the mem array to MEM and uses a
15*5e8a0c62SIlya Leoshkevich * single relative long instruction on it. The other elements remain zero.
16*5e8a0c62SIlya Leoshkevich * This is in order to prevent stumbling upon MEM in random memory in case
17*5e8a0c62SIlya Leoshkevich * there is an off-by-a-small-value bug.
18*5e8a0c62SIlya Leoshkevich *
19*5e8a0c62SIlya Leoshkevich * Note that while gcc supports the ZL constraint for relative long operands,
20*5e8a0c62SIlya Leoshkevich * clang doesn't, so the assembly code accesses mem[MEM_IDX] using MEM_ASM.
21*5e8a0c62SIlya Leoshkevich */
22*5e8a0c62SIlya Leoshkevich static long mem[0x1000];
23*5e8a0c62SIlya Leoshkevich #define MEM_IDX 0x800
24*5e8a0c62SIlya Leoshkevich #define MEM_ASM "mem+0x800*8"
25*5e8a0c62SIlya Leoshkevich
26*5e8a0c62SIlya Leoshkevich /* Initial %r2 value. */
27*5e8a0c62SIlya Leoshkevich #define REG 0x1234567887654321
28*5e8a0c62SIlya Leoshkevich
29*5e8a0c62SIlya Leoshkevich /* Initial mem[MEM_IDX] value. */
30*5e8a0c62SIlya Leoshkevich #define MEM 0xfedcba9889abcdef
31*5e8a0c62SIlya Leoshkevich
32*5e8a0c62SIlya Leoshkevich /* Initial cc value. */
33*5e8a0c62SIlya Leoshkevich #define CC 0
34*5e8a0c62SIlya Leoshkevich
35*5e8a0c62SIlya Leoshkevich /* Relative long instructions and their expected effects. */
36*5e8a0c62SIlya Leoshkevich #define FOR_EACH_INSN(F) \
37*5e8a0c62SIlya Leoshkevich F(cgfrl, REG, MEM, 2) \
38*5e8a0c62SIlya Leoshkevich F(cghrl, REG, MEM, 2) \
39*5e8a0c62SIlya Leoshkevich F(cgrl, REG, MEM, 2) \
40*5e8a0c62SIlya Leoshkevich F(chrl, REG, MEM, 1) \
41*5e8a0c62SIlya Leoshkevich F(clgfrl, REG, MEM, 2) \
42*5e8a0c62SIlya Leoshkevich F(clghrl, REG, MEM, 2) \
43*5e8a0c62SIlya Leoshkevich F(clgrl, REG, MEM, 1) \
44*5e8a0c62SIlya Leoshkevich F(clhrl, REG, MEM, 2) \
45*5e8a0c62SIlya Leoshkevich F(clrl, REG, MEM, 1) \
46*5e8a0c62SIlya Leoshkevich F(crl, REG, MEM, 1) \
47*5e8a0c62SIlya Leoshkevich F(larl, (long)&mem[MEM_IDX], MEM, CC) \
48*5e8a0c62SIlya Leoshkevich F(lgfrl, 0xfffffffffedcba98, MEM, CC) \
49*5e8a0c62SIlya Leoshkevich F(lghrl, 0xfffffffffffffedc, MEM, CC) \
50*5e8a0c62SIlya Leoshkevich F(lgrl, MEM, MEM, CC) \
51*5e8a0c62SIlya Leoshkevich F(lhrl, 0x12345678fffffedc, MEM, CC) \
52*5e8a0c62SIlya Leoshkevich F(llghrl, 0x000000000000fedc, MEM, CC) \
53*5e8a0c62SIlya Leoshkevich F(llhrl, 0x123456780000fedc, MEM, CC) \
54*5e8a0c62SIlya Leoshkevich F(lrl, 0x12345678fedcba98, MEM, CC) \
55*5e8a0c62SIlya Leoshkevich F(stgrl, REG, REG, CC) \
56*5e8a0c62SIlya Leoshkevich F(sthrl, REG, 0x4321ba9889abcdef, CC) \
57*5e8a0c62SIlya Leoshkevich F(strl, REG, 0x8765432189abcdef, CC)
58*5e8a0c62SIlya Leoshkevich
59*5e8a0c62SIlya Leoshkevich /* Test functions. */
60*5e8a0c62SIlya Leoshkevich #define DEFINE_EX_TEST(insn, exp_reg, exp_mem, exp_cc) \
61*5e8a0c62SIlya Leoshkevich static long test_ex_ ## insn(long reg, long *cc) \
62*5e8a0c62SIlya Leoshkevich { \
63*5e8a0c62SIlya Leoshkevich register long r2 asm("r2"); \
64*5e8a0c62SIlya Leoshkevich char mask = 0x20; /* make target use %r2 */ \
65*5e8a0c62SIlya Leoshkevich long pm, target; \
66*5e8a0c62SIlya Leoshkevich \
67*5e8a0c62SIlya Leoshkevich r2 = reg; \
68*5e8a0c62SIlya Leoshkevich asm("larl %[target],0f\n" \
69*5e8a0c62SIlya Leoshkevich "cr %%r0,%%r0\n" /* initial cc */ \
70*5e8a0c62SIlya Leoshkevich "ex %[mask],0(%[target])\n" \
71*5e8a0c62SIlya Leoshkevich "jg 1f\n" \
72*5e8a0c62SIlya Leoshkevich "0: " #insn " %%r0," MEM_ASM "\n" \
73*5e8a0c62SIlya Leoshkevich "1: ipm %[pm]\n" \
74*5e8a0c62SIlya Leoshkevich : [target] "=&a" (target), [r2] "+r" (r2), [pm] "=r" (pm) \
75*5e8a0c62SIlya Leoshkevich : [mask] "a" (mask) \
76*5e8a0c62SIlya Leoshkevich : "cc", "memory"); \
77*5e8a0c62SIlya Leoshkevich reg = r2; \
78*5e8a0c62SIlya Leoshkevich *cc = (pm >> 28) & 3; \
79*5e8a0c62SIlya Leoshkevich \
80*5e8a0c62SIlya Leoshkevich return reg; \
81*5e8a0c62SIlya Leoshkevich }
82*5e8a0c62SIlya Leoshkevich
83*5e8a0c62SIlya Leoshkevich #define DEFINE_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc) \
84*5e8a0c62SIlya Leoshkevich static long test_exrl_ ## insn(long reg, long *cc) \
85*5e8a0c62SIlya Leoshkevich { \
86*5e8a0c62SIlya Leoshkevich register long r2 asm("r2"); \
87*5e8a0c62SIlya Leoshkevich char mask = 0x20; /* make target use %r2 */ \
88*5e8a0c62SIlya Leoshkevich long pm; \
89*5e8a0c62SIlya Leoshkevich \
90*5e8a0c62SIlya Leoshkevich r2 = reg; \
91*5e8a0c62SIlya Leoshkevich asm("cr %%r0,%%r0\n" /* initial cc */ \
92*5e8a0c62SIlya Leoshkevich "exrl %[mask],0f\n" \
93*5e8a0c62SIlya Leoshkevich "jg 1f\n" \
94*5e8a0c62SIlya Leoshkevich "0: " #insn " %%r0," MEM_ASM "\n" \
95*5e8a0c62SIlya Leoshkevich "1: ipm %[pm]\n" \
96*5e8a0c62SIlya Leoshkevich : [r2] "+r" (r2), [pm] "=r" (pm) \
97*5e8a0c62SIlya Leoshkevich : [mask] "a" (mask) \
98*5e8a0c62SIlya Leoshkevich : "cc", "memory"); \
99*5e8a0c62SIlya Leoshkevich reg = r2; \
100*5e8a0c62SIlya Leoshkevich *cc = (pm >> 28) & 3; \
101*5e8a0c62SIlya Leoshkevich \
102*5e8a0c62SIlya Leoshkevich return reg; \
103*5e8a0c62SIlya Leoshkevich }
104*5e8a0c62SIlya Leoshkevich
105*5e8a0c62SIlya Leoshkevich FOR_EACH_INSN(DEFINE_EX_TEST)
106*5e8a0c62SIlya Leoshkevich FOR_EACH_INSN(DEFINE_EXRL_TEST)
107*5e8a0c62SIlya Leoshkevich
108*5e8a0c62SIlya Leoshkevich /* Test definitions. */
109*5e8a0c62SIlya Leoshkevich #define REGISTER_EX_EXRL_TEST(ex_insn, insn, _exp_reg, _exp_mem, _exp_cc) \
110*5e8a0c62SIlya Leoshkevich { \
111*5e8a0c62SIlya Leoshkevich .name = #ex_insn " " #insn, \
112*5e8a0c62SIlya Leoshkevich .func = test_ ## ex_insn ## _ ## insn, \
113*5e8a0c62SIlya Leoshkevich .exp_reg = (_exp_reg), \
114*5e8a0c62SIlya Leoshkevich .exp_mem = (_exp_mem), \
115*5e8a0c62SIlya Leoshkevich .exp_cc = (_exp_cc), \
116*5e8a0c62SIlya Leoshkevich },
117*5e8a0c62SIlya Leoshkevich
118*5e8a0c62SIlya Leoshkevich #define REGISTER_EX_TEST(insn, exp_reg, exp_mem, exp_cc) \
119*5e8a0c62SIlya Leoshkevich REGISTER_EX_EXRL_TEST(ex, insn, exp_reg, exp_mem, exp_cc)
120*5e8a0c62SIlya Leoshkevich
121*5e8a0c62SIlya Leoshkevich #define REGISTER_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc) \
122*5e8a0c62SIlya Leoshkevich REGISTER_EX_EXRL_TEST(exrl, insn, exp_reg, exp_mem, exp_cc)
123*5e8a0c62SIlya Leoshkevich
124*5e8a0c62SIlya Leoshkevich static const struct test tests[] = {
125*5e8a0c62SIlya Leoshkevich FOR_EACH_INSN(REGISTER_EX_TEST)
126*5e8a0c62SIlya Leoshkevich FOR_EACH_INSN(REGISTER_EXRL_TEST)
127*5e8a0c62SIlya Leoshkevich };
128*5e8a0c62SIlya Leoshkevich
129*5e8a0c62SIlya Leoshkevich /* Loop over all tests and run them. */
main(void)130*5e8a0c62SIlya Leoshkevich int main(void)
131*5e8a0c62SIlya Leoshkevich {
132*5e8a0c62SIlya Leoshkevich const struct test *test;
133*5e8a0c62SIlya Leoshkevich int ret = EXIT_SUCCESS;
134*5e8a0c62SIlya Leoshkevich long reg, cc;
135*5e8a0c62SIlya Leoshkevich size_t i;
136*5e8a0c62SIlya Leoshkevich
137*5e8a0c62SIlya Leoshkevich for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
138*5e8a0c62SIlya Leoshkevich test = &tests[i];
139*5e8a0c62SIlya Leoshkevich mem[MEM_IDX] = MEM;
140*5e8a0c62SIlya Leoshkevich cc = -1;
141*5e8a0c62SIlya Leoshkevich reg = test->func(REG, &cc);
142*5e8a0c62SIlya Leoshkevich #define ASSERT_EQ(expected, actual) do { \
143*5e8a0c62SIlya Leoshkevich if (expected != actual) { \
144*5e8a0c62SIlya Leoshkevich fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " (0x%lx)\n", \
145*5e8a0c62SIlya Leoshkevich test->name, expected, actual); \
146*5e8a0c62SIlya Leoshkevich ret = EXIT_FAILURE; \
147*5e8a0c62SIlya Leoshkevich } \
148*5e8a0c62SIlya Leoshkevich } while (0)
149*5e8a0c62SIlya Leoshkevich ASSERT_EQ(test->exp_reg, reg);
150*5e8a0c62SIlya Leoshkevich ASSERT_EQ(test->exp_mem, mem[MEM_IDX]);
151*5e8a0c62SIlya Leoshkevich ASSERT_EQ(test->exp_cc, cc);
152*5e8a0c62SIlya Leoshkevich #undef ASSERT_EQ
153*5e8a0c62SIlya Leoshkevich }
154*5e8a0c62SIlya Leoshkevich
155*5e8a0c62SIlya Leoshkevich return ret;
156*5e8a0c62SIlya Leoshkevich }
157