master
c 420 lines 10.8 KB
Raw
1 /*
2 * Test Octeon-specific user-mode instructions.
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include <assert.h>
8 #include <stdint.h>
9
10 static uint64_t octeon_baddu(uint64_t rs, uint64_t rt)
11 {
12 uint64_t rd;
13
14 asm volatile(
15 "move $8, %[rs]\n\t"
16 "move $9, %[rt]\n\t"
17 ".word 0x71095028\n\t" /* baddu $10, $8, $9 */
18 "move %[rd], $10\n\t"
19 : [rd] "=r" (rd)
20 : [rs] "r" (rs), [rt] "r" (rt)
21 : "$8", "$9", "$10");
22
23 return rd;
24 }
25
26 static uint64_t octeon_dmul(uint64_t rs, uint64_t rt)
27 {
28 uint64_t rd;
29
30 asm volatile(
31 "move $8, %[rs]\n\t"
32 "move $9, %[rt]\n\t"
33 ".word 0x71095003\n\t" /* dmul $10, $8, $9 */
34 "move %[rd], $10\n\t"
35 : [rd] "=r" (rd)
36 : [rs] "r" (rs), [rt] "r" (rt)
37 : "$8", "$9", "$10");
38
39 return rd;
40 }
41
42 static uint64_t octeon_dpop(uint64_t rs)
43 {
44 uint64_t rd;
45
46 asm volatile(
47 "move $8, %[rs]\n\t"
48 ".word 0x7100502d\n\t" /* dpop $10, $8 */
49 "move %[rd], $10\n\t"
50 : [rd] "=r" (rd)
51 : [rs] "r" (rs)
52 : "$8", "$10");
53
54 return rd;
55 }
56
57 static uint64_t octeon_seq(uint64_t rs, uint64_t rt)
58 {
59 uint64_t rd;
60
61 asm volatile(
62 "move $8, %[rs]\n\t"
63 "move $9, %[rt]\n\t"
64 ".word 0x7109502a\n\t" /* seq $10, $8, $9 */
65 "move %[rd], $10\n\t"
66 : [rd] "=r" (rd)
67 : [rs] "r" (rs), [rt] "r" (rt)
68 : "$8", "$9", "$10");
69
70 return rd;
71 }
72
73 static uint64_t octeon_sne(uint64_t rs, uint64_t rt)
74 {
75 uint64_t rd;
76
77 asm volatile(
78 "move $8, %[rs]\n\t"
79 "move $9, %[rt]\n\t"
80 ".word 0x7109502b\n\t" /* sne $10, $8, $9 */
81 "move %[rd], $10\n\t"
82 : [rd] "=r" (rd)
83 : [rs] "r" (rs), [rt] "r" (rt)
84 : "$8", "$9", "$10");
85
86 return rd;
87 }
88
89 static uint64_t octeon_vmulu(uint64_t mpl0, uint64_t rs, uint64_t rt)
90 {
91 uint64_t rd;
92
93 asm volatile(
94 "move $8, %[mpl0]\n\t"
95 "move $9, $0\n\t"
96 ".word 0x71090008\n\t" /* mtm0 $8, $9 */
97 "move $8, %[rs]\n\t"
98 "move $9, %[rt]\n\t"
99 ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
100 "move %[rd], $10\n\t"
101 : [rd] "=r" (rd)
102 : [mpl0] "r" (mpl0), [rs] "r" (rs), [rt] "r" (rt)
103 : "$8", "$9", "$10");
104
105 return rd;
106 }
107
108 static uint64_t octeon_vmm0(uint64_t mpl0, uint64_t p0,
109 uint64_t rs, uint64_t rt)
110 {
111 uint64_t rd;
112
113 asm volatile(
114 "move $8, %[mpl0]\n\t"
115 "move $9, $0\n\t"
116 ".word 0x71090008\n\t" /* mtm0 $8, $9 */
117 "move $8, %[p0]\n\t"
118 "move $9, $0\n\t"
119 ".word 0x71090009\n\t" /* mtp0 $8, $9 */
120 "move $8, %[rs]\n\t"
121 "move $9, %[rt]\n\t"
122 ".word 0x71095010\n\t" /* vmm0 $10, $8, $9 */
123 "move %[rd], $10\n\t"
124 : [rd] "=r" (rd)
125 : [mpl0] "r" (mpl0), [p0] "r" (p0),
126 [rs] "r" (rs), [rt] "r" (rt)
127 : "$8", "$9", "$10");
128
129 return rd;
130 }
131
132 static uint64_t octeon_qmac_lo(uint64_t rs, uint64_t rt, uint64_t lo)
133 {
134 uint64_t rd;
135
136 asm volatile(
137 "move $8, %[rs]\n\t"
138 "move $9, %[rt]\n\t"
139 "mtlo %[lo]\n\t"
140 "mthi $0\n\t"
141 ".word 0x710904d2\n\t" /* qmac.03 $8, $9 */
142 "mflo %[rd]\n\t"
143 : [rd] "=r" (rd)
144 : [rs] "r" (rs), [rt] "r" (rt), [lo] "r" (lo)
145 : "$8", "$9");
146
147 return rd;
148 }
149
150 static uint64_t octeon_qmacs_state(uint64_t rs, uint64_t rt, uint64_t lo)
151 {
152 uint64_t hi, rd;
153
154 asm volatile(
155 "move $8, %[rs]\n\t"
156 "move $9, %[rt]\n\t"
157 "mtlo %[lo]\n\t"
158 "mthi $0\n\t"
159 ".word 0x71090012\n\t" /* qmacs.00 $8, $9 */
160 "mfhi %[hi]\n\t"
161 "mflo %[rd]\n\t"
162 : [hi] "=r" (hi), [rd] "=r" (rd)
163 : [rs] "r" (rs), [rt] "r" (rt), [lo] "r" (lo)
164 : "$8", "$9");
165
166 return ((hi & 1) << 32) | (rd & 0xffffffff);
167 }
168
169 static uint64_t octeon_vmm0_zeroes_mpl1(void)
170 {
171 uint64_t rd;
172
173 asm volatile(
174 "move $8, %[mpl0]\n\t"
175 "move $9, $0\n\t"
176 ".word 0x71090008\n\t" /* mtm0 $8, $9 */
177 "move $8, %[mpl1]\n\t"
178 "move $9, $0\n\t"
179 ".word 0x7109000c\n\t" /* mtm1 $8, $9 */
180 "move $8, %[vmm0_rs]\n\t"
181 "move $9, $0\n\t"
182 ".word 0x71095010\n\t" /* vmm0 $10, $8, $9 */
183 "move $8, %[vmulu_rs]\n\t"
184 "move $9, $0\n\t"
185 ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
186 "move $8, $0\n\t"
187 "move $9, $0\n\t"
188 ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
189 "move %[rd], $10\n\t"
190 : [rd] "=r" (rd)
191 : [mpl0] "r" (1ULL), [mpl1] "r" (1ULL),
192 [vmm0_rs] "r" (2ULL), [vmulu_rs] "r" (1ULL)
193 : "$8", "$9", "$10");
194
195 return rd;
196 }
197
198 static uint64_t octeon_mtp0_zeroes_p1(void)
199 {
200 uint64_t rd;
201
202 asm volatile(
203 "move $8, %[mpl0]\n\t"
204 "move $9, $0\n\t"
205 ".word 0x71090008\n\t" /* mtm0 $8, $9 */
206 "move $8, %[p1]\n\t"
207 "move $9, $0\n\t"
208 ".word 0x7109000a\n\t" /* mtp1 $8, $9 */
209 "move $8, $0\n\t"
210 "move $9, $0\n\t"
211 ".word 0x71090009\n\t" /* mtp0 $8, $9 */
212 "move $8, $0\n\t"
213 "move $9, $0\n\t"
214 ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
215 "move $8, $0\n\t"
216 "move $9, $0\n\t"
217 ".word 0x7109500f\n\t" /* vmulu $10, $8, $9 */
218 "move %[rd], $10\n\t"
219 : [rd] "=r" (rd)
220 : [mpl0] "r" (0ULL), [p1] "r" (1ULL)
221 : "$8", "$9", "$10");
222
223 return rd;
224 }
225
226 static uint64_t octeon_cop2_key0_readback(uint64_t value)
227 {
228 uint64_t rd;
229
230 asm volatile(
231 "move $8, %[value]\n\t"
232 ".word 0x48a80104\n\t" /* dmtc2 $8, AES_KEY0 selector */
233 ".word 0x482a0104\n\t" /* dmfc2 $10, AES_KEY0 selector */
234 "move %[rd], $10\n\t"
235 : [rd] "=r" (rd)
236 : [value] "r" (value)
237 : "$8", "$10");
238
239 return rd;
240 }
241
242 static uint64_t octeon_cop2_key2_readback(uint64_t value)
243 {
244 uint64_t rd;
245
246 asm volatile(
247 "move $8, %[value]\n\t"
248 ".word 0x48a80106\n\t" /* dmtc2 $8, AES_KEY2 selector */
249 ".word 0x482a0106\n\t" /* dmfc2 $10, AES_KEY2 selector */
250 "move %[rd], $10\n\t"
251 : [rd] "=r" (rd)
252 : [value] "r" (value)
253 : "$8", "$10");
254
255 return rd;
256 }
257
258 static uint64_t octeon_cop2_key3_readback(uint64_t value)
259 {
260 uint64_t rd;
261
262 asm volatile(
263 "move $8, %[value]\n\t"
264 ".word 0x48a80107\n\t" /* dmtc2 $8, AES_KEY3 selector */
265 ".word 0x482a0107\n\t" /* dmfc2 $10, AES_KEY3 selector */
266 "move %[rd], $10\n\t"
267 : [rd] "=r" (rd)
268 : [value] "r" (value)
269 : "$8", "$10");
270
271 return rd;
272 }
273
274 static uint64_t octeon_cop2_keylength_readback(uint64_t value)
275 {
276 uint64_t rd;
277
278 asm volatile(
279 "move $8, %[value]\n\t"
280 ".word 0x48a80110\n\t" /* dmtc2 $8, AES_KEYLENGTH selector */
281 ".word 0x482a0110\n\t" /* dmfc2 $10, AES_KEYLENGTH selector */
282 "move %[rd], $10\n\t"
283 : [rd] "=r" (rd)
284 : [value] "r" (value)
285 : "$8", "$10");
286
287 return rd;
288 }
289
290 static uint64_t octeon_cop2_hsh_dat0_readback(uint64_t value)
291 {
292 uint64_t rd;
293
294 asm volatile(
295 "move $8, %[value]\n\t"
296 ".word 0x48a80040\n\t" /* dmtc2 $8, HSH_DAT0 selector */
297 ".word 0x482a0040\n\t" /* dmfc2 $10, HSH_DAT0 selector */
298 "move %[rd], $10\n\t"
299 : [rd] "=r" (rd)
300 : [value] "r" (value)
301 : "$8", "$10");
302
303 return rd;
304 }
305
306 static uint64_t octeon_cop2_crc_len_readback(uint64_t value)
307 {
308 uint64_t rd;
309
310 asm volatile(
311 "move $8, %[value]\n\t"
312 ".word 0x48a81202\n\t" /* dmtc2 $8, CRC_LEN selector */
313 ".word 0x482a0202\n\t" /* dmfc2 $10, CRC_LEN selector */
314 "move %[rd], $10\n\t"
315 : [rd] "=r" (rd)
316 : [value] "r" (value)
317 : "$8", "$10");
318
319 return rd;
320 }
321
322 static uint64_t octeon_cop2_crc_poly_reflect_readback(uint64_t value)
323 {
324 uint64_t rd;
325
326 asm volatile(
327 "move $8, %[value]\n\t"
328 ".word 0x48a84210\n\t" /* dmtc2 $8, CRC_POLYNOMIAL_REFLECT selector */
329 ".word 0x482a0200\n\t" /* dmfc2 $10, CRC_POLYNOMIAL selector */
330 "move %[rd], $10\n\t"
331 : [rd] "=r" (rd)
332 : [value] "r" (value)
333 : "$8", "$10");
334
335 return rd;
336 }
337
338 static uint64_t octeon_cop2_gfm_mul_reflect_write_readback(uint64_t value)
339 {
340 uint64_t rd;
341
342 asm volatile(
343 "move $8, %[value]\n\t"
344 ".word 0x48a80058\n\t" /* dmtc2 $8, GFM_MUL_REFLECT0 selector */
345 ".word 0x482a0258\n\t" /* dmfc2 $10, GFM_MUL0 selector */
346 "move %[rd], $10\n\t"
347 : [rd] "=r" (rd)
348 : [value] "r" (value)
349 : "$8", "$10");
350
351 return rd;
352 }
353
354 static uint64_t octeon_cop2_gfm_mul_reflect_readback(uint64_t value)
355 {
356 uint64_t rd;
357
358 asm volatile(
359 "move $8, %[value]\n\t"
360 ".word 0x48a80258\n\t" /* dmtc2 $8, GFM_MUL0 selector */
361 ".word 0x482a0058\n\t" /* dmfc2 $10, GFM_MUL_REFLECT0 selector */
362 "move %[rd], $10\n\t"
363 : [rd] "=r" (rd)
364 : [value] "r" (value)
365 : "$8", "$10");
366
367 return rd;
368 }
369
370 static uint64_t octeon_rdhwr31_non_decreasing(void)
371 {
372 uint64_t first, second;
373
374 asm volatile(
375 ".word 0x7c08f83b\n\t" /* rdhwr $8, $31 */
376 ".word 0x7c09f83b\n\t" /* rdhwr $9, $31 */
377 "move %[first], $8\n\t"
378 "move %[second], $9\n\t"
379 : [first] "=r" (first), [second] "=r" (second)
380 :
381 : "$8", "$9");
382
383 return second >= first;
384 }
385
386 int main(void)
387 {
388 assert(octeon_baddu(0x123, 0x0f0) == 0x13);
389 assert(octeon_dmul(0x12345678, 0x10) == 0x123456780);
390 assert(octeon_dpop(0xf0f0f0f0f0f0f0f0ULL) == 32);
391 assert(octeon_seq(0xabc, 0xabc) == 1);
392 assert(octeon_seq(0xabc, 0xdef) == 0);
393 assert(octeon_sne(0xabc, 0xabc) == 0);
394 assert(octeon_sne(0xabc, 0xdef) == 1);
395 assert(octeon_qmac_lo(0x0003000000000000ULL, 2, 1) == 13);
396 assert(octeon_qmacs_state(1, 1, 0x7ffffffe) == 0x17fffffffULL);
397 assert(octeon_qmacs_state(0x8000, 0x8000, 0) == 0x17fffffffULL);
398 assert(octeon_vmulu(5, 7, 11) == 46);
399 assert(octeon_vmm0(5, 13, 7, 11) == 59);
400 assert(octeon_vmm0_zeroes_mpl1() == 0);
401 assert(octeon_mtp0_zeroes_p1() == 0);
402 assert(octeon_cop2_key0_readback(0x1122334455667788ULL) ==
403 0x1122334455667788ULL);
404 assert(octeon_cop2_key2_readback(0x8877665544332211ULL) ==
405 0x8877665544332211ULL);
406 assert(octeon_cop2_key3_readback(0x0102030405060708ULL) ==
407 0x0102030405060708ULL);
408 assert(octeon_cop2_keylength_readback(0xa5) == 1);
409 assert(octeon_cop2_hsh_dat0_readback(0x0102030405060708ULL) ==
410 0x0102030405060708ULL);
411 assert(octeon_cop2_crc_len_readback(0xb5) == 5);
412 assert(octeon_cop2_crc_poly_reflect_readback(0x12345678) == 0x482c6a1e);
413 assert(octeon_cop2_gfm_mul_reflect_write_readback(
414 0x0123456789abcdefULL) == 0xf7b3d591e6a2c480ULL);
415 assert(octeon_cop2_gfm_mul_reflect_readback(
416 0xfedcba9876543210ULL) == 0x084c2a6e195d3b7fULL);
417 assert(octeon_rdhwr31_non_decreasing());
418
419 return 0;
420 }