Subversion Repositories Kolibri OS

Rev

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