This add emulation for the prtyw and prtyd instructions.

Signed-off-by: Matt Brown <matthew.brown....@gmail.com>
---
 arch/powerpc/lib/sstep.c | 58 +++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 603654d..3228783 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -652,6 +652,42 @@ static nokprobe_inline void do_bpermd(struct pt_regs 
*regs, unsigned long v1,
        regs->gpr[ra] = 0 | perm;
 }
 
+static nokprobe_inline void do_prtyw(struct pt_regs *regs, unsigned long v,
+                               int ra)
+{
+       unsigned long low, high, out;
+       unsigned int i;
+
+       high = 0;
+       low = 0;
+       out = 0;
+
+       for (i = 0; i < 8; i++) {
+               if (v & (1 << (i * 8)))
+                       (i < 4) ? (low++) : (high++);
+       }
+
+       if (low % 2)
+               out |= low;
+       if (high % 2)
+               out |= (high << 32);
+
+       regs->gpr[ra] = out;
+}
+
+static nokprobe_inline void do_prtyd(struct pt_regs *regs, unsigned long v,
+                               int ra)
+{
+       unsigned int count, i;
+
+       count = 0;
+       for (i = 0; i < 8; i++) {
+               if (v & (1 << (i * 8)))
+                       count++;
+       }
+       regs->gpr[ra] = count % 2;
+}
+
 static nokprobe_inline int trap_compare(long v1, long v2)
 {
        int ret = 0;
@@ -1278,16 +1314,15 @@ int analyse_instr(struct instruction_op *op, struct 
pt_regs *regs,
                        do_popcnt(regs, val, 8, ra);
                        goto logical_done;
 
-               case 17076744:  /* popcntw */
+               case 2101768:   /* prtyw */
                        val = regs->gpr[rd];
-                       do_popcnt(regs, val, 32, ra);
+                       do_prtyw(regs, val, ra);
                        goto logical_done;
-#ifdef __powerpc64__
-               case 19173896:  /* popcntd */
+
+               case 2134536:   /* prtyd */
                        val = regs->gpr[rd];
-                       do_popcnt(regs, val, 64, ra);
+                       do_prtyd(regs, val, ra);
                        goto logical_done;
-#endif
 
 #ifdef __powerpc64__
                case 2396736:   /* bpermd */
@@ -1297,6 +1332,17 @@ int analyse_instr(struct instruction_op *op, struct 
pt_regs *regs,
                        goto logical_done;
 #endif
 
+               case 17076744:  /* popcntw */
+                       val = regs->gpr[rd];
+                       do_popcnt(regs, val, 32, ra);
+                       goto logical_done;
+#ifdef __powerpc64__
+               case 19173896:  /* popcntd */
+                       val = regs->gpr[rd];
+                       do_popcnt(regs, val, 64, ra);
+                       goto logical_done;
+#endif
+
 /*
  * Shift instructions
  */
-- 
2.9.3

Reply via email to