xref: /qemu/tests/tcg/s390x/shift.c (revision b83a80e8)
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 
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