printf: Remove unused 'bprintf'
[drm/drm-misc.git] / arch / powerpc / lib / test_emulate_step.c
blob66b5b4fa16864937e25b8a9643c9eab76906b937
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Simple sanity tests for instruction emulation infrastructure.
5 * Copyright IBM Corp. 2016
6 */
8 #define pr_fmt(fmt) "emulate_step_test: " fmt
10 #include <linux/ptrace.h>
11 #include <asm/cpu_has_feature.h>
12 #include <asm/sstep.h>
13 #include <asm/ppc-opcode.h>
14 #include <asm/text-patching.h>
15 #include <asm/inst.h>
17 #define MAX_SUBTESTS 16
19 #define IGNORE_GPR(n) (0x1UL << (n))
20 #define IGNORE_XER (0x1UL << 32)
21 #define IGNORE_CCR (0x1UL << 33)
22 #define NEGATIVE_TEST (0x1UL << 63)
24 #define TEST_PLD(r, base, i, pr) \
25 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
26 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
28 #define TEST_PLWZ(r, base, i, pr) \
29 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
30 PPC_RAW_LWZ(r, base, i))
32 #define TEST_PSTD(r, base, i, pr) \
33 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
34 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
36 #define TEST_PLFS(r, base, i, pr) \
37 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
38 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
40 #define TEST_PSTFS(r, base, i, pr) \
41 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
42 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
44 #define TEST_PLFD(r, base, i, pr) \
45 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
46 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
48 #define TEST_PSTFD(r, base, i, pr) \
49 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
50 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
52 #define TEST_PADDI(t, a, i, pr) \
53 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
54 PPC_RAW_ADDI(t, a, i))
56 static void __init init_pt_regs(struct pt_regs *regs)
58 static unsigned long msr;
59 static bool msr_cached;
61 memset(regs, 0, sizeof(struct pt_regs));
63 if (likely(msr_cached)) {
64 regs->msr = msr;
65 return;
68 asm volatile("mfmsr %0" : "=r"(regs->msr));
70 regs->msr |= MSR_FP;
71 regs->msr |= MSR_VEC;
72 regs->msr |= MSR_VSX;
74 msr = regs->msr;
75 msr_cached = true;
78 static void __init show_result(char *mnemonic, char *result)
80 pr_info("%-14s : %s\n", mnemonic, result);
83 static void __init show_result_with_descr(char *mnemonic, char *descr,
84 char *result)
86 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
89 static void __init test_ld(void)
91 struct pt_regs regs;
92 unsigned long a = 0x23;
93 int stepped = -1;
95 init_pt_regs(&regs);
96 regs.gpr[3] = (unsigned long) &a;
98 /* ld r5, 0(r3) */
99 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
101 if (stepped == 1 && regs.gpr[5] == a)
102 show_result("ld", "PASS");
103 else
104 show_result("ld", "FAIL");
107 static void __init test_pld(void)
109 struct pt_regs regs;
110 unsigned long a = 0x23;
111 int stepped = -1;
113 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
114 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
115 return;
118 init_pt_regs(&regs);
119 regs.gpr[3] = (unsigned long)&a;
121 /* pld r5, 0(r3), 0 */
122 stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
124 if (stepped == 1 && regs.gpr[5] == a)
125 show_result("pld", "PASS");
126 else
127 show_result("pld", "FAIL");
130 static void __init test_lwz(void)
132 struct pt_regs regs;
133 unsigned int a = 0x4545;
134 int stepped = -1;
136 init_pt_regs(&regs);
137 regs.gpr[3] = (unsigned long) &a;
139 /* lwz r5, 0(r3) */
140 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
142 if (stepped == 1 && regs.gpr[5] == a)
143 show_result("lwz", "PASS");
144 else
145 show_result("lwz", "FAIL");
148 static void __init test_plwz(void)
150 struct pt_regs regs;
151 unsigned int a = 0x4545;
152 int stepped = -1;
154 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
155 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
156 return;
159 init_pt_regs(&regs);
160 regs.gpr[3] = (unsigned long)&a;
162 /* plwz r5, 0(r3), 0 */
164 stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
166 if (stepped == 1 && regs.gpr[5] == a)
167 show_result("plwz", "PASS");
168 else
169 show_result("plwz", "FAIL");
172 static void __init test_lwzx(void)
174 struct pt_regs regs;
175 unsigned int a[3] = {0x0, 0x0, 0x1234};
176 int stepped = -1;
178 init_pt_regs(&regs);
179 regs.gpr[3] = (unsigned long) a;
180 regs.gpr[4] = 8;
181 regs.gpr[5] = 0x8765;
183 /* lwzx r5, r3, r4 */
184 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
185 if (stepped == 1 && regs.gpr[5] == a[2])
186 show_result("lwzx", "PASS");
187 else
188 show_result("lwzx", "FAIL");
191 static void __init test_std(void)
193 struct pt_regs regs;
194 unsigned long a = 0x1234;
195 int stepped = -1;
197 init_pt_regs(&regs);
198 regs.gpr[3] = (unsigned long) &a;
199 regs.gpr[5] = 0x5678;
201 /* std r5, 0(r3) */
202 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
203 if (stepped == 1 && regs.gpr[5] == a)
204 show_result("std", "PASS");
205 else
206 show_result("std", "FAIL");
209 static void __init test_pstd(void)
211 struct pt_regs regs;
212 unsigned long a = 0x1234;
213 int stepped = -1;
215 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
216 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
217 return;
220 init_pt_regs(&regs);
221 regs.gpr[3] = (unsigned long)&a;
222 regs.gpr[5] = 0x5678;
224 /* pstd r5, 0(r3), 0 */
225 stepped = emulate_step(&regs, TEST_PSTD(5, 3, 0, 0));
226 if (stepped == 1 || regs.gpr[5] == a)
227 show_result("pstd", "PASS");
228 else
229 show_result("pstd", "FAIL");
232 static void __init test_ldarx_stdcx(void)
234 struct pt_regs regs;
235 unsigned long a = 0x1234;
236 int stepped = -1;
237 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
239 init_pt_regs(&regs);
240 asm volatile("mfcr %0" : "=r"(regs.ccr));
243 /*** ldarx ***/
245 regs.gpr[3] = (unsigned long) &a;
246 regs.gpr[4] = 0;
247 regs.gpr[5] = 0x5678;
249 /* ldarx r5, r3, r4, 0 */
250 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
253 * Don't touch 'a' here. Touching 'a' can do Load/store
254 * of 'a' which result in failure of subsequent stdcx.
255 * Instead, use hardcoded value for comparison.
257 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
258 show_result("ldarx / stdcx.", "FAIL (ldarx)");
259 return;
263 /*** stdcx. ***/
265 regs.gpr[5] = 0x9ABC;
267 /* stdcx. r5, r3, r4 */
268 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
271 * Two possible scenarios that indicates successful emulation
272 * of stdcx. :
273 * 1. Reservation is active and store is performed. In this
274 * case cr0.eq bit will be set to 1.
275 * 2. Reservation is not active and store is not performed.
276 * In this case cr0.eq bit will be set to 0.
278 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
279 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
280 show_result("ldarx / stdcx.", "PASS");
281 else
282 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
285 #ifdef CONFIG_PPC_FPU
286 static void __init test_lfsx_stfsx(void)
288 struct pt_regs regs;
289 union {
290 float a;
291 int b;
292 } c;
293 int cached_b;
294 int stepped = -1;
296 init_pt_regs(&regs);
299 /*** lfsx ***/
301 c.a = 123.45;
302 cached_b = c.b;
304 regs.gpr[3] = (unsigned long) &c.a;
305 regs.gpr[4] = 0;
307 /* lfsx frt10, r3, r4 */
308 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
310 if (stepped == 1)
311 show_result("lfsx", "PASS");
312 else
313 show_result("lfsx", "FAIL");
316 /*** stfsx ***/
318 c.a = 678.91;
320 /* stfsx frs10, r3, r4 */
321 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
323 if (stepped == 1 && c.b == cached_b)
324 show_result("stfsx", "PASS");
325 else
326 show_result("stfsx", "FAIL");
329 static void __init test_plfs_pstfs(void)
331 struct pt_regs regs;
332 union {
333 float a;
334 int b;
335 } c;
336 int cached_b;
337 int stepped = -1;
339 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
340 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
341 return;
344 init_pt_regs(&regs);
347 /*** plfs ***/
349 c.a = 123.45;
350 cached_b = c.b;
352 regs.gpr[3] = (unsigned long)&c.a;
354 /* plfs frt10, 0(r3), 0 */
355 stepped = emulate_step(&regs, TEST_PLFS(10, 3, 0, 0));
357 if (stepped == 1)
358 show_result("plfs", "PASS");
359 else
360 show_result("plfs", "FAIL");
363 /*** pstfs ***/
365 c.a = 678.91;
367 /* pstfs frs10, 0(r3), 0 */
368 stepped = emulate_step(&regs, TEST_PSTFS(10, 3, 0, 0));
370 if (stepped == 1 && c.b == cached_b)
371 show_result("pstfs", "PASS");
372 else
373 show_result("pstfs", "FAIL");
376 static void __init test_lfdx_stfdx(void)
378 struct pt_regs regs;
379 union {
380 double a;
381 long b;
382 } c;
383 long cached_b;
384 int stepped = -1;
386 init_pt_regs(&regs);
389 /*** lfdx ***/
391 c.a = 123456.78;
392 cached_b = c.b;
394 regs.gpr[3] = (unsigned long) &c.a;
395 regs.gpr[4] = 0;
397 /* lfdx frt10, r3, r4 */
398 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
400 if (stepped == 1)
401 show_result("lfdx", "PASS");
402 else
403 show_result("lfdx", "FAIL");
406 /*** stfdx ***/
408 c.a = 987654.32;
410 /* stfdx frs10, r3, r4 */
411 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
413 if (stepped == 1 && c.b == cached_b)
414 show_result("stfdx", "PASS");
415 else
416 show_result("stfdx", "FAIL");
419 static void __init test_plfd_pstfd(void)
421 struct pt_regs regs;
422 union {
423 double a;
424 long b;
425 } c;
426 long cached_b;
427 int stepped = -1;
429 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
430 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
431 return;
434 init_pt_regs(&regs);
437 /*** plfd ***/
439 c.a = 123456.78;
440 cached_b = c.b;
442 regs.gpr[3] = (unsigned long)&c.a;
444 /* plfd frt10, 0(r3), 0 */
445 stepped = emulate_step(&regs, TEST_PLFD(10, 3, 0, 0));
447 if (stepped == 1)
448 show_result("plfd", "PASS");
449 else
450 show_result("plfd", "FAIL");
453 /*** pstfd ***/
455 c.a = 987654.32;
457 /* pstfd frs10, 0(r3), 0 */
458 stepped = emulate_step(&regs, TEST_PSTFD(10, 3, 0, 0));
460 if (stepped == 1 && c.b == cached_b)
461 show_result("pstfd", "PASS");
462 else
463 show_result("pstfd", "FAIL");
465 #else
466 static void __init test_lfsx_stfsx(void)
468 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
469 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
472 static void __init test_plfs_pstfs(void)
474 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
475 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
478 static void __init test_lfdx_stfdx(void)
480 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
481 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
484 static void __init test_plfd_pstfd(void)
486 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
487 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
489 #endif /* CONFIG_PPC_FPU */
491 #ifdef CONFIG_ALTIVEC
492 static void __init test_lvx_stvx(void)
494 struct pt_regs regs;
495 union {
496 vector128 a;
497 u32 b[4];
498 } c;
499 u32 cached_b[4];
500 int stepped = -1;
502 init_pt_regs(&regs);
505 /*** lvx ***/
507 cached_b[0] = c.b[0] = 923745;
508 cached_b[1] = c.b[1] = 2139478;
509 cached_b[2] = c.b[2] = 9012;
510 cached_b[3] = c.b[3] = 982134;
512 regs.gpr[3] = (unsigned long) &c.a;
513 regs.gpr[4] = 0;
515 /* lvx vrt10, r3, r4 */
516 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
518 if (stepped == 1)
519 show_result("lvx", "PASS");
520 else
521 show_result("lvx", "FAIL");
524 /*** stvx ***/
526 c.b[0] = 4987513;
527 c.b[1] = 84313948;
528 c.b[2] = 71;
529 c.b[3] = 498532;
531 /* stvx vrs10, r3, r4 */
532 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
534 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
535 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
536 show_result("stvx", "PASS");
537 else
538 show_result("stvx", "FAIL");
540 #else
541 static void __init test_lvx_stvx(void)
543 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
544 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
546 #endif /* CONFIG_ALTIVEC */
548 #ifdef CONFIG_VSX
549 static void __init test_lxvd2x_stxvd2x(void)
551 struct pt_regs regs;
552 union {
553 vector128 a;
554 u32 b[4];
555 } c;
556 u32 cached_b[4];
557 int stepped = -1;
559 init_pt_regs(&regs);
562 /*** lxvd2x ***/
564 cached_b[0] = c.b[0] = 18233;
565 cached_b[1] = c.b[1] = 34863571;
566 cached_b[2] = c.b[2] = 834;
567 cached_b[3] = c.b[3] = 6138911;
569 regs.gpr[3] = (unsigned long) &c.a;
570 regs.gpr[4] = 0;
572 /* lxvd2x vsr39, r3, r4 */
573 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
575 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
576 show_result("lxvd2x", "PASS");
577 } else {
578 if (!cpu_has_feature(CPU_FTR_VSX))
579 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
580 else
581 show_result("lxvd2x", "FAIL");
585 /*** stxvd2x ***/
587 c.b[0] = 21379463;
588 c.b[1] = 87;
589 c.b[2] = 374234;
590 c.b[3] = 4;
592 /* stxvd2x vsr39, r3, r4 */
593 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
595 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
596 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
597 cpu_has_feature(CPU_FTR_VSX)) {
598 show_result("stxvd2x", "PASS");
599 } else {
600 if (!cpu_has_feature(CPU_FTR_VSX))
601 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
602 else
603 show_result("stxvd2x", "FAIL");
606 #else
607 static void __init test_lxvd2x_stxvd2x(void)
609 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
610 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
612 #endif /* CONFIG_VSX */
614 #ifdef CONFIG_VSX
615 static void __init test_lxvp_stxvp(void)
617 struct pt_regs regs;
618 union {
619 vector128 a;
620 u32 b[4];
621 } c[2];
622 u32 cached_b[8];
623 int stepped = -1;
625 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
626 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
627 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
628 return;
631 init_pt_regs(&regs);
633 /*** lxvp ***/
635 cached_b[0] = c[0].b[0] = 18233;
636 cached_b[1] = c[0].b[1] = 34863571;
637 cached_b[2] = c[0].b[2] = 834;
638 cached_b[3] = c[0].b[3] = 6138911;
639 cached_b[4] = c[1].b[0] = 1234;
640 cached_b[5] = c[1].b[1] = 5678;
641 cached_b[6] = c[1].b[2] = 91011;
642 cached_b[7] = c[1].b[3] = 121314;
644 regs.gpr[4] = (unsigned long)&c[0].a;
647 * lxvp XTp,DQ(RA)
648 * XTp = 32xTX + 2xTp
649 * let TX=1 Tp=1 RA=4 DQ=0
651 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
653 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
654 show_result("lxvp", "PASS");
655 } else {
656 if (!cpu_has_feature(CPU_FTR_VSX))
657 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
658 else
659 show_result("lxvp", "FAIL");
662 /*** stxvp ***/
664 c[0].b[0] = 21379463;
665 c[0].b[1] = 87;
666 c[0].b[2] = 374234;
667 c[0].b[3] = 4;
668 c[1].b[0] = 90;
669 c[1].b[1] = 122;
670 c[1].b[2] = 555;
671 c[1].b[3] = 32144;
674 * stxvp XSp,DQ(RA)
675 * XSp = 32xSX + 2xSp
676 * let SX=1 Sp=1 RA=4 DQ=0
678 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
680 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
681 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
682 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
683 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
684 cpu_has_feature(CPU_FTR_VSX)) {
685 show_result("stxvp", "PASS");
686 } else {
687 if (!cpu_has_feature(CPU_FTR_VSX))
688 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
689 else
690 show_result("stxvp", "FAIL");
693 #else
694 static void __init test_lxvp_stxvp(void)
696 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
697 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
699 #endif /* CONFIG_VSX */
701 #ifdef CONFIG_VSX
702 static void __init test_lxvpx_stxvpx(void)
704 struct pt_regs regs;
705 union {
706 vector128 a;
707 u32 b[4];
708 } c[2];
709 u32 cached_b[8];
710 int stepped = -1;
712 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
713 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
714 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
715 return;
718 init_pt_regs(&regs);
720 /*** lxvpx ***/
722 cached_b[0] = c[0].b[0] = 18233;
723 cached_b[1] = c[0].b[1] = 34863571;
724 cached_b[2] = c[0].b[2] = 834;
725 cached_b[3] = c[0].b[3] = 6138911;
726 cached_b[4] = c[1].b[0] = 1234;
727 cached_b[5] = c[1].b[1] = 5678;
728 cached_b[6] = c[1].b[2] = 91011;
729 cached_b[7] = c[1].b[3] = 121314;
731 regs.gpr[3] = (unsigned long)&c[0].a;
732 regs.gpr[4] = 0;
735 * lxvpx XTp,RA,RB
736 * XTp = 32xTX + 2xTp
737 * let TX=1 Tp=1 RA=3 RB=4
739 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
741 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
742 show_result("lxvpx", "PASS");
743 } else {
744 if (!cpu_has_feature(CPU_FTR_VSX))
745 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
746 else
747 show_result("lxvpx", "FAIL");
750 /*** stxvpx ***/
752 c[0].b[0] = 21379463;
753 c[0].b[1] = 87;
754 c[0].b[2] = 374234;
755 c[0].b[3] = 4;
756 c[1].b[0] = 90;
757 c[1].b[1] = 122;
758 c[1].b[2] = 555;
759 c[1].b[3] = 32144;
762 * stxvpx XSp,RA,RB
763 * XSp = 32xSX + 2xSp
764 * let SX=1 Sp=1 RA=3 RB=4
766 stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
768 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
769 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
770 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
771 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
772 cpu_has_feature(CPU_FTR_VSX)) {
773 show_result("stxvpx", "PASS");
774 } else {
775 if (!cpu_has_feature(CPU_FTR_VSX))
776 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
777 else
778 show_result("stxvpx", "FAIL");
781 #else
782 static void __init test_lxvpx_stxvpx(void)
784 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
785 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
787 #endif /* CONFIG_VSX */
789 #ifdef CONFIG_VSX
790 static void __init test_plxvp_pstxvp(void)
792 ppc_inst_t instr;
793 struct pt_regs regs;
794 union {
795 vector128 a;
796 u32 b[4];
797 } c[2];
798 u32 cached_b[8];
799 int stepped = -1;
801 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
802 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
803 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
804 return;
807 /*** plxvp ***/
809 cached_b[0] = c[0].b[0] = 18233;
810 cached_b[1] = c[0].b[1] = 34863571;
811 cached_b[2] = c[0].b[2] = 834;
812 cached_b[3] = c[0].b[3] = 6138911;
813 cached_b[4] = c[1].b[0] = 1234;
814 cached_b[5] = c[1].b[1] = 5678;
815 cached_b[6] = c[1].b[2] = 91011;
816 cached_b[7] = c[1].b[3] = 121314;
818 init_pt_regs(&regs);
819 regs.gpr[3] = (unsigned long)&c[0].a;
822 * plxvp XTp,D(RA),R
823 * XTp = 32xTX + 2xTp
824 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
826 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
828 stepped = emulate_step(&regs, instr);
829 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
830 show_result("plxvp", "PASS");
831 } else {
832 if (!cpu_has_feature(CPU_FTR_VSX))
833 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
834 else
835 show_result("plxvp", "FAIL");
838 /*** pstxvp ***/
840 c[0].b[0] = 21379463;
841 c[0].b[1] = 87;
842 c[0].b[2] = 374234;
843 c[0].b[3] = 4;
844 c[1].b[0] = 90;
845 c[1].b[1] = 122;
846 c[1].b[2] = 555;
847 c[1].b[3] = 32144;
850 * pstxvp XSp,D(RA),R
851 * XSp = 32xSX + 2xSp
852 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
854 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
856 stepped = emulate_step(&regs, instr);
858 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
859 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
860 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
861 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
862 cpu_has_feature(CPU_FTR_VSX)) {
863 show_result("pstxvp", "PASS");
864 } else {
865 if (!cpu_has_feature(CPU_FTR_VSX))
866 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
867 else
868 show_result("pstxvp", "FAIL");
871 #else
872 static void __init test_plxvp_pstxvp(void)
874 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
875 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
877 #endif /* CONFIG_VSX */
879 static void __init run_tests_load_store(void)
881 test_ld();
882 test_pld();
883 test_lwz();
884 test_plwz();
885 test_lwzx();
886 test_std();
887 test_pstd();
888 test_ldarx_stdcx();
889 test_lfsx_stfsx();
890 test_plfs_pstfs();
891 test_lfdx_stfdx();
892 test_plfd_pstfd();
893 test_lvx_stvx();
894 test_lxvd2x_stxvd2x();
895 test_lxvp_stxvp();
896 test_lxvpx_stxvpx();
897 test_plxvp_pstxvp();
900 struct compute_test {
901 char *mnemonic;
902 unsigned long cpu_feature;
903 struct {
904 char *descr;
905 unsigned long flags;
906 ppc_inst_t instr;
907 struct pt_regs regs;
908 } subtests[MAX_SUBTESTS + 1];
911 /* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
912 #define SI_MIN BIT(33)
913 #define SI_MAX (BIT(33) - 1)
914 #define SI_UMAX (BIT(34) - 1)
916 static struct compute_test compute_tests[] = {
918 .mnemonic = "nop",
919 .subtests = {
921 .descr = "R0 = LONG_MAX",
922 .instr = ppc_inst(PPC_RAW_NOP()),
923 .regs = {
924 .gpr[0] = LONG_MAX,
930 .mnemonic = "setb",
931 .cpu_feature = CPU_FTR_ARCH_300,
932 .subtests = {
934 .descr = "BFA = 1, CR = GT",
935 .instr = ppc_inst(PPC_RAW_SETB(20, 1)),
936 .regs = {
937 .ccr = 0x4000000,
941 .descr = "BFA = 4, CR = LT",
942 .instr = ppc_inst(PPC_RAW_SETB(20, 4)),
943 .regs = {
944 .ccr = 0x8000,
948 .descr = "BFA = 5, CR = EQ",
949 .instr = ppc_inst(PPC_RAW_SETB(20, 5)),
950 .regs = {
951 .ccr = 0x200,
957 .mnemonic = "add",
958 .subtests = {
960 .descr = "RA = LONG_MIN, RB = LONG_MIN",
961 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
962 .regs = {
963 .gpr[21] = LONG_MIN,
964 .gpr[22] = LONG_MIN,
968 .descr = "RA = LONG_MIN, RB = LONG_MAX",
969 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
970 .regs = {
971 .gpr[21] = LONG_MIN,
972 .gpr[22] = LONG_MAX,
976 .descr = "RA = LONG_MAX, RB = LONG_MAX",
977 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
978 .regs = {
979 .gpr[21] = LONG_MAX,
980 .gpr[22] = LONG_MAX,
984 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
985 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
986 .regs = {
987 .gpr[21] = ULONG_MAX,
988 .gpr[22] = ULONG_MAX,
992 .descr = "RA = ULONG_MAX, RB = 0x1",
993 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
994 .regs = {
995 .gpr[21] = ULONG_MAX,
996 .gpr[22] = 0x1,
1000 .descr = "RA = INT_MIN, RB = INT_MIN",
1001 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1002 .regs = {
1003 .gpr[21] = INT_MIN,
1004 .gpr[22] = INT_MIN,
1008 .descr = "RA = INT_MIN, RB = INT_MAX",
1009 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1010 .regs = {
1011 .gpr[21] = INT_MIN,
1012 .gpr[22] = INT_MAX,
1016 .descr = "RA = INT_MAX, RB = INT_MAX",
1017 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1018 .regs = {
1019 .gpr[21] = INT_MAX,
1020 .gpr[22] = INT_MAX,
1024 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1025 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1026 .regs = {
1027 .gpr[21] = UINT_MAX,
1028 .gpr[22] = UINT_MAX,
1032 .descr = "RA = UINT_MAX, RB = 0x1",
1033 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1034 .regs = {
1035 .gpr[21] = UINT_MAX,
1036 .gpr[22] = 0x1,
1042 .mnemonic = "add.",
1043 .subtests = {
1045 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1046 .flags = IGNORE_CCR,
1047 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1048 .regs = {
1049 .gpr[21] = LONG_MIN,
1050 .gpr[22] = LONG_MIN,
1054 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1055 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1056 .regs = {
1057 .gpr[21] = LONG_MIN,
1058 .gpr[22] = LONG_MAX,
1062 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1063 .flags = IGNORE_CCR,
1064 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1065 .regs = {
1066 .gpr[21] = LONG_MAX,
1067 .gpr[22] = LONG_MAX,
1071 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1072 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1073 .regs = {
1074 .gpr[21] = ULONG_MAX,
1075 .gpr[22] = ULONG_MAX,
1079 .descr = "RA = ULONG_MAX, RB = 0x1",
1080 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1081 .regs = {
1082 .gpr[21] = ULONG_MAX,
1083 .gpr[22] = 0x1,
1087 .descr = "RA = INT_MIN, RB = INT_MIN",
1088 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1089 .regs = {
1090 .gpr[21] = INT_MIN,
1091 .gpr[22] = INT_MIN,
1095 .descr = "RA = INT_MIN, RB = INT_MAX",
1096 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1097 .regs = {
1098 .gpr[21] = INT_MIN,
1099 .gpr[22] = INT_MAX,
1103 .descr = "RA = INT_MAX, RB = INT_MAX",
1104 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1105 .regs = {
1106 .gpr[21] = INT_MAX,
1107 .gpr[22] = INT_MAX,
1111 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1112 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1113 .regs = {
1114 .gpr[21] = UINT_MAX,
1115 .gpr[22] = UINT_MAX,
1119 .descr = "RA = UINT_MAX, RB = 0x1",
1120 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1121 .regs = {
1122 .gpr[21] = UINT_MAX,
1123 .gpr[22] = 0x1,
1129 .mnemonic = "addc",
1130 .subtests = {
1132 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1133 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1134 .regs = {
1135 .gpr[21] = LONG_MIN,
1136 .gpr[22] = LONG_MIN,
1140 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1141 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1142 .regs = {
1143 .gpr[21] = LONG_MIN,
1144 .gpr[22] = LONG_MAX,
1148 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1149 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1150 .regs = {
1151 .gpr[21] = LONG_MAX,
1152 .gpr[22] = LONG_MAX,
1156 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1157 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1158 .regs = {
1159 .gpr[21] = ULONG_MAX,
1160 .gpr[22] = ULONG_MAX,
1164 .descr = "RA = ULONG_MAX, RB = 0x1",
1165 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1166 .regs = {
1167 .gpr[21] = ULONG_MAX,
1168 .gpr[22] = 0x1,
1172 .descr = "RA = INT_MIN, RB = INT_MIN",
1173 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1174 .regs = {
1175 .gpr[21] = INT_MIN,
1176 .gpr[22] = INT_MIN,
1180 .descr = "RA = INT_MIN, RB = INT_MAX",
1181 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1182 .regs = {
1183 .gpr[21] = INT_MIN,
1184 .gpr[22] = INT_MAX,
1188 .descr = "RA = INT_MAX, RB = INT_MAX",
1189 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1190 .regs = {
1191 .gpr[21] = INT_MAX,
1192 .gpr[22] = INT_MAX,
1196 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1197 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1198 .regs = {
1199 .gpr[21] = UINT_MAX,
1200 .gpr[22] = UINT_MAX,
1204 .descr = "RA = UINT_MAX, RB = 0x1",
1205 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1206 .regs = {
1207 .gpr[21] = UINT_MAX,
1208 .gpr[22] = 0x1,
1212 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1213 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1214 .regs = {
1215 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1216 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1222 .mnemonic = "addc.",
1223 .subtests = {
1225 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1226 .flags = IGNORE_CCR,
1227 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1228 .regs = {
1229 .gpr[21] = LONG_MIN,
1230 .gpr[22] = LONG_MIN,
1234 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1235 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1236 .regs = {
1237 .gpr[21] = LONG_MIN,
1238 .gpr[22] = LONG_MAX,
1242 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1243 .flags = IGNORE_CCR,
1244 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1245 .regs = {
1246 .gpr[21] = LONG_MAX,
1247 .gpr[22] = LONG_MAX,
1251 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1252 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1253 .regs = {
1254 .gpr[21] = ULONG_MAX,
1255 .gpr[22] = ULONG_MAX,
1259 .descr = "RA = ULONG_MAX, RB = 0x1",
1260 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1261 .regs = {
1262 .gpr[21] = ULONG_MAX,
1263 .gpr[22] = 0x1,
1267 .descr = "RA = INT_MIN, RB = INT_MIN",
1268 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1269 .regs = {
1270 .gpr[21] = INT_MIN,
1271 .gpr[22] = INT_MIN,
1275 .descr = "RA = INT_MIN, RB = INT_MAX",
1276 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1277 .regs = {
1278 .gpr[21] = INT_MIN,
1279 .gpr[22] = INT_MAX,
1283 .descr = "RA = INT_MAX, RB = INT_MAX",
1284 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1285 .regs = {
1286 .gpr[21] = INT_MAX,
1287 .gpr[22] = INT_MAX,
1291 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1292 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1293 .regs = {
1294 .gpr[21] = UINT_MAX,
1295 .gpr[22] = UINT_MAX,
1299 .descr = "RA = UINT_MAX, RB = 0x1",
1300 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1301 .regs = {
1302 .gpr[21] = UINT_MAX,
1303 .gpr[22] = 0x1,
1307 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1308 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1309 .regs = {
1310 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1311 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1317 .mnemonic = "divde",
1318 .subtests = {
1320 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1321 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1322 .regs = {
1323 .gpr[21] = LONG_MIN,
1324 .gpr[22] = LONG_MIN,
1328 .descr = "RA = 1L, RB = 0",
1329 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1330 .flags = IGNORE_GPR(20),
1331 .regs = {
1332 .gpr[21] = 1L,
1333 .gpr[22] = 0,
1337 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1338 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1339 .regs = {
1340 .gpr[21] = LONG_MIN,
1341 .gpr[22] = LONG_MAX,
1347 .mnemonic = "divde.",
1348 .subtests = {
1350 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1351 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1352 .regs = {
1353 .gpr[21] = LONG_MIN,
1354 .gpr[22] = LONG_MIN,
1358 .descr = "RA = 1L, RB = 0",
1359 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1360 .flags = IGNORE_GPR(20),
1361 .regs = {
1362 .gpr[21] = 1L,
1363 .gpr[22] = 0,
1367 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1368 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1369 .regs = {
1370 .gpr[21] = LONG_MIN,
1371 .gpr[22] = LONG_MAX,
1377 .mnemonic = "divdeu",
1378 .subtests = {
1380 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1381 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1382 .flags = IGNORE_GPR(20),
1383 .regs = {
1384 .gpr[21] = LONG_MIN,
1385 .gpr[22] = LONG_MIN,
1389 .descr = "RA = 1L, RB = 0",
1390 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1391 .flags = IGNORE_GPR(20),
1392 .regs = {
1393 .gpr[21] = 1L,
1394 .gpr[22] = 0,
1398 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1399 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1400 .regs = {
1401 .gpr[21] = LONG_MIN,
1402 .gpr[22] = LONG_MAX,
1406 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1407 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1408 .regs = {
1409 .gpr[21] = LONG_MAX - 1,
1410 .gpr[22] = LONG_MAX,
1414 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1415 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1416 .flags = IGNORE_GPR(20),
1417 .regs = {
1418 .gpr[21] = LONG_MIN + 1,
1419 .gpr[22] = LONG_MIN,
1425 .mnemonic = "divdeu.",
1426 .subtests = {
1428 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1429 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1430 .flags = IGNORE_GPR(20),
1431 .regs = {
1432 .gpr[21] = LONG_MIN,
1433 .gpr[22] = LONG_MIN,
1437 .descr = "RA = 1L, RB = 0",
1438 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1439 .flags = IGNORE_GPR(20),
1440 .regs = {
1441 .gpr[21] = 1L,
1442 .gpr[22] = 0,
1446 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1447 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1448 .regs = {
1449 .gpr[21] = LONG_MIN,
1450 .gpr[22] = LONG_MAX,
1454 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1455 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1456 .regs = {
1457 .gpr[21] = LONG_MAX - 1,
1458 .gpr[22] = LONG_MAX,
1462 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1463 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1464 .flags = IGNORE_GPR(20),
1465 .regs = {
1466 .gpr[21] = LONG_MIN + 1,
1467 .gpr[22] = LONG_MIN,
1473 .mnemonic = "paddi",
1474 .cpu_feature = CPU_FTR_ARCH_31,
1475 .subtests = {
1477 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
1478 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1479 .regs = {
1480 .gpr[21] = 0,
1481 .gpr[22] = LONG_MIN,
1485 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
1486 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1487 .regs = {
1488 .gpr[21] = 0,
1489 .gpr[22] = LONG_MIN,
1493 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
1494 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1495 .regs = {
1496 .gpr[21] = 0,
1497 .gpr[22] = LONG_MAX,
1501 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1502 .instr = TEST_PADDI(21, 22, SI_UMAX, 0),
1503 .regs = {
1504 .gpr[21] = 0,
1505 .gpr[22] = ULONG_MAX,
1509 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
1510 .instr = TEST_PADDI(21, 22, 0x1, 0),
1511 .regs = {
1512 .gpr[21] = 0,
1513 .gpr[22] = ULONG_MAX,
1517 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
1518 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1519 .regs = {
1520 .gpr[21] = 0,
1521 .gpr[22] = INT_MIN,
1525 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
1526 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1527 .regs = {
1528 .gpr[21] = 0,
1529 .gpr[22] = INT_MIN,
1533 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
1534 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1535 .regs = {
1536 .gpr[21] = 0,
1537 .gpr[22] = INT_MAX,
1541 .descr = "RA = UINT_MAX, SI = 0x1, R = 0",
1542 .instr = TEST_PADDI(21, 22, 0x1, 0),
1543 .regs = {
1544 .gpr[21] = 0,
1545 .gpr[22] = UINT_MAX,
1549 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
1550 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1551 .regs = {
1552 .gpr[21] = 0,
1553 .gpr[22] = UINT_MAX,
1557 .descr = "RA is r0, SI = SI_MIN, R = 0",
1558 .instr = TEST_PADDI(21, 0, SI_MIN, 0),
1559 .regs = {
1560 .gpr[21] = 0x0,
1564 .descr = "RA = 0, SI = SI_MIN, R = 0",
1565 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1566 .regs = {
1567 .gpr[21] = 0x0,
1568 .gpr[22] = 0x0,
1572 .descr = "RA is r0, SI = 0, R = 1",
1573 .instr = TEST_PADDI(21, 0, 0, 1),
1574 .regs = {
1575 .gpr[21] = 0,
1579 .descr = "RA is r0, SI = SI_MIN, R = 1",
1580 .instr = TEST_PADDI(21, 0, SI_MIN, 1),
1581 .regs = {
1582 .gpr[21] = 0,
1585 /* Invalid instruction form with R = 1 and RA != 0 */
1587 .descr = "RA = R22(0), SI = 0, R = 1",
1588 .instr = TEST_PADDI(21, 22, 0, 1),
1589 .flags = NEGATIVE_TEST,
1590 .regs = {
1591 .gpr[21] = 0,
1592 .gpr[22] = 0,
1599 static int __init emulate_compute_instr(struct pt_regs *regs,
1600 ppc_inst_t instr,
1601 bool negative)
1603 int analysed;
1604 struct instruction_op op;
1606 if (!regs || !ppc_inst_val(instr))
1607 return -EINVAL;
1609 /* This is not a return frame regs */
1610 regs->nip = patch_site_addr(&patch__exec_instr);
1612 analysed = analyse_instr(&op, regs, instr);
1613 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
1614 if (negative)
1615 return -EFAULT;
1616 pr_info("emulation failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1617 return -EFAULT;
1619 if (analysed == 1 && negative)
1620 pr_info("negative test failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1621 if (!negative)
1622 emulate_update_regs(regs, &op);
1623 return 0;
1626 static int __init execute_compute_instr(struct pt_regs *regs,
1627 ppc_inst_t instr)
1629 extern int exec_instr(struct pt_regs *regs);
1631 if (!regs || !ppc_inst_val(instr))
1632 return -EINVAL;
1634 /* Patch the NOP with the actual instruction */
1635 patch_instruction_site(&patch__exec_instr, instr);
1636 if (exec_instr(regs)) {
1637 pr_info("execution failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1638 return -EFAULT;
1641 return 0;
1644 #define gpr_mismatch(gprn, exp, got) \
1645 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1646 gprn, exp, got)
1648 #define reg_mismatch(name, exp, got) \
1649 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1650 name, exp, got)
1652 static void __init run_tests_compute(void)
1654 unsigned long flags;
1655 struct compute_test *test;
1656 struct pt_regs *regs, exp, got;
1657 unsigned int i, j, k;
1658 ppc_inst_t instr;
1659 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
1661 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1662 test = &compute_tests[i];
1664 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1665 show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1666 continue;
1669 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
1670 instr = test->subtests[j].instr;
1671 flags = test->subtests[j].flags;
1672 regs = &test->subtests[j].regs;
1673 negative = flags & NEGATIVE_TEST;
1674 ignore_xer = flags & IGNORE_XER;
1675 ignore_ccr = flags & IGNORE_CCR;
1676 passed = true;
1678 memcpy(&exp, regs, sizeof(struct pt_regs));
1679 memcpy(&got, regs, sizeof(struct pt_regs));
1682 * Set a compatible MSR value explicitly to ensure
1683 * that XER and CR bits are updated appropriately
1685 exp.msr = MSR_KERNEL;
1686 got.msr = MSR_KERNEL;
1688 rc = emulate_compute_instr(&got, instr, negative) != 0;
1689 if (negative) {
1690 /* skip executing instruction */
1691 passed = rc;
1692 goto print;
1693 } else if (rc || execute_compute_instr(&exp, instr)) {
1694 passed = false;
1695 goto print;
1698 /* Verify GPR values */
1699 for (k = 0; k < 32; k++) {
1700 ignore_gpr = flags & IGNORE_GPR(k);
1701 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
1702 passed = false;
1703 gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
1707 /* Verify LR value */
1708 if (exp.link != got.link) {
1709 passed = false;
1710 reg_mismatch("LR", exp.link, got.link);
1713 /* Verify XER value */
1714 if (!ignore_xer && exp.xer != got.xer) {
1715 passed = false;
1716 reg_mismatch("XER", exp.xer, got.xer);
1719 /* Verify CR value */
1720 if (!ignore_ccr && exp.ccr != got.ccr) {
1721 passed = false;
1722 reg_mismatch("CR", exp.ccr, got.ccr);
1725 print:
1726 show_result_with_descr(test->mnemonic,
1727 test->subtests[j].descr,
1728 passed ? "PASS" : "FAIL");
1733 static int __init test_emulate_step(void)
1735 printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1736 run_tests_load_store();
1737 run_tests_compute();
1739 return 0;
1741 late_initcall(test_emulate_step);