18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Simple sanity tests for instruction emulation infrastructure. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2016 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "emulate_step_test: " fmt 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 118c2ecf20Sopenharmony_ci#include <asm/cpu_has_feature.h> 128c2ecf20Sopenharmony_ci#include <asm/sstep.h> 138c2ecf20Sopenharmony_ci#include <asm/ppc-opcode.h> 148c2ecf20Sopenharmony_ci#include <asm/code-patching.h> 158c2ecf20Sopenharmony_ci#include <asm/inst.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define MAX_SUBTESTS 16 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define IGNORE_GPR(n) (0x1UL << (n)) 208c2ecf20Sopenharmony_ci#define IGNORE_XER (0x1UL << 32) 218c2ecf20Sopenharmony_ci#define IGNORE_CCR (0x1UL << 33) 228c2ecf20Sopenharmony_ci#define NEGATIVE_TEST (0x1UL << 63) 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define TEST_PLD(r, base, i, pr) \ 258c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 268c2ecf20Sopenharmony_ci PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define TEST_PLWZ(r, base, i, pr) \ 298c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 308c2ecf20Sopenharmony_ci PPC_RAW_LWZ(r, base, i)) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define TEST_PSTD(r, base, i, pr) \ 338c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 348c2ecf20Sopenharmony_ci PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define TEST_PLFS(r, base, i, pr) \ 378c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 388c2ecf20Sopenharmony_ci PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define TEST_PSTFS(r, base, i, pr) \ 418c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 428c2ecf20Sopenharmony_ci PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define TEST_PLFD(r, base, i, pr) \ 458c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 468c2ecf20Sopenharmony_ci PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define TEST_PSTFD(r, base, i, pr) \ 498c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 508c2ecf20Sopenharmony_ci PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define TEST_PADDI(t, a, i, pr) \ 538c2ecf20Sopenharmony_ci ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 548c2ecf20Sopenharmony_ci PPC_RAW_ADDI(t, a, i)) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void __init init_pt_regs(struct pt_regs *regs) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci static unsigned long msr; 608c2ecf20Sopenharmony_ci static bool msr_cached; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci memset(regs, 0, sizeof(struct pt_regs)); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if (likely(msr_cached)) { 658c2ecf20Sopenharmony_ci regs->msr = msr; 668c2ecf20Sopenharmony_ci return; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci asm volatile("mfmsr %0" : "=r"(regs->msr)); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci regs->msr |= MSR_FP; 728c2ecf20Sopenharmony_ci regs->msr |= MSR_VEC; 738c2ecf20Sopenharmony_ci regs->msr |= MSR_VSX; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci msr = regs->msr; 768c2ecf20Sopenharmony_ci msr_cached = true; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void __init show_result(char *mnemonic, char *result) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci pr_info("%-14s : %s\n", mnemonic, result); 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic void __init show_result_with_descr(char *mnemonic, char *descr, 858c2ecf20Sopenharmony_ci char *result) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci pr_info("%-14s : %-50s %s\n", mnemonic, descr, result); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic void __init test_ld(void) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci struct pt_regs regs; 938c2ecf20Sopenharmony_ci unsigned long a = 0x23; 948c2ecf20Sopenharmony_ci int stepped = -1; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci init_pt_regs(®s); 978c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &a; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* ld r5, 0(r3) */ 1008c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0))); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a) 1038c2ecf20Sopenharmony_ci show_result("ld", "PASS"); 1048c2ecf20Sopenharmony_ci else 1058c2ecf20Sopenharmony_ci show_result("ld", "FAIL"); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic void __init test_pld(void) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct pt_regs regs; 1118c2ecf20Sopenharmony_ci unsigned long a = 0x23; 1128c2ecf20Sopenharmony_ci int stepped = -1; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 1158c2ecf20Sopenharmony_ci show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 1168c2ecf20Sopenharmony_ci return; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci init_pt_regs(®s); 1208c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long)&a; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* pld r5, 0(r3), 0 */ 1238c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0)); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a) 1268c2ecf20Sopenharmony_ci show_result("pld", "PASS"); 1278c2ecf20Sopenharmony_ci else 1288c2ecf20Sopenharmony_ci show_result("pld", "FAIL"); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void __init test_lwz(void) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct pt_regs regs; 1348c2ecf20Sopenharmony_ci unsigned int a = 0x4545; 1358c2ecf20Sopenharmony_ci int stepped = -1; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci init_pt_regs(®s); 1388c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &a; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci /* lwz r5, 0(r3) */ 1418c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0))); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a) 1448c2ecf20Sopenharmony_ci show_result("lwz", "PASS"); 1458c2ecf20Sopenharmony_ci else 1468c2ecf20Sopenharmony_ci show_result("lwz", "FAIL"); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void __init test_plwz(void) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci struct pt_regs regs; 1528c2ecf20Sopenharmony_ci unsigned int a = 0x4545; 1538c2ecf20Sopenharmony_ci int stepped = -1; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 1568c2ecf20Sopenharmony_ci show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)"); 1578c2ecf20Sopenharmony_ci return; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci init_pt_regs(®s); 1618c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long)&a; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* plwz r5, 0(r3), 0 */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0)); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a) 1688c2ecf20Sopenharmony_ci show_result("plwz", "PASS"); 1698c2ecf20Sopenharmony_ci else 1708c2ecf20Sopenharmony_ci show_result("plwz", "FAIL"); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void __init test_lwzx(void) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct pt_regs regs; 1768c2ecf20Sopenharmony_ci unsigned int a[3] = {0x0, 0x0, 0x1234}; 1778c2ecf20Sopenharmony_ci int stepped = -1; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci init_pt_regs(®s); 1808c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) a; 1818c2ecf20Sopenharmony_ci regs.gpr[4] = 8; 1828c2ecf20Sopenharmony_ci regs.gpr[5] = 0x8765; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* lwzx r5, r3, r4 */ 1858c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4))); 1868c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a[2]) 1878c2ecf20Sopenharmony_ci show_result("lwzx", "PASS"); 1888c2ecf20Sopenharmony_ci else 1898c2ecf20Sopenharmony_ci show_result("lwzx", "FAIL"); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic void __init test_std(void) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci struct pt_regs regs; 1958c2ecf20Sopenharmony_ci unsigned long a = 0x1234; 1968c2ecf20Sopenharmony_ci int stepped = -1; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci init_pt_regs(®s); 1998c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &a; 2008c2ecf20Sopenharmony_ci regs.gpr[5] = 0x5678; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* std r5, 0(r3) */ 2038c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0))); 2048c2ecf20Sopenharmony_ci if (stepped == 1 && regs.gpr[5] == a) 2058c2ecf20Sopenharmony_ci show_result("std", "PASS"); 2068c2ecf20Sopenharmony_ci else 2078c2ecf20Sopenharmony_ci show_result("std", "FAIL"); 2088c2ecf20Sopenharmony_ci} 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic void __init test_pstd(void) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct pt_regs regs; 2138c2ecf20Sopenharmony_ci unsigned long a = 0x1234; 2148c2ecf20Sopenharmony_ci int stepped = -1; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 2178c2ecf20Sopenharmony_ci show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)"); 2188c2ecf20Sopenharmony_ci return; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci init_pt_regs(®s); 2228c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long)&a; 2238c2ecf20Sopenharmony_ci regs.gpr[5] = 0x5678; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* pstd r5, 0(r3), 0 */ 2268c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0)); 2278c2ecf20Sopenharmony_ci if (stepped == 1 || regs.gpr[5] == a) 2288c2ecf20Sopenharmony_ci show_result("pstd", "PASS"); 2298c2ecf20Sopenharmony_ci else 2308c2ecf20Sopenharmony_ci show_result("pstd", "FAIL"); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic void __init test_ldarx_stdcx(void) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct pt_regs regs; 2368c2ecf20Sopenharmony_ci unsigned long a = 0x1234; 2378c2ecf20Sopenharmony_ci int stepped = -1; 2388c2ecf20Sopenharmony_ci unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */ 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci init_pt_regs(®s); 2418c2ecf20Sopenharmony_ci asm volatile("mfcr %0" : "=r"(regs.ccr)); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /*** ldarx ***/ 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &a; 2478c2ecf20Sopenharmony_ci regs.gpr[4] = 0; 2488c2ecf20Sopenharmony_ci regs.gpr[5] = 0x5678; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* ldarx r5, r3, r4, 0 */ 2518c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0))); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* 2548c2ecf20Sopenharmony_ci * Don't touch 'a' here. Touching 'a' can do Load/store 2558c2ecf20Sopenharmony_ci * of 'a' which result in failure of subsequent stdcx. 2568c2ecf20Sopenharmony_ci * Instead, use hardcoded value for comparison. 2578c2ecf20Sopenharmony_ci */ 2588c2ecf20Sopenharmony_ci if (stepped <= 0 || regs.gpr[5] != 0x1234) { 2598c2ecf20Sopenharmony_ci show_result("ldarx / stdcx.", "FAIL (ldarx)"); 2608c2ecf20Sopenharmony_ci return; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /*** stdcx. ***/ 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci regs.gpr[5] = 0x9ABC; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* stdcx. r5, r3, r4 */ 2698c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4))); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* 2728c2ecf20Sopenharmony_ci * Two possible scenarios that indicates successful emulation 2738c2ecf20Sopenharmony_ci * of stdcx. : 2748c2ecf20Sopenharmony_ci * 1. Reservation is active and store is performed. In this 2758c2ecf20Sopenharmony_ci * case cr0.eq bit will be set to 1. 2768c2ecf20Sopenharmony_ci * 2. Reservation is not active and store is not performed. 2778c2ecf20Sopenharmony_ci * In this case cr0.eq bit will be set to 0. 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq)) 2808c2ecf20Sopenharmony_ci || (regs.gpr[5] != a && !(regs.ccr & cr0_eq)))) 2818c2ecf20Sopenharmony_ci show_result("ldarx / stdcx.", "PASS"); 2828c2ecf20Sopenharmony_ci else 2838c2ecf20Sopenharmony_ci show_result("ldarx / stdcx.", "FAIL (stdcx.)"); 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_FPU 2878c2ecf20Sopenharmony_cistatic void __init test_lfsx_stfsx(void) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct pt_regs regs; 2908c2ecf20Sopenharmony_ci union { 2918c2ecf20Sopenharmony_ci float a; 2928c2ecf20Sopenharmony_ci int b; 2938c2ecf20Sopenharmony_ci } c; 2948c2ecf20Sopenharmony_ci int cached_b; 2958c2ecf20Sopenharmony_ci int stepped = -1; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci init_pt_regs(®s); 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /*** lfsx ***/ 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci c.a = 123.45; 3038c2ecf20Sopenharmony_ci cached_b = c.b; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &c.a; 3068c2ecf20Sopenharmony_ci regs.gpr[4] = 0; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci /* lfsx frt10, r3, r4 */ 3098c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4))); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (stepped == 1) 3128c2ecf20Sopenharmony_ci show_result("lfsx", "PASS"); 3138c2ecf20Sopenharmony_ci else 3148c2ecf20Sopenharmony_ci show_result("lfsx", "FAIL"); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /*** stfsx ***/ 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci c.a = 678.91; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* stfsx frs10, r3, r4 */ 3228c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4))); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (stepped == 1 && c.b == cached_b) 3258c2ecf20Sopenharmony_ci show_result("stfsx", "PASS"); 3268c2ecf20Sopenharmony_ci else 3278c2ecf20Sopenharmony_ci show_result("stfsx", "FAIL"); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic void __init test_plfs_pstfs(void) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct pt_regs regs; 3338c2ecf20Sopenharmony_ci union { 3348c2ecf20Sopenharmony_ci float a; 3358c2ecf20Sopenharmony_ci int b; 3368c2ecf20Sopenharmony_ci } c; 3378c2ecf20Sopenharmony_ci int cached_b; 3388c2ecf20Sopenharmony_ci int stepped = -1; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 3418c2ecf20Sopenharmony_ci show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 3428c2ecf20Sopenharmony_ci return; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci init_pt_regs(®s); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci /*** plfs ***/ 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci c.a = 123.45; 3518c2ecf20Sopenharmony_ci cached_b = c.b; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long)&c.a; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* plfs frt10, 0(r3), 0 */ 3568c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0)); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (stepped == 1) 3598c2ecf20Sopenharmony_ci show_result("plfs", "PASS"); 3608c2ecf20Sopenharmony_ci else 3618c2ecf20Sopenharmony_ci show_result("plfs", "FAIL"); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /*** pstfs ***/ 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci c.a = 678.91; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci /* pstfs frs10, 0(r3), 0 */ 3698c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0)); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci if (stepped == 1 && c.b == cached_b) 3728c2ecf20Sopenharmony_ci show_result("pstfs", "PASS"); 3738c2ecf20Sopenharmony_ci else 3748c2ecf20Sopenharmony_ci show_result("pstfs", "FAIL"); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic void __init test_lfdx_stfdx(void) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci struct pt_regs regs; 3808c2ecf20Sopenharmony_ci union { 3818c2ecf20Sopenharmony_ci double a; 3828c2ecf20Sopenharmony_ci long b; 3838c2ecf20Sopenharmony_ci } c; 3848c2ecf20Sopenharmony_ci long cached_b; 3858c2ecf20Sopenharmony_ci int stepped = -1; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci init_pt_regs(®s); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci /*** lfdx ***/ 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci c.a = 123456.78; 3938c2ecf20Sopenharmony_ci cached_b = c.b; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &c.a; 3968c2ecf20Sopenharmony_ci regs.gpr[4] = 0; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* lfdx frt10, r3, r4 */ 3998c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4))); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (stepped == 1) 4028c2ecf20Sopenharmony_ci show_result("lfdx", "PASS"); 4038c2ecf20Sopenharmony_ci else 4048c2ecf20Sopenharmony_ci show_result("lfdx", "FAIL"); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci /*** stfdx ***/ 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci c.a = 987654.32; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* stfdx frs10, r3, r4 */ 4128c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4))); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (stepped == 1 && c.b == cached_b) 4158c2ecf20Sopenharmony_ci show_result("stfdx", "PASS"); 4168c2ecf20Sopenharmony_ci else 4178c2ecf20Sopenharmony_ci show_result("stfdx", "FAIL"); 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic void __init test_plfd_pstfd(void) 4218c2ecf20Sopenharmony_ci{ 4228c2ecf20Sopenharmony_ci struct pt_regs regs; 4238c2ecf20Sopenharmony_ci union { 4248c2ecf20Sopenharmony_ci double a; 4258c2ecf20Sopenharmony_ci long b; 4268c2ecf20Sopenharmony_ci } c; 4278c2ecf20Sopenharmony_ci long cached_b; 4288c2ecf20Sopenharmony_ci int stepped = -1; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 4318c2ecf20Sopenharmony_ci show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 4328c2ecf20Sopenharmony_ci return; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci init_pt_regs(®s); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /*** plfd ***/ 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci c.a = 123456.78; 4418c2ecf20Sopenharmony_ci cached_b = c.b; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long)&c.a; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* plfd frt10, 0(r3), 0 */ 4468c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0)); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (stepped == 1) 4498c2ecf20Sopenharmony_ci show_result("plfd", "PASS"); 4508c2ecf20Sopenharmony_ci else 4518c2ecf20Sopenharmony_ci show_result("plfd", "FAIL"); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /*** pstfd ***/ 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci c.a = 987654.32; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci /* pstfd frs10, 0(r3), 0 */ 4598c2ecf20Sopenharmony_ci stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0)); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (stepped == 1 && c.b == cached_b) 4628c2ecf20Sopenharmony_ci show_result("pstfd", "PASS"); 4638c2ecf20Sopenharmony_ci else 4648c2ecf20Sopenharmony_ci show_result("pstfd", "FAIL"); 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci#else 4678c2ecf20Sopenharmony_cistatic void __init test_lfsx_stfsx(void) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 4708c2ecf20Sopenharmony_ci show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic void __init test_plfs_pstfs(void) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)"); 4768c2ecf20Sopenharmony_ci show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)"); 4778c2ecf20Sopenharmony_ci} 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_cistatic void __init test_lfdx_stfdx(void) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 4828c2ecf20Sopenharmony_ci show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic void __init test_plfd_pstfd(void) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)"); 4888c2ecf20Sopenharmony_ci show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)"); 4898c2ecf20Sopenharmony_ci} 4908c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_FPU */ 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci#ifdef CONFIG_ALTIVEC 4938c2ecf20Sopenharmony_cistatic void __init test_lvx_stvx(void) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct pt_regs regs; 4968c2ecf20Sopenharmony_ci union { 4978c2ecf20Sopenharmony_ci vector128 a; 4988c2ecf20Sopenharmony_ci u32 b[4]; 4998c2ecf20Sopenharmony_ci } c; 5008c2ecf20Sopenharmony_ci u32 cached_b[4]; 5018c2ecf20Sopenharmony_ci int stepped = -1; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci init_pt_regs(®s); 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci /*** lvx ***/ 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci cached_b[0] = c.b[0] = 923745; 5098c2ecf20Sopenharmony_ci cached_b[1] = c.b[1] = 2139478; 5108c2ecf20Sopenharmony_ci cached_b[2] = c.b[2] = 9012; 5118c2ecf20Sopenharmony_ci cached_b[3] = c.b[3] = 982134; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &c.a; 5148c2ecf20Sopenharmony_ci regs.gpr[4] = 0; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci /* lvx vrt10, r3, r4 */ 5178c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4))); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (stepped == 1) 5208c2ecf20Sopenharmony_ci show_result("lvx", "PASS"); 5218c2ecf20Sopenharmony_ci else 5228c2ecf20Sopenharmony_ci show_result("lvx", "FAIL"); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci /*** stvx ***/ 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci c.b[0] = 4987513; 5288c2ecf20Sopenharmony_ci c.b[1] = 84313948; 5298c2ecf20Sopenharmony_ci c.b[2] = 71; 5308c2ecf20Sopenharmony_ci c.b[3] = 498532; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* stvx vrs10, r3, r4 */ 5338c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4))); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 5368c2ecf20Sopenharmony_ci cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) 5378c2ecf20Sopenharmony_ci show_result("stvx", "PASS"); 5388c2ecf20Sopenharmony_ci else 5398c2ecf20Sopenharmony_ci show_result("stvx", "FAIL"); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci#else 5428c2ecf20Sopenharmony_cistatic void __init test_lvx_stvx(void) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)"); 5458c2ecf20Sopenharmony_ci show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)"); 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci#endif /* CONFIG_ALTIVEC */ 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci#ifdef CONFIG_VSX 5508c2ecf20Sopenharmony_cistatic void __init test_lxvd2x_stxvd2x(void) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci struct pt_regs regs; 5538c2ecf20Sopenharmony_ci union { 5548c2ecf20Sopenharmony_ci vector128 a; 5558c2ecf20Sopenharmony_ci u32 b[4]; 5568c2ecf20Sopenharmony_ci } c; 5578c2ecf20Sopenharmony_ci u32 cached_b[4]; 5588c2ecf20Sopenharmony_ci int stepped = -1; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci init_pt_regs(®s); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci /*** lxvd2x ***/ 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci cached_b[0] = c.b[0] = 18233; 5668c2ecf20Sopenharmony_ci cached_b[1] = c.b[1] = 34863571; 5678c2ecf20Sopenharmony_ci cached_b[2] = c.b[2] = 834; 5688c2ecf20Sopenharmony_ci cached_b[3] = c.b[3] = 6138911; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci regs.gpr[3] = (unsigned long) &c.a; 5718c2ecf20Sopenharmony_ci regs.gpr[4] = 0; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci /* lxvd2x vsr39, r3, r4 */ 5748c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4))); 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 5778c2ecf20Sopenharmony_ci show_result("lxvd2x", "PASS"); 5788c2ecf20Sopenharmony_ci } else { 5798c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_VSX)) 5808c2ecf20Sopenharmony_ci show_result("lxvd2x", "PASS (!CPU_FTR_VSX)"); 5818c2ecf20Sopenharmony_ci else 5828c2ecf20Sopenharmony_ci show_result("lxvd2x", "FAIL"); 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci /*** stxvd2x ***/ 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci c.b[0] = 21379463; 5898c2ecf20Sopenharmony_ci c.b[1] = 87; 5908c2ecf20Sopenharmony_ci c.b[2] = 374234; 5918c2ecf20Sopenharmony_ci c.b[3] = 4; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* stxvd2x vsr39, r3, r4 */ 5948c2ecf20Sopenharmony_ci stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4))); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 5978c2ecf20Sopenharmony_ci cached_b[2] == c.b[2] && cached_b[3] == c.b[3] && 5988c2ecf20Sopenharmony_ci cpu_has_feature(CPU_FTR_VSX)) { 5998c2ecf20Sopenharmony_ci show_result("stxvd2x", "PASS"); 6008c2ecf20Sopenharmony_ci } else { 6018c2ecf20Sopenharmony_ci if (!cpu_has_feature(CPU_FTR_VSX)) 6028c2ecf20Sopenharmony_ci show_result("stxvd2x", "PASS (!CPU_FTR_VSX)"); 6038c2ecf20Sopenharmony_ci else 6048c2ecf20Sopenharmony_ci show_result("stxvd2x", "FAIL"); 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci#else 6088c2ecf20Sopenharmony_cistatic void __init test_lxvd2x_stxvd2x(void) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)"); 6118c2ecf20Sopenharmony_ci show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)"); 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci#endif /* CONFIG_VSX */ 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_cistatic void __init run_tests_load_store(void) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci test_ld(); 6188c2ecf20Sopenharmony_ci test_pld(); 6198c2ecf20Sopenharmony_ci test_lwz(); 6208c2ecf20Sopenharmony_ci test_plwz(); 6218c2ecf20Sopenharmony_ci test_lwzx(); 6228c2ecf20Sopenharmony_ci test_std(); 6238c2ecf20Sopenharmony_ci test_pstd(); 6248c2ecf20Sopenharmony_ci test_ldarx_stdcx(); 6258c2ecf20Sopenharmony_ci test_lfsx_stfsx(); 6268c2ecf20Sopenharmony_ci test_plfs_pstfs(); 6278c2ecf20Sopenharmony_ci test_lfdx_stfdx(); 6288c2ecf20Sopenharmony_ci test_plfd_pstfd(); 6298c2ecf20Sopenharmony_ci test_lvx_stvx(); 6308c2ecf20Sopenharmony_ci test_lxvd2x_stxvd2x(); 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistruct compute_test { 6348c2ecf20Sopenharmony_ci char *mnemonic; 6358c2ecf20Sopenharmony_ci unsigned long cpu_feature; 6368c2ecf20Sopenharmony_ci struct { 6378c2ecf20Sopenharmony_ci char *descr; 6388c2ecf20Sopenharmony_ci unsigned long flags; 6398c2ecf20Sopenharmony_ci struct ppc_inst instr; 6408c2ecf20Sopenharmony_ci struct pt_regs regs; 6418c2ecf20Sopenharmony_ci } subtests[MAX_SUBTESTS + 1]; 6428c2ecf20Sopenharmony_ci}; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */ 6458c2ecf20Sopenharmony_ci#define SI_MIN BIT(33) 6468c2ecf20Sopenharmony_ci#define SI_MAX (BIT(33) - 1) 6478c2ecf20Sopenharmony_ci#define SI_UMAX (BIT(34) - 1) 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_cistatic struct compute_test compute_tests[] = { 6508c2ecf20Sopenharmony_ci { 6518c2ecf20Sopenharmony_ci .mnemonic = "nop", 6528c2ecf20Sopenharmony_ci .subtests = { 6538c2ecf20Sopenharmony_ci { 6548c2ecf20Sopenharmony_ci .descr = "R0 = LONG_MAX", 6558c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_INST_NOP), 6568c2ecf20Sopenharmony_ci .regs = { 6578c2ecf20Sopenharmony_ci .gpr[0] = LONG_MAX, 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci }, 6628c2ecf20Sopenharmony_ci { 6638c2ecf20Sopenharmony_ci .mnemonic = "add", 6648c2ecf20Sopenharmony_ci .subtests = { 6658c2ecf20Sopenharmony_ci { 6668c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 6678c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 6688c2ecf20Sopenharmony_ci .regs = { 6698c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 6708c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 6718c2ecf20Sopenharmony_ci } 6728c2ecf20Sopenharmony_ci }, 6738c2ecf20Sopenharmony_ci { 6748c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 6758c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 6768c2ecf20Sopenharmony_ci .regs = { 6778c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 6788c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci }, 6818c2ecf20Sopenharmony_ci { 6828c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX, RB = LONG_MAX", 6838c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 6848c2ecf20Sopenharmony_ci .regs = { 6858c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX, 6868c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci }, 6898c2ecf20Sopenharmony_ci { 6908c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 6918c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 6928c2ecf20Sopenharmony_ci .regs = { 6938c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 6948c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci }, 6978c2ecf20Sopenharmony_ci { 6988c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = 0x1", 6998c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7008c2ecf20Sopenharmony_ci .regs = { 7018c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 7028c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci }, 7058c2ecf20Sopenharmony_ci { 7068c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MIN", 7078c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7088c2ecf20Sopenharmony_ci .regs = { 7098c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 7108c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 7118c2ecf20Sopenharmony_ci } 7128c2ecf20Sopenharmony_ci }, 7138c2ecf20Sopenharmony_ci { 7148c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MAX", 7158c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7168c2ecf20Sopenharmony_ci .regs = { 7178c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 7188c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 7198c2ecf20Sopenharmony_ci } 7208c2ecf20Sopenharmony_ci }, 7218c2ecf20Sopenharmony_ci { 7228c2ecf20Sopenharmony_ci .descr = "RA = INT_MAX, RB = INT_MAX", 7238c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7248c2ecf20Sopenharmony_ci .regs = { 7258c2ecf20Sopenharmony_ci .gpr[21] = INT_MAX, 7268c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 7278c2ecf20Sopenharmony_ci } 7288c2ecf20Sopenharmony_ci }, 7298c2ecf20Sopenharmony_ci { 7308c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = UINT_MAX", 7318c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7328c2ecf20Sopenharmony_ci .regs = { 7338c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 7348c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 7358c2ecf20Sopenharmony_ci } 7368c2ecf20Sopenharmony_ci }, 7378c2ecf20Sopenharmony_ci { 7388c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = 0x1", 7398c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 7408c2ecf20Sopenharmony_ci .regs = { 7418c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 7428c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci }, 7478c2ecf20Sopenharmony_ci { 7488c2ecf20Sopenharmony_ci .mnemonic = "add.", 7498c2ecf20Sopenharmony_ci .subtests = { 7508c2ecf20Sopenharmony_ci { 7518c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 7528c2ecf20Sopenharmony_ci .flags = IGNORE_CCR, 7538c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7548c2ecf20Sopenharmony_ci .regs = { 7558c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 7568c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci }, 7598c2ecf20Sopenharmony_ci { 7608c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 7618c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7628c2ecf20Sopenharmony_ci .regs = { 7638c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 7648c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci }, 7678c2ecf20Sopenharmony_ci { 7688c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX, RB = LONG_MAX", 7698c2ecf20Sopenharmony_ci .flags = IGNORE_CCR, 7708c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7718c2ecf20Sopenharmony_ci .regs = { 7728c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX, 7738c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci }, 7768c2ecf20Sopenharmony_ci { 7778c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 7788c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7798c2ecf20Sopenharmony_ci .regs = { 7808c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 7818c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 7828c2ecf20Sopenharmony_ci } 7838c2ecf20Sopenharmony_ci }, 7848c2ecf20Sopenharmony_ci { 7858c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = 0x1", 7868c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7878c2ecf20Sopenharmony_ci .regs = { 7888c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 7898c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci }, 7928c2ecf20Sopenharmony_ci { 7938c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MIN", 7948c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 7958c2ecf20Sopenharmony_ci .regs = { 7968c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 7978c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci }, 8008c2ecf20Sopenharmony_ci { 8018c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MAX", 8028c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 8038c2ecf20Sopenharmony_ci .regs = { 8048c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 8058c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 8068c2ecf20Sopenharmony_ci } 8078c2ecf20Sopenharmony_ci }, 8088c2ecf20Sopenharmony_ci { 8098c2ecf20Sopenharmony_ci .descr = "RA = INT_MAX, RB = INT_MAX", 8108c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 8118c2ecf20Sopenharmony_ci .regs = { 8128c2ecf20Sopenharmony_ci .gpr[21] = INT_MAX, 8138c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci }, 8168c2ecf20Sopenharmony_ci { 8178c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = UINT_MAX", 8188c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 8198c2ecf20Sopenharmony_ci .regs = { 8208c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 8218c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci }, 8248c2ecf20Sopenharmony_ci { 8258c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = 0x1", 8268c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 8278c2ecf20Sopenharmony_ci .regs = { 8288c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 8298c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci }, 8348c2ecf20Sopenharmony_ci { 8358c2ecf20Sopenharmony_ci .mnemonic = "addc", 8368c2ecf20Sopenharmony_ci .subtests = { 8378c2ecf20Sopenharmony_ci { 8388c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 8398c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8408c2ecf20Sopenharmony_ci .regs = { 8418c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 8428c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 8438c2ecf20Sopenharmony_ci } 8448c2ecf20Sopenharmony_ci }, 8458c2ecf20Sopenharmony_ci { 8468c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 8478c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8488c2ecf20Sopenharmony_ci .regs = { 8498c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 8508c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci }, 8538c2ecf20Sopenharmony_ci { 8548c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX, RB = LONG_MAX", 8558c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8568c2ecf20Sopenharmony_ci .regs = { 8578c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX, 8588c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci }, 8618c2ecf20Sopenharmony_ci { 8628c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 8638c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8648c2ecf20Sopenharmony_ci .regs = { 8658c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 8668c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 8678c2ecf20Sopenharmony_ci } 8688c2ecf20Sopenharmony_ci }, 8698c2ecf20Sopenharmony_ci { 8708c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = 0x1", 8718c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8728c2ecf20Sopenharmony_ci .regs = { 8738c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 8748c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci }, 8778c2ecf20Sopenharmony_ci { 8788c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MIN", 8798c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8808c2ecf20Sopenharmony_ci .regs = { 8818c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 8828c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci }, 8858c2ecf20Sopenharmony_ci { 8868c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MAX", 8878c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8888c2ecf20Sopenharmony_ci .regs = { 8898c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 8908c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci }, 8938c2ecf20Sopenharmony_ci { 8948c2ecf20Sopenharmony_ci .descr = "RA = INT_MAX, RB = INT_MAX", 8958c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 8968c2ecf20Sopenharmony_ci .regs = { 8978c2ecf20Sopenharmony_ci .gpr[21] = INT_MAX, 8988c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci }, 9018c2ecf20Sopenharmony_ci { 9028c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = UINT_MAX", 9038c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 9048c2ecf20Sopenharmony_ci .regs = { 9058c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 9068c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci }, 9098c2ecf20Sopenharmony_ci { 9108c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = 0x1", 9118c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 9128c2ecf20Sopenharmony_ci .regs = { 9138c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 9148c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 9158c2ecf20Sopenharmony_ci } 9168c2ecf20Sopenharmony_ci }, 9178c2ecf20Sopenharmony_ci { 9188c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 9198c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 9208c2ecf20Sopenharmony_ci .regs = { 9218c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN | (uint)INT_MIN, 9228c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN | (uint)INT_MIN, 9238c2ecf20Sopenharmony_ci } 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci }, 9278c2ecf20Sopenharmony_ci { 9288c2ecf20Sopenharmony_ci .mnemonic = "addc.", 9298c2ecf20Sopenharmony_ci .subtests = { 9308c2ecf20Sopenharmony_ci { 9318c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 9328c2ecf20Sopenharmony_ci .flags = IGNORE_CCR, 9338c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9348c2ecf20Sopenharmony_ci .regs = { 9358c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 9368c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 9378c2ecf20Sopenharmony_ci } 9388c2ecf20Sopenharmony_ci }, 9398c2ecf20Sopenharmony_ci { 9408c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 9418c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9428c2ecf20Sopenharmony_ci .regs = { 9438c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 9448c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci }, 9478c2ecf20Sopenharmony_ci { 9488c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX, RB = LONG_MAX", 9498c2ecf20Sopenharmony_ci .flags = IGNORE_CCR, 9508c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9518c2ecf20Sopenharmony_ci .regs = { 9528c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX, 9538c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci }, 9568c2ecf20Sopenharmony_ci { 9578c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 9588c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9598c2ecf20Sopenharmony_ci .regs = { 9608c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 9618c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci }, 9648c2ecf20Sopenharmony_ci { 9658c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, RB = 0x1", 9668c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9678c2ecf20Sopenharmony_ci .regs = { 9688c2ecf20Sopenharmony_ci .gpr[21] = ULONG_MAX, 9698c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci }, 9728c2ecf20Sopenharmony_ci { 9738c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MIN", 9748c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9758c2ecf20Sopenharmony_ci .regs = { 9768c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 9778c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci }, 9808c2ecf20Sopenharmony_ci { 9818c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, RB = INT_MAX", 9828c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9838c2ecf20Sopenharmony_ci .regs = { 9848c2ecf20Sopenharmony_ci .gpr[21] = INT_MIN, 9858c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 9868c2ecf20Sopenharmony_ci } 9878c2ecf20Sopenharmony_ci }, 9888c2ecf20Sopenharmony_ci { 9898c2ecf20Sopenharmony_ci .descr = "RA = INT_MAX, RB = INT_MAX", 9908c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9918c2ecf20Sopenharmony_ci .regs = { 9928c2ecf20Sopenharmony_ci .gpr[21] = INT_MAX, 9938c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 9948c2ecf20Sopenharmony_ci } 9958c2ecf20Sopenharmony_ci }, 9968c2ecf20Sopenharmony_ci { 9978c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = UINT_MAX", 9988c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 9998c2ecf20Sopenharmony_ci .regs = { 10008c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 10018c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci }, 10048c2ecf20Sopenharmony_ci { 10058c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, RB = 0x1", 10068c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 10078c2ecf20Sopenharmony_ci .regs = { 10088c2ecf20Sopenharmony_ci .gpr[21] = UINT_MAX, 10098c2ecf20Sopenharmony_ci .gpr[22] = 0x1, 10108c2ecf20Sopenharmony_ci } 10118c2ecf20Sopenharmony_ci }, 10128c2ecf20Sopenharmony_ci { 10138c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 10148c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 10158c2ecf20Sopenharmony_ci .regs = { 10168c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN | (uint)INT_MIN, 10178c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN | (uint)INT_MIN, 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci } 10218c2ecf20Sopenharmony_ci }, 10228c2ecf20Sopenharmony_ci { 10238c2ecf20Sopenharmony_ci .mnemonic = "divde", 10248c2ecf20Sopenharmony_ci .subtests = { 10258c2ecf20Sopenharmony_ci { 10268c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 10278c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 10288c2ecf20Sopenharmony_ci .regs = { 10298c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 10308c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 10318c2ecf20Sopenharmony_ci } 10328c2ecf20Sopenharmony_ci }, 10338c2ecf20Sopenharmony_ci { 10348c2ecf20Sopenharmony_ci .descr = "RA = 1L, RB = 0", 10358c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 10368c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 10378c2ecf20Sopenharmony_ci .regs = { 10388c2ecf20Sopenharmony_ci .gpr[21] = 1L, 10398c2ecf20Sopenharmony_ci .gpr[22] = 0, 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci }, 10428c2ecf20Sopenharmony_ci { 10438c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 10448c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 10458c2ecf20Sopenharmony_ci .regs = { 10468c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 10478c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci } 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci }, 10528c2ecf20Sopenharmony_ci { 10538c2ecf20Sopenharmony_ci .mnemonic = "divde.", 10548c2ecf20Sopenharmony_ci .subtests = { 10558c2ecf20Sopenharmony_ci { 10568c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 10578c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 10588c2ecf20Sopenharmony_ci .regs = { 10598c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 10608c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci }, 10638c2ecf20Sopenharmony_ci { 10648c2ecf20Sopenharmony_ci .descr = "RA = 1L, RB = 0", 10658c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 10668c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 10678c2ecf20Sopenharmony_ci .regs = { 10688c2ecf20Sopenharmony_ci .gpr[21] = 1L, 10698c2ecf20Sopenharmony_ci .gpr[22] = 0, 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci }, 10728c2ecf20Sopenharmony_ci { 10738c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 10748c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 10758c2ecf20Sopenharmony_ci .regs = { 10768c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 10778c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci } 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci }, 10828c2ecf20Sopenharmony_ci { 10838c2ecf20Sopenharmony_ci .mnemonic = "divdeu", 10848c2ecf20Sopenharmony_ci .subtests = { 10858c2ecf20Sopenharmony_ci { 10868c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 10878c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 10888c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 10898c2ecf20Sopenharmony_ci .regs = { 10908c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 10918c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 10928c2ecf20Sopenharmony_ci } 10938c2ecf20Sopenharmony_ci }, 10948c2ecf20Sopenharmony_ci { 10958c2ecf20Sopenharmony_ci .descr = "RA = 1L, RB = 0", 10968c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 10978c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 10988c2ecf20Sopenharmony_ci .regs = { 10998c2ecf20Sopenharmony_ci .gpr[21] = 1L, 11008c2ecf20Sopenharmony_ci .gpr[22] = 0, 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci }, 11038c2ecf20Sopenharmony_ci { 11048c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 11058c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 11068c2ecf20Sopenharmony_ci .regs = { 11078c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 11088c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci }, 11118c2ecf20Sopenharmony_ci { 11128c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 11138c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 11148c2ecf20Sopenharmony_ci .regs = { 11158c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX - 1, 11168c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci }, 11198c2ecf20Sopenharmony_ci { 11208c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 11218c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 11228c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 11238c2ecf20Sopenharmony_ci .regs = { 11248c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN + 1, 11258c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 11268c2ecf20Sopenharmony_ci } 11278c2ecf20Sopenharmony_ci } 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci }, 11308c2ecf20Sopenharmony_ci { 11318c2ecf20Sopenharmony_ci .mnemonic = "divdeu.", 11328c2ecf20Sopenharmony_ci .subtests = { 11338c2ecf20Sopenharmony_ci { 11348c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MIN", 11358c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 11368c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 11378c2ecf20Sopenharmony_ci .regs = { 11388c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 11398c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci }, 11428c2ecf20Sopenharmony_ci { 11438c2ecf20Sopenharmony_ci .descr = "RA = 1L, RB = 0", 11448c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 11458c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 11468c2ecf20Sopenharmony_ci .regs = { 11478c2ecf20Sopenharmony_ci .gpr[21] = 1L, 11488c2ecf20Sopenharmony_ci .gpr[22] = 0, 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci }, 11518c2ecf20Sopenharmony_ci { 11528c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, RB = LONG_MAX", 11538c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 11548c2ecf20Sopenharmony_ci .regs = { 11558c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN, 11568c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci }, 11598c2ecf20Sopenharmony_ci { 11608c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 11618c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 11628c2ecf20Sopenharmony_ci .regs = { 11638c2ecf20Sopenharmony_ci .gpr[21] = LONG_MAX - 1, 11648c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci }, 11678c2ecf20Sopenharmony_ci { 11688c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 11698c2ecf20Sopenharmony_ci .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 11708c2ecf20Sopenharmony_ci .flags = IGNORE_GPR(20), 11718c2ecf20Sopenharmony_ci .regs = { 11728c2ecf20Sopenharmony_ci .gpr[21] = LONG_MIN + 1, 11738c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci }, 11788c2ecf20Sopenharmony_ci { 11798c2ecf20Sopenharmony_ci .mnemonic = "paddi", 11808c2ecf20Sopenharmony_ci .cpu_feature = CPU_FTR_ARCH_31, 11818c2ecf20Sopenharmony_ci .subtests = { 11828c2ecf20Sopenharmony_ci { 11838c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0", 11848c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MIN, 0), 11858c2ecf20Sopenharmony_ci .regs = { 11868c2ecf20Sopenharmony_ci .gpr[21] = 0, 11878c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 11888c2ecf20Sopenharmony_ci } 11898c2ecf20Sopenharmony_ci }, 11908c2ecf20Sopenharmony_ci { 11918c2ecf20Sopenharmony_ci .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0", 11928c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MAX, 0), 11938c2ecf20Sopenharmony_ci .regs = { 11948c2ecf20Sopenharmony_ci .gpr[21] = 0, 11958c2ecf20Sopenharmony_ci .gpr[22] = LONG_MIN, 11968c2ecf20Sopenharmony_ci } 11978c2ecf20Sopenharmony_ci }, 11988c2ecf20Sopenharmony_ci { 11998c2ecf20Sopenharmony_ci .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0", 12008c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MAX, 0), 12018c2ecf20Sopenharmony_ci .regs = { 12028c2ecf20Sopenharmony_ci .gpr[21] = 0, 12038c2ecf20Sopenharmony_ci .gpr[22] = LONG_MAX, 12048c2ecf20Sopenharmony_ci } 12058c2ecf20Sopenharmony_ci }, 12068c2ecf20Sopenharmony_ci { 12078c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0", 12088c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_UMAX, 0), 12098c2ecf20Sopenharmony_ci .regs = { 12108c2ecf20Sopenharmony_ci .gpr[21] = 0, 12118c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci }, 12148c2ecf20Sopenharmony_ci { 12158c2ecf20Sopenharmony_ci .descr = "RA = ULONG_MAX, SI = 0x1, R = 0", 12168c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, 0x1, 0), 12178c2ecf20Sopenharmony_ci .regs = { 12188c2ecf20Sopenharmony_ci .gpr[21] = 0, 12198c2ecf20Sopenharmony_ci .gpr[22] = ULONG_MAX, 12208c2ecf20Sopenharmony_ci } 12218c2ecf20Sopenharmony_ci }, 12228c2ecf20Sopenharmony_ci { 12238c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, SI = SI_MIN, R = 0", 12248c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MIN, 0), 12258c2ecf20Sopenharmony_ci .regs = { 12268c2ecf20Sopenharmony_ci .gpr[21] = 0, 12278c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci }, 12308c2ecf20Sopenharmony_ci { 12318c2ecf20Sopenharmony_ci .descr = "RA = INT_MIN, SI = SI_MAX, R = 0", 12328c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MAX, 0), 12338c2ecf20Sopenharmony_ci .regs = { 12348c2ecf20Sopenharmony_ci .gpr[21] = 0, 12358c2ecf20Sopenharmony_ci .gpr[22] = INT_MIN, 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci }, 12388c2ecf20Sopenharmony_ci { 12398c2ecf20Sopenharmony_ci .descr = "RA = INT_MAX, SI = SI_MAX, R = 0", 12408c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MAX, 0), 12418c2ecf20Sopenharmony_ci .regs = { 12428c2ecf20Sopenharmony_ci .gpr[21] = 0, 12438c2ecf20Sopenharmony_ci .gpr[22] = INT_MAX, 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci }, 12468c2ecf20Sopenharmony_ci { 12478c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, SI = 0x1, R = 0", 12488c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, 0x1, 0), 12498c2ecf20Sopenharmony_ci .regs = { 12508c2ecf20Sopenharmony_ci .gpr[21] = 0, 12518c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 12528c2ecf20Sopenharmony_ci } 12538c2ecf20Sopenharmony_ci }, 12548c2ecf20Sopenharmony_ci { 12558c2ecf20Sopenharmony_ci .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0", 12568c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MAX, 0), 12578c2ecf20Sopenharmony_ci .regs = { 12588c2ecf20Sopenharmony_ci .gpr[21] = 0, 12598c2ecf20Sopenharmony_ci .gpr[22] = UINT_MAX, 12608c2ecf20Sopenharmony_ci } 12618c2ecf20Sopenharmony_ci }, 12628c2ecf20Sopenharmony_ci { 12638c2ecf20Sopenharmony_ci .descr = "RA is r0, SI = SI_MIN, R = 0", 12648c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 0, SI_MIN, 0), 12658c2ecf20Sopenharmony_ci .regs = { 12668c2ecf20Sopenharmony_ci .gpr[21] = 0x0, 12678c2ecf20Sopenharmony_ci } 12688c2ecf20Sopenharmony_ci }, 12698c2ecf20Sopenharmony_ci { 12708c2ecf20Sopenharmony_ci .descr = "RA = 0, SI = SI_MIN, R = 0", 12718c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, SI_MIN, 0), 12728c2ecf20Sopenharmony_ci .regs = { 12738c2ecf20Sopenharmony_ci .gpr[21] = 0x0, 12748c2ecf20Sopenharmony_ci .gpr[22] = 0x0, 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci }, 12778c2ecf20Sopenharmony_ci { 12788c2ecf20Sopenharmony_ci .descr = "RA is r0, SI = 0, R = 1", 12798c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 0, 0, 1), 12808c2ecf20Sopenharmony_ci .regs = { 12818c2ecf20Sopenharmony_ci .gpr[21] = 0, 12828c2ecf20Sopenharmony_ci } 12838c2ecf20Sopenharmony_ci }, 12848c2ecf20Sopenharmony_ci { 12858c2ecf20Sopenharmony_ci .descr = "RA is r0, SI = SI_MIN, R = 1", 12868c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 0, SI_MIN, 1), 12878c2ecf20Sopenharmony_ci .regs = { 12888c2ecf20Sopenharmony_ci .gpr[21] = 0, 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci }, 12918c2ecf20Sopenharmony_ci /* Invalid instruction form with R = 1 and RA != 0 */ 12928c2ecf20Sopenharmony_ci { 12938c2ecf20Sopenharmony_ci .descr = "RA = R22(0), SI = 0, R = 1", 12948c2ecf20Sopenharmony_ci .instr = TEST_PADDI(21, 22, 0, 1), 12958c2ecf20Sopenharmony_ci .flags = NEGATIVE_TEST, 12968c2ecf20Sopenharmony_ci .regs = { 12978c2ecf20Sopenharmony_ci .gpr[21] = 0, 12988c2ecf20Sopenharmony_ci .gpr[22] = 0, 12998c2ecf20Sopenharmony_ci } 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci } 13028c2ecf20Sopenharmony_ci } 13038c2ecf20Sopenharmony_ci}; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_cistatic int __init emulate_compute_instr(struct pt_regs *regs, 13068c2ecf20Sopenharmony_ci struct ppc_inst instr, 13078c2ecf20Sopenharmony_ci bool negative) 13088c2ecf20Sopenharmony_ci{ 13098c2ecf20Sopenharmony_ci int analysed; 13108c2ecf20Sopenharmony_ci struct instruction_op op; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (!regs || !ppc_inst_val(instr)) 13138c2ecf20Sopenharmony_ci return -EINVAL; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci regs->nip = patch_site_addr(&patch__exec_instr); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci analysed = analyse_instr(&op, regs, instr); 13188c2ecf20Sopenharmony_ci if (analysed != 1 || GETTYPE(op.type) != COMPUTE) { 13198c2ecf20Sopenharmony_ci if (negative) 13208c2ecf20Sopenharmony_ci return -EFAULT; 13218c2ecf20Sopenharmony_ci pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr)); 13228c2ecf20Sopenharmony_ci return -EFAULT; 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci if (analysed == 1 && negative) 13258c2ecf20Sopenharmony_ci pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr)); 13268c2ecf20Sopenharmony_ci if (!negative) 13278c2ecf20Sopenharmony_ci emulate_update_regs(regs, &op); 13288c2ecf20Sopenharmony_ci return 0; 13298c2ecf20Sopenharmony_ci} 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic int __init execute_compute_instr(struct pt_regs *regs, 13328c2ecf20Sopenharmony_ci struct ppc_inst instr) 13338c2ecf20Sopenharmony_ci{ 13348c2ecf20Sopenharmony_ci extern int exec_instr(struct pt_regs *regs); 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci if (!regs || !ppc_inst_val(instr)) 13378c2ecf20Sopenharmony_ci return -EINVAL; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci /* Patch the NOP with the actual instruction */ 13408c2ecf20Sopenharmony_ci patch_instruction_site(&patch__exec_instr, instr); 13418c2ecf20Sopenharmony_ci if (exec_instr(regs)) { 13428c2ecf20Sopenharmony_ci pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr)); 13438c2ecf20Sopenharmony_ci return -EFAULT; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci return 0; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci#define gpr_mismatch(gprn, exp, got) \ 13508c2ecf20Sopenharmony_ci pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 13518c2ecf20Sopenharmony_ci gprn, exp, got) 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci#define reg_mismatch(name, exp, got) \ 13548c2ecf20Sopenharmony_ci pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 13558c2ecf20Sopenharmony_ci name, exp, got) 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic void __init run_tests_compute(void) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci unsigned long flags; 13608c2ecf20Sopenharmony_ci struct compute_test *test; 13618c2ecf20Sopenharmony_ci struct pt_regs *regs, exp, got; 13628c2ecf20Sopenharmony_ci unsigned int i, j, k; 13638c2ecf20Sopenharmony_ci struct ppc_inst instr; 13648c2ecf20Sopenharmony_ci bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 13678c2ecf20Sopenharmony_ci test = &compute_tests[i]; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) { 13708c2ecf20Sopenharmony_ci show_result(test->mnemonic, "SKIP (!CPU_FTR)"); 13718c2ecf20Sopenharmony_ci continue; 13728c2ecf20Sopenharmony_ci } 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 13758c2ecf20Sopenharmony_ci instr = test->subtests[j].instr; 13768c2ecf20Sopenharmony_ci flags = test->subtests[j].flags; 13778c2ecf20Sopenharmony_ci regs = &test->subtests[j].regs; 13788c2ecf20Sopenharmony_ci negative = flags & NEGATIVE_TEST; 13798c2ecf20Sopenharmony_ci ignore_xer = flags & IGNORE_XER; 13808c2ecf20Sopenharmony_ci ignore_ccr = flags & IGNORE_CCR; 13818c2ecf20Sopenharmony_ci passed = true; 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci memcpy(&exp, regs, sizeof(struct pt_regs)); 13848c2ecf20Sopenharmony_ci memcpy(&got, regs, sizeof(struct pt_regs)); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci /* 13878c2ecf20Sopenharmony_ci * Set a compatible MSR value explicitly to ensure 13888c2ecf20Sopenharmony_ci * that XER and CR bits are updated appropriately 13898c2ecf20Sopenharmony_ci */ 13908c2ecf20Sopenharmony_ci exp.msr = MSR_KERNEL; 13918c2ecf20Sopenharmony_ci got.msr = MSR_KERNEL; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci rc = emulate_compute_instr(&got, instr, negative) != 0; 13948c2ecf20Sopenharmony_ci if (negative) { 13958c2ecf20Sopenharmony_ci /* skip executing instruction */ 13968c2ecf20Sopenharmony_ci passed = rc; 13978c2ecf20Sopenharmony_ci goto print; 13988c2ecf20Sopenharmony_ci } else if (rc || execute_compute_instr(&exp, instr)) { 13998c2ecf20Sopenharmony_ci passed = false; 14008c2ecf20Sopenharmony_ci goto print; 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci /* Verify GPR values */ 14048c2ecf20Sopenharmony_ci for (k = 0; k < 32; k++) { 14058c2ecf20Sopenharmony_ci ignore_gpr = flags & IGNORE_GPR(k); 14068c2ecf20Sopenharmony_ci if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 14078c2ecf20Sopenharmony_ci passed = false; 14088c2ecf20Sopenharmony_ci gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 14098c2ecf20Sopenharmony_ci } 14108c2ecf20Sopenharmony_ci } 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci /* Verify LR value */ 14138c2ecf20Sopenharmony_ci if (exp.link != got.link) { 14148c2ecf20Sopenharmony_ci passed = false; 14158c2ecf20Sopenharmony_ci reg_mismatch("LR", exp.link, got.link); 14168c2ecf20Sopenharmony_ci } 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci /* Verify XER value */ 14198c2ecf20Sopenharmony_ci if (!ignore_xer && exp.xer != got.xer) { 14208c2ecf20Sopenharmony_ci passed = false; 14218c2ecf20Sopenharmony_ci reg_mismatch("XER", exp.xer, got.xer); 14228c2ecf20Sopenharmony_ci } 14238c2ecf20Sopenharmony_ci 14248c2ecf20Sopenharmony_ci /* Verify CR value */ 14258c2ecf20Sopenharmony_ci if (!ignore_ccr && exp.ccr != got.ccr) { 14268c2ecf20Sopenharmony_ci passed = false; 14278c2ecf20Sopenharmony_ci reg_mismatch("CR", exp.ccr, got.ccr); 14288c2ecf20Sopenharmony_ci } 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ciprint: 14318c2ecf20Sopenharmony_ci show_result_with_descr(test->mnemonic, 14328c2ecf20Sopenharmony_ci test->subtests[j].descr, 14338c2ecf20Sopenharmony_ci passed ? "PASS" : "FAIL"); 14348c2ecf20Sopenharmony_ci } 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci} 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_cistatic int __init test_emulate_step(void) 14398c2ecf20Sopenharmony_ci{ 14408c2ecf20Sopenharmony_ci printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 14418c2ecf20Sopenharmony_ci run_tests_load_store(); 14428c2ecf20Sopenharmony_ci run_tests_compute(); 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci return 0; 14458c2ecf20Sopenharmony_ci} 14468c2ecf20Sopenharmony_cilate_initcall(test_emulate_step); 1447