1#include <inttypes.h> 2#include <stdint.h> 3#include <stdio.h> 4 5#define DEFINE_SHIFT_SINGLE_COMMON(_name, _insn_str) \ 6 static uint64_t _name(uint64_t op1, uint64_t op2, uint64_t *cc) \ 7 { \ 8 asm(" sll %[cc],28\n" \ 9 " spm %[cc]\n" \ 10 " " _insn_str "\n" \ 11 " ipm %[cc]\n" \ 12 " srl %[cc],28" \ 13 : [op1] "+&r" (op1), \ 14 [cc] "+&r" (*cc) \ 15 : [op2] "r" (op2) \ 16 : "cc"); \ 17 return op1; \ 18 } 19#define DEFINE_SHIFT_SINGLE_2(_insn, _offset) \ 20 DEFINE_SHIFT_SINGLE_COMMON(_insn ## _ ## _offset, \ 21 #_insn " %[op1]," #_offset "(%[op2])") 22#define DEFINE_SHIFT_SINGLE_3(_insn, _offset) \ 23 DEFINE_SHIFT_SINGLE_COMMON(_insn ## _ ## _offset, \ 24 #_insn " %[op1],%[op1]," #_offset "(%[op2])") 25#define DEFINE_SHIFT_DOUBLE(_insn, _offset) \ 26 static uint64_t _insn ## _ ## _offset(uint64_t op1, uint64_t op2, \ 27 uint64_t *cc) \ 28 { \ 29 uint32_t op1h = op1 >> 32; \ 30 uint32_t op1l = op1 & 0xffffffff; \ 31 register uint32_t r2 asm("2") = op1h; \ 32 register uint32_t r3 asm("3") = op1l; \ 33 \ 34 asm(" sll %[cc],28\n" \ 35 " spm %[cc]\n" \ 36 " " #_insn " %[r2]," #_offset "(%[op2])\n" \ 37 " ipm %[cc]\n" \ 38 " srl %[cc],28" \ 39 : [r2] "+&r" (r2), \ 40 [r3] "+&r" (r3), \ 41 [cc] "+&r" (*cc) \ 42 : [op2] "r" (op2) \ 43 : "cc"); \ 44 op1h = r2; \ 45 op1l = r3; \ 46 return (((uint64_t)op1h) << 32) | op1l; \ 47 } 48 49DEFINE_SHIFT_SINGLE_3(rll, 0x4cf3b); 50DEFINE_SHIFT_SINGLE_3(rllg, 0x697c9); 51DEFINE_SHIFT_SINGLE_2(sla, 0x4b0); 52DEFINE_SHIFT_SINGLE_2(sla, 0xd54); 53DEFINE_SHIFT_SINGLE_3(slak, 0x2832c); 54DEFINE_SHIFT_SINGLE_3(slag, 0x66cc4); 55DEFINE_SHIFT_SINGLE_3(slag, 0xd54); 56DEFINE_SHIFT_SINGLE_2(sll, 0xd04); 57DEFINE_SHIFT_SINGLE_3(sllk, 0x2699f); 58DEFINE_SHIFT_SINGLE_3(sllg, 0x59df9); 59DEFINE_SHIFT_SINGLE_2(sra, 0x67e); 60DEFINE_SHIFT_SINGLE_3(srak, 0x60943); 61DEFINE_SHIFT_SINGLE_3(srag, 0x6b048); 62DEFINE_SHIFT_SINGLE_2(srl, 0x035); 63DEFINE_SHIFT_SINGLE_3(srlk, 0x43dfc); 64DEFINE_SHIFT_SINGLE_3(srlg, 0x27227); 65DEFINE_SHIFT_DOUBLE(slda, 0x38b); 66DEFINE_SHIFT_DOUBLE(sldl, 0x031); 67DEFINE_SHIFT_DOUBLE(srda, 0x36f); 68DEFINE_SHIFT_DOUBLE(srdl, 0x99a); 69 70struct shift_test { 71 const char *name; 72 uint64_t (*insn)(uint64_t, uint64_t, uint64_t *); 73 uint64_t op1; 74 uint64_t op2; 75 uint64_t exp_result; 76 uint64_t exp_cc; 77}; 78 79static const struct shift_test tests[] = { 80 { 81 .name = "rll", 82 .insn = rll_0x4cf3b, 83 .op1 = 0xecbd589a45c248f5ull, 84 .op2 = 0x62e5508ccb4c99fdull, 85 .exp_result = 0xecbd589af545c248ull, 86 .exp_cc = 0, 87 }, 88 { 89 .name = "rllg", 90 .insn = rllg_0x697c9, 91 .op1 = 0xaa2d54c1b729f7f4ull, 92 .op2 = 0x5ffcf7465f5cd71full, 93 .exp_result = 0x29f7f4aa2d54c1b7ull, 94 .exp_cc = 0, 95 }, 96 { 97 .name = "sla-1", 98 .insn = sla_0x4b0, 99 .op1 = 0x8bf21fb67cca0e96ull, 100 .op2 = 0x3ddf2f53347d3030ull, 101 .exp_result = 0x8bf21fb600000000ull, 102 .exp_cc = 3, 103 }, 104 { 105 .name = "sla-2", 106 .insn = sla_0xd54, 107 .op1 = 0xe4faaed5def0e926ull, 108 .op2 = 0x18d586fab239cbeeull, 109 .exp_result = 0xe4faaed5fbc3a498ull, 110 .exp_cc = 3, 111 }, 112 { 113 .name = "slak", 114 .insn = slak_0x2832c, 115 .op1 = 0x7300bf78707f09f9ull, 116 .op2 = 0x4d193b85bb5cb39bull, 117 .exp_result = 0x7300bf783f84fc80ull, 118 .exp_cc = 3, 119 }, 120 { 121 .name = "slag-1", 122 .insn = slag_0x66cc4, 123 .op1 = 0xe805966de1a77762ull, 124 .op2 = 0x0e92953f6aa91c6bull, 125 .exp_result = 0xbbb1000000000000ull, 126 .exp_cc = 3, 127 }, 128 { 129 .name = "slag-2", 130 .insn = slag_0xd54, 131 .op1 = 0xdef0e92600000000ull, 132 .op2 = 0x18d586fab239cbeeull, 133 .exp_result = 0xfbc3a49800000000ull, 134 .exp_cc = 3, 135 }, 136 { 137 .name = "sll", 138 .insn = sll_0xd04, 139 .op1 = 0xb90281a3105939dfull, 140 .op2 = 0xb5e4df7e082e4c5eull, 141 .exp_result = 0xb90281a300000000ull, 142 .exp_cc = 0, 143 }, 144 { 145 .name = "sllk", 146 .insn = sllk_0x2699f, 147 .op1 = 0x777c6cf116f99557ull, 148 .op2 = 0xe0556cf112e5a458ull, 149 .exp_result = 0x777c6cf100000000ull, 150 .exp_cc = 0, 151 }, 152 { 153 .name = "sllg", 154 .insn = sllg_0x59df9, 155 .op1 = 0xcdf86cbfbc0f3557ull, 156 .op2 = 0x325a45acf99c6d3dull, 157 .exp_result = 0x55c0000000000000ull, 158 .exp_cc = 0, 159 }, 160 { 161 .name = "sra", 162 .insn = sra_0x67e, 163 .op1 = 0xb878f048d5354183ull, 164 .op2 = 0x9e27d13195931f79ull, 165 .exp_result = 0xb878f048ffffffffull, 166 .exp_cc = 1, 167 }, 168 { 169 .name = "srak", 170 .insn = srak_0x60943, 171 .op1 = 0xb6ceb5a429cedb35ull, 172 .op2 = 0x352354900ae34d7aull, 173 .exp_result = 0xb6ceb5a400000000ull, 174 .exp_cc = 0, 175 }, 176 { 177 .name = "srag", 178 .insn = srag_0x6b048, 179 .op1 = 0xd54dd4468676c63bull, 180 .op2 = 0x84d026db7b4dca28ull, 181 .exp_result = 0xffffffffffffd54dull, 182 .exp_cc = 1, 183 }, 184 { 185 .name = "srl", 186 .insn = srl_0x035, 187 .op1 = 0x09be503ef826815full, 188 .op2 = 0xbba8d1a0e542d5c1ull, 189 .exp_result = 0x9be503e00000000ull, 190 .exp_cc = 0, 191 }, 192 { 193 .name = "srlk", 194 .insn = srlk_0x43dfc, 195 .op1 = 0x540d6c8de71aee2aull, 196 .op2 = 0x0000000000000000ull, 197 .exp_result = 0x540d6c8d00000000ull, 198 .exp_cc = 0, 199 }, 200 { 201 .name = "srlg", 202 .insn = srlg_0x27227, 203 .op1 = 0x26f7123c1c447a34ull, 204 .op2 = 0x0000000000000000ull, 205 .exp_result = 0x00000000004dee24ull, 206 .exp_cc = 0, 207 }, 208 { 209 .name = "slda", 210 .insn = slda_0x38b, 211 .op1 = 0x7988f722dd5bbe7cull, 212 .op2 = 0x9aed3f95b4d78cc2ull, 213 .exp_result = 0x1ee45bab77cf8000ull, 214 .exp_cc = 3, 215 }, 216 { 217 .name = "sldl", 218 .insn = sldl_0x031, 219 .op1 = 0xaae2918dce2b049aull, 220 .op2 = 0x0000000000000000ull, 221 .exp_result = 0x0934000000000000ull, 222 .exp_cc = 0, 223 }, 224 { 225 .name = "srda", 226 .insn = srda_0x36f, 227 .op1 = 0x0cd4ed9228a50978ull, 228 .op2 = 0x72b046f0848b8cc9ull, 229 .exp_result = 0x000000000000000cull, 230 .exp_cc = 2, 231 }, 232 { 233 .name = "srdl", 234 .insn = srdl_0x99a, 235 .op1 = 0x1018611c41689a1dull, 236 .op2 = 0x2907e150c50ba319ull, 237 .exp_result = 0x0000000000000203ull, 238 .exp_cc = 0, 239 }, 240}; 241 242int main(void) 243{ 244 int ret = 0; 245 size_t i; 246 247 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 248 uint64_t result; 249 uint64_t cc = 0; 250 251 result = tests[i].insn(tests[i].op1, tests[i].op2, &cc); 252 if (result != tests[i].exp_result) { 253 fprintf(stderr, 254 "bad %s result:\n" 255 "actual = 0x%" PRIx64 "\n" 256 "expected = 0x%" PRIx64 "\n", 257 tests[i].name, result, tests[i].exp_result); 258 ret = 1; 259 } 260 if (cc != tests[i].exp_cc) { 261 fprintf(stderr, 262 "bad %s cc:\n" 263 "actual = %" PRIu64 "\n" 264 "expected = %" PRIu64 "\n", 265 tests[i].name, cc, tests[i].exp_cc); 266 ret = 1; 267 } 268 } 269 return ret; 270} 271