Subversion Repositories Kolibri OS

Rev

Rev 6934 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _ASM_X86_HWEIGHT_H
  2. #define _ASM_X86_HWEIGHT_H
  3.  
  4. #include <asm/cpufeatures.h>
  5.  
  6. #ifdef CONFIG_64BIT
  7. /* popcnt %edi, %eax -- redundant REX prefix for alignment */
  8. #define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7"
  9. /* popcnt %rdi, %rax */
  10. #define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7"
  11. #define REG_IN "D"
  12. #define REG_OUT "a"
  13. #else
  14. /* popcnt %eax, %eax */
  15. #define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0"
  16. #define REG_IN "a"
  17. #define REG_OUT "a"
  18. #endif
  19.  
  20. /*
  21.  * __sw_hweightXX are called from within the alternatives below
  22.  * and callee-clobbered registers need to be taken care of. See
  23.  * ARCH_HWEIGHT_CFLAGS in <arch/x86/Kconfig> for the respective
  24.  * compiler switches.
  25.  */
  26. static __always_inline unsigned int __arch_hweight32(unsigned int w)
  27. {
  28.     unsigned int res = w - ((w >> 1) & 0x55555555);
  29.     res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
  30.     res = (res + (res >> 4)) & 0x0F0F0F0F;
  31.     res = res + (res >> 8);
  32.     return (res + (res >> 16)) & 0x000000FF;
  33. }
  34.  
  35. static inline unsigned int __arch_hweight16(unsigned int w)
  36. {
  37.         return __arch_hweight32(w & 0xffff);
  38. }
  39.  
  40. static inline unsigned int __arch_hweight8(unsigned int w)
  41. {
  42.         return __arch_hweight32(w & 0xff);
  43. }
  44.  
  45. #ifdef CONFIG_X86_32
  46. static inline unsigned long __arch_hweight64(__u64 w)
  47. {
  48.         return  __arch_hweight32((u32)w) +
  49.                 __arch_hweight32((u32)(w >> 32));
  50. }
  51. #else
  52. static __always_inline unsigned long __arch_hweight64(__u64 w)
  53. {
  54.         unsigned long res = 0;
  55.  
  56.         asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT)
  57.                      : "="REG_OUT (res)
  58.                      : REG_IN (w));
  59.  
  60.         return res;
  61. }
  62. #endif /* CONFIG_X86_32 */
  63.  
  64. #endif
  65.