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