1
2
3
4
5
6
7
8#define pr_fmt(fmt) "emulate_step_test: " fmt
9
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/code-patching.h>
15#include <asm/inst.h>
16
17#define MAX_SUBTESTS 16
18
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)
23
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))
27
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))
31
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))
35
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))
39
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))
43
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))
47
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))
51
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))
55
56#define TEST_SETB(t, bfa) ppc_inst(PPC_INST_SETB | ___PPC_RT(t) | ___PPC_RA((bfa & 0x7) << 2))
57
58
59static void __init init_pt_regs(struct pt_regs *regs)
60{
61 static unsigned long msr;
62 static bool msr_cached;
63
64 memset(regs, 0, sizeof(struct pt_regs));
65
66 if (likely(msr_cached)) {
67 regs->msr = msr;
68 return;
69 }
70
71 asm volatile("mfmsr %0" : "=r"(regs->msr));
72
73 regs->msr |= MSR_FP;
74 regs->msr |= MSR_VEC;
75 regs->msr |= MSR_VSX;
76
77 msr = regs->msr;
78 msr_cached = true;
79}
80
81static void __init show_result(char *mnemonic, char *result)
82{
83 pr_info("%-14s : %s\n", mnemonic, result);
84}
85
86static void __init show_result_with_descr(char *mnemonic, char *descr,
87 char *result)
88{
89 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
90}
91
92static void __init test_ld(void)
93{
94 struct pt_regs regs;
95 unsigned long a = 0x23;
96 int stepped = -1;
97
98 init_pt_regs(®s);
99 regs.gpr[3] = (unsigned long) &a;
100
101
102 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0)));
103
104 if (stepped == 1 && regs.gpr[5] == a)
105 show_result("ld", "PASS");
106 else
107 show_result("ld", "FAIL");
108}
109
110static void __init test_pld(void)
111{
112 struct pt_regs regs;
113 unsigned long a = 0x23;
114 int stepped = -1;
115
116 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
117 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
118 return;
119 }
120
121 init_pt_regs(®s);
122 regs.gpr[3] = (unsigned long)&a;
123
124
125 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0));
126
127 if (stepped == 1 && regs.gpr[5] == a)
128 show_result("pld", "PASS");
129 else
130 show_result("pld", "FAIL");
131}
132
133static void __init test_lwz(void)
134{
135 struct pt_regs regs;
136 unsigned int a = 0x4545;
137 int stepped = -1;
138
139 init_pt_regs(®s);
140 regs.gpr[3] = (unsigned long) &a;
141
142
143 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
144
145 if (stepped == 1 && regs.gpr[5] == a)
146 show_result("lwz", "PASS");
147 else
148 show_result("lwz", "FAIL");
149}
150
151static void __init test_plwz(void)
152{
153 struct pt_regs regs;
154 unsigned int a = 0x4545;
155 int stepped = -1;
156
157 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
158 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
159 return;
160 }
161
162 init_pt_regs(®s);
163 regs.gpr[3] = (unsigned long)&a;
164
165
166
167 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0));
168
169 if (stepped == 1 && regs.gpr[5] == a)
170 show_result("plwz", "PASS");
171 else
172 show_result("plwz", "FAIL");
173}
174
175static void __init test_lwzx(void)
176{
177 struct pt_regs regs;
178 unsigned int a[3] = {0x0, 0x0, 0x1234};
179 int stepped = -1;
180
181 init_pt_regs(®s);
182 regs.gpr[3] = (unsigned long) a;
183 regs.gpr[4] = 8;
184 regs.gpr[5] = 0x8765;
185
186
187 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
188 if (stepped == 1 && regs.gpr[5] == a[2])
189 show_result("lwzx", "PASS");
190 else
191 show_result("lwzx", "FAIL");
192}
193
194static void __init test_std(void)
195{
196 struct pt_regs regs;
197 unsigned long a = 0x1234;
198 int stepped = -1;
199
200 init_pt_regs(®s);
201 regs.gpr[3] = (unsigned long) &a;
202 regs.gpr[5] = 0x5678;
203
204
205 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0)));
206 if (stepped == 1 && regs.gpr[5] == a)
207 show_result("std", "PASS");
208 else
209 show_result("std", "FAIL");
210}
211
212static void __init test_pstd(void)
213{
214 struct pt_regs regs;
215 unsigned long a = 0x1234;
216 int stepped = -1;
217
218 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
219 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
220 return;
221 }
222
223 init_pt_regs(®s);
224 regs.gpr[3] = (unsigned long)&a;
225 regs.gpr[5] = 0x5678;
226
227
228 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0));
229 if (stepped == 1 || regs.gpr[5] == a)
230 show_result("pstd", "PASS");
231 else
232 show_result("pstd", "FAIL");
233}
234
235static void __init test_ldarx_stdcx(void)
236{
237 struct pt_regs regs;
238 unsigned long a = 0x1234;
239 int stepped = -1;
240 unsigned long cr0_eq = 0x1 << 29;
241
242 init_pt_regs(®s);
243 asm volatile("mfcr %0" : "=r"(regs.ccr));
244
245
246
247
248 regs.gpr[3] = (unsigned long) &a;
249 regs.gpr[4] = 0;
250 regs.gpr[5] = 0x5678;
251
252
253 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
254
255
256
257
258
259
260 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
261 show_result("ldarx / stdcx.", "FAIL (ldarx)");
262 return;
263 }
264
265
266
267
268 regs.gpr[5] = 0x9ABC;
269
270
271 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
272
273
274
275
276
277
278
279
280
281 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
282 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
283 show_result("ldarx / stdcx.", "PASS");
284 else
285 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
286}
287
288#ifdef CONFIG_PPC_FPU
289static void __init test_lfsx_stfsx(void)
290{
291 struct pt_regs regs;
292 union {
293 float a;
294 int b;
295 } c;
296 int cached_b;
297 int stepped = -1;
298
299 init_pt_regs(®s);
300
301
302
303
304 c.a = 123.45;
305 cached_b = c.b;
306
307 regs.gpr[3] = (unsigned long) &c.a;
308 regs.gpr[4] = 0;
309
310
311 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
312
313 if (stepped == 1)
314 show_result("lfsx", "PASS");
315 else
316 show_result("lfsx", "FAIL");
317
318
319
320
321 c.a = 678.91;
322
323
324 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
325
326 if (stepped == 1 && c.b == cached_b)
327 show_result("stfsx", "PASS");
328 else
329 show_result("stfsx", "FAIL");
330}
331
332static void __init test_plfs_pstfs(void)
333{
334 struct pt_regs regs;
335 union {
336 float a;
337 int b;
338 } c;
339 int cached_b;
340 int stepped = -1;
341
342 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
343 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
344 return;
345 }
346
347 init_pt_regs(®s);
348
349
350
351
352 c.a = 123.45;
353 cached_b = c.b;
354
355 regs.gpr[3] = (unsigned long)&c.a;
356
357
358 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0));
359
360 if (stepped == 1)
361 show_result("plfs", "PASS");
362 else
363 show_result("plfs", "FAIL");
364
365
366
367
368 c.a = 678.91;
369
370
371 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0));
372
373 if (stepped == 1 && c.b == cached_b)
374 show_result("pstfs", "PASS");
375 else
376 show_result("pstfs", "FAIL");
377}
378
379static void __init test_lfdx_stfdx(void)
380{
381 struct pt_regs regs;
382 union {
383 double a;
384 long b;
385 } c;
386 long cached_b;
387 int stepped = -1;
388
389 init_pt_regs(®s);
390
391
392
393
394 c.a = 123456.78;
395 cached_b = c.b;
396
397 regs.gpr[3] = (unsigned long) &c.a;
398 regs.gpr[4] = 0;
399
400
401 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
402
403 if (stepped == 1)
404 show_result("lfdx", "PASS");
405 else
406 show_result("lfdx", "FAIL");
407
408
409
410
411 c.a = 987654.32;
412
413
414 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
415
416 if (stepped == 1 && c.b == cached_b)
417 show_result("stfdx", "PASS");
418 else
419 show_result("stfdx", "FAIL");
420}
421
422static void __init test_plfd_pstfd(void)
423{
424 struct pt_regs regs;
425 union {
426 double a;
427 long b;
428 } c;
429 long cached_b;
430 int stepped = -1;
431
432 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
433 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
434 return;
435 }
436
437 init_pt_regs(®s);
438
439
440
441
442 c.a = 123456.78;
443 cached_b = c.b;
444
445 regs.gpr[3] = (unsigned long)&c.a;
446
447
448 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0));
449
450 if (stepped == 1)
451 show_result("plfd", "PASS");
452 else
453 show_result("plfd", "FAIL");
454
455
456
457
458 c.a = 987654.32;
459
460
461 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0));
462
463 if (stepped == 1 && c.b == cached_b)
464 show_result("pstfd", "PASS");
465 else
466 show_result("pstfd", "FAIL");
467}
468#else
469static void __init test_lfsx_stfsx(void)
470{
471 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
472 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
473}
474
475static void __init test_plfs_pstfs(void)
476{
477 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
478 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
479}
480
481static void __init test_lfdx_stfdx(void)
482{
483 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
484 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
485}
486
487static void __init test_plfd_pstfd(void)
488{
489 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
490 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
491}
492#endif
493
494#ifdef CONFIG_ALTIVEC
495static void __init test_lvx_stvx(void)
496{
497 struct pt_regs regs;
498 union {
499 vector128 a;
500 u32 b[4];
501 } c;
502 u32 cached_b[4];
503 int stepped = -1;
504
505 init_pt_regs(®s);
506
507
508
509
510 cached_b[0] = c.b[0] = 923745;
511 cached_b[1] = c.b[1] = 2139478;
512 cached_b[2] = c.b[2] = 9012;
513 cached_b[3] = c.b[3] = 982134;
514
515 regs.gpr[3] = (unsigned long) &c.a;
516 regs.gpr[4] = 0;
517
518
519 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
520
521 if (stepped == 1)
522 show_result("lvx", "PASS");
523 else
524 show_result("lvx", "FAIL");
525
526
527
528
529 c.b[0] = 4987513;
530 c.b[1] = 84313948;
531 c.b[2] = 71;
532 c.b[3] = 498532;
533
534
535 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
536
537 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
538 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
539 show_result("stvx", "PASS");
540 else
541 show_result("stvx", "FAIL");
542}
543#else
544static void __init test_lvx_stvx(void)
545{
546 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
547 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
548}
549#endif
550
551#ifdef CONFIG_VSX
552static void __init test_lxvd2x_stxvd2x(void)
553{
554 struct pt_regs regs;
555 union {
556 vector128 a;
557 u32 b[4];
558 } c;
559 u32 cached_b[4];
560 int stepped = -1;
561
562 init_pt_regs(®s);
563
564
565
566
567 cached_b[0] = c.b[0] = 18233;
568 cached_b[1] = c.b[1] = 34863571;
569 cached_b[2] = c.b[2] = 834;
570 cached_b[3] = c.b[3] = 6138911;
571
572 regs.gpr[3] = (unsigned long) &c.a;
573 regs.gpr[4] = 0;
574
575
576 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
577
578 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
579 show_result("lxvd2x", "PASS");
580 } else {
581 if (!cpu_has_feature(CPU_FTR_VSX))
582 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
583 else
584 show_result("lxvd2x", "FAIL");
585 }
586
587
588
589
590 c.b[0] = 21379463;
591 c.b[1] = 87;
592 c.b[2] = 374234;
593 c.b[3] = 4;
594
595
596 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
597
598 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
599 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
600 cpu_has_feature(CPU_FTR_VSX)) {
601 show_result("stxvd2x", "PASS");
602 } else {
603 if (!cpu_has_feature(CPU_FTR_VSX))
604 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
605 else
606 show_result("stxvd2x", "FAIL");
607 }
608}
609#else
610static void __init test_lxvd2x_stxvd2x(void)
611{
612 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
613 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
614}
615#endif
616
617#ifdef CONFIG_VSX
618static void __init test_lxvp_stxvp(void)
619{
620 struct pt_regs regs;
621 union {
622 vector128 a;
623 u32 b[4];
624 } c[2];
625 u32 cached_b[8];
626 int stepped = -1;
627
628 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
629 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
630 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
631 return;
632 }
633
634 init_pt_regs(®s);
635
636
637
638 cached_b[0] = c[0].b[0] = 18233;
639 cached_b[1] = c[0].b[1] = 34863571;
640 cached_b[2] = c[0].b[2] = 834;
641 cached_b[3] = c[0].b[3] = 6138911;
642 cached_b[4] = c[1].b[0] = 1234;
643 cached_b[5] = c[1].b[1] = 5678;
644 cached_b[6] = c[1].b[2] = 91011;
645 cached_b[7] = c[1].b[3] = 121314;
646
647 regs.gpr[4] = (unsigned long)&c[0].a;
648
649
650
651
652
653
654 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
655
656 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
657 show_result("lxvp", "PASS");
658 } else {
659 if (!cpu_has_feature(CPU_FTR_VSX))
660 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
661 else
662 show_result("lxvp", "FAIL");
663 }
664
665
666
667 c[0].b[0] = 21379463;
668 c[0].b[1] = 87;
669 c[0].b[2] = 374234;
670 c[0].b[3] = 4;
671 c[1].b[0] = 90;
672 c[1].b[1] = 122;
673 c[1].b[2] = 555;
674 c[1].b[3] = 32144;
675
676
677
678
679
680
681 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
682
683 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
684 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
685 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
686 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
687 cpu_has_feature(CPU_FTR_VSX)) {
688 show_result("stxvp", "PASS");
689 } else {
690 if (!cpu_has_feature(CPU_FTR_VSX))
691 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
692 else
693 show_result("stxvp", "FAIL");
694 }
695}
696#else
697static void __init test_lxvp_stxvp(void)
698{
699 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
700 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
701}
702#endif
703
704#ifdef CONFIG_VSX
705static void __init test_lxvpx_stxvpx(void)
706{
707 struct pt_regs regs;
708 union {
709 vector128 a;
710 u32 b[4];
711 } c[2];
712 u32 cached_b[8];
713 int stepped = -1;
714
715 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
716 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
717 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
718 return;
719 }
720
721 init_pt_regs(®s);
722
723
724
725 cached_b[0] = c[0].b[0] = 18233;
726 cached_b[1] = c[0].b[1] = 34863571;
727 cached_b[2] = c[0].b[2] = 834;
728 cached_b[3] = c[0].b[3] = 6138911;
729 cached_b[4] = c[1].b[0] = 1234;
730 cached_b[5] = c[1].b[1] = 5678;
731 cached_b[6] = c[1].b[2] = 91011;
732 cached_b[7] = c[1].b[3] = 121314;
733
734 regs.gpr[3] = (unsigned long)&c[0].a;
735 regs.gpr[4] = 0;
736
737
738
739
740
741
742 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
743
744 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
745 show_result("lxvpx", "PASS");
746 } else {
747 if (!cpu_has_feature(CPU_FTR_VSX))
748 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
749 else
750 show_result("lxvpx", "FAIL");
751 }
752
753
754
755 c[0].b[0] = 21379463;
756 c[0].b[1] = 87;
757 c[0].b[2] = 374234;
758 c[0].b[3] = 4;
759 c[1].b[0] = 90;
760 c[1].b[1] = 122;
761 c[1].b[2] = 555;
762 c[1].b[3] = 32144;
763
764
765
766
767
768
769 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
770
771 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
772 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
773 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
774 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
775 cpu_has_feature(CPU_FTR_VSX)) {
776 show_result("stxvpx", "PASS");
777 } else {
778 if (!cpu_has_feature(CPU_FTR_VSX))
779 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
780 else
781 show_result("stxvpx", "FAIL");
782 }
783}
784#else
785static void __init test_lxvpx_stxvpx(void)
786{
787 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
788 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
789}
790#endif
791
792#ifdef CONFIG_VSX
793static void __init test_plxvp_pstxvp(void)
794{
795 struct ppc_inst instr;
796 struct pt_regs regs;
797 union {
798 vector128 a;
799 u32 b[4];
800 } c[2];
801 u32 cached_b[8];
802 int stepped = -1;
803
804 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
805 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
806 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
807 return;
808 }
809
810
811
812 cached_b[0] = c[0].b[0] = 18233;
813 cached_b[1] = c[0].b[1] = 34863571;
814 cached_b[2] = c[0].b[2] = 834;
815 cached_b[3] = c[0].b[3] = 6138911;
816 cached_b[4] = c[1].b[0] = 1234;
817 cached_b[5] = c[1].b[1] = 5678;
818 cached_b[6] = c[1].b[2] = 91011;
819 cached_b[7] = c[1].b[3] = 121314;
820
821 init_pt_regs(®s);
822 regs.gpr[3] = (unsigned long)&c[0].a;
823
824
825
826
827
828
829 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
830
831 stepped = emulate_step(®s, instr);
832 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
833 show_result("plxvp", "PASS");
834 } else {
835 if (!cpu_has_feature(CPU_FTR_VSX))
836 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
837 else
838 show_result("plxvp", "FAIL");
839 }
840
841
842
843 c[0].b[0] = 21379463;
844 c[0].b[1] = 87;
845 c[0].b[2] = 374234;
846 c[0].b[3] = 4;
847 c[1].b[0] = 90;
848 c[1].b[1] = 122;
849 c[1].b[2] = 555;
850 c[1].b[3] = 32144;
851
852
853
854
855
856
857 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
858
859 stepped = emulate_step(®s, instr);
860
861 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
862 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
863 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
864 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
865 cpu_has_feature(CPU_FTR_VSX)) {
866 show_result("pstxvp", "PASS");
867 } else {
868 if (!cpu_has_feature(CPU_FTR_VSX))
869 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
870 else
871 show_result("pstxvp", "FAIL");
872 }
873}
874#else
875static void __init test_plxvp_pstxvp(void)
876{
877 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
878 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
879}
880#endif
881
882static void __init run_tests_load_store(void)
883{
884 test_ld();
885 test_pld();
886 test_lwz();
887 test_plwz();
888 test_lwzx();
889 test_std();
890 test_pstd();
891 test_ldarx_stdcx();
892 test_lfsx_stfsx();
893 test_plfs_pstfs();
894 test_lfdx_stfdx();
895 test_plfd_pstfd();
896 test_lvx_stvx();
897 test_lxvd2x_stxvd2x();
898 test_lxvp_stxvp();
899 test_lxvpx_stxvpx();
900 test_plxvp_pstxvp();
901}
902
903struct compute_test {
904 char *mnemonic;
905 unsigned long cpu_feature;
906 struct {
907 char *descr;
908 unsigned long flags;
909 struct ppc_inst instr;
910 struct pt_regs regs;
911 } subtests[MAX_SUBTESTS + 1];
912};
913
914
915#define SI_MIN BIT(33)
916#define SI_MAX (BIT(33) - 1)
917#define SI_UMAX (BIT(34) - 1)
918
919static struct compute_test compute_tests[] = {
920 {
921 .mnemonic = "nop",
922 .subtests = {
923 {
924 .descr = "R0 = LONG_MAX",
925 .instr = ppc_inst(PPC_RAW_NOP()),
926 .regs = {
927 .gpr[0] = LONG_MAX,
928 }
929 }
930 }
931 },
932 {
933 .mnemonic = "setb",
934 .cpu_feature = CPU_FTR_ARCH_300,
935 .subtests = {
936 {
937 .descr = "BFA = 1, CR = GT",
938 .instr = TEST_SETB(20, 1),
939 .regs = {
940 .ccr = 0x4000000,
941 }
942 },
943 {
944 .descr = "BFA = 4, CR = LT",
945 .instr = TEST_SETB(20, 4),
946 .regs = {
947 .ccr = 0x8000,
948 }
949 },
950 {
951 .descr = "BFA = 5, CR = EQ",
952 .instr = TEST_SETB(20, 5),
953 .regs = {
954 .ccr = 0x200,
955 }
956 }
957 }
958 },
959 {
960 .mnemonic = "add",
961 .subtests = {
962 {
963 .descr = "RA = LONG_MIN, RB = LONG_MIN",
964 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
965 .regs = {
966 .gpr[21] = LONG_MIN,
967 .gpr[22] = LONG_MIN,
968 }
969 },
970 {
971 .descr = "RA = LONG_MIN, RB = LONG_MAX",
972 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
973 .regs = {
974 .gpr[21] = LONG_MIN,
975 .gpr[22] = LONG_MAX,
976 }
977 },
978 {
979 .descr = "RA = LONG_MAX, RB = LONG_MAX",
980 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
981 .regs = {
982 .gpr[21] = LONG_MAX,
983 .gpr[22] = LONG_MAX,
984 }
985 },
986 {
987 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
988 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
989 .regs = {
990 .gpr[21] = ULONG_MAX,
991 .gpr[22] = ULONG_MAX,
992 }
993 },
994 {
995 .descr = "RA = ULONG_MAX, RB = 0x1",
996 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
997 .regs = {
998 .gpr[21] = ULONG_MAX,
999 .gpr[22] = 0x1,
1000 }
1001 },
1002 {
1003 .descr = "RA = INT_MIN, RB = INT_MIN",
1004 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1005 .regs = {
1006 .gpr[21] = INT_MIN,
1007 .gpr[22] = INT_MIN,
1008 }
1009 },
1010 {
1011 .descr = "RA = INT_MIN, RB = INT_MAX",
1012 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1013 .regs = {
1014 .gpr[21] = INT_MIN,
1015 .gpr[22] = INT_MAX,
1016 }
1017 },
1018 {
1019 .descr = "RA = INT_MAX, RB = INT_MAX",
1020 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1021 .regs = {
1022 .gpr[21] = INT_MAX,
1023 .gpr[22] = INT_MAX,
1024 }
1025 },
1026 {
1027 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1028 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1029 .regs = {
1030 .gpr[21] = UINT_MAX,
1031 .gpr[22] = UINT_MAX,
1032 }
1033 },
1034 {
1035 .descr = "RA = UINT_MAX, RB = 0x1",
1036 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1037 .regs = {
1038 .gpr[21] = UINT_MAX,
1039 .gpr[22] = 0x1,
1040 }
1041 }
1042 }
1043 },
1044 {
1045 .mnemonic = "add.",
1046 .subtests = {
1047 {
1048 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1049 .flags = IGNORE_CCR,
1050 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1051 .regs = {
1052 .gpr[21] = LONG_MIN,
1053 .gpr[22] = LONG_MIN,
1054 }
1055 },
1056 {
1057 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1058 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1059 .regs = {
1060 .gpr[21] = LONG_MIN,
1061 .gpr[22] = LONG_MAX,
1062 }
1063 },
1064 {
1065 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1066 .flags = IGNORE_CCR,
1067 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1068 .regs = {
1069 .gpr[21] = LONG_MAX,
1070 .gpr[22] = LONG_MAX,
1071 }
1072 },
1073 {
1074 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1075 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1076 .regs = {
1077 .gpr[21] = ULONG_MAX,
1078 .gpr[22] = ULONG_MAX,
1079 }
1080 },
1081 {
1082 .descr = "RA = ULONG_MAX, RB = 0x1",
1083 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1084 .regs = {
1085 .gpr[21] = ULONG_MAX,
1086 .gpr[22] = 0x1,
1087 }
1088 },
1089 {
1090 .descr = "RA = INT_MIN, RB = INT_MIN",
1091 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1092 .regs = {
1093 .gpr[21] = INT_MIN,
1094 .gpr[22] = INT_MIN,
1095 }
1096 },
1097 {
1098 .descr = "RA = INT_MIN, RB = INT_MAX",
1099 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1100 .regs = {
1101 .gpr[21] = INT_MIN,
1102 .gpr[22] = INT_MAX,
1103 }
1104 },
1105 {
1106 .descr = "RA = INT_MAX, RB = INT_MAX",
1107 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1108 .regs = {
1109 .gpr[21] = INT_MAX,
1110 .gpr[22] = INT_MAX,
1111 }
1112 },
1113 {
1114 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1115 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1116 .regs = {
1117 .gpr[21] = UINT_MAX,
1118 .gpr[22] = UINT_MAX,
1119 }
1120 },
1121 {
1122 .descr = "RA = UINT_MAX, RB = 0x1",
1123 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1124 .regs = {
1125 .gpr[21] = UINT_MAX,
1126 .gpr[22] = 0x1,
1127 }
1128 }
1129 }
1130 },
1131 {
1132 .mnemonic = "addc",
1133 .subtests = {
1134 {
1135 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1136 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1137 .regs = {
1138 .gpr[21] = LONG_MIN,
1139 .gpr[22] = LONG_MIN,
1140 }
1141 },
1142 {
1143 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1144 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1145 .regs = {
1146 .gpr[21] = LONG_MIN,
1147 .gpr[22] = LONG_MAX,
1148 }
1149 },
1150 {
1151 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1152 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1153 .regs = {
1154 .gpr[21] = LONG_MAX,
1155 .gpr[22] = LONG_MAX,
1156 }
1157 },
1158 {
1159 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1160 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1161 .regs = {
1162 .gpr[21] = ULONG_MAX,
1163 .gpr[22] = ULONG_MAX,
1164 }
1165 },
1166 {
1167 .descr = "RA = ULONG_MAX, RB = 0x1",
1168 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1169 .regs = {
1170 .gpr[21] = ULONG_MAX,
1171 .gpr[22] = 0x1,
1172 }
1173 },
1174 {
1175 .descr = "RA = INT_MIN, RB = INT_MIN",
1176 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1177 .regs = {
1178 .gpr[21] = INT_MIN,
1179 .gpr[22] = INT_MIN,
1180 }
1181 },
1182 {
1183 .descr = "RA = INT_MIN, RB = INT_MAX",
1184 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1185 .regs = {
1186 .gpr[21] = INT_MIN,
1187 .gpr[22] = INT_MAX,
1188 }
1189 },
1190 {
1191 .descr = "RA = INT_MAX, RB = INT_MAX",
1192 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1193 .regs = {
1194 .gpr[21] = INT_MAX,
1195 .gpr[22] = INT_MAX,
1196 }
1197 },
1198 {
1199 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1200 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1201 .regs = {
1202 .gpr[21] = UINT_MAX,
1203 .gpr[22] = UINT_MAX,
1204 }
1205 },
1206 {
1207 .descr = "RA = UINT_MAX, RB = 0x1",
1208 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1209 .regs = {
1210 .gpr[21] = UINT_MAX,
1211 .gpr[22] = 0x1,
1212 }
1213 },
1214 {
1215 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1216 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1217 .regs = {
1218 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1219 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1220 }
1221 }
1222 }
1223 },
1224 {
1225 .mnemonic = "addc.",
1226 .subtests = {
1227 {
1228 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1229 .flags = IGNORE_CCR,
1230 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1231 .regs = {
1232 .gpr[21] = LONG_MIN,
1233 .gpr[22] = LONG_MIN,
1234 }
1235 },
1236 {
1237 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1238 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1239 .regs = {
1240 .gpr[21] = LONG_MIN,
1241 .gpr[22] = LONG_MAX,
1242 }
1243 },
1244 {
1245 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1246 .flags = IGNORE_CCR,
1247 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1248 .regs = {
1249 .gpr[21] = LONG_MAX,
1250 .gpr[22] = LONG_MAX,
1251 }
1252 },
1253 {
1254 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1255 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1256 .regs = {
1257 .gpr[21] = ULONG_MAX,
1258 .gpr[22] = ULONG_MAX,
1259 }
1260 },
1261 {
1262 .descr = "RA = ULONG_MAX, RB = 0x1",
1263 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1264 .regs = {
1265 .gpr[21] = ULONG_MAX,
1266 .gpr[22] = 0x1,
1267 }
1268 },
1269 {
1270 .descr = "RA = INT_MIN, RB = INT_MIN",
1271 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1272 .regs = {
1273 .gpr[21] = INT_MIN,
1274 .gpr[22] = INT_MIN,
1275 }
1276 },
1277 {
1278 .descr = "RA = INT_MIN, RB = INT_MAX",
1279 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1280 .regs = {
1281 .gpr[21] = INT_MIN,
1282 .gpr[22] = INT_MAX,
1283 }
1284 },
1285 {
1286 .descr = "RA = INT_MAX, RB = INT_MAX",
1287 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1288 .regs = {
1289 .gpr[21] = INT_MAX,
1290 .gpr[22] = INT_MAX,
1291 }
1292 },
1293 {
1294 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1295 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1296 .regs = {
1297 .gpr[21] = UINT_MAX,
1298 .gpr[22] = UINT_MAX,
1299 }
1300 },
1301 {
1302 .descr = "RA = UINT_MAX, RB = 0x1",
1303 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1304 .regs = {
1305 .gpr[21] = UINT_MAX,
1306 .gpr[22] = 0x1,
1307 }
1308 },
1309 {
1310 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1311 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1312 .regs = {
1313 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1314 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1315 }
1316 }
1317 }
1318 },
1319 {
1320 .mnemonic = "divde",
1321 .subtests = {
1322 {
1323 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1324 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1325 .regs = {
1326 .gpr[21] = LONG_MIN,
1327 .gpr[22] = LONG_MIN,
1328 }
1329 },
1330 {
1331 .descr = "RA = 1L, RB = 0",
1332 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1333 .flags = IGNORE_GPR(20),
1334 .regs = {
1335 .gpr[21] = 1L,
1336 .gpr[22] = 0,
1337 }
1338 },
1339 {
1340 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1341 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1342 .regs = {
1343 .gpr[21] = LONG_MIN,
1344 .gpr[22] = LONG_MAX,
1345 }
1346 }
1347 }
1348 },
1349 {
1350 .mnemonic = "divde.",
1351 .subtests = {
1352 {
1353 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1354 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1355 .regs = {
1356 .gpr[21] = LONG_MIN,
1357 .gpr[22] = LONG_MIN,
1358 }
1359 },
1360 {
1361 .descr = "RA = 1L, RB = 0",
1362 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1363 .flags = IGNORE_GPR(20),
1364 .regs = {
1365 .gpr[21] = 1L,
1366 .gpr[22] = 0,
1367 }
1368 },
1369 {
1370 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1371 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1372 .regs = {
1373 .gpr[21] = LONG_MIN,
1374 .gpr[22] = LONG_MAX,
1375 }
1376 }
1377 }
1378 },
1379 {
1380 .mnemonic = "divdeu",
1381 .subtests = {
1382 {
1383 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1384 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1385 .flags = IGNORE_GPR(20),
1386 .regs = {
1387 .gpr[21] = LONG_MIN,
1388 .gpr[22] = LONG_MIN,
1389 }
1390 },
1391 {
1392 .descr = "RA = 1L, RB = 0",
1393 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1394 .flags = IGNORE_GPR(20),
1395 .regs = {
1396 .gpr[21] = 1L,
1397 .gpr[22] = 0,
1398 }
1399 },
1400 {
1401 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1402 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1403 .regs = {
1404 .gpr[21] = LONG_MIN,
1405 .gpr[22] = LONG_MAX,
1406 }
1407 },
1408 {
1409 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1410 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1411 .regs = {
1412 .gpr[21] = LONG_MAX - 1,
1413 .gpr[22] = LONG_MAX,
1414 }
1415 },
1416 {
1417 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1418 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1419 .flags = IGNORE_GPR(20),
1420 .regs = {
1421 .gpr[21] = LONG_MIN + 1,
1422 .gpr[22] = LONG_MIN,
1423 }
1424 }
1425 }
1426 },
1427 {
1428 .mnemonic = "divdeu.",
1429 .subtests = {
1430 {
1431 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1432 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1433 .flags = IGNORE_GPR(20),
1434 .regs = {
1435 .gpr[21] = LONG_MIN,
1436 .gpr[22] = LONG_MIN,
1437 }
1438 },
1439 {
1440 .descr = "RA = 1L, RB = 0",
1441 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1442 .flags = IGNORE_GPR(20),
1443 .regs = {
1444 .gpr[21] = 1L,
1445 .gpr[22] = 0,
1446 }
1447 },
1448 {
1449 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1450 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1451 .regs = {
1452 .gpr[21] = LONG_MIN,
1453 .gpr[22] = LONG_MAX,
1454 }
1455 },
1456 {
1457 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1458 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1459 .regs = {
1460 .gpr[21] = LONG_MAX - 1,
1461 .gpr[22] = LONG_MAX,
1462 }
1463 },
1464 {
1465 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1466 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1467 .flags = IGNORE_GPR(20),
1468 .regs = {
1469 .gpr[21] = LONG_MIN + 1,
1470 .gpr[22] = LONG_MIN,
1471 }
1472 }
1473 }
1474 },
1475 {
1476 .mnemonic = "paddi",
1477 .cpu_feature = CPU_FTR_ARCH_31,
1478 .subtests = {
1479 {
1480 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
1481 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1482 .regs = {
1483 .gpr[21] = 0,
1484 .gpr[22] = LONG_MIN,
1485 }
1486 },
1487 {
1488 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
1489 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1490 .regs = {
1491 .gpr[21] = 0,
1492 .gpr[22] = LONG_MIN,
1493 }
1494 },
1495 {
1496 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
1497 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1498 .regs = {
1499 .gpr[21] = 0,
1500 .gpr[22] = LONG_MAX,
1501 }
1502 },
1503 {
1504 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1505 .instr = TEST_PADDI(21, 22, SI_UMAX, 0),
1506 .regs = {
1507 .gpr[21] = 0,
1508 .gpr[22] = ULONG_MAX,
1509 }
1510 },
1511 {
1512 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
1513 .instr = TEST_PADDI(21, 22, 0x1, 0),
1514 .regs = {
1515 .gpr[21] = 0,
1516 .gpr[22] = ULONG_MAX,
1517 }
1518 },
1519 {
1520 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
1521 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1522 .regs = {
1523 .gpr[21] = 0,
1524 .gpr[22] = INT_MIN,
1525 }
1526 },
1527 {
1528 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
1529 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1530 .regs = {
1531 .gpr[21] = 0,
1532 .gpr[22] = INT_MIN,
1533 }
1534 },
1535 {
1536 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
1537 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1538 .regs = {
1539 .gpr[21] = 0,
1540 .gpr[22] = INT_MAX,
1541 }
1542 },
1543 {
1544 .descr = "RA = UINT_MAX, SI = 0x1, R = 0",
1545 .instr = TEST_PADDI(21, 22, 0x1, 0),
1546 .regs = {
1547 .gpr[21] = 0,
1548 .gpr[22] = UINT_MAX,
1549 }
1550 },
1551 {
1552 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
1553 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1554 .regs = {
1555 .gpr[21] = 0,
1556 .gpr[22] = UINT_MAX,
1557 }
1558 },
1559 {
1560 .descr = "RA is r0, SI = SI_MIN, R = 0",
1561 .instr = TEST_PADDI(21, 0, SI_MIN, 0),
1562 .regs = {
1563 .gpr[21] = 0x0,
1564 }
1565 },
1566 {
1567 .descr = "RA = 0, SI = SI_MIN, R = 0",
1568 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1569 .regs = {
1570 .gpr[21] = 0x0,
1571 .gpr[22] = 0x0,
1572 }
1573 },
1574 {
1575 .descr = "RA is r0, SI = 0, R = 1",
1576 .instr = TEST_PADDI(21, 0, 0, 1),
1577 .regs = {
1578 .gpr[21] = 0,
1579 }
1580 },
1581 {
1582 .descr = "RA is r0, SI = SI_MIN, R = 1",
1583 .instr = TEST_PADDI(21, 0, SI_MIN, 1),
1584 .regs = {
1585 .gpr[21] = 0,
1586 }
1587 },
1588
1589 {
1590 .descr = "RA = R22(0), SI = 0, R = 1",
1591 .instr = TEST_PADDI(21, 22, 0, 1),
1592 .flags = NEGATIVE_TEST,
1593 .regs = {
1594 .gpr[21] = 0,
1595 .gpr[22] = 0,
1596 }
1597 }
1598 }
1599 }
1600};
1601
1602static int __init emulate_compute_instr(struct pt_regs *regs,
1603 struct ppc_inst instr,
1604 bool negative)
1605{
1606 int analysed;
1607 struct instruction_op op;
1608
1609 if (!regs || !ppc_inst_val(instr))
1610 return -EINVAL;
1611
1612
1613 regs->nip = patch_site_addr(&patch__exec_instr);
1614
1615 analysed = analyse_instr(&op, regs, instr);
1616 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
1617 if (negative)
1618 return -EFAULT;
1619 pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr));
1620 return -EFAULT;
1621 }
1622 if (analysed == 1 && negative)
1623 pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr));
1624 if (!negative)
1625 emulate_update_regs(regs, &op);
1626 return 0;
1627}
1628
1629static int __init execute_compute_instr(struct pt_regs *regs,
1630 struct ppc_inst instr)
1631{
1632 extern int exec_instr(struct pt_regs *regs);
1633
1634 if (!regs || !ppc_inst_val(instr))
1635 return -EINVAL;
1636
1637
1638 patch_instruction_site(&patch__exec_instr, instr);
1639 if (exec_instr(regs)) {
1640 pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr));
1641 return -EFAULT;
1642 }
1643
1644 return 0;
1645}
1646
1647#define gpr_mismatch(gprn, exp, got) \
1648 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1649 gprn, exp, got)
1650
1651#define reg_mismatch(name, exp, got) \
1652 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1653 name, exp, got)
1654
1655static void __init run_tests_compute(void)
1656{
1657 unsigned long flags;
1658 struct compute_test *test;
1659 struct pt_regs *regs, exp, got;
1660 unsigned int i, j, k;
1661 struct ppc_inst instr;
1662 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
1663
1664 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1665 test = &compute_tests[i];
1666
1667 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1668 show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1669 continue;
1670 }
1671
1672 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
1673 instr = test->subtests[j].instr;
1674 flags = test->subtests[j].flags;
1675 regs = &test->subtests[j].regs;
1676 negative = flags & NEGATIVE_TEST;
1677 ignore_xer = flags & IGNORE_XER;
1678 ignore_ccr = flags & IGNORE_CCR;
1679 passed = true;
1680
1681 memcpy(&exp, regs, sizeof(struct pt_regs));
1682 memcpy(&got, regs, sizeof(struct pt_regs));
1683
1684
1685
1686
1687
1688 exp.msr = MSR_KERNEL;
1689 got.msr = MSR_KERNEL;
1690
1691 rc = emulate_compute_instr(&got, instr, negative) != 0;
1692 if (negative) {
1693
1694 passed = rc;
1695 goto print;
1696 } else if (rc || execute_compute_instr(&exp, instr)) {
1697 passed = false;
1698 goto print;
1699 }
1700
1701
1702 for (k = 0; k < 32; k++) {
1703 ignore_gpr = flags & IGNORE_GPR(k);
1704 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
1705 passed = false;
1706 gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
1707 }
1708 }
1709
1710
1711 if (exp.link != got.link) {
1712 passed = false;
1713 reg_mismatch("LR", exp.link, got.link);
1714 }
1715
1716
1717 if (!ignore_xer && exp.xer != got.xer) {
1718 passed = false;
1719 reg_mismatch("XER", exp.xer, got.xer);
1720 }
1721
1722
1723 if (!ignore_ccr && exp.ccr != got.ccr) {
1724 passed = false;
1725 reg_mismatch("CR", exp.ccr, got.ccr);
1726 }
1727
1728print:
1729 show_result_with_descr(test->mnemonic,
1730 test->subtests[j].descr,
1731 passed ? "PASS" : "FAIL");
1732 }
1733 }
1734}
1735
1736static int __init test_emulate_step(void)
1737{
1738 printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1739 run_tests_load_store();
1740 run_tests_compute();
1741
1742 return 0;
1743}
1744late_initcall(test_emulate_step);
1745