diff mbox

[4/5] powerpc/lib/sstep: Add prty instruction emulation

Message ID 20170713032548.451-4-matthew.brown.dev@gmail.com (mailing list archive)
State Superseded
Headers show

Commit Message

Matt Brown July 13, 2017, 3:25 a.m. UTC
This add emulation for the prtyw and prtyd instructions.

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

Comments

Segher Boessenkool July 13, 2017, 7:37 a.m. UTC | #1
On Thu, Jul 13, 2017 at 01:25:47PM +1000, Matt Brown wrote:
> +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)))

1UL

> +			(i < 4) ? (low++) : (high++);
> +	}
> +
> +	if (low % 2)
> +		out |= low;
> +	if (high % 2)
> +		out |= (high << 32);

Only the low bit of each word of the output can be set.  Something
like

  out = ((high & 1) << 32) | (low & 1);


Segher
Matt Brown July 14, 2017, 12:46 a.m. UTC | #2
On Thu, Jul 13, 2017 at 5:37 PM, Segher Boessenkool
<segher@kernel.crashing.org> wrote:
> On Thu, Jul 13, 2017 at 01:25:47PM +1000, Matt Brown wrote:
>> +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)))
>
> 1UL
>
>> +                     (i < 4) ? (low++) : (high++);
>> +     }
>> +
>> +     if (low % 2)
>> +             out |= low;
>> +     if (high % 2)
>> +             out |= (high << 32);
>
> Only the low bit of each word of the output can be set.  Something
> like
>
>   out = ((high & 1) << 32) | (low & 1);
>
Ah, I wasn't aware. That way is much more concise too :)

Thanks,
Matt
>
> Segher
kernel test robot July 14, 2017, 7:02 p.m. UTC | #3
Hi Matt,

[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.12 next-20170714]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Matt-Brown/powerpc-lib-sstep-Add-cmpb-instruction-emulation/20170714-020837
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-chrp32_defconfig (attached as .config)
compiler: powerpc-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   arch/powerpc/lib/sstep.c: In function 'do_prtyw':
>> arch/powerpc/lib/sstep.c:673:16: error: left shift count >= width of type [-Werror=shift-count-overflow]
      out |= (high << 32);
                   ^~
   cc1: all warnings being treated as errors

vim +673 arch/powerpc/lib/sstep.c

   654	
   655	static nokprobe_inline void do_prtyw(struct pt_regs *regs, unsigned long v,
   656					int ra)
   657	{
   658		unsigned long low, high, out;
   659		unsigned int i;
   660	
   661		high = 0;
   662		low = 0;
   663		out = 0;
   664	
   665		for (i = 0; i < 8; i++) {
   666			if (v & (1 << (i * 8)))
   667				(i < 4) ? (low++) : (high++);
   668		}
   669	
   670		if (low % 2)
   671			out |= low;
   672		if (high % 2)
 > 673			out |= (high << 32);
   674	
   675		regs->gpr[ra] = out;
   676	}
   677	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

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
  */