* [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.