All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation
@ 2017-07-24  1:01 Matt Brown
  2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-24  1:01 UTC (permalink / raw)
  To: linuxppc-dev

This patch adds emulation of the cmpb instruction, enabling xmon to
emulate this instruction.
Tested for correctness against the cmpb asm instruction on ppc64le.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
v2: 
	- fixed opcode
	- fixed mask typecasting
---
 arch/powerpc/lib/sstep.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 33117f8..87d277f 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -596,6 +596,22 @@ static nokprobe_inline void do_cmp_unsigned(struct pt_regs *regs, unsigned long
 	regs->ccr = (regs->ccr & ~(0xf << shift)) | (crval << shift);
 }
 
+static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1,
+				unsigned long v2, int rd)
+{
+	unsigned long long out_val, mask;
+	int i;
+
+	out_val = 0;
+	for (i = 0; i < 8; i++) {
+		mask = 0xffUL << (i * 8);
+		if ((v1 & mask) == (v2 & mask))
+			out_val |= mask;
+	}
+
+	regs->gpr[rd] = out_val;
+}
+
 static nokprobe_inline int trap_compare(long v1, long v2)
 {
 	int ret = 0;
@@ -1049,6 +1065,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 			do_cmp_unsigned(regs, val, val2, rd >> 2);
 			goto instr_done;
 
+		case 508: /* cmpb */
+			do_cmpb(regs, regs->gpr[rd], regs->gpr[rb], ra);
+			goto instr_done;
+
 /*
  * Arithmetic instructions
  */
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
  2017-07-24  1:01 [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation Matt Brown
@ 2017-07-24  1:01 ` Matt Brown
  2017-07-24  7:36   ` Segher Boessenkool
  2017-07-24 10:28   ` Balbir Singh
  2017-07-24  1:01 ` [PATCH v2 3/5] powerpc/lib/sstep: Add bpermd " Matt Brown
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-24  1:01 UTC (permalink / raw)
  To: linuxppc-dev

This adds emulations for the popcntb, popcntw, and popcntd instructions.
Tested for correctness against the popcnt{b,w,d} instructions on ppc64le.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
v2:
	- fixed opcodes
	- fixed typecasting
	- fixed bitshifting error for both 32 and 64bit arch
---
 arch/powerpc/lib/sstep.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 87d277f..e6a16a3 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -612,6 +612,35 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1,
 	regs->gpr[rd] = out_val;
 }
 
+/*
+ * The size parameter is used to adjust the equivalent popcnt instruction.
+ * popcntb = 8, popcntw = 32, popcntd = 64
+ */
+static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1,
+				int size, int ra)
+{
+	unsigned long long high, low, mask;
+	unsigned int n;
+	int i, j;
+
+	high = 0;
+	low = 0;
+
+	for (i = 0; i < (64 / size); i++) {
+		n = 0;
+		for (j = 0; j < size; j++) {
+			mask = 1UL << (j + (i * size));
+			if (v1 & mask)
+				n++;
+		}
+		if ((i * size) < 32)
+			low |= n << (i * size);
+		else
+			high |= n << ((i * size) - 32);
+	}
+	regs->gpr[ra] = (high << 32) | low;
+}
+
 static nokprobe_inline int trap_compare(long v1, long v2)
 {
 	int ret = 0;
@@ -1194,6 +1223,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 			regs->gpr[ra] = regs->gpr[rd] & ~regs->gpr[rb];
 			goto logical_done;
 
+		case 122:	/* popcntb */
+			do_popcnt(regs, regs->gpr[rd], 8, ra);
+			goto logical_done;
+
 		case 124:	/* nor */
 			regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]);
 			goto logical_done;
@@ -1206,6 +1239,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 			regs->gpr[ra] = regs->gpr[rd] ^ regs->gpr[rb];
 			goto logical_done;
 
+		case 378:	/* popcntw */
+			do_popcnt(regs, regs->gpr[rd], 32, ra);
+			goto logical_done;
+
 		case 412:	/* orc */
 			regs->gpr[ra] = regs->gpr[rd] | ~regs->gpr[rb];
 			goto logical_done;
@@ -1217,7 +1254,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 		case 476:	/* nand */
 			regs->gpr[ra] = ~(regs->gpr[rd] & regs->gpr[rb]);
 			goto logical_done;
-
+#ifdef __powerpc64__
+		case 506:	/* popcntd */
+			do_popcnt(regs, regs->gpr[rd], 64, ra);
+			goto logical_done;
+#endif
 		case 922:	/* extsh */
 			regs->gpr[ra] = (signed short) regs->gpr[rd];
 			goto logical_done;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 3/5] powerpc/lib/sstep: Add bpermd instruction emulation
  2017-07-24  1:01 [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation Matt Brown
  2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
@ 2017-07-24  1:01 ` Matt Brown
  2017-07-24  1:01 ` [PATCH 4/5] powerpc/lib/sstep: Add prty " Matt Brown
  2017-07-24  1:01 ` [PATCH v2 5/5] powerpc/lib/sstep: Add isel " Matt Brown
  3 siblings, 0 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-24  1:01 UTC (permalink / raw)
  To: linuxppc-dev

This adds emulation for the bpermd instruction.
Tested for correctness against the bpermd instruction on ppc64le.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
v2:
	- fixed opcode
	- added ifdef tags to do_bpermd func
	- fixed bitshifting errors
---
 arch/powerpc/lib/sstep.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index e6a16a3..a756f44 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -641,6 +641,24 @@ static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1,
 	regs->gpr[ra] = (high << 32) | low;
 }
 
+#ifdef __powerpc64__
+static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1,
+				unsigned long v2, int ra)
+{
+	unsigned char perm, idx;
+	unsigned int i;
+
+	perm = 0;
+	for (i = 0; i < 8; i++) {
+		idx = (v1 >> (i * 8)) & 0xff;
+		if (idx < 64)
+			if (v2 & PPC_BIT(idx))
+				perm |= 1 << i;
+	}
+	regs->gpr[ra] = perm;
+}
+#endif /* __powerpc64__ */
+
 static nokprobe_inline int trap_compare(long v1, long v2)
 {
 	int ret = 0;
@@ -1230,7 +1248,11 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 		case 124:	/* nor */
 			regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]);
 			goto logical_done;
-
+#ifdef __powerpc64__
+		case 252:	/* bpermd */
+			do_bpermd(regs, regs->gpr[rd], regs->gpr[rb], ra);
+			goto logical_done;
+#endif
 		case 284:	/* xor */
 			regs->gpr[ra] = ~(regs->gpr[rd] ^ regs->gpr[rb]);
 			goto logical_done;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/5] powerpc/lib/sstep: Add prty instruction emulation
  2017-07-24  1:01 [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation Matt Brown
  2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
  2017-07-24  1:01 ` [PATCH v2 3/5] powerpc/lib/sstep: Add bpermd " Matt Brown
@ 2017-07-24  1:01 ` Matt Brown
  2017-07-24  1:01 ` [PATCH v2 5/5] powerpc/lib/sstep: Add isel " Matt Brown
  3 siblings, 0 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-24  1:01 UTC (permalink / raw)
  To: linuxppc-dev

This add emulation for the prtyw and prtyd instructions.
Tested for logical correctness against the prtyw and prtyd instructions
on ppc64le.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
v2:
	- fixed opcodes
	- fixed bitshifting and typecast errors
	- merged do_prtyw and do_prtyd into single function
---
 arch/powerpc/lib/sstep.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index a756f44..1820fd6 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -658,6 +658,29 @@ static nokprobe_inline void do_bpermd(struct pt_regs *regs, unsigned long v1,
 	regs->gpr[ra] = perm;
 }
 #endif /* __powerpc64__ */
+/*
+ * The size parameter adjusts the equivalent prty instruction.
+ * prtyw = 32, prtyd = 64
+ */
+static nokprobe_inline void do_prty(struct pt_regs *regs, unsigned long v,
+				int size, int ra)
+{
+	unsigned long long high, low;
+	unsigned int i;
+
+	high = 0;
+	low = 0;
+
+	for (i = 0; i < 8; i++) {
+		if (v & (1UL << (i * 8)))
+			(i < 4) ? (low++) : (high++);
+	}
+
+	if (size == 32)
+		regs->gpr[ra] = ((high & 1) << 32) | (low & 1);
+	else
+		regs->gpr[ra] = (high + low) & 1;
+}
 
 static nokprobe_inline int trap_compare(long v1, long v2)
 {
@@ -1248,6 +1271,14 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 		case 124:	/* nor */
 			regs->gpr[ra] = ~(regs->gpr[rd] | regs->gpr[rb]);
 			goto logical_done;
+
+		case 154:	/* prtyw */
+			do_prty(regs, regs->gpr[rd], 32, ra);
+			goto logical_done;
+
+		case 186:	/* prtyd */
+			do_prty(regs, regs->gpr[rd], 64, ra);
+			goto logical_done;
 #ifdef __powerpc64__
 		case 252:	/* bpermd */
 			do_bpermd(regs, regs->gpr[rd], regs->gpr[rb], ra);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v2 5/5] powerpc/lib/sstep: Add isel instruction emulation
  2017-07-24  1:01 [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation Matt Brown
                   ` (2 preceding siblings ...)
  2017-07-24  1:01 ` [PATCH 4/5] powerpc/lib/sstep: Add prty " Matt Brown
@ 2017-07-24  1:01 ` Matt Brown
  3 siblings, 0 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-24  1:01 UTC (permalink / raw)
  To: linuxppc-dev

This adds emulation for the isel instruction.
Tested for correctness against the isel instruction and its extended
mnemonics (lt, gt, eq) on ppc64le.

Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
---
v2:
	- fixed opcode
	- fixed definition to include the 'if RA=0, a=0' clause
	- fixed ccr bitshifting error
---
 arch/powerpc/lib/sstep.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index b08eb96..e1f4ec6 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1246,6 +1246,17 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
 /*
  * Logical instructions
  */
+		case 15:	/* isel */
+			mb = (instr >> 6) & 0x1f; /* bc */
+			val = (regs->ccr >> (31 - mb)) & 1;
+			val2 = (ra) ? regs->gpr[ra] : 0;
+
+			if (val)
+				regs->gpr[rd] = val2;
+			else
+				regs->gpr[rd] = regs->gpr[rb];
+			goto logical_done;
+
 		case 26:	/* cntlzw */
 			asm("cntlzw %0,%1" : "=r" (regs->gpr[ra]) :
 			    "r" (regs->gpr[rd]));
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
  2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
@ 2017-07-24  7:36   ` Segher Boessenkool
  2017-07-24 10:28   ` Balbir Singh
  1 sibling, 0 replies; 8+ messages in thread
From: Segher Boessenkool @ 2017-07-24  7:36 UTC (permalink / raw)
  To: Matt Brown; +Cc: linuxppc-dev

Hi Matt,

On Mon, Jul 24, 2017 at 11:01:06AM +1000, Matt Brown wrote:
> +	for (i = 0; i < (64 / size); i++) {

If you do

  for (i = 0; i < 64; i += size)

things are slightly nicer.

> +		if ((i * size) < 32)
> +			low |= n << (i * size);
> +		else
> +			high |= n << ((i * size) - 32);
> +	}
> +	regs->gpr[ra] = (high << 32) | low;

Why have separate high and low vars?

And there are much better ways to calculate popcount, of course.


Segher

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
  2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
  2017-07-24  7:36   ` Segher Boessenkool
@ 2017-07-24 10:28   ` Balbir Singh
  2017-07-25  0:53     ` Matt Brown
  1 sibling, 1 reply; 8+ messages in thread
From: Balbir Singh @ 2017-07-24 10:28 UTC (permalink / raw)
  To: Matt Brown; +Cc: open list:LINUX FOR POWERPC (32-BIT AND 64-BIT)

On Mon, Jul 24, 2017 at 11:01 AM, Matt Brown
<matthew.brown.dev@gmail.com> wrote:
> This adds emulations for the popcntb, popcntw, and popcntd instructions.
> Tested for correctness against the popcnt{b,w,d} instructions on ppc64le.
>
> Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
> ---
> v2:
>         - fixed opcodes
>         - fixed typecasting
>         - fixed bitshifting error for both 32 and 64bit arch
> ---
>  arch/powerpc/lib/sstep.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
> index 87d277f..e6a16a3 100644
> --- a/arch/powerpc/lib/sstep.c
> +++ b/arch/powerpc/lib/sstep.c
> @@ -612,6 +612,35 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1,
>         regs->gpr[rd] = out_val;
>  }
>
> +/*
> + * The size parameter is used to adjust the equivalent popcnt instruction.
> + * popcntb = 8, popcntw = 32, popcntd = 64
> + */
> +static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1,
> +                               int size, int ra)
> +{
> +       unsigned long long high, low, mask;
> +       unsigned int n;
> +       int i, j;
> +
> +       high = 0;
> +       low = 0;
> +
> +       for (i = 0; i < (64 / size); i++) {
> +               n = 0;
> +               for (j = 0; j < size; j++) {
> +                       mask = 1UL << (j + (i * size));
> +                       if (v1 & mask)
> +                               n++;
> +               }
> +               if ((i * size) < 32)
> +                       low |= n << (i * size);
> +               else
> +                       high |= n << ((i * size) - 32);
> +       }
> +       regs->gpr[ra] = (high << 32) | low;
> +}

There's a way to do it in very efficient way via the Giles-Miller
method of side-ways addition

Please see

http://opensourceforu.com/2012/06/power-programming-bitwise-tips-tricks/
and lib/hweight.c, you can reuse the code from lib/hweight.c

Balbir Singh

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
  2017-07-24 10:28   ` Balbir Singh
@ 2017-07-25  0:53     ` Matt Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Matt Brown @ 2017-07-25  0:53 UTC (permalink / raw)
  To: Balbir Singh; +Cc: open list:LINUX FOR POWERPC (32-BIT AND 64-BIT)

On Mon, Jul 24, 2017 at 8:28 PM, Balbir Singh <bsingharora@gmail.com> wrote:
> On Mon, Jul 24, 2017 at 11:01 AM, Matt Brown
> <matthew.brown.dev@gmail.com> wrote:
>> This adds emulations for the popcntb, popcntw, and popcntd instructions.
>> Tested for correctness against the popcnt{b,w,d} instructions on ppc64le.
>>
>> Signed-off-by: Matt Brown <matthew.brown.dev@gmail.com>
>> ---
>> v2:
>>         - fixed opcodes
>>         - fixed typecasting
>>         - fixed bitshifting error for both 32 and 64bit arch
>> ---
>>  arch/powerpc/lib/sstep.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 42 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
>> index 87d277f..e6a16a3 100644
>> --- a/arch/powerpc/lib/sstep.c
>> +++ b/arch/powerpc/lib/sstep.c
>> @@ -612,6 +612,35 @@ static nokprobe_inline void do_cmpb(struct pt_regs *regs, unsigned long v1,
>>         regs->gpr[rd] = out_val;
>>  }
>>
>> +/*
>> + * The size parameter is used to adjust the equivalent popcnt instruction.
>> + * popcntb = 8, popcntw = 32, popcntd = 64
>> + */
>> +static nokprobe_inline void do_popcnt(struct pt_regs *regs, unsigned long v1,
>> +                               int size, int ra)
>> +{
>> +       unsigned long long high, low, mask;
>> +       unsigned int n;
>> +       int i, j;
>> +
>> +       high = 0;
>> +       low = 0;
>> +
>> +       for (i = 0; i < (64 / size); i++) {
>> +               n = 0;
>> +               for (j = 0; j < size; j++) {
>> +                       mask = 1UL << (j + (i * size));
>> +                       if (v1 & mask)
>> +                               n++;
>> +               }
>> +               if ((i * size) < 32)
>> +                       low |= n << (i * size);
>> +               else
>> +                       high |= n << ((i * size) - 32);
>> +       }
>> +       regs->gpr[ra] = (high << 32) | low;
>> +}
>
> There's a way to do it in very efficient way via the Giles-Miller
> method of side-ways addition
>
> Please see
>
> http://opensourceforu.com/2012/06/power-programming-bitwise-tips-tricks/
> and lib/hweight.c, you can reuse the code from lib/hweight.c

Oh that's a really cool technique.
We could use that for the parity instructions too.

>
> Balbir Singh

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-07-25  0:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-24  1:01 [PATCH v2 1/5] powerpc/lib/sstep: Add cmpb instruction emulation Matt Brown
2017-07-24  1:01 ` [PATCH v2 2/5] powerpc/lib/sstep: Add popcnt " Matt Brown
2017-07-24  7:36   ` Segher Boessenkool
2017-07-24 10:28   ` Balbir Singh
2017-07-25  0:53     ` Matt Brown
2017-07-24  1:01 ` [PATCH v2 3/5] powerpc/lib/sstep: Add bpermd " Matt Brown
2017-07-24  1:01 ` [PATCH 4/5] powerpc/lib/sstep: Add prty " Matt Brown
2017-07-24  1:01 ` [PATCH v2 5/5] powerpc/lib/sstep: Add isel " Matt Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.