arch_hweight.h 1.4 KB

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