1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Simple sanity tests for instruction emulation infrastructure.
4 *
5 * Copyright IBM Corp. 2016
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
56static void __init init_pt_regs(struct pt_regs *regs)
57{
58	static unsigned long msr;
59	static bool msr_cached;
60
61	memset(regs, 0, sizeof(struct pt_regs));
62
63	if (likely(msr_cached)) {
64		regs->msr = msr;
65		return;
66	}
67
68	asm volatile("mfmsr %0" : "=r"(regs->msr));
69
70	regs->msr |= MSR_FP;
71	regs->msr |= MSR_VEC;
72	regs->msr |= MSR_VSX;
73
74	msr = regs->msr;
75	msr_cached = true;
76}
77
78static void __init show_result(char *mnemonic, char *result)
79{
80	pr_info("%-14s : %s\n", mnemonic, result);
81}
82
83static void __init show_result_with_descr(char *mnemonic, char *descr,
84					  char *result)
85{
86	pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
87}
88
89static void __init test_ld(void)
90{
91	struct pt_regs regs;
92	unsigned long a = 0x23;
93	int stepped = -1;
94
95	init_pt_regs(&regs);
96	regs.gpr[3] = (unsigned long) &a;
97
98	/* ld r5, 0(r3) */
99	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
100
101	if (stepped == 1 && regs.gpr[5] == a)
102		show_result("ld", "PASS");
103	else
104		show_result("ld", "FAIL");
105}
106
107static void __init test_pld(void)
108{
109	struct pt_regs regs;
110	unsigned long a = 0x23;
111	int stepped = -1;
112
113	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
114		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
115		return;
116	}
117
118	init_pt_regs(&regs);
119	regs.gpr[3] = (unsigned long)&a;
120
121	/* pld r5, 0(r3), 0 */
122	stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
123
124	if (stepped == 1 && regs.gpr[5] == a)
125		show_result("pld", "PASS");
126	else
127		show_result("pld", "FAIL");
128}
129
130static void __init test_lwz(void)
131{
132	struct pt_regs regs;
133	unsigned int a = 0x4545;
134	int stepped = -1;
135
136	init_pt_regs(&regs);
137	regs.gpr[3] = (unsigned long) &a;
138
139	/* lwz r5, 0(r3) */
140	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
141
142	if (stepped == 1 && regs.gpr[5] == a)
143		show_result("lwz", "PASS");
144	else
145		show_result("lwz", "FAIL");
146}
147
148static void __init test_plwz(void)
149{
150	struct pt_regs regs;
151	unsigned int a = 0x4545;
152	int stepped = -1;
153
154	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
155		show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
156		return;
157	}
158
159	init_pt_regs(&regs);
160	regs.gpr[3] = (unsigned long)&a;
161
162	/* plwz r5, 0(r3), 0 */
163
164	stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
165
166	if (stepped == 1 && regs.gpr[5] == a)
167		show_result("plwz", "PASS");
168	else
169		show_result("plwz", "FAIL");
170}
171
172static void __init test_lwzx(void)
173{
174	struct pt_regs regs;
175	unsigned int a[3] = {0x0, 0x0, 0x1234};
176	int stepped = -1;
177
178	init_pt_regs(&regs);
179	regs.gpr[3] = (unsigned long) a;
180	regs.gpr[4] = 8;
181	regs.gpr[5] = 0x8765;
182
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");
189}
190
191static void __init test_std(void)
192{
193	struct pt_regs regs;
194	unsigned long a = 0x1234;
195	int stepped = -1;
196
197	init_pt_regs(&regs);
198	regs.gpr[3] = (unsigned long) &a;
199	regs.gpr[5] = 0x5678;
200
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");
207}
208
209static void __init test_pstd(void)
210{
211	struct pt_regs regs;
212	unsigned long a = 0x1234;
213	int stepped = -1;
214
215	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
216		show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
217		return;
218	}
219
220	init_pt_regs(&regs);
221	regs.gpr[3] = (unsigned long)&a;
222	regs.gpr[5] = 0x5678;
223
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");
230}
231
232static void __init test_ldarx_stdcx(void)
233{
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 */
238
239	init_pt_regs(&regs);
240	asm volatile("mfcr %0" : "=r"(regs.ccr));
241
242
243	/*** ldarx ***/
244
245	regs.gpr[3] = (unsigned long) &a;
246	regs.gpr[4] = 0;
247	regs.gpr[5] = 0x5678;
248
249	/* ldarx r5, r3, r4, 0 */
250	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
251
252	/*
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.
256	 */
257	if (stepped <= 0 || regs.gpr[5] != 0x1234) {
258		show_result("ldarx / stdcx.", "FAIL (ldarx)");
259		return;
260	}
261
262
263	/*** stdcx. ***/
264
265	regs.gpr[5] = 0x9ABC;
266
267	/* stdcx. r5, r3, r4 */
268	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
269
270	/*
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.
277	 */
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.)");
283}
284
285#ifdef CONFIG_PPC_FPU
286static void __init test_lfsx_stfsx(void)
287{
288	struct pt_regs regs;
289	union {
290		float a;
291		int b;
292	} c;
293	int cached_b;
294	int stepped = -1;
295
296	init_pt_regs(&regs);
297
298
299	/*** lfsx ***/
300
301	c.a = 123.45;
302	cached_b = c.b;
303
304	regs.gpr[3] = (unsigned long) &c.a;
305	regs.gpr[4] = 0;
306
307	/* lfsx frt10, r3, r4 */
308	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
309
310	if (stepped == 1)
311		show_result("lfsx", "PASS");
312	else
313		show_result("lfsx", "FAIL");
314
315
316	/*** stfsx ***/
317
318	c.a = 678.91;
319
320	/* stfsx frs10, r3, r4 */
321	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
322
323	if (stepped == 1 && c.b == cached_b)
324		show_result("stfsx", "PASS");
325	else
326		show_result("stfsx", "FAIL");
327}
328
329static void __init test_plfs_pstfs(void)
330{
331	struct pt_regs regs;
332	union {
333		float a;
334		int b;
335	} c;
336	int cached_b;
337	int stepped = -1;
338
339	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
340		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
341		return;
342	}
343
344	init_pt_regs(&regs);
345
346
347	/*** plfs ***/
348
349	c.a = 123.45;
350	cached_b = c.b;
351
352	regs.gpr[3] = (unsigned long)&c.a;
353
354	/* plfs frt10, 0(r3), 0  */
355	stepped = emulate_step(&regs, TEST_PLFS(10, 3, 0, 0));
356
357	if (stepped == 1)
358		show_result("plfs", "PASS");
359	else
360		show_result("plfs", "FAIL");
361
362
363	/*** pstfs ***/
364
365	c.a = 678.91;
366
367	/* pstfs frs10, 0(r3), 0 */
368	stepped = emulate_step(&regs, TEST_PSTFS(10, 3, 0, 0));
369
370	if (stepped == 1 && c.b == cached_b)
371		show_result("pstfs", "PASS");
372	else
373		show_result("pstfs", "FAIL");
374}
375
376static void __init test_lfdx_stfdx(void)
377{
378	struct pt_regs regs;
379	union {
380		double a;
381		long b;
382	} c;
383	long cached_b;
384	int stepped = -1;
385
386	init_pt_regs(&regs);
387
388
389	/*** lfdx ***/
390
391	c.a = 123456.78;
392	cached_b = c.b;
393
394	regs.gpr[3] = (unsigned long) &c.a;
395	regs.gpr[4] = 0;
396
397	/* lfdx frt10, r3, r4 */
398	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
399
400	if (stepped == 1)
401		show_result("lfdx", "PASS");
402	else
403		show_result("lfdx", "FAIL");
404
405
406	/*** stfdx ***/
407
408	c.a = 987654.32;
409
410	/* stfdx frs10, r3, r4 */
411	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
412
413	if (stepped == 1 && c.b == cached_b)
414		show_result("stfdx", "PASS");
415	else
416		show_result("stfdx", "FAIL");
417}
418
419static void __init test_plfd_pstfd(void)
420{
421	struct pt_regs regs;
422	union {
423		double a;
424		long b;
425	} c;
426	long cached_b;
427	int stepped = -1;
428
429	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
430		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
431		return;
432	}
433
434	init_pt_regs(&regs);
435
436
437	/*** plfd ***/
438
439	c.a = 123456.78;
440	cached_b = c.b;
441
442	regs.gpr[3] = (unsigned long)&c.a;
443
444	/* plfd frt10, 0(r3), 0 */
445	stepped = emulate_step(&regs, TEST_PLFD(10, 3, 0, 0));
446
447	if (stepped == 1)
448		show_result("plfd", "PASS");
449	else
450		show_result("plfd", "FAIL");
451
452
453	/*** pstfd ***/
454
455	c.a = 987654.32;
456
457	/* pstfd frs10, 0(r3), 0 */
458	stepped = emulate_step(&regs, TEST_PSTFD(10, 3, 0, 0));
459
460	if (stepped == 1 && c.b == cached_b)
461		show_result("pstfd", "PASS");
462	else
463		show_result("pstfd", "FAIL");
464}
465#else
466static void __init test_lfsx_stfsx(void)
467{
468	show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
469	show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
470}
471
472static void __init test_plfs_pstfs(void)
473{
474	show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
475	show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
476}
477
478static void __init test_lfdx_stfdx(void)
479{
480	show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
481	show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
482}
483
484static void __init test_plfd_pstfd(void)
485{
486	show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
487	show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
488}
489#endif /* CONFIG_PPC_FPU */
490
491#ifdef CONFIG_ALTIVEC
492static void __init test_lvx_stvx(void)
493{
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;
501
502	init_pt_regs(&regs);
503
504
505	/*** lvx ***/
506
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;
511
512	regs.gpr[3] = (unsigned long) &c.a;
513	regs.gpr[4] = 0;
514
515	/* lvx vrt10, r3, r4 */
516	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
517
518	if (stepped == 1)
519		show_result("lvx", "PASS");
520	else
521		show_result("lvx", "FAIL");
522
523
524	/*** stvx ***/
525
526	c.b[0] = 4987513;
527	c.b[1] = 84313948;
528	c.b[2] = 71;
529	c.b[3] = 498532;
530
531	/* stvx vrs10, r3, r4 */
532	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
533
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");
539}
540#else
541static void __init test_lvx_stvx(void)
542{
543	show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
544	show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
545}
546#endif /* CONFIG_ALTIVEC */
547
548#ifdef CONFIG_VSX
549static void __init test_lxvd2x_stxvd2x(void)
550{
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;
558
559	init_pt_regs(&regs);
560
561
562	/*** lxvd2x ***/
563
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;
568
569	regs.gpr[3] = (unsigned long) &c.a;
570	regs.gpr[4] = 0;
571
572	/* lxvd2x vsr39, r3, r4 */
573	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
574
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");
582	}
583
584
585	/*** stxvd2x ***/
586
587	c.b[0] = 21379463;
588	c.b[1] = 87;
589	c.b[2] = 374234;
590	c.b[3] = 4;
591
592	/* stxvd2x vsr39, r3, r4 */
593	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
594
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");
604	}
605}
606#else
607static void __init test_lxvd2x_stxvd2x(void)
608{
609	show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
610	show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
611}
612#endif /* CONFIG_VSX */
613
614#ifdef CONFIG_VSX
615static void __init test_lxvp_stxvp(void)
616{
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;
624
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;
629	}
630
631	init_pt_regs(&regs);
632
633	/*** lxvp ***/
634
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;
643
644	regs.gpr[4] = (unsigned long)&c[0].a;
645
646	/*
647	 * lxvp XTp,DQ(RA)
648	 * XTp = 32xTX + 2xTp
649	 * let TX=1 Tp=1 RA=4 DQ=0
650	 */
651	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
652
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");
660	}
661
662	/*** stxvp ***/
663
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;
672
673	/*
674	 * stxvp XSp,DQ(RA)
675	 * XSp = 32xSX + 2xSp
676	 * let SX=1 Sp=1 RA=4 DQ=0
677	 */
678	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
679
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");
691	}
692}
693#else
694static void __init test_lxvp_stxvp(void)
695{
696	show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
697	show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
698}
699#endif /* CONFIG_VSX */
700
701#ifdef CONFIG_VSX
702static void __init test_lxvpx_stxvpx(void)
703{
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;
711
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;
716	}
717
718	init_pt_regs(&regs);
719
720	/*** lxvpx ***/
721
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;
730
731	regs.gpr[3] = (unsigned long)&c[0].a;
732	regs.gpr[4] = 0;
733
734	/*
735	 * lxvpx XTp,RA,RB
736	 * XTp = 32xTX + 2xTp
737	 * let TX=1 Tp=1 RA=3 RB=4
738	 */
739	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
740
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");
748	}
749
750	/*** stxvpx ***/
751
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;
760
761	/*
762	 * stxvpx XSp,RA,RB
763	 * XSp = 32xSX + 2xSp
764	 * let SX=1 Sp=1 RA=3 RB=4
765	 */
766	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
767
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");
779	}
780}
781#else
782static void __init test_lxvpx_stxvpx(void)
783{
784	show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
785	show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
786}
787#endif /* CONFIG_VSX */
788
789#ifdef CONFIG_VSX
790static void __init test_plxvp_pstxvp(void)
791{
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;
800
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;
805	}
806
807	/*** plxvp ***/
808
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;
817
818	init_pt_regs(&regs);
819	regs.gpr[3] = (unsigned long)&c[0].a;
820
821	/*
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
825	 */
826	instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
827
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");
836	}
837
838	/*** pstxvp ***/
839
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;
848
849	/*
850	 * pstxvp XSp,D(RA),R
851	 * XSp = 32xSX + 2xSp
852	 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
853	 */
854	instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
855
856	stepped = emulate_step(&regs, instr);
857
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");
869	}
870}
871#else
872static void __init test_plxvp_pstxvp(void)
873{
874	show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
875	show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
876}
877#endif /* CONFIG_VSX */
878
879static void __init run_tests_load_store(void)
880{
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();
898}
899
900struct 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];
909};
910
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)
915
916static struct compute_test compute_tests[] = {
917	{
918		.mnemonic = "nop",
919		.subtests = {
920			{
921				.descr = "R0 = LONG_MAX",
922				.instr = ppc_inst(PPC_RAW_NOP()),
923				.regs = {
924					.gpr[0] = LONG_MAX,
925				}
926			}
927		}
928	},
929	{
930		.mnemonic = "setb",
931		.cpu_feature = CPU_FTR_ARCH_300,
932		.subtests = {
933			{
934				.descr = "BFA = 1, CR = GT",
935				.instr = ppc_inst(PPC_RAW_SETB(20, 1)),
936				.regs = {
937					.ccr = 0x4000000,
938				}
939			},
940			{
941				.descr = "BFA = 4, CR = LT",
942				.instr = ppc_inst(PPC_RAW_SETB(20, 4)),
943				.regs = {
944					.ccr = 0x8000,
945				}
946			},
947			{
948				.descr = "BFA = 5, CR = EQ",
949				.instr = ppc_inst(PPC_RAW_SETB(20, 5)),
950				.regs = {
951					.ccr = 0x200,
952				}
953			}
954		}
955	},
956	{
957		.mnemonic = "add",
958		.subtests = {
959			{
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,
965				}
966			},
967			{
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,
973				}
974			},
975			{
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,
981				}
982			},
983			{
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,
989				}
990			},
991			{
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,
997				}
998			},
999			{
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,
1005				}
1006			},
1007			{
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,
1013				}
1014			},
1015			{
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,
1021				}
1022			},
1023			{
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,
1029				}
1030			},
1031			{
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,
1037				}
1038			}
1039		}
1040	},
1041	{
1042		.mnemonic = "add.",
1043		.subtests = {
1044			{
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,
1051				}
1052			},
1053			{
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,
1059				}
1060			},
1061			{
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,
1068				}
1069			},
1070			{
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,
1076				}
1077			},
1078			{
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,
1084				}
1085			},
1086			{
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,
1092				}
1093			},
1094			{
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,
1100				}
1101			},
1102			{
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,
1108				}
1109			},
1110			{
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,
1116				}
1117			},
1118			{
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,
1124				}
1125			}
1126		}
1127	},
1128	{
1129		.mnemonic = "addc",
1130		.subtests = {
1131			{
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,
1137				}
1138			},
1139			{
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,
1145				}
1146			},
1147			{
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,
1153				}
1154			},
1155			{
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,
1161				}
1162			},
1163			{
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,
1169				}
1170			},
1171			{
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,
1177				}
1178			},
1179			{
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,
1185				}
1186			},
1187			{
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,
1193				}
1194			},
1195			{
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,
1201				}
1202			},
1203			{
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,
1209				}
1210			},
1211			{
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,
1217				}
1218			}
1219		}
1220	},
1221	{
1222		.mnemonic = "addc.",
1223		.subtests = {
1224			{
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,
1231				}
1232			},
1233			{
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,
1239				}
1240			},
1241			{
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,
1248				}
1249			},
1250			{
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,
1256				}
1257			},
1258			{
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,
1264				}
1265			},
1266			{
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,
1272				}
1273			},
1274			{
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,
1280				}
1281			},
1282			{
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,
1288				}
1289			},
1290			{
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,
1296				}
1297			},
1298			{
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,
1304				}
1305			},
1306			{
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,
1312				}
1313			}
1314		}
1315	},
1316	{
1317		.mnemonic = "divde",
1318		.subtests = {
1319			{
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,
1325				}
1326			},
1327			{
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,
1334				}
1335			},
1336			{
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,
1342				}
1343			}
1344		}
1345	},
1346	{
1347		.mnemonic = "divde.",
1348		.subtests = {
1349			{
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,
1355				}
1356			},
1357			{
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,
1364				}
1365			},
1366			{
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,
1372				}
1373			}
1374		}
1375	},
1376	{
1377		.mnemonic = "divdeu",
1378		.subtests = {
1379			{
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,
1386				}
1387			},
1388			{
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,
1395				}
1396			},
1397			{
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,
1403				}
1404			},
1405			{
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,
1411				}
1412			},
1413			{
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,
1420				}
1421			}
1422		}
1423	},
1424	{
1425		.mnemonic = "divdeu.",
1426		.subtests = {
1427			{
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,
1434				}
1435			},
1436			{
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,
1443				}
1444			},
1445			{
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,
1451				}
1452			},
1453			{
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,
1459				}
1460			},
1461			{
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,
1468				}
1469			}
1470		}
1471	},
1472	{
1473		.mnemonic = "paddi",
1474		.cpu_feature = CPU_FTR_ARCH_31,
1475		.subtests = {
1476			{
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,
1482				}
1483			},
1484			{
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,
1490				}
1491			},
1492			{
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,
1498				}
1499			},
1500			{
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,
1506				}
1507			},
1508			{
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,
1514				}
1515			},
1516			{
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,
1522				}
1523			},
1524			{
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,
1530				}
1531			},
1532			{
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,
1538				}
1539			},
1540			{
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,
1546				}
1547			},
1548			{
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,
1554				}
1555			},
1556			{
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,
1561				}
1562			},
1563			{
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,
1569				}
1570			},
1571			{
1572				.descr = "RA is r0, SI = 0, R = 1",
1573				.instr = TEST_PADDI(21, 0, 0, 1),
1574				.regs = {
1575					.gpr[21] = 0,
1576				}
1577			},
1578			{
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,
1583				}
1584			},
1585			/* Invalid instruction form with R = 1 and RA != 0 */
1586			{
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,
1593				}
1594			}
1595		}
1596	}
1597};
1598
1599static int __init emulate_compute_instr(struct pt_regs *regs,
1600					ppc_inst_t instr,
1601					bool negative)
1602{
1603	int analysed;
1604	struct instruction_op op;
1605
1606	if (!regs || !ppc_inst_val(instr))
1607		return -EINVAL;
1608
1609	/* This is not a return frame regs */
1610	regs->nip = patch_site_addr(&patch__exec_instr);
1611
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;
1618	}
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;
1624}
1625
1626static int __init execute_compute_instr(struct pt_regs *regs,
1627					ppc_inst_t instr)
1628{
1629	extern int exec_instr(struct pt_regs *regs);
1630
1631	if (!regs || !ppc_inst_val(instr))
1632		return -EINVAL;
1633
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;
1639	}
1640
1641	return 0;
1642}
1643
1644#define gpr_mismatch(gprn, exp, got)	\
1645	pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
1646		gprn, exp, got)
1647
1648#define reg_mismatch(name, exp, got)	\
1649	pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
1650		name, exp, got)
1651
1652static void __init run_tests_compute(void)
1653{
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;
1660
1661	for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1662		test = &compute_tests[i];
1663
1664		if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1665			show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1666			continue;
1667		}
1668
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;
1677
1678			memcpy(&exp, regs, sizeof(struct pt_regs));
1679			memcpy(&got, regs, sizeof(struct pt_regs));
1680
1681			/*
1682			 * Set a compatible MSR value explicitly to ensure
1683			 * that XER and CR bits are updated appropriately
1684			 */
1685			exp.msr = MSR_KERNEL;
1686			got.msr = MSR_KERNEL;
1687
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;
1696			}
1697
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]);
1704				}
1705			}
1706
1707			/* Verify LR value */
1708			if (exp.link != got.link) {
1709				passed = false;
1710				reg_mismatch("LR", exp.link, got.link);
1711			}
1712
1713			/* Verify XER value */
1714			if (!ignore_xer && exp.xer != got.xer) {
1715				passed = false;
1716				reg_mismatch("XER", exp.xer, got.xer);
1717			}
1718
1719			/* Verify CR value */
1720			if (!ignore_ccr && exp.ccr != got.ccr) {
1721				passed = false;
1722				reg_mismatch("CR", exp.ccr, got.ccr);
1723			}
1724
1725print:
1726			show_result_with_descr(test->mnemonic,
1727					       test->subtests[j].descr,
1728					       passed ? "PASS" : "FAIL");
1729		}
1730	}
1731}
1732
1733static int __init test_emulate_step(void)
1734{
1735	printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1736	run_tests_load_store();
1737	run_tests_compute();
1738
1739	return 0;
1740}
1741late_initcall(test_emulate_step);
1742