Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754590AbcCXDFB (ORCPT ); Wed, 23 Mar 2016 23:05:01 -0400 Received: from mail-pf0-f195.google.com ([209.85.192.195]:36594 "EHLO mail-pf0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753295AbcCXDE7 (ORCPT ); Wed, 23 Mar 2016 23:04:59 -0400 From: Zhaoxiu Zeng To: Arnd Bergmann , Andrew Morton , Martin Kepplinger , Sasha Levin , Denys Vlasenko , Ingo Molnar , Yury Norov Cc: linux-kernel@vger.kernel.org, linux-arch@vger.kernel.org, Zeng Zhaoxiu Subject: [PATCH 01/31] bitops: add parity functions Date: Thu, 24 Mar 2016 11:03:32 +0800 Message-Id: <1458788612-4367-1-git-send-email-zhaoxiu.zeng@gmail.com> X-Mailer: git-send-email 2.5.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5058 Lines: 147 From: Zeng Zhaoxiu When I do "grep parity -r linux", I found many parity calculations distributed in many drivers. These patches provide generic and architecture-specific parity calculations. Signed-off-by: Zeng Zhaoxiu --- include/asm-generic/bitops.h | 1 + include/asm-generic/bitops/arch_parity.h | 39 +++++++++++++++++++++++++++++++ include/asm-generic/bitops/const_parity.h | 36 ++++++++++++++++++++++++++++ include/asm-generic/bitops/parity.h | 7 ++++++ include/linux/bitops.h | 5 ++++ 5 files changed, 88 insertions(+) create mode 100644 include/asm-generic/bitops/arch_parity.h create mode 100644 include/asm-generic/bitops/const_parity.h create mode 100644 include/asm-generic/bitops/parity.h diff --git a/include/asm-generic/bitops.h b/include/asm-generic/bitops.h index dcdcacf..d85722f 100644 --- a/include/asm-generic/bitops.h +++ b/include/asm-generic/bitops.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/include/asm-generic/bitops/arch_parity.h b/include/asm-generic/bitops/arch_parity.h new file mode 100644 index 0000000..8d51eb3 --- /dev/null +++ b/include/asm-generic/bitops/arch_parity.h @@ -0,0 +1,39 @@ +#ifndef _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ +#define _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ + +#include + +/* + * Refrence to 'https://graphics.stanford.edu/~seander/bithacks.html#ParityParallel'. + */ + +static inline unsigned int __arch_parity4(unsigned int w) +{ + w &= 0xf; + return (0x6996 >> w) & 1; +} + +static inline unsigned int __arch_parity8(unsigned int w) +{ + w ^= w >> 4; + return __arch_parity4(w); +} + +static inline unsigned int __arch_parity16(unsigned int w) +{ + w ^= w >> 8; + return __arch_parity8(w); +} + +static inline unsigned int __arch_parity32(unsigned int w) +{ + w ^= w >> 16; + return __arch_parity16(w); +} + +static inline unsigned int __arch_parity64(__u64 w) +{ + return __arch_parity32((unsigned int)(w >> 32) ^ (unsigned int)w); +} + +#endif /* _ASM_GENERIC_BITOPS_ARCH_PARITY_H_ */ diff --git a/include/asm-generic/bitops/const_parity.h b/include/asm-generic/bitops/const_parity.h new file mode 100644 index 0000000..9590315 --- /dev/null +++ b/include/asm-generic/bitops/const_parity.h @@ -0,0 +1,36 @@ +#ifndef _ASM_GENERIC_BITOPS_CONST_PARITY_H_ +#define _ASM_GENERIC_BITOPS_CONST_PARITY_H_ + +/* + * Compile time versions of __arch_parityN() + */ +#define __const_parity4(w) ((0x6996 >> ((w) & 0xf)) & 1) +#define __const_parity8(w) (__const_parity4(w ^ (w >> 4))) +#define __const_parity16(w) (__const_parity8(w ^ (w >> 8))) +#define __const_parity32(w) (__const_parity16(w ^ (w >> 16))) +#define __const_parity64(w) (__const_parity32(w ^ (w >> 32))) + +/* + * Generic interface. + */ +#define parity4(w) (__builtin_constant_p(w) ? __const_parity4(w) : __arch_parity4(w)) +#define parity8(w) (__builtin_constant_p(w) ? __const_parity8(w) : __arch_parity8(w)) +#define parity16(w) (__builtin_constant_p(w) ? __const_parity16(w) : __arch_parity16(w)) +#define parity32(w) (__builtin_constant_p(w) ? __const_parity32(w) : __arch_parity32(w)) +#define parity64(w) (__builtin_constant_p(w) ? __const_parity64(w) : __arch_parity64(w)) + +/* + * Interface for known constant arguments + */ +#define PARITY4(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity4(w)) +#define PARITY8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity8(w)) +#define PARITY16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity16(w)) +#define PARITY32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity32(w)) +#define PARITY64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_parity64(w)) + +/* + * Type invariant interface to the compile time constant parity functions. + */ +#define PARITY(w) PARITY64((u64)w) + +#endif /* _ASM_GENERIC_BITOPS_CONST_PARITY_H_ */ diff --git a/include/asm-generic/bitops/parity.h b/include/asm-generic/bitops/parity.h new file mode 100644 index 0000000..a91dce7 --- /dev/null +++ b/include/asm-generic/bitops/parity.h @@ -0,0 +1,7 @@ +#ifndef _ASM_GENERIC_BITOPS_PARITY_H_ +#define _ASM_GENERIC_BITOPS_PARITY_H_ + +#include +#include + +#endif /* _ASM_GENERIC_BITOPS_PARITY_H_ */ diff --git a/include/linux/bitops.h b/include/linux/bitops.h index defeaac..f91cb44 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -80,6 +80,11 @@ static __always_inline unsigned long hweight_long(unsigned long w) return sizeof(w) == 4 ? hweight32(w) : hweight64(w); } +static __always_inline unsigned int parity_long(unsigned long w) +{ + return sizeof(w) == 4 ? parity32(w) : parity64(w); +} + /** * rol64 - rotate a 64-bit value left * @word: value to rotate -- 2.5.0