powerpc/sstep: Add tests for prefixed integer load/stores
authorJordan Niethe <jniethe5@gmail.com>
Mon, 25 May 2020 02:59:19 +0000 (12:59 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 23 Jul 2020 07:25:06 +0000 (17:25 +1000)
Add tests for the prefixed versions of the integer load/stores that
are currently tested. This includes the following instructions:
  * Prefixed Load Doubleword (pld)
  * Prefixed Load Word and Zero (plwz)
  * Prefixed Store Doubleword (pstd)

Skip the new tests if ISA v3.1 is unsupported.

Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
[mpe: Fix conflicts with ppc-opcode.h changes]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200525025923.19843-1-jniethe5@gmail.com
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/lib/test_emulate_step.c

index 6b7a3f0..90ae33a 100644 (file)
 #define PPC_INST_BRANCH                        0x48000000
 #define PPC_INST_BRANCH_COND           0x40800000
 
+/* Prefixes */
+#define PPC_PREFIX_MLS                 0x06000000
+#define PPC_PREFIX_8LS                 0x04000000
+
+/* Prefixed instructions */
+#define PPC_INST_PLD                   0xe4000000
+#define PPC_INST_PSTD                  0xf4000000
+
 /* macros to insert fields into opcodes */
 #define ___PPC_RA(a)   (((a) & 0x1f) << 16)
 #define ___PPC_RB(b)   (((b) & 0x1f) << 11)
 #define __PPC_CT(t)    (((t) & 0x0f) << 21)
 #define __PPC_SPR(r)   ((((r) & 0x1f) << 16) | ((((r) >> 5) & 0x1f) << 11))
 #define __PPC_RC21     (0x1 << 10)
+#define __PPC_PRFX_R(r)        (((r) & 0x1) << 20)
 
 /*
  * Both low and high 16 bits are added as SIGNED additions, so if low 16 bits
index 988c734..34f1ea0 100644 (file)
 #define IGNORE_XER     (0x1UL << 32)
 #define IGNORE_CCR     (0x1UL << 33)
 
+#define TEST_PLD(r, base, i, pr) \
+       ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
+                       PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
+
+#define TEST_PLWZ(r, base, i, pr) \
+       ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
+                       PPC_RAW_LWZ(r, base, i))
+
+#define TEST_PSTD(r, base, i, pr) \
+       ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
+                       PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
+
 static void __init init_pt_regs(struct pt_regs *regs)
 {
        static unsigned long msr;
@@ -70,6 +82,29 @@ static void __init test_ld(void)
                show_result("ld", "FAIL");
 }
 
+static void __init test_pld(void)
+{
+       struct pt_regs regs;
+       unsigned long a = 0x23;
+       int stepped = -1;
+
+       if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
+               show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
+               return;
+       }
+
+       init_pt_regs(&regs);
+       regs.gpr[3] = (unsigned long)&a;
+
+       /* pld r5, 0(r3), 0 */
+       stepped = emulate_step(&regs, TEST_PLD(5, 3, 0, 0));
+
+       if (stepped == 1 && regs.gpr[5] == a)
+               show_result("pld", "PASS");
+       else
+               show_result("pld", "FAIL");
+}
+
 static void __init test_lwz(void)
 {
        struct pt_regs regs;
@@ -88,6 +123,30 @@ static void __init test_lwz(void)
                show_result("lwz", "FAIL");
 }
 
+static void __init test_plwz(void)
+{
+       struct pt_regs regs;
+       unsigned int a = 0x4545;
+       int stepped = -1;
+
+       if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
+               show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
+               return;
+       }
+
+       init_pt_regs(&regs);
+       regs.gpr[3] = (unsigned long)&a;
+
+       /* plwz r5, 0(r3), 0 */
+
+       stepped = emulate_step(&regs, TEST_PLWZ(5, 3, 0, 0));
+
+       if (stepped == 1 && regs.gpr[5] == a)
+               show_result("plwz", "PASS");
+       else
+               show_result("plwz", "FAIL");
+}
+
 static void __init test_lwzx(void)
 {
        struct pt_regs regs;
@@ -125,6 +184,29 @@ static void __init test_std(void)
                show_result("std", "FAIL");
 }
 
+static void __init test_pstd(void)
+{
+       struct pt_regs regs;
+       unsigned long a = 0x1234;
+       int stepped = -1;
+
+       if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
+               show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
+               return;
+       }
+
+       init_pt_regs(&regs);
+       regs.gpr[3] = (unsigned long)&a;
+       regs.gpr[5] = 0x5678;
+
+       /* pstd r5, 0(r3), 0 */
+       stepped = emulate_step(&regs, TEST_PSTD(5, 3, 0, 0));
+       if (stepped == 1 || regs.gpr[5] == a)
+               show_result("pstd", "PASS");
+       else
+               show_result("pstd", "FAIL");
+}
+
 static void __init test_ldarx_stdcx(void)
 {
        struct pt_regs regs;
@@ -404,9 +486,12 @@ static void __init test_lxvd2x_stxvd2x(void)
 static void __init run_tests_load_store(void)
 {
        test_ld();
+       test_pld();
        test_lwz();
+       test_plwz();
        test_lwzx();
        test_std();
+       test_pstd();
        test_ldarx_stdcx();
        test_lfsx_stfsx();
        test_lfdx_stfdx();