summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorSandipan Das <sandipan@linux.vnet.ibm.com>2017-10-10 08:45:30 +0200
committerMichael Ellerman <mpe@ellerman.id.au>2017-10-10 11:16:32 +0200
commitb0490a04e736356e427e227902b17f9927a56caf (patch)
treedc96af57600fdc47d874e933103265e4dff79233 /arch/powerpc
parentpowerpc/livepatch: Fix livepatch stack access (diff)
downloadlinux-b0490a04e736356e427e227902b17f9927a56caf.tar.xz
linux-b0490a04e736356e427e227902b17f9927a56caf.zip
powerpc/lib/sstep: Fix count leading zeros instructions
According to the GCC documentation, the behaviour of __builtin_clz() and __builtin_clzl() is undefined if the value of the input argument is zero. Without handling this special case, these builtins have been used for emulating the following instructions: * Count Leading Zeros Word (cntlzw[.]) * Count Leading Zeros Doubleword (cntlzd[.]) This fixes the emulated behaviour of these instructions by adding an additional check for this special case. Fixes: 3cdfcbfd32b9d ("powerpc: Change analyse_instr so it doesn't modify *regs") Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com> Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/lib/sstep.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 5e8418c28bd8..f208f560aecd 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1684,11 +1684,13 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs,
* Logical instructions
*/
case 26: /* cntlzw */
- op->val = __builtin_clz((unsigned int) regs->gpr[rd]);
+ val = (unsigned int) regs->gpr[rd];
+ op->val = ( val ? __builtin_clz(val) : 32 );
goto logical_done;
#ifdef __powerpc64__
case 58: /* cntlzd */
- op->val = __builtin_clzl(regs->gpr[rd]);
+ val = regs->gpr[rd];
+ op->val = ( val ? __builtin_clzl(val) : 64 );
goto logical_done;
#endif
case 28: /* and */