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(®s); 744ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 754ceae137SRavi Bangoria 764ceae137SRavi Bangoria /* ld r5, 0(r3) */ 771d33dd84SBalamuruhan S stepped = emulate_step(®s, 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(®s); 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(®s, 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(®s); 1154ceae137SRavi Bangoria regs.gpr[3] = (unsigned long) &a; 1164ceae137SRavi Bangoria 1174ceae137SRavi Bangoria /* lwz r5, 0(r3) */ 1181d33dd84SBalamuruhan S stepped = emulate_step(®s, 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(®s); 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(®s, 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(®s); 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(®s, 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(®s); 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(®s, 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(®s); 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(®s, 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(®s); 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(®s, 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(®s, 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(®s); 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(®s, 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(®s, 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(®s); 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(®s, 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(®s, 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(®s); 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(®s, 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(®s, 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(®s); 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(®s, 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(®s, 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