Re: [PATCH v3 2/5] powerpc/lib/sstep: Add popcnt instruction emulation
From: Balbir Singh <bsingharora@gmail.com>
Date: 2017-07-25 13:32:44
On Tue, Jul 25, 2017 at 8:24 PM, David Laight [off-list ref] wrote:
From: Linuxppc-dev [mailto:linuxppc-dev-bounces+david.laight=aculab.com@lists.ozlabs.org] On Behalf Ofquoted
Matt Brown Sent: 25 July 2017 04:33 To: linuxppc-dev@lists.ozlabs.org Subject: [PATCH v3 2/5] powerpc/lib/sstep: Add popcnt instruction emulation 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 <redacted> --- v3: - optimised using the Giles-Miller method of side-ways addition v2: - fixed opcodes - fixed typecasting - fixed bitshifting error for both 32 and 64bit arch --- arch/powerpc/lib/sstep.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-)diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 87d277f..c1f9cdb 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c@@ -612,6 +612,32 @@ 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 out = v1; + + out = (0x5555555555555555 & out) + (0x5555555555555555 & (out >> 1)); + out = (0x3333333333333333 & out) + (0x3333333333333333 & (out >> 2)); + out = (0x0f0f0f0f0f0f0f0f & out) + (0x0f0f0f0f0f0f0f0f & (out >> 4)); + if (size == 8) { /* popcntb */ + regs->gpr[ra] = out;I'm pretty sure you need to mask the result with 7.
Absolutely! Good catch! Balbir Singh.