On Tue, Jul 25, 2017 at 8:24 PM, David Laight <david.lai...@aculab.com> wrote: > From: Linuxppc-dev > [mailto:linuxppc-dev-bounces+david.laight=aculab....@lists.ozlabs.org] On > Behalf Of >> 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 <matthew.brown....@gmail.com> >> --- >> 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.