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
49 DEFINE_SHIFT_SINGLE_3(rll, 0x4cf3b);
50 DEFINE_SHIFT_SINGLE_3(rllg, 0x697c9);
51 DEFINE_SHIFT_SINGLE_2(sla, 0x4b0);
52 DEFINE_SHIFT_SINGLE_2(sla, 0xd54);
53 DEFINE_SHIFT_SINGLE_3(slak, 0x2832c);
54 DEFINE_SHIFT_SINGLE_3(slag, 0x66cc4);
55 DEFINE_SHIFT_SINGLE_3(slag, 0xd54);
56 DEFINE_SHIFT_SINGLE_2(sll, 0xd04);
57 DEFINE_SHIFT_SINGLE_3(sllk, 0x2699f);
58 DEFINE_SHIFT_SINGLE_3(sllg, 0x59df9);
59 DEFINE_SHIFT_SINGLE_2(sra, 0x67e);
60 DEFINE_SHIFT_SINGLE_3(srak, 0x60943);
61 DEFINE_SHIFT_SINGLE_3(srag, 0x6b048);
62 DEFINE_SHIFT_SINGLE_2(srl, 0x035);
63 DEFINE_SHIFT_SINGLE_3(srlk, 0x43dfc);
64 DEFINE_SHIFT_SINGLE_3(srlg, 0x27227);
65 DEFINE_SHIFT_DOUBLE(slda, 0x38b);
66 DEFINE_SHIFT_DOUBLE(sldl, 0x031);
67 DEFINE_SHIFT_DOUBLE(srda, 0x36f);
68 DEFINE_SHIFT_DOUBLE(srdl, 0x99a);
69
70 struct 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
79 static 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
main(void)242 int 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