Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: 8187/1: add CONFIG_HAVE_ARCH_BITREVERSE to support rbit instruction

this change add CONFIG_HAVE_ARCH_BITREVERSE config option,
so that we can use some architecture's bitrev hardware instruction
to do bitrev operation.

Introduce __constant_bitrev* macro for constant bitrev operation.

Change __bitrev16() __bitrev32() to be inline function,
don't need export symbol for these tiny functions.

Signed-off-by: Yalin Wang <yalin.wang@sonymobile.com>
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

authored by

Yalin Wang and committed by
Russell King
556d2f05 97bf6af1

+84 -19
+73 -4
include/linux/bitrev.h
··· 3 3 4 4 #include <linux/types.h> 5 5 6 - extern u8 const byte_rev_table[256]; 6 + #ifdef CONFIG_HAVE_ARCH_BITREVERSE 7 + #include <asm/bitrev.h> 7 8 8 - static inline u8 bitrev8(u8 byte) 9 + #define __bitrev32 __arch_bitrev32 10 + #define __bitrev16 __arch_bitrev16 11 + #define __bitrev8 __arch_bitrev8 12 + 13 + #else 14 + extern u8 const byte_rev_table[256]; 15 + static inline u8 __bitrev8(u8 byte) 9 16 { 10 17 return byte_rev_table[byte]; 11 18 } 12 19 13 - extern u16 bitrev16(u16 in); 14 - extern u32 bitrev32(u32 in); 20 + static inline u16 __bitrev16(u16 x) 21 + { 22 + return (__bitrev8(x & 0xff) << 8) | __bitrev8(x >> 8); 23 + } 15 24 25 + static inline u32 __bitrev32(u32 x) 26 + { 27 + return (__bitrev16(x & 0xffff) << 16) | __bitrev16(x >> 16); 28 + } 29 + 30 + #endif /* CONFIG_HAVE_ARCH_BITREVERSE */ 31 + 32 + #define __constant_bitrev32(x) \ 33 + ({ \ 34 + u32 __x = x; \ 35 + __x = (__x >> 16) | (__x << 16); \ 36 + __x = ((__x & (u32)0xFF00FF00UL) >> 8) | ((__x & (u32)0x00FF00FFUL) << 8); \ 37 + __x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \ 38 + __x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \ 39 + __x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \ 40 + __x; \ 41 + }) 42 + 43 + #define __constant_bitrev16(x) \ 44 + ({ \ 45 + u16 __x = x; \ 46 + __x = (__x >> 8) | (__x << 8); \ 47 + __x = ((__x & (u16)0xF0F0U) >> 4) | ((__x & (u16)0x0F0FU) << 4); \ 48 + __x = ((__x & (u16)0xCCCCU) >> 2) | ((__x & (u16)0x3333U) << 2); \ 49 + __x = ((__x & (u16)0xAAAAU) >> 1) | ((__x & (u16)0x5555U) << 1); \ 50 + __x; \ 51 + }) 52 + 53 + #define __constant_bitrev8(x) \ 54 + ({ \ 55 + u8 __x = x; \ 56 + __x = (__x >> 4) | (__x << 4); \ 57 + __x = ((__x & (u8)0xCCU) >> 2) | ((__x & (u8)0x33U) << 2); \ 58 + __x = ((__x & (u8)0xAAU) >> 1) | ((__x & (u8)0x55U) << 1); \ 59 + __x; \ 60 + }) 61 + 62 + #define bitrev32(x) \ 63 + ({ \ 64 + u32 __x = x; \ 65 + __builtin_constant_p(__x) ? \ 66 + __constant_bitrev32(__x) : \ 67 + __bitrev32(__x); \ 68 + }) 69 + 70 + #define bitrev16(x) \ 71 + ({ \ 72 + u16 __x = x; \ 73 + __builtin_constant_p(__x) ? \ 74 + __constant_bitrev16(__x) : \ 75 + __bitrev16(__x); \ 76 + }) 77 + 78 + #define bitrev8(x) \ 79 + ({ \ 80 + u8 __x = x; \ 81 + __builtin_constant_p(__x) ? \ 82 + __constant_bitrev8(__x) : \ 83 + __bitrev8(__x) ; \ 84 + }) 16 85 #endif /* _LINUX_BITREV_H */
+9
lib/Kconfig
··· 13 13 config BITREVERSE 14 14 tristate 15 15 16 + config HAVE_ARCH_BITREVERSE 17 + boolean 18 + default n 19 + depends on BITREVERSE 20 + help 21 + This option provides an config for the architecture which have instruction 22 + can do bitreverse operation, we use the hardware instruction if the architecture 23 + have this capability. 24 + 16 25 config RATIONAL 17 26 boolean 18 27
+2 -15
lib/bitrev.c
··· 1 + #ifndef CONFIG_HAVE_ARCH_BITREVERSE 1 2 #include <linux/types.h> 2 3 #include <linux/module.h> 3 4 #include <linux/bitrev.h> ··· 43 42 }; 44 43 EXPORT_SYMBOL_GPL(byte_rev_table); 45 44 46 - u16 bitrev16(u16 x) 47 - { 48 - return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8); 49 - } 50 - EXPORT_SYMBOL(bitrev16); 51 - 52 - /** 53 - * bitrev32 - reverse the order of bits in a u32 value 54 - * @x: value to be bit-reversed 55 - */ 56 - u32 bitrev32(u32 x) 57 - { 58 - return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16); 59 - } 60 - EXPORT_SYMBOL(bitrev32); 45 + #endif /* CONFIG_HAVE_ARCH_BITREVERSE */