xref: /openbmc/linux/arch/powerpc/lib/test_emulate_step.c (revision b6b54b42722a2393056c891c0d05cd8cc40eb776)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24ceae137SRavi Bangoria /*
384022ac1SSandipan Das  * Simple sanity tests for instruction emulation infrastructure.
44ceae137SRavi Bangoria  *
54ceae137SRavi Bangoria  * Copyright IBM Corp. 2016
64ceae137SRavi Bangoria  */
74ceae137SRavi Bangoria 
84ceae137SRavi Bangoria #define pr_fmt(fmt) "emulate_step_test: " fmt
94ceae137SRavi Bangoria 
104ceae137SRavi Bangoria #include <linux/ptrace.h>
114ceae137SRavi Bangoria #include <asm/sstep.h>
124ceae137SRavi Bangoria #include <asm/ppc-opcode.h>
1384022ac1SSandipan Das #include <asm/code-patching.h>
1475346251SJordan Niethe #include <asm/inst.h>
154ceae137SRavi Bangoria 
1684022ac1SSandipan Das #define MAX_SUBTESTS	16
1784022ac1SSandipan Das 
1884022ac1SSandipan Das #define IGNORE_GPR(n)	(0x1UL << (n))
1984022ac1SSandipan Das #define IGNORE_XER	(0x1UL << 32)
2084022ac1SSandipan Das #define IGNORE_CCR	(0x1UL << 33)
214ceae137SRavi Bangoria 
22*b6b54b42SJordan Niethe #define TEST_PLD(r, base, i, pr) \
23*b6b54b42SJordan Niethe 	ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
24*b6b54b42SJordan Niethe 			PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
25*b6b54b42SJordan Niethe 
26*b6b54b42SJordan Niethe #define TEST_PLWZ(r, base, i, pr) \
27*b6b54b42SJordan Niethe 	ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
28*b6b54b42SJordan Niethe 			PPC_RAW_LWZ(r, base, i))
29*b6b54b42SJordan Niethe 
30*b6b54b42SJordan Niethe #define TEST_PSTD(r, base, i, pr) \
31*b6b54b42SJordan Niethe 	ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
32*b6b54b42SJordan Niethe 			PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
33*b6b54b42SJordan Niethe 
344ceae137SRavi Bangoria static void __init init_pt_regs(struct pt_regs *regs)
354ceae137SRavi Bangoria {
364ceae137SRavi Bangoria 	static unsigned long msr;
374ceae137SRavi Bangoria 	static bool msr_cached;
384ceae137SRavi Bangoria 
394ceae137SRavi Bangoria 	memset(regs, 0, sizeof(struct pt_regs));
404ceae137SRavi Bangoria 
414ceae137SRavi Bangoria 	if (likely(msr_cached)) {
424ceae137SRavi Bangoria 		regs->msr = msr;
434ceae137SRavi Bangoria 		return;
444ceae137SRavi Bangoria 	}
454ceae137SRavi Bangoria 
464ceae137SRavi Bangoria 	asm volatile("mfmsr %0" : "=r"(regs->msr));
474ceae137SRavi Bangoria 
484ceae137SRavi Bangoria 	regs->msr |= MSR_FP;
494ceae137SRavi Bangoria 	regs->msr |= MSR_VEC;
504ceae137SRavi Bangoria 	regs->msr |= MSR_VSX;
514ceae137SRavi Bangoria 
524ceae137SRavi Bangoria 	msr = regs->msr;
534ceae137SRavi Bangoria 	msr_cached = true;
544ceae137SRavi Bangoria }
554ceae137SRavi Bangoria 
5684022ac1SSandipan Das static void __init show_result(char *mnemonic, char *result)
574ceae137SRavi Bangoria {
5884022ac1SSandipan Das 	pr_info("%-14s : %s\n", mnemonic, result);
5984022ac1SSandipan Das }
6084022ac1SSandipan Das 
6184022ac1SSandipan Das static void __init show_result_with_descr(char *mnemonic, char *descr,
6284022ac1SSandipan Das 					  char *result)
6384022ac1SSandipan Das {
6484022ac1SSandipan Das 	pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
654ceae137SRavi Bangoria }
664ceae137SRavi Bangoria 
674ceae137SRavi Bangoria static void __init test_ld(void)
684ceae137SRavi Bangoria {
694ceae137SRavi Bangoria 	struct pt_regs regs;
704ceae137SRavi Bangoria 	unsigned long a = 0x23;
714ceae137SRavi Bangoria 	int stepped = -1;
724ceae137SRavi Bangoria 
734ceae137SRavi Bangoria 	init_pt_regs(&regs);
744ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
754ceae137SRavi Bangoria 
764ceae137SRavi Bangoria 	/* ld r5, 0(r3) */
771d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
784ceae137SRavi Bangoria 
794ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a)
804ceae137SRavi Bangoria 		show_result("ld", "PASS");
814ceae137SRavi Bangoria 	else
824ceae137SRavi Bangoria 		show_result("ld", "FAIL");
834ceae137SRavi Bangoria }
844ceae137SRavi Bangoria 
85*b6b54b42SJordan Niethe static void __init test_pld(void)
86*b6b54b42SJordan Niethe {
87*b6b54b42SJordan Niethe 	struct pt_regs regs;
88*b6b54b42SJordan Niethe 	unsigned long a = 0x23;
89*b6b54b42SJordan Niethe 	int stepped = -1;
90*b6b54b42SJordan Niethe 
91*b6b54b42SJordan Niethe 	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
92*b6b54b42SJordan Niethe 		show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
93*b6b54b42SJordan Niethe 		return;
94*b6b54b42SJordan Niethe 	}
95*b6b54b42SJordan Niethe 
96*b6b54b42SJordan Niethe 	init_pt_regs(&regs);
97*b6b54b42SJordan Niethe 	regs.gpr[3] = (unsigned long)&a;
98*b6b54b42SJordan Niethe 
99*b6b54b42SJordan Niethe 	/* pld r5, 0(r3), 0 */
100*b6b54b42SJordan Niethe 	stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
101*b6b54b42SJordan Niethe 
102*b6b54b42SJordan Niethe 	if (stepped == 1 && regs.gpr[5] == a)
103*b6b54b42SJordan Niethe 		show_result("pld", "PASS");
104*b6b54b42SJordan Niethe 	else
105*b6b54b42SJordan Niethe 		show_result("pld", "FAIL");
106*b6b54b42SJordan Niethe }
107*b6b54b42SJordan Niethe 
1084ceae137SRavi Bangoria static void __init test_lwz(void)
1094ceae137SRavi Bangoria {
1104ceae137SRavi Bangoria 	struct pt_regs regs;
1114ceae137SRavi Bangoria 	unsigned int a = 0x4545;
1124ceae137SRavi Bangoria 	int stepped = -1;
1134ceae137SRavi Bangoria 
1144ceae137SRavi Bangoria 	init_pt_regs(&regs);
1154ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
1164ceae137SRavi Bangoria 
1174ceae137SRavi Bangoria 	/* lwz r5, 0(r3) */
1181d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
1194ceae137SRavi Bangoria 
1204ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a)
1214ceae137SRavi Bangoria 		show_result("lwz", "PASS");
1224ceae137SRavi Bangoria 	else
1234ceae137SRavi Bangoria 		show_result("lwz", "FAIL");
1244ceae137SRavi Bangoria }
1254ceae137SRavi Bangoria 
126*b6b54b42SJordan Niethe static void __init test_plwz(void)
127*b6b54b42SJordan Niethe {
128*b6b54b42SJordan Niethe 	struct pt_regs regs;
129*b6b54b42SJordan Niethe 	unsigned int a = 0x4545;
130*b6b54b42SJordan Niethe 	int stepped = -1;
131*b6b54b42SJordan Niethe 
132*b6b54b42SJordan Niethe 	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
133*b6b54b42SJordan Niethe 		show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
134*b6b54b42SJordan Niethe 		return;
135*b6b54b42SJordan Niethe 	}
136*b6b54b42SJordan Niethe 
137*b6b54b42SJordan Niethe 	init_pt_regs(&regs);
138*b6b54b42SJordan Niethe 	regs.gpr[3] = (unsigned long)&a;
139*b6b54b42SJordan Niethe 
140*b6b54b42SJordan Niethe 	/* plwz r5, 0(r3), 0 */
141*b6b54b42SJordan Niethe 
142*b6b54b42SJordan Niethe 	stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
143*b6b54b42SJordan Niethe 
144*b6b54b42SJordan Niethe 	if (stepped == 1 && regs.gpr[5] == a)
145*b6b54b42SJordan Niethe 		show_result("plwz", "PASS");
146*b6b54b42SJordan Niethe 	else
147*b6b54b42SJordan Niethe 		show_result("plwz", "FAIL");
148*b6b54b42SJordan Niethe }
149*b6b54b42SJordan Niethe 
1504ceae137SRavi Bangoria static void __init test_lwzx(void)
1514ceae137SRavi Bangoria {
1524ceae137SRavi Bangoria 	struct pt_regs regs;
1534ceae137SRavi Bangoria 	unsigned int a[3] = {0x0, 0x0, 0x1234};
1544ceae137SRavi Bangoria 	int stepped = -1;
1554ceae137SRavi Bangoria 
1564ceae137SRavi Bangoria 	init_pt_regs(&regs);
1574ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) a;
1584ceae137SRavi Bangoria 	regs.gpr[4] = 8;
1594ceae137SRavi Bangoria 	regs.gpr[5] = 0x8765;
1604ceae137SRavi Bangoria 
1614ceae137SRavi Bangoria 	/* lwzx r5, r3, r4 */
1621d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
1634ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a[2])
1644ceae137SRavi Bangoria 		show_result("lwzx", "PASS");
1654ceae137SRavi Bangoria 	else
1664ceae137SRavi Bangoria 		show_result("lwzx", "FAIL");
1674ceae137SRavi Bangoria }
1684ceae137SRavi Bangoria 
1694ceae137SRavi Bangoria static void __init test_std(void)
1704ceae137SRavi Bangoria {
1714ceae137SRavi Bangoria 	struct pt_regs regs;
1724ceae137SRavi Bangoria 	unsigned long a = 0x1234;
1734ceae137SRavi Bangoria 	int stepped = -1;
1744ceae137SRavi Bangoria 
1754ceae137SRavi Bangoria 	init_pt_regs(&regs);
1764ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
1774ceae137SRavi Bangoria 	regs.gpr[5] = 0x5678;
1784ceae137SRavi Bangoria 
1794ceae137SRavi Bangoria 	/* std r5, 0(r3) */
1801d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
18159ed2adfSNicholas Piggin 	if (stepped == 1 && regs.gpr[5] == a)
1824ceae137SRavi Bangoria 		show_result("std", "PASS");
1834ceae137SRavi Bangoria 	else
1844ceae137SRavi Bangoria 		show_result("std", "FAIL");
1854ceae137SRavi Bangoria }
1864ceae137SRavi Bangoria 
187*b6b54b42SJordan Niethe static void __init test_pstd(void)
188*b6b54b42SJordan Niethe {
189*b6b54b42SJordan Niethe 	struct pt_regs regs;
190*b6b54b42SJordan Niethe 	unsigned long a = 0x1234;
191*b6b54b42SJordan Niethe 	int stepped = -1;
192*b6b54b42SJordan Niethe 
193*b6b54b42SJordan Niethe 	if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
194*b6b54b42SJordan Niethe 		show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
195*b6b54b42SJordan Niethe 		return;
196*b6b54b42SJordan Niethe 	}
197*b6b54b42SJordan Niethe 
198*b6b54b42SJordan Niethe 	init_pt_regs(&regs);
199*b6b54b42SJordan Niethe 	regs.gpr[3] = (unsigned long)&a;
200*b6b54b42SJordan Niethe 	regs.gpr[5] = 0x5678;
201*b6b54b42SJordan Niethe 
202*b6b54b42SJordan Niethe 	/* pstd r5, 0(r3), 0 */
203*b6b54b42SJordan Niethe 	stepped = emulate_step(&regs, TEST_PSTD(5, 3, 0, 0));
204*b6b54b42SJordan Niethe 	if (stepped == 1 || regs.gpr[5] == a)
205*b6b54b42SJordan Niethe 		show_result("pstd", "PASS");
206*b6b54b42SJordan Niethe 	else
207*b6b54b42SJordan Niethe 		show_result("pstd", "FAIL");
208*b6b54b42SJordan Niethe }
209*b6b54b42SJordan Niethe 
2104ceae137SRavi Bangoria static void __init test_ldarx_stdcx(void)
2114ceae137SRavi Bangoria {
2124ceae137SRavi Bangoria 	struct pt_regs regs;
2134ceae137SRavi Bangoria 	unsigned long a = 0x1234;
2144ceae137SRavi Bangoria 	int stepped = -1;
2154ceae137SRavi Bangoria 	unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
2164ceae137SRavi Bangoria 
2174ceae137SRavi Bangoria 	init_pt_regs(&regs);
2184ceae137SRavi Bangoria 	asm volatile("mfcr %0" : "=r"(regs.ccr));
2194ceae137SRavi Bangoria 
2204ceae137SRavi Bangoria 
2214ceae137SRavi Bangoria 	/*** ldarx ***/
2224ceae137SRavi Bangoria 
2234ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
2244ceae137SRavi Bangoria 	regs.gpr[4] = 0;
2254ceae137SRavi Bangoria 	regs.gpr[5] = 0x5678;
2264ceae137SRavi Bangoria 
2274ceae137SRavi Bangoria 	/* ldarx r5, r3, r4, 0 */
2281d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
2294ceae137SRavi Bangoria 
2304ceae137SRavi Bangoria 	/*
2314ceae137SRavi Bangoria 	 * Don't touch 'a' here. Touching 'a' can do Load/store
2324ceae137SRavi Bangoria 	 * of 'a' which result in failure of subsequent stdcx.
2334ceae137SRavi Bangoria 	 * Instead, use hardcoded value for comparison.
2344ceae137SRavi Bangoria 	 */
2354ceae137SRavi Bangoria 	if (stepped <= 0 || regs.gpr[5] != 0x1234) {
2364ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "FAIL (ldarx)");
2374ceae137SRavi Bangoria 		return;
2384ceae137SRavi Bangoria 	}
2394ceae137SRavi Bangoria 
2404ceae137SRavi Bangoria 
2414ceae137SRavi Bangoria 	/*** stdcx. ***/
2424ceae137SRavi Bangoria 
2434ceae137SRavi Bangoria 	regs.gpr[5] = 0x9ABC;
2444ceae137SRavi Bangoria 
2454ceae137SRavi Bangoria 	/* stdcx. r5, r3, r4 */
2461d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
2474ceae137SRavi Bangoria 
2484ceae137SRavi Bangoria 	/*
2494ceae137SRavi Bangoria 	 * Two possible scenarios that indicates successful emulation
2504ceae137SRavi Bangoria 	 * of stdcx. :
2514ceae137SRavi Bangoria 	 *  1. Reservation is active and store is performed. In this
2524ceae137SRavi Bangoria 	 *     case cr0.eq bit will be set to 1.
2534ceae137SRavi Bangoria 	 *  2. Reservation is not active and store is not performed.
2544ceae137SRavi Bangoria 	 *     In this case cr0.eq bit will be set to 0.
2554ceae137SRavi Bangoria 	 */
2564ceae137SRavi Bangoria 	if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
2574ceae137SRavi Bangoria 			|| (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
2584ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "PASS");
2594ceae137SRavi Bangoria 	else
2604ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "FAIL (stdcx.)");
2614ceae137SRavi Bangoria }
2624ceae137SRavi Bangoria 
2634ceae137SRavi Bangoria #ifdef CONFIG_PPC_FPU
2644ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void)
2654ceae137SRavi Bangoria {
2664ceae137SRavi Bangoria 	struct pt_regs regs;
2674ceae137SRavi Bangoria 	union {
2684ceae137SRavi Bangoria 		float a;
2694ceae137SRavi Bangoria 		int b;
2704ceae137SRavi Bangoria 	} c;
2714ceae137SRavi Bangoria 	int cached_b;
2724ceae137SRavi Bangoria 	int stepped = -1;
2734ceae137SRavi Bangoria 
2744ceae137SRavi Bangoria 	init_pt_regs(&regs);
2754ceae137SRavi Bangoria 
2764ceae137SRavi Bangoria 
2774ceae137SRavi Bangoria 	/*** lfsx ***/
2784ceae137SRavi Bangoria 
2794ceae137SRavi Bangoria 	c.a = 123.45;
2804ceae137SRavi Bangoria 	cached_b = c.b;
2814ceae137SRavi Bangoria 
2824ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
2834ceae137SRavi Bangoria 	regs.gpr[4] = 0;
2844ceae137SRavi Bangoria 
2854ceae137SRavi Bangoria 	/* lfsx frt10, r3, r4 */
2861d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
2874ceae137SRavi Bangoria 
2884ceae137SRavi Bangoria 	if (stepped == 1)
2894ceae137SRavi Bangoria 		show_result("lfsx", "PASS");
2904ceae137SRavi Bangoria 	else
2914ceae137SRavi Bangoria 		show_result("lfsx", "FAIL");
2924ceae137SRavi Bangoria 
2934ceae137SRavi Bangoria 
2944ceae137SRavi Bangoria 	/*** stfsx ***/
2954ceae137SRavi Bangoria 
2964ceae137SRavi Bangoria 	c.a = 678.91;
2974ceae137SRavi Bangoria 
2984ceae137SRavi Bangoria 	/* stfsx frs10, r3, r4 */
2991d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
3004ceae137SRavi Bangoria 
3014ceae137SRavi Bangoria 	if (stepped == 1 && c.b == cached_b)
3024ceae137SRavi Bangoria 		show_result("stfsx", "PASS");
3034ceae137SRavi Bangoria 	else
3044ceae137SRavi Bangoria 		show_result("stfsx", "FAIL");
3054ceae137SRavi Bangoria }
3064ceae137SRavi Bangoria 
3074ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void)
3084ceae137SRavi Bangoria {
3094ceae137SRavi Bangoria 	struct pt_regs regs;
3104ceae137SRavi Bangoria 	union {
3114ceae137SRavi Bangoria 		double a;
3124ceae137SRavi Bangoria 		long b;
3134ceae137SRavi Bangoria 	} c;
3144ceae137SRavi Bangoria 	long cached_b;
3154ceae137SRavi Bangoria 	int stepped = -1;
3164ceae137SRavi Bangoria 
3174ceae137SRavi Bangoria 	init_pt_regs(&regs);
3184ceae137SRavi Bangoria 
3194ceae137SRavi Bangoria 
3204ceae137SRavi Bangoria 	/*** lfdx ***/
3214ceae137SRavi Bangoria 
3224ceae137SRavi Bangoria 	c.a = 123456.78;
3234ceae137SRavi Bangoria 	cached_b = c.b;
3244ceae137SRavi Bangoria 
3254ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
3264ceae137SRavi Bangoria 	regs.gpr[4] = 0;
3274ceae137SRavi Bangoria 
3284ceae137SRavi Bangoria 	/* lfdx frt10, r3, r4 */
3291d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
3304ceae137SRavi Bangoria 
3314ceae137SRavi Bangoria 	if (stepped == 1)
3324ceae137SRavi Bangoria 		show_result("lfdx", "PASS");
3334ceae137SRavi Bangoria 	else
3344ceae137SRavi Bangoria 		show_result("lfdx", "FAIL");
3354ceae137SRavi Bangoria 
3364ceae137SRavi Bangoria 
3374ceae137SRavi Bangoria 	/*** stfdx ***/
3384ceae137SRavi Bangoria 
3394ceae137SRavi Bangoria 	c.a = 987654.32;
3404ceae137SRavi Bangoria 
3414ceae137SRavi Bangoria 	/* stfdx frs10, r3, r4 */
3421d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
3434ceae137SRavi Bangoria 
3444ceae137SRavi Bangoria 	if (stepped == 1 && c.b == cached_b)
3454ceae137SRavi Bangoria 		show_result("stfdx", "PASS");
3464ceae137SRavi Bangoria 	else
3474ceae137SRavi Bangoria 		show_result("stfdx", "FAIL");
3484ceae137SRavi Bangoria }
3494ceae137SRavi Bangoria #else
3504ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void)
3514ceae137SRavi Bangoria {
3524ceae137SRavi Bangoria 	show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
3534ceae137SRavi Bangoria 	show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
3544ceae137SRavi Bangoria }
3554ceae137SRavi Bangoria 
3564ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void)
3574ceae137SRavi Bangoria {
3584ceae137SRavi Bangoria 	show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
3594ceae137SRavi Bangoria 	show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
3604ceae137SRavi Bangoria }
3614ceae137SRavi Bangoria #endif /* CONFIG_PPC_FPU */
3624ceae137SRavi Bangoria 
3634ceae137SRavi Bangoria #ifdef CONFIG_ALTIVEC
3644ceae137SRavi Bangoria static void __init test_lvx_stvx(void)
3654ceae137SRavi Bangoria {
3664ceae137SRavi Bangoria 	struct pt_regs regs;
3674ceae137SRavi Bangoria 	union {
3684ceae137SRavi Bangoria 		vector128 a;
3694ceae137SRavi Bangoria 		u32 b[4];
3704ceae137SRavi Bangoria 	} c;
3714ceae137SRavi Bangoria 	u32 cached_b[4];
3724ceae137SRavi Bangoria 	int stepped = -1;
3734ceae137SRavi Bangoria 
3744ceae137SRavi Bangoria 	init_pt_regs(&regs);
3754ceae137SRavi Bangoria 
3764ceae137SRavi Bangoria 
3774ceae137SRavi Bangoria 	/*** lvx ***/
3784ceae137SRavi Bangoria 
3794ceae137SRavi Bangoria 	cached_b[0] = c.b[0] = 923745;
3804ceae137SRavi Bangoria 	cached_b[1] = c.b[1] = 2139478;
3814ceae137SRavi Bangoria 	cached_b[2] = c.b[2] = 9012;
3824ceae137SRavi Bangoria 	cached_b[3] = c.b[3] = 982134;
3834ceae137SRavi Bangoria 
3844ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
3854ceae137SRavi Bangoria 	regs.gpr[4] = 0;
3864ceae137SRavi Bangoria 
3874ceae137SRavi Bangoria 	/* lvx vrt10, r3, r4 */
3881d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
3894ceae137SRavi Bangoria 
3904ceae137SRavi Bangoria 	if (stepped == 1)
3914ceae137SRavi Bangoria 		show_result("lvx", "PASS");
3924ceae137SRavi Bangoria 	else
3934ceae137SRavi Bangoria 		show_result("lvx", "FAIL");
3944ceae137SRavi Bangoria 
3954ceae137SRavi Bangoria 
3964ceae137SRavi Bangoria 	/*** stvx ***/
3974ceae137SRavi Bangoria 
3984ceae137SRavi Bangoria 	c.b[0] = 4987513;
3994ceae137SRavi Bangoria 	c.b[1] = 84313948;
4004ceae137SRavi Bangoria 	c.b[2] = 71;
4014ceae137SRavi Bangoria 	c.b[3] = 498532;
4024ceae137SRavi Bangoria 
4034ceae137SRavi Bangoria 	/* stvx vrs10, r3, r4 */
4041d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
4054ceae137SRavi Bangoria 
4064ceae137SRavi Bangoria 	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
4074ceae137SRavi Bangoria 	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
4084ceae137SRavi Bangoria 		show_result("stvx", "PASS");
4094ceae137SRavi Bangoria 	else
4104ceae137SRavi Bangoria 		show_result("stvx", "FAIL");
4114ceae137SRavi Bangoria }
4124ceae137SRavi Bangoria #else
4134ceae137SRavi Bangoria static void __init test_lvx_stvx(void)
4144ceae137SRavi Bangoria {
4154ceae137SRavi Bangoria 	show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
4164ceae137SRavi Bangoria 	show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
4174ceae137SRavi Bangoria }
4184ceae137SRavi Bangoria #endif /* CONFIG_ALTIVEC */
4194ceae137SRavi Bangoria 
4204ceae137SRavi Bangoria #ifdef CONFIG_VSX
4214ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void)
4224ceae137SRavi Bangoria {
4234ceae137SRavi Bangoria 	struct pt_regs regs;
4244ceae137SRavi Bangoria 	union {
4254ceae137SRavi Bangoria 		vector128 a;
4264ceae137SRavi Bangoria 		u32 b[4];
4274ceae137SRavi Bangoria 	} c;
4284ceae137SRavi Bangoria 	u32 cached_b[4];
4294ceae137SRavi Bangoria 	int stepped = -1;
4304ceae137SRavi Bangoria 
4314ceae137SRavi Bangoria 	init_pt_regs(&regs);
4324ceae137SRavi Bangoria 
4334ceae137SRavi Bangoria 
4344ceae137SRavi Bangoria 	/*** lxvd2x ***/
4354ceae137SRavi Bangoria 
4364ceae137SRavi Bangoria 	cached_b[0] = c.b[0] = 18233;
4374ceae137SRavi Bangoria 	cached_b[1] = c.b[1] = 34863571;
4384ceae137SRavi Bangoria 	cached_b[2] = c.b[2] = 834;
4394ceae137SRavi Bangoria 	cached_b[3] = c.b[3] = 6138911;
4404ceae137SRavi Bangoria 
4414ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
4424ceae137SRavi Bangoria 	regs.gpr[4] = 0;
4434ceae137SRavi Bangoria 
4444ceae137SRavi Bangoria 	/* lxvd2x vsr39, r3, r4 */
4451d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
4464ceae137SRavi Bangoria 
4475a61640eSRavi Bangoria 	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
4484ceae137SRavi Bangoria 		show_result("lxvd2x", "PASS");
4495a61640eSRavi Bangoria 	} else {
4505a61640eSRavi Bangoria 		if (!cpu_has_feature(CPU_FTR_VSX))
4515a61640eSRavi Bangoria 			show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
4524ceae137SRavi Bangoria 		else
4534ceae137SRavi Bangoria 			show_result("lxvd2x", "FAIL");
4545a61640eSRavi Bangoria 	}
4554ceae137SRavi Bangoria 
4564ceae137SRavi Bangoria 
4574ceae137SRavi Bangoria 	/*** stxvd2x ***/
4584ceae137SRavi Bangoria 
4594ceae137SRavi Bangoria 	c.b[0] = 21379463;
4604ceae137SRavi Bangoria 	c.b[1] = 87;
4614ceae137SRavi Bangoria 	c.b[2] = 374234;
4624ceae137SRavi Bangoria 	c.b[3] = 4;
4634ceae137SRavi Bangoria 
4644ceae137SRavi Bangoria 	/* stxvd2x vsr39, r3, r4 */
4651d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
4664ceae137SRavi Bangoria 
4674ceae137SRavi Bangoria 	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
4685a61640eSRavi Bangoria 	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
4695a61640eSRavi Bangoria 	    cpu_has_feature(CPU_FTR_VSX)) {
4704ceae137SRavi Bangoria 		show_result("stxvd2x", "PASS");
4715a61640eSRavi Bangoria 	} else {
4725a61640eSRavi Bangoria 		if (!cpu_has_feature(CPU_FTR_VSX))
4735a61640eSRavi Bangoria 			show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
4744ceae137SRavi Bangoria 		else
4754ceae137SRavi Bangoria 			show_result("stxvd2x", "FAIL");
4764ceae137SRavi Bangoria 	}
4775a61640eSRavi Bangoria }
4784ceae137SRavi Bangoria #else
4794ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void)
4804ceae137SRavi Bangoria {
4814ceae137SRavi Bangoria 	show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
4824ceae137SRavi Bangoria 	show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
4834ceae137SRavi Bangoria }
4844ceae137SRavi Bangoria #endif /* CONFIG_VSX */
4854ceae137SRavi Bangoria 
48684022ac1SSandipan Das static void __init run_tests_load_store(void)
4874ceae137SRavi Bangoria {
4884ceae137SRavi Bangoria 	test_ld();
489*b6b54b42SJordan Niethe 	test_pld();
4904ceae137SRavi Bangoria 	test_lwz();
491*b6b54b42SJordan Niethe 	test_plwz();
4924ceae137SRavi Bangoria 	test_lwzx();
4934ceae137SRavi Bangoria 	test_std();
494*b6b54b42SJordan Niethe 	test_pstd();
4954ceae137SRavi Bangoria 	test_ldarx_stdcx();
4964ceae137SRavi Bangoria 	test_lfsx_stfsx();
4974ceae137SRavi Bangoria 	test_lfdx_stfdx();
4984ceae137SRavi Bangoria 	test_lvx_stvx();
4994ceae137SRavi Bangoria 	test_lxvd2x_stxvd2x();
50084022ac1SSandipan Das }
50184022ac1SSandipan Das 
50284022ac1SSandipan Das struct compute_test {
50384022ac1SSandipan Das 	char *mnemonic;
50484022ac1SSandipan Das 	struct {
50584022ac1SSandipan Das 		char *descr;
50684022ac1SSandipan Das 		unsigned long flags;
50794afd069SJordan Niethe 		struct ppc_inst instr;
50884022ac1SSandipan Das 		struct pt_regs regs;
50984022ac1SSandipan Das 	} subtests[MAX_SUBTESTS + 1];
51084022ac1SSandipan Das };
51184022ac1SSandipan Das 
51284022ac1SSandipan Das static struct compute_test compute_tests[] = {
51384022ac1SSandipan Das 	{
51484022ac1SSandipan Das 		.mnemonic = "nop",
51584022ac1SSandipan Das 		.subtests = {
51684022ac1SSandipan Das 			{
51784022ac1SSandipan Das 				.descr = "R0 = LONG_MAX",
51875346251SJordan Niethe 				.instr = ppc_inst(PPC_INST_NOP),
51984022ac1SSandipan Das 				.regs = {
52084022ac1SSandipan Das 					.gpr[0] = LONG_MAX,
52184022ac1SSandipan Das 				}
52284022ac1SSandipan Das 			}
52384022ac1SSandipan Das 		}
52444dea178SSandipan Das 	},
52544dea178SSandipan Das 	{
52644dea178SSandipan Das 		.mnemonic = "add",
52744dea178SSandipan Das 		.subtests = {
52844dea178SSandipan Das 			{
52944dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
5301d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
53144dea178SSandipan Das 				.regs = {
53244dea178SSandipan Das 					.gpr[21] = LONG_MIN,
53344dea178SSandipan Das 					.gpr[22] = LONG_MIN,
53444dea178SSandipan Das 				}
53544dea178SSandipan Das 			},
53644dea178SSandipan Das 			{
53744dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
5381d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
53944dea178SSandipan Das 				.regs = {
54044dea178SSandipan Das 					.gpr[21] = LONG_MIN,
54144dea178SSandipan Das 					.gpr[22] = LONG_MAX,
54244dea178SSandipan Das 				}
54344dea178SSandipan Das 			},
54444dea178SSandipan Das 			{
54544dea178SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
5461d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
54744dea178SSandipan Das 				.regs = {
54844dea178SSandipan Das 					.gpr[21] = LONG_MAX,
54944dea178SSandipan Das 					.gpr[22] = LONG_MAX,
55044dea178SSandipan Das 				}
55144dea178SSandipan Das 			},
55244dea178SSandipan Das 			{
55344dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
5541d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
55544dea178SSandipan Das 				.regs = {
55644dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
55744dea178SSandipan Das 					.gpr[22] = ULONG_MAX,
55844dea178SSandipan Das 				}
55944dea178SSandipan Das 			},
56044dea178SSandipan Das 			{
56144dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
5621d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
56344dea178SSandipan Das 				.regs = {
56444dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
56544dea178SSandipan Das 					.gpr[22] = 0x1,
56644dea178SSandipan Das 				}
56744dea178SSandipan Das 			},
56844dea178SSandipan Das 			{
56944dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
5701d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
57144dea178SSandipan Das 				.regs = {
57244dea178SSandipan Das 					.gpr[21] = INT_MIN,
57344dea178SSandipan Das 					.gpr[22] = INT_MIN,
57444dea178SSandipan Das 				}
57544dea178SSandipan Das 			},
57644dea178SSandipan Das 			{
57744dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
5781d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
57944dea178SSandipan Das 				.regs = {
58044dea178SSandipan Das 					.gpr[21] = INT_MIN,
58144dea178SSandipan Das 					.gpr[22] = INT_MAX,
58244dea178SSandipan Das 				}
58344dea178SSandipan Das 			},
58444dea178SSandipan Das 			{
58544dea178SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
5861d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
58744dea178SSandipan Das 				.regs = {
58844dea178SSandipan Das 					.gpr[21] = INT_MAX,
58944dea178SSandipan Das 					.gpr[22] = INT_MAX,
59044dea178SSandipan Das 				}
59144dea178SSandipan Das 			},
59244dea178SSandipan Das 			{
59344dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
5941d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
59544dea178SSandipan Das 				.regs = {
59644dea178SSandipan Das 					.gpr[21] = UINT_MAX,
59744dea178SSandipan Das 					.gpr[22] = UINT_MAX,
59844dea178SSandipan Das 				}
59944dea178SSandipan Das 			},
60044dea178SSandipan Das 			{
60144dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
6021d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
60344dea178SSandipan Das 				.regs = {
60444dea178SSandipan Das 					.gpr[21] = UINT_MAX,
60544dea178SSandipan Das 					.gpr[22] = 0x1,
60644dea178SSandipan Das 				}
60744dea178SSandipan Das 			}
60844dea178SSandipan Das 		}
60944dea178SSandipan Das 	},
61044dea178SSandipan Das 	{
61144dea178SSandipan Das 		.mnemonic = "add.",
61244dea178SSandipan Das 		.subtests = {
61344dea178SSandipan Das 			{
61444dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
61544dea178SSandipan Das 				.flags = IGNORE_CCR,
6161d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
61744dea178SSandipan Das 				.regs = {
61844dea178SSandipan Das 					.gpr[21] = LONG_MIN,
61944dea178SSandipan Das 					.gpr[22] = LONG_MIN,
62044dea178SSandipan Das 				}
62144dea178SSandipan Das 			},
62244dea178SSandipan Das 			{
62344dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
6241d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
62544dea178SSandipan Das 				.regs = {
62644dea178SSandipan Das 					.gpr[21] = LONG_MIN,
62744dea178SSandipan Das 					.gpr[22] = LONG_MAX,
62844dea178SSandipan Das 				}
62944dea178SSandipan Das 			},
63044dea178SSandipan Das 			{
63144dea178SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
63244dea178SSandipan Das 				.flags = IGNORE_CCR,
6331d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
63444dea178SSandipan Das 				.regs = {
63544dea178SSandipan Das 					.gpr[21] = LONG_MAX,
63644dea178SSandipan Das 					.gpr[22] = LONG_MAX,
63744dea178SSandipan Das 				}
63844dea178SSandipan Das 			},
63944dea178SSandipan Das 			{
64044dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
6411d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
64244dea178SSandipan Das 				.regs = {
64344dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
64444dea178SSandipan Das 					.gpr[22] = ULONG_MAX,
64544dea178SSandipan Das 				}
64644dea178SSandipan Das 			},
64744dea178SSandipan Das 			{
64844dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
6491d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
65044dea178SSandipan Das 				.regs = {
65144dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
65244dea178SSandipan Das 					.gpr[22] = 0x1,
65344dea178SSandipan Das 				}
65444dea178SSandipan Das 			},
65544dea178SSandipan Das 			{
65644dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
6571d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
65844dea178SSandipan Das 				.regs = {
65944dea178SSandipan Das 					.gpr[21] = INT_MIN,
66044dea178SSandipan Das 					.gpr[22] = INT_MIN,
66144dea178SSandipan Das 				}
66244dea178SSandipan Das 			},
66344dea178SSandipan Das 			{
66444dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
6651d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
66644dea178SSandipan Das 				.regs = {
66744dea178SSandipan Das 					.gpr[21] = INT_MIN,
66844dea178SSandipan Das 					.gpr[22] = INT_MAX,
66944dea178SSandipan Das 				}
67044dea178SSandipan Das 			},
67144dea178SSandipan Das 			{
67244dea178SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
6731d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
67444dea178SSandipan Das 				.regs = {
67544dea178SSandipan Das 					.gpr[21] = INT_MAX,
67644dea178SSandipan Das 					.gpr[22] = INT_MAX,
67744dea178SSandipan Das 				}
67844dea178SSandipan Das 			},
67944dea178SSandipan Das 			{
68044dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
6811d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
68244dea178SSandipan Das 				.regs = {
68344dea178SSandipan Das 					.gpr[21] = UINT_MAX,
68444dea178SSandipan Das 					.gpr[22] = UINT_MAX,
68544dea178SSandipan Das 				}
68644dea178SSandipan Das 			},
68744dea178SSandipan Das 			{
68844dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
6891d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
69044dea178SSandipan Das 				.regs = {
69144dea178SSandipan Das 					.gpr[21] = UINT_MAX,
69244dea178SSandipan Das 					.gpr[22] = 0x1,
69344dea178SSandipan Das 				}
69444dea178SSandipan Das 			}
69544dea178SSandipan Das 		}
69678a8da06SSandipan Das 	},
69778a8da06SSandipan Das 	{
69878a8da06SSandipan Das 		.mnemonic = "addc",
69978a8da06SSandipan Das 		.subtests = {
70078a8da06SSandipan Das 			{
70178a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
7021d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
70378a8da06SSandipan Das 				.regs = {
70478a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
70578a8da06SSandipan Das 					.gpr[22] = LONG_MIN,
70678a8da06SSandipan Das 				}
70778a8da06SSandipan Das 			},
70878a8da06SSandipan Das 			{
70978a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
7101d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
71178a8da06SSandipan Das 				.regs = {
71278a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
71378a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
71478a8da06SSandipan Das 				}
71578a8da06SSandipan Das 			},
71678a8da06SSandipan Das 			{
71778a8da06SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
7181d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
71978a8da06SSandipan Das 				.regs = {
72078a8da06SSandipan Das 					.gpr[21] = LONG_MAX,
72178a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
72278a8da06SSandipan Das 				}
72378a8da06SSandipan Das 			},
72478a8da06SSandipan Das 			{
72578a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
7261d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
72778a8da06SSandipan Das 				.regs = {
72878a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
72978a8da06SSandipan Das 					.gpr[22] = ULONG_MAX,
73078a8da06SSandipan Das 				}
73178a8da06SSandipan Das 			},
73278a8da06SSandipan Das 			{
73378a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
7341d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
73578a8da06SSandipan Das 				.regs = {
73678a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
73778a8da06SSandipan Das 					.gpr[22] = 0x1,
73878a8da06SSandipan Das 				}
73978a8da06SSandipan Das 			},
74078a8da06SSandipan Das 			{
74178a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
7421d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
74378a8da06SSandipan Das 				.regs = {
74478a8da06SSandipan Das 					.gpr[21] = INT_MIN,
74578a8da06SSandipan Das 					.gpr[22] = INT_MIN,
74678a8da06SSandipan Das 				}
74778a8da06SSandipan Das 			},
74878a8da06SSandipan Das 			{
74978a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
7501d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
75178a8da06SSandipan Das 				.regs = {
75278a8da06SSandipan Das 					.gpr[21] = INT_MIN,
75378a8da06SSandipan Das 					.gpr[22] = INT_MAX,
75478a8da06SSandipan Das 				}
75578a8da06SSandipan Das 			},
75678a8da06SSandipan Das 			{
75778a8da06SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
7581d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
75978a8da06SSandipan Das 				.regs = {
76078a8da06SSandipan Das 					.gpr[21] = INT_MAX,
76178a8da06SSandipan Das 					.gpr[22] = INT_MAX,
76278a8da06SSandipan Das 				}
76378a8da06SSandipan Das 			},
76478a8da06SSandipan Das 			{
76578a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
7661d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
76778a8da06SSandipan Das 				.regs = {
76878a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
76978a8da06SSandipan Das 					.gpr[22] = UINT_MAX,
77078a8da06SSandipan Das 				}
77178a8da06SSandipan Das 			},
77278a8da06SSandipan Das 			{
77378a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
7741d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
77578a8da06SSandipan Das 				.regs = {
77678a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
77778a8da06SSandipan Das 					.gpr[22] = 0x1,
77878a8da06SSandipan Das 				}
77978a8da06SSandipan Das 			},
78078a8da06SSandipan Das 			{
78178a8da06SSandipan Das 				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
7821d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
78378a8da06SSandipan Das 				.regs = {
78478a8da06SSandipan Das 					.gpr[21] = LONG_MIN | (uint)INT_MIN,
78578a8da06SSandipan Das 					.gpr[22] = LONG_MIN | (uint)INT_MIN,
78678a8da06SSandipan Das 				}
78778a8da06SSandipan Das 			}
78878a8da06SSandipan Das 		}
78978a8da06SSandipan Das 	},
79078a8da06SSandipan Das 	{
79178a8da06SSandipan Das 		.mnemonic = "addc.",
79278a8da06SSandipan Das 		.subtests = {
79378a8da06SSandipan Das 			{
79478a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
79578a8da06SSandipan Das 				.flags = IGNORE_CCR,
7961d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
79778a8da06SSandipan Das 				.regs = {
79878a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
79978a8da06SSandipan Das 					.gpr[22] = LONG_MIN,
80078a8da06SSandipan Das 				}
80178a8da06SSandipan Das 			},
80278a8da06SSandipan Das 			{
80378a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
8041d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
80578a8da06SSandipan Das 				.regs = {
80678a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
80778a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
80878a8da06SSandipan Das 				}
80978a8da06SSandipan Das 			},
81078a8da06SSandipan Das 			{
81178a8da06SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
81278a8da06SSandipan Das 				.flags = IGNORE_CCR,
8131d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
81478a8da06SSandipan Das 				.regs = {
81578a8da06SSandipan Das 					.gpr[21] = LONG_MAX,
81678a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
81778a8da06SSandipan Das 				}
81878a8da06SSandipan Das 			},
81978a8da06SSandipan Das 			{
82078a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
8211d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
82278a8da06SSandipan Das 				.regs = {
82378a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
82478a8da06SSandipan Das 					.gpr[22] = ULONG_MAX,
82578a8da06SSandipan Das 				}
82678a8da06SSandipan Das 			},
82778a8da06SSandipan Das 			{
82878a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
8291d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
83078a8da06SSandipan Das 				.regs = {
83178a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
83278a8da06SSandipan Das 					.gpr[22] = 0x1,
83378a8da06SSandipan Das 				}
83478a8da06SSandipan Das 			},
83578a8da06SSandipan Das 			{
83678a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
8371d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
83878a8da06SSandipan Das 				.regs = {
83978a8da06SSandipan Das 					.gpr[21] = INT_MIN,
84078a8da06SSandipan Das 					.gpr[22] = INT_MIN,
84178a8da06SSandipan Das 				}
84278a8da06SSandipan Das 			},
84378a8da06SSandipan Das 			{
84478a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
8451d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
84678a8da06SSandipan Das 				.regs = {
84778a8da06SSandipan Das 					.gpr[21] = INT_MIN,
84878a8da06SSandipan Das 					.gpr[22] = INT_MAX,
84978a8da06SSandipan Das 				}
85078a8da06SSandipan Das 			},
85178a8da06SSandipan Das 			{
85278a8da06SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
8531d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
85478a8da06SSandipan Das 				.regs = {
85578a8da06SSandipan Das 					.gpr[21] = INT_MAX,
85678a8da06SSandipan Das 					.gpr[22] = INT_MAX,
85778a8da06SSandipan Das 				}
85878a8da06SSandipan Das 			},
85978a8da06SSandipan Das 			{
86078a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
8611d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
86278a8da06SSandipan Das 				.regs = {
86378a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
86478a8da06SSandipan Das 					.gpr[22] = UINT_MAX,
86578a8da06SSandipan Das 				}
86678a8da06SSandipan Das 			},
86778a8da06SSandipan Das 			{
86878a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
8691d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
87078a8da06SSandipan Das 				.regs = {
87178a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
87278a8da06SSandipan Das 					.gpr[22] = 0x1,
87378a8da06SSandipan Das 				}
87478a8da06SSandipan Das 			},
87578a8da06SSandipan Das 			{
87678a8da06SSandipan Das 				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
8771d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
87878a8da06SSandipan Das 				.regs = {
87978a8da06SSandipan Das 					.gpr[21] = LONG_MIN | (uint)INT_MIN,
88078a8da06SSandipan Das 					.gpr[22] = LONG_MIN | (uint)INT_MIN,
88178a8da06SSandipan Das 				}
88278a8da06SSandipan Das 			}
88378a8da06SSandipan Das 		}
88484022ac1SSandipan Das 	}
88584022ac1SSandipan Das };
88684022ac1SSandipan Das 
88784022ac1SSandipan Das static int __init emulate_compute_instr(struct pt_regs *regs,
88894afd069SJordan Niethe 					struct ppc_inst instr)
88984022ac1SSandipan Das {
89084022ac1SSandipan Das 	struct instruction_op op;
89184022ac1SSandipan Das 
892777e26f0SJordan Niethe 	if (!regs || !ppc_inst_val(instr))
89384022ac1SSandipan Das 		return -EINVAL;
89484022ac1SSandipan Das 
89584022ac1SSandipan Das 	if (analyse_instr(&op, regs, instr) != 1 ||
89684022ac1SSandipan Das 	    GETTYPE(op.type) != COMPUTE) {
897777e26f0SJordan Niethe 		pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr));
89884022ac1SSandipan Das 		return -EFAULT;
89984022ac1SSandipan Das 	}
90084022ac1SSandipan Das 
90184022ac1SSandipan Das 	emulate_update_regs(regs, &op);
90284022ac1SSandipan Das 	return 0;
90384022ac1SSandipan Das }
90484022ac1SSandipan Das 
90584022ac1SSandipan Das static int __init execute_compute_instr(struct pt_regs *regs,
90694afd069SJordan Niethe 					struct ppc_inst instr)
90784022ac1SSandipan Das {
90884022ac1SSandipan Das 	extern int exec_instr(struct pt_regs *regs);
90984022ac1SSandipan Das 	extern s32 patch__exec_instr;
91084022ac1SSandipan Das 
911777e26f0SJordan Niethe 	if (!regs || !ppc_inst_val(instr))
91284022ac1SSandipan Das 		return -EINVAL;
91384022ac1SSandipan Das 
91484022ac1SSandipan Das 	/* Patch the NOP with the actual instruction */
91584022ac1SSandipan Das 	patch_instruction_site(&patch__exec_instr, instr);
91684022ac1SSandipan Das 	if (exec_instr(regs)) {
917777e26f0SJordan Niethe 		pr_info("execution failed, instruction = 0x%08x\n", ppc_inst_val(instr));
91884022ac1SSandipan Das 		return -EFAULT;
91984022ac1SSandipan Das 	}
92084022ac1SSandipan Das 
92184022ac1SSandipan Das 	return 0;
92284022ac1SSandipan Das }
92384022ac1SSandipan Das 
92484022ac1SSandipan Das #define gpr_mismatch(gprn, exp, got)	\
92584022ac1SSandipan Das 	pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
92684022ac1SSandipan Das 		gprn, exp, got)
92784022ac1SSandipan Das 
92884022ac1SSandipan Das #define reg_mismatch(name, exp, got)	\
92984022ac1SSandipan Das 	pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
93084022ac1SSandipan Das 		name, exp, got)
93184022ac1SSandipan Das 
93284022ac1SSandipan Das static void __init run_tests_compute(void)
93384022ac1SSandipan Das {
93484022ac1SSandipan Das 	unsigned long flags;
93584022ac1SSandipan Das 	struct compute_test *test;
93684022ac1SSandipan Das 	struct pt_regs *regs, exp, got;
93794afd069SJordan Niethe 	unsigned int i, j, k;
93894afd069SJordan Niethe 	struct ppc_inst instr;
93984022ac1SSandipan Das 	bool ignore_gpr, ignore_xer, ignore_ccr, passed;
94084022ac1SSandipan Das 
94184022ac1SSandipan Das 	for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
94284022ac1SSandipan Das 		test = &compute_tests[i];
94384022ac1SSandipan Das 
94484022ac1SSandipan Das 		for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
94584022ac1SSandipan Das 			instr = test->subtests[j].instr;
94684022ac1SSandipan Das 			flags = test->subtests[j].flags;
94784022ac1SSandipan Das 			regs = &test->subtests[j].regs;
94884022ac1SSandipan Das 			ignore_xer = flags & IGNORE_XER;
94984022ac1SSandipan Das 			ignore_ccr = flags & IGNORE_CCR;
95084022ac1SSandipan Das 			passed = true;
95184022ac1SSandipan Das 
95284022ac1SSandipan Das 			memcpy(&exp, regs, sizeof(struct pt_regs));
95384022ac1SSandipan Das 			memcpy(&got, regs, sizeof(struct pt_regs));
95484022ac1SSandipan Das 
95584022ac1SSandipan Das 			/*
95684022ac1SSandipan Das 			 * Set a compatible MSR value explicitly to ensure
95784022ac1SSandipan Das 			 * that XER and CR bits are updated appropriately
95884022ac1SSandipan Das 			 */
95984022ac1SSandipan Das 			exp.msr = MSR_KERNEL;
96084022ac1SSandipan Das 			got.msr = MSR_KERNEL;
96184022ac1SSandipan Das 
96284022ac1SSandipan Das 			if (emulate_compute_instr(&got, instr) ||
96384022ac1SSandipan Das 			    execute_compute_instr(&exp, instr)) {
96484022ac1SSandipan Das 				passed = false;
96584022ac1SSandipan Das 				goto print;
96684022ac1SSandipan Das 			}
96784022ac1SSandipan Das 
96884022ac1SSandipan Das 			/* Verify GPR values */
96984022ac1SSandipan Das 			for (k = 0; k < 32; k++) {
97084022ac1SSandipan Das 				ignore_gpr = flags & IGNORE_GPR(k);
97184022ac1SSandipan Das 				if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
97284022ac1SSandipan Das 					passed = false;
97384022ac1SSandipan Das 					gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
97484022ac1SSandipan Das 				}
97584022ac1SSandipan Das 			}
97684022ac1SSandipan Das 
97784022ac1SSandipan Das 			/* Verify LR value */
97884022ac1SSandipan Das 			if (exp.link != got.link) {
97984022ac1SSandipan Das 				passed = false;
98084022ac1SSandipan Das 				reg_mismatch("LR", exp.link, got.link);
98184022ac1SSandipan Das 			}
98284022ac1SSandipan Das 
98384022ac1SSandipan Das 			/* Verify XER value */
98484022ac1SSandipan Das 			if (!ignore_xer && exp.xer != got.xer) {
98584022ac1SSandipan Das 				passed = false;
98684022ac1SSandipan Das 				reg_mismatch("XER", exp.xer, got.xer);
98784022ac1SSandipan Das 			}
98884022ac1SSandipan Das 
98984022ac1SSandipan Das 			/* Verify CR value */
99084022ac1SSandipan Das 			if (!ignore_ccr && exp.ccr != got.ccr) {
99184022ac1SSandipan Das 				passed = false;
99284022ac1SSandipan Das 				reg_mismatch("CR", exp.ccr, got.ccr);
99384022ac1SSandipan Das 			}
99484022ac1SSandipan Das 
99584022ac1SSandipan Das print:
99684022ac1SSandipan Das 			show_result_with_descr(test->mnemonic,
99784022ac1SSandipan Das 					       test->subtests[j].descr,
99884022ac1SSandipan Das 					       passed ? "PASS" : "FAIL");
99984022ac1SSandipan Das 		}
100084022ac1SSandipan Das 	}
100184022ac1SSandipan Das }
100284022ac1SSandipan Das 
100384022ac1SSandipan Das static int __init test_emulate_step(void)
100484022ac1SSandipan Das {
100584022ac1SSandipan Das 	printk(KERN_INFO "Running instruction emulation self-tests ...\n");
100684022ac1SSandipan Das 	run_tests_load_store();
100784022ac1SSandipan Das 	run_tests_compute();
10084ceae137SRavi Bangoria 
10094ceae137SRavi Bangoria 	return 0;
10104ceae137SRavi Bangoria }
10114ceae137SRavi Bangoria late_initcall(test_emulate_step);
1012