xref: /openbmc/linux/arch/powerpc/lib/test_emulate_step.c (revision 1d33dd84080f4a430bde2fc363d9b70f0a010c19)
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 
224ceae137SRavi Bangoria static void __init init_pt_regs(struct pt_regs *regs)
234ceae137SRavi Bangoria {
244ceae137SRavi Bangoria 	static unsigned long msr;
254ceae137SRavi Bangoria 	static bool msr_cached;
264ceae137SRavi Bangoria 
274ceae137SRavi Bangoria 	memset(regs, 0, sizeof(struct pt_regs));
284ceae137SRavi Bangoria 
294ceae137SRavi Bangoria 	if (likely(msr_cached)) {
304ceae137SRavi Bangoria 		regs->msr = msr;
314ceae137SRavi Bangoria 		return;
324ceae137SRavi Bangoria 	}
334ceae137SRavi Bangoria 
344ceae137SRavi Bangoria 	asm volatile("mfmsr %0" : "=r"(regs->msr));
354ceae137SRavi Bangoria 
364ceae137SRavi Bangoria 	regs->msr |= MSR_FP;
374ceae137SRavi Bangoria 	regs->msr |= MSR_VEC;
384ceae137SRavi Bangoria 	regs->msr |= MSR_VSX;
394ceae137SRavi Bangoria 
404ceae137SRavi Bangoria 	msr = regs->msr;
414ceae137SRavi Bangoria 	msr_cached = true;
424ceae137SRavi Bangoria }
434ceae137SRavi Bangoria 
4484022ac1SSandipan Das static void __init show_result(char *mnemonic, char *result)
454ceae137SRavi Bangoria {
4684022ac1SSandipan Das 	pr_info("%-14s : %s\n", mnemonic, result);
4784022ac1SSandipan Das }
4884022ac1SSandipan Das 
4984022ac1SSandipan Das static void __init show_result_with_descr(char *mnemonic, char *descr,
5084022ac1SSandipan Das 					  char *result)
5184022ac1SSandipan Das {
5284022ac1SSandipan Das 	pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
534ceae137SRavi Bangoria }
544ceae137SRavi Bangoria 
554ceae137SRavi Bangoria static void __init test_ld(void)
564ceae137SRavi Bangoria {
574ceae137SRavi Bangoria 	struct pt_regs regs;
584ceae137SRavi Bangoria 	unsigned long a = 0x23;
594ceae137SRavi Bangoria 	int stepped = -1;
604ceae137SRavi Bangoria 
614ceae137SRavi Bangoria 	init_pt_regs(&regs);
624ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
634ceae137SRavi Bangoria 
644ceae137SRavi Bangoria 	/* ld r5, 0(r3) */
65*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LD(5, 3, 0)));
664ceae137SRavi Bangoria 
674ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a)
684ceae137SRavi Bangoria 		show_result("ld", "PASS");
694ceae137SRavi Bangoria 	else
704ceae137SRavi Bangoria 		show_result("ld", "FAIL");
714ceae137SRavi Bangoria }
724ceae137SRavi Bangoria 
734ceae137SRavi Bangoria static void __init test_lwz(void)
744ceae137SRavi Bangoria {
754ceae137SRavi Bangoria 	struct pt_regs regs;
764ceae137SRavi Bangoria 	unsigned int a = 0x4545;
774ceae137SRavi Bangoria 	int stepped = -1;
784ceae137SRavi Bangoria 
794ceae137SRavi Bangoria 	init_pt_regs(&regs);
804ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
814ceae137SRavi Bangoria 
824ceae137SRavi Bangoria 	/* lwz r5, 0(r3) */
83*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
844ceae137SRavi Bangoria 
854ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a)
864ceae137SRavi Bangoria 		show_result("lwz", "PASS");
874ceae137SRavi Bangoria 	else
884ceae137SRavi Bangoria 		show_result("lwz", "FAIL");
894ceae137SRavi Bangoria }
904ceae137SRavi Bangoria 
914ceae137SRavi Bangoria static void __init test_lwzx(void)
924ceae137SRavi Bangoria {
934ceae137SRavi Bangoria 	struct pt_regs regs;
944ceae137SRavi Bangoria 	unsigned int a[3] = {0x0, 0x0, 0x1234};
954ceae137SRavi Bangoria 	int stepped = -1;
964ceae137SRavi Bangoria 
974ceae137SRavi Bangoria 	init_pt_regs(&regs);
984ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) a;
994ceae137SRavi Bangoria 	regs.gpr[4] = 8;
1004ceae137SRavi Bangoria 	regs.gpr[5] = 0x8765;
1014ceae137SRavi Bangoria 
1024ceae137SRavi Bangoria 	/* lwzx r5, r3, r4 */
103*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
1044ceae137SRavi Bangoria 	if (stepped == 1 && regs.gpr[5] == a[2])
1054ceae137SRavi Bangoria 		show_result("lwzx", "PASS");
1064ceae137SRavi Bangoria 	else
1074ceae137SRavi Bangoria 		show_result("lwzx", "FAIL");
1084ceae137SRavi Bangoria }
1094ceae137SRavi Bangoria 
1104ceae137SRavi Bangoria static void __init test_std(void)
1114ceae137SRavi Bangoria {
1124ceae137SRavi Bangoria 	struct pt_regs regs;
1134ceae137SRavi Bangoria 	unsigned long a = 0x1234;
1144ceae137SRavi Bangoria 	int stepped = -1;
1154ceae137SRavi Bangoria 
1164ceae137SRavi Bangoria 	init_pt_regs(&regs);
1174ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
1184ceae137SRavi Bangoria 	regs.gpr[5] = 0x5678;
1194ceae137SRavi Bangoria 
1204ceae137SRavi Bangoria 	/* std r5, 0(r3) */
121*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STD(5, 3, 0)));
12259ed2adfSNicholas Piggin 	if (stepped == 1 && regs.gpr[5] == a)
1234ceae137SRavi Bangoria 		show_result("std", "PASS");
1244ceae137SRavi Bangoria 	else
1254ceae137SRavi Bangoria 		show_result("std", "FAIL");
1264ceae137SRavi Bangoria }
1274ceae137SRavi Bangoria 
1284ceae137SRavi Bangoria static void __init test_ldarx_stdcx(void)
1294ceae137SRavi Bangoria {
1304ceae137SRavi Bangoria 	struct pt_regs regs;
1314ceae137SRavi Bangoria 	unsigned long a = 0x1234;
1324ceae137SRavi Bangoria 	int stepped = -1;
1334ceae137SRavi Bangoria 	unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
1344ceae137SRavi Bangoria 
1354ceae137SRavi Bangoria 	init_pt_regs(&regs);
1364ceae137SRavi Bangoria 	asm volatile("mfcr %0" : "=r"(regs.ccr));
1374ceae137SRavi Bangoria 
1384ceae137SRavi Bangoria 
1394ceae137SRavi Bangoria 	/*** ldarx ***/
1404ceae137SRavi Bangoria 
1414ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &a;
1424ceae137SRavi Bangoria 	regs.gpr[4] = 0;
1434ceae137SRavi Bangoria 	regs.gpr[5] = 0x5678;
1444ceae137SRavi Bangoria 
1454ceae137SRavi Bangoria 	/* ldarx r5, r3, r4, 0 */
146*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
1474ceae137SRavi Bangoria 
1484ceae137SRavi Bangoria 	/*
1494ceae137SRavi Bangoria 	 * Don't touch 'a' here. Touching 'a' can do Load/store
1504ceae137SRavi Bangoria 	 * of 'a' which result in failure of subsequent stdcx.
1514ceae137SRavi Bangoria 	 * Instead, use hardcoded value for comparison.
1524ceae137SRavi Bangoria 	 */
1534ceae137SRavi Bangoria 	if (stepped <= 0 || regs.gpr[5] != 0x1234) {
1544ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "FAIL (ldarx)");
1554ceae137SRavi Bangoria 		return;
1564ceae137SRavi Bangoria 	}
1574ceae137SRavi Bangoria 
1584ceae137SRavi Bangoria 
1594ceae137SRavi Bangoria 	/*** stdcx. ***/
1604ceae137SRavi Bangoria 
1614ceae137SRavi Bangoria 	regs.gpr[5] = 0x9ABC;
1624ceae137SRavi Bangoria 
1634ceae137SRavi Bangoria 	/* stdcx. r5, r3, r4 */
164*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
1654ceae137SRavi Bangoria 
1664ceae137SRavi Bangoria 	/*
1674ceae137SRavi Bangoria 	 * Two possible scenarios that indicates successful emulation
1684ceae137SRavi Bangoria 	 * of stdcx. :
1694ceae137SRavi Bangoria 	 *  1. Reservation is active and store is performed. In this
1704ceae137SRavi Bangoria 	 *     case cr0.eq bit will be set to 1.
1714ceae137SRavi Bangoria 	 *  2. Reservation is not active and store is not performed.
1724ceae137SRavi Bangoria 	 *     In this case cr0.eq bit will be set to 0.
1734ceae137SRavi Bangoria 	 */
1744ceae137SRavi Bangoria 	if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
1754ceae137SRavi Bangoria 			|| (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
1764ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "PASS");
1774ceae137SRavi Bangoria 	else
1784ceae137SRavi Bangoria 		show_result("ldarx / stdcx.", "FAIL (stdcx.)");
1794ceae137SRavi Bangoria }
1804ceae137SRavi Bangoria 
1814ceae137SRavi Bangoria #ifdef CONFIG_PPC_FPU
1824ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void)
1834ceae137SRavi Bangoria {
1844ceae137SRavi Bangoria 	struct pt_regs regs;
1854ceae137SRavi Bangoria 	union {
1864ceae137SRavi Bangoria 		float a;
1874ceae137SRavi Bangoria 		int b;
1884ceae137SRavi Bangoria 	} c;
1894ceae137SRavi Bangoria 	int cached_b;
1904ceae137SRavi Bangoria 	int stepped = -1;
1914ceae137SRavi Bangoria 
1924ceae137SRavi Bangoria 	init_pt_regs(&regs);
1934ceae137SRavi Bangoria 
1944ceae137SRavi Bangoria 
1954ceae137SRavi Bangoria 	/*** lfsx ***/
1964ceae137SRavi Bangoria 
1974ceae137SRavi Bangoria 	c.a = 123.45;
1984ceae137SRavi Bangoria 	cached_b = c.b;
1994ceae137SRavi Bangoria 
2004ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
2014ceae137SRavi Bangoria 	regs.gpr[4] = 0;
2024ceae137SRavi Bangoria 
2034ceae137SRavi Bangoria 	/* lfsx frt10, r3, r4 */
204*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
2054ceae137SRavi Bangoria 
2064ceae137SRavi Bangoria 	if (stepped == 1)
2074ceae137SRavi Bangoria 		show_result("lfsx", "PASS");
2084ceae137SRavi Bangoria 	else
2094ceae137SRavi Bangoria 		show_result("lfsx", "FAIL");
2104ceae137SRavi Bangoria 
2114ceae137SRavi Bangoria 
2124ceae137SRavi Bangoria 	/*** stfsx ***/
2134ceae137SRavi Bangoria 
2144ceae137SRavi Bangoria 	c.a = 678.91;
2154ceae137SRavi Bangoria 
2164ceae137SRavi Bangoria 	/* stfsx frs10, r3, r4 */
217*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
2184ceae137SRavi Bangoria 
2194ceae137SRavi Bangoria 	if (stepped == 1 && c.b == cached_b)
2204ceae137SRavi Bangoria 		show_result("stfsx", "PASS");
2214ceae137SRavi Bangoria 	else
2224ceae137SRavi Bangoria 		show_result("stfsx", "FAIL");
2234ceae137SRavi Bangoria }
2244ceae137SRavi Bangoria 
2254ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void)
2264ceae137SRavi Bangoria {
2274ceae137SRavi Bangoria 	struct pt_regs regs;
2284ceae137SRavi Bangoria 	union {
2294ceae137SRavi Bangoria 		double a;
2304ceae137SRavi Bangoria 		long b;
2314ceae137SRavi Bangoria 	} c;
2324ceae137SRavi Bangoria 	long cached_b;
2334ceae137SRavi Bangoria 	int stepped = -1;
2344ceae137SRavi Bangoria 
2354ceae137SRavi Bangoria 	init_pt_regs(&regs);
2364ceae137SRavi Bangoria 
2374ceae137SRavi Bangoria 
2384ceae137SRavi Bangoria 	/*** lfdx ***/
2394ceae137SRavi Bangoria 
2404ceae137SRavi Bangoria 	c.a = 123456.78;
2414ceae137SRavi Bangoria 	cached_b = c.b;
2424ceae137SRavi Bangoria 
2434ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
2444ceae137SRavi Bangoria 	regs.gpr[4] = 0;
2454ceae137SRavi Bangoria 
2464ceae137SRavi Bangoria 	/* lfdx frt10, r3, r4 */
247*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
2484ceae137SRavi Bangoria 
2494ceae137SRavi Bangoria 	if (stepped == 1)
2504ceae137SRavi Bangoria 		show_result("lfdx", "PASS");
2514ceae137SRavi Bangoria 	else
2524ceae137SRavi Bangoria 		show_result("lfdx", "FAIL");
2534ceae137SRavi Bangoria 
2544ceae137SRavi Bangoria 
2554ceae137SRavi Bangoria 	/*** stfdx ***/
2564ceae137SRavi Bangoria 
2574ceae137SRavi Bangoria 	c.a = 987654.32;
2584ceae137SRavi Bangoria 
2594ceae137SRavi Bangoria 	/* stfdx frs10, r3, r4 */
260*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
2614ceae137SRavi Bangoria 
2624ceae137SRavi Bangoria 	if (stepped == 1 && c.b == cached_b)
2634ceae137SRavi Bangoria 		show_result("stfdx", "PASS");
2644ceae137SRavi Bangoria 	else
2654ceae137SRavi Bangoria 		show_result("stfdx", "FAIL");
2664ceae137SRavi Bangoria }
2674ceae137SRavi Bangoria #else
2684ceae137SRavi Bangoria static void __init test_lfsx_stfsx(void)
2694ceae137SRavi Bangoria {
2704ceae137SRavi Bangoria 	show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
2714ceae137SRavi Bangoria 	show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
2724ceae137SRavi Bangoria }
2734ceae137SRavi Bangoria 
2744ceae137SRavi Bangoria static void __init test_lfdx_stfdx(void)
2754ceae137SRavi Bangoria {
2764ceae137SRavi Bangoria 	show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
2774ceae137SRavi Bangoria 	show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
2784ceae137SRavi Bangoria }
2794ceae137SRavi Bangoria #endif /* CONFIG_PPC_FPU */
2804ceae137SRavi Bangoria 
2814ceae137SRavi Bangoria #ifdef CONFIG_ALTIVEC
2824ceae137SRavi Bangoria static void __init test_lvx_stvx(void)
2834ceae137SRavi Bangoria {
2844ceae137SRavi Bangoria 	struct pt_regs regs;
2854ceae137SRavi Bangoria 	union {
2864ceae137SRavi Bangoria 		vector128 a;
2874ceae137SRavi Bangoria 		u32 b[4];
2884ceae137SRavi Bangoria 	} c;
2894ceae137SRavi Bangoria 	u32 cached_b[4];
2904ceae137SRavi Bangoria 	int stepped = -1;
2914ceae137SRavi Bangoria 
2924ceae137SRavi Bangoria 	init_pt_regs(&regs);
2934ceae137SRavi Bangoria 
2944ceae137SRavi Bangoria 
2954ceae137SRavi Bangoria 	/*** lvx ***/
2964ceae137SRavi Bangoria 
2974ceae137SRavi Bangoria 	cached_b[0] = c.b[0] = 923745;
2984ceae137SRavi Bangoria 	cached_b[1] = c.b[1] = 2139478;
2994ceae137SRavi Bangoria 	cached_b[2] = c.b[2] = 9012;
3004ceae137SRavi Bangoria 	cached_b[3] = c.b[3] = 982134;
3014ceae137SRavi Bangoria 
3024ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
3034ceae137SRavi Bangoria 	regs.gpr[4] = 0;
3044ceae137SRavi Bangoria 
3054ceae137SRavi Bangoria 	/* lvx vrt10, r3, r4 */
306*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
3074ceae137SRavi Bangoria 
3084ceae137SRavi Bangoria 	if (stepped == 1)
3094ceae137SRavi Bangoria 		show_result("lvx", "PASS");
3104ceae137SRavi Bangoria 	else
3114ceae137SRavi Bangoria 		show_result("lvx", "FAIL");
3124ceae137SRavi Bangoria 
3134ceae137SRavi Bangoria 
3144ceae137SRavi Bangoria 	/*** stvx ***/
3154ceae137SRavi Bangoria 
3164ceae137SRavi Bangoria 	c.b[0] = 4987513;
3174ceae137SRavi Bangoria 	c.b[1] = 84313948;
3184ceae137SRavi Bangoria 	c.b[2] = 71;
3194ceae137SRavi Bangoria 	c.b[3] = 498532;
3204ceae137SRavi Bangoria 
3214ceae137SRavi Bangoria 	/* stvx vrs10, r3, r4 */
322*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
3234ceae137SRavi Bangoria 
3244ceae137SRavi Bangoria 	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
3254ceae137SRavi Bangoria 	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
3264ceae137SRavi Bangoria 		show_result("stvx", "PASS");
3274ceae137SRavi Bangoria 	else
3284ceae137SRavi Bangoria 		show_result("stvx", "FAIL");
3294ceae137SRavi Bangoria }
3304ceae137SRavi Bangoria #else
3314ceae137SRavi Bangoria static void __init test_lvx_stvx(void)
3324ceae137SRavi Bangoria {
3334ceae137SRavi Bangoria 	show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
3344ceae137SRavi Bangoria 	show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
3354ceae137SRavi Bangoria }
3364ceae137SRavi Bangoria #endif /* CONFIG_ALTIVEC */
3374ceae137SRavi Bangoria 
3384ceae137SRavi Bangoria #ifdef CONFIG_VSX
3394ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void)
3404ceae137SRavi Bangoria {
3414ceae137SRavi Bangoria 	struct pt_regs regs;
3424ceae137SRavi Bangoria 	union {
3434ceae137SRavi Bangoria 		vector128 a;
3444ceae137SRavi Bangoria 		u32 b[4];
3454ceae137SRavi Bangoria 	} c;
3464ceae137SRavi Bangoria 	u32 cached_b[4];
3474ceae137SRavi Bangoria 	int stepped = -1;
3484ceae137SRavi Bangoria 
3494ceae137SRavi Bangoria 	init_pt_regs(&regs);
3504ceae137SRavi Bangoria 
3514ceae137SRavi Bangoria 
3524ceae137SRavi Bangoria 	/*** lxvd2x ***/
3534ceae137SRavi Bangoria 
3544ceae137SRavi Bangoria 	cached_b[0] = c.b[0] = 18233;
3554ceae137SRavi Bangoria 	cached_b[1] = c.b[1] = 34863571;
3564ceae137SRavi Bangoria 	cached_b[2] = c.b[2] = 834;
3574ceae137SRavi Bangoria 	cached_b[3] = c.b[3] = 6138911;
3584ceae137SRavi Bangoria 
3594ceae137SRavi Bangoria 	regs.gpr[3] = (unsigned long) &c.a;
3604ceae137SRavi Bangoria 	regs.gpr[4] = 0;
3614ceae137SRavi Bangoria 
3624ceae137SRavi Bangoria 	/* lxvd2x vsr39, r3, r4 */
363*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
3644ceae137SRavi Bangoria 
3655a61640eSRavi Bangoria 	if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
3664ceae137SRavi Bangoria 		show_result("lxvd2x", "PASS");
3675a61640eSRavi Bangoria 	} else {
3685a61640eSRavi Bangoria 		if (!cpu_has_feature(CPU_FTR_VSX))
3695a61640eSRavi Bangoria 			show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
3704ceae137SRavi Bangoria 		else
3714ceae137SRavi Bangoria 			show_result("lxvd2x", "FAIL");
3725a61640eSRavi Bangoria 	}
3734ceae137SRavi Bangoria 
3744ceae137SRavi Bangoria 
3754ceae137SRavi Bangoria 	/*** stxvd2x ***/
3764ceae137SRavi Bangoria 
3774ceae137SRavi Bangoria 	c.b[0] = 21379463;
3784ceae137SRavi Bangoria 	c.b[1] = 87;
3794ceae137SRavi Bangoria 	c.b[2] = 374234;
3804ceae137SRavi Bangoria 	c.b[3] = 4;
3814ceae137SRavi Bangoria 
3824ceae137SRavi Bangoria 	/* stxvd2x vsr39, r3, r4 */
383*1d33dd84SBalamuruhan S 	stepped = emulate_step(&regs, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
3844ceae137SRavi Bangoria 
3854ceae137SRavi Bangoria 	if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
3865a61640eSRavi Bangoria 	    cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
3875a61640eSRavi Bangoria 	    cpu_has_feature(CPU_FTR_VSX)) {
3884ceae137SRavi Bangoria 		show_result("stxvd2x", "PASS");
3895a61640eSRavi Bangoria 	} else {
3905a61640eSRavi Bangoria 		if (!cpu_has_feature(CPU_FTR_VSX))
3915a61640eSRavi Bangoria 			show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
3924ceae137SRavi Bangoria 		else
3934ceae137SRavi Bangoria 			show_result("stxvd2x", "FAIL");
3944ceae137SRavi Bangoria 	}
3955a61640eSRavi Bangoria }
3964ceae137SRavi Bangoria #else
3974ceae137SRavi Bangoria static void __init test_lxvd2x_stxvd2x(void)
3984ceae137SRavi Bangoria {
3994ceae137SRavi Bangoria 	show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
4004ceae137SRavi Bangoria 	show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
4014ceae137SRavi Bangoria }
4024ceae137SRavi Bangoria #endif /* CONFIG_VSX */
4034ceae137SRavi Bangoria 
40484022ac1SSandipan Das static void __init run_tests_load_store(void)
4054ceae137SRavi Bangoria {
4064ceae137SRavi Bangoria 	test_ld();
4074ceae137SRavi Bangoria 	test_lwz();
4084ceae137SRavi Bangoria 	test_lwzx();
4094ceae137SRavi Bangoria 	test_std();
4104ceae137SRavi Bangoria 	test_ldarx_stdcx();
4114ceae137SRavi Bangoria 	test_lfsx_stfsx();
4124ceae137SRavi Bangoria 	test_lfdx_stfdx();
4134ceae137SRavi Bangoria 	test_lvx_stvx();
4144ceae137SRavi Bangoria 	test_lxvd2x_stxvd2x();
41584022ac1SSandipan Das }
41684022ac1SSandipan Das 
41784022ac1SSandipan Das struct compute_test {
41884022ac1SSandipan Das 	char *mnemonic;
41984022ac1SSandipan Das 	struct {
42084022ac1SSandipan Das 		char *descr;
42184022ac1SSandipan Das 		unsigned long flags;
42294afd069SJordan Niethe 		struct ppc_inst instr;
42384022ac1SSandipan Das 		struct pt_regs regs;
42484022ac1SSandipan Das 	} subtests[MAX_SUBTESTS + 1];
42584022ac1SSandipan Das };
42684022ac1SSandipan Das 
42784022ac1SSandipan Das static struct compute_test compute_tests[] = {
42884022ac1SSandipan Das 	{
42984022ac1SSandipan Das 		.mnemonic = "nop",
43084022ac1SSandipan Das 		.subtests = {
43184022ac1SSandipan Das 			{
43284022ac1SSandipan Das 				.descr = "R0 = LONG_MAX",
43375346251SJordan Niethe 				.instr = ppc_inst(PPC_INST_NOP),
43484022ac1SSandipan Das 				.regs = {
43584022ac1SSandipan Das 					.gpr[0] = LONG_MAX,
43684022ac1SSandipan Das 				}
43784022ac1SSandipan Das 			}
43884022ac1SSandipan Das 		}
43944dea178SSandipan Das 	},
44044dea178SSandipan Das 	{
44144dea178SSandipan Das 		.mnemonic = "add",
44244dea178SSandipan Das 		.subtests = {
44344dea178SSandipan Das 			{
44444dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
445*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
44644dea178SSandipan Das 				.regs = {
44744dea178SSandipan Das 					.gpr[21] = LONG_MIN,
44844dea178SSandipan Das 					.gpr[22] = LONG_MIN,
44944dea178SSandipan Das 				}
45044dea178SSandipan Das 			},
45144dea178SSandipan Das 			{
45244dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
453*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
45444dea178SSandipan Das 				.regs = {
45544dea178SSandipan Das 					.gpr[21] = LONG_MIN,
45644dea178SSandipan Das 					.gpr[22] = LONG_MAX,
45744dea178SSandipan Das 				}
45844dea178SSandipan Das 			},
45944dea178SSandipan Das 			{
46044dea178SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
461*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
46244dea178SSandipan Das 				.regs = {
46344dea178SSandipan Das 					.gpr[21] = LONG_MAX,
46444dea178SSandipan Das 					.gpr[22] = LONG_MAX,
46544dea178SSandipan Das 				}
46644dea178SSandipan Das 			},
46744dea178SSandipan Das 			{
46844dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
469*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
47044dea178SSandipan Das 				.regs = {
47144dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
47244dea178SSandipan Das 					.gpr[22] = ULONG_MAX,
47344dea178SSandipan Das 				}
47444dea178SSandipan Das 			},
47544dea178SSandipan Das 			{
47644dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
477*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
47844dea178SSandipan Das 				.regs = {
47944dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
48044dea178SSandipan Das 					.gpr[22] = 0x1,
48144dea178SSandipan Das 				}
48244dea178SSandipan Das 			},
48344dea178SSandipan Das 			{
48444dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
485*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
48644dea178SSandipan Das 				.regs = {
48744dea178SSandipan Das 					.gpr[21] = INT_MIN,
48844dea178SSandipan Das 					.gpr[22] = INT_MIN,
48944dea178SSandipan Das 				}
49044dea178SSandipan Das 			},
49144dea178SSandipan Das 			{
49244dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
493*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
49444dea178SSandipan Das 				.regs = {
49544dea178SSandipan Das 					.gpr[21] = INT_MIN,
49644dea178SSandipan Das 					.gpr[22] = INT_MAX,
49744dea178SSandipan Das 				}
49844dea178SSandipan Das 			},
49944dea178SSandipan Das 			{
50044dea178SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
501*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
50244dea178SSandipan Das 				.regs = {
50344dea178SSandipan Das 					.gpr[21] = INT_MAX,
50444dea178SSandipan Das 					.gpr[22] = INT_MAX,
50544dea178SSandipan Das 				}
50644dea178SSandipan Das 			},
50744dea178SSandipan Das 			{
50844dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
509*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
51044dea178SSandipan Das 				.regs = {
51144dea178SSandipan Das 					.gpr[21] = UINT_MAX,
51244dea178SSandipan Das 					.gpr[22] = UINT_MAX,
51344dea178SSandipan Das 				}
51444dea178SSandipan Das 			},
51544dea178SSandipan Das 			{
51644dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
517*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
51844dea178SSandipan Das 				.regs = {
51944dea178SSandipan Das 					.gpr[21] = UINT_MAX,
52044dea178SSandipan Das 					.gpr[22] = 0x1,
52144dea178SSandipan Das 				}
52244dea178SSandipan Das 			}
52344dea178SSandipan Das 		}
52444dea178SSandipan Das 	},
52544dea178SSandipan Das 	{
52644dea178SSandipan Das 		.mnemonic = "add.",
52744dea178SSandipan Das 		.subtests = {
52844dea178SSandipan Das 			{
52944dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
53044dea178SSandipan Das 				.flags = IGNORE_CCR,
531*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
53244dea178SSandipan Das 				.regs = {
53344dea178SSandipan Das 					.gpr[21] = LONG_MIN,
53444dea178SSandipan Das 					.gpr[22] = LONG_MIN,
53544dea178SSandipan Das 				}
53644dea178SSandipan Das 			},
53744dea178SSandipan Das 			{
53844dea178SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
539*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
54044dea178SSandipan Das 				.regs = {
54144dea178SSandipan Das 					.gpr[21] = LONG_MIN,
54244dea178SSandipan Das 					.gpr[22] = LONG_MAX,
54344dea178SSandipan Das 				}
54444dea178SSandipan Das 			},
54544dea178SSandipan Das 			{
54644dea178SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
54744dea178SSandipan Das 				.flags = IGNORE_CCR,
548*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
54944dea178SSandipan Das 				.regs = {
55044dea178SSandipan Das 					.gpr[21] = LONG_MAX,
55144dea178SSandipan Das 					.gpr[22] = LONG_MAX,
55244dea178SSandipan Das 				}
55344dea178SSandipan Das 			},
55444dea178SSandipan Das 			{
55544dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
556*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
55744dea178SSandipan Das 				.regs = {
55844dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
55944dea178SSandipan Das 					.gpr[22] = ULONG_MAX,
56044dea178SSandipan Das 				}
56144dea178SSandipan Das 			},
56244dea178SSandipan Das 			{
56344dea178SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
564*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
56544dea178SSandipan Das 				.regs = {
56644dea178SSandipan Das 					.gpr[21] = ULONG_MAX,
56744dea178SSandipan Das 					.gpr[22] = 0x1,
56844dea178SSandipan Das 				}
56944dea178SSandipan Das 			},
57044dea178SSandipan Das 			{
57144dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
572*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
57344dea178SSandipan Das 				.regs = {
57444dea178SSandipan Das 					.gpr[21] = INT_MIN,
57544dea178SSandipan Das 					.gpr[22] = INT_MIN,
57644dea178SSandipan Das 				}
57744dea178SSandipan Das 			},
57844dea178SSandipan Das 			{
57944dea178SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
580*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
58144dea178SSandipan Das 				.regs = {
58244dea178SSandipan Das 					.gpr[21] = INT_MIN,
58344dea178SSandipan Das 					.gpr[22] = INT_MAX,
58444dea178SSandipan Das 				}
58544dea178SSandipan Das 			},
58644dea178SSandipan Das 			{
58744dea178SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
588*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
58944dea178SSandipan Das 				.regs = {
59044dea178SSandipan Das 					.gpr[21] = INT_MAX,
59144dea178SSandipan Das 					.gpr[22] = INT_MAX,
59244dea178SSandipan Das 				}
59344dea178SSandipan Das 			},
59444dea178SSandipan Das 			{
59544dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
596*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
59744dea178SSandipan Das 				.regs = {
59844dea178SSandipan Das 					.gpr[21] = UINT_MAX,
59944dea178SSandipan Das 					.gpr[22] = UINT_MAX,
60044dea178SSandipan Das 				}
60144dea178SSandipan Das 			},
60244dea178SSandipan Das 			{
60344dea178SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
604*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
60544dea178SSandipan Das 				.regs = {
60644dea178SSandipan Das 					.gpr[21] = UINT_MAX,
60744dea178SSandipan Das 					.gpr[22] = 0x1,
60844dea178SSandipan Das 				}
60944dea178SSandipan Das 			}
61044dea178SSandipan Das 		}
61178a8da06SSandipan Das 	},
61278a8da06SSandipan Das 	{
61378a8da06SSandipan Das 		.mnemonic = "addc",
61478a8da06SSandipan Das 		.subtests = {
61578a8da06SSandipan Das 			{
61678a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
617*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
61878a8da06SSandipan Das 				.regs = {
61978a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
62078a8da06SSandipan Das 					.gpr[22] = LONG_MIN,
62178a8da06SSandipan Das 				}
62278a8da06SSandipan Das 			},
62378a8da06SSandipan Das 			{
62478a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
625*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
62678a8da06SSandipan Das 				.regs = {
62778a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
62878a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
62978a8da06SSandipan Das 				}
63078a8da06SSandipan Das 			},
63178a8da06SSandipan Das 			{
63278a8da06SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
633*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
63478a8da06SSandipan Das 				.regs = {
63578a8da06SSandipan Das 					.gpr[21] = LONG_MAX,
63678a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
63778a8da06SSandipan Das 				}
63878a8da06SSandipan Das 			},
63978a8da06SSandipan Das 			{
64078a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
641*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
64278a8da06SSandipan Das 				.regs = {
64378a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
64478a8da06SSandipan Das 					.gpr[22] = ULONG_MAX,
64578a8da06SSandipan Das 				}
64678a8da06SSandipan Das 			},
64778a8da06SSandipan Das 			{
64878a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
649*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
65078a8da06SSandipan Das 				.regs = {
65178a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
65278a8da06SSandipan Das 					.gpr[22] = 0x1,
65378a8da06SSandipan Das 				}
65478a8da06SSandipan Das 			},
65578a8da06SSandipan Das 			{
65678a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
657*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
65878a8da06SSandipan Das 				.regs = {
65978a8da06SSandipan Das 					.gpr[21] = INT_MIN,
66078a8da06SSandipan Das 					.gpr[22] = INT_MIN,
66178a8da06SSandipan Das 				}
66278a8da06SSandipan Das 			},
66378a8da06SSandipan Das 			{
66478a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
665*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
66678a8da06SSandipan Das 				.regs = {
66778a8da06SSandipan Das 					.gpr[21] = INT_MIN,
66878a8da06SSandipan Das 					.gpr[22] = INT_MAX,
66978a8da06SSandipan Das 				}
67078a8da06SSandipan Das 			},
67178a8da06SSandipan Das 			{
67278a8da06SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
673*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
67478a8da06SSandipan Das 				.regs = {
67578a8da06SSandipan Das 					.gpr[21] = INT_MAX,
67678a8da06SSandipan Das 					.gpr[22] = INT_MAX,
67778a8da06SSandipan Das 				}
67878a8da06SSandipan Das 			},
67978a8da06SSandipan Das 			{
68078a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
681*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
68278a8da06SSandipan Das 				.regs = {
68378a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
68478a8da06SSandipan Das 					.gpr[22] = UINT_MAX,
68578a8da06SSandipan Das 				}
68678a8da06SSandipan Das 			},
68778a8da06SSandipan Das 			{
68878a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
689*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
69078a8da06SSandipan Das 				.regs = {
69178a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
69278a8da06SSandipan Das 					.gpr[22] = 0x1,
69378a8da06SSandipan Das 				}
69478a8da06SSandipan Das 			},
69578a8da06SSandipan Das 			{
69678a8da06SSandipan Das 				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
697*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
69878a8da06SSandipan Das 				.regs = {
69978a8da06SSandipan Das 					.gpr[21] = LONG_MIN | (uint)INT_MIN,
70078a8da06SSandipan Das 					.gpr[22] = LONG_MIN | (uint)INT_MIN,
70178a8da06SSandipan Das 				}
70278a8da06SSandipan Das 			}
70378a8da06SSandipan Das 		}
70478a8da06SSandipan Das 	},
70578a8da06SSandipan Das 	{
70678a8da06SSandipan Das 		.mnemonic = "addc.",
70778a8da06SSandipan Das 		.subtests = {
70878a8da06SSandipan Das 			{
70978a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MIN",
71078a8da06SSandipan Das 				.flags = IGNORE_CCR,
711*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
71278a8da06SSandipan Das 				.regs = {
71378a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
71478a8da06SSandipan Das 					.gpr[22] = LONG_MIN,
71578a8da06SSandipan Das 				}
71678a8da06SSandipan Das 			},
71778a8da06SSandipan Das 			{
71878a8da06SSandipan Das 				.descr = "RA = LONG_MIN, RB = LONG_MAX",
719*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
72078a8da06SSandipan Das 				.regs = {
72178a8da06SSandipan Das 					.gpr[21] = LONG_MIN,
72278a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
72378a8da06SSandipan Das 				}
72478a8da06SSandipan Das 			},
72578a8da06SSandipan Das 			{
72678a8da06SSandipan Das 				.descr = "RA = LONG_MAX, RB = LONG_MAX",
72778a8da06SSandipan Das 				.flags = IGNORE_CCR,
728*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
72978a8da06SSandipan Das 				.regs = {
73078a8da06SSandipan Das 					.gpr[21] = LONG_MAX,
73178a8da06SSandipan Das 					.gpr[22] = LONG_MAX,
73278a8da06SSandipan Das 				}
73378a8da06SSandipan Das 			},
73478a8da06SSandipan Das 			{
73578a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = ULONG_MAX",
736*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
73778a8da06SSandipan Das 				.regs = {
73878a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
73978a8da06SSandipan Das 					.gpr[22] = ULONG_MAX,
74078a8da06SSandipan Das 				}
74178a8da06SSandipan Das 			},
74278a8da06SSandipan Das 			{
74378a8da06SSandipan Das 				.descr = "RA = ULONG_MAX, RB = 0x1",
744*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
74578a8da06SSandipan Das 				.regs = {
74678a8da06SSandipan Das 					.gpr[21] = ULONG_MAX,
74778a8da06SSandipan Das 					.gpr[22] = 0x1,
74878a8da06SSandipan Das 				}
74978a8da06SSandipan Das 			},
75078a8da06SSandipan Das 			{
75178a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MIN",
752*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
75378a8da06SSandipan Das 				.regs = {
75478a8da06SSandipan Das 					.gpr[21] = INT_MIN,
75578a8da06SSandipan Das 					.gpr[22] = INT_MIN,
75678a8da06SSandipan Das 				}
75778a8da06SSandipan Das 			},
75878a8da06SSandipan Das 			{
75978a8da06SSandipan Das 				.descr = "RA = INT_MIN, RB = INT_MAX",
760*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
76178a8da06SSandipan Das 				.regs = {
76278a8da06SSandipan Das 					.gpr[21] = INT_MIN,
76378a8da06SSandipan Das 					.gpr[22] = INT_MAX,
76478a8da06SSandipan Das 				}
76578a8da06SSandipan Das 			},
76678a8da06SSandipan Das 			{
76778a8da06SSandipan Das 				.descr = "RA = INT_MAX, RB = INT_MAX",
768*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
76978a8da06SSandipan Das 				.regs = {
77078a8da06SSandipan Das 					.gpr[21] = INT_MAX,
77178a8da06SSandipan Das 					.gpr[22] = INT_MAX,
77278a8da06SSandipan Das 				}
77378a8da06SSandipan Das 			},
77478a8da06SSandipan Das 			{
77578a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = UINT_MAX",
776*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
77778a8da06SSandipan Das 				.regs = {
77878a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
77978a8da06SSandipan Das 					.gpr[22] = UINT_MAX,
78078a8da06SSandipan Das 				}
78178a8da06SSandipan Das 			},
78278a8da06SSandipan Das 			{
78378a8da06SSandipan Das 				.descr = "RA = UINT_MAX, RB = 0x1",
784*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
78578a8da06SSandipan Das 				.regs = {
78678a8da06SSandipan Das 					.gpr[21] = UINT_MAX,
78778a8da06SSandipan Das 					.gpr[22] = 0x1,
78878a8da06SSandipan Das 				}
78978a8da06SSandipan Das 			},
79078a8da06SSandipan Das 			{
79178a8da06SSandipan Das 				.descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
792*1d33dd84SBalamuruhan S 				.instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
79378a8da06SSandipan Das 				.regs = {
79478a8da06SSandipan Das 					.gpr[21] = LONG_MIN | (uint)INT_MIN,
79578a8da06SSandipan Das 					.gpr[22] = LONG_MIN | (uint)INT_MIN,
79678a8da06SSandipan Das 				}
79778a8da06SSandipan Das 			}
79878a8da06SSandipan Das 		}
79984022ac1SSandipan Das 	}
80084022ac1SSandipan Das };
80184022ac1SSandipan Das 
80284022ac1SSandipan Das static int __init emulate_compute_instr(struct pt_regs *regs,
80394afd069SJordan Niethe 					struct ppc_inst instr)
80484022ac1SSandipan Das {
80584022ac1SSandipan Das 	struct instruction_op op;
80684022ac1SSandipan Das 
807777e26f0SJordan Niethe 	if (!regs || !ppc_inst_val(instr))
80884022ac1SSandipan Das 		return -EINVAL;
80984022ac1SSandipan Das 
81084022ac1SSandipan Das 	if (analyse_instr(&op, regs, instr) != 1 ||
81184022ac1SSandipan Das 	    GETTYPE(op.type) != COMPUTE) {
812777e26f0SJordan Niethe 		pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr));
81384022ac1SSandipan Das 		return -EFAULT;
81484022ac1SSandipan Das 	}
81584022ac1SSandipan Das 
81684022ac1SSandipan Das 	emulate_update_regs(regs, &op);
81784022ac1SSandipan Das 	return 0;
81884022ac1SSandipan Das }
81984022ac1SSandipan Das 
82084022ac1SSandipan Das static int __init execute_compute_instr(struct pt_regs *regs,
82194afd069SJordan Niethe 					struct ppc_inst instr)
82284022ac1SSandipan Das {
82384022ac1SSandipan Das 	extern int exec_instr(struct pt_regs *regs);
82484022ac1SSandipan Das 	extern s32 patch__exec_instr;
82584022ac1SSandipan Das 
826777e26f0SJordan Niethe 	if (!regs || !ppc_inst_val(instr))
82784022ac1SSandipan Das 		return -EINVAL;
82884022ac1SSandipan Das 
82984022ac1SSandipan Das 	/* Patch the NOP with the actual instruction */
83084022ac1SSandipan Das 	patch_instruction_site(&patch__exec_instr, instr);
83184022ac1SSandipan Das 	if (exec_instr(regs)) {
832777e26f0SJordan Niethe 		pr_info("execution failed, instruction = 0x%08x\n", ppc_inst_val(instr));
83384022ac1SSandipan Das 		return -EFAULT;
83484022ac1SSandipan Das 	}
83584022ac1SSandipan Das 
83684022ac1SSandipan Das 	return 0;
83784022ac1SSandipan Das }
83884022ac1SSandipan Das 
83984022ac1SSandipan Das #define gpr_mismatch(gprn, exp, got)	\
84084022ac1SSandipan Das 	pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
84184022ac1SSandipan Das 		gprn, exp, got)
84284022ac1SSandipan Das 
84384022ac1SSandipan Das #define reg_mismatch(name, exp, got)	\
84484022ac1SSandipan Das 	pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n",	\
84584022ac1SSandipan Das 		name, exp, got)
84684022ac1SSandipan Das 
84784022ac1SSandipan Das static void __init run_tests_compute(void)
84884022ac1SSandipan Das {
84984022ac1SSandipan Das 	unsigned long flags;
85084022ac1SSandipan Das 	struct compute_test *test;
85184022ac1SSandipan Das 	struct pt_regs *regs, exp, got;
85294afd069SJordan Niethe 	unsigned int i, j, k;
85394afd069SJordan Niethe 	struct ppc_inst instr;
85484022ac1SSandipan Das 	bool ignore_gpr, ignore_xer, ignore_ccr, passed;
85584022ac1SSandipan Das 
85684022ac1SSandipan Das 	for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
85784022ac1SSandipan Das 		test = &compute_tests[i];
85884022ac1SSandipan Das 
85984022ac1SSandipan Das 		for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
86084022ac1SSandipan Das 			instr = test->subtests[j].instr;
86184022ac1SSandipan Das 			flags = test->subtests[j].flags;
86284022ac1SSandipan Das 			regs = &test->subtests[j].regs;
86384022ac1SSandipan Das 			ignore_xer = flags & IGNORE_XER;
86484022ac1SSandipan Das 			ignore_ccr = flags & IGNORE_CCR;
86584022ac1SSandipan Das 			passed = true;
86684022ac1SSandipan Das 
86784022ac1SSandipan Das 			memcpy(&exp, regs, sizeof(struct pt_regs));
86884022ac1SSandipan Das 			memcpy(&got, regs, sizeof(struct pt_regs));
86984022ac1SSandipan Das 
87084022ac1SSandipan Das 			/*
87184022ac1SSandipan Das 			 * Set a compatible MSR value explicitly to ensure
87284022ac1SSandipan Das 			 * that XER and CR bits are updated appropriately
87384022ac1SSandipan Das 			 */
87484022ac1SSandipan Das 			exp.msr = MSR_KERNEL;
87584022ac1SSandipan Das 			got.msr = MSR_KERNEL;
87684022ac1SSandipan Das 
87784022ac1SSandipan Das 			if (emulate_compute_instr(&got, instr) ||
87884022ac1SSandipan Das 			    execute_compute_instr(&exp, instr)) {
87984022ac1SSandipan Das 				passed = false;
88084022ac1SSandipan Das 				goto print;
88184022ac1SSandipan Das 			}
88284022ac1SSandipan Das 
88384022ac1SSandipan Das 			/* Verify GPR values */
88484022ac1SSandipan Das 			for (k = 0; k < 32; k++) {
88584022ac1SSandipan Das 				ignore_gpr = flags & IGNORE_GPR(k);
88684022ac1SSandipan Das 				if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
88784022ac1SSandipan Das 					passed = false;
88884022ac1SSandipan Das 					gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
88984022ac1SSandipan Das 				}
89084022ac1SSandipan Das 			}
89184022ac1SSandipan Das 
89284022ac1SSandipan Das 			/* Verify LR value */
89384022ac1SSandipan Das 			if (exp.link != got.link) {
89484022ac1SSandipan Das 				passed = false;
89584022ac1SSandipan Das 				reg_mismatch("LR", exp.link, got.link);
89684022ac1SSandipan Das 			}
89784022ac1SSandipan Das 
89884022ac1SSandipan Das 			/* Verify XER value */
89984022ac1SSandipan Das 			if (!ignore_xer && exp.xer != got.xer) {
90084022ac1SSandipan Das 				passed = false;
90184022ac1SSandipan Das 				reg_mismatch("XER", exp.xer, got.xer);
90284022ac1SSandipan Das 			}
90384022ac1SSandipan Das 
90484022ac1SSandipan Das 			/* Verify CR value */
90584022ac1SSandipan Das 			if (!ignore_ccr && exp.ccr != got.ccr) {
90684022ac1SSandipan Das 				passed = false;
90784022ac1SSandipan Das 				reg_mismatch("CR", exp.ccr, got.ccr);
90884022ac1SSandipan Das 			}
90984022ac1SSandipan Das 
91084022ac1SSandipan Das print:
91184022ac1SSandipan Das 			show_result_with_descr(test->mnemonic,
91284022ac1SSandipan Das 					       test->subtests[j].descr,
91384022ac1SSandipan Das 					       passed ? "PASS" : "FAIL");
91484022ac1SSandipan Das 		}
91584022ac1SSandipan Das 	}
91684022ac1SSandipan Das }
91784022ac1SSandipan Das 
91884022ac1SSandipan Das static int __init test_emulate_step(void)
91984022ac1SSandipan Das {
92084022ac1SSandipan Das 	printk(KERN_INFO "Running instruction emulation self-tests ...\n");
92184022ac1SSandipan Das 	run_tests_load_store();
92284022ac1SSandipan Das 	run_tests_compute();
9234ceae137SRavi Bangoria 
9244ceae137SRavi Bangoria 	return 0;
9254ceae137SRavi Bangoria }
9264ceae137SRavi Bangoria late_initcall(test_emulate_step);
927