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